/// <summary> /// Outer product of two vectors; Sets <i>A[i,j] = x[i] * y[j]</i>. /// </summary> /// <param name="x">the first source vector.</param> /// <param name="y">the second source vector.</param> /// <param name="A">the matrix to hold the resultsd Set this parameter to <i>null</i> to indicate that a new result matrix shall be constructed.</param> /// <returns>A (for convenience only).</returns> public static DoubleMatrix2D MultOuter(DoubleMatrix1D x, DoubleMatrix1D y, DoubleMatrix2D A) { int rows = x.Size; int columns = y.Size; if (A == null) { A = x.Like2D(rows, columns); } if (A.Rows != rows || A.Columns != columns) { throw new ArgumentException(); } for (int row = rows; --row >= 0;) { A.ViewRow(row).Assign(y); } for (int column = columns; --column >= 0;) { A.ViewColumn(column).Assign(x, BinaryFunctions.Mult); } return(A); }
/// <summary> /// Returns a string representation of the given matrix. /// </summary> /// <param name="matrix"> /// The matrix to convert. /// </param> /// <returns> /// A string representation of the given matrix. /// </returns> public string ToString(DoubleMatrix1D matrix) { DoubleMatrix2D easy = matrix.Like2D(1, matrix.Size); easy.ViewRow(0).Assign(matrix); return(ToString(easy)); }
public void Dger(double alpha, DoubleMatrix1D x, DoubleMatrix1D y, DoubleMatrix2D A) { Cern.Jet.Math.PlusMult fun = new Cern.Jet.Math.PlusMult(0); for (int i = A.Rows; --i >= 0;) { fun.Multiplicator = alpha * x[i]; A.ViewRow(i).Assign(y, fun); } }
public void Dswap(DoubleMatrix2D A, DoubleMatrix2D B) { //B.Swap(A); not yet implemented A.CheckShape(B); for (int i = A.Rows; --i >= 0;) { A.ViewRow(i).Swap(B.ViewRow(i)); } }
/// <summary> /// Returns a string representations of all cells; no alignment considered. /// </summary> /// <param name="matrix"> /// The matrix. /// </param> /// <returns> /// A string representation of all cells. /// </returns> public string[][] Format(DoubleMatrix2D matrix) { var strings = new string[matrix.Rows][]; for (int row = matrix.Rows; --row >= 0;) { strings[row] = FormatRow(matrix.ViewRow(row)); } return(strings); }
/// <summary> /// Returns the infinity norm of matrix <i>A</i>, which is the maximum absolute row sum. /// </summary> /// <param name="A">The matrix A.</param> /// <returns>The infinity norm of matrix <i>A</i></returns> public static double NormInfinity(DoubleMatrix2D A) { double max = 0; for (int row = A.Rows; --row >= 0;) { //max = System.Math.Max(max, normInfinity(A.ViewRow(row))); max = System.Math.Max(max, Norm1(A.ViewRow(row))); } return(max); }
/// <summary> /// Constructs and returns a new Cholesky decomposition object for a symmetric and positive definite matrix; /// The decomposed matrices can be retrieved via instance methods of the returned decomposition object. /// /// Return a structure to access <i>L</i> and <i>isSymmetricPositiveDefinite</i> flag. /// </summary> /// <param name="A">Square, symmetric matrix.</param> /// <exception cref="ArgumentException">if <i>A</i> is not square.</exception> public CholeskyDecomposition(DoubleMatrix2D A) { Property.DEFAULT.CheckSquare(A); // Initialize. //double[][] A = Arg.getArray(); n = A.Rows; //L = new double[n][n]; mL = A.Like(n, n); isSymmetricPositiveDefinite = (A.Columns == n); //precompute and cache some views to avoid regenerating them time and again DoubleMatrix1D[] Lrows = new DoubleMatrix1D[n]; for (int j = 0; j < n; j++) { Lrows[j] = mL.ViewRow(j); } // Main loop. for (int j = 0; j < n; j++) { //double[] Lrowj = L[j]; //DoubleMatrix1D Lrowj = L.ViewRow(j); double d = 0.0; for (int k = 0; k < j; k++) { //double[] Lrowk = L[k]; double s = Lrows[k].ZDotProduct(Lrows[j], 0, k); /* * DoubleMatrix1D Lrowk = L.ViewRow(k); * double s = 0.0; * for (int i = 0; i < k; i++) { * s += Lrowk.getQuick(i)*Lrowj.getQuick(i); * } */ s = (A[j, k] - s) / mL[k, k]; Lrows[j][k] = s; d = d + s * s; isSymmetricPositiveDefinite = isSymmetricPositiveDefinite && (A[k, j] == A[j, k]); } d = A[j, j] - d; isSymmetricPositiveDefinite = isSymmetricPositiveDefinite && (d > 0.0); mL[j, j] = System.Math.Sqrt(System.Math.Max(d, 0.0)); for (int k = j + 1; k < n; k++) { mL[j, k] = 0.0; } } }
public static DoubleMatrix2D PermuteRows(DoubleMatrix2D A, int[] indexes, int[] work) { // check validity int size = A.Rows; if (indexes.Length != size) { throw new IndexOutOfRangeException("invalid permutation"); } /* * int i=size; * int a; * while (--i >= 0 && (a=indexes[i])==i) if (a < 0 || a >= size) throw new IndexOutOfRangeException("invalid permutation"); * if (i<0) return; // nothing to permute */ int columns = A.Columns; if (columns < size / 10) { // quicker double[] doubleWork = new double[size]; for (int j = A.Columns; --j >= 0;) { Permute(A.ViewColumn(j), indexes, doubleWork); } return(A); } var swapper = new Cern.Colt.Swapper((a, b) => { A.ViewRow(a).Swap(A.ViewRow(b)); } ); Cern.Colt.GenericPermuting.permute(indexes, swapper, work, null); return(A); }
/// <summary> /// Solves <i>A*X = B</i>; returns <i>X</i>. /// </summary> /// <param name="B">A Matrix with as many rows as <i>A</i> and any number of columns.</param> /// <returns><i>X</i> so that <i>L*L'*X = B</i>.</returns> /// <exception cref="ArgumentException">if <i>B.Rows != A.Rows</i>.</exception> /// <exception cref="ArgumentException">if <i>!isSymmetricPositiveDefinite()</i>.</exception> private DoubleMatrix2D XXXsolveBuggy(DoubleMatrix2D B) { var F = Cern.Jet.Math.Functions.functions; if (B.Rows != n) { throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_MatrixRowDimensionsMustAgree); } if (!isSymmetricPositiveDefinite) { throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_MatrixIsNotSymmetricPositiveDefinite); } // Copy right hand side. DoubleMatrix2D X = B.Copy(); int nx = B.Columns; // precompute and cache some views to avoid regenerating them time and again DoubleMatrix1D[] Xrows = new DoubleMatrix1D[n]; for (int k = 0; k < n; k++) { Xrows[k] = X.ViewRow(k); } // Solve L*Y = B; for (int k = 0; k < n; k++) { for (int i = k + 1; i < n; i++) { // X[i,j] -= X[k,j]*L[i,k] Xrows[i].Assign(Xrows[k], F2.MinusMult(mL[i, k])); } Xrows[k].Assign(F1.Div(mL[k, k])); } // Solve L'*X = Y; for (int k = n - 1; k >= 0; k--) { Xrows[k].Assign(F1.Div(mL[k, k])); for (int i = 0; i < k; i++) { // X[i,j] -= X[k,j]*L[k,i] Xrows[i].Assign(Xrows[k], F2.MinusMult(mL[k, i])); } } return(X); }
/// <summary> /// A matrix <i>A</i> is <i>diagonally dominant by row</i> if the absolute value of each diagonal element is larger than the sum of the absolute values of the off-diagonal elements in the corresponding row. /// <i>returns true if for all i: abs(A[i,i]) > Sum(abs(A[i,j])); j != i.</i> /// Matrix may but need not be square. /// <p> /// Note: Ignores tolerance. /// <summary> public Boolean IsDiagonallyDominantByRow(DoubleMatrix2D A) { Cern.Jet.Math.Functions F = Cern.Jet.Math.Functions.functions; double epsilon = Tolerance; int min = System.Math.Min(A.Rows, A.Columns); for (int i = min; --i >= 0;) { double diag = System.Math.Abs(A[i, i]); diag += diag; if (diag <= A.ViewRow(i).Aggregate(F2.Plus, F1.Abs)) { return(false); } } return(true); }
/// <summary> /// Modifies the given matrix square matrix<i>A</i> such that it is diagonally dominant by row and column, hence non-singular, hence invertible. /// For testing purposes only. /// <summary> ///<param name = "A" > the square matrix to modify.</param> ///<exception cref = "ArgumentException" >if <i>!isSquare(A)</i>. </exception> public void GenerateNonSingular(DoubleMatrix2D A) { CheckSquare(A); var F = Cern.Jet.Math.Functions.functions; int min = System.Math.Min(A.Rows, A.Columns); for (int i = min; --i >= 0;) { A[i, i] = 0; } for (int i = min; --i >= 0;) { double rowSum = A.ViewRow(i).Aggregate(F2.Plus, F1.Abs); double colSum = A.ViewColumn(i).Aggregate(F2.Plus, F1.Abs); A[i, i] = System.Math.Max(rowSum, colSum) + i + 1; } }
/// <summary> /// Copies the columns of the indicated rows into a new sub matrix. /// <i>sub[0..rowIndexes.Length-1,0..columnTo-columnFrom] = A[rowIndexes(:),columnFrom..columnTo]</i>; /// The returned matrix is <i>not backed</i> by this matrix, so changes in the returned matrix are <i>not reflected</i> in this matrix, and vice-versa. /// </summary> /// <param name="A">the source matrix to copy from.</param> /// <param name="rowIndexes">the indexes of the rows to copyd May be unsorted.</param> /// <param name="columnFrom">the index of the first column to copy (inclusive).</param> /// <param name="columnTo">the index of the last column to copy (inclusive).</param> /// <returns>a new sub matrix; with <i>sub.Rows==rowIndexes.Length; sub.Columns==columnTo-columnFrom+1</i>.</returns> /// <exception cref="IndexOutOfRangeException">if <i>columnFrom < 0 || columnTo-columnFrom+1 < 0 || columnTo+1>matrix.Columns || for any row=rowIndexes[i]: row < 0 || row >= matrix.Rows</i>.</exception> private static DoubleMatrix2D SubMatrix(DoubleMatrix2D A, int[] rowIndexes, int columnFrom, int columnTo) { int width = columnTo - columnFrom + 1; int rows = A.Rows; A = A.ViewPart(0, columnFrom, rows, width); DoubleMatrix2D sub = A.Like(rowIndexes.Length, width); for (int r = rowIndexes.Length; --r >= 0;) { int row = rowIndexes[r]; if (row < 0 || row >= rows) { throw new IndexOutOfRangeException("Illegal Index"); } sub.ViewRow(r).Assign(A.ViewRow(row)); } return(sub); }
/// <summary> /// Sorts the matrix rows according to the order induced by the specified comparator. /// </summary> /// <param name="matrix"> /// The matrix to be sorted. /// </param> /// <param name="c"> /// The comparator to determine the order. /// </param> /// <returns> /// A new matrix view having rows sorted as specified. /// </returns> public DoubleMatrix2D Sort(DoubleMatrix2D matrix, DoubleMatrix1DComparator c) { var rowIndexes = new int[matrix.Rows]; // row indexes to reorder instead of matrix itself for (int i = rowIndexes.Length; --i >= 0;) { rowIndexes[i] = i; } var views = new DoubleMatrix1D[matrix.Rows]; // precompute views for speed for (int i = views.Length; --i >= 0;) { views[i] = matrix.ViewRow(i); } RunSort(rowIndexes, 0, rowIndexes.Length, (a, b) => c(views[a], views[b])); // view the matrix according to the reordered row indexes // take all columns in the original order return(matrix.ViewSelection(rowIndexes, null)); }
public void Decompose(DoubleMatrix2D A) { int CUT_OFF = 10; // setup LU = A; int m = A.Rows; int n = A.Columns; // setup pivot vector if (this.piv == null || this.piv.Length != m) { this.piv = new int[m]; } for (int i = m; --i >= 0;) { piv[i] = i; } pivsign = 1; if (m * n == 0) { LU = LU; return; // nothing to do } //precompute and cache some views to avoid regenerating them time and again DoubleMatrix1D[] LUrows = new DoubleMatrix1D[m]; for (int i = 0; i < m; i++) { LUrows[i] = LU.ViewRow(i); } IntArrayList nonZeroIndexes = new IntArrayList(); // sparsity DoubleMatrix1D LUcolj = LU.ViewColumn(0).Like(); // blocked column j Cern.Jet.Math.Mult multFunction = Cern.Jet.Math.Mult.CreateInstance(0); // Outer loop. for (int j = 0; j < n; j++) { // blocking (make copy of j-th column to localize references) LUcolj.Assign(LU.ViewColumn(j)); // sparsity detection int maxCardinality = m / CUT_OFF; // == heuristic depending on speedup LUcolj.GetNonZeros(nonZeroIndexes, null, maxCardinality); int cardinality = nonZeroIndexes.Count; Boolean sparse = (cardinality < maxCardinality); // Apply previous transformations. for (int i = 0; i < m; i++) { int kmax = System.Math.Min(i, j); double s; if (sparse) { s = LUrows[i].ZDotProduct(LUcolj, 0, kmax, nonZeroIndexes); } else { s = LUrows[i].ZDotProduct(LUcolj, 0, kmax); } double before = LUcolj[i]; double after = before - s; LUcolj[i] = after; // LUcolj is a copy LU[i, j] = after; // this is the original if (sparse) { if (before == 0 && after != 0) { // nasty bug fixed! int pos = nonZeroIndexes.BinarySearch(i); pos = -pos - 1; nonZeroIndexes.Insert(pos, i); } if (before != 0 && after == 0) { nonZeroIndexes.Remove(nonZeroIndexes.BinarySearch(i)); } } } // Find pivot and exchange if necessary. int p = j; if (p < m) { double max = System.Math.Abs(LUcolj[p]); for (int i = j + 1; i < m; i++) { double v = System.Math.Abs(LUcolj[i]); if (v > max) { p = i; max = v; } } } if (p != j) { LUrows[p].Swap(LUrows[j]); int k = piv[p]; piv[p] = piv[j]; piv[j] = k; pivsign = -pivsign; } // Compute multipliers. double jj; if (j < m && (jj = LU[j, j]) != 0.0) { multFunction.Multiplicator = 1 / jj; LU.ViewColumn(j).ViewPart(j + 1, m - (j + 1)).Assign(multFunction); } } LU = LU; }
public void Solve(DoubleMatrix2D B) { int CUT_OFF = 10; //algebra.property().checkRectangular(LU); int m = M; int n = N; if (B.Rows != m) { throw new ArgumentException("Matrix row dimensions must agree."); } if (!this.IsNonsingular) { throw new ArgumentException("Matrix is singular."); } // right hand side with pivoting // Matrix Xmat = B.getMatrix(piv,0,nx-1); if (this.work1 == null || this.work1.Length < m) { this.work1 = new int[m]; } //if (this.work2 == null || this.work2.Length < m) this.work2 = new int[m]; Algebra.PermuteRows(B, this.piv, this.work1); if (m * n == 0) { return; // nothing to do } int nx = B.Columns; //precompute and cache some views to avoid regenerating them time and again DoubleMatrix1D[] Brows = new DoubleMatrix1D[n]; for (int k = 0; k < n; k++) { Brows[k] = B.ViewRow(k); } // transformations Cern.Jet.Math.Mult div = Cern.Jet.Math.Mult.Div(0); Cern.Jet.Math.PlusMult minusMult = Cern.Jet.Math.PlusMult.MinusMult(0); IntArrayList nonZeroIndexes = new IntArrayList(); // sparsity DoubleMatrix1D Browk = Cern.Colt.Matrix.DoubleFactory1D.Dense.Make(nx); // blocked row k // Solve L*Y = B(piv,:) for (int k = 0; k < n; k++) { // blocking (make copy of k-th row to localize references) Browk.Assign(Brows[k]); // sparsity detection int maxCardinality = nx / CUT_OFF; // == heuristic depending on speedup Browk.GetNonZeros(nonZeroIndexes, null, maxCardinality); int cardinality = nonZeroIndexes.Count; Boolean sparse = (cardinality < maxCardinality); for (int i = k + 1; i < n; i++) { //for (int j = 0; j < nx; j++) B[i][j] -= B[k][j]*LU[i][k]; //for (int j = 0; j < nx; j++) B.set(i,j, B.Get(i,j) - B.Get(k,j)*LU.Get(i,k)); minusMult.Multiplicator = -LU[i, k]; if (minusMult.Multiplicator != 0) { if (sparse) { Brows[i].Assign(Browk, minusMult, nonZeroIndexes); } else { Brows[i].Assign(Browk, minusMult); } } } } // Solve U*B = Y; for (int k = n - 1; k >= 0; k--) { // for (int j = 0; j < nx; j++) B[k][j] /= LU[k][k]; // for (int j = 0; j < nx; j++) B.set(k,j, B.Get(k,j) / LU.Get(k,k)); div.Multiplicator = 1 / LU[k, k]; Brows[k].Assign(div); // blocking if (Browk == null) { Browk = Cern.Colt.Matrix.DoubleFactory1D.Dense.Make(B.Columns); } Browk.Assign(Brows[k]); // sparsity detection int maxCardinality = nx / CUT_OFF; // == heuristic depending on speedup Browk.GetNonZeros(nonZeroIndexes, null, maxCardinality); int cardinality = nonZeroIndexes.Count; Boolean sparse = (cardinality < maxCardinality); //Browk.GetNonZeros(nonZeroIndexes,null); //Boolean sparse = nonZeroIndexes.Count < nx/10; for (int i = 0; i < k; i++) { // for (int j = 0; j < nx; j++) B[i][j] -= B[k][j]*LU[i][k]; // for (int j = 0; j < nx; j++) B.set(i,j, B.Get(i,j) - B.Get(k,j)*LU.Get(i,k)); minusMult.Multiplicator = -LU[i, k]; if (minusMult.Multiplicator != 0) { if (sparse) { Brows[i].Assign(Browk, minusMult, nonZeroIndexes); } else { Brows[i].Assign(Browk, minusMult); } } } } }
public override DoubleMatrix2D ZMult(DoubleMatrix2D B, DoubleMatrix2D C, double alpha, double beta, Boolean transposeA, Boolean transposeB) { if (transposeB) { B = B.ViewDice(); } int m = Rows; int n = Columns; if (transposeA) { m = Columns; n = Rows; } int p = B.Columns; Boolean ignore = (C == null); if (C == null) { C = new DenseDoubleMatrix2D(m, p); } if (B.Rows != n) { throw new ArgumentException(String.Format(Cern.LocalizedResources.Instance().Exception_Matrix2DInnerDimensionMustAgree, ToStringShort(), (transposeB ? B.ViewDice() : B).ToStringShort())); } if (C.Rows != m || C.Columns != p) { throw new ArgumentException(String.Format(Cern.LocalizedResources.Instance().Exception_IncompatibleResultMatrix, ToStringShort(), (transposeB ? B.ViewDice() : B).ToStringShort(), C.ToStringShort())); } if (this == C || B == C) { throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_MatricesMustNotBeIdentical); } if (!ignore) { C.Assign(F1.Mult(beta)); } // cache views DoubleMatrix1D[] Brows = new DoubleMatrix1D[n]; for (int i = n; --i >= 0;) { Brows[i] = B.ViewRow(i); } DoubleMatrix1D[] Crows = new DoubleMatrix1D[m]; for (int i = m; --i >= 0;) { Crows[i] = C.ViewRow(i); } ForEachNonZero( new Cern.Colt.Function.IntIntDoubleFunction((i, j, value) => { var fun = F2.PlusMult(value * alpha); //fun.multiplicator = value * alpha; if (!transposeA) { Crows[i].Assign(Brows[j], fun); } else { Crows[j].Assign(Brows[i], fun); } return(value); } )); return(C); }
public override DoubleMatrix2D ZMult(DoubleMatrix2D B, DoubleMatrix2D C, double alpha, double beta, Boolean transposeA, Boolean transposeB) { if (transposeB) { B = B.ViewDice(); } int m = Rows; int n = Columns; if (transposeA) { m = Columns; n = Rows; } int p = B.Columns; Boolean ignore = (C == null); if (C == null) { C = new DenseDoubleMatrix2D(m, p); } if (B.Rows != n) { throw new ArgumentException("Matrix2D inner dimensions must agree:" + ToStringShort() + ", " + (transposeB ? B.ViewDice() : B).ToStringShort()); } if (C.Rows != m || C.Columns != p) { throw new ArgumentException("Incompatibel result matrix: " + ToStringShort() + ", " + (transposeB ? B.ViewDice() : B).ToStringShort() + ", " + C.ToStringShort()); } if (this == C || B == C) { throw new ArgumentException("Matrices must not be identical"); } if (!ignore) { C.Assign(F1.Mult(beta)); } // cache views DoubleMatrix1D[] Brows = new DoubleMatrix1D[n]; for (int i = n; --i >= 0;) { Brows[i] = B.ViewRow(i); } DoubleMatrix1D[] Crows = new DoubleMatrix1D[m]; for (int i = m; --i >= 0;) { Crows[i] = C.ViewRow(i); } ForEachNonZero( new Cern.Colt.Function.IntIntDoubleFunction((i, j, value) => { var fun = F2.PlusMult(value * alpha); //fun.multiplicator = value * alpha; if (!transposeA) { Crows[i].Assign(Brows[j], fun); } else { Crows[j].Assign(Brows[i], fun); } return(value); } )); return(C); }
public override DoubleMatrix2D ZMult(DoubleMatrix2D B, DoubleMatrix2D C, double alpha, double beta, Boolean transposeA, Boolean transposeB) { if (transposeB) { B = B.ViewDice(); } int m = Rows; int n = Columns; if (transposeA) { m = Columns; n = Rows; } int p = B.Columns; Boolean ignore = (C == null); if (C == null) { C = new DenseDoubleMatrix2D(m, p); } if (B.Rows != n) { throw new ArgumentException(String.Format(Cern.LocalizedResources.Instance().Exception_Matrix2DInnerDimensionMustAgree, ToStringShort(), (transposeB ? B.ViewDice() : B).ToStringShort())); } if (C.Rows != m || C.Columns != p) { throw new ArgumentException(String.Format(Cern.LocalizedResources.Instance().Exception_IncompatibleResultMatrix, ToStringShort(), (transposeB ? B.ViewDice() : B).ToStringShort(), C.ToStringShort())); } if (this == C || B == C) { throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_MatricesMustNotBeIdentical); } if (!ignore) { C.Assign(F1.Mult(beta)); } // cache views DoubleMatrix1D[] Brows = new DoubleMatrix1D[n]; for (int i = n; --i >= 0;) { Brows[i] = B.ViewRow(i); } DoubleMatrix1D[] Crows = new DoubleMatrix1D[m]; for (int i = m; --i >= 0;) { Crows[i] = C.ViewRow(i); } int[] idx = Indexes.ToArray(); double[] vals = Values.ToArray(); for (int i = Starts.Length - 1; --i >= 0;) { int low = Starts[i]; for (int k = Starts[i + 1]; --k >= low;) { int j = idx[k]; var fun = F2.PlusMult(vals[k] * alpha); //fun.Multiplicator = vals[k] * alpha; if (!transposeA) { Crows[i].Assign(Brows[j], fun); } else { Crows[j].Assign(Brows[i], fun); } } } return(C); }