예제 #1
0
        /**
         * Performs sanity checks on the input data and reshapes internal matrices.  By reshaping
         * a matrix it will only declare new memory when needed.
         */
        public void configure(DMatrixRMaj initParam, DMatrixRMaj X, DMatrixRMaj Y)
        {
            if (Y.getNumRows() != X.getNumRows())
            {
                throw new ArgumentException("Different vector lengths");
            }
            else if (Y.getNumCols() != 1 || X.getNumCols() != 1)
            {
                throw new ArgumentException("Inputs must be a column vector");
            }

            int numParam  = initParam.getNumElements();
            int numPoints = Y.getNumRows();

            if (param.getNumElements() != initParam.getNumElements())
            {
                // reshaping a matrix means that new memory is only declared when needed
                this.param.reshape(numParam, 1, false);
                this.d.reshape(numParam, 1, false);
                this.H.reshape(numParam, numParam, false);
                this.negDelta.reshape(numParam, 1, false);
                this.tempParam.reshape(numParam, 1, false);
                this.A.reshape(numParam, numParam, false);
            }

            param.set(initParam);

            // reshaping a matrix means that new memory is only declared when needed
            temp0.reshape(numPoints, 1, false);
            temp1.reshape(numPoints, 1, false);
            tempDH.reshape(numPoints, 1, false);
            jacobian.reshape(numParam, numPoints, false);
        }
예제 #2
0
        /**
         * Computes the d and H parameters.  Where d is the average error gradient and
         * H is an approximation of the hessian.
         */
        private void computeDandH(DMatrixRMaj param, DMatrixRMaj x, DMatrixRMaj y)
        {
            func.compute(param, x, tempDH);
            CommonOps_DDRM.subtractEquals(tempDH, y);

            computeNumericalJacobian(param, x, jacobian);

            int numParam = param.getNumElements();
            int length   = x.getNumElements();

            // d = average{ (f(x_i;p) - y_i) * jacobian(:,i) }
            for (int i = 0; i < numParam; i++)
            {
                double total = 0;
                for (int j = 0; j < length; j++)
                {
                    total += tempDH.get(j, 0) * jacobian.get(i, j);
                }
                d.set(i, 0, total / length);
            }

            // compute the approximation of the hessian
            CommonOps_DDRM.multTransB(jacobian, jacobian, H);
            CommonOps_DDRM.scale(1.0 / length, H);
        }
예제 #3
0
        public static void inv(DMatrixRMaj mat, DMatrixRMaj inv)
        {
            double max = Math.Abs(mat.data[0]);
            int    N   = mat.getNumElements();

            for (int i = 1; i < N; i++)
            {
                double a = Math.Abs(mat.data[i]);
                if (a > max)
                {
                    max = a;
                }
            }

            switch (mat.numRows)
            {
            case 2:
                inv2(mat, inv, 1.0 / max);
                break;

            case 3:
                inv3(mat, inv, 1.0 / max);
                break;

            case 4:
                inv4(mat, inv, 1.0 / max);
                break;

            case 5:
                inv5(mat, inv, 1.0 / max);
                break;

            default: throw new ArgumentException("Not supported");
            }
        }
예제 #4
0
        public static void convert(DMatrixRMaj src, FMatrixRMaj dst)
        {
            int N = src.getNumElements();

            for (int i = 0; i < N; i++)
            {
                dst.data[i] = (float)src.data[i];
            }
        }
예제 #5
0
        /**
         * <p>
         * Adds random values to each element in the matrix from an uniform distribution.<br>
         * <br>
         * a<sub>ij</sub> = a<sub>ij</sub> + U(min,max)<br>
         * </p>
         *
         * @param A The matrix who is to be randomized. Modified
         * @param min The minimum value each element can be.
         * @param max The maximum value each element can be..
         * @param rand Random number generator used to fill the matrix.
         */
        public static void addUniform(DMatrixRMaj A, double min, double max, IMersenneTwister rand)
        {
            double[] d    = A.getData();
            int      size = A.getNumElements();

            double r = max - min;

            for (int i = 0; i < size; i++)
            {
                d[i] += r * rand.NextDouble() + min;
            }
        }
예제 #6
0
        /**
         * <p>
         * Creates a reflector from the provided vector and gamma.<br>
         * <br>
         * Q = I - &gamma; u u<sup>T</sup><br>
         * </p>
         *
         * <p>
         * In practice {@link VectorVectorMult_DDRM#householder(double, DMatrixD1, DMatrixD1, DMatrixD1)}  multHouseholder}
         * should be used for performance reasons since there is no need to calculate Q explicitly.
         * </p>
         *
         * @param u A vector.  Not modified.
         * @param gamma To produce a reflector gamma needs to be equal to 2/||u||.
         * @return An orthogonal reflector.
         */
        public static DMatrixRMaj createReflector(DMatrixRMaj u, double gamma)
        {
            if (!MatrixFeatures_DDRM.isVector(u))
            {
                throw new ArgumentException("u must be a vector");
            }

            DMatrixRMaj Q = CommonOps_DDRM.identity(u.getNumElements());

            CommonOps_DDRM.multAddTransB(-gamma, u, u, Q);

            return(Q);
        }
예제 #7
0
        /**
         * Computes the QR decomposition of the provided matrix.
         *
         * @param A Matrix which is to be decomposed.  Not modified.
         */
        public void decompose(DMatrixRMaj A)
        {
            Equation.Equation eq = new Equation.Equation();

            this.QR = (DMatrixRMaj)A.copy();

            int N = Math.Min(A.numCols, A.numRows);

            gammas = new double[A.numCols];

            for (int i = 0; i < N; i++)
            {
                // update temporary variables
                eq.alias(QR.numRows - i, "Ni", QR, "QR", i, "i");

                // Place the column that should be zeroed into v
                eq.process("v=QR(i:,i)");
                eq.process("maxV=max(abs(v))");

                // Note that v is lazily created above.  Need direct access to it, which is done below.
                DMatrixRMaj v = eq.lookupMatrix("v");

                double maxV = eq.lookupDouble("maxV");
                if (maxV > 0 && v.getNumElements() > 1)
                {
                    // normalize to reduce overflow issues
                    eq.process("v=v/maxV");

                    // compute the magnitude of the vector
                    double tau = NormOps_DDRM.normF(v);

                    if (v.get(0) < 0)
                    {
                        tau *= -1.0;
                    }

                    eq.alias(tau, "tau");
                    eq.process("u_0 = v(0,0)+tau");
                    eq.process("gamma = u_0/tau");
                    eq.process("v=v/u_0");
                    eq.process("v(0,0)=1");
                    eq.process("QR(i:,i:) = (eye(Ni) - gamma*v*v')*QR(i:,i:)");
                    eq.process("QR(i:,i) = v");
                    eq.process("QR(i,i) = -1*tau*maxV");

                    // save gamma for recomputing Q later on
                    gammas[i] = eq.lookupDouble("gamma");
                }
            }
        }
예제 #8
0
        /**
         * Normalizes the matrix such that the Frobenius norm is equal to one.
         *
         * @param A The matrix that is to be normalized.
         */
        public static void normalizeF(DMatrixRMaj A)
        {
            double val = normF(A);

            if (val == 0)
            {
                return;
            }

            int size = A.getNumElements();

            for (int i = 0; i < size; i++)
            {
                A.div(i, val);
            }
        }
예제 #9
0
        /**
         * <p>
         * Performs a rank one update on matrix A using vectors u and w.  The results are stored in A.<br>
         * <br>
         * A = A + &gamma; u w<sup>T</sup><br>
         * </p>
         * <p>
         * This is called a rank1 update because the matrix u w<sup>T</sup> has a rank of 1.
         * </p>
         *
         * @param gamma A scalar.
         * @param A A m by m matrix. Modified.
         * @param u A vector with m elements.  Not modified.
         */
        public static void rank1Update(double gamma,
                                       DMatrixRMaj A,
                                       DMatrixRMaj u,
                                       DMatrixRMaj w)
        {
            int n = u.getNumElements();

            int matrixIndex = 0;

            for (int i = 0; i < n; i++)
            {
                double elementU = u.data[i];

                for (int j = 0; j < n; j++)
                {
                    A.data[matrixIndex++] += gamma * elementU * w.data[j];
                }
            }
        }
예제 #10
0
        /**
         * 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 - &gamma;*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;
                }
            }
        }