947 typedef Teuchos::SerialDenseMatrix<int,Scalar>
mat_type;
950 typedef Teuchos::ScalarTraits<scalar_type> STS;
951 typedef Teuchos::ScalarTraits<magnitude_type> STM;
952 typedef Teuchos::BLAS<int, scalar_type> blas_type;
953 typedef Teuchos::LAPACK<int, scalar_type> lapack_type;
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>
1148 using Teuchos::Array;
1149 using Teuchos::Copy;
1150 using Teuchos::LEFT_SIDE;
1151 using Teuchos::RIGHT_SIDE;
1154 const int M = R.numRows();
1155 const int N = R.numCols();
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.");
1208 blas.TRSM(
side, Teuchos::UPPER_TRI, Teuchos::NO_TRANS,
1209 Teuchos::NON_UNIT_DIAG,
X.numRows(),
X.numCols(),
1210 STS::one(), R.values(), R.stride(),
1211 X.values(),
X.stride());
1219 blas.TRSM(
side, Teuchos::UPPER_TRI, Teuchos::NO_TRANS,
1220 Teuchos::NON_UNIT_DIAG,
X.numRows(),
X.numCols(),
1221 STS::one(), R.values(), R.stride(),
1222 X.values(),
X.stride());
1226 if (
ops.infNaNCount (
X,
false) != 0) {
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;
1247 ops.zeroOutStrictLowerTriangle (
R_copy);
1262 ops.conjugateTransposeOfUpperTriangular (
R_star, R);
1276 "Should never get here! Invalid robustness value "
1277 <<
robustness <<
". Please report this bug to the "
1278 "Belos developers.");
1298 out <<
"Testing Givens rotations:" << endl;
1300 Scalar y = STS::random();
1301 out <<
" x = " <<
x <<
", y = " << y << endl;
1306 out <<
"-- After computing rotation:" << endl;
1308 out <<
"---- x = " <<
x <<
", y = " << y
1309 <<
", result = " << result << endl;
1312 out <<
"-- After applying rotation:" << endl;
1314 out <<
"---- x = " <<
x <<
", y = " << y << endl;
1317 if (STS::magnitude(y) > 2*STS::eps())
1358 using Teuchos::Array;
1362 "numCols = " <<
numCols <<
" <= 0.");
1386 makeRandomProblem (H, z);
1408 theCosines, theSines,
curCol);
1481 for (
int i = 0;
i <=
j; ++
i) {
1510 out <<
"||H y_givens - z||_2 / ||H||_F = "
1513 out <<
"||H y_blockGivens - z||_2 / ||H||_F = "
1516 out <<
"||H y_lapack - z||_2 / ||H||_F = "
1519 out <<
"||y_givens - y_lapack||_2 / ||y_lapack||_2 = "
1522 out <<
"||y_blockGivens - y_lapack||_2 / ||y_lapack||_2 = "
1526 out <<
"Least-squares condition number = "
1599 using Teuchos::LEFT_SIDE;
1600 using Teuchos::RIGHT_SIDE;
1602 typedef Teuchos::SerialDenseMatrix<int, scalar_type>
mat_type;
1607 verboseOut <<
"Testing upper triangular solves" << endl;
1611 verboseOut <<
"-- Generating test matrix" << endl;
1615 for (
int j = 0;
j <
N; ++
j) {
1616 for (
int i = 0;
i <=
j; ++
i) {
1617 R(
i,
j) = STS::random ();
1644 verboseOut <<
"---- ||R*X - B||_F = " <<
Resid.normFrobenius() << endl;
1645 verboseOut <<
"---- ||R||_F ||X||_F + ||B||_F = "
1670 verboseOut <<
"---- ||Y||_F ||R||_F + ||B^*||_F = "
1684 std::ostream& warn_;
1707 using Teuchos::Array;
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());
1742 if (STS::isComplex) {
1743 rwork.resize (std::max (1, 5 *
N));
1748 Scalar lworkScalar = STS::one();
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);
1754 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1755 "_GELSS workspace query returned INFO = "
1756 << info <<
" != 0.");
1757 const int lwork =
static_cast<int> (STS::real (lworkScalar));
1758 TEUCHOS_TEST_FOR_EXCEPTION(lwork < 0, std::logic_error,
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);
1768 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::runtime_error,
1769 "_GELSS returned INFO = " << info <<
" != 0.");
1785 const int numRows = curCol + 2;
1790 const mat_type R_view (Teuchos::View, R, numRows-1, numRows-1);
1791 const mat_type z_view (Teuchos::View, z, numRows-1, z.numCols());
1792 mat_type y_view (Teuchos::View, y, numRows-1, y.numCols());
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) {
1811 H(i,j) = STS::zero();
1822 const int numTrials = 1000;
1824 for (
int trial = 0; trial < numTrials && z_init == STM::zero(); ++trial) {
1825 z_init = STM::random();
1827 TEUCHOS_TEST_FOR_EXCEPTION(z_init == STM::zero(), std::runtime_error,
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);
1875 Teuchos::ArrayView<magnitude_type> sigmas)
1877 using Teuchos::Array;
1878 using Teuchos::ArrayView;
1880 const int numRows = A.numRows();
1881 const int numCols = A.numCols();
1882 TEUCHOS_TEST_FOR_EXCEPTION(sigmas.size() < std::min (numRows, 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);
1899 Scalar lworkScalar = STS::zero();
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 <<
".");
1933 std::pair<magnitude_type, magnitude_type>
1934 extremeSingularValues (
const mat_type& A)
1936 using Teuchos::Array;
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,
1962 const std::pair<magnitude_type, magnitude_type> sigmaMaxMin =
1963 extremeSingularValues (A);
1967 TEUCHOS_TEST_FOR_EXCEPTION(sigmaMaxMin.second == STM::zero(), std::runtime_error,
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();
1992 STM::zero() : STM::squareroot (1 - sinTheta * sinTheta);
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;
2014 ops.matMatMult (STS::one(), r, -STS::one(), A, x);
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);
2038 return x_diff.normFrobenius() /
2039 (scalingFactor == STM::zero() ? STM::one() : scalingFactor);
2089 updateColumnGivens (
const mat_type& H,
2093 Teuchos::ArrayView<scalar_type> theCosines,
2094 Teuchos::ArrayView<scalar_type> theSines,
2100 const int numRows = curCol + 2;
2101 const int LDR = R.stride();
2102 const bool extraDebug =
false;
2105 cerr <<
"updateColumnGivens: curCol = " << curCol << endl;
2111 const mat_type H_col (Teuchos::View, H, numRows, 1, 0, curCol);
2115 mat_type R_col (Teuchos::View, R, numRows, 1, 0, curCol);
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;
2162 R_col(curCol+1, 0) = STS::zero();
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);
2189 return STS::magnitude( z(numRows-1, 0) );
2232 const int numRows = curCol + 2;
2233 const int numCols = curCol + 1;
2234 const int LDR = R.stride();
2237 const mat_type H_view (Teuchos::View, H, numRows, numCols);
2238 mat_type R_view (Teuchos::View, R, numRows, numCols);
2239 R_view.assign (H_view);
2243 mat_type y_view (Teuchos::View, y, numRows, y.numCols());
2244 mat_type z_view (Teuchos::View, z, numRows, y.numCols());
2245 y_view.assign (z_view);
2249 Scalar lworkScalar = STS::zero();
2251 lapack.GELS (
'N', numRows, numCols, y_view.numCols(),
2252 NULL, LDR, NULL, y_view.stride(),
2253 &lworkScalar, -1, &info);
2254 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
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" :
"") <<
".");
2260 TEUCHOS_TEST_FOR_EXCEPTION(STS::real(lworkScalar) < STM::zero(),
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.");
2266 TEUCHOS_TEST_FOR_EXCEPTION(STS::isComplex && STS::imag(lworkScalar) != STM::zero(),
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)));
2280 Teuchos::Array<Scalar> work (lwork);
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),
2291 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
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" :
"") <<
".");
2300 return STS::magnitude( y_view(numRows-1, 0) );
2314 updateColumnsGivens (
const mat_type& H,
2318 Teuchos::ArrayView<scalar_type> theCosines,
2319 Teuchos::ArrayView<scalar_type> theSines,
2323 TEUCHOS_TEST_FOR_EXCEPTION(startCol > endCol, std::invalid_argument,
2324 "updateColumnGivens: startCol = " << startCol
2325 <<
" > endCol = " << endCol <<
".");
2328 for (
int curCol = startCol; curCol <= endCol; ++curCol) {
2329 lastResult = updateColumnGivens (H, R, y, z, theCosines, theSines, curCol);
2347 updateColumnsGivensBlock (
const mat_type& H,
2351 Teuchos::ArrayView<scalar_type> theCosines,
2352 Teuchos::ArrayView<scalar_type> theSines,
2356 const int numRows = endCol + 2;
2357 const int numColsToUpdate = endCol - startCol + 1;
2358 const int LDR = R.stride();
2363 const mat_type H_view (Teuchos::View, H, numRows, numColsToUpdate, 0, startCol);
2364 mat_type R_view (Teuchos::View, R, numRows, numColsToUpdate, 0, startCol);
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;
2399 R(curCol+1, curCol) = STS::zero();
2406 const int LDZ = z.stride();
2407 blas.ROT (z.numCols(),
2408 &z(curCol,0), LDZ, &z(curCol+1,0), LDZ,
2409 &theCosine, &theSine);
2415 return STS::magnitude( z(numRows-1, 0) );