/// <summary> /// Return the component of the vector perpendicular to all the vectors in the vector space spanned by vlist /// </summary> /// <param name="vlist">a set of vectors perpendicular to each other</param> /// <returns>the vector perpendicular to all the vectors in the vector space spanned by vlist</returns> public IVector ProjectOrthogonal(IEnumerable <IVector> vlist) { IVector b = this; foreach (IVector v in vlist) { b = b.Minus(b.ProjectAlong(v)); } return(b); }
public IVector ProjectOrthogonal(List <IVector> vlist, out Dictionary <int, double> alpha) { IVector b = this; double sigma; alpha = new Dictionary <int, double>(); alpha[vlist.Count] = 1; for (int i = 0; i < vlist.Count; ++i) { IVector v = vlist[i]; IVector b_along = b.ProjectAlong(v, out sigma); b = b.Minus(b_along); alpha[i] = sigma; } return(b); }
public IMatrix Minus(IMatrix rhs) { Debug.Assert(RowCount == rhs.RowCount); Debug.Assert(ColCount == rhs.ColCount); HashSet <int> allRows = new HashSet <int>(); foreach (int k in mInternal.Keys) { allRows.Add(k); } foreach (int k in rhs.RowKeys) { allRows.Add(k); } IMatrix result = this.Zero(mRowKeys, mColKeys, mDefaultVal); foreach (int k in allRows) { IVector row1 = this[k]; IVector row2 = rhs[k]; if (row1 == null) { result[k] = row2.Multiply(-1); } else if (row2 == null) { result[k] = row1.Clone(); } else { result[k] = row1.Minus(row2); } } return(result); }
/// <summary> /// 采用观测值和近似值初始化。 /// </summary> /// <param name="Observation">观测值</param> /// <param name="Approx">近似值</param> public AdjustVector(IVector Observation, IVector Approx) : base((Observation.Minus(Approx))) { this.Observation = Observation; this.Approx = Approx; }
/// <summary> /// Get the point in the vector space which is closest to b /// </summary> /// <param name="b">A vector which may be outside the vector space</param> /// <returns>Return point in the vector space closest to b</returns> public IVector GetClosedPoint(IVector b) { IVector b_orth = b.ProjectOrthogonal(mOrthogonalBasis); return(b.Minus(b_orth)); }
public override double[] Solve() { int m = A.RowCount; int n = A.ColCount; Debug.Assert(m >= n); IVector t = new SparseVector(n); for (int i = 0; i < m; ++i) { t[i] = 0; } IVector s = new SparseVector(n); IVector sy = new SparseVector(n); for (int i = 0; i < n; ++i) { s[i] = 0; } IVector s_old = s; IMatrix U; // U is a m x m orthogonal matrix IMatrix Vt; // V is a n x n orthogonal matrix IMatrix Sigma; // Sigma is a m x n diagonal matrix with non-negative real numbers on its diagonal SVD.Factorize(A, out U, out Sigma, out Vt); // A is a m x n matrix IMatrix Ut = U.Transpose(); IMatrix V = Vt.Transpose(); //SigmaInv is obtained by replacing every non-zero diagonal entry by its reciprocal and transposing the resulting matrix IMatrix SigmaInv = new SparseMatrix(m, n); for (int i = 0; i < n; ++i) // assuming m >= n { double sigma_i = Sigma[i, i]; if (sigma_i < epsilon) // model matrix A is rank deficient { throw new Exception("Near rank-deficient model matrix"); } SigmaInv[i, i] = 1.0 / sigma_i; } SigmaInv = SigmaInv.Transpose(); double[] W = new double[m]; for (int j = 0; j < mMaxIters; ++j) { Console.WriteLine("j: {0}", j); IVector z = new SparseVector(m); double[] g = new double[m]; double[] gprime = new double[m]; for (int k = 0; k < m; ++k) { g[k] = mLinkFunc.GetInvLink(t[k]); gprime[k] = mLinkFunc.GetInvLinkDerivative(t[k]); z[k] = t[k] + (b[k] - g[k]) / gprime[k]; } int tiny_weight_count = 0; for (int k = 0; k < m; ++k) { double w_kk = gprime[k] * gprime[k] / GetVariance(g[k]); W[k] = w_kk; if (w_kk < double.Epsilon * 2) { tiny_weight_count++; } } if (tiny_weight_count > 0) { Console.WriteLine("Warning: tiny weights encountered, (diag(W)) is too small"); } s_old = s; IMatrix UtW = new SparseMatrix(m, m); for (int k = 0; k < m; ++k) { for (int k2 = 0; k2 < m; ++k2) { UtW[k, k2] = Ut[k, k2] * W[k]; } } IMatrix UtWU = UtW.Multiply(U); // m x m positive definite matrix IMatrix L; // m x m lower triangular matrix Cholesky.Factorize(UtWU, out L); IMatrix Lt = L.Transpose(); // m x m upper triangular matrix IVector UtWz = UtW.Multiply(z); // m x 1 vector // (Ut * W * U) * s = Ut * W * z // L * Lt * s = Ut * W * z (Cholesky factorization on Ut * W * U) // L * sy = Ut * W * z, Lt * s = sy s = new SparseVector(n); for (int i = 0; i < n; ++i) { s[i] = 0; sy[i] = 0; } // forward solve sy for L * sy = Ut * W * z for (int i = 0; i < n; ++i) // since m >= n { double cross_prod = 0; for (int k = 0; k < i; ++k) { cross_prod += L[i, k] * sy[k]; } sy[i] = (UtWz[i] - cross_prod) / L[i, i]; } // backward solve s for Lt * s = sy for (int i = n - 1; i >= 0; --i) { double cross_prod = 0; for (int k = i + 1; k < n; ++k) { cross_prod += Lt[i, k] * s[k]; } s[i] = (sy[i] - cross_prod) / Lt[i, i]; } t = U.Multiply(s); if ((s_old.Minus(s)).Norm(2) < mTol) { break; } } IVector x = V.Multiply(SigmaInv).Multiply(Ut).Multiply(t); mX = new double[n]; for (int i = 0; i < n; ++i) { mX[i] = x[i]; } UpdateStatistics(W); return X; }
public override double[] Solve() { int m = A.RowCount; int n = A.ColCount; Debug.Assert(m >= n); IVector s = new SparseVector(n); IVector sy = new SparseVector(n); for (int i = 0; i < n; ++i) { s[i] = 0; } IVector t = new SparseVector(m); for (int i = 0; i < m; ++i) { t[i] = 0; } double[] g = new double[m]; double[] gprime = new double[m]; IMatrix Q; IMatrix R; QR.Factorize(A, out Q, out R); // A is m x n, Q is m x n orthogonal matrix, R is n x n (R will be upper triangular matrix if m == n) IMatrix Qt = Q.Transpose(); IVector W = null; for (int j = 0; j < mMaxIters; ++j) { IVector z = new SparseVector(m); for (int k = 0; k < m; ++k) { g[k] = mLinkFunc.GetInvLink(t[k]); gprime[k] = mLinkFunc.GetInvLinkDerivative(t[k]); z[k] = t[k] + (b[k] - g[k]) / gprime[k]; } W = new SparseVector(m); double w_kk_min = double.MaxValue; for (int k = 0; k < m; ++k) { double g_variance = GetVariance(g[k]); double w_kk = gprime[k] * gprime[k] / (g_variance); W[k] = w_kk; w_kk_min = System.Math.Min(w_kk, w_kk_min); } if (w_kk_min < System.Math.Sqrt(double.Epsilon)) { Console.WriteLine("Warning: Tiny weights encountered, min(diag(W)) is too small"); } IVector s_old = s; IMatrix WQ = new SparseMatrix(m, n); // W * Q IVector Wz = new SparseVector(m); // W * z for (int k = 0; k < m; k++) { Wz[k] = z[k] * W[k]; for (int k2 = 0; k2 < m; ++k2) { WQ[k, k2] = Q[k, k2] * W[k]; } } IMatrix QtWQ = Qt.Multiply(WQ); // a n x n positive definite matrix, therefore can apply Cholesky IVector QtWz = Qt.Multiply(Wz); IMatrix L; Cholesky.Factorize(QtWQ, out L); IMatrix Lt = L.Transpose(); // (Qt * W * Q) * s = Qt * W * z; // L * Lt * s = Qt * W * z (Cholesky factorization on Qt * W * Q) // L * sy = Qt * W * z, Lt * s = sy // Now forward solve sy for L * sy = Qt * W * z // Now backward solve s for Lt * s = sy s = new SparseVector(n); for (int i = 0; i < n; ++i) { s[i] = 0; sy[i] = 0; } //forward solve sy for L * sy = Qt * W * z //Console.WriteLine(L); for (int i = 0; i < n; ++i) { double cross_prod = 0; for (int k = 0; k < i; ++k) { cross_prod += L[i, k] * sy[k]; } sy[i] = (QtWz[i] - cross_prod) / L[i, i]; } //backward solve s for U * s = sy for (int i = n - 1; i >= 0; --i) { double cross_prod = 0; for (int k = i + 1; k < n; ++k) { cross_prod += Lt[i, k] * s[k]; } s[i] = (sy[i] - cross_prod) / Lt[i, i]; } t = Q.Multiply(s); double cost = (s_old.Minus(s)).Norm(2); if (j % 100 == 0) { Console.WriteLine("Iteration: {0}, Cost: {1}", j, cost); } if (cost < mTol) { break; } } mX = new double[n]; //backsolve x for R * x = Qt * t IVector c = Qt.Multiply(t); for (int i = n - 1; i >= 0; --i) // since m >= n { double cross_prod = 0; for (int j = i + 1; j < n; ++j) { cross_prod += R[i, j] * mX[j]; } mX[i] = (c[i] - cross_prod) / R[i, i]; } UpdateStatistics(W); return(X); }