Professional Documents
Culture Documents
Computational Tools
Computational Tools
QR$rank
Solve(A,b) Solve linear system
A%*%sol To verify that A*sol=b
Sum(vector) Sum of the items of the vector
Set.seed(123) Procedure to generate random numbers
L<-list(number=5, greetings= “ciao” List = include several objects within 1 single element
Extract elements > l$number
Diag(pi,4) Diagonal matrix 4x4 with diagonal elements coming from π
Round (2^9,9…) Value close to actual result
1:4 > 3 FALSE 1>3
FALSE 2>3
FALSE 3>3
TRUE 4>3
FUNCTION Solve a*x^2+b*x+c=0
Function(a,b,c)
Quadra<-function (a,b,c){
Delta <- b^2-4*a*c
If (delta>=0){
x_1<-(-b+sqrt(delta))/(2*a)
x_2<-(-b+sqrt(delta))/(2*a)
res<-c(x_1,x_2)} else<-“delta is negative:
complex roots”}res}
FOR HISTOGRAM
Hist(c$grade, xlab
Curve(f(x), xlim=c(0,10)) Xlim=sets the x-axis limits for the current axes or chart
c(0,10) vector of extremes 0 and 10
Colour<- ifelse(x<=0, ifelse(y<=, “red”, Colour<- (test if x is smaller or equal to 0, for x<= test y if y<=0 then points will
“green”), ifelse(y<=0, “blue”, “black”)) be red if y >=0 points will be green, for x>=0 and y<=0 points will be blue, for
y>=0 points will be black)
Plot (x,y,t=“l”, xlab= “sampled points”, Command to join the points previously drawn by a line
main= “squared x”)
> # "t" stands for 'type', "l" stands for 'line', 'main' is the title
>plot(x,y,t="l",xlab="Sampled points",
main="Squared x") > # 'l' means 'lines', 'p' means 'points', 'b' means 'both lines and points'
> # 'cex' is an expansion term, size of the dots
>plot(x,y,t="l",cex=2.5,pch=20,col="red") > # 'pch' is the type of points
>plot(x,y,t="p",cex=2.5,pch=20,col="red") > # 'col' is color, can be specified also with numbers
>plot(x,y,t="b",cex=2.5,pch=18,col="red")
Computational tools command inputs
“p”: Points
“l”: Lines
“b”: Both
“c”: The lines part alone of “b”
“o”: Both “overplotted”
“h”: Histogram like (or high-density) vertical lines
“n”: No plotting
line type (lty) can be specified using either text (“blank”, “solid”, “dashed”,
“dotted”, “dotdash”, “longdash”, “twodash”) or number (0, 1, 2, 3, 4, 5, 6).
Note that lty = “solid” is identical to lty=1.
# Second Function
func7 <- function(x)
{
x
}
x <- seq(0,10,length=100)
plot(x, func6(x), col="blue", lwd="1", main="Graph
#1")
lines(x, func7(x), col="red")
func_name<-function(argument){
statement
}
Uniroot (function of which is needed to find the root, The function uniroot searches the interval from lower to upper for a root (i.e., zero) of the
interval in which is needed to investigate the function f with respect to its first argument
solution)
> # ROOT FINDING #>> find the zeros of a function(where the f(x)=0)
> f <- function(x) x^4+3*x^3+3*x^2-2*x-2 > # Consider the following function. Let us plot it and an horizontal line at zero level, i.e.
Computational tools command inputs
> curve(f,-3,3) > # evidently there are two intersections (zeros) between 'f' and the x-axis (i.e. the horizontal
> abline(h=0) line).
> # If roots (zeros) are sought (ricercati), then the command 'uniroot' might be used as follows
> uniroot(f,c(-1,0)) # Note that this will look for a zero of 'f' in the interval [-1,0]
$root # i.e. the interval for search must be given as a vector of two entries
[1] -0.6744252
$f.root
[1] 7.183991e-07
$iter
[1] 4
$init.it
[1] NA
$estim.prec
[1] 6.103516e-05
# Note that this will look for a zero of 'f' in the interval [0,1]
> sol <- uniroot(f,c(0,1))
> sol
$root
[1] 0.7740835
$f.root
[1] 3.222181e-07
$iter
[1] 6
$init.it
[1] NA
$estim.prec
[1] 0.0001199778
> sol$root
[1] 0.7740835
> sol$f.root
[1] 3.222181e-07
> # ...and to zoom and better see the zeros we can type:
> curve(f,-2,1)
> abline(h=0)
SOLVE THE PROBLEM f(x)=g(x) > # write the problem in the form h(x) = f(x) - g(x)
> # then use uniroot.
> dnorm(10,0.5,3) # computes the 'normal distribution' (with mean 0.5 and # standard deviation 3, at the value 10
[1] 0.0008836587
> # We recall that the 'max' or 'min' functions can > max(c(-34,12,5,sqrt(3),.03^3))
select the maximum/minimum [1] 12
> # number among a series of values > min(c(-34,12,5,sqrt(3),.03^3))
[1] -34
> # The command 'seq' can be partially enriched
using also the argument 'length.out', i.e.
> seq(from=2, to=5,length.out=3) # generates a sequence of 3 equal-spaced elements where the first is 2 and the third is 5
[1] 2.0 3.5 5.0
> seq(1,10,length.out=20) # generates a sequence of 20 equal-spaced elements where the first is 1 and the third is 10
[1] 1.000000 1.473684 1.947368 2.421053 2.894737
Shorter ways to write seq(_,_, length.out)
3.368421 3.842105
[8] 4.315789 4.789474 5.263158 5.736842 6.210526 > seq(1,10,length=20)
6.684211 7.157895 > seq(1,10,len=20)
[15] 7.631579 8.105263 8.578947 9.052632 9.526316
10.000000
OPTIMIZATION: to find local minima/maxima (i.e. to optimize a function)
> # when you have just one variable use the command 'optimize'
draw the function to allocate it in the best interval
> f <- function(x) x^4-3*x^3-3*x^2-3*x-2
> curve(f,-5,5)
> abline(h=0,col="blue")
> curve(f,0,5) > # inflection points at x1 = (3-17^(1/2))/4 and x2 = (3+17^(1/2))/4, i.e.
> # Imposing the equation f''(x) = 12x^2- > points((3-17^0.5)/4, f((3-17^0.5)/4),pch=19) # outside the interval [0,5]
18x-6 = 0 we find that 'f' has two > points((3+17^0.5)/4, f((3+17^0.5)/4),pch=19)
> # Imposing the equation f'(x) = 4x^3-9x^2-6x-3 = 0 we can find that 'f' has a
> # minimum point nearby x=3, given by
[1] -0.0001765588
> g <- function(x) 4*x^3-9*x^2-6*x-3
> windows()
> curve(g,2.5,3.5)
> abline(h=0,col="green")
> uniroot(g,c(2.5,3.5))
Computational tools command inputs
> # Now we want to use the command 'optimize' to directly find the minimum
point of 'f':
> optimize(f,c(2,4))
$minimum
[1] 2.864946
$objective
[1] -38.39441
MINIMIZING/MAXIMIZING with
CONSTRAINTS
x>=0,y>=0, x-2y>=1 transform it into a
matrix of the form Ax=b
1 0 x > 0
Computational tools command inputs
0 1 y = 0
> # Now we consider the introduction of 1 -2 1
'linear constraints', i.e. the feasible set 'D'
defined by the following constraints: KEEP AN EYE ON THE SIGNS!!!
'x >= 0, -y <= 1, x+y <= 2', which must be If one of the constraints has a different sign than the others then CHANGE IT
rearranged into 'x >= 0, y >= 1, -x-y >= -2'. Example
> # Observe that by looking at the plot of min g(x,y)
'g(x,y)' we easily see that the solution of (x,y) in D
the constrained optimization is located at
the right lower corner (1,1) of the triangle g <- function(x,y) x^2+y^2-3*x+y+2
which describes the feasible set gb <- function(x) g(x[1],x[2])
points(1,1,pch=19) > x <- seq(-2, 2, len=1001)
>A > y <- seq(-2,2, len=1001)
[,1] [,2] gz <- outer(x,y,g)
[1,] 1 0 > image(x,y,gz)
[2,] 0 1 > contour(x,y,gz,labcex=1.3)
[3,] -1 -1 > contour(x,y,gz,add=T,labcex=1.8)
>b
[1] 0 1 -2 > abline(v=0,col="blue") # necessary to consider the first constraint
> abline(h=1,col="blue") # necessary to consider the second constraint
> # To solve the constrained optimization > abline(2,-1,col="blue") # necessary to consider the third constraint
problem we type: > polygon(c(0,0,1), c(1,2,1), col="grey", density=c(30,40))
> # where
> # '(0.1,1.1)' is the starting point for > # Now, the feasible set 'D' contains linear constraints in the form 'Ax >=
minimization b', where we have for 'A' and 'b'
> # 'gb' is the function to be minimized > A <-matrix(c(1,0,0,1,-1,-1),3,2,byrow=T)
(must be a function of a 2-real vector)
> # 'NULL' (the third argument) indicates
that the heuristic optimization method
"Nelder-Mead" is used
> # (in case 'NULL' is replaced by the vector
'c(gb_x,gb_y)' of partial derivatives of 'gb',
then > b <- c(0,1,-2)
> # (the exact and more accurate
optimization method "BFGS" is used in
place of "Nelder-Mead" > constrOptim(c(0.1,1.1), gb, NULL,A,b)
> gb_x <- function(x,y) 2*x-3 # partial $par
derivative of 'gb' with respect to 'x' [1] 0.9999394 1.0000000
> gb_y <- function(x,y) 2*y+1 # partial
derivative of 'gb' with respect to 'y' $value
> gbg <- function(x) { c( gb_x(x[1],x[2]) , [1] 2.000061
gb_y(x[1],x[2]) ) } # define the 'gradient'
function of 'gb'. $counts
function gradient
272 NA
$convergence
[1] 0
$message
NULL
Computational tools command inputs
$outer.iterations
[1] 3
$barrier.value
[1] 6.494207e-08
curve(x^2,-2,2)
curve(log(x+4),add=T)
h<-function(x) x^2- log(x+4)
soll<-uniroot(h,c(-1.5,0.5))
Z<-outer((-5:5),(-10:10),f) Matrix of entries dimension 11x21 being 11=5-(-5)+1) and 21=10-(-10)+1
Plot a 3D graph of the function z(x,y) The entry z(I,j) contains the value of f at the point in position(I,j)
Persp(x,y,z)
> # The command to compute integrals in
R is 'integrate'. For example:
> f <- function(x) cos(x)/(1+sin(x))
>f
function(x) cos(x)/(1+sin(x))
> curve(f,0,10)
> pi
[1] 3.141593
> integrate(f,0,pi/2) > # Let us integrate this function between '0' and 'pi/2'
0.6931472 with absolute error < 7.7e-15
> in_f <- integrate(f,0,pi/2)
> str(in_f)
List of 5
$ value : num 0.693
$ abs.error : num 7.7e-15
$ subdivisions: int 1
$ message : chr "OK"
$ call : language integrate(f = f, lower = 0,
upper = pi/2)
- attr(*, "class")= chr "integrate"
> in_f$value
[1] 0.6931472
Computational tools command inputs
> tent(1:4)
[1] 0 -2 -4 -6
> points(tent(1:4))
> plot(x,y,t="b",cex=1.5,pch=18,col="blue",cex.lab=1.25)
> # 'cex.lab' is the size of labels 'x' and 'y' on the axes
> # We can also add a legend whose upper left corner is in position (0.5,0.5)
> legend(0.0,0.8,"Points and lines",col="blue",pch=18)
> # Examples using 'curve' (observe that the operator '**' is treated as '^')
> f <- function(x) x-x**3
> curve(f,-3,3,lwd=2)
> windows()
> curve(x-x**3,-3,3,lwd=3,lty=2,col="red")
> # ...and note the different label on the axes
> # Now, to overlap different graphs/plots you can use 'add', e.g.
> plot(x,y)
> curve(f,-3,3,add=T) # the same of typing 'curve(f,-3,3,add=TRUE)'
Computational tools command inputs
> plot(x,y,pch=19)
> curve(x-x**5,add=T,col=4)
$f.root
[1] 2.165849e-06
$iter
[1] 2
$init.it
[1] NA
$estim.prec
[1] 0.0001148596
##################################################
> # EXERCISE: Try with the command "uniroot(f,c(-2,2))" ...and find out why it provides an Error !!!!
> # EXERCISE: compute the actual interest rate, after 1 year, of a BTP whose nominal reward is 3%,
> # it is purchased at April 1st, 2013 at a price of 101.7 and pays 1.5 in each semester
> # (here the investment in the BTP starts in April 1st 2013 and expires in April 1st 2014)
> btp <- function(r,price=101.7) -price + 1.5*1/(1+r)^0.5 + 101.5*1/(1+r) # 'price' is a parameter !!!!
> curve(btp,0,1)
> curve(btp,0,0.1) # zoom in to better locate the root
> curve(btp,0,0.02) # zoom in to better locate the root
> abline(h=0,col=3) # trace an horizontal line simulating the x-axis
> grid(col="red") # if you prefer to add a red 'grid'
> zz <- uniroot(btp,c(1.0e-2,1.5e-2))
> zz
$root
[1] 0.01288338
$f.root
[1] -0.0005999008
Computational tools command inputs
$iter
[1] 2
$init.it
[1] NA
$estim.prec
[1] 6.103516e-05
> # Observe that 'zz' is a list, and we have indeed:
> str(zz)
List of 5
$ root : num 0.0129
$ f.root : num -6e-04
$ iter : int 2
$ init.it : int NA
$ estim.prec: num 6.1e-05
> zz$root # Note that the root is just 1.28%, which is significantly smaller than 3% !!!!!
[1] 0.01288338
> str(zz)
> # We also recall the use and definition of a user-defined function, e.g.
> tent <- function(x) ifelse(x<0.5,2*x, 2-2*x)
> tent(0.1)
[1] 0.2
> tent(5)
[1] -8
> tent(18)
[1] -34
> # ...and we can draw the graph of function 'tent' (with a red grid) using
> curve(tent(x),-2,5)
> grid(col="red")
> points(-2:5,tent(-2:5)) # this command also gives points on the graph
> # To reverse the effects of a command we can use 'rev', whose effect depends on the
> # function it is applied to. Here is an example:
>x
[1] 3.486252 7.020825 5.031558 4.218064 4.195686 6.465254 5.578663 5.536243
[9] 5.651386 1.673548
> sort(x)
[1] 1.673548 3.486252 4.195686 4.218064 5.031558 5.536243 5.578663 5.651386
[9] 6.465254 7.020825
> rev(sort(x))
[1] 7.020825 6.465254 5.651386 5.578663 5.536243 5.031558 4.218064 4.195686
[9] 3.486252 1.673548
> sort(x,decreasing=T)
[1] 7.020825 6.465254 5.651386 5.578663 5.536243 5.031558 4.218064 4.195686
[9] 3.486252 1.673548
> y <- log(x+2)
> plot(x,y)
Computational tools command inputs
> polygon(c(x,rev(y)),c(y,rev(x)),col="red") # the vertices of the polygon have coordinates
# in the vectors 'c(x,rev(y))' and 'c(y,rev(x))'
###########################
# Plots with two unknowns #
###########################
> # Other graphic commands can be define
> # With the 'persp' command we can plot a 3D graph of the function 'z=f(x,y)'
> persp(x,y,z)
> windows()
> persp(x,y,z,theta=30,phi=30,ticktype="detailed") # gives the same 3D plot with a different perspective
# 'theta' gives the azimuthal direction, 'phi' the colatitude
> persp(x,y,z,theta=30, phi=30,ticktype="detailed",box=F) # will not plot any bounding box around f(x,y)
> ?persp # to see many more parameters/arguments of 'persp' function
> # We also have a different way to plot the 3D graph of a function, using its level curves, i.e.
> image(x,y,z)
> # and it is possible to add contours relative to the same levels of the function
> contour(x,y,z, add=T)
> contour(x,y,z, add=F)
> contour(x,y,z, add=T, labcex=1.2) # this adds the size of the level sets (using 'labcex')
> grid(col=2) # this adds, as usual, a red (i.e. col=2) grid
> # There is also the chance to zoom into the 3D plot around a specific point, say (1,2):
> x <- seq(0.5,1.5, length=31)
> y <- seq(1,3,length=40)
> z2 <- outer(x,y,f)
> image(x,y,z2)
> contour(x,y,z2,add=T,nlevels=20) # 'nlevels' specifies the number of desired level curves
> #=========================================================
> # EXERCISE n.13 (from the exam N.101 in January 7, 2015):
> #=========================================================
> f <- function(p) 4*exp(1.5*p) - 0.6*exp(4*p)
> curve(f,-5,5)
> curve(f,-1,1)
> grid(col=2)
> # In this case we want to find a maximum, thus we properly use 'optimize' as
> optimize(f, c(0,0.8), maximum=T)
$maximum
[1] 0.3665013
$objective
[1] 4.332155
> # this implies that the correct answer to the exercise is (b)
> #===========================================
> # Exercise 1 (optimization with 2 unknowns)
> #===========================================
NULL
Computational tools command inputs
> fb(c(0.5789234,-1.7893906)) # Remember that 'fb' is a function of a 2-real vector !!!!!!!
[1] -8.842105
> # Now let us draw the function 'fb'. We have to define a grid of points
> # nearby the maximum point found above
> x <- seq(-3,3,len=31)
>x
[1] -3.0 -2.8 -2.6 -2.4 -2.2 -2.0 -1.8 -1.6 -1.4 -1.2 -1.0 -0.8 -0.6 -0.4 -0.2 0.0 0.2 0.4
[19] 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0
> y <- seq(-3,3,len=31)
>y
[1] -3.0 -2.8 -2.6 -2.4 -2.2 -2.0 -1.8 -1.6 -1.4 -1.2 -1.0 -0.8 -0.6 -0.4 -0.2 0.0 0.2 0.4
[19] 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0
> zf <- outer(x,y,f)
> str(zf)
num [1:31, 1:31] 61 53.8 47 40.6 34.6 29 23.8 19 14.6 10.6 ...
> image(x,y,zf)
> contour(x,y,zf,add=T,labcex=1.3)
> #===========================================
> # Exercise 2 (optimization with 2 unknowns)
> #===========================================
> f <- function(x,y) (x^2+y^2+x*y)/6 + exp(-x^2+2*x) + exp(-y^2+2*y)
>x
[1] -3.0 -2.8 -2.6 -2.4 -2.2 -2.0 -1.8 -1.6 -1.4 -1.2 -1.0 -0.8 -0.6 -0.4 -0.2 0.0 0.2 0.4
[19] 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0
>y
[1] -3.0 -2.8 -2.6 -2.4 -2.2 -2.0 -1.8 -1.6 -1.4 -1.2 -1.0 -0.8 -0.6 -0.4 -0.2 0.0 0.2 0.4
[19] 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0
> fz <- outer(x,y,f)
> image(x,y,fz)
> contour(x,y,fz,add=T)
> contour(x,y,fz,labcex=2,add=T)
$value
[1] -4.388433
$counts
function gradient
49 NA
$convergence
[1] 0
$message
NULL
> points(0.4347055,1.9172768,pch=19) # plots the minimum point
> g(0.4347055,1.9172768) # gives the value of the function 'g' (of two real unknowns)
[1] -4.388433
> gb(c(0.4347055,1.9172768)) # gives the value of the function 'gb' (of a 2-real vector)
[1] -4.388433
> #===========================
> # DERIVATIVES OF A FUNCTION
> #===========================
> # As regards the derivative of a function of one unknown, let us consider the next example and compare
the
> # plots of f(x) an f'(x) from a theoretical point of view: observe that the function increases when the
> # derivative is positive. Moreover, the function is convex whenever f''(x) is positive.
> f <- function(x) 3*x^3+2*x^2+x
> curve(f,-3,3)
> abline(h=0,col="green")
> g <- function(x) 9*x^2+4*x+1
> curve(g,-3,3,lty="dashed",add=T)
> h <- function(x) 18*x+4
> curve(h,-3,3,lty="dotted",add=T)
> # As regards partial derivatives f_x and f_y of the function f(x,y), it is possible to define them by using
> # finite differences, i.e.
> # f(x+h,y)-f(x,y) f(x,y+h)-f(x,y)
> # f_x = ----------------- f_y = -----------------
>#hh
> x <- seq(-3,3,len=31)
> y <- seq(-3,3,len=31)
> f <- function(x,y) (x^2+x*y+y^2)/6 + exp(-x^2+2*x) + exp(-y^2+2*y)
Computational tools command inputs
> fx <- function(x,y,h=0.0001) (f(x+h,y)-f(x,y))/h
> fy <- function(x,y,h=0.0001) (f(x,y+h)-f(x,y))/h
> # Now, let us plot the partial derivatives fx and fy. They are, similarly to f(x,y) functions of 2 unknowns,
thus,
> fz <- outer(x,y,f)
> fxz <- outer(x,y,fx)
> fyz <- outer(x,y,fy)
> str(fyz)
num [1:31, 1:31] -1.5 -1.47 -1.43 -1.4 -1.37 ...
> contour(x,y,fz, labcex=1.3) # plots the level contours of the function
> contour(x,y,fxz, add=T, col=2, lty=2, labcex=1, level=0, lwd=2) # plots the level contours of fx
> contour(x,y,fyz, add=T, col=3, lty=2, labcex=1, level=0, lwd=2) # plots the level contours of fy
$rank
[1] 2
$qraux
[1] 1.707107e+00 7.071068e-01 2.220446e-16
$pivot
[1] 1 3 2
attr(,"class")
[1] "qr"
Computational tools command inputs
> # so that the rank of the complete matrix is equal to 2, and Rouchè-Capelli Theorem
> # says that no solution is allowed for the linear system. Indeed,...
> solve(A,b)
Error in solve.default(A, b) :
Lapack routine dgesv: system is exactly singular: U[2,2] = 0
> # As a third case we consider for the matrix 'A' the expression
> A <- matrix(c(1,2,3,4,5,6,7,8,9),3,3,byrow=T)
>A
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[3,] 7 8 9
> # and given the vector 'v' as
> v <- c(1,1/2,-1)
>v
[1] 1.0 0.5 -1.0
> # we obtain for the product 'A*v' (remember the use of the operator "%*%" in place of "*")
> A%*%v
[,1]
[1,] -1.0
[2,] 0.5
[3,] 2.0
> # I want to show that the previous product can be seen as the linear combination
> # of colums of 'A', indeed...
> 1*A[,1]+1/2*A[,2]-1*A[,3]
[1] -1.0 0.5 2.0
> # Now we compute the rank of 'A'
> rr <- qr(A)
> rr$rank
[1] 2
> # Let us also choose a vector 'b' of known terms for the linear system, as
> b <- c(7,5,3)
>b
[1] 7 5 3
>A
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[3,] 7 8 9
> # Let us try to solve the linear system 'Ax=b' and verify that we obtain a specific error message
> solve(A,b)
Error in solve.default(A, b) :
il sistema è numericamente singolare: valore di condizione di reciprocità = 1.54198e-18
> # Let us verify if Rouchè-Capelli theorem is satisfied. Thus, we verify both the rank of
> # 'A' and the rank of the complete matrix 'Ab', i.e.
> Ab <- cbind(A,b)
> Ab
Computational tools command inputs
b
[1,] 1 2 3 7
[2,] 4 5 6 5
[3,] 7 8 9 3
> qr(Ab)$rank
[1] 2
> qr(A)$rank
[1] 2
> # which implies that by the Rouchè-Capelli Theorem we have infinite solutions to 'Ax=b'.
> # Let us choose now for 'b' the vector
> b <- c(-2,6,1)
>A
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[3,] 7 8 9
> Ab <-cbind(A,b)
> Ab
b
[1,] 1 2 3 -2
[2,] 4 5 6 6
[3,] 7 8 9 1
> qr(Ab)$rank
[1] 3
> qr(A)$rank
[1] 2
> # and 'Ax=b' is an IMPOSSIBLE system, being 'qr(Ab)$rank' not equal to 'qr(A)$rank'
> # We choose now the matrix 'A <- matrix(c(1,1,2,3),2,2,byrow=T)' and the vector 'b <- c(1,2)', i.e.
> A <- matrix(c(1,1,2,3),2,2,byrow=T)
>A
[,1] [,2]
[1,] 1 1
[2,] 2 3
> b <- c(1,2)
> qr(A)$rank
[1] 2
> qr(cbind(A,b))$rank
[1] 2
> # thus, Rouchè-Capelli Theorem ensures that 'Ax=b' admits solutions
> sol <- solve(A,b)
> sol
[1] 1 0
> # Now, let us compute the inverse of matrix 'A', i.e. A^(-1), using 'solve(A)'
> invA <- solve(A)
> invA
[,1] [,2]
[1,] 3 -1
[2,] -2 1
> # and verify that invA*A is the identity matrix
> invA%*%A
[,1] [,2]
Computational tools command inputs
[1,] 1 0
[2,] 0 1
> # Of course when solving 'Ax=b' we also have 'x = A^(-1)b, indeed...
> invA%*%b
[,1]
[1,] 1
[2,] 0
> # which coincides with 'sol'. Let us now consider again one of the above examples
> A <- matrix(1:9,3,3, byrow=T)
>A
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[3,] 7 8 9
> b <- c(7,5,3)
> solve(A,b)
Error in solve.default(A, b) :
il sistema è numericamente singolare: valore di condizione di reciprocità = 2.59052e-18
> det(A)
[1] 6.661338e-16
> # which implies that the matrix 'A' is near singular. However, since we also have
> qr(A)$rank
[1] 2
> qr(cbind(A,b))$rank
[1] 2
> # by Rouchè-Capelli we know that the linear system admits infinite solutions. One of them
> # can be found using the so called "Pseudo-inverse" or "Moore-Penrose pseudo-inverse" of 'A', as
> library(MASS)
> ginvA <- ginv(A)
> ginvA
[,1] [,2] [,3]
[1,] -0.63888889 -1.666667e-01 0.30555556
[2,] -0.05555556 3.469447e-17 0.05555556
[3,] 0.52777778 1.666667e-01 -0.19444444
> sol <- ginvA%*%b
> sol
[,1]
[1,] -4.3888889
[2,] -0.2222222
[3,] 3.9444444
> A%*%sol
[,1]
[1,] 7
[2,] 5
[3,] 3
>b
[1] 7 5 3
> # TO SUMMARIZE: the linear system 'Ax=b' admits solutions if and only if rk(A)=rk(A|b).
> # If the latter condition is satisfied, then to solve it you can use the inverse or the
> # generalized inverse of A, depending on the fact that A can be or be not singular. I.e.,
> # check if the system has a solution applying Rouchè-Capelli Theorem: if there is a solution
Computational tools command inputs
> # compute ginv(A)%*%b, because also in case 'A' is invertible, its "inverse" coincides with
> # its "pseudo-inverse".
> # In the next example (i.e. x+y=1, x+y=17) the linear system DOES NOT admit solution
> library(MASS)
> A <- matrix(c(1,1,1,1),2,2)
> b <- c(1,17)
> v <- ginv(A)%*%b
>v
[,1]
[1,] 4.5
[2,] 4.5
> # however we have that
> A%*%v
[,1]
[1,] 9
[2,] 9
>b
[1] 1 17
> # thus, we found the vector 'v' which IS NOT A SOLUTION of the linear system !!!!!!!!
> qr(A)$rank
[1] 1
> qr(cbind(A,b))$rank
[1] 2
> # Let us consider the next payoff-matrix with 3 scenarios and 3 assets
> Y <- matrix(c(104, 104, 104, 108, 102, 100, 112, 106, 93),3,3)
>Y
[,1] [,2] [,3]
[1,] 104 108 112
[2,] 104 102 106
[3,] 104 100 93
> # suppose we have the portfolio 'x' as
> x <- c(1/3,1/3,1/3)
> # and let us compute the payoffs
> y <- Y%*%x
>y
[,1]
[1,] 108
[2,] 104
[3,] 99
> # equivalently 'y' is a linear combination of the columns of 'Y', i.e.
> 1/3*Y[,1]+1/3*Y[,2]+1/3*Y[,3]
[1] 108 104 99
> # Let us consider the next vector of pay-per-unit of the assets
Computational tools command inputs
> pai <- c(100,100,100)
> # so that our portfolio costs, for any asset,
> x*pai
[1] 33.33333 33.33333 33.33333
> # and the overall cost is
> sum(x*pai)
[1] 100
> # Can the asset b <- c(112,106,104) be "replicated"?
> qr(Y)$rank
[1] 3
> qr(cbind(Y,c(112,106,104)))$rank
[1] 3
> # thus 'b' can surely be replicated (i.e. the linear system Yx=b admits solutions)
> b <- c(112,106,104)
> x <- ginv(Y)%*%b
>x
[,1]
[1,] 3.846154e-02
[2,] 1.000000e+00
[3,] 1.776357e-15
> # and to prove that 'Yx=b' admits solution we have...
> Y%*%x
[,1]
[1,] 112
[2,] 106
[3,] 104
>b
[1] 112 106 104
>Y
[,1] [,2] [,3]
[1,] 104 108 112
[2,] 104 102 106
[3,] 104 100 93
> solve(Y,b)
[1] 0.03846154 1.00000000 0.00000000
> # Which is now the price of the vector b we replicated?
> pai
[1] 100 100 100
> sum(pai*x)
[1] 103.8462
> #===========================================================