Пример #1
0
        //! QR Solve

        /*! This implementation is based on MINPACK
         *  (<http://www.netlib.org/minpack>,
         *  <http://www.netlib.org/cephes/linalg.tgz>)
         *
         *  Given an m by n matrix A, an n by n diagonal matrix d,
         *  and an m-vector b, the problem is to determine an x which
         *  solves the system
         *
         *  A*x = b ,     d*x = 0 ,
         *
         *  in the least squares sense.
         *
         *  d is an input array of length n which must contain the
         *  diagonal elements of the matrix d.
         *
         *  See lmdiff.cpp for further details.
         */
        public static Vector qrSolve(Matrix a, Vector b, bool pivot = true, Vector d = null)
        {
            int m = a.rows();
            int n = a.columns();

            if (d == null)
            {
                d = new Vector();
            }
            Utils.QL_REQUIRE(b.Count == m, () => "dimensions of A and b don't match");
            Utils.QL_REQUIRE(d.Count == n || d.empty(), () => "dimensions of A and d don't match");

            Matrix q = new Matrix(m, n), r = new Matrix(n, n);

            List <int> lipvt = MatrixUtilities.qrDecomposition(a, ref q, ref r, pivot);
            List <int> ipvt  = new List <int>(n);

            ipvt = lipvt;

            //std::copy(lipvt.begin(), lipvt.end(), ipvt.get());

            Matrix aT = Matrix.transpose(a);
            Matrix rT = Matrix.transpose(r);

            Vector sdiag = new Vector(n);
            Vector wa    = new Vector(n);

            Vector ld = new Vector(n, 0.0);

            if (!d.empty())
            {
                ld = d;
                //std::copy(d.begin(), d.end(), ld.begin());
            }
            Vector x   = new Vector(n);
            Vector qtb = Matrix.transpose(q) * b;

            MINPACK.qrsolv(n, rT, n, ipvt, ld, qtb, x, sdiag, wa);

            return(x);
        }
Пример #2
0
        //! QR decompoisition

        /*! This implementation is based on MINPACK
         *  (<http://www.netlib.org/minpack>,
         *  <http://www.netlib.org/cephes/linalg.tgz>)
         *
         *  This subroutine uses householder transformations with column
         *  pivoting (optional) to compute a qr factorization of the
         *  m by n matrix A. That is, qrfac determines an orthogonal
         *  matrix q, a permutation matrix p, and an upper trapezoidal
         *  matrix r with diagonal elements of nonincreasing magnitude,
         *  such that A*p = q*r.
         *
         *  Return value ipvt is an integer array of length n, which
         *  defines the permutation matrix p such that A*p = q*r.
         *  Column j of p is column ipvt(j) of the identity matrix.
         *
         *  See lmdiff.cpp for further details.
         */
        //public static List<int> qrDecomposition(Matrix A, Matrix q, Matrix r, bool pivot = true) {
        public static List <int> qrDecomposition(Matrix M, Matrix q, Matrix r, bool pivot)
        {
            Matrix mT = Matrix.transpose(M);
            int    m  = M.rows();
            int    n  = M.columns();

            List <int> lipvt = new InitializedList <int>(n);
            Vector     rdiag = new Vector(n);
            Vector     wa    = new Vector(n);

            MINPACK.qrfac(m, n, mT, 0, (pivot)?1:0, ref lipvt, n, ref rdiag, ref rdiag, wa);

            if (r.columns() != n || r.rows() != n)
            {
                r = new Matrix(n, n);
            }

            for (int i = 0; i < n; ++i)
            {
                //    std::fill(r.row_begin(i), r.row_begin(i)+i, 0.0);
                r[i, i] = rdiag[i];
                if (i < m)
                {
                    //        std::copy(mT.column_begin(i)+i+1, mT.column_end(i),
                    //                  r.row_begin(i)+i+1);
                }
                else
                {
                    //        std::fill(r.row_begin(i)+i+1, r.row_end(i), 0.0);
                }
            }

            if (q.rows() != m || q.columns() != n)
            {
                q = new Matrix(m, n);
            }

            Vector w = new Vector(m);
            //for (int k=0; k < m; ++k) {
            //    std::fill(w.begin(), w.end(), 0.0);
            //    w[k] = 1.0;

            //    for (int j=0; j < Math.Min(n, m); ++j) {
            //        double t3 = mT[j,j];
            //        if (t3 != 0.0) {
            //            double t
            //                = std::inner_product(mT.row_begin(j)+j, mT.row_end(j),
            //                                     w.begin()+j, 0.0)/t3;
            //            for (int i=j; i<m; ++i) {
            //                w[i]-=mT[j,i]*t;
            //            }
            //        }
            //        q[k,j] = w[j];
            //    }
            //    std::fill(q.row_begin(k) + Math.Min(n, m), q.row_end(k), 0.0);
            //}

            List <int> ipvt = new InitializedList <int>(n);

            //if (pivot) {
            //    std::copy(lipvt.get(), lipvt.get()+n, ipvt.begin());
            //}
            //else {
            //    for (int i=0; i < n; ++i)
            //        ipvt[i] = i;
            //}

            return(ipvt);
        }
Пример #3
0
        //! QR decompoisition

        /*! This implementation is based on MINPACK
         *  (<http://www.netlib.org/minpack>,
         *  <http://www.netlib.org/cephes/linalg.tgz>)
         *
         *  This subroutine uses householder transformations with column
         *  pivoting (optional) to compute a qr factorization of the
         *  m by n matrix A. That is, qrfac determines an orthogonal
         *  matrix q, a permutation matrix p, and an upper trapezoidal
         *  matrix r with diagonal elements of nonincreasing magnitude,
         *  such that A*p = q*r.
         *
         *  Return value ipvt is an integer array of length n, which
         *  defines the permutation matrix p such that A*p = q*r.
         *  Column j of p is column ipvt(j) of the identity matrix.
         *
         *  See lmdiff.cpp for further details.
         */
        //public static List<int> qrDecomposition(Matrix A, Matrix q, Matrix r, bool pivot = true) {
        public static List <int> qrDecomposition(Matrix M, ref Matrix q, ref Matrix r, bool pivot)
        {
            Matrix mT = Matrix.transpose(M);
            int    m  = M.rows();
            int    n  = M.columns();

            List <int> lipvt = new InitializedList <int>(n);
            Vector     rdiag = new Vector(n);
            Vector     wa    = new Vector(n);

            MINPACK.qrfac(m, n, mT, 0, (pivot)?1:0, ref lipvt, n, ref rdiag, ref rdiag, wa);

            if (r.columns() != n || r.rows() != n)
            {
                r = new Matrix(n, n);
            }

            for (int i = 0; i < n; ++i)
            {
                r[i, i] = rdiag[i];
                if (i < m)
                {
                    for (int j = i; j < mT.rows() - 1; j++)
                    {
                        r[i, j + 1] = mT[j + 1, i];
                    }
                }
            }

            if (q.rows() != m || q.columns() != n)
            {
                q = new Matrix(m, n);
            }

            Vector w = new Vector(m);

            for (int k = 0; k < m; ++k)
            {
                w.Erase();
                w[k] = 1.0;

                for (int j = 0; j < Math.Min(n, m); ++j)
                {
                    double t3 = mT[j, j];
                    if (t3 != 0.0)
                    {
                        double t = 0;
                        for (int kk = j; kk < mT.columns(); kk++)
                        {
                            t += (mT[j, kk] * w[kk]) / t3;
                        }

                        for (int i = j; i < m; ++i)
                        {
                            w[i] -= mT[j, i] * t;
                        }
                    }
                    q[k, j] = w[j];
                }
            }

            List <int> ipvt = new InitializedList <int>(n);

            if (pivot)
            {
                for (int i = 0; i < n; ++i)
                {
                    ipvt[i] = lipvt[i];
                }
            }
            else
            {
                for (int i = 0; i < n; ++i)
                {
                    ipvt[i] = i;
                }
            }

            return(ipvt);
        }
Пример #4
0
        public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria)
        {
            EndCriteria.Type ecType = EndCriteria.Type.None;
            P.reset();
            Vector x_ = P.currentValue();

            currentProblem_ = P;
            initCostValues_ = P.costFunction().values(x_);
            int m = initCostValues_.size();
            int n = x_.size();

            if (useCostFunctionsJacobian_)
            {
                initJacobian_ = new Matrix(m, n);
                P.costFunction().jacobian(initJacobian_, x_);
            }

            Vector xx = new Vector(x_);
            Vector fvec = new Vector(m), diag = new Vector(n);

            int    mode   = 1;
            double factor = 1;
            int    nprint = 0;
            int    info   = 0;
            int    nfev   = 0;

            Matrix fjac = new Matrix(m, n);

            int ldfjac = m;

            List <int> ipvt = new InitializedList <int>(n);
            Vector     qtf = new Vector(n), wa1 = new Vector(n), wa2 = new Vector(n), wa3 = new Vector(n), wa4 = new Vector(m);

            // call lmdif to minimize the sum of the squares of m functions
            // in n variables by the Levenberg-Marquardt algorithm.
            Func <int, int, Vector, int, Matrix> j = null;

            if (useCostFunctionsJacobian_)
            {
                j = jacFcn;
            }

            // requirements; check here to get more detailed error messages.
            Utils.QL_REQUIRE(n > 0, () => "no variables given");
            Utils.QL_REQUIRE(m >= n, () => $"less functions ({m}) than available variables ({n})");
            Utils.QL_REQUIRE(endCriteria.functionEpsilon() >= 0.0, () => "negative f tolerance");
            Utils.QL_REQUIRE(xtol_ >= 0.0, () => "negative x tolerance");
            Utils.QL_REQUIRE(gtol_ >= 0.0, () => "negative g tolerance");
            Utils.QL_REQUIRE(endCriteria.maxIterations() > 0, () => "null number of evaluations");

            MINPACK.lmdif(m, n, xx, ref fvec,
                          endCriteria.functionEpsilon(),
                          xtol_,
                          gtol_,
                          endCriteria.maxIterations(),
                          epsfcn_,
                          diag, mode, factor,
                          nprint, ref info, ref nfev, ref fjac,
                          ldfjac, ref ipvt, ref qtf,
                          wa1, wa2, wa3, wa4,
                          fcn, j);
            info_ = info;
            // check requirements & endCriteria evaluation
            Utils.QL_REQUIRE(info != 0, () => "MINPACK: improper input parameters");
            if (info != 6)
            {
                ecType = EndCriteria.Type.StationaryFunctionValue;
            }
            endCriteria.checkMaxIterations(nfev, ref ecType);
            Utils.QL_REQUIRE(info != 7, () => "MINPACK: xtol is too small. no further " +
                             "improvement in the approximate " +
                             "solution x is possible.");
            Utils.QL_REQUIRE(info != 8, () => "MINPACK: gtol is too small. fvec is " +
                             "orthogonal to the columns of the " +
                             "jacobian to machine precision.");
            // set problem
            x_ = new Vector(xx.GetRange(0, n));
            P.setCurrentValue(x_);
            P.setFunctionValue(P.costFunction().value(x_));

            return(ecType);
        }
Пример #5
0
        public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria)
        {
            EndCriteria.Type ecType = EndCriteria.Type.None;
            P.reset();
            Vector x_ = P.currentValue();

            currentProblem_ = P;
            initCostValues_ = P.costFunction().values(x_);
            int m = initCostValues_.size();
            int n = x_.size();

            if (useCostFunctionsJacobian_)
            {
                initJacobian_ = new Matrix(m, n);
                P.costFunction().jacobian(initJacobian_, x_);
            }

            Vector xx = new Vector(x_);
            Vector fvec = new Vector(m), diag = new Vector(n);

            int    mode   = 1;
            double factor = 1;
            int    nprint = 0;
            int    info   = 0;
            int    nfev   = 0;

            Matrix fjac = new Matrix(m, n);

            int ldfjac = m;

            List <int> ipvt = new InitializedList <int>(n);
            Vector     qtf = new Vector(n), wa1 = new Vector(n), wa2 = new Vector(n), wa3 = new Vector(n), wa4 = new Vector(m);

            // call lmdif to minimize the sum of the squares of m functions
            // in n variables by the Levenberg-Marquardt algorithm.
            Func <int, int, Vector, int, Matrix> j = null;

            if (useCostFunctionsJacobian_)
            {
                j = jacFcn;
            }

            MINPACK.lmdif(m, n, xx, ref fvec,
                          endCriteria.functionEpsilon(),
                          xtol_,
                          gtol_,
                          endCriteria.maxIterations(),
                          epsfcn_,
                          diag, mode, factor,
                          nprint, ref info, ref nfev, ref fjac,
                          ldfjac, ref ipvt, ref qtf,
                          wa1, wa2, wa3, wa4,
                          fcn, j);
            info_ = info;
            // check requirements & endCriteria evaluation
            if (info == 0)
            {
                throw new ApplicationException("MINPACK: improper input parameters");
            }
            //if(info == 6) throw new ApplicationException("MINPACK: ftol is too small. no further " +
            //                                             "reduction in the sum of squares is possible.");

            if (info != 6)
            {
                ecType = EndCriteria.Type.StationaryFunctionValue;
            }
            //QL_REQUIRE(info != 5, "MINPACK: number of calls to fcn has reached or exceeded maxfev.");
            endCriteria.checkMaxIterations(nfev, ref ecType);
            if (info == 7)
            {
                throw new ApplicationException("MINPACK: xtol is too small. no further " +
                                               "improvement in the approximate " +
                                               "solution x is possible.");
            }
            if (info == 8)
            {
                throw new ApplicationException("MINPACK: gtol is too small. fvec is " +
                                               "orthogonal to the columns of the " +
                                               "jacobian to machine precision.");
            }
            // set problem
            x_ = new Vector(xx.GetRange(0, n));
            P.setCurrentValue(x_);
            P.setFunctionValue(P.costFunction().value(x_));

            return(ecType);
        }