public static MatrixC operator *(MatrixC m1, MatrixC m2) { if (m1.GetCols()!=m2.GetRows()) { throw new ArgumentOutOfRangeException( "Columns", m1, "The numbers of columns of the first matrix must be equal to" + " the number of rows of the second matrix!"); } MatrixC result = new MatrixC(m1.GetRows(), m2.GetCols()); VectorC v1 = new VectorC(m1.GetCols()); VectorC v2 = new VectorC(m2.GetRows()); for (int i = 0; i < m1.GetRows(); i++) { v1 = m1.GetRowVector(i); for (int j = 0; j < m2.GetCols(); j++) { v2 = m2.GetColVector(j); result[i, j] = VectorC.DotProduct(v1, v2); } } return result; }
public MatrixC Transpose() { MatrixC m = new MatrixC(Cols, Rows); for (int i = 0; i < Rows; i++) { for (int j = 0; j < Cols; j++) { m[j, i] = matrix[i, j]; } } return m; }
public bool Equals(MatrixC m) { return matrix == m.matrix; }
public MatrixC Identity() { MatrixC m = new MatrixC(Rows, Cols); for (int i = 0; i < Rows; i++) { for (int j = 0; j < Cols; j++) { if (i == j) { m[i, j] = 1; } } } return m; }
public static MatrixC Transform(VectorC v1, VectorC v2) { if (v1.GetSize() != v2.GetSize()) { throw new ArgumentOutOfRangeException( "v1", v1.GetSize(), "The vectors must have the same size!"); } MatrixC result = new MatrixC(v1.GetSize(), v1.GetSize()); for (int i = 0; i < v1.GetSize(); i++) { for (int j = 0; j < v1.GetSize(); j++) { result[j, i] = v1[i] * v2[j]; } } return result; }
public MatrixC Clone() { // returns a deep copy of the matrix MatrixC m = new MatrixC(matrix); m.matrix = (double[,])matrix.Clone(); return m; }
public static VectorC Transform(VectorC v, MatrixC m) { VectorC result = new VectorC(v.GetSize()); //if (!m.IsSquared()) //{ // throw new ArgumentOutOfRangeException( // "Dimension", m.GetRows(), "The matrix must be squared!"); //} //if (m.GetRows() != v.GetSize()) //{ // throw new ArgumentOutOfRangeException( // "Size", v.GetSize(), "The size of the vector must be equal" // + "to the number of rows of the matrix!"); //} for (int i = 0; i < m.GetRows(); i++) { result[i] = 0.0; for (int j = 0; j < m.GetCols(); j++) { result[i] += v[j] * m[j, i]; } } return result; }
public static MatrixC operator /(double d, MatrixC m) { MatrixC result = new MatrixC(m.GetRows(), m.GetCols()); for (int i = 0; i < m.GetRows(); i++) { for (int j = 0; j < m.GetCols(); j++) { result[i, j] = d/ m[i, j]; } } return result; }
public static MatrixC Inverse(MatrixC m) { if (Determinant(m) == 0) { throw new DivideByZeroException( "Cannot inverse a matrix with a zero determinant!"); } return (Adjoint(m) / Determinant(m)); }
public static MatrixC Minor(MatrixC m, int row, int col) { MatrixC mm = new MatrixC(m.GetRows() - 1, m.GetCols() - 1); int ii = 0, jj = 0; for (int i = 0; i < m.GetRows(); i++) { if (i == row) continue; jj = 0; for (int j = 0; j < m.GetCols(); j++) { if (j == col) continue; mm[ii, jj] = m[i, j]; jj++; } ii++; } return mm; }
public static double Determinant(MatrixC m) { double result = 0.0; if (!m.IsSquared()) { throw new ArgumentOutOfRangeException( "Dimension", m.GetRows(), "The matrix must be squared!"); } if (m.GetRows() == 1) result = m[0, 0]; else { for (int i = 0; i < m.GetRows(); i++) { result += Math.Pow(-1, i)*m[0, i] * Determinant(MatrixC.Minor(m, 0, i)); } } return result; }
public static bool CompareDimension(MatrixC m1, MatrixC m2) { if (m1.GetRows() == m2.GetRows() && m1.GetCols() == m2.GetCols()) return true; else return false; }
public static MatrixC Adjoint(MatrixC m) { if (!m.IsSquared()) { throw new ArgumentOutOfRangeException( "Dimension", m.GetRows(), "The matrix must be squared!"); } MatrixC ma = new MatrixC(m.GetRows(), m.GetCols()); for (int i = 0; i < m.GetRows(); i++) { for (int j = 0; j < m.GetCols(); j++) { ma[i, j] = Math.Pow(-1, i + j) * (Determinant(Minor(m, i, j))); } } return ma.GetTranspose(); }
public static MatrixC operator *(MatrixC m, double d) { MatrixC result = new MatrixC(m.GetRows(), m.GetCols()); for (int i = 0; i < m.GetRows(); i++) { for (int j = 0; j < m.GetCols(); j++) { result[i, j] = m[i, j] * d; } } return result; }
public MatrixC(MatrixC m) { Rows = m.GetRows(); Cols = m.GetCols(); matrix = m.matrix; }
/// <summary> /// Implementation Convex optimization using ADMM( Stephen Boyd, Stanford) It is essentially least squares fitting with non-negativity constraints /// An ANOVA computation is added below for significance testing although this implementation is NOT VALIDATED /// The matrix is any reference matrix (database) and y is the experimental data. The result is a vector of coefficients for the model /// </summary> /// <param name="matrix"></param> /// <param name="y"></param> /// <returns></returns> public VectorC MatchLibraryMatrix(MatrixC matrix, VectorC y) { #region ADMM (Alternating direction method of multipliers) //regularized matrix version of least squares //x = (A'*A)*A'*b //rho, the wiggle factor double rho = .001; //Ax = b where x is the prediction, b is the experimental and A is the reference database matrix // A = x^t*x var A = matrix.Transpose() * matrix; //b = xt*y MatrixC y1 = new MatrixC(matrix.GetRows(), 1); y1.ReplaceCol(y, 0); var temp1 = matrix.Transpose() * y1; VectorC b = new VectorC(temp1.GetRows()); for(int i = 0; i < temp1.GetRows();i++) { b[i] = temp1[i,0]; } //create identity matrix var I = A.Identity(); //A' = (A + rho*I) var Aprime = MatrixC.Inverse(A + (rho * I)); double[] components = new double[b.GetSize()]; //add zeros to vectors for (int i = 0; i < b.GetSize(); i++) { components[i] = 0; } VectorC u = new VectorC(components); //accululated error in the negative direction VectorC z = new VectorC(components); //non-negative version of x VectorC x = new VectorC(components); //regularized least squares u = u.Clone(); z = z.Clone(); x = x.Clone(); double sumSquares = 0; for (int i = 0; i < 1500; i++) { x = MatrixC.Transform(Aprime, (b + rho * (z - u))); //for each element in x + u //z = (x + u); for (int j = 0; j < x.GetSize(); j++) { var temp = x[j] + u[j]; if (temp > 0) { z[j] = temp; } else { z[j] = 0; } } if (i == 1499) { int test11 = 0; } //for each element in x - z // u = u + (x - z); for (int k = 0; k < u.GetSize(); k++) { u[k] = u[k] + (x[k] - z[k]); } //calculate RMS error for (int ii = 0; ii < x.GetSize(); ii++) { sumSquares += (x[ii] - z[ii])*(x[ii] - z[ii]); } var RMS = Math.Sqrt(sumSquares / x.GetSize()); if (RMS < .001) { break; } } #endregion #region ANOVA //Matrix yMatrix = Matrix.Create(y); //Matrix database = (m.Transpose()*m).GetInverse()*m.Transpose(); ////ADMM //var predicted = m*z; ////Hat matrix. The hat matrix is used to reduce overfitting by finding outliers ////inv(x'*x)*x'*x' //var hatMatrix = (m*(m.Transpose()*m).GetInverse())*m.Transpose(); ////J matrix square matrix of ones //Matrix JMatrix = Matrix.Create(hatMatrix.ColumnCount, hatMatrix.RowCount); //for (int i = 0; i < JMatrix.ColumnCount; i++) //{ // for (int j = 0; j < JMatrix.RowCount; j++) // { // JMatrix[i, j] = 1; // } //} ////SSr (2000 is the observations or m/z in our case) ////y'*[H - (1/n)J]*y //var SSr = Y.Transpose()*((hatMatrix - (1/2000)*JMatrix))*Y; ////Mean Square Regression //var MSR = SSr/matrix.GetLongLength(1); ////Identity matrix //// The following constructs a nxn identity matrix: //DenseMatrix identityMatrix = DenseMatrix.GetIdentity(2001); ////SSE ////y'*[I-H]*y //var SSe = Y.Transpose()*(identityMatrix - hatMatrix)*Y; //double MSquareRegression = MSR[0, 0]; ////Mean Square Error //var MSE = SSe/(2000 - (matrix.GetLongLength(1) + 1)); //double MSquareError = MSE[0, 0]; ////F-statistic ////The fstat conducts a hypothesis test. It simply says, is there at least one coefficient that ////id different than zero? //var f = MSquareRegression/MSquareError; ////get covariance matrix //var C = MSquareError*(m.Transpose()*m).GetInverse(); ////get diangonal //var d = C.GetDiagonal(); ////conduct t-test for all coefficients (vectorResult for OLS) //for (int i = 0; i < z.Length; i++) //{ // double tTest = z[i]/Math.Sqrt(d[i]); //} ////populate correlation scores (vectorResult for OLS) //for (int i = 0; i < z.Length; i++) //{ //} #endregion return z; }
public static MatrixC operator -(MatrixC m1, MatrixC m2) { if (!MatrixC.CompareDimension(m1, m2)) { throw new ArgumentOutOfRangeException( "Dimension", m1, "The dimensions of two matrices must be the same!"); } MatrixC result = new MatrixC(m1.GetRows(), m1.GetCols()); for (int i = 0; i < m1.GetRows(); i++) { for (int j = 0; j < m1.GetCols(); j++) { result[i, j] = m1[i, j] - m2[i, j]; } } return result; }