How to do Gaussian elimination in R (do not use solve)
I had to reorder you matrix A
, don't know how do a generic code:
A <- matrix(c(2,-5,4,1,-4,6,1,-2.5,1),byrow=T,nrow=3,ncol=3)
b <- matrix(c(-3,5,10),nrow=3,ncol=1)
p <- nrow(A)
(U.pls <- cbind(A,b))
U.pls[1,] <- U.pls[1,]/U.pls[1,1]
for (i in 2:p){
for (j in i:p) {
U.pls[j, ] <- U.pls[j, ] - U.pls[i-1, ] * U.pls[j, i-1]
}
U.pls[i,] <- U.pls[i,]/U.pls[i,i]
}
for (i in p:2){
for (j in i:2-1) {
U.pls[j, ] <- U.pls[j, ] - U.pls[i, ] * U.pls[j, i]
}
}
U.pls
EDIT:
A <- matrix(c(2,-5,4,1,-2.5,1,1,-4,6),byrow=T,nrow=3,ncol=3)
b <- matrix(c(-3,5,10),nrow=3,ncol=1)
p <- nrow(A)
(U.pls <- cbind(A,b))
U.pls[1,] <- U.pls[1,]/U.pls[1,1]
i <- 2
while (i < p+1) {
j <- i
while (j < p+1) {
U.pls[j, ] <- U.pls[j, ] - U.pls[i-1, ] * U.pls[j, i-1]
j <- j+1
}
while (U.pls[i,i] == 0) {
U.pls <- rbind(U.pls[-i,],U.pls[i,])
}
U.pls[i,] <- U.pls[i,]/U.pls[i,i]
i <- i+1
}
for (i in p:2){
for (j in i:2-1) {
U.pls[j, ] <- U.pls[j, ] - U.pls[i, ] * U.pls[j, i]
}
}
U.pls
Gaussian Elimination not working
You say that your code creates the upper triangular matrix of A correctly, but it doesn't. Let me show you an example.
Let A and b be
A =
3 2 3 4
4 3 2 1
1 0 4 0
0 5 0 3
b =
2
4
6
7
If we run your code as it is and look at A and b we get
A =
3.0000 2.0000 3.0000 4.0000
1.3333 0.3333 -2.0000 -4.3333
0.3333 -2.0000 -1.0000 -10.0000
0 15.0000 -30.0000 -232.0000
b =
7.0000
-203.0000
187.0000
7.0000
Which is neither a triangular matrix, nor the b that we expected. But if we modify slightly your program to be:
function [ x ] = Gauss( A,b )
n=length(b);
for j=1:n-1
if A(j,j)==0
break;
end;
for i=j+1:n
f=A(i,j)/A(j,j); %%Save the proportion between the rows in a
%%different variable outside the matrix, or
%%you will loose the value that was originally there
b(i)=b(i)-f*b(j); %%The operation has to be done in the row you are currently working
for k=1:n %%You have to make the operation in the full row,
%%not only in the remaining columns, also you can
%%make this without a for loop using `:`
%%indexing, but if you dont know about it,
%%leave as it is, it works
A(i,k)=A(i,k)-f*A(j,k);
end
end
end
A
b
end
You get this result
A =
3.0000 2.0000 3.0000 4.0000
0 0.3333 -2.0000 -4.3333
0 0 -1.0000 -10.0000
0 0 0 -232.0000
b =
2.0000
1.3333
8.0000
227.0000
Which is a upper triangular matrix, and the b we want. Hopefully you can take it from here, just as a reference the next steps should look like this
A =
1.0000 0.6667 1.0000 1.3333
0 1.0000 -6.0000 -13.0000
0 0 1.0000 10.0000
0 0 0 1.0000
b =
0.6667
4.0000
-8.0000
-0.9784
then
A =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
b =
-1.1379
1.9871
1.7845
-0.9784
In which A is already an identity matrix, which mean that b is already our answer, that we can corroborate doing
A\b
ans=
-1.1379
1.9871
1.7845
-0.9784
J: Gauss-Jordan elimination
Thanks to Eelvex, who advised me to look in addons/math/misc/linear.ijs
, I've concluded the task with this nice code:
gj=: monad :0
I=. i.#y
for_i. I do. y=. y - (col - i=I) */ (i{y) % i{col=. i{"1 y end.
)
gj Ab
1 0 0 0 _1
0 1 0 0 3
0 0 1 0 _2
0 0 0 1 2
It has taken some time to understand verb pivot
in linear.ijs
- but pencil-paper method helps.
R Gaussian Elimination and qr factorization
When you read the help for qr
you see that R uses a pivoted QR-decomposition.
So
str(b)
gives
List of 4
$ qr : num [1:30, 1:6] -3.2292 0.218 0.0623 0.0371 0.302 ...
$ rank : int 4
$ qraux: num [1:6] 1.05 1.11 1.04 1.22 0 ...
$ pivot: int [1:6] 1 3 5 6 2 4
- attr(*, "class")= chr "qr"
Thus you need to apply pivot
to a
or the inverse of pivot
to d
to line the matrices up correctly. So
pivots <- b$pivot
d.ok <- d[,order(pivots)]
all.equal(a,d.ok)
gives
[1] TRUE
You can also do
a.p <- a[,pivots]
all.equal(a.p,d)
which also results in TRUE
.
What is wrong with my Gauss-Jordan elimination?
Problem is solved. The question has been updated, among other with the new code (the old one is still available, to allow comparison). There were two bugs (the below "STEP XYZ" references the corresponding source code's STEP, not the steps mentionned on this StackOverflow question, which are presented a bit differently) :
The subtraction concerning the identity matrix didn't use identity matrix's coefficient (STEP 4). Bug fix :
identity_matrix(id_line)(id_column) -= identity_matrix(id_last_pivot)(id_column) * tmp
Second, in STEP 3, I forgot to store the pivot in a temporary variable, in order to divide the both matrices (original and identity ones) with it. Without storing it, the value of the pivot changed after the division on the original matrix. Bug fix :
val tmp = mutable_being_inversed_matrix(id_last_pivot)(general_id_column)
mutable_being_inversed_matrix(id_last_pivot) = mutable_being_inversed_matrix(id_last_pivot).map(coefficient => coefficient / tmp)
identity_matrix(id_last_pivot) = identity_matrix(id_last_pivot).map(coefficient => coefficient / tmp)
Related Topics
Using Filtered Datatables in Shiny
Keyboard Shortcut for Inserting Roxygen #' Comment Start
Ggplot2: Add P-Values to the Plot
How to Create Geom_Boxplot with Large Amount of Continuous X-Variables
Using R to Fit a Sigmoidal Curve
R Markdown Math Equation Alignment
Grouping with Custom Geom Fails - How to Inspect Internal Object from Draw_Panel()
Delete Rows Based on Multiple Conditions with Dplyr
How Calculate Growth Rate in Long Format Data Frame
Insert Images Using Knitr::Include_Graphics in a for Loop
R Ggplot2 Center Align a Multi-Line Title
References Truncated in Beamer Presentation Prepared in Knitr/Rmarkdown
How to Create a List in R from Two Vectors (One Would Be the Keys, the Other the Values)
R, Deep VS. Shallow Copies, Pass by Reference
Function Commenting Conventions in R
Ggplot Object Not Found Error When Adding Layer with Different Data