This vignette illustrates the ideas behind solving systems of linear equations of the form \(\mathbf{A x = b}\) where
The general conditions for solutions are:
We use c( R(A), R(cbind(A,b)) )
to show the ranks, and all.equal( R(A), R(cbind(A,b)) )
to test
for consistency.
library(matlib) # use the package
Each equation in two unknowns corresponds to a line in 2D space. The equations have a unique solution if all lines intersect in a point.
A <- matrix(c(1, 2, -1, 2), 2, 2)
b <- c(2,1)
showEqn(A, b)
## [,1]
## [1,] "1*x1 - 1*x2 = 2"
## [2,] "2*x1 + 2*x2 = 1"
c( R(A), R(cbind(A,b)) ) # show ranks
## [1] 2 2
all.equal( R(A), R(cbind(A,b)) ) # consistent?
## [1] TRUE
Plot them:
plotEqn(A,b)
For three (or more) equations in two unknowns, \(r(\mathbf{A}) \le 2\), because \(r(\mathbf{A}) \le \min(m,n)\). The equations will be consistent if \(r(\mathbf{A}) = r(\mathbf{A | b})\), which means that whatever linear relations exist among the rows of \(\mathbf{A}\) are the same as those among the elements of \(\mathbf{b}\).
A <- matrix(c(1,2,3, -1, 2, 1), 3, 2)
b <- c(2,1,3)
showEqn(A, b)
## [,1]
## [1,] "1*x1 - 1*x2 = 2"
## [2,] "2*x1 + 2*x2 = 1"
## [3,] "3*x1 + 1*x2 = 3"
c( R(A), R(cbind(A,b)) ) # show ranks
## [1] 2 2
all.equal( R(A), R(cbind(A,b)) ) # consistent?
## [1] TRUE
Plot them:
plotEqn(A,b)
A <- matrix(c(1,2,3, -1, 2, 1), 3, 2)
b <- c(2,1,6)
showEqn(A, b)
## [,1]
## [1,] "1*x1 - 1*x2 = 2"
## [2,] "2*x1 + 2*x2 = 1"
## [3,] "3*x1 + 1*x2 = 6"
c( R(A), R(cbind(A,b)) ) # show ranks
## [1] 2 3
all.equal( R(A), R(cbind(A,b)) ) # consistent?
## [1] "Mean relative difference: 0.5"
An approximate solution is sometimes available using a generalized inverse.
x <- MASS::ginv(A) %*% b
x
## [,1]
## [1,] 2
## [2,] -1
Plot the equations. You can see that each pair of equations has a solution, but all three do not have a common, consistent solution.
plotEqn(A,b, xlim=c(-2, 4))
points(x[1], x[2], pch=15)
Each equation in three unknowns corresponds to a plane in 3D space. The equations have a unique solution if all planes intersect in a point.
A <- matrix(c(2, 1, -1,
-3, -1, 2,
-2, 1, 2), 3, 3, byrow=TRUE)
colnames(A) <- paste0('x', 1:3)
b <- c(8, -11, -3)
showEqn(A, b)
## [,1]
## [1,] "2*x1 + 1*x2 - 1*x3 = 8"
## [2,] "-3*x1 - 1*x2 + 2*x3 = -11"
## [3,] "-2*x1 + 1*x2 + 2*x3 = -3"
Are the equations consistent?
c( R(A), R(cbind(A,b)) ) # show ranks
## [1] 3 3
all.equal( R(A), R(cbind(A,b)) ) # consistent?
## [1] TRUE
Solve for \(\mathbf{x}\).
solve(A, b)
## x1 x2 x3
## 2 3 -1
solve(A) %*% b
## [,1]
## x1 2
## x2 3
## x3 -1
inv(A) %*% b
## [,1]
## [1,] 2
## [2,] 3
## [3,] -1
Another way to see the solution is to reduce \(\mathbf{A | b}\) to echelon form. The result is \(\mathbf{I | A^{-1}b}\), with the solution in the last column.
echelon(A, b)
## x1 x2 x3
## [1,] 1 0 0 2
## [2,] 0 1 0 3
## [3,] 0 0 1 -1
echelon(A, b, verbose=TRUE, fractions=TRUE)
## row: 1
## x1 x2 x3
## [1,] 1 1/3 -2/3 11/3
## [2,] 0 1/3 1/3 2/3
## [3,] 0 5/3 2/3 13/3
## row: 2
## x1 x2 x3
## [1,] 1 0 -4/5 14/5
## [2,] 0 1 2/5 13/5
## [3,] 0 0 1/5 -1/5
## row: 3
## x1 x2 x3
## [1,] 1 0 0 2
## [2,] 0 1 0 3
## [3,] 0 0 1 -1
## x1 x2 x3
## [1,] 1 0 0 2
## [2,] 0 1 0 3
## [3,] 0 0 1 -1
Plot them. plotEqn3d
uses rgl
for 3D graphics. If you rotate the figure, you'll see an orientation
where all three planes intersect at the solution point, \(\mathbf{x} = (2, 3, -1)\)
plotEqn3d(A,b, xlim=c(0,4), ylim=c(0,4))
You must enable Javascript to view this page properly.
A <- matrix(c(1, 3, 1,
1, -2, -2,
2, 1, -1), 3, 3, byrow=TRUE)
colnames(A) <- paste0('x', 1:3)
b <- c(2, 3, 6)
showEqn(A, b)
## [,1]
## [1,] "1*x1 + 3*x2 + 1*x3 = 2"
## [2,] "1*x1 - 2*x2 - 2*x3 = 3"
## [3,] "2*x1 + 1*x2 - 1*x3 = 6"
Are the equations consistent? No.
c( R(A), R(cbind(A,b)) ) # show ranks
## [1] 2 3
all.equal( R(A), R(cbind(A,b)) ) # consistent?
## [1] "Mean relative difference: 0.5"