头文件:
/* * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected] * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 2 or any later version. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. A copy of the GNU General Public License is available at: * http://www.fsf.org/licensing/licenses */ /***************************************************************************** * linequs1.h * * Function template for solving deterministic linear equations. * * For a n-by-n coefficient matrix A and n-by-1 constant vector b, Gauss * elimination method can solve the equations Ax=b. But the decomposition * methods are more commonly used. if A is not SPD, the LU decomposition * can be use to solve the equations; if A is SPD, the Cholesky decomposition * is the better choice; if A is a tridiagonal matrix, then the Forward * Elimination and Backward Substitution maybe the best choice. * * These functions can be used by both REAL or COMPLEX linear equations. * * Zhang Ming, 2010-07 (revised 2010-12), Xi'an Jiaotong University. *****************************************************************************/ #ifndef DETLINEQUS_H #define DETLINEQUS_H #include <vector.h> #include <matrix.h> #include <cholesky.h> #include <lud.h> namespace splab { template<typename Type> Vector<Type> gaussSolver( const Matrix<Type>&, const Vector<Type>& ); template<typename Type> void gaussSolver( Matrix<Type>&, Matrix<Type>& ); template<typename Type> Vector<Type> luSolver( const Matrix<Type>&, const Vector<Type>& ); template<typename Type> Matrix<Type> luSolver( const Matrix<Type>&, const Matrix<Type>& ); template<typename Type> Vector<Type> choleskySolver( const Matrix<Type>&, const Vector<Type>& ); template<typename Type> Matrix<Type> choleskySolver( const Matrix<Type>&, const Matrix<Type>& ); template<typename Type> Vector<Type> utSolver( const Matrix<Type>&, const Vector<Type>& ); template<typename Type> Vector<Type> ltSolver( const Matrix<Type>&, const Vector<Type>& ); template<typename Type> Vector<Type> febsSolver( const Vector<Type>&, const Vector<Type>&, const Vector<Type>&, const Vector<Type>& ); #include <linequs1-impl.h> } // namespace splab #endif // DETLINEQUS_H
实现文件:
/* * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected] * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 2 or any later version. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. A copy of the GNU General Public License is available at: * http://www.fsf.org/licensing/licenses */ /***************************************************************************** * linequs1-impl.h * * Implementation for deterministic linear equations. * * Zhang Ming, 2010-07 (revised 2010-12), Xi'an Jiaotong University. *****************************************************************************/ /** * Linear equations solution by Gauss-Jordan elimination, Ax=B. * A ---> The n-by-n coefficient matrix(Full Rank); * b ---> The n-by-1 right-hand side vector; * x ---> The n-by-1 solution vector. */ template <typename Type> Vector<Type> gaussSolver( const Matrix<Type> &A, const Vector<Type> &b ) { assert( A.rows() == b.size() ); int rows = b.size(); Vector<Type> x( rows ); Matrix<Type> C(A); Matrix<Type> B( rows, 1 ); for( int i=0; i<rows; ++i ) B[i][0] = b[i]; gaussSolver( C, B ); for( int i=0; i<rows; ++i ) x[i] = B[i][0]; return x; } /** * Linear equations solution by Gauss-Jordan elimination, AX=B. * A ---> The n-by-n coefficient matrix(Full Rank); * B ---> The n-by-m right-hand side vectors; * When solving is completion, A is replaced by its inverse and * B is replaced by the corresponding set of solution vectors. * Adapted from Numerical Recipes. */ template <typename Type> void gaussSolver( Matrix<Type> &A, Matrix<Type> &B ) { assert( A.rows() == B.rows() ); int i, j, k, l, ll, icol, irow, n=A.rows(), m=B.cols(); Type big, dum, pivinv; Vector<int> indxc(n), indxr(n), ipiv(n); for( j=0; j<n; j++ ) ipiv[j]=0; for( i=0; i<n; ++i ) { big = 0.0; for( j=0; j<n; ++j ) if( ipiv[j] != 1 ) for( k=0; k<n; ++k ) if( ipiv[k] == 0 ) if( abs(A[j][k]) >= abs(big) ) { big = abs(A[j][k]); irow = j; icol = k; } ++(ipiv[icol]); if( irow != icol ) { for( l=0; l<n; ++l ) swap( A[irow][l], A[icol][l] ); for( l=0; l<m; ++l ) swap( B[irow][l], B[icol][l] ); } indxr[i] = irow; indxc[i] = icol; if( abs(A[icol][icol]) == 0.0 ) { cerr << "Singular Matrix!" << endl; return; } pivinv = Type(1) / A[icol][icol]; A[icol][icol] = Type(1); for( l=0; l<n; ++l ) A[icol][l] *= pivinv; for( l=0; l<m; ++l ) B[icol][l] *= pivinv; for( ll=0; ll<n; ++ll ) if( ll != icol ) { dum = A[ll][icol]; A[ll][icol] = 0; for( l=0; l<n; ++l ) A[ll][l] -= A[icol][l]*dum; for( l=0; l<m; ++l ) B[ll][l] -= B[icol][l]*dum; } } for( l=n-1; l>=0; --l ) if( indxr[l] != indxc[l] ) for( k=0; k<n; k++ ) swap( A[k][indxr[l]], A[k][indxc[l]] ); } /** * Linear equations solution by LU decomposition, Ax=b. * A ---> The n-by-n coefficient matrix(Full Rank); * b ---> The n-by-1 right-hand side vector; * x ---> The n-by-1 solution vector. */ template <typename Type> Vector<Type> luSolver( const Matrix<Type> &A, const Vector<Type> &b ) { assert( A.rows() == b.size() ); LUD<Type> lu; lu.dec( A ); return lu.solve( b ); } /** * Linear equations solution by LU decomposition, AX=B. * A ---> The n-by-n coefficient matrix(Full Rank); * B ---> The n-by-m right-hand side vector; * X ---> The n-by-m solution vectors. */ template <typename Type> Matrix<Type> luSolver( const Matrix<Type> &A, const Matrix<Type> &B ) { assert( A.rows() == B.rows() ); LUD<Type> lu; lu.dec( A ); return lu.solve( B ); } /** * Linear equations solution by Cholesky decomposition, Ax=b. * A ---> The n-by-n coefficient matrix(Full Rank); * b ---> The n-by-1 right-hand side vector; * x ---> The n-by-1 solution vector. */ template <typename Type> Vector<Type> choleskySolver( const Matrix<Type> &A, const Vector<Type> &b ) { assert( A.rows() == b.size() ); Cholesky<Type> cho; cho.dec(A); if( cho.isSpd() ) return cho.solve( b ); else { cerr << "Factorization was not complete!" << endl; return Vector<Type>(0); } } /** * Linear equations solution by Cholesky decomposition, AX=B. * A ---> The n-by-n coefficient matrix(Full Rank); * B ---> The n-by-m right-hand side vector; * X ---> The n-by-m solution vectors. */ template <typename Type> Matrix<Type> choleskySolver( const Matrix<Type> &A, const Matrix<Type> &B ) { assert( A.rows() == B.rows() ); Cholesky<Type> cho; cho.dec(A); if( cho.isSpd() ) return cho.solve( B ); else { cerr << "Factorization was not complete!" << endl; return Matrix<Type>(0,0); } } /** * Solve the upper triangular system U*x = b. * U ---> The n-by-n upper triangular matrix(Full Rank); * b ---> The n-by-1 right-hand side vector; * x ---> The n-by-1 solution vector. */ template <typename Type> Vector<Type> utSolver( const Matrix<Type> &U, const Vector<Type> &b ) { int n = b.dim(); assert( U.rows() == n ); assert( U.rows() == U.cols() ); Vector<Type> x(b); for( int k=n; k >= 1; --k ) { x(k) /= U(k,k); for( int i=1; i<k; ++i ) x(i) -= x(k) * U(i,k); } return x; } /** * Solve the lower triangular system L*x = b. * L ---> The n-by-n lower triangular matrix(Full Rank); * b ---> The n-by-1 right-hand side vector; * x ---> The n-by-1 solution vector. */ template <typename Type> Vector<Type> ltSolver( const Matrix<Type> &L, const Vector<Type> &b ) { int n = b.dim(); assert( L.rows() == n ); assert( L.rows() == L.cols() ); Vector<Type> x(b); for( int k=1; k <= n; ++k ) { x(k) /= L(k,k); for( int i=k+1; i<= n; ++i ) x(i) -= x(k) * L(i,k); } return x; } /** * Tridiagonal equations solution by Forward Elimination and Backward Substitution. * a ---> The n-1-by-1 main(0th) diagonal vector; * b ---> The n-by-1 -1th(above main) diagonal vector; * c ---> The n-1-by-1 +1th(below main) diagonal vector; * d ---> The right-hand side vector; * x ---> The n-by-1 solution vector. */ template <typename Type> Vector<Type> febsSolver( const Vector<Type> &a, const Vector<Type> &b, const Vector<Type> &c, const Vector<Type> &d ) { int n = b.size(); assert( a.size() == n-1 ); assert( c.size() == n-1 ); assert( d.size() == n ); Type mu = 0; Vector<Type> x(d), bb(b); for( int i=0; i<n-1; ++i ) { mu = a[i] / bb[i]; bb[i+1] = bb[i+1] - mu*c[i]; x[i+1] = x[i+1] - mu*x[i]; } x[n-1] = x[n-1] / bb[n-1]; for( int i=n-2; i>=0; --i ) x[i] = ( x[i]-c[i]*x[i+1] ) / bb[i]; // for( int j=1; j<n; ++j ) // { // mu = a(j) / bb(j); // bb(j+1) = bb(j+1) - mu*c(j); // x(j+1) = x(j+1) - mu*x(j); // } // // x(n) = x(n) / bb(n); // for( int j=n-1; j>0; --j ) // x(j) = ( x(j)-c(j)*x(j+1) ) / bb(j); return x; }
测试代码:
/***************************************************************************** * linequs1_test.cpp * * Deterministic Linear Equations testing. * * Zhang Ming, 2010-07 (revised 2010-12), Xi'an Jiaotong University. *****************************************************************************/ #define BOUNDS_CHECK #include <iostream> #include <iomanip> #include <linequs1.h> using namespace std; using namespace splab; typedef float Type; const int M = 3; const int N = 3; int main() { Matrix<Type> A(M,N), B; Vector<Type> b(N); // ordinary linear equations A[0][0] = 1; A[0][1] = 2; A[0][2] = 1; A[1][0] = 2; A[1][1] = 5; A[1][2] = 4; A[2][0] = 1; A[2][1] = 1; A[2][2] = 0; B = eye( N, Type(1.0) ); b[0] = 1; b[1] = 0; b[2] = 1; Matrix<Type> invA( A ); Matrix<Type> X( B ); cout << setiosflags(ios::fixed) << setprecision(4) << endl; cout << "The original matrix A is : " << A << endl; gaussSolver( invA, X ); cout << "The inverse of A is (Gauss Solver) : " << invA << endl; cout << "The inverse matrix of A is (LUD Solver) : " << luSolver( A, B ) << endl; cout << "The constant vector b : " << b << endl; cout << "The solution of A * x = b is (Gauss Solver) : " << gaussSolver( A, b ) << endl; cout << "The solution of A * x = b is (LUD Solver) : " << luSolver( A, b ) << endl << endl; Matrix<complex<Type> > cA = complexMatrix( A, B ); Vector<complex<Type> > cb = complexVector( b, b ); cout << "The original complex matrix cA is : " << cA << endl; cout << "The constant complex vector cb : " << cb << endl; cout << "The solution of cA * cx = cb is (Gauss Solver) : " << gaussSolver( cA, cb ) << endl; cout << "The solution of cA * cx = cb is (LUD Solver) : " << luSolver( cA, cb ) << endl; cout << "The cA*cx - cb is : "<< cA*luSolver(cA,cb) - cb << endl << endl; // linear equations with symmetric coefficient matrix for( int i=1; i<N+1; ++i ) { for( int j=1; j<N+1; ++j ) if( i == j ) A(i,i) = Type(i); else if( i < j ) A(i,j) = Type(i); else A(i,j) = Type(j); b(i) = Type( i*(i+1)/2.0 + i*(N-i) ); } cout << "The original matrix A : " << A << endl; cout << "The inverse matrix of A is (Cholesky Solver) : " << choleskySolver( A, B ) << endl; cout << "The constant vector b : " << b << endl; cout << "The solution of Ax = b is (Cholesky Solver) : " << choleskySolver( A, b ) << endl << endl; cA = complexMatrix( A ); cb = complexVector( b, b ); cout << "The original complex matrix A : " << cA << endl; cout << "The constant complex vector b : " << cb << endl; cout << "The solution of Ax = b is (Cholesky Solver) : " << choleskySolver( cA, cb ) << endl << endl; // upper and lower triangular system for( int i=0; i<N; ++i ) for( int j=i; j<N; ++j ) B[i][j] = A[i][j]; cout << "The original matrix B : " << B << endl; cout << "The constant vector b : " << b << endl; cout << "The solution of Ax = b is (Upper Triangular Solver) : " << utSolver( B, b ) << endl << endl; cA = complexMatrix( trT(B), -trT(B) ); cout << "The original complex matrix A : " << cA << endl; cout << "The constant complex vector b : " << cb << endl; cout << "The solution of Ax = b is (Lower Triangular Solver) : " << ltSolver( cA, cb ) << endl << endl; // Tridiagonal linear equations Vector<Type> aa( 3, -1 ), bb( 4, 4 ), cc( 3, -2 ), dd( 4 ); dd(1) = 3; dd(2) = 2; dd(3) = 2; dd(4) = 3; cout << "The elements below main diagonal is : " << aa << endl; cout << "The elements on main diagonal is : " << bb << endl; cout << "The elements above main diagonal is : " << cc << endl; cout << "The elements constant vector is : " << dd << endl; cout << "Teh solution is (Forward Elimination and Backward Substitution) : " << febsSolver( aa, bb, cc, dd ) << endl; Vector<complex<Type> > caa = complexVector(aa); Vector<complex<Type> > cbb = complexVector(bb); Vector<complex<Type> > ccc = complexVector(cc); Vector<complex<Type> > cdd = complexVector(Vector<Type>(dd.dim()),dd); cout << "The elements below main diagonal is : " << caa << endl; cout << "The elements on main diagonal is : " << cbb << endl; cout << "The elements above main diagonal is : " << ccc << endl; cout << "The elements constant vector is : " << cdd << endl; cout << "Teh solution is (Forward Elimination and Backward Substitution) : " << febsSolver( caa, cbb, ccc, cdd ) << endl; return 0; }
运行结果:
The original matrix A is : size: 3 by 3 1.0000 2.0000 1.0000 2.0000 5.0000 4.0000 1.0000 1.0000 0.0000 The inverse of A is (Gauss Solver) : size: 3 by 3 -4.0000 1.0000 3.0000 4.0000 -1.0000 -2.0000 -3.0000 1.0000 1.0000 The inverse matrix of A is (LUD Solver) : size: 3 by 3 -4.0000 1.0000 3.0000 4.0000 -1.0000 -2.0000 -3.0000 1.0000 1.0000 The constant vector b : size: 3 by 1 1.0000 0.0000 1.0000 The solution of A * x = b is (Gauss Solver) : size: 3 by 1 -1.0000 2.0000 -2.0000 The solution of A * x = b is (LUD Solver) : size: 3 by 1 -1.0000 2.0000 -2.0000 The original complex matrix cA is : size: 3 by 3 (1.0000,1.0000) (2.0000,0.0000) (1.0000,0.0000) (2.0000,0.0000) (5.0000,1.0000) (4.0000,0.0000) (1.0000,0.0000) (1.0000,0.0000) (0.0000,1.0000) The constant complex vector cb : size: 3 by 1 (1.0000,1.0000) (0.0000,0.0000) (1.0000,1.0000) The solution of cA * cx = cb is (Gauss Solver) : size: 3 by 1 (0.4000,-0.8000) (-0.4000,1.2000) (0.6000,-1.0000) The solution of cA * cx = cb is (LUD Solver) : size: 3 by 1 (0.4000,-0.8000) (-0.4000,1.2000) (0.6000,-1.0000) The cA*cx - cb is : size: 3 by 1 (-0.0000,0.0000) (0.0000,0.0000) (-0.0000,-0.0000) The original matrix A : size: 3 by 3 1.0000 1.0000 1.0000 1.0000 2.0000 2.0000 1.0000 2.0000 3.0000 The inverse matrix of A is (Cholesky Solver) : size: 3 by 3 2.0000 -1.0000 0.0000 -1.0000 2.0000 -1.0000 0.0000 -1.0000 1.0000 The constant vector b : size: 3 by 1 3.0000 5.0000 6.0000 The solution of Ax = b is (Cholesky Solver) : size: 3 by 1 1.0000 1.0000 1.0000 The original complex matrix A : size: 3 by 3 (1.0000,0.0000) (1.0000,0.0000) (1.0000,0.0000) (1.0000,0.0000) (2.0000,0.0000) (2.0000,0.0000) (1.0000,0.0000) (2.0000,0.0000) (3.0000,0.0000) The constant complex vector b : size: 3 by 1 (3.0000,3.0000) (5.0000,5.0000) (6.0000,6.0000) The solution of Ax = b is (Cholesky Solver) : size: 3 by 1 (1.0000,1.0000) (1.0000,1.0000) (1.0000,1.0000) The original matrix B : size: 3 by 3 1.0000 1.0000 1.0000 0.0000 2.0000 2.0000 0.0000 0.0000 3.0000 The constant vector b : size: 3 by 1 3.0000 5.0000 6.0000 The solution of Ax = b is (Upper Triangular Solver) : size: 3 by 1 0.5000 0.5000 2.0000 The original complex matrix A : size: 3 by 3 (1.0000,-1.0000) (0.0000,-0.0000) (0.0000,-0.0000) (1.0000,-1.0000) (2.0000,-2.0000) (0.0000,-0.0000) (1.0000,-1.0000) (2.0000,-2.0000) (3.0000,-3.0000) The constant complex vector b : size: 3 by 1 (3.0000,3.0000) (5.0000,5.0000) (6.0000,6.0000) The solution of Ax = b is (Lower Triangular Solver) : size: 3 by 1 (0.0000,3.0000) (0.0000,1.0000) (0.0000,0.3333) The elements below main diagonal is : size: 3 by 1 -1.0000 -1.0000 -1.0000 The elements on main diagonal is : size: 4 by 1 4.0000 4.0000 4.0000 4.0000 The elements above main diagonal is : size: 3 by 1 -2.0000 -2.0000 -2.0000 The elements constant vector is : size: 4 by 1 3.0000 2.0000 2.0000 3.0000 Teh solution is (Forward Elimination and Backward Substitution) : size: 4 by 1 1.5610 1.6220 1.4634 1.1159 The elements below main diagonal is : size: 3 by 1 (-1.0000,0.0000) (-1.0000,0.0000) (-1.0000,0.0000) The elements on main diagonal is : size: 4 by 1 (4.0000,0.0000) (4.0000,0.0000) (4.0000,0.0000) (4.0000,0.0000) The elements above main diagonal is : size: 3 by 1 (-2.0000,0.0000) (-2.0000,0.0000) (-2.0000,0.0000) The elements constant vector is : size: 4 by 1 (0.0000,3.0000) (0.0000,2.0000) (0.0000,2.0000) (0.0000,3.0000) Teh solution is (Forward Elimination and Backward Substitution) : size: 4 by 1 (0.0000,1.5610) (0.0000,1.6220) (0.0000,1.4634) (0.0000,1.1159) Process returned 0 (0x0) execution time : 0.187 s Press any key to continue.