Gaussian Elimination is an algorithm to solve a system of linear equations of n variables. It uses elementary operations to find the solution to the system of linear equations. It is an efficient method to find the determinant and inverse of a matrix as well. In this program, we will learn how to solve a system of equations using this method. We will also learn how to calculate the determinant of the n x n matrix used in the process.
- We create a module for 3 matrices a(n,m) for the augmented matrix, b(n) for temporary values of x and x(n) for the final solutions. We will need this in the main program as well as the subroutine.
- We read the number of variables, n at the time of execution.
- We read the augmented matrix from an input file and display it on the screen.
- Optional: At this stage, we can create another matrix check(n,m) to store the initial values of elements of a(n,m). This can help us substitute the obtained values of x1,x2,...,xn later and verify them.
- We call a subroutine and display the results only in the square matrix a(n,n) is non-singular. This is also called the coefficient matrix.The subroutine needs only the input m or n. The rest of the values are held in the module. The subroutine generates the arrays and the output sing to tell the status of singularity of the matrix a(n,n).
- Optional: We can evaluate the L.H.S. and R.H.S by using two simple one-column arrays of n rows. R.H.S will simply be the initial values of a(:,m) and L.H.S. will be a1*x1+a12*x2+...a1n*xn, a21*x1+a22*x2+...a2n*xn,and so on for all n equations. If L.H.S. and R.H.S. are equal for all rows, we have successfully recreated the equation to verify the results.
- The first step is forward elimination. Starting with the first row, we make sure that the diagonal element has the largest element for its column in that row and all the subsequent rows. If not, we swap rows with the row from the rows below which has the largest element in that column. This is an elementary operation.
- Next, we perform another elementary operation. We subtract from each subsequent row c=a(k,i)/a(i,i) times the row whose diagonal element large has been set now. So, every a(k,:)=a(k,:)-c*a(i,:). These two steps are repeated for all rows till we get a triangulated matrix.
- At this stage we can calculate the determinant by multiplying all the diagonal elements a(i,i) together. If the determinant is non-zero, we proceed with the next step. Else we return to the main program.
- Finally, we perform back substitution. So, xn=bn/a(n,n). Knowing this, we calculate x(n-1)=[b(n-1)-a(n,n)*x(n)]/a(n-1,n-1)...and so on to find values of xn, x(n-1) through x1.We store this result in the array x(n).
Forward Elimination and Triangularization |
Row Swapping Explained further |
Back Substitution to Calculate the Final Values of xn through x1 Backwards |
Now for the FORTRAN program,
!To use arrays in the program
module arrays
real, allocatable :: a(:,:) , x(:), b(:)
end module arrays
!To solve a system of equations of n variables using Gauss elimination method
program gausepivot
use arrays
implicit none
integer i,j,n,m,sing,flag
real, allocatable :: LHS(:),RHS(:), check(:,:) !These arrays are optional. Only to verify results
write(*,*) "Give the size of the coefficient matrix i.e. the number of variables in the system of linear equations"
read (*,*) n
write(*,*) "The size of the coefficient matrix is ",n
open(unit=1, file='gause.in')
m=n+1
allocate (a(n,m),x(n),b(n))
write(*,*) "Producing the augmented matrix:"
do i=1,n
read(unit=1,fmt=*) (a(i,j),j=1,m)
write(*,*) (a(i,j),j=1,m)
end do
!To verify results later. Optional
allocate(check(n,m)) !To save the values of the array a(n,m) before they are altered
do i=1,n
do j=1,m
check(i,j)=a(i,j)
end do
end do
call gauss (m,sing) !To call the subroutine that calculates the results
if (sing==1) then
write(*,*) "the coefficient matrix is singular"
else ! To display results only if the matrix is non-singular
write(*,*) "The given equation has the set of solutions in the order given as follows"
write(*,*) (x(i),i=1,n)
end if
allocate (LHS(n),RHS(n)) !To test the values in array x(n) by substituting them in the linear equation. Optional
do i=1,n
LHS(i)=0
do j=1,m-1
LHS(i)=x(j)*check(i,j)+LHS(i)
end do
write(*,20) "LHS of row #",i,"=",LHS(i)
20 format (a,i3,a,f20.8)
RHS(i)=check(i,m)
write(*,10) "RHS of row #",i,"=",RHS(i)
10 format (a,i3,a,f20.8)
end do
flag=0 !To set the flag=1 if the L.H.S. is not equal to the R.H.S.
do i=1,n
if (abs(LHS(i)-RHS(i)).gt.00001) then
flag=1
exit
end if
end do
if (flag==1) then !To write if results match or not
write(*,*) "Results incorrect"
else
write(*,*) "The program works"
end if
end program gausepivot
subroutine gauss (m,sing) !Subroutine for the actual calculations
use arrays
implicit none
integer :: n,m,sing,j,imax,i,k
real:: temp(m),eps,flag,large,aa,det,sumax,c
eps=1.0e-5
!Forward Elimination
!Triangulation
n=m-1
do i=1,n
flag=0
large=abs(a(i,i)) !To define the diagonal element of every row as 'large'
do j=i+1,n
aa=abs(a(j,i)) !To check the subsequent elements in the same column below the row
if (aa>large) then !To check if the diagonal element is the largest in the column
large=aa
flag=1
imax=j
end if
end do
!Row swapping
if (flag==1) then !To swap rows so that the diagonal element of each row is larger than all elements in the same column in rows below it
temp=a(i,:)
a(i,:)=a(imax,:)
a(imax,:)=temp
end if
do k=i+1,n !To eliminate a variable from all subsequent rows
c=a(k,i)/a(i,i) !Note that this value is fixed for a given k. (Elementary operation)
a(k,:)=a(k,:)-c*a(i,:) !This will become zero when a(k,i)= a(k,i) from the row a(k,:)
end do
end do
!Checking for singularity of coefficient matrix
!Find det(a)
det=1.0 !At this point the determinant is calculated simply by multiplying all the diagonal elements a(i,i)
do i=1,n
det=det*a(i,i)
end do
if (abs(det)<eps) then !Calculating the determinant helps us find out if the matrix is singular
sing=1 !In this case we will not get results
return
else
sing=0
end if
!Back substitution
b=a(:,m)
do i=n,1,-1 !This time we go from the bottom row to the top
sumax=0.0
do j=i+1,n !We look at all elements in the row to the right of the diagonal
sumax=sumax+a(i,j)*x(j)
end do
x(i)=(b(i)-sumax)/a(i,i)
end do
end subroutine gauss
!To use arrays in the program
module arrays
real, allocatable :: a(:,:) , x(:), b(:)
end module arrays
!To solve a system of equations of n variables using Gauss elimination method
program gausepivot
use arrays
implicit none
integer i,j,n,m,sing,flag
real, allocatable :: LHS(:),RHS(:), check(:,:) !These arrays are optional. Only to verify results
write(*,*) "Give the size of the coefficient matrix i.e. the number of variables in the system of linear equations"
read (*,*) n
write(*,*) "The size of the coefficient matrix is ",n
open(unit=1, file='gause.in')
m=n+1
allocate (a(n,m),x(n),b(n))
write(*,*) "Producing the augmented matrix:"
do i=1,n
read(unit=1,fmt=*) (a(i,j),j=1,m)
write(*,*) (a(i,j),j=1,m)
end do
!To verify results later. Optional
allocate(check(n,m)) !To save the values of the array a(n,m) before they are altered
do i=1,n
do j=1,m
check(i,j)=a(i,j)
end do
end do
call gauss (m,sing) !To call the subroutine that calculates the results
if (sing==1) then
write(*,*) "the coefficient matrix is singular"
else ! To display results only if the matrix is non-singular
write(*,*) "The given equation has the set of solutions in the order given as follows"
write(*,*) (x(i),i=1,n)
end if
allocate (LHS(n),RHS(n)) !To test the values in array x(n) by substituting them in the linear equation. Optional
do i=1,n
LHS(i)=0
do j=1,m-1
LHS(i)=x(j)*check(i,j)+LHS(i)
end do
write(*,20) "LHS of row #",i,"=",LHS(i)
20 format (a,i3,a,f20.8)
RHS(i)=check(i,m)
write(*,10) "RHS of row #",i,"=",RHS(i)
10 format (a,i3,a,f20.8)
end do
flag=0 !To set the flag=1 if the L.H.S. is not equal to the R.H.S.
do i=1,n
if (abs(LHS(i)-RHS(i)).gt.00001) then
flag=1
exit
end if
end do
if (flag==1) then !To write if results match or not
write(*,*) "Results incorrect"
else
write(*,*) "The program works"
end if
end program gausepivot
subroutine gauss (m,sing) !Subroutine for the actual calculations
use arrays
implicit none
integer :: n,m,sing,j,imax,i,k
real:: temp(m),eps,flag,large,aa,det,sumax,c
eps=1.0e-5
!Forward Elimination
!Triangulation
n=m-1
do i=1,n
flag=0
large=abs(a(i,i)) !To define the diagonal element of every row as 'large'
do j=i+1,n
aa=abs(a(j,i)) !To check the subsequent elements in the same column below the row
if (aa>large) then !To check if the diagonal element is the largest in the column
large=aa
flag=1
imax=j
end if
end do
!Row swapping
if (flag==1) then !To swap rows so that the diagonal element of each row is larger than all elements in the same column in rows below it
temp=a(i,:)
a(i,:)=a(imax,:)
a(imax,:)=temp
end if
do k=i+1,n !To eliminate a variable from all subsequent rows
c=a(k,i)/a(i,i) !Note that this value is fixed for a given k. (Elementary operation)
a(k,:)=a(k,:)-c*a(i,:) !This will become zero when a(k,i)= a(k,i) from the row a(k,:)
end do
end do
!Checking for singularity of coefficient matrix
!Find det(a)
det=1.0 !At this point the determinant is calculated simply by multiplying all the diagonal elements a(i,i)
do i=1,n
det=det*a(i,i)
end do
if (abs(det)<eps) then !Calculating the determinant helps us find out if the matrix is singular
sing=1 !In this case we will not get results
return
else
sing=0
end if
!Back substitution
b=a(:,m)
do i=n,1,-1 !This time we go from the bottom row to the top
sumax=0.0
do j=i+1,n !We look at all elements in the row to the right of the diagonal
sumax=sumax+a(i,j)*x(j)
end do
x(i)=(b(i)-sumax)/a(i,i)
end do
end subroutine gauss
Sample Output for a System of 4 Linear Equations with 4 Variables |
No comments:
Post a Comment