38 #ifndef GMM_SOLVER_CCG_H__
39 #define GMM_SOLVER_CCG_H__
46 template <
typename CMatrix,
typename CINVMatrix,
typename Matps,
48 void pseudo_inverse(
const CMatrix &C, CINVMatrix &CINV,
49 const Matps& , VectorX&) {
56 typedef VectorX TmpVec;
57 typedef typename linalg_traits<VectorX>::value_type value_type;
59 size_type nr = mat_nrows(C), nc = mat_ncols(C);
61 TmpVec d(nr), e(nr), l(nc), p(nr), q(nr), r(nr);
62 value_type rho, rho_1,
alpha;
67 d[i] = 1.0; rho = 1.0;
72 while (rho >= 1E-38) {
74 mult(gmm::transposed(C), p, l);
77 add(scaled(p, alpha), e);
78 add(scaled(q, -alpha), r);
81 add(r, scaled(p, rho / rho_1), p);
84 mult(transposed(C), e, l);
87 copy(l, mat_row(CINV, i));
94 template <
typename Matrix,
typename CMatrix,
typename Matps,
95 typename VectorX,
typename VectorB,
typename VectorF,
96 typename Preconditioner >
98 const VectorB& b,
const VectorF& f,
const Matps& PS,
99 const Preconditioner& M,
iteration &iter) {
100 typedef typename temporary_dense_vector<VectorX>::vector_type TmpVec;
101 typedef typename temporary_vector<CMatrix>::vector_type TmpCVec;
102 typedef row_matrix<TmpCVec> TmpCmat;
104 typedef typename linalg_traits<VectorX>::value_type value_type;
105 value_type rho = 1.0, rho_1, lambda, gamma;
106 TmpVec p(vect_size(x)), q(vect_size(x)), q2(vect_size(x)),
107 r(vect_size(x)), old_z(vect_size(x)), z(vect_size(x)),
109 std::vector<bool> satured(mat_nrows(C));
111 iter.set_rhsnorm(sqrt(
vect_sp(PS, b, b)));
112 if (iter.get_rhsnorm() == 0.0) iter.set_rhsnorm(1.0);
114 TmpCmat CINV(mat_nrows(C), mat_ncols(C));
115 pseudo_inverse(C, CINV, PS, x);
121 mult(A, scaled(x, -1.0), b, r);
123 bool transition =
false;
124 for (size_type i = 0; i < mat_nrows(C); ++i) {
125 value_type al =
vect_sp(mat_row(C, i), x) - f[i];
126 if (al >= -1.0E-15) {
127 if (!satured[i]) { satured[i] =
true; transition =
true; }
128 value_type bb =
vect_sp(mat_row(CINV, i), z);
129 if (bb > 0.0)
add(scaled(mat_row(C, i), -bb), z);
136 rho_1 = rho; rho =
vect_sp(PS, r, z);
138 if (iter.finished(rho))
break;
140 if (iter.get_noisy() > 0 && transition) std::cout <<
"transition\n";
141 if (transition || iter.first()) gamma = 0.0;
142 else gamma = std::max(0.0, (rho -
vect_sp(PS, old_z, z) ) / rho_1);
145 add(z, scaled(p, gamma), p);
150 lambda = rho /
vect_sp(PS, q, p);
151 for (size_type i = 0; i < mat_nrows(C); ++i)
153 value_type bb =
vect_sp(mat_row(C, i), p) - f[i];
155 lambda = std::min(lambda, (f[i]-
vect_sp(mat_row(C, i), x)) / bb);
157 add(x, scaled(p, lambda), x);
158 add(memox, scaled(x, -1.0), memox);
165 #endif // GMM_SOLVER_CCG_H__