00001 #include "GLinear_Homo_Eq.h"
00002 #include <iostream>
00003 #include <sstream>
00004 #include <cmath>
00005 #include "../io_src/GError_Output.h"
00006
00007 using namespace GMathLib;
00008 using namespace GMathLib::IO;
00009 using namespace GMathLib::GMatrix_Util;
00010
00011 GLinear_Homo_Eq::GLinear_Homo_Eq()
00012 : GObject(), p_lu(0)
00013 {
00014 Class_Name("GLinear_Homo_Eq");
00015 }
00016
00017 GLinear_Homo_Eq::~GLinear_Homo_Eq()
00018 {
00019 if(p_lu != 0){
00020 delete p_lu;
00021 }
00022 }
00023
00024
00025
00026
00027 void GLinear_Homo_Eq::S_Gauss_Partial_Pivot(const GMatrix& matrix, const GVector& vec, GVector& answer_vec){
00028 GMatrix matrix_copy = matrix;
00029 GVector vec_copy = vec;
00030
00031 S_Gauss_Partial_Pivot(matrix_copy, vec_copy, answer_vec);
00032 }
00033
00034 void GLinear_Homo_Eq::S_Gauss_Partial_Pivot(GMatrix& A, GVector& b, GVector& x)
00035 {
00036
00037 if( !check_matrix_size(A, b, x) ){
00038 std::string errorinfo = "Matrix or vector size is invalid !";
00039 GError_Output::Puts(Class_Name() + "::S_Gauss_Partial_Pivot", errorinfo);
00040
00041 return;
00042 }
00043
00044 const double TINY = 1.0e-10;
00045 int n = b.Size();
00046 int status = 0;
00047 int pk, max_p, pj;
00048 int *p = new int[n];
00049 double max, aik;
00050 double pivot, multi, sum;
00051
00052
00053 for(int k = 0; k < n; k++)
00054 p[k] = k;
00055
00056 for(int k = 0; k < n - 1; k++){
00057
00058
00059 pk = p[k]; max = 0.0; max_p = k;
00060 for(int i = k; i < n; i++){
00061 aik = A(p[i], k);
00062
00063 if(std::abs(aik) > max){
00064 max = std::abs(aik);
00065 max_p = i;
00066 }
00067 }
00068
00069
00070 if(max <= TINY){
00071 status = 8; break;
00072 }
00073
00074
00075 if(max_p != k){
00076 p[k] = p[max_p]; p[max_p] = pk; pk = p[k];
00077 }
00078
00079
00080 pivot = 1.0 / A(pk, k);
00081 for(int j = k +1; j < n; j++){
00082 pj = p[j];
00083 multi = A(pj, k) * pivot;
00084
00085 if(std::abs(multi) > TINY){
00086 for(int i = k + 1; i < n; i++)
00087 A(pj, i) = A(pj, i) - multi * A(pk, i);
00088
00089 b(pj) = b(pj) - multi * b(pk);
00090 }else{
00091 A(pj, k) = 0.0;
00092 }
00093 }
00094 }
00095
00096
00097
00098
00099 if(std::abs( A(p[n-1], n -1) ) < TINY)
00100 status = 9;
00101
00102
00103 if(status != 0){
00104 std::ostringstream oss;
00105 oss << status;
00106 std::string errorinfo = "GAUSS, Failed! The system is singular! STATUS : " + oss.str();
00107 GError_Output::Puts(Class_Name() + "::S_Gauss_Partial_Pivot", errorinfo);
00108 }else{
00109
00110
00111 x(n-1) = b(p[n-1]) / A(p[n-1], n-1);
00112 for(int k = n - 2; k >= 0; k--){
00113 pk=p[k]; sum = b(pk);
00114 for(int i = k + 1; i < n; i++)
00115 sum = sum - A(pk, i) * x(i);
00116
00117 x(k) = sum / A(pk, k);
00118 }
00119 }
00120
00121 delete p;
00122 }
00123
00124
00125
00126
00127
00128 void GLinear_Homo_Eq::S_LU_Partial_Pivot(GMatrix& matrix, GVector& vec, GVector& answer_vec, bool do_lu_cmp_flag)
00129 {
00130
00131 if( !check_matrix_size(matrix, vec, answer_vec) ){
00132 std::string errorinfo = "Matrix or vector size is invalid !";
00133 GError_Output::Puts(Class_Name() + "::S_LU_Partial_Pivot", errorinfo);
00134
00135 return;
00136 }
00137
00138 GMatrix* p_Alu = 0;
00139 GMatrix* p_P = 0;
00140 int n = matrix.Row();
00141
00142
00143 if(p_lu == 0){
00144 p_lu = new GLU_Composition();
00145 }
00146
00147
00148 if(do_lu_cmp_flag){
00149 p_lu->LU_Composition(matrix, GLU_Composition::LU_COMBINED);
00150 }else{
00151 if( p_lu->Get_LU() == 0){
00152 std::string errorinfo = "Specify do_lu_cmp_flag=true !";
00153 GError_Output::Puts(Class_Name() + "::S_LU_Partial_Pivot", errorinfo);
00154
00155 return;
00156 }
00157 }
00158
00159
00160 p_Alu = p_lu->Get_LU();
00161 p_P = p_lu->Get_P();
00162
00163
00164
00165 GVector b(n);
00166 b.Multi(*p_P, vec);
00167
00168
00169
00170
00171 double sum;
00172
00173
00174 answer_vec(0) = b(0);
00175
00176 for(int i=1; i < n; i++){
00177 sum = 0.0;
00178 for(int j=0; j <= i-1; j++){
00179 sum += (*p_Alu)(i, j) * answer_vec(j);
00180 }
00181
00182 answer_vec(i) = b(i) - sum;
00183 }
00184
00185
00186 answer_vec(n-1) = answer_vec(n-1) / (*p_Alu)(n-1, n-1);
00187
00188 for(int i=n-2; i >= 0; i--){
00189 sum = 0.0;
00190 for(int j=i+1; j < n; j++){
00191 sum += (*p_Alu)(i, j) * answer_vec(j);
00192 }
00193
00194 answer_vec(i) = ( answer_vec(i) - sum ) / (*p_Alu)(i, i);
00195 }
00196 }
00197
00198 bool GLinear_Homo_Eq::check_matrix_size(GMatrix& matrix, GVector& vec, GVector& answer_vec)
00199 {
00200 if(matrix.Column() != matrix.Row()){
00201 return false;
00202 }else if( matrix.Row() != vec.Row()){
00203 return false;
00204 }else if( matrix.Row() != answer_vec.Row()){
00205 return false;
00206 }else if( vec.Shape() != GVector::COLUMN_VECTOR
00207 || answer_vec.Shape() != GVector::COLUMN_VECTOR ){
00208 return false;
00209 }else{
00210 return true;
00211 }
00212 }