37 #ifndef GMM_RANGE_BASIS_H
38 #define GMM_RANGE_BASIS_H
51 template <
typename T,
typename VECT,
typename MAT1>
52 void tridiag_qr_algorithm
53 (std::vector<
typename number_traits<T>::magnitude_type> diag,
54 std::vector<T> sdiag,
const VECT &eigval_,
const MAT1 &eigvect_,
55 bool compvect, tol_type_for_qr tol = default_tol_for_qr) {
56 VECT &eigval =
const_cast<VECT &
>(eigval_);
57 MAT1 &eigvect =
const_cast<MAT1 &
>(eigvect_);
58 typedef typename number_traits<T>::magnitude_type R;
60 if (compvect)
gmm::copy(identity_matrix(), eigvect);
62 size_type n = diag.size(), q = 0, p, ite = 0;
64 if (n == 1) { eigval[0] = gmm::real(diag[0]);
return; }
66 symmetric_qr_stop_criterion(diag, sdiag, p, q, tol);
69 sub_interval SUBI(p, n-p-q), SUBJ(0, mat_ncols(eigvect)), SUBK(p, n-p-q);
70 if (!compvect) SUBK = sub_interval(0,0);
72 symmetric_Wilkinson_qr_step(sub_vector(diag, SUBI),
73 sub_vector(sdiag, SUBI),
74 sub_matrix(eigvect, SUBJ, SUBK), compvect);
76 symmetric_qr_stop_criterion(diag, sdiag, p, q, tol*R(3));
78 GMM_ASSERT1(ite < n*100,
"QR algorithm failed.");
85 template <
typename Mat>
86 void range_basis_eff_Lanczos(
const Mat &BB, std::set<size_type> &columns,
88 typedef std::set<size_type> TAB;
89 typedef typename linalg_traits<Mat>::value_type T;
90 typedef typename number_traits<T>::magnitude_type R;
93 col_matrix< rsvector<T> > B(mat_nrows(BB), mat_ncols(BB));
96 for (TAB::iterator it = columns.begin(); it!=columns.end(); ++it, ++k)
99 std::vector<T> w(mat_nrows(B));
101 std::vector<T> sdiag(restart);
102 std::vector<R> eigval(restart), diag(restart);
103 dense_matrix<T> eigvect(restart, restart);
108 std::vector<T> v(nc_r), v0(nc_r), wl(nc_r);
109 dense_matrix<T> lv(nc_r, restart);
117 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++k)
118 add(scaled(mat_col(B, *it), v[k]), w);
120 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++k)
121 v[k] =
vect_hp(w, mat_col(B, *it));
133 R beta = R(0),
alpha;
136 if (sdiag.size() != restart) {
137 sdiag.resize(restart);
138 eigval.resize(restart);
139 diag.resize(restart);
144 for (
size_type i = 0; i < restart; ++i) {
148 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++k)
149 add(scaled(mat_col(B, *it), v[k]), w);
152 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++k)
153 wl[k] = v[k]*rho -
vect_hp(w, mat_col(B, *it)) - beta*v0[k];
156 gmm::add(gmm::scaled(v, -alpha), wl);
159 if (beta < EPS) { eff_restart = i+1;
break; }
160 gmm::copy(gmm::scaled(wl, T(1) / beta), v);
162 if (eff_restart != restart) {
163 sdiag.resize(eff_restart);
164 eigval.resize(eff_restart);
165 diag.resize(eff_restart);
169 tridiag_qr_algorithm(diag, sdiag, eigval, eigvect,
true);
173 for (
size_type j = 0; j < eff_restart; ++j) {
174 R nvp=gmm::abs(eigval[j]);
181 GMM_ASSERT1(num !=
size_type(-1),
"Internal error");
185 if (gmm::abs(rho2-rho_old) < rho_old*R(EPS))
break;
187 if (gmm::abs(rho-rho2) < rho*R(EPS)*R(100))
break;
190 if (gmm::abs(rho-rho2) < rho*R(EPS*10.)) {
193 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++j)
194 if (gmm::abs(v[j]) > val_max) {
195 val_max = gmm::abs(v[j]);
198 columns.erase(j_max);
199 nc_r = columns.size();
208 template <
typename Mat>
209 void range_basis_eff_lu(
const Mat &B, std::set<size_type> &columns,
210 std::vector<bool> &c_ortho,
double EPS) {
212 typedef std::set<size_type> TAB;
213 typedef typename linalg_traits<Mat>::value_type T;
214 typedef typename number_traits<T>::magnitude_type R;
216 size_type nc_r = 0, nc_o = 0, nc = mat_ncols(B), nr = mat_nrows(B), i, j;
218 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it)
219 if (!(c_ortho[*it])) ++nc_r;
else nc_o++;
223 gmm::row_matrix< gmm::rsvector<T> > Hr(nc, nc_r), Ho(nc, nc_o);
224 gmm::row_matrix< gmm::rsvector<T> > BBr(nr, nc_r), BBo(nr, nc_o);
227 for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it)
229 { Hr(*it, i) = T(1)/
vect_norminf(mat_col(B, *it)); ++i; }
231 { Ho(*it, j) = T(1)/
vect_norm2(mat_col(B, *it)); ++j; }
235 gmm::dense_matrix<T> M(nc_r, nc_r), BBB(nc_r, nc_o), MM(nc_r, nc_r);
237 gmm::mult(gmm::conjugated(BBr), BBo, BBB);
238 gmm::mult(BBB, gmm::conjugated(BBB), MM);
239 gmm::add(gmm::scaled(MM, T(-1)), M);
241 std::vector<int> ipvt(nc_r);
245 for (i = 0; i < nc_r; ++i) emax = std::max(emax, gmm::abs(M(i,i)));
248 std::set<size_type> c = columns;
249 for (TAB::iterator it = c.begin(); it != c.end(); ++it)
250 if (!(c_ortho[*it])) {
251 if (gmm::abs(M(i,i)) <= R(EPS)*emax) columns.erase(*it);
262 template <
typename Mat>
263 void range_basis_eff_Gram_Schmidt_sparse(
const Mat &BB,
264 std::set<size_type> &columns,
265 std::vector<bool> &c_ortho,
268 typedef std::set<size_type> TAB;
269 typedef typename linalg_traits<Mat>::value_type T;
270 typedef typename number_traits<T>::magnitude_type R;
272 size_type nc = mat_ncols(BB), nr = mat_nrows(BB);
273 std::set<size_type> c = columns, rc = columns;
275 gmm::col_matrix< rsvector<T> > B(nr, nc);
276 for (std::set<size_type>::iterator it = columns.begin();
277 it != columns.end(); ++it) {
278 gmm::copy(mat_col(BB, *it), mat_col(B, *it));
279 gmm::scale(mat_col(B, *it), T(1)/
vect_norm2(mat_col(B, *it)));
282 for (std::set<size_type>::iterator it = c.begin(); it != c.end(); ++it)
284 for (std::set<size_type>::iterator it2 = rc.begin();
285 it2 != rc.end(); ++it2)
286 if (!(c_ortho[*it2])) {
287 T r = -
vect_hp(mat_col(B, *it2), mat_col(B, *it));
288 if (r != T(0))
add(scaled(mat_col(B, *it), r), mat_col(B, *it2));
295 for (std::set<size_type>::iterator it=rc.begin(); it != rc.end();) {
296 TAB::iterator itnext = it; ++itnext;
298 if (nmax < n) { nmax = n; cmax = *it; }
299 if (n < R(EPS)) { columns.erase(*it); rc.erase(*it); }
303 if (nmax < R(EPS))
break;
305 gmm::scale(mat_col(B, cmax), T(1)/
vect_norm2(mat_col(B, cmax)));
307 for (std::set<size_type>::iterator it=rc.begin(); it!=rc.end(); ++it) {
308 T r = -
vect_hp(mat_col(B, *it), mat_col(B, cmax));
309 if (r != T(0))
add(scaled(mat_col(B, cmax), r), mat_col(B, *it));
312 for (std::set<size_type>::iterator it=rc.begin(); it!=rc.end(); ++it)
318 template <
typename Mat>
319 void range_basis_eff_Gram_Schmidt_dense(
const Mat &B,
320 std::set<size_type> &columns,
321 std::vector<bool> &c_ortho,
324 typedef std::set<size_type> TAB;
325 typedef typename linalg_traits<Mat>::value_type T;
326 typedef typename number_traits<T>::magnitude_type R;
328 size_type nc_r = columns.size(), nc = mat_ncols(B), nr = mat_nrows(B), i;
329 std::set<size_type> rc;
331 row_matrix< gmm::rsvector<T> > H(nc, nc_r), BB(nr, nc_r);
332 std::vector<T> v(nc_r);
333 std::vector<size_type> ind(nc_r);
336 for (TAB::iterator it = columns.begin(); it != columns.end(); ++it, ++i)
337 H(*it, i) = T(1) /
vect_norm2(mat_col(B, *it));
340 dense_matrix<T> M(nc_r, nc_r);
341 mult(gmm::conjugated(BB), BB, M);
344 for (TAB::iterator it = columns.begin(); it != columns.end(); ++it, ++i)
347 rank_one_update(M, scaled(v, T(-1)), v);
350 else { rc.insert(i); ind[i] = *it; }
352 while (rc.size() > 0) {
356 for (TAB::iterator it = rc.begin(); it != rc.end();) {
357 TAB::iterator itnext = it; ++itnext;
358 R a = gmm::abs(M(*it, *it));
359 if (a > nmax) { nmax = a; imax = *it; }
360 if (a < R(EPS)) { columns.erase(ind[*it]); rc.erase(*it); }
364 if (nmax < R(EPS))
break;
367 gmm::scale(mat_row(M, imax), T(1) / sqrt(nmax));
368 gmm::scale(mat_col(M, imax), T(1) / sqrt(nmax));
371 copy(mat_row(M, imax), v);
372 rank_one_update(M, scaled(v, T(-1)), v);
373 M(imax, imax) = T(1);
377 for (std::set<size_type>::iterator it=rc.begin(); it!=rc.end(); ++it)
378 columns.erase(ind[*it]);
382 template <
typename Mat>
383 void range_basis(
const Mat &B, std::set<size_type> &columns,
384 double EPS, col_major,
bool skip_init=
false) {
386 typedef typename linalg_traits<Mat>::value_type T;
387 typedef typename number_traits<T>::magnitude_type R;
389 size_type nc = mat_ncols(B), nr = mat_nrows(B);
390 std::vector<bool> c_ortho(nc);
393 std::vector<R> norms(nc);
397 norm_max = std::max(norm_max, norms[i]);
401 std::vector< std::set<size_type> > nnzs(nr+1);
403 if (norms[i] > norm_max*R(EPS)) {
407 const auto eps = R(EPS) * norms[i];
408 const auto col = mat_const_col(B, i);
409 const auto ite = vect_const_end(col);
410 for (
auto it = vect_const_begin(col); it != ite; ++it)
411 if (gmm::abs(*it) >= eps)
414 nnzs[nnz_eps].insert(i);
417 std::vector<bool> booked(nr);
419 for (std::set<size_type>::iterator it = nnzs[i].begin();
420 it != nnzs[i].end(); ++it) {
421 const auto eps = R(EPS) * norms[*it];
422 const auto col = mat_const_col(B, *it);
423 const auto ite = vect_const_end(col);
424 bool reserve__rb =
true;
425 for (
auto it1 = vect_const_begin(col); it1 != ite; ++it1)
426 if (gmm::abs(*it1) >= eps && booked[it1.index()])
429 for (
auto it1 = vect_const_begin(col); it1 != ite; ++it1)
430 if (gmm::abs(*it1) >= eps)
431 booked[it1.index()] =
true;
437 size_type sizesm[7] = {125, 200, 350, 550, 800, 1100, 1500}, actsize;
438 for (
int k = 0; k < 7; ++k) {
440 std::set<size_type> c1, cres;
442 for (std::set<size_type>::iterator it = columns.begin();
443 it != columns.end(); ++it) {
445 if (c1.size() >= actsize) {
446 range_basis_eff_Gram_Schmidt_dense(B, c1, c_ortho, EPS);
447 for (std::set<size_type>::iterator it2=c1.begin(); it2 != c1.end();
448 ++it2) cres.insert(*it2);
453 range_basis_eff_Gram_Schmidt_dense(B, c1, c_ortho, EPS);
454 for (std::set<size_type>::iterator it = c1.begin(); it != c1.end(); ++it)
457 if (nc_r <= actsize)
return;
458 if (columns.size() == nc_r)
break;
459 if (sizesm[k] >= 350 && columns.size() > (nc_r*19)/20)
break;
461 if (columns.size() > std::max(
size_type(10), actsize))
462 range_basis_eff_Lanczos(B, columns, EPS);
464 range_basis_eff_Gram_Schmidt_dense(B, columns, c_ortho, EPS);
468 template <
typename Mat>
469 void range_basis(
const Mat &B, std::set<size_type> &columns,
470 double EPS, row_major) {
471 typedef typename linalg_traits<Mat>::value_type T;
472 gmm::col_matrix< rsvector<T> > BB(mat_nrows(B), mat_ncols(B));
473 GMM_WARNING3(
"A copy of a row matrix is done into a column matrix "
474 "for range basis algorithm.");
476 range_basis(BB, columns, EPS);
501 template <
typename Mat>
502 void range_basis(
const Mat &B, std::set<size_type> &columns,
504 range_basis(B, columns, EPS,
505 typename principal_orientation_type
506 <
typename linalg_traits<Mat>::sub_orientation>::potype());
void copy(const L1 &l1, L2 &l2)
*/
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
void fill_random(L &l)
fill a vector or matrix with random value (uniform [-1,1]).
strongest_value_type< V1, V2 >::value_type vect_hp(const V1 &v1, const V2 &v2)
*/
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norminf(const V &v)
Infinity norm of a vector.
void clear(L &l)
clear (fill with zeros) a vector or matrix.
void resize(V &v, size_type n)
*/
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*/
void add(const L1 &l1, L2 &l2)
*/
LU factorizations and determinant computation for dense matrices.
size_type lu_factor(DenseMatrix &A, Pvector &ipvt)
LU Factorization of a general (dense) matrix (real or complex).
Include the base gmm files.
size_t size_type
used as the common size type in the library
size_type alpha(short_type n, short_type d)
Return the value of which is the number of monomials of a polynomial of variables and degree .