00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef SELDON_FILE_SPARSE_CHOLESKY_FACTORIZATION_CXX
00021
00022 namespace Seldon
00023 {
00024
00026
00031 template<class T, class Prop, class Allocator>
00032 void GetCholesky(Matrix<T, Prop, ArrayRowSymSparse, Allocator>& A)
00033 {
00034 int n = A.GetN();
00035 T t, s, fact;
00036 int j_col, jrow, index_lu, jpos;
00037 Vector<T> Row_Val(n);
00038 IVect Index(n), Row_Ind(n);
00039 Row_Val.Fill(0);
00040 Row_Ind.Fill(-1);
00041
00042 Index.Fill(-1);
00043
00044
00045 Matrix<T, General, ArrayRowSparse, Allocator> B;
00046 Copy(A, B);
00047
00048
00049 A.Clear();
00050 A.Reallocate(n, n);
00051
00052
00053 for (int i_row = 0; i_row < n; i_row++)
00054 {
00055 int size_row = B.GetRowSize(i_row);
00056
00057
00058 int length_lower = 0, length_upper = 1;
00059 Row_Ind(i_row) = i_row;
00060 Row_Val(i_row) = 0.0;
00061 Index(i_row) = i_row;
00062
00063 for (int j = 0; j < size_row; j++)
00064 {
00065 int k = B.Index(i_row, j);
00066 t = B.Value(i_row, j);
00067 if (k < i_row)
00068 {
00069 Row_Ind(length_lower) = k;
00070 Row_Val(length_lower) = t;
00071 Index(k) = length_lower;
00072 length_lower++;
00073 }
00074 else if (k == i_row)
00075 Row_Val(i_row) = t;
00076 else
00077 {
00078 jpos = i_row + length_upper;
00079 Row_Ind(jpos) = k;
00080 Row_Val(jpos) = t;
00081 Index(k) = jpos;
00082 length_upper++;
00083 }
00084 }
00085
00086 B.ClearRow(i_row);
00087
00088 j_col = 0;
00089 int length = 0;
00090
00091
00092 while (j_col < length_lower)
00093 {
00094 jrow = Row_Ind(j_col);
00095
00096
00097 int k = j_col;
00098 for (int j = (j_col+1) ; j < length_lower; j++)
00099 {
00100 if (Row_Ind(j) < jrow)
00101 {
00102 jrow = Row_Ind(j);
00103 k = j;
00104 }
00105 }
00106
00107
00108 if (k != j_col)
00109 {
00110
00111 int j = Row_Ind(j_col);
00112 Row_Ind(j_col) = Row_Ind(k);
00113 Row_Ind(k) = j;
00114
00115 Index(jrow) = j_col;
00116 Index(j) = k;
00117
00118 s = Row_Val(j_col);
00119 Row_Val(j_col) = Row_Val(k);
00120 Row_Val(k) = s;
00121 }
00122
00123
00124 Index(jrow) = -1;
00125 fact = Row_Val(j_col) * A.Value(jrow, 0);
00126
00127
00128 for (int k = 1; k < A.GetRowSize(jrow); k++)
00129 {
00130 s = fact * A.Value(jrow, k);
00131 int j = A.Index(jrow, k);
00132
00133 jpos = Index(j);
00134 if (j >= i_row)
00135 {
00136
00137 if (jpos == -1)
00138 {
00139
00140 int i = i_row + length_upper;
00141 Row_Ind(i) = j;
00142 Index(j) = i;
00143 Row_Val(i) = -s;
00144 length_upper++;
00145 }
00146 else
00147 {
00148
00149 Row_Val(jpos) -= s;
00150 }
00151 }
00152 else
00153 {
00154
00155 if (jpos == -1)
00156 {
00157
00158 Row_Ind(length_lower) = j;
00159 Index(j) = length_lower;
00160 Row_Val(length_lower) = -s;
00161 length_lower++;
00162 }
00163 else
00164 {
00165
00166 Row_Val(jpos) -= s;
00167 }
00168 }
00169 }
00170
00171
00172
00173
00174 Row_Val(length) = fact;
00175 Row_Ind(length) = jrow;
00176 ++length;
00177 j_col++;
00178 }
00179
00180 for (int k = 0; k < length_upper; k++)
00181 Index(Row_Ind(i_row + k)) = -1;
00182
00183
00184 size_row = length_upper;
00185 A.ReallocateRow(i_row, length_upper);
00186
00187
00188 if (Row_Val(i_row) < 0)
00189 {
00190 cout << "Error during Cholesky factorization " << endl;
00191 cout << "Matrix must be definite positive " << endl;
00192 cout << "but diagonal element of row " << i_row
00193 << "is equal to " << Row_Val(i_row) << endl;
00194
00195 #ifdef SELDON_WITH_ABORT
00196 abort();
00197 #endif
00198 }
00199
00200 A.Value(i_row, 0) = 1.0 / Row_Val(i_row);
00201 A.Index(i_row, 0) = i_row;
00202 index_lu = 1;
00203
00204
00205 for (int k = i_row + 1; k < i_row + length_upper; k++)
00206 {
00207 A.Index(i_row, index_lu) = Row_Ind(k);
00208 A.Value(i_row, index_lu) = Row_Val(k);
00209 index_lu++;
00210 }
00211 }
00212
00213
00214 for (int i = 0; i < n; i++)
00215 {
00216 A.Value(i, 0) = sqrt(A.Value(i,0));
00217
00218 for (int k = 1; k < A.GetRowSize(i); k++)
00219 A.Value(i, k) *= A.Value(i, 0);
00220 }
00221 }
00222
00223
00224
00225 template<class classTrans,
00226 class T0, class T1, class Prop, class Storage,
00227 class Allocator1, class Allocator2>
00228 void SolveCholesky(const classTrans& TransA,
00229 const Matrix<T0, Prop, ArrayRowSymSparse, Allocator1>& A,
00230 Vector<T1, Storage, Allocator2>& x)
00231 {
00232 int n = A.GetM();
00233 if (n <= 0)
00234 return;
00235
00236 if (TransA.Trans())
00237 {
00238
00239 int j;
00240 for (int i = n - 1; i >= 0; i--)
00241 {
00242 T1 val = x(i);
00243 for (int k = 1; k < A.GetRowSize(i) ; k++)
00244 {
00245 j = A.Index(i, k);
00246 val -= A.Value(i, k) * x(j);
00247 }
00248
00249 x(i) = val * A.Value(i, 0);
00250 }
00251 }
00252 else
00253 {
00254
00255 int j;
00256 for (int i = 0; i < n; i++)
00257 {
00258 x(i) *= A.Value(i, 0);
00259 for (int k = 1; k < A.GetRowSize(i) ; k++)
00260 {
00261 j = A.Index(i, k);
00262 x(j) -= A.Value(i, k) * x(i);
00263 }
00264 }
00265 }
00266 }
00267
00268
00269
00270 template<class classTrans,
00271 class T0, class T1, class Prop, class Storage,
00272 class Allocator1, class Allocator2>
00273 void MltCholesky(const classTrans& TransA,
00274 const Matrix<T0, Prop, ArrayRowSymSparse, Allocator1>& A,
00275 Vector<T1, Storage, Allocator2>& x)
00276 {
00277 int n = A.GetM();
00278 if (n <= 0)
00279 return;
00280
00281 if (TransA.Trans())
00282 {
00283
00284 int j;
00285 for (int i = 0; i < n; i++)
00286 {
00287 T1 val = x(i) / A.Value(i, 0);
00288 for (int k = 1; k < A.GetRowSize(i) ; k++)
00289 {
00290 j = A.Index(i, k);
00291 val += A.Value(i, k)*x(j);
00292 }
00293
00294 x(i) = val;
00295 }
00296 }
00297 else
00298 {
00299
00300 int j;
00301 for (int i = n - 1; i >= 0; i--)
00302 {
00303 for (int k = 1; k < A.GetRowSize(i) ; k++)
00304 {
00305 j = A.Index(i, k);
00306 x(j) += A.Value(i, k)*x(i);
00307 }
00308
00309 x(i) /= A.Value(i, 0);
00310 }
00311 }
00312 }
00313
00314 }
00315
00316 #define SELDON_FILE_SPARSE_CHOLESKY_FACTORIZATION_CXX
00317 #endif