10 #ifndef __Belos_ProjectedLeastSquaresSolver_hpp
11 #define __Belos_ProjectedLeastSquaresSolver_hpp
18 #include "Teuchos_oblackholestream.hpp"
21 #include "Teuchos_StandardParameterEntryValidators.hpp"
43 template<
class Scalar>
45 printMatrix (std::ostream& out,
46 const std::string& name,
51 const int numRows = A.
numRows();
52 const int numCols = A.
numCols();
54 out << name <<
" = " << endl <<
'[';
57 for (
int i = 0; i < numRows; ++i) {
64 for (
int i = 0; i < numRows; ++i) {
65 for (
int j = 0; j < numCols; ++j) {
69 }
else if (i < numRows-1) {
80 template<
class Scalar>
82 print (std::ostream& out,
84 const std::string& linePrefix)
88 const int numRows = A.
numRows();
89 const int numCols = A.
numCols();
91 out << linePrefix <<
'[';
94 for (
int i = 0; i < numRows; ++i) {
101 for (
int i = 0; i < numRows; ++i) {
102 for (
int j = 0; j < numCols; ++j) {
104 out << linePrefix <<
" ";
109 }
else if (i < numRows-1) {
115 out << linePrefix <<
']' << endl;
126 template<
class Scalar>
206 H (maxNumIterations+1, maxNumIterations),
207 R (maxNumIterations+1, maxNumIterations),
208 y (maxNumIterations+1, 1),
209 z (maxNumIterations+1, 1),
242 const Scalar initialResidualNorm (beta);
243 z(0,0) = initialResidualNorm;
261 const int maxNumIterations)
267 "ProjectedLeastSquaresProblem::reset: initial "
268 "residual beta = " << beta <<
" < 0.");
270 "ProjectedLeastSquaresProblem::reset: maximum number "
271 "of iterations " << maxNumIterations <<
" <= 0.");
274 const int errcode =
H.
reshape (maxNumIterations+1, maxNumIterations);
276 "Failed to reshape H into a " << (maxNumIterations+1)
277 <<
" x " << maxNumIterations <<
" matrix.");
282 const int errcode =
R.
reshape (maxNumIterations+1, maxNumIterations);
284 "Failed to reshape R into a " << (maxNumIterations+1)
285 <<
" x " << maxNumIterations <<
" matrix.");
290 const int errcode =
y.
reshape (maxNumIterations+1, 1);
292 "Failed to reshape y into a " << (maxNumIterations+1)
293 <<
" x " << 1 <<
" matrix.");
298 const int errcode =
z.
reshape (maxNumIterations+1, 1);
300 "Failed to reshape z into a " << (maxNumIterations+1)
301 <<
" x " << 1 <<
" matrix.");
316 template<
class Scalar>
340 for (
int i = 0; i < A.
numRows(); ++i) {
341 for (
int j = 0; j < A.
numCols(); ++j) {
353 for (
int j = 0; j < N; ++j) {
354 for (
int i = 0; i <= j; ++i) {
366 for (
int j = 0; j < N; ++j) {
367 for (
int i = j+1; i < A.
numRows(); ++i) {
398 A_22 =
rcp (
new mat_type (
View, A, numRows2, numCols2, numRows1, numCols1));
406 const int numRows = A.
numRows();
407 const int numCols = A.
numCols();
409 if (numRows == 0 || numCols == 0) {
412 for (
int j = 0; j < numCols; ++j) {
415 for (
int i = 0; i < numRows; ++i) {
431 const int numRows = Y.
numRows();
432 const int numCols = Y.
numCols();
435 std::invalid_argument,
"Dimensions of X and Y don't "
437 <<
", and Y is " << numRows <<
" x " << numCols <<
".");
438 for (
int j = 0; j < numCols; ++j) {
439 for (
int i = 0; i < numRows; ++i) {
440 Y(i,j) += alpha * X(i,j);
449 const int numRows = A.
numRows();
450 const int numCols = A.
numCols();
454 std::invalid_argument,
455 "matAdd: The input matrices A and B have incompatible dimensions. "
456 "A is " << numRows <<
" x " << numCols <<
", but B is " <<
458 if (numRows == 0 || numCols == 0) {
461 for (
int j = 0; j < numCols; ++j) {
465 for (
int i = 0; i < numRows; ++i) {
476 const int numRows = A.
numRows();
477 const int numCols = A.
numCols();
481 std::invalid_argument,
482 "matSub: The input matrices A and B have incompatible dimensions. "
483 "A is " << numRows <<
" x " << numCols <<
", but B is " <<
485 if (numRows == 0 || numCols == 0) {
488 for (
int j = 0; j < numCols; ++j) {
492 for (
int i = 0; i < numRows; ++i) {
508 std::invalid_argument,
509 "rightUpperTriSolve: R and B have incompatible "
510 "dimensions. B has " << B.
numCols() <<
" columns, "
511 "but R has " << R.
numRows() <<
" rows.");
535 std::invalid_argument,
536 "matMatMult: The input matrices A and B have "
537 "incompatible dimensions. A is " << A.
numRows()
538 <<
" x " << A.
numCols() <<
", but B is "
541 std::invalid_argument,
542 "matMatMult: The input matrix A and the output "
543 "matrix C have incompatible dimensions. A has "
547 std::invalid_argument,
548 "matMatMult: The input matrix B and the output "
549 "matrix C have incompatible dimensions. B has "
550 << B.
numCols() <<
" columns, but C has "
551 << C.
numCols() <<
" columns.");
569 for (
int j = 0; j < A.
numCols(); ++j) {
570 if (upperTriangular) {
571 for (
int i = 0; i <= j && i < A.
numRows(); ++i) {
577 for (
int i = 0; i < A.
numRows(); ++i) {
592 std::pair<bool, std::pair<magnitude_type, magnitude_type> >
599 for (
int j = 0; j < A.
numCols(); ++j) {
603 for (
int i = 0; i <= j && i < A.
numRows(); ++i) {
605 upperTri += A_ij_mag * A_ij_mag;
608 for (
int i = j+1; i < A.
numRows(); ++i) {
610 lowerTri += A_ij_mag * A_ij_mag;
616 return std::make_pair (count == 0, std::make_pair (lowerTri, upperTri));
625 std::pair<bool, std::pair<magnitude_type, magnitude_type> >
632 for (
int j = 0; j < A.
numCols(); ++j) {
636 for (
int i = 0; i <= j+1 && i < A.
numRows(); ++i) {
638 upper += A_ij_mag * A_ij_mag;
641 for (
int i = j+2; i < A.
numRows(); ++i) {
643 lower += A_ij_mag * A_ij_mag;
649 return std::make_pair (count == 0, std::make_pair (lower, upper));
660 const char*
const matrixName)
const
662 std::pair<bool, std::pair<magnitude_type, magnitude_type> > result =
667 <<
" matrix " << matrixName <<
" is not upper "
668 "triangular. ||tril(A)||_F = "
669 << result.second.first <<
" and ||A||_F = "
670 << result.second.second <<
".");
681 const char*
const matrixName)
const
683 std::pair<bool, std::pair<magnitude_type, magnitude_type> > result =
688 <<
" matrix " << matrixName <<
" is not upper "
689 "triangular. ||tril(A(2:end, :))||_F = "
690 << result.second.first <<
" and ||A||_F = "
691 << result.second.second <<
".");
711 const char*
const matrixName,
714 std::pair<bool, std::pair<magnitude_type, magnitude_type> > result =
720 result.second.first :
721 result.second.first / result.second.second);
724 <<
" matrix " << matrixName <<
" is not upper "
725 "triangular. ||tril(A(2:end, :))||_F "
726 << (result.second.second ==
STM::zero() ?
"" :
" / ||A||_F")
727 <<
" = " << err <<
" > " << relativeTolerance <<
".");
744 const char*
const matrixName,
745 const int minNumRows,
746 const int minNumCols)
const
749 std::invalid_argument,
750 "The matrix " << matrixName <<
" is " << A.
numRows()
751 <<
" x " << A.
numCols() <<
", and therefore does not "
752 "satisfy the minimum dimensions " << minNumRows
753 <<
" x " << minNumCols <<
".");
769 const char*
const matrixName,
771 const int numCols)
const
774 std::invalid_argument,
775 "The matrix " << matrixName <<
" is supposed to be "
776 << numRows <<
" x " << numCols <<
", but is "
811 const char* strings[] = {
"None",
"Some",
"Lots"};
813 std::invalid_argument,
814 "Invalid enum value " << x <<
".");
815 return std::string (strings[x]);
822 const char* strings[] = {
"None",
"Some",
"Lots"};
824 if (x == strings[r]) {
829 "Invalid robustness string " << x <<
".");
845 using Teuchos::stringToIntegralParameterEntryValidator;
852 docs[0] =
"Use the BLAS' triangular solve. This may result in Inf or "
853 "NaN output if the triangular matrix is rank deficient.";
854 docs[1] =
"Robustness somewhere between \"None\" and \"Lots\".";
855 docs[2] =
"Solve the triangular system in a least-squares sense, using "
856 "an SVD-based algorithm. This will always succeed, though the "
857 "solution may not make sense for GMRES.";
862 const std::string pname (
"Robustness of Projected Least-Squares Solve");
864 return stringToIntegralParameterEntryValidator<ERobustness> (strs, docs,
930 template<
class Scalar>
972 defaultRobustness_ (defaultRobustness)
992 return updateColumnGivens (problem.
H, problem.
R, problem.
y, problem.
z,
1015 return updateColumnsGivens (problem.
H, problem.
R, problem.
y, problem.
z,
1037 solveGivens (problem.
y, problem.
R, problem.
z, curCol);
1044 std::pair<int, bool>
1091 std::pair<int, bool>
1099 "The output X and right-hand side B have different "
1100 "numbers of rows. X has " << X.
numRows() <<
" rows"
1101 ", and B has " << B.
numRows() <<
" rows.");
1107 "The output X has more columns than the "
1108 "right-hand side B. X has " << X.
numCols()
1109 <<
" columns and B has " << B.
numCols()
1127 std::pair<int, bool>
1142 std::pair<int, bool>
1157 "The input matrix R has fewer columns than rows. "
1158 "R is " << M <<
" x " << N <<
".");
1164 "The input/output matrix X has only "
1165 << X.
numRows() <<
" rows, but needs at least "
1166 << N <<
" rows to match the matrix for a "
1167 "left-side solve R \\ X.");
1170 "The input/output matrix X has only "
1171 << X.
numCols() <<
" columns, but needs at least "
1172 << N <<
" columns to match the matrix for a "
1173 "right-side solve X / R.");
1177 std::invalid_argument,
1178 "Invalid robustness value " << robustness <<
".");
1186 "There " << (count != 1 ?
"are" :
"is")
1187 <<
" " << count <<
" Inf or NaN entr"
1188 << (count != 1 ?
"ies" :
"y")
1189 <<
" in the upper triangle of R.");
1192 "There " << (count != 1 ?
"are" :
"is")
1193 <<
" " << count <<
" Inf or NaN entr"
1194 << (count != 1 ?
"ies" :
"y") <<
" in the "
1195 "right-hand side(s) X.");
1200 bool foundRankDeficiency =
false;
1228 warn_ <<
"Upper triangular solve: Found Infs and/or NaNs in the "
1229 "solution after using the fast algorithm. Retrying using a more "
1230 "robust algorithm." << std::endl;
1250 rank = solveLeastSquaresUsingSVD (R_copy, X);
1265 rank = solveLeastSquaresUsingSVD (R_star, X_star);
1271 foundRankDeficiency =
true;
1276 "Should never get here! Invalid robustness value "
1277 << robustness <<
". Please report this bug to the "
1278 "Belos developers.");
1280 return std::make_pair (rank, foundRankDeficiency);
1298 out <<
"Testing Givens rotations:" << endl;
1301 out <<
" x = " << x <<
", y = " << y << endl;
1303 Scalar theCosine, theSine, result;
1305 computeGivensRotation (x, y, theCosine, theSine, result);
1306 out <<
"-- After computing rotation:" << endl;
1307 out <<
"---- cos,sin = " << theCosine <<
"," << theSine << endl;
1308 out <<
"---- x = " << x <<
", y = " << y
1309 <<
", result = " << result << endl;
1311 blas.
ROT (1, &x, 1, &y, 1, &theCosine, &theSine);
1312 out <<
"-- After applying rotation:" << endl;
1313 out <<
"---- cos,sin = " << theCosine <<
"," << theSine << endl;
1314 out <<
"---- x = " << x <<
", y = " << y << endl;
1355 const bool testBlockGivens=
false,
1356 const bool extraVerbose=
false)
1362 "numCols = " << numCols <<
" <= 0.");
1363 const int numRows = numCols + 1;
1368 mat_type R_givens (numRows, numCols);
1371 Array<Scalar> theCosines (numCols);
1372 Array<Scalar> theSines (numCols);
1374 mat_type R_blockGivens (numRows, numCols);
1375 mat_type y_blockGivens (numRows, 1);
1376 mat_type z_blockGivens (numRows, 1);
1377 Array<Scalar> blockCosines (numCols);
1378 Array<Scalar> blockSines (numCols);
1379 const int panelWidth = std::min (3, numCols);
1381 mat_type R_lapack (numRows, numCols);
1386 makeRandomProblem (H, z);
1388 printMatrix<Scalar> (out,
"H", H);
1389 printMatrix<Scalar> (out,
"z", z);
1395 if (testBlockGivens) {
1396 z_blockGivens.
assign (z);
1406 for (
int curCol = 0; curCol < numCols; ++curCol) {
1407 residualNormGivens = updateColumnGivens (H, R_givens, y_givens, z_givens,
1408 theCosines, theSines, curCol);
1410 solveGivens (y_givens, R_givens, z_givens, numCols-1);
1415 if (testBlockGivens) {
1416 const bool testBlocksAtATime =
true;
1417 if (testBlocksAtATime) {
1419 for (
int startCol = 0; startCol < numCols; startCol += panelWidth) {
1420 int endCol = std::min (startCol + panelWidth - 1, numCols - 1);
1421 residualNormBlockGivens =
1422 updateColumnsGivens (H, R_blockGivens, y_blockGivens, z_blockGivens,
1423 blockCosines, blockSines, startCol, endCol);
1429 for (
int startCol = 0; startCol < numCols; ++startCol) {
1430 residualNormBlockGivens =
1431 updateColumnsGivens (H, R_blockGivens, y_blockGivens, z_blockGivens,
1432 blockCosines, blockSines, startCol, startCol);
1439 solveGivens (y_blockGivens, R_blockGivens, z_blockGivens, numCols-1);
1444 solveLapack (H, R_lapack, y_lapack, z_lapack, numCols-1);
1451 leastSquaresConditionNumber (H, z, residualNormLapack);
1467 solutionError (y_givens_view, y_lapack_view);
1468 const magnitude_type blockGivensSolutionError = testBlockGivens ?
1469 solutionError (y_blockGivens_view, y_lapack_view) :
1476 mat_type R_factorFromGivens (numCols, numCols);
1477 mat_type R_factorFromBlockGivens (numCols, numCols);
1478 mat_type R_factorFromLapack (numCols, numCols);
1480 for (
int j = 0; j < numCols; ++j) {
1481 for (
int i = 0; i <= j; ++i) {
1482 R_factorFromGivens(i,j) = R_givens(i,j);
1483 if (testBlockGivens) {
1484 R_factorFromBlockGivens(i,j) = R_blockGivens(i,j);
1486 R_factorFromLapack(i,j) = R_lapack(i,j);
1490 printMatrix<Scalar> (out,
"R_givens", R_factorFromGivens);
1491 printMatrix<Scalar> (out,
"y_givens", y_givens_view);
1492 printMatrix<Scalar> (out,
"z_givens", z_givens);
1494 if (testBlockGivens) {
1495 printMatrix<Scalar> (out,
"R_blockGivens", R_factorFromBlockGivens);
1496 printMatrix<Scalar> (out,
"y_blockGivens", y_blockGivens_view);
1497 printMatrix<Scalar> (out,
"z_blockGivens", z_blockGivens);
1500 printMatrix<Scalar> (out,
"R_lapack", R_factorFromLapack);
1501 printMatrix<Scalar> (out,
"y_lapack", y_lapack_view);
1502 printMatrix<Scalar> (out,
"z_lapack", z_lapack);
1508 out <<
"||H||_F = " << H_norm << endl;
1510 out <<
"||H y_givens - z||_2 / ||H||_F = "
1511 << leastSquaresResidualNorm (H, y_givens_view, z) / H_norm << endl;
1512 if (testBlockGivens) {
1513 out <<
"||H y_blockGivens - z||_2 / ||H||_F = "
1514 << leastSquaresResidualNorm (H, y_blockGivens_view, z) / H_norm << endl;
1516 out <<
"||H y_lapack - z||_2 / ||H||_F = "
1517 << leastSquaresResidualNorm (H, y_lapack_view, z) / H_norm << endl;
1519 out <<
"||y_givens - y_lapack||_2 / ||y_lapack||_2 = "
1520 << givensSolutionError << endl;
1521 if (testBlockGivens) {
1522 out <<
"||y_blockGivens - y_lapack||_2 / ||y_lapack||_2 = "
1523 << blockGivensSolutionError << endl;
1526 out <<
"Least-squares condition number = "
1527 << leastSquaresCondNum << endl;
1545 wiggleFactor * leastSquaresCondNum;
1547 solutionErrorBoundFactor *
STS::eps();
1548 out <<
"Solution error bound: " << solutionErrorBoundFactor
1549 <<
" * eps = " << solutionErrorBound << endl;
1562 }
else if (givensSolutionError > solutionErrorBound) {
1564 }
else if (testBlockGivens) {
1567 }
else if (blockGivensSolutionError > solutionErrorBound) {
1595 const int testProblemSize,
1597 const bool verbose=
false)
1605 std::ostream& verboseOut = verbose ? out : blackHole;
1607 verboseOut <<
"Testing upper triangular solves" << endl;
1611 verboseOut <<
"-- Generating test matrix" << endl;
1612 const int N = testProblemSize;
1615 for (
int j = 0; j < N; ++j) {
1616 for (
int i = 0; i <= j; ++i) {
1636 verboseOut <<
"-- Solving RX=B" << endl;
1640 mat_type Resid (N, 1);
1644 verboseOut <<
"---- ||R*X - B||_F = " << Resid.
normFrobenius() << endl;
1645 verboseOut <<
"---- ||R||_F ||X||_F + ||B||_F = "
1657 mat_type B_star (1, N);
1659 mat_type B_star_copy (1, N);
1660 B_star_copy.
assign (B_star);
1662 verboseOut <<
"-- Solving YR=B^*" << endl;
1666 mat_type Resid2 (1, N);
1667 Resid2.
assign (B_star_copy);
1669 verboseOut <<
"---- ||Y*R - B^*||_F = " << Resid2.
normFrobenius() << endl;
1670 verboseOut <<
"---- ||Y||_F ||R||_F + ||B^*||_F = "
1684 std::ostream& warn_;
1713 "solveLeastSquaresUsingSVD: The input matrix A "
1714 "contains " << count <<
"Inf and/or NaN entr"
1715 << (count != 1 ?
"ies" :
"y") <<
".");
1718 "solveLeastSquaresUsingSVD: The input matrix X "
1719 "contains " << count <<
"Inf and/or NaN entr"
1720 << (count != 1 ?
"ies" :
"y") <<
".");
1722 const int N = std::min (A.numRows(), A.numCols());
1733 Array<magnitude_type> singularValues (N);
1741 Array<magnitude_type> rwork (1);
1743 rwork.resize (std::max (1, 5 * N));
1750 lapack.GELSS (A.numRows(), A.numCols(), X.numCols(),
1751 A.values(), A.stride(), X.values(), X.stride(),
1752 &singularValues[0], rankTolerance, &rank,
1753 &lworkScalar, -1, &rwork[0], &info);
1755 "_GELSS workspace query returned INFO = "
1756 << info <<
" != 0.");
1757 const int lwork =
static_cast<int> (
STS::real (lworkScalar));
1759 "_GELSS workspace query returned LWORK = "
1760 << lwork <<
" < 0.");
1762 Array<Scalar> work (std::max (1, lwork));
1764 lapack.GELSS (A.numRows(), A.numCols(), X.numCols(),
1765 A.values(), A.stride(), X.values(), X.stride(),
1766 &singularValues[0], rankTolerance, &rank,
1767 &work[0], lwork, &rwork[0], &info);
1769 "_GELSS returned INFO = " << info <<
" != 0.");
1785 const int numRows = curCol + 2;
1795 R_view, z_view, defaultRobustness_);
1809 for (
int j = 0; j < H.numCols(); ++j) {
1810 for (
int i = j+2; i < H.numRows(); ++i) {
1822 const int numTrials = 1000;
1824 for (
int trial = 0; trial < numTrials && z_init ==
STM::zero(); ++trial) {
1828 "After " << numTrials <<
" trial"
1829 << (numTrials != 1 ?
"s" :
"")
1830 <<
", we were unable to generate a nonzero pseudo"
1831 "random real number. This most likely indicates a "
1832 "broken pseudorandom number generator.");
1845 computeGivensRotation (
const Scalar& x,
1853 const bool useLartg =
false;
1858 lapack.LARTG (x, y, &theCosine, &theSine, &result);
1867 blas.ROTG (&x_temp, &y_temp, &theCosine, &theSine);
1880 const int numRows = A.numRows();
1881 const int numCols = A.numCols();
1883 std::invalid_argument,
1884 "The sigmas array is only of length " << sigmas.
size()
1885 <<
", but must be of length at least "
1886 << std::min (numRows, numCols)
1887 <<
" in order to hold all the singular values of the "
1893 mat_type A_copy (numRows, numCols);
1900 Array<magnitude_type> rwork (std::max (std::min (numRows, numCols) - 1, 1));
1901 lapack.GESVD (
'N',
'N', numRows, numCols,
1902 A_copy.values(), A_copy.stride(), &sigmas[0],
1903 (Scalar*) NULL, 1, (Scalar*) NULL, 1,
1904 &lworkScalar, -1, &rwork[0], &info);
1906 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1907 "LAPACK _GESVD workspace query failed with INFO = "
1909 const
int lwork = static_cast<
int> (STS::real (lworkScalar));
1910 TEUCHOS_TEST_FOR_EXCEPTION(lwork < 0, std::logic_error,
1911 "LAPACK _GESVD workspace query returned LWORK = "
1912 << lwork << " < 0.");
1915 Teuchos::Array<Scalar> work (std::max (1, lwork));
1918 lapack.GESVD ('N', 'N', numRows, numCols,
1919 A_copy.values(), A_copy.stride(), &sigmas[0],
1920 (Scalar*) NULL, 1, (Scalar*) NULL, 1,
1921 &work[0], lwork, &rwork[0], &info);
1922 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1923 "LAPACK _GESVD failed with INFO = " << info << ".");
1934 extremeSingularValues (const
mat_type& A)
1938 const int numRows = A.numRows();
1939 const int numCols = A.numCols();
1941 Array<magnitude_type> sigmas (std::min (numRows, numCols));
1942 singularValues (A, sigmas);
1943 return std::make_pair (sigmas[0], sigmas[std::min(numRows, numCols) - 1]);
1957 leastSquaresConditionNumber (
const mat_type& A,
1959 const magnitude_type& residualNorm)
1962 const std::pair<magnitude_type, magnitude_type> sigmaMaxMin =
1963 extremeSingularValues (A);
1968 "The test matrix is rank deficient; LAPACK's _GESVD "
1969 "routine reports that its smallest singular value is "
1973 const magnitude_type A_cond = sigmaMaxMin.first / sigmaMaxMin.second;
1979 const magnitude_type sinTheta = residualNorm / b.normFrobenius();
1991 const magnitude_type cosTheta = (sinTheta >
STM::one()) ?
1997 const magnitude_type tanTheta = sinTheta / cosTheta;
2000 return 2 * A_cond / cosTheta + tanTheta * A_cond * A_cond;
2005 leastSquaresResidualNorm (
const mat_type& A,
2009 mat_type r (b.numRows(), b.numCols());
2013 LocalDenseMatrixOps<Scalar> ops;
2015 return r.normFrobenius ();
2023 solutionError (
const mat_type& x_approx,
2026 const int numRows = x_exact.numRows();
2027 const int numCols = x_exact.numCols();
2029 mat_type x_diff (numRows, numCols);
2030 for (
int j = 0; j < numCols; ++j) {
2031 for (
int i = 0; i < numRows; ++i) {
2032 x_diff(i,j) = x_exact(i,j) - x_approx(i,j);
2035 const magnitude_type scalingFactor = x_exact.normFrobenius();
2038 return x_diff.normFrobenius() /
2089 updateColumnGivens (
const mat_type& H,
2100 const int numRows = curCol + 2;
2101 const int LDR = R.stride();
2102 const bool extraDebug =
false;
2105 cerr <<
"updateColumnGivens: curCol = " << curCol << endl;
2119 R_col.assign (H_col);
2122 printMatrix<Scalar> (cerr,
"R_col before ", R_col);
2128 for (
int j = 0; j < curCol; ++j) {
2131 Scalar theCosine = theCosines[j];
2132 Scalar theSine = theSines[j];
2135 cerr <<
" j = " << j <<
": (cos,sin) = "
2136 << theCosines[j] <<
"," << theSines[j] << endl;
2138 blas.ROT (1, &R_col(j,0), LDR, &R_col(j+1,0), LDR,
2139 &theCosine, &theSine);
2141 if (extraDebug && curCol > 0) {
2142 printMatrix<Scalar> (cerr,
"R_col after applying previous "
2143 "Givens rotations", R_col);
2148 Scalar theCosine, theSine, result;
2149 computeGivensRotation (R_col(curCol,0), R_col(curCol+1,0),
2150 theCosine, theSine, result);
2151 theCosines[curCol] = theCosine;
2152 theSines[curCol] = theSine;
2155 cerr <<
" New cos,sin = " << theCosine <<
"," << theSine << endl;
2161 R_col(curCol, 0) = result;
2165 printMatrix<Scalar> (cerr,
"R_col after applying current "
2166 "Givens rotation", R_col);
2174 const int LDZ = z.stride();
2175 blas.ROT (z.numCols(),
2176 &z(curCol,0), LDZ, &z(curCol+1,0), LDZ,
2177 &theCosine, &theSine);
2183 printMatrix<Scalar> (cerr,
"z_after", z);
2232 const int numRows = curCol + 2;
2233 const int numCols = curCol + 1;
2234 const int LDR = R.stride();
2239 R_view.assign (H_view);
2251 lapack.GELS (
'N', numRows, numCols, y_view.numCols(),
2252 NULL, LDR, NULL, y_view.stride(),
2253 &lworkScalar, -1, &info);
2255 "LAPACK _GELS workspace query failed with INFO = "
2256 << info <<
", for a " << numRows <<
" x " << numCols
2257 <<
" matrix with " << y_view.numCols()
2258 <<
" right hand side"
2259 << ((y_view.numCols() != 1) ?
"s" :
"") <<
".");
2262 "LAPACK _GELS workspace query returned an LWORK with "
2263 "negative real part: LWORK = " << lworkScalar
2264 <<
". That should never happen. Please report this "
2265 "to the Belos developers.");
2268 "LAPACK _GELS workspace query returned an LWORK with "
2269 "nonzero imaginary part: LWORK = " << lworkScalar
2270 <<
". That should never happen. Please report this "
2271 "to the Belos developers.");
2277 const int lwork = std::max (1, static_cast<int> (
STS::real (lworkScalar)));
2285 lapack.GELS (
'N', numRows, numCols, y_view.numCols(),
2286 R_view.values(), R_view.stride(),
2287 y_view.values(), y_view.stride(),
2288 (lwork > 0 ? &work[0] : (Scalar*) NULL),
2292 "Solving projected least-squares problem with LAPACK "
2293 "_GELS failed with INFO = " << info <<
", for a "
2294 << numRows <<
" x " << numCols <<
" matrix with "
2295 << y_view.numCols() <<
" right hand side"
2296 << (y_view.numCols() != 1 ?
"s" :
"") <<
".");
2314 updateColumnsGivens (
const mat_type& H,
2324 "updateColumnGivens: startCol = " << startCol
2325 <<
" > endCol = " << endCol <<
".");
2326 magnitude_type lastResult =
STM::zero();
2328 for (
int curCol = startCol; curCol <= endCol; ++curCol) {
2329 lastResult = updateColumnGivens (H, R, y, z, theCosines, theSines, curCol);
2347 updateColumnsGivensBlock (
const mat_type& H,
2356 const int numRows = endCol + 2;
2357 const int numColsToUpdate = endCol - startCol + 1;
2358 const int LDR = R.stride();
2365 R_view.assign (H_view);
2373 for (
int j = 0; j < startCol; ++j) {
2374 blas.ROT (numColsToUpdate,
2375 &R(j, startCol), LDR, &R(j+1, startCol), LDR,
2376 &theCosines[j], &theSines[j]);
2380 for (
int curCol = startCol; curCol < endCol; ++curCol) {
2383 for (
int j = startCol; j < curCol; ++j) {
2384 blas.ROT (1, &R(j, curCol), LDR, &R(j+1, curCol), LDR,
2385 &theCosines[j], &theSines[j]);
2389 Scalar theCosine, theSine, result;
2390 computeGivensRotation (R(curCol, curCol), R(curCol+1, curCol),
2391 theCosine, theSine, result);
2392 theCosines[curCol] = theCosine;
2393 theSines[curCol] = theSine;
2398 R(curCol+1, curCol) = result;
2406 const int LDZ = z.stride();
2407 blas.ROT (z.numCols(),
2408 &z(curCol,0), LDZ, &z(curCol+1,0), LDZ,
2409 &theCosine, &theSine);
2421 #endif // __Belos_ProjectedLeastSquaresSolver_hpp
ScalarType * values() const
Collection of types and exceptions used within the Belos solvers.
Teuchos::SerialDenseMatrix< int, Scalar > z
Current right-hand side of the projected least-squares problem.
void TRSM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType &m, const OrdinalType &n, const alpha_type alpha, const A_type *A, const OrdinalType &lda, ScalarType *B, const OrdinalType &ldb) const
Teuchos::SerialDenseMatrix< int, Scalar > y
Current solution of the projected least-squares problem.
Teuchos::Array< Scalar > theCosines
Array of cosines from the computed Givens rotations.
void ensureMinimumDimensions(const mat_type &A, const char *const matrixName, const int minNumRows, const int minNumCols) const
Ensure that the matrix A is at least minNumRows by minNumCols.
std::pair< int, bool > solveUpperTriangularSystemInPlace(Teuchos::ESide side, mat_type &X, const mat_type &R, const ERobustness robustness)
Solve square upper triangular linear system(s) in place.
ProjectedLeastSquaresSolver(std::ostream &warnStream, const ERobustness defaultRobustness=ROBUSTNESS_NONE)
Constructor.
void matSub(mat_type &A, const mat_type &B) const
A := A - B.
static magnitudeType eps()
void ROT(const OrdinalType &n, ScalarType *dx, const OrdinalType &incx, ScalarType *dy, const OrdinalType &incy, MagnitudeType *c, ScalarType *s) const
void conjugateTransposeOfUpperTriangular(mat_type &L, const mat_type &R) const
L := (conjugate) transpose of R (upper triangular).
int infNaNCount(const mat_type &A, const bool upperTriangular=false) const
Return the number of Inf or NaN entries in the matrix A.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
static magnitudeType real(T a)
std::string robustnessEnumToString(const ERobustness x)
Convert the given ERobustness enum value to a string.
ERobustness robustnessStringToEnum(const std::string &x)
Convert the given robustness string value to an ERobustness enum.
void GEMM(ETransp transa, ETransp transb, const OrdinalType &m, const OrdinalType &n, const OrdinalType &k, const alpha_type alpha, const A_type *A, const OrdinalType &lda, const B_type *B, const OrdinalType &ldb, const beta_type beta, ScalarType *C, const OrdinalType &ldc) const
bool testGivensRotations(std::ostream &out)
Test Givens rotations.
std::pair< int, bool > solveUpperTriangularSystem(Teuchos::ESide side, mat_type &X, const mat_type &R, const mat_type &B, const ERobustness robustness)
Solve the given square upper triangular linear system(s).
ScalarTraits< ScalarType >::magnitudeType normFrobenius() const
Methods for solving GMRES' projected least-squares problem.
void zeroOutStrictLowerTriangle(mat_type &A) const
Zero out everything below the diagonal of A.
ProjectedLeastSquaresProblem(const int maxNumIterations)
Constructor.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
magnitude_type updateColumns(ProjectedLeastSquaresProblem< Scalar > &problem, const int startCol, const int endCol)
Update columns [startCol,endCol] of the projected least-squares problem.
Teuchos::SerialDenseMatrix< int, Scalar > H
The upper Hessenberg matrix from GMRES.
"Container" for the GMRES projected least-squares problem.
int putScalar(const ScalarType value=Teuchos::ScalarTraits< ScalarType >::zero())
void reset(const typename Teuchos::ScalarTraits< Scalar >::magnitudeType beta)
Reset the projected least-squares problem.
std::pair< int, bool > solveUpperTriangularSystemInPlace(Teuchos::ESide side, mat_type &X, const mat_type &R)
Solve square upper triangular linear system(s) in place.
Scalar scalar_type
The template parameter of this class.
void matScale(mat_type &A, const scalar_type &alpha) const
A := alpha * A.
void axpy(mat_type &Y, const scalar_type &alpha, const mat_type &X) const
Y := Y + alpha * X.
static magnitudeType imag(T a)
static bool isnaninf(const T &x)
Teuchos::ScalarTraits< Scalar >::magnitudeType magnitude_type
The type of the magnitude of scalar_type values.
Teuchos::RCP< Teuchos::ParameterEntryValidator > robustnessValidator()
Make a ParameterList validator for ERobustness.
void conjugateTranspose(mat_type &A_star, const mat_type &A) const
A_star := (conjugate) transpose of A.
static magnitudeType magnitude(T a)
OrdinalType numCols() const
Teuchos::ScalarTraits< Scalar >::magnitudeType magnitude_type
The type of the magnitude of a scalar_type value.
Teuchos::SerialDenseMatrix< int, Scalar > mat_type
The type of a dense matrix (or vector) of scalar_type.
void solve(ProjectedLeastSquaresProblem< Scalar > &problem, const int curCol)
Solve the projected least-squares problem.
bool testUpdateColumn(std::ostream &out, const int numCols, const bool testBlockGivens=false, const bool extraVerbose=false)
Test update and solve using Givens rotations.
int reshape(OrdinalType numRows, OrdinalType numCols)
Teuchos::ScalarTraits< Scalar >::magnitudeType magnitude_type
The type of the magnitude of a scalar_type value.
Teuchos::Array< Scalar > theSines
Array of sines from the computed Givens rotations.
Scalar scalar_type
The type of the entries in the projected least-squares problem.
std::pair< bool, std::pair< magnitude_type, magnitude_type > > isUpperHessenberg(const mat_type &A) const
Is the matrix A upper Hessenberg?
void matMatMult(const scalar_type &beta, mat_type &C, const scalar_type &alpha, const mat_type &A, const mat_type &B) const
C := beta*C + alpha*A*B.
void matAdd(mat_type &A, const mat_type &B) const
A := A + B.
Low-level operations on non-distributed dense matrices.
void reallocateAndReset(const typename Teuchos::ScalarTraits< Scalar >::magnitudeType beta, const int maxNumIterations)
(Re)allocate and reset the projected least-squares problem.
ERobustness
Robustness level of projected least-squares solver operations.
bool testTriangularSolves(std::ostream &out, const int testProblemSize, const ERobustness robustness, const bool verbose=false)
Test upper triangular solves.
static const bool isComplex
void ensureUpperHessenberg(const mat_type &A, const char *const matrixName) const
Throw an exception if A is not (strictly) upper Hessenberg.
std::pair< bool, std::pair< magnitude_type, magnitude_type > > isUpperTriangular(const mat_type &A) const
Is the matrix A upper triangular / trapezoidal?
std::pair< int, bool > solveUpperTriangularSystem(Teuchos::ESide side, mat_type &X, const mat_type &R, const mat_type &B)
Solve the given square upper triangular linear system(s).
void partition(Teuchos::RCP< mat_type > &A_11, Teuchos::RCP< mat_type > &A_21, Teuchos::RCP< mat_type > &A_12, Teuchos::RCP< mat_type > &A_22, mat_type &A, const int numRows1, const int numRows2, const int numCols1, const int numCols2)
A -> [A_11, A_21, A_12, A_22].
Belos header file which uses auto-configuration information to include necessary C++ headers...
void rightUpperTriSolve(mat_type &B, const mat_type &R) const
In Matlab notation: B = B / R, where R is upper triangular.
void ensureUpperTriangular(const mat_type &A, const char *const matrixName) const
Throw an exception if A is not upper triangular / trapezoidal.
Teuchos::SerialDenseMatrix< int, Scalar > R
Upper triangular factor from the QR factorization of H.
SerialDenseMatrix< OrdinalType, ScalarType > & assign(const SerialDenseMatrix< OrdinalType, ScalarType > &Source)
void ensureEqualDimensions(const mat_type &A, const char *const matrixName, const int numRows, const int numCols) const
Ensure that the matrix A is exactly numRows by numCols.
OrdinalType stride() const
magnitude_type updateColumn(ProjectedLeastSquaresProblem< Scalar > &problem, const int curCol)
Update column curCol of the projected least-squares problem.
OrdinalType numRows() const
Scalar scalar_type
The template parameter of this class.
Teuchos::SerialDenseMatrix< int, Scalar > mat_type
The type of a dense matrix (or vector) of scalar_type.
void ensureUpperHessenberg(const mat_type &A, const char *const matrixName, const magnitude_type relativeTolerance) const
Throw an exception if A is not "approximately" upper Hessenberg.