38 #ifndef GMM_RANGE_BASIS_H
39 #define GMM_RANGE_BASIS_H
52 template <
typename T,
typename VECT,
typename MAT1>
53 void tridiag_qr_algorithm
54 (std::vector<
typename number_traits<T>::magnitude_type> diag,
55 std::vector<T> sdiag,
const VECT &eigval_,
const MAT1 &eigvect_,
56 bool compvect, tol_type_for_qr tol = default_tol_for_qr) {
57 VECT &eigval =
const_cast<VECT &
>(eigval_);
58 MAT1 &eigvect =
const_cast<MAT1 &
>(eigvect_);
59 typedef typename number_traits<T>::magnitude_type R;
61 if (compvect) gmm::copy(identity_matrix(), eigvect);
63 size_type n = diag.size(), q = 0, p, ite = 0;
65 if (n == 1) { eigval[0] = gmm::real(diag[0]);
return; }
67 symmetric_qr_stop_criterion(diag, sdiag, p, q, tol);
70 sub_interval SUBI(p, n-p-q), SUBJ(0, mat_ncols(eigvect)), SUBK(p, n-p-q);
71 if (!compvect) SUBK = sub_interval(0,0);
73 symmetric_Wilkinson_qr_step(sub_vector(diag, SUBI),
74 sub_vector(sdiag, SUBI),
75 sub_matrix(eigvect, SUBJ, SUBK), compvect);
77 symmetric_qr_stop_criterion(diag, sdiag, p, q, tol*R(3));
79 GMM_ASSERT1(ite < n*100,
"QR algorithm failed.");
82 gmm::copy(diag, eigval);
86 template <
typename Mat>
87 void range_basis_eff_Lanczos(
const Mat &BB, std::set<size_type> &columns,
89 typedef std::set<size_type> TAB;
90 typedef typename linalg_traits<Mat>::value_type T;
91 typedef typename number_traits<T>::magnitude_type R;
94 col_matrix< rsvector<T> > B(mat_nrows(BB), mat_ncols(BB));
97 for (TAB::iterator it = columns.begin(); it!=columns.end(); ++it, ++k){
98 gmm::copy(scaled(mat_col(BB, *it), T(1)/
vect_norm2(mat_col(BB, *it))),
101 std::vector<T> w(mat_nrows(B));
103 std::vector<T> sdiag(restart);
104 std::vector<R> eigval(restart), diag(restart);
105 dense_matrix<T> eigvect(restart, restart);
110 std::vector<T> v(nc_r), v0(nc_r), wl(nc_r);
111 dense_matrix<T> lv(nc_r, restart);
119 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++k)
120 add(scaled(mat_col(B, *it), v[k]), w);
122 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++k)
123 v[k] =
vect_hp(w, mat_col(B, *it));
135 R beta = R(0),
alpha;
138 if (sdiag.size() != restart) {
139 sdiag.resize(restart); eigval.resize(restart); diag.resize(restart);
gmm::resize(eigvect, restart, restart);
143 for (
size_type i = 0; i < restart; ++i) {
144 gmm::copy(v, mat_col(lv, i));
147 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++k)
148 add(scaled(mat_col(B, *it), v[k]), w);
151 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++k)
152 wl[k] = v[k]*rho -
vect_hp(w, mat_col(B, *it)) - beta*v0[k];
155 gmm::add(gmm::scaled(v, -alpha), wl);
158 if (beta < EPS) { eff_restart = i+1;
break; }
159 gmm::copy(gmm::scaled(wl, T(1) / beta), v);
161 if (eff_restart != restart) {
162 sdiag.resize(eff_restart); eigval.resize(eff_restart); diag.resize(eff_restart);
165 tridiag_qr_algorithm(diag, sdiag, eigval, eigvect,
true);
169 for (
size_type j = 0; j < eff_restart; ++j)
170 { R nvp=gmm::abs(eigval[j]);
if (nvp > rho2) { rho2=nvp; num=j; }}
172 GMM_ASSERT1(num !=
size_type(-1),
"Internal error");
174 gmm::mult(lv, mat_col(eigvect, num), v);
176 if (gmm::abs(rho2-rho_old) < rho_old*R(EPS))
break;
178 if (gmm::abs(rho-rho2) < rho*R(EPS)*R(100))
break;
181 if (gmm::abs(rho-rho2) < rho*R(EPS*10.)) {
184 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++j)
185 if (gmm::abs(v[j]) > val_max)
186 { val_max = gmm::abs(v[j]); j_max = *it; }
187 columns.erase(j_max); nc_r = columns.size();
195 template <
typename Mat>
196 void range_basis_eff_lu(
const Mat &B, std::set<size_type> &columns,
197 std::vector<bool> &c_ortho,
double EPS) {
199 typedef std::set<size_type> TAB;
200 typedef typename linalg_traits<Mat>::value_type T;
201 typedef typename number_traits<T>::magnitude_type R;
203 size_type nc_r = 0, nc_o = 0, nc = mat_ncols(B), nr = mat_nrows(B), i, j;
205 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it)
206 if (!(c_ortho[*it])) ++nc_r;
else nc_o++;
210 gmm::row_matrix< gmm::rsvector<T> > Hr(nc, nc_r), Ho(nc, nc_o);
211 gmm::row_matrix< gmm::rsvector<T> > BBr(nr, nc_r), BBo(nr, nc_o);
214 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it)
216 { Hr(*it, i) = T(1)/
vect_norminf(mat_col(B, *it)); ++i; }
218 { Ho(*it, j) = T(1)/
vect_norm2(mat_col(B, *it)); ++j; }
220 gmm::mult(B, Hr, BBr);
221 gmm::mult(B, Ho, BBo);
222 gmm::dense_matrix<T> M(nc_r, nc_r), BBB(nc_r, nc_o), MM(nc_r, nc_r);
223 gmm::mult(gmm::conjugated(BBr), BBr, M);
224 gmm::mult(gmm::conjugated(BBr), BBo, BBB);
225 gmm::mult(BBB, gmm::conjugated(BBB), MM);
226 gmm::add(gmm::scaled(MM, T(-1)), M);
228 std::vector<int> ipvt(nc_r);
232 for (i = 0; i < nc_r; ++i) emax = std::max(emax, gmm::abs(M(i,i)));
235 std::set<size_type> c = columns;
236 for (TAB::iterator it = c.begin(); it != c.end(); ++it)
237 if (!(c_ortho[*it])) {
238 if (gmm::abs(M(i,i)) <= R(EPS)*emax) columns.erase(*it);
249 template <
typename Mat>
250 void range_basis_eff_Gram_Schmidt_sparse(
const Mat &BB,
251 std::set<size_type> &columns,
252 std::vector<bool> &c_ortho,
255 typedef std::set<size_type> TAB;
256 typedef typename linalg_traits<Mat>::value_type T;
257 typedef typename number_traits<T>::magnitude_type R;
259 size_type nc = mat_ncols(BB), nr = mat_nrows(BB);
260 std::set<size_type> c = columns, rc = columns;
262 gmm::col_matrix< rsvector<T> > B(nr, nc);
263 for (std::set<size_type>::iterator it = columns.begin();
264 it != columns.end(); ++it) {
265 gmm::copy(mat_col(BB, *it), mat_col(B, *it));
266 gmm::scale(mat_col(B, *it), T(1)/
vect_norm2(mat_col(B, *it)));
269 for (std::set<size_type>::iterator it = c.begin(); it != c.end(); ++it)
271 for (std::set<size_type>::iterator it2 = rc.begin();
272 it2 != rc.end(); ++it2)
273 if (!(c_ortho[*it2])) {
274 T r = -
vect_hp(mat_col(B, *it2), mat_col(B, *it));
275 if (r != T(0))
add(scaled(mat_col(B, *it), r), mat_col(B, *it2));
282 for (std::set<size_type>::iterator it=rc.begin(); it != rc.end();) {
283 TAB::iterator itnext = it; ++itnext;
285 if (nmax < n) { nmax = n; cmax = *it; }
286 if (n < R(EPS)) { columns.erase(*it); rc.erase(*it); }
290 if (nmax < R(EPS))
break;
292 gmm::scale(mat_col(B, cmax), T(1)/
vect_norm2(mat_col(B, cmax)));
294 for (std::set<size_type>::iterator it=rc.begin(); it!=rc.end(); ++it) {
295 T r = -
vect_hp(mat_col(B, *it), mat_col(B, cmax));
296 if (r != T(0))
add(scaled(mat_col(B, cmax), r), mat_col(B, *it));
299 for (std::set<size_type>::iterator it=rc.begin(); it!=rc.end(); ++it)
305 template <
typename Mat>
306 void range_basis_eff_Gram_Schmidt_dense(
const Mat &B,
307 std::set<size_type> &columns,
308 std::vector<bool> &c_ortho,
311 typedef std::set<size_type> TAB;
312 typedef typename linalg_traits<Mat>::value_type T;
313 typedef typename number_traits<T>::magnitude_type R;
315 size_type nc_r = columns.size(), nc = mat_ncols(B), nr = mat_nrows(B), i;
316 std::set<size_type> rc;
318 row_matrix< gmm::rsvector<T> > H(nc, nc_r), BB(nr, nc_r);
319 std::vector<T> v(nc_r);
320 std::vector<size_type> ind(nc_r);
323 for (TAB::iterator it = columns.begin(); it != columns.end(); ++it, ++i)
324 H(*it, i) = T(1) /
vect_norm2(mat_col(B, *it));
327 dense_matrix<T> M(nc_r, nc_r);
328 mult(gmm::conjugated(BB), BB, M);
331 for (TAB::iterator it = columns.begin(); it != columns.end(); ++it, ++i)
333 gmm::copy(mat_row(M, i), v);
334 rank_one_update(M, scaled(v, T(-1)), v);
337 else { rc.insert(i); ind[i] = *it; }
339 while (rc.size() > 0) {
343 for (TAB::iterator it = rc.begin(); it != rc.end();) {
344 TAB::iterator itnext = it; ++itnext;
345 R a = gmm::abs(M(*it, *it));
346 if (a > nmax) { nmax = a; imax = *it; }
347 if (a < R(EPS)) { columns.erase(ind[*it]); rc.erase(*it); }
351 if (nmax < R(EPS))
break;
354 gmm::scale(mat_row(M, imax), T(1) / sqrt(nmax));
355 gmm::scale(mat_col(M, imax), T(1) / sqrt(nmax));
358 copy(mat_row(M, imax), v);
359 rank_one_update(M, scaled(v, T(-1)), v);
360 M(imax, imax) = T(1);
364 for (std::set<size_type>::iterator it=rc.begin(); it!=rc.end(); ++it)
365 columns.erase(ind[*it]);
368 template <
typename L>
size_type nnz_eps(
const L& l,
double eps) {
369 typename linalg_traits<L>::const_iterator it = vect_const_begin(l),
370 ite = vect_const_end(l);
372 for (; it != ite; ++it)
if (gmm::abs(*it) >= eps) ++res;
376 template <
typename L>
377 bool reserve__rb(
const L& l, std::vector<bool> &b,
double eps) {
378 typename linalg_traits<L>::const_iterator it = vect_const_begin(l),
379 ite = vect_const_end(l);
381 for (; it != ite; ++it)
382 if (gmm::abs(*it) >= eps && b[it.index()]) ok =
false;
384 for (it = vect_const_begin(l); it != ite; ++it)
385 if (gmm::abs(*it) >= eps) b[it.index()] =
true;
390 template <
typename Mat>
391 void range_basis(
const Mat &B, std::set<size_type> &columns,
392 double EPS, col_major,
bool skip_init=
false) {
394 typedef typename linalg_traits<Mat>::value_type T;
395 typedef typename number_traits<T>::magnitude_type R;
397 size_type nc = mat_ncols(B), nr = mat_nrows(B);
399 std::vector<R> norms(nc);
400 std::vector<bool> c_ortho(nc), booked(nr);
401 std::vector< std::set<size_type> > nnzs(mat_nrows(B));
408 norm_max = std::max(norm_max, norms[i]);
413 if (norms[i] > norm_max*R(EPS)) {
415 nnzs[nnz_eps(mat_col(B, i), R(EPS) * norms[i])].insert(i);
419 for (std::set<size_type>::iterator it = nnzs[i].begin();
420 it != nnzs[i].end(); ++it)
421 if (reserve__rb(mat_col(B, *it), booked, R(EPS) * norms[*it]))
425 size_type sizesm[7] = {125, 200, 350, 550, 800, 1100, 1500}, actsize;
426 for (
int k = 0; k < 7; ++k) {
428 std::set<size_type> c1, cres;
430 for (std::set<size_type>::iterator it = columns.begin();
431 it != columns.end(); ++it) {
433 if (c1.size() >= actsize) {
434 range_basis_eff_Gram_Schmidt_dense(B, c1, c_ortho, EPS);
435 for (std::set<size_type>::iterator it2=c1.begin(); it2 != c1.end();
436 ++it2) cres.insert(*it2);
441 range_basis_eff_Gram_Schmidt_dense(B, c1, c_ortho, EPS);
442 for (std::set<size_type>::iterator it = c1.begin(); it != c1.end(); ++it)
445 if (nc_r <= actsize)
return;
446 if (columns.size() == nc_r)
break;
447 if (sizesm[k] >= 350 && columns.size() > (nc_r*19)/20)
break;
449 if (columns.size() > std::max(
size_type(10), actsize))
450 range_basis_eff_Lanczos(B, columns, EPS);
452 range_basis_eff_Gram_Schmidt_dense(B, columns, c_ortho, EPS);
456 template <
typename Mat>
457 void range_basis(
const Mat &B, std::set<size_type> &columns,
458 double EPS, row_major) {
459 typedef typename linalg_traits<Mat>::value_type T;
460 gmm::col_matrix< rsvector<T> > BB(mat_nrows(B), mat_ncols(B));
461 GMM_WARNING3(
"A copy of a row matrix is done into a column matrix "
462 "for range basis algorithm.");
464 range_basis(BB, columns, EPS);
489 template <
typename Mat>
490 void range_basis(
const Mat &B, std::set<size_type> &columns,
492 range_basis(B, columns, EPS,
493 typename principal_orientation_type
494 <
typename linalg_traits<Mat>::sub_orientation>::potype());