示例#1
0
        /**
         * <p>
         * The condition number of a matrix is used to measure the sensitivity of the linear
         * system <b>Ax=b</b>.  A value near one indicates that it is a well conditioned matrix.<br>
         * <br>
         * &kappa;<sub>p</sub> = ||A||<sub>p</sub>||A<sup>-1</sup>||<sub>p</sub>
         * </p>
         * <p>
         * If the matrix is not square then the condition of either A<sup>T</sup>A or AA<sup>T</sup> is computed.
         * <p>
         * @param A The matrix.
         * @param p p-norm
         * @return The condition number.
         */
        public static float conditionP(FMatrixRMaj A, float p)
        {
            if (p == 2)
            {
                return(conditionP2(A));
            }
            else if (A.numRows == A.numCols)
            {
                // square matrices are the typical case

                FMatrixRMaj A_inv = new FMatrixRMaj(A.numRows, A.numCols);

                if (!CommonOps_FDRM.invert(A, A_inv))
                {
                    throw new ArgumentException("A can't be inverted.");
                }

                return(normP(A, p) * normP(A_inv, p));
            }
            else
            {
                FMatrixRMaj pinv = new FMatrixRMaj(A.numCols, A.numRows);
                CommonOps_FDRM.pinv(A, pinv);

                return(normP(A, p) * normP(pinv, p));
            }
        }
        //@Override
        public FMatrixRMaj getQ(FMatrixRMaj Q, bool compact)
        {
            int minLength = Math.Min(Ablock.numRows, Ablock.numCols);

            if (Q == null)
            {
                if (compact)
                {
                    Q = new FMatrixRMaj(Ablock.numRows, minLength);
                    CommonOps_FDRM.setIdentity(Q);
                }
                else
                {
                    Q = new FMatrixRMaj(Ablock.numRows, Ablock.numRows);
                    CommonOps_FDRM.setIdentity(Q);
                }
            }

            FMatrixRBlock Qblock = new FMatrixRBlock();

            Qblock.numRows     = Q.numRows;
            Qblock.numCols     = Q.numCols;
            Qblock.blockLength = blockLength;
            Qblock.data        = Q.data;

            ((QRDecompositionHouseholder_FDRB)alg).getQ(Qblock, compact);

            convertBlockToRow(Q.numRows, Q.numCols, Ablock.blockLength, Q.data);

            return(Q);
        }
示例#3
0
        /**
         * <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(FMatrixRMaj A)
        {
            setExpectedMaxSize(A.numRows, A.numCols);

            convertToColumnMajor(A);

            maxAbs = CommonOps_FDRM.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);
        }
示例#4
0
        /**
         * <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>| &le; 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(FMatrixRMaj m, float tol)
        {
            if (m.numCols != m.numRows)
            {
                return(false);
            }

            float max = CommonOps_FDRM.elementMaxAbs(m);

            for (int i = 0; i < m.numRows; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    float a = m.get(i, j) / max;
                    float b = m.get(j, i) / max;

                    float diff = Math.Abs(a - b);

                    if (!(diff <= tol))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
        /**
         * Returns the orthogonal V matrix.
         *
         * @param V If not null then the results will be stored here.  Otherwise a new matrix will be created.
         * @return The extracted Q matrix.
         */
        public virtual FMatrixRMaj getV(FMatrixRMaj V, bool transpose, bool compact)
        {
            V = handleV(V, transpose, compact, m, n, min);
            CommonOps_FDRM.setIdentity(V);

//        UBV.print();

            // todo the very first multiplication can be avoided by setting to the rank1update output
            for (int j = min - 1; j >= 0; j--)
            {
                u[j + 1] = 1;
                for (int i = j + 2; i < n; i++)
                {
                    u[i] = UBV.get(j, i);
                }
                if (transpose)
                {
                    QrHelperFunctions_FDRM.rank1UpdateMultL(V, u, gammasV[j], j + 1, j + 1, n);
                }
                else
                {
                    QrHelperFunctions_FDRM.rank1UpdateMultR(V, u, gammasV[j], j + 1, j + 1, n, this.b);
                }
            }

            return(V);
        }
        public virtual FMatrixRMaj getU(FMatrixRMaj U, bool transpose, bool compact)
        {
            U = BidiagonalDecompositionRow_FDRM.handleU(U, false, compact, m, n, min);

            if (compact)
            {
                // U = Q*U1
                FMatrixRMaj Q1 = decompQRP.getQ(null, true);
                FMatrixRMaj U1 = decompBi.getU(null, false, true);
                CommonOps_FDRM.mult(Q1, U1, U);
            }
            else
            {
                // U = [Q1*U1 Q2]
                FMatrixRMaj Q   = decompQRP.getQ(U, false);
                FMatrixRMaj U1  = decompBi.getU(null, false, true);
                FMatrixRMaj Q1  = CommonOps_FDRM.extract(Q, 0, Q.numRows, 0, min);
                FMatrixRMaj tmp = new FMatrixRMaj(Q1.numRows, U1.numCols);
                CommonOps_FDRM.mult(Q1, U1, tmp);
                CommonOps_FDRM.insert(tmp, Q, 0, 0);
            }

            if (transpose)
            {
                CommonOps_FDRM.transpose(U);
            }

            return(U);
        }
示例#7
0
        //@Override
        public FMatrixRMaj getV(FMatrixRMaj V, bool transpose)
        {
            if (!prefComputeV)
            {
                throw new ArgumentException("As requested V was not computed.");
            }
            if (transpose)
            {
                if (V == null)
                {
                    return(Vt);
                }

                V.set(Vt);
            }
            else
            {
                if (V == null)
                {
                    V = new FMatrixRMaj(Vt.numCols, Vt.numRows);
                }
                else
                {
                    V.reshape(Vt.numCols, Vt.numRows);
                }

                CommonOps_FDRM.transpose(Vt, V);
            }

            return(V);
        }
        /**
         * Returns the orthogonal U matrix.
         *
         * @param U If not null then the results will be stored here.  Otherwise a new matrix will be created.
         * @return The extracted Q matrix.
         */
        public virtual FMatrixRMaj getU(FMatrixRMaj U, bool transpose, bool compact)
        {
            U = handleU(U, transpose, compact, m, n, min);
            CommonOps_FDRM.setIdentity(U);

            for (int i = 0; i < m; i++)
            {
                u[i] = 0;
            }

            for (int j = min - 1; j >= 0; j--)
            {
                u[j] = 1;
                for (int i = j + 1; i < m; i++)
                {
                    u[i] = UBV.get(i, j);
                }
                if (transpose)
                {
                    QrHelperFunctions_FDRM.rank1UpdateMultL(U, u, gammasU[j], j, j, m);
                }
                else
                {
                    QrHelperFunctions_FDRM.rank1UpdateMultR(U, u, gammasU[j], j, j, m, this.b);
                }
            }

            return(U);
        }
        public virtual FMatrixRMaj getT(FMatrixRMaj T)
        {
            int N = Ablock.numRows;

            if (T == null)
            {
                T = new FMatrixRMaj(N, N);
            }
            else
            {
                CommonOps_FDRM.fill(T, 0);
            }

            float[] diag = new float[N];
            float[] off  = new float[N];

            ((TridiagonalDecompositionHouseholder_FDRB)alg).getDiagonal(diag, off);

            T.unsafe_set(0, 0, diag[0]);
            for (int i = 1; i < N; i++)
            {
                T.unsafe_set(i, i, diag[i]);
                T.unsafe_set(i, i - 1, off[i - 1]);
                T.unsafe_set(i - 1, i, off[i - 1]);
            }

            return(T);
        }
示例#10
0
        //@Override
        public FMatrixRMaj getU(FMatrixRMaj U, bool transpose)
        {
            if (!prefComputeU)
            {
                throw new ArgumentException("As requested U was not computed.");
            }
            if (transpose)
            {
                if (U == null)
                {
                    return(Ut);
                }
                U.set(Ut);
            }
            else
            {
                if (U == null)
                {
                    U = new FMatrixRMaj(Ut.numCols, Ut.numRows);
                }
                else
                {
                    U.reshape(Ut.numCols, Ut.numRows);
                }

                CommonOps_FDRM.transpose(Ut, U);
            }

            return(U);
        }
        /**
         * <p>
         * Computes a metric which measures the the quality of an eigen value decomposition.  If a
         * value is returned that is close to or smaller than 1e-15 then it is within machine precision.
         * </p>
         * <p>
         * EVD quality is defined as:<br>
         * <br>
         * Quality = ||A*V - V*D|| / ||A*V||.
         *  </p>
         *
         * @param orig The original matrix. Not modified.
         * @param eig EVD of the original matrix. Not modified.
         * @return The quality of the decomposition.
         */
        public static float quality(FMatrixRMaj orig, EigenDecomposition_F32 <FMatrixRMaj> eig)
        {
            FMatrixRMaj A = orig;
            FMatrixRMaj V = EigenOps_FDRM.createMatrixV(eig);
            FMatrixRMaj D = EigenOps_FDRM.createMatrixD(eig);

            // L = A*V
            FMatrixRMaj L = new FMatrixRMaj(A.numRows, V.numCols);

            CommonOps_FDRM.mult(A, V, L);
            // R = V*D
            FMatrixRMaj R = new FMatrixRMaj(V.numRows, D.numCols);

            CommonOps_FDRM.mult(V, D, R);

            FMatrixRMaj diff = new FMatrixRMaj(L.numRows, L.numCols);

            CommonOps_FDRM.subtract(L, R, diff);

            float top    = NormOps_FDRM.normF(diff);
            float bottom = NormOps_FDRM.normF(L);

            float error = top / bottom;

            return(error);
        }
示例#12
0
        /**
         * <p>
         * Element wise p-norm:<br>
         * <br>
         * norm = {&sum;<sub>i=1:m</sub> &sum;<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 float elementP(FMatrix1Row A, float p)
        {
            if (p == 1)
            {
                return(CommonOps_FDRM.elementSumAbs(A));
            }
            if (p == 2)
            {
                return(normF(A));
            }
            else
            {
                float max = CommonOps_FDRM.elementMaxAbs(A);

                if (max == 0.0f)
                {
                    return(0.0f);
                }

                float total = 0;

                int size = A.getNumElements();

                for (int i = 0; i < size; i++)
                {
                    float a = A.get(i) / max;

                    total += (float)Math.Pow(Math.Abs(a), p);
                }

                return(max * (float)Math.Pow(total, 1.0f / p));
            }
        }
示例#13
0
        /**
         * <p>
         * Computes W from the householder reflectors stored in the columns of the row block
         * submatrix Y.
         * </p>
         *
         * <p>
         * Y = v<sup>(1)</sup><br>
         * W = -&beta;<sub>1</sub>v<sup>(1)</sup><br>
         * for j=2:r<br>
         * &nbsp;&nbsp;z = -&beta;(I +WY<sup>T</sup>)v<sup>(j)</sup> <br>
         * &nbsp;&nbsp;W = [W z]<br>
         * &nbsp;&nbsp;Y = [Y v<sup>(j)</sup>]<br>
         * end<br>
         * <br>
         * where v<sup>(.)</sup> are the house holder vectors, and r is the block length.  Note that
         * Y already contains the householder vectors so it does not need to be modified.
         * </p>
         *
         * <p>
         * Y and W are assumed to have the same number of rows and columns.
         * </p>
         */
        public static void computeW_row(int blockLength,
                                        FSubmatrixD1 Y, FSubmatrixD1 W,
                                        float[] beta, int betaIndex)
        {
            int heightY = Y.row1 - Y.row0;

            CommonOps_FDRM.fill(W.original, 0);

            // W = -beta*v(1)
            BlockHouseHolder_FDRB.scale_row(blockLength, Y, W, 0, 1, -beta[betaIndex++]);

            int min = Math.Min(heightY, W.col1 - W.col0);

            // set up rest of the rows
            for (int i = 1; i < min; i++)
            {
                // w=-beta*(I + W*Y^T)*u
                float b = -beta[betaIndex++];

                // w = w -beta*W*(Y^T*u)
                for (int j = 0; j < i; j++)
                {
                    float yv = BlockHouseHolder_FDRB.innerProdRow(blockLength, Y, i, Y, j, 1);
                    VectorOps_FDRB.add_row(blockLength, W, i, 1, W, j, b * yv, W, i, 1, Y.col1 - Y.col0);
                }

                //w=w -beta*u + stuff above
                BlockHouseHolder_FDRB.add_row(blockLength, Y, i, b, W, i, 1, W, i, 1, Y.col1 - Y.col0);
            }
        }
示例#14
0
        public virtual FMatrixRBlock getT(FMatrixRBlock T)
        {
            if (T == null)
            {
                T = new FMatrixRBlock(A.numRows, A.numCols, A.blockLength);
            }
            else
            {
                if (T.numRows != A.numRows || T.numCols != A.numCols)
                {
                    throw new ArgumentException("T must have the same dimensions as the input matrix");
                }

                CommonOps_FDRM.fill(T, 0);
            }

            T.set(0, 0, A.data[0]);
            for (int i = 1; i < A.numRows; i++)
            {
                float d = A.get(i - 1, i);
                T.set(i, i, A.get(i, i));
                T.set(i - 1, i, d);
                T.set(i, i - 1, d);
            }

            return(T);
        }
示例#15
0
        /**
         * <p>
         * Checks to see if a matrix is orthogonal or isometric.
         * </p>
         *
         * @param Q The matrix being tested. Not modified.
         * @param tol Tolerance.
         * @return True if it passes the test.
         */
        public static bool isOrthogonal(FMatrixRMaj Q, float tol)
        {
            if (Q.numRows < Q.numCols)
            {
                throw new ArgumentException("The number of rows must be more than or equal to the number of columns");
            }

            FMatrixRMaj[] u = CommonOps_FDRM.columnsToVector(Q, null);

            for (int i = 0; i < u.Length; i++)
            {
                FMatrixRMaj a = u[i];

                for (int j = i + 1; j < u.Length; j++)
                {
                    float val = VectorVectorMult_FDRM.innerProd(a, u[j]);

                    if (!(Math.Abs(val) <= tol))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
        private bool extractSeparate(int numCols)
        {
            if (!computeEigenValues())
            {
                return(false);
            }

            // ---- set up the helper to decompose the same tridiagonal matrix
            // swap arrays instead of copying them to make it slightly faster
            helper.reset(numCols);
            diagSaved = helper.swapDiag(diagSaved);
            offSaved  = helper.swapOff(offSaved);

            // extract the orthogonal from the similar transform
            V = decomp.getQ(V, true);

            // tell eigenvector algorithm to update this matrix as it computes the rotators
            vector.setQ(V);

            // extract eigenvectors
            if (!vector.process(-1, null, null, values))
            {
                return(false);
            }

            // the ordering of the eigenvalues might have changed
            values = helper.copyEigenvalues(values);
            // the V matrix contains the eigenvectors.  Convert those into column vectors
            eigenvectors = CommonOps_FDRM.rowsToVector(V, eigenvectors);

            return(true);
        }
示例#17
0
        /**
         * <p>
         * Creates a pivot matrix that exchanges the rows in a matrix:
         * <br>
         * A' = P*A<br>
         * </p>
         * <p>
         * For example, if element 0 in 'pivots' is 2 then the first row in A' will be the 3rd row in A.
         * </p>
         *
         * @param ret If null then a new matrix is declared otherwise the results are written to it.  Is modified.
         * @param pivots Specifies the new order of rows in a matrix.
         * @param numPivots How many elements in pivots are being used.
         * @param transposed If the transpose of the matrix is returned.
         * @return A pivot matrix.
         */
        public static FMatrixRMaj pivotMatrix(FMatrixRMaj ret, int[] pivots, int numPivots, bool transposed)
        {
            if (ret == null)
            {
                ret = new FMatrixRMaj(numPivots, numPivots);
            }
            else
            {
                if (ret.numCols != numPivots || ret.numRows != numPivots)
                {
                    throw new ArgumentException("Unexpected matrix dimension");
                }
                CommonOps_FDRM.fill(ret, 0);
            }

            if (transposed)
            {
                for (int i = 0; i < numPivots; i++)
                {
                    ret.set(pivots[i], i, 1);
                }
            }
            else
            {
                for (int i = 0; i < numPivots; i++)
                {
                    ret.set(i, pivots[i], 1);
                }
            }

            return(ret);
        }
        public virtual bool setA(FMatrixRMaj A)
        {
            pinv.reshape(A.numCols, A.numRows, false);

            if (!svd.decompose(A))
            {
                return(false);
            }

            svd.getU(U_t, true);
            svd.getV(V, false);
            float[] S = svd.getSingularValues();
            int     N = Math.Min(A.numRows, A.numCols);

            // compute the threshold for singular values which are to be zeroed
            float maxSingular = 0;

            for (int i = 0; i < N; i++)
            {
                if (S[i] > maxSingular)
                {
                    maxSingular = S[i];
                }
            }

            float tau = threshold * Math.Max(A.numCols, A.numRows) * maxSingular;

            // computer the pseudo inverse of A
            if (maxSingular != 0.0f)
            {
                for (int i = 0; i < N; i++)
                {
                    float s = S[i];
                    if (s < tau)
                    {
                        S[i] = 0;
                    }
                    else
                    {
                        S[i] = 1.0f / S[i];
                    }
                }
            }

            // V*W
            for (int i = 0; i < V.numRows; i++)
            {
                int index = i * V.numCols;
                for (int j = 0; j < V.numCols; j++)
                {
                    V.data[index++] *= S[j];
                }
            }

            // V*W*U^T
            CommonOps_FDRM.mult(V, U_t, pinv);

            return(true);
        }
示例#19
0
        public void minus(FMatrixRMaj A, /**/ float b, FMatrixRMaj output)
        {
            CommonOps_FDRM.subtract(A, b, output);
        }

        public void plus(FMatrixRMaj A, /**/ float b, FMatrixRMaj output)
        {
            CommonOps_FDRM.add(A, b, output);
        }
        /**
         * Makes a draw on the distribution.  The results are added to parameter 'x'
         */
        public void next(FMatrixRMaj x)
        {
            for (int i = 0; i < r.numRows; i++)
            {
                r.set(i, 0, (float)rand.NextGaussian());
            }

            CommonOps_FDRM.multAdd(A, r, x);
        }
示例#21
0
        /**
         * <p>
         * Returns the null-space from the singular value decomposition. The null space is a set of non-zero vectors that
         * when multiplied by the original matrix return zero.
         * </p>
         *
         * <p>
         * The null space is found by extracting the columns in V that are associated singular values less than
         * or equal to the threshold. In some situations a non-compact SVD is required.
         * </p>
         *
         * @param svd A precomputed decomposition.  Not modified.
         * @param nullSpace Storage for null space.  Will be reshaped as needed.  Modified.
         * @param tol Threshold for selecting singular values.  Try UtilEjml.F_EPS.
         * @return The null space.
         */
        public static FMatrixRMaj nullSpace(SingularValueDecomposition_F32 <FMatrixRMaj> svd,
                                            FMatrixRMaj nullSpace, float tol)
        {
            int N = svd.numberOfSingularValues();

            float[] s = svd.getSingularValues();

            FMatrixRMaj V = svd.getV(null, true);

            if (V.numRows != svd.numCols())
            {
                throw new ArgumentException(
                          "Can't compute the null space using a compact SVD for a matrix of this size.");
            }

            // first determine the size of the null space
            int numVectors = svd.numCols() - N;

            for (int i = 0; i < N; i++)
            {
                if (s[i] <= tol)
                {
                    numVectors++;
                }
            }

            // declare output data
            if (nullSpace == null)
            {
                nullSpace = new FMatrixRMaj(numVectors, svd.numCols());
            }
            else
            {
                nullSpace.reshape(numVectors, svd.numCols());
            }

            // now extract the vectors
            int count = 0;

            for (int i = 0; i < N; i++)
            {
                if (s[i] <= tol)
                {
                    CommonOps_FDRM.extract(V, i, i + 1, 0, V.numCols, nullSpace, count++, 0);
                }
            }
            for (int i = N; i < svd.numCols(); i++)
            {
                CommonOps_FDRM.extract(V, i, i + 1, 0, V.numCols, nullSpace, count++, 0);
            }

            CommonOps_FDRM.transpose(nullSpace);

            return(nullSpace);
        }
示例#22
0
 /**
  * Computes the p=&#8734; norm.  If A is a matrix then the induced norm is computed.
  *
  * @param A Matrix or vector.
  * @return The norm.
  */
 public static float normPInf(FMatrixRMaj A)
 {
     if (MatrixFeatures_FDRM.isVector(A))
     {
         return(CommonOps_FDRM.elementMaxAbs(A));
     }
     else
     {
         return(inducedPInf(A));
     }
 }
示例#23
0
        /**
         * Compute the A matrix from the Q and R matrices.
         *
         * @return The A matrix.
         */
        public override FMatrixRMaj getA()
        {
            if (A.data.Length < numRows * numCols)
            {
                A = new FMatrixRMaj(numRows, numCols);
            }
            A.reshape(numRows, numCols, false);
            CommonOps_FDRM.mult(Q, R, A);

            return(A);
        }
示例#24
0
        public static void invert(LinearSolverDense <FMatrixRMaj> solver, FMatrix1Row A, FMatrixRMaj A_inv)
        {
            if (A.numRows != A_inv.numRows || A.numCols != A_inv.numCols)
            {
                throw new ArgumentException("A and A_inv must have the same dimensions");
            }

            CommonOps_FDRM.setIdentity(A_inv);

            solver.solve(A_inv, A_inv);
        }
        public override void invert(FMatrixRMaj A_inv)
        {
            if (A_inv.numCols != numRows || A_inv.numRows != numCols)
            {
                throw new ArgumentException("Unexpected dimensions for A_inv");
            }

            I.reshape(numRows, numRows);
            CommonOps_FDRM.setIdentity(I);

            solve(I, A_inv);
        }
示例#26
0
        public override void solve(FMatrixRMaj B, FMatrixRMaj X)
        {
            if (X.numRows != numCols)
            {
                throw new ArgumentException("Unexpected dimensions for X");
            }
            else if (B.numRows != numRows || B.numCols != X.numCols)
            {
                throw new ArgumentException("Unexpected dimensions for B");
            }

            int BnumCols = B.numCols;

            // get the pivots and transpose them
            int[] pivots = decomposition.getColPivots();

            // solve each column one by one
            for (int colB = 0; colB < BnumCols; colB++)
            {
                x_basic.reshape(numRows, 1);
                Y.reshape(numRows, 1);

                // make a copy of this column in the vector
                for (int i = 0; i < numRows; i++)
                {
                    Y.data[i] = B.get(i, colB);
                }

                // Solve Q*a=b => a = Q'*b
                CommonOps_FDRM.multTransA(Q, Y, x_basic);

                // solve for Rx = b using the standard upper triangular solver
                TriangularSolver_FDRM.solveU(R11.data, x_basic.data, rank);

                // finish the basic solution by filling in zeros
                x_basic.reshape(numCols, 1, true);
                for (int i = rank; i < numCols; i++)
                {
                    x_basic.data[i] = 0;
                }

                if (norm2Solution && rank < numCols)
                {
                    upgradeSolution(x_basic);
                }

                // save the results
                for (int i = 0; i < numCols; i++)
                {
                    X.set(pivots[i], colB, x_basic.data[i]);
                }
            }
        }
示例#27
0
        /**
         * An alternative implementation of {@link #multTransA_small} that performs well on large
         * matrices.  There is a relative performance hit when used on small matrices.
         *
         * @param A A matrix that is m by n. Not modified.
         * @param B A Vector that has length m. Not modified.
         * @param C A column vector that has length n. Modified.
         */
        public static void multTransA_reorder(FMatrix1Row A, FMatrixD1 B, FMatrixD1 C)
        {
            if (C.numCols != 1)
            {
                throw new MatrixDimensionException("C is not a column vector");
            }
            else if (C.numRows != A.numCols)
            {
                throw new MatrixDimensionException("C is not the expected length");
            }
            if (B.numRows == 1)
            {
                if (A.numRows != B.numCols)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else if (B.numCols == 1)
            {
                if (A.numRows != B.numRows)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else
            {
                throw new MatrixDimensionException("B is not a vector");
            }

            if (A.numRows == 0)
            {
                CommonOps_FDRM.fill(C, 0);
                return;
            }

            float B_val = B.get(0);

            for (int i = 0; i < A.numCols; i++)
            {
                C.set(i, A.get(i) * B_val);
            }

            int indexA = A.numCols;

            for (int i = 1; i < A.numRows; i++)
            {
                B_val = B.get(i);
                for (int j = 0; j < A.numCols; j++)
                {
                    C.plus(j, A.get(indexA++) * B_val);
                }
            }
        }
示例#28
0
        /**
         * <p>
         * Creates a randomly generated set of orthonormal vectors.  At most it can generate the same
         * number of vectors as the dimension of the vectors.
         * </p>
         *
         * <p>
         * This is done by creating random vectors then ensuring that they are orthogonal
         * to all the ones previously created with reflectors.
         * </p>
         *
         * <p>
         * NOTE: This employs a brute force O(N<sup>3</sup>) algorithm.
         * </p>
         *
         * @param dimen dimension of the space which the vectors will span.
         * @param numVectors How many vectors it should generate.
         * @param rand Used to create random vectors.
         * @return Array of N random orthogonal vectors of unit length.
         */
        // is there a faster algorithm out there? This one is a bit sluggish
        public static FMatrixRMaj[] span(int dimen, int numVectors, IMersenneTwister rand)
        {
            if (dimen < numVectors)
            {
                throw new ArgumentException("The number of vectors must be less than or equal to the dimension");
            }

            FMatrixRMaj[] u = new FMatrixRMaj[numVectors];

            u[0] = RandomMatrices_FDRM.rectangle(dimen, 1, -1, 1, rand);
            NormOps_FDRM.normalizeF(u[0]);

            for (int i = 1; i < numVectors; i++)
            {
//            Console.WriteLine(" i = "+i);
                FMatrixRMaj a = new FMatrixRMaj(dimen, 1);
                FMatrixRMaj r = null;

                for (int j = 0; j < i; j++)
                {
//                Console.WriteLine("j = "+j);
                    if (j == 0)
                    {
                        r = RandomMatrices_FDRM.rectangle(dimen, 1, -1, 1, rand);
                    }

                    // find a vector that is normal to vector j
                    // u[i] = (1/2)*(r + Q[j]*r)
                    a.set(r);
                    VectorVectorMult_FDRM.householder(-2.0f, u[j], r, a);
                    CommonOps_FDRM.add(r, a, a);
                    CommonOps_FDRM.scale(0.5f, a);

//                UtilEjml.print(a);

                    FMatrixRMaj t = a;
                    a = r;
                    r = t;

                    // normalize it so it doesn't get too small
                    float val = NormOps_FDRM.normF(r);
                    if (val == 0 || float.IsNaN(val) || float.IsInfinity(val))
                    {
                        throw new InvalidOperationException("Failed sanity check");
                    }
                    CommonOps_FDRM.divide(r, val);
                }

                u[i] = r;
            }

            return(u);
        }
示例#29
0
        /**
         * Creates a new random symmetric matrix that will have the specified real eigenvalues.
         *
         * @param num Dimension of the resulting matrix.
         * @param rand Random number generator.
         * @param eigenvalues Set of real eigenvalues that the matrix will have.
         * @return A random matrix with the specified eigenvalues.
         */
        public static FMatrixRMaj symmetricWithEigenvalues(int num, IMersenneTwister rand, float[] eigenvalues)
        {
            FMatrixRMaj V = RandomMatrices_FDRM.orthogonal(num, num, rand);
            FMatrixRMaj D = CommonOps_FDRM.diag(eigenvalues);

            FMatrixRMaj temp = new FMatrixRMaj(num, num);

            CommonOps_FDRM.mult(V, D, temp);
            CommonOps_FDRM.multTransB(temp, V, D);

            return(D);
        }
示例#30
0
        /**
         * <p>
         * Performs a matrix vector multiply.<br>
         * <br>
         * c = A * b <br>
         * and<br>
         * c = A * b<sup>T</sup> <br>
         * <br>
         * c<sub>i</sub> = Sum{ j=1:n, a<sub>ij</sub> * b<sub>j</sub>}<br>
         * <br>
         * where A is a matrix, b is a column or transposed row vector, and c is a column vector.
         * </p>
         *
         * @param A A matrix that is m by n. Not modified.
         * @param B A vector that has length n. Not modified.
         * @param C A column vector that has length m. Modified.
         */
        public static void mult(FMatrix1Row A, FMatrixD1 B, FMatrixD1 C)
        {
            if (C.numCols != 1)
            {
                throw new MatrixDimensionException("C is not a column vector");
            }
            else if (C.numRows != A.numRows)
            {
                throw new MatrixDimensionException("C is not the expected length");
            }

            if (B.numRows == 1)
            {
                if (A.numCols != B.numCols)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else if (B.numCols == 1)
            {
                if (A.numCols != B.numRows)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else
            {
                throw new MatrixDimensionException("B is not a vector");
            }

            if (A.numCols == 0)
            {
                CommonOps_FDRM.fill(C, 0);
                return;
            }

            int   indexA = 0;
            int   cIndex = 0;
            float b0     = B.get(0);

            for (int i = 0; i < A.numRows; i++)
            {
                float total = A.get(indexA++) * b0;

                for (int j = 1; j < A.numCols; j++)
                {
                    total += A.get(indexA++) * B.get(j);
                }

                C.set(cIndex++, total);
            }
        }