/// <summary> /// Returns a deep-copy clone of the vector. /// </summary> /// <returns>A deep-copy clone of the vector.</returns> public Vector <T> Clone() { var result = Build.SameAs(this); Storage.CopyToUnchecked(result.Storage, ExistingData.AssumeZeros); return(result); }
/// <summary> /// Solves a system of linear equations, <b>Ax = b</b>, with A LU factorized. /// </summary> /// <param name="input">The right hand side vector, <b>b</b>.</param> /// <returns>The left hand side <see cref="Vector{T}"/>, <b>x</b>.</returns> public virtual Vector <T> Solve(Vector <T> input) { var x = v_builder.SameAs(input, input.Count); Solve(input, x); return(x); }
/// <summary> /// Solves a system of linear equations, <b>Ax = b</b>, with A EVD factorized. /// </summary> /// <param name="input">The right hand side vector, <b>b</b>.</param> /// <returns>The left hand side <see cref="Vector{T}"/>, <b>x</b>.</returns> public virtual Vector <T> Solve(Vector <T> input) { var x = v_builder.SameAs(EigenVectors, EigenVectors.ColumnCount); Solve(input, x); return(x); }
/// <summary> /// Solves a system of linear equations, <b>Ax = b</b>, with A SVD factorized. /// </summary> /// <param name="input">The right hand side vector, <b>b</b>.</param> /// <returns>The left hand side <see cref="Vector{T}"/>, <b>x</b>.</returns> public virtual Vector <T> Solve(Vector <T> input) { if (!VectorsComputed) { throw new InvalidOperationException("Resources.SingularVectorsNotComputed"); } var x = v_builder.SameAs(U, VT.ColumnCount); Solve(input, x); return(x); }
public static Vector <T> SameAs <T>(this VectorBuilder <T> builder, Vector <T> example, Func <T> f) where T : struct, global::System.IEquatable <T>, global::System.IFormattable { Contract.Requires(builder != null); Contract.Requires(example != null); Contract.Requires(f != null); var result = builder.SameAs(example); Contract.Assume(result != null); result.MapInplace(x => f()); return(result); }
public static UserSvd Create(Matrix <double> matrix, bool computeVectors) { var nm = Math.Min(matrix.RowCount + 1, matrix.ColumnCount); var matrixCopy = matrix.Clone(); var s = v_builder.SameAs(matrixCopy, nm); var u = m_builder.SameAs(matrixCopy, matrixCopy.RowCount, matrixCopy.RowCount, fullyMutable: true); var vt = m_builder.SameAs(matrixCopy, matrixCopy.ColumnCount, matrixCopy.ColumnCount, fullyMutable: true); const int maxiter = 1000; var e = new double[matrixCopy.ColumnCount]; var work = new double[matrixCopy.RowCount]; int i, j; int l, lp1; double t; var ncu = matrixCopy.RowCount; // Reduce matrixCopy to bidiagonal form, storing the diagonal elements // In s and the super-diagonal elements in e. var nct = Math.Min(matrixCopy.RowCount - 1, matrixCopy.ColumnCount); var nrt = Math.Max(0, Math.Min(matrixCopy.ColumnCount - 2, matrixCopy.RowCount)); var lu = Math.Max(nct, nrt); for (l = 0; l < lu; l++) { lp1 = l + 1; if (l < nct) { // Compute the transformation for the l-th column and place the l-th diagonal in VectorS[l]. var xnorm = Dnrm2Column(matrixCopy, matrixCopy.RowCount, l, l); s[l] = xnorm; if (s[l] != 0.0) { if (matrixCopy.At(l, l) != 0.0) { s[l] = Dsign(s[l], matrixCopy.At(l, l)); } DscalColumn(matrixCopy, matrixCopy.RowCount, l, l, 1.0 / s[l]); matrixCopy.At(l, l, (1.0 + matrixCopy.At(l, l))); } s[l] = -s[l]; } for (j = lp1; j < matrixCopy.ColumnCount; j++) { if (l < nct) { if (s[l] != 0.0) { // Apply the transformation. t = -Ddot(matrixCopy, matrixCopy.RowCount, l, j, l) / matrixCopy.At(l, l); for (var ii = l; ii < matrixCopy.RowCount; ii++) { matrixCopy.At(ii, j, matrixCopy.At(ii, j) + (t * matrixCopy.At(ii, l))); } } } // Place the l-th row of matrixCopy into e for the // Subsequent calculation of the row transformation. e[j] = matrixCopy.At(l, j); } if (computeVectors && l < nct) { // Place the transformation in u for subsequent back multiplication. for (i = l; i < matrixCopy.RowCount; i++) { u.At(i, l, matrixCopy.At(i, l)); } } if (l >= nrt) { continue; } // Compute the l-th row transformation and place the l-th super-diagonal in e(l). var enorm = Dnrm2Vector(e, lp1); e[l] = enorm; if (e[l] != 0.0) { if (e[lp1] != 0.0) { e[l] = Dsign(e[l], e[lp1]); } DscalVector(e, lp1, 1.0 / e[l]); e[lp1] = 1.0 + e[lp1]; } e[l] = -e[l]; if (lp1 < matrixCopy.RowCount && e[l] != 0.0) { // Apply the transformation. for (i = lp1; i < matrixCopy.RowCount; i++) { work[i] = 0.0; } for (j = lp1; j < matrixCopy.ColumnCount; j++) { for (var ii = lp1; ii < matrixCopy.RowCount; ii++) { work[ii] += e[j] * matrixCopy.At(ii, j); } } for (j = lp1; j < matrixCopy.ColumnCount; j++) { var ww = -e[j] / e[lp1]; for (var ii = lp1; ii < matrixCopy.RowCount; ii++) { matrixCopy.At(ii, j, matrixCopy.At(ii, j) + (ww * work[ii])); } } } if (computeVectors) { // Place the transformation in v for subsequent back multiplication. for (i = lp1; i < matrixCopy.ColumnCount; i++) { vt.At(i, l, e[i]); } } } // Set up the final bidiagonal matrixCopy or order m. var m = Math.Min(matrixCopy.ColumnCount, matrixCopy.RowCount + 1); var nctp1 = nct + 1; var nrtp1 = nrt + 1; if (nct < matrixCopy.ColumnCount) { s[nctp1 - 1] = matrixCopy.At((nctp1 - 1), (nctp1 - 1)); } if (matrixCopy.RowCount < m) { s[m - 1] = 0.0; } if (nrtp1 < m) { e[nrtp1 - 1] = matrixCopy.At((nrtp1 - 1), (m - 1)); } e[m - 1] = 0.0; // If required, generate u. if (computeVectors) { for (j = nctp1 - 1; j < ncu; j++) { for (i = 0; i < matrixCopy.RowCount; i++) { u.At(i, j, 0.0); } u.At(j, j, 1.0); } for (l = nct - 1; l >= 0; l--) { if (s[l] != 0.0) { for (j = l + 1; j < ncu; j++) { t = -Ddot(u, matrixCopy.RowCount, l, j, l) / u.At(l, l); for (var ii = l; ii < matrixCopy.RowCount; ii++) { u.At(ii, j, u.At(ii, j) + (t * u.At(ii, l))); } } DscalColumn(u, matrixCopy.RowCount, l, l, -1.0); u.At(l, l, 1.0 + u.At(l, l)); for (i = 0; i < l; i++) { u.At(i, l, 0.0); } } else { for (i = 0; i < matrixCopy.RowCount; i++) { u.At(i, l, 0.0); } u.At(l, l, 1.0); } } } // If it is required, generate v. if (computeVectors) { for (l = matrixCopy.ColumnCount - 1; l >= 0; l--) { lp1 = l + 1; if (l < nrt) { if (e[l] != 0.0) { for (j = lp1; j < matrixCopy.ColumnCount; j++) { t = -Ddot(vt, matrixCopy.ColumnCount, l, j, lp1) / vt.At(lp1, l); for (var ii = l; ii < matrixCopy.ColumnCount; ii++) { vt.At(ii, j, vt.At(ii, j) + (t * vt.At(ii, l))); } } } } for (i = 0; i < matrixCopy.ColumnCount; i++) { vt.At(i, l, 0.0); } vt.At(l, l, 1.0); } } // Transform s and e so that they are double . for (i = 0; i < m; i++) { double r; if (s[i] != 0.0) { t = s[i]; r = s[i] / t; s[i] = t; if (i < m - 1) { e[i] = e[i] / r; } if (computeVectors) { DscalColumn(u, matrixCopy.RowCount, i, 0, r); } } // Exit if (i == m - 1) { break; } if (e[i] != 0.0) { t = e[i]; r = t / e[i]; e[i] = t; s[i + 1] = s[i + 1] * r; if (computeVectors) { DscalColumn(vt, matrixCopy.ColumnCount, i + 1, 0, r); } } } // Main iteration loop for the singular values. var mn = m; var iter = 0; bool AlmostEquals(double val1, double val2) { if (Math.Abs(val1 - val2) < 1e-8) { return(true); } return(false); } while (m > 0) { // Quit if all the singular values have been found. If too many iterations have been performed, // throw exception that Convergence Failed if (iter >= maxiter) { throw new ArgumentException("NonConvergenceException()");; } // This section of the program inspects for negligible elements in the s and e arrays. On // completion the variables case and l are set as follows. // Case = 1 if VectorS[m] and e[l-1] are negligible and l < m // Case = 2 if VectorS[l] is negligible and l < m // Case = 3 if e[l-1] is negligible, l < m, and VectorS[l, ..., VectorS[m] are not negligible (qr step). // Case = 4 if e[m-1] is negligible (convergence). double ztest; double test; for (l = m - 2; l >= 0; l--) { test = Math.Abs(s[l]) + Math.Abs(s[l + 1]); ztest = test + Math.Abs(e[l]); if (AlmostEquals(test, ztest)) { e[l] = 0.0; break; } } int kase; if (l == m - 2) { kase = 4; } else { int ls; for (ls = m - 1; ls > l; ls--) { test = 0.0; if (ls != m - 1) { test = test + Math.Abs(e[ls]); } if (ls != l + 1) { test = test + Math.Abs(e[ls - 1]); } ztest = test + Math.Abs(s[ls]); if (AlmostEquals(test, ztest)) { s[ls] = 0.0; break; } } if (ls == l) { kase = 3; } else if (ls == m - 1) { kase = 1; } else { kase = 2; l = ls; } } l = l + 1; // Perform the task indicated by case. int k; double f; double sn; double cs; double t1; switch (kase) { // Deflate negligible VectorS[m]. case 1: f = e[m - 2]; e[m - 2] = 0.0; for (var kk = l; kk < m - 1; kk++) { k = m - 2 - kk + l; t1 = s[k]; Drotg(ref t1, ref f, out cs, out sn); s[k] = t1; if (k != l) { f = -sn * e[k - 1]; e[k - 1] = cs * e[k - 1]; } if (computeVectors) { Drot(vt, matrixCopy.ColumnCount, k, m - 1, cs, sn); } } break; // Split at negligible VectorS[l]. case 2: f = e[l - 1]; e[l - 1] = 0.0; for (k = l; k < m; k++) { t1 = s[k]; Drotg(ref t1, ref f, out cs, out sn); s[k] = t1; f = -sn * e[k]; e[k] = cs * e[k]; if (computeVectors) { Drot(u, matrixCopy.RowCount, k, l - 1, cs, sn); } } break; // Perform one qr step. case 3: // Calculate the shift. var scale = 0.0; scale = Math.Max(scale, Math.Abs(s[m - 1])); scale = Math.Max(scale, Math.Abs(s[m - 2])); scale = Math.Max(scale, Math.Abs(e[m - 2])); scale = Math.Max(scale, Math.Abs(s[l])); scale = Math.Max(scale, Math.Abs(e[l])); var sm = s[m - 1] / scale; var smm1 = s[m - 2] / scale; var emm1 = e[m - 2] / scale; var sl = s[l] / scale; var el = e[l] / scale; var b = (((smm1 + sm) * (smm1 - sm)) + (emm1 * emm1)) / 2.0; var c = (sm * emm1) * (sm * emm1); var shift = 0.0; if (b != 0.0 || c != 0.0) { shift = Math.Sqrt((b * b) + c); if (b < 0.0) { shift = -shift; } shift = c / (b + shift); } f = ((sl + sm) * (sl - sm)) + shift; var g = sl * el; // Chase zeros. for (k = l; k < m - 1; k++) { Drotg(ref f, ref g, out cs, out sn); if (k != l) { e[k - 1] = f; } f = (cs * s[k]) + (sn * e[k]); e[k] = (cs * e[k]) - (sn * s[k]); g = sn * s[k + 1]; s[k + 1] = cs * s[k + 1]; if (computeVectors) { Drot(vt, matrixCopy.ColumnCount, k, k + 1, cs, sn); } Drotg(ref f, ref g, out cs, out sn); s[k] = f; f = (cs * e[k]) + (sn * s[k + 1]); s[k + 1] = (-sn * e[k]) + (cs * s[k + 1]); g = sn * e[k + 1]; e[k + 1] = cs * e[k + 1]; if (computeVectors && k < matrixCopy.RowCount) { Drot(u, matrixCopy.RowCount, k, k + 1, cs, sn); } } e[m - 2] = f; iter = iter + 1; break; // Convergence. case 4: // Make the singular value positive if (s[l] < 0.0) { s[l] = -s[l]; if (computeVectors) { DscalColumn(vt, matrixCopy.ColumnCount, l, 0, -1.0); } } // Order the singular value. while (l != mn - 1) { if (s[l] >= s[l + 1]) { break; } t = s[l]; s[l] = s[l + 1]; s[l + 1] = t; if (computeVectors && l < matrixCopy.ColumnCount) { Dswap(vt, matrixCopy.ColumnCount, l, l + 1); } if (computeVectors && l < matrixCopy.RowCount) { Dswap(u, matrixCopy.RowCount, l, l + 1); } l = l + 1; } iter = 0; m = m - 1; break; } } if (computeVectors) { vt = vt.Transpose(); } // Adjust the size of s if rows < columns. We are using ported copy of linpack's svd code and it uses // a singular vector of length mRows+1 when mRows < mColumns. The last element is not used and needs to be removed. // we should port lapack's svd routine to remove this problem. if (matrixCopy.RowCount < matrixCopy.ColumnCount) { nm--; var tmp = v_builder.SameAs(matrixCopy, nm); for (i = 0; i < nm; i++) { tmp[i] = s[i]; } s = tmp; } return(new UserSvd(s, u, vt, computeVectors)); }