/** * <p> * Returns true if the matrix is symmetric within the tolerance. Only square matrices can be * symmetric. * </p> * <p> * A matrix is symmetric if:<br> * |a<sub>ij</sub> - a<sub>ji</sub>| ≤ tol * </p> * * @param m A matrix. Not modified. * @param tol Tolerance for how similar two elements need to be. * @return true if it is symmetric and false if it is not. */ public static bool isSymmetric(DMatrixRMaj m, double tol) { if (m.numCols != m.numRows) { return(false); } double max = CommonOps_DDRM.elementMaxAbs(m); for (int i = 0; i < m.numRows; i++) { for (int j = 0; j < i; j++) { double a = m.get(i, j) / max; double b = m.get(j, i) / max; double diff = Math.Abs(a - b); if (!(diff <= tol)) { return(false); } } } return(true); }
/** * <p> * Element wise p-norm:<br> * <br> * norm = {∑<sub>i=1:m</sub> ∑<sub>j=1:n</sub> { |a<sub>ij</sub>|<sup>p</sup>}}<sup>1/p</sup> * </p> * * <p> * This is not the same as the induced p-norm used on matrices, but is the same as the vector p-norm. * </p> * * @param A Matrix. Not modified. * @param p p value. * @return The norm's value. */ public static double elementP(DMatrix1Row A, double p) { if (p == 1) { return(CommonOps_DDRM.elementSumAbs(A)); } if (p == 2) { return(normF(A)); } else { double max = CommonOps_DDRM.elementMaxAbs(A); if (max == 0.0) { return(0.0); } double total = 0; int size = A.getNumElements(); for (int i = 0; i < size; i++) { double a = A.get(i) / max; total += Math.Pow(Math.Abs(a), p); } return(max * Math.Pow(total, 1.0 / p)); } }
/** * <p> * To decompose the matrix 'A' it must have full rank. 'A' is a 'm' by 'n' matrix. * It requires about 2n*m<sup>2</sup>-2m<sup>2</sup>/3 flops. * </p> * * <p> * The matrix provided here can be of different * dimension than the one specified in the constructor. It just has to be smaller than or equal * to it. * </p> */ public override bool decompose(DMatrixRMaj A) { setExpectedMaxSize(A.numRows, A.numCols); convertToColumnMajor(A); maxAbs = CommonOps_DDRM.elementMaxAbs(A); // initialize pivot variables setupPivotInfo(); // go through each column and perform the decomposition for (int j = 0; j < minLength; j++) { if (j > 0) { updateNorms(j); } swapColumns(j); // if its degenerate stop processing if (!householderPivot(j)) { break; } updateA(j); rank = j + 1; } return(true); }
/** * Computes the p=∞ norm. If A is a matrix then the induced norm is computed. * * @param A Matrix or vector. * @return The norm. */ public static double normPInf(DMatrixRMaj A) { if (MatrixFeatures_DDRM.isVector(A)) { return(CommonOps_DDRM.elementMaxAbs(A)); } else { return(inducedPInf(A)); } }
/** * <p> * Computes the Frobenius matrix norm:<br> * <br> * normF = Sqrt{ ∑<sub>i=1:m</sub> ∑<sub>j=1:n</sub> { a<sub>ij</sub><sup>2</sup>} } * </p> * <p> * This is equivalent to the element wise p=2 norm. See {@link #fastNormF} for another implementation * that is faster, but more prone to underflow/overflow errors. * </p> * * @param a The matrix whose norm is computed. Not modified. * @return The norm's value. */ public static double normF(DMatrixD1 a) { double total = 0; double scale = CommonOps_DDRM.elementMaxAbs(a); if (scale == 0.0) { return(0.0); } int size = a.getNumElements(); for (int i = 0; i < size; i++) { double val = a.get(i) / scale; total += val * val; } return(scale * Math.Sqrt(total)); }
/** * Sums up the square of each element in the matrix. This is equivalent to the * Frobenius norm squared. * * @param m Matrix. * @return Sum of elements squared. */ public static double elementSumSq(DMatrixD1 m) { // minimize round off error double maxAbs = CommonOps_DDRM.elementMaxAbs(m); if (maxAbs == 0) { return(0); } double total = 0; int N = m.NumElements; for (int i = 0; i < N; i++) { double d = m.data[i] / maxAbs; total += d * d; } return(maxAbs * total * maxAbs); }
public double elementMaxAbs(Matrix A) { return(CommonOps_DDRM.elementMaxAbs((DMatrixRMaj)A)); }
/** * Computes the QR decomposition of the provided matrix. * * @param A Matrix which is to be decomposed. Not modified. */ public void decompose(DMatrixRMaj A) { this.QR = (DMatrixRMaj)A.copy(); int N = Math.Min(A.numCols, A.numRows); gammas = new double[A.numCols]; DMatrixRMaj A_small = new DMatrixRMaj(A.numRows, A.numCols); DMatrixRMaj A_mod = new DMatrixRMaj(A.numRows, A.numCols); DMatrixRMaj v = new DMatrixRMaj(A.numRows, 1); DMatrixRMaj Q_k = new DMatrixRMaj(A.numRows, A.numRows); for (int i = 0; i < N; i++) { // reshape temporary variables A_small.reshape(QR.numRows - i, QR.numCols - i, false); A_mod.reshape(A_small.numRows, A_small.numCols, false); v.reshape(A_small.numRows, 1, false); Q_k.reshape(v.getNumElements(), v.getNumElements(), false); // use extract matrix to get the column that is to be zeroed CommonOps_DDRM.extract(QR, i, QR.numRows, i, i + 1, v, 0, 0); double max = CommonOps_DDRM.elementMaxAbs(v); if (max > 0 && v.getNumElements() > 1) { // normalize to reduce overflow issues CommonOps_DDRM.divide(v, max); // compute the magnitude of the vector double tau = NormOps_DDRM.normF(v); if (v.get(0) < 0) { tau *= -1.0; } double u_0 = v.get(0) + tau; double gamma = u_0 / tau; CommonOps_DDRM.divide(v, u_0); v.set(0, 1.0); // extract the submatrix of A which is being operated on CommonOps_DDRM.extract(QR, i, QR.numRows, i, QR.numCols, A_small, 0, 0); // A = (I - γ*u*u<sup>T</sup>)A CommonOps_DDRM.setIdentity(Q_k); CommonOps_DDRM.multAddTransB(-gamma, v, v, Q_k); CommonOps_DDRM.mult(Q_k, A_small, A_mod); // save the results CommonOps_DDRM.insert(A_mod, QR, i, i); CommonOps_DDRM.insert(v, QR, i, i); QR.unsafe_set(i, i, -tau * max); // save gamma for recomputing Q later on gammas[i] = gamma; } } }