Linear System Solutions in C++ using Boost::ublas
#include < boost/numeric/ublas/matrix.hpp >
#include < boost/numeric/ublas/lu.hpp >
#include < boost/numeric/ublas/io.hpp >
using namespace boost::numeric::ublas;
using namespace std;
typedef boost::numeric::ublas::vector< double > ublasVector;
typedef boost::numeric::ublas::matrix< double > ublasMatrix;
typedef boost::numeric::ublas::matrix_row< ublasMatrix > ublasMatrixRow;
typedef boost::numeric::ublas::matrix_range< matrix < double > > ublasMatrixRange;
Gaussian Elimination Method
// Ax=b ==>> transform to Ux=b
ublasVector GaussianElimination(ublasMatrix um, ublasVector uv)
{
std::cout << uv << std::endl;
std::cout << um << std::endl;
// eliminate and create upper triangle augmented matrix
for(int i=0; i<(uv.size()-1); ++i){
for(int j=i+1; j< uv.size(); ++j){
double lem=um(j,i)/um(i,i);
ublasMatrixRow(um,j) -= lem*ublasMatrixRow(um,i);
uv(j)-=lem*uv(i);
}
}
// back substitution to get result
for(int i=uv.size()-1; i>=0; --i){
double in=inner_prod(subrange(uv,i+1,uv.size()),subrange(ublasMatrixRow(um,i),i+1,uv.size()));
uv(i)=(uv(i)-in)/um(i,i);
}
ublasVector retuv(uv);
return retuv;
}
LU Decomposition
// decompose Ax=b ==>> LUx=b hance tranform A=LU
void LUDecomposition(ublasMatrix& um)
{
std::cout << um << std::endl;
for(int i=0; i< (um.size1()-1); ++i){
for(int j=i+1; j< um.size1(); ++j){
double lem=um(j,i)/um(i,i);
ublasMatrixRange(um,range(j,j+1),range(i+1,um.size1())) -= lem*ublasMatrixRange(um,range(i,i+1),range(i+1,um.size1()));
um(j,i)=lem;
}
}
}
LU Solver using LUDecomposition
// This use LUdecompose matrix to resolve liner equation
ublasVector LUSolver(ublasMatrix um, ublasVector uv)
{
// forward substitution Ly=b to get solution for y
for(int i=1; i< uv.size(); ++i){
double in=inner_prod(subrange(ublasMatrixRow(um,i),0,i),subrange(uv,0,i));
uv(i)-=in;
}
// back substitution to get result Ux=y
for(int i=uv.size()-1; i>=0; --i){
double in=inner_prod(subrange(uv,i+1,uv.size()),subrange(ublasMatrixRow(um,i),i+1,uv.size()));
uv(i)=(uv(i)-in)/um(i,i);
}
ublasVector retuv(uv);
return retuv;
}
Test Programs
void testLUDecompose()
{
ublasVector uv (3);
uv (0) = 6;uv (1) = 3;uv (2) = 7;
ublasMatrix um(3,3);
um(0,0)=3;um(0,1)=-1;um(0,2)=4;
um(1,0)=-2;um(1,1)=0;um(1,2)=5;
um(2,0)=7;um(2,1)=2;um(2,2)=-2;
std::cout << um << std::endl;
LUDecomposition(um);
std::cout << um << std::endl;
// calculate determinante |A|
double dt=1;
for(int i=0; i< um.size1();++i) dt*=um(i,i);
std::cout << dt << std::endl;
ublasVector retuv=LUSolver(um,uv);
std::cout << retuv << std::endl;
}
Choleski Decomposition Method
// decompose Ax=b ==>> L*trans(L)x=b
void CholeskiDecomposition(ublasMatrix& um)
{
std::cout << um << std::endl;
for(int i=0; i< um.size1(); ++i){
try{
ublasVector uv=subrange(ublasMatrixRow(um,i),0,i);
double in = inner_prod(uv,uv);
if(in < um(i,i))
um(i,i)=sqrt(um(i,i)-inner_prod(uv,uv));
else
cout<< "Matirx is not positive definite" << endl; // throw exception here
for(int j=i+1; j< um.size1(); ++j){
double in = inner_prod(subrange(ublasMatrixRow(um,i),0,i),subrange(ublasMatrixRow(um,j),0,i));
um(j,i) = (um(j,i) - in)/um(i,i);
}
}
for(int i=1; i< um.size1(); ++i) {
ublasMatrixRange(um,range(0,i),range(i,i+1))=zero_matrix(i,1);
}
}
void testCholeski()
{
ublasMatrix um1(3,3);
um1(0,0)=4;um1(0,1)=-2;um1(0,2)=1;
um1(1,0)=-2;um1(1,1)=4;um1(1,2)=-2;
um1(2,0)=1;um1(2,1)=-2;um1(2,2)=4;
std::cout << um1 << std::endl;
CholeskiDecomposition(um1);
std::cout << um1 << std::endl;
ublasMatrix umt=trans(um1);
std::cout << umt << std::endl;
std::cout << prod(um1,umt) << std::endl;
}
No comments:
Post a Comment
would you like it. :)