Beispiel #1
0
        public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria)
        {
            // set up of the problem
            //double ftol = endCriteria.functionEpsilon();    // end criteria on f(x) (see Numerical Recipes in C++, p.410)
            double xtol = endCriteria.rootEpsilon(); // end criteria on x (see GSL v. 1.9, http://www.gnu.org/software/gsl/)
            int    maxStationaryStateIterations_ = endCriteria.maxStationaryStateIterations();

            EndCriteria.Type ecType = EndCriteria.Type.None;
            P.reset();
            Vector x_ = P.currentValue();
            int    iterationNumber_ = 0;

            // Initialize vertices of the simplex
            bool end = false;
            int  n   = x_.Count;

            vertices_ = new InitializedList <Vector>(n + 1, x_);
            for (int i = 0; i < n; i++)
            {
                Vector direction = new Vector(n, 0.0);
                Vector vertice   = vertices_[i + 1];
                direction[i] = 1.0;
                P.constraint().update(ref vertice, direction, lambda_);
                vertices_[i + 1] = vertice;
            }
            // Initialize function values at the vertices of the simplex
            values_ = new Vector(n + 1, 0.0);
            for (int i = 0; i <= n; i++)
            {
                values_[i] = P.value(vertices_[i]);
            }
            // Loop looking for minimum
            do
            {
                sum_ = new Vector(n, 0.0);
                for (int i = 0; i <= n; i++)
                {
                    sum_ += vertices_[i];
                }
                // Determine the best (iLowest), worst (iHighest)
                // and 2nd worst (iNextHighest) vertices
                int iLowest = 0;
                int iHighest;
                int iNextHighest;
                if (values_[0] < values_[1])
                {
                    iHighest     = 1;
                    iNextHighest = 0;
                }
                else
                {
                    iHighest     = 0;
                    iNextHighest = 1;
                }
                for (int i = 1; i <= n; i++)
                {
                    if (values_[i] > values_[iHighest])
                    {
                        iNextHighest = iHighest;
                        iHighest     = i;
                    }
                    else
                    {
                        if ((values_[i] > values_[iNextHighest]) && i != iHighest)
                        {
                            iNextHighest = i;
                        }
                    }
                    if (values_[i] < values_[iLowest])
                    {
                        iLowest = i;
                    }
                }
                // Now compute accuracy, update iteration number and check end criteria
                // GSL exit strategy on x (see GSL v. 1.9, http://www.gnu.org/software/gsl
                double simplexSize = Utils.computeSimplexSize(vertices_);
                ++iterationNumber_;
                if (simplexSize < xtol || endCriteria.checkMaxIterations(iterationNumber_, ref ecType))
                {
                    endCriteria.checkStationaryPoint(0.0, 0.0, ref maxStationaryStateIterations_, ref ecType);
                    endCriteria.checkMaxIterations(iterationNumber_, ref ecType);
                    x_ = vertices_[iLowest];
                    double low = values_[iLowest];
                    P.setFunctionValue(low);
                    P.setCurrentValue(x_);
                    return(ecType);
                }
                // If end criteria is not met, continue
                double factor = -1.0;
                double vTry   = extrapolate(ref P, iHighest, ref factor);
                if ((vTry <= values_[iLowest]) && (factor.IsEqual(-1.0)))
                {
                    factor = 2.0;
                    extrapolate(ref P, iHighest, ref factor);
                }
                else if (Math.Abs(factor) > Const.QL_EPSILON)
                {
                    if (vTry >= values_[iNextHighest])
                    {
                        double vSave = values_[iHighest];
                        factor = 0.5;
                        vTry   = extrapolate(ref P, iHighest, ref factor);
                        if (vTry >= vSave && Math.Abs(factor) > Const.QL_EPSILON)
                        {
                            for (int i = 0; i <= n; i++)
                            {
                                if (i != iLowest)
                                {
#if QL_ARRAY_EXPRESSIONS
                                    vertices_[i] = 0.5 * (vertices_[i] + vertices_[iLowest]);
#else
                                    vertices_[i] += vertices_[iLowest];
                                    vertices_[i] *= 0.5;
#endif
                                    values_[i] = P.value(vertices_[i]);
                                }
                            }
                        }
                    }
                }
                // If can't extrapolate given the constraints, exit
                if (Math.Abs(factor) <= Const.QL_EPSILON)
                {
                    x_ = vertices_[iLowest];
                    double low = values_[iLowest];
                    P.setFunctionValue(low);
                    P.setCurrentValue(x_);
                    return(EndCriteria.Type.StationaryFunctionValue);
                }
            }while (end == false);
            Utils.QL_FAIL("optimization failed: unexpected behaviour");
            return(0);
        }
        public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria)
        {
            // Initializations
            double ftol = endCriteria.functionEpsilon();
            int    maxStationaryStateIterations_ = endCriteria.maxStationaryStateIterations();

            EndCriteria.Type ecType = EndCriteria.Type.None; // reset end criteria
            P.reset();                                       // reset problem
            Vector x_ = P.currentValue();                    // store the starting point
            int    iterationNumber_ = 0;

            // dimension line search
            lineSearch_.searchDirection = new Vector(x_.size());
            bool done = false;

            // function and squared norm of gradient values
            double fnew, fold, gold2;
            double fdiff;
            // classical initial value for line-search step
            double t = 1.0;
            // Set gradient g at the size of the optimization problem
            // search direction
            int    sz = lineSearch_.searchDirection.size();
            Vector prevGradient = new Vector(sz), d = new Vector(sz), sddiff = new Vector(sz), direction = new Vector(sz);

            // Initialize cost function, gradient prevGradient and search direction
            P.setFunctionValue(P.valueAndGradient(ref prevGradient, x_));
            P.setGradientNormValue(Vector.DotProduct(prevGradient, prevGradient));
            lineSearch_.searchDirection = prevGradient * -1;

            bool first_time = true;

            // Loop over iterations
            do
            {
                // Linesearch
                if (!first_time)
                {
                    prevGradient = lineSearch_.lastGradient();
                }
                t = (lineSearch_.value(P, ref ecType, endCriteria, t));
                // don't throw: it can fail just because maxIterations exceeded
                if (lineSearch_.succeed())
                {
                    // Updates

                    // New point
                    x_ = lineSearch_.lastX();
                    // New function value
                    fold = P.functionValue();
                    P.setFunctionValue(lineSearch_.lastFunctionValue());
                    // New gradient and search direction vectors

                    // orthogonalization coef
                    gold2 = P.gradientNormValue();
                    P.setGradientNormValue(lineSearch_.lastGradientNorm2());

                    // conjugate gradient search direction
                    direction = getUpdatedDirection(P, gold2, prevGradient);

                    sddiff = direction - lineSearch_.searchDirection;
                    lineSearch_.searchDirection = direction;
                    // Now compute accuracy and check end criteria
                    // Numerical Recipes exit strategy on fx (see NR in C++, p.423)
                    fnew  = P.functionValue();
                    fdiff = 2.0 * Math.Abs(fnew - fold) /
                            (Math.Abs(fnew) + Math.Abs(fold) + Const.QL_EPSILON);

                    if (fdiff < ftol ||
                        endCriteria.checkMaxIterations(iterationNumber_, ref ecType))
                    {
                        endCriteria.checkStationaryFunctionValue(0.0, 0.0, ref maxStationaryStateIterations_, ref ecType);
                        endCriteria.checkMaxIterations(iterationNumber_, ref ecType);
                        return(ecType);
                    }
                    P.setCurrentValue(x_); // update problem current value
                    ++iterationNumber_;    // Increase iteration number
                    first_time = false;
                }
                else
                {
                    done = true;
                }
            }while (!done);
            P.setCurrentValue(x_);
            return(ecType);
        }
        public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria)
        {
            int stationaryStateIterations_ = 0;

            EndCriteria.Type ecType = EndCriteria.Type.None;
            P.reset();
            Vector x = P.currentValue();

            iteration_ = 0;
            n_         = x.size();
            ptry_      = new Vector(n_, 0.0);

            // build vertices

            vertices_ = new InitializedList <Vector>(n_ + 1, x);
            for (i_ = 0; i_ < n_; i_++)
            {
                Vector direction = new Vector(n_, 0.0);
                direction[i_] = 1.0;
                Vector tmp = vertices_[i_ + 1];
                P.constraint().update(ref tmp, direction, lambda_);
                vertices_[i_ + 1] = tmp;
            }

            values_ = new Vector(n_ + 1, 0.0);
            for (i_ = 0; i_ <= n_; i_++)
            {
                if (!P.constraint().test(vertices_[i_]))
                {
                    values_[i_] = Double.MaxValue;
                }
                else
                {
                    values_[i_] = P.value(vertices_[i_]);
                }
                if (Double.IsNaN(ytry_))
                {
                    // handle NAN
                    values_[i_] = Double.MaxValue;
                }
            }

            // minimize

            T_  = T0_;
            yb_ = Double.MaxValue;
            pb_ = new Vector(n_, 0.0);
            do
            {
                iterationT_ = iteration_;
                do
                {
                    sum_ = new Vector(n_, 0.0);
                    for (i_ = 0; i_ <= n_; i_++)
                    {
                        sum_ += vertices_[i_];
                    }
                    tt_   = -T_;
                    ilo_  = 0;
                    ihi_  = 1;
                    ynhi_ = values_[0] + tt_ * Math.Log(rng_.next().value);
                    ylo_  = ynhi_;
                    yhi_  = values_[1] + tt_ * Math.Log(rng_.next().value);
                    if (ylo_ > yhi_)
                    {
                        ihi_  = 0;
                        ilo_  = 1;
                        ynhi_ = yhi_;
                        yhi_  = ylo_;
                        ylo_  = ynhi_;
                    }

                    for (i_ = 2; i_ < n_ + 1; i_++)
                    {
                        yt_ = values_[i_] + tt_ * Math.Log(rng_.next().value);
                        if (yt_ <= ylo_)
                        {
                            ilo_ = i_;
                            ylo_ = yt_;
                        }

                        if (yt_ > yhi_)
                        {
                            ynhi_ = yhi_;
                            ihi_  = i_;
                            yhi_  = yt_;
                        }
                        else
                        {
                            if (yt_ > ynhi_)
                            {
                                ynhi_ = yt_;
                            }
                        }
                    }

                    // GSL end criterion in x (cf. above)
                    if (endCriteria.checkStationaryPoint(simplexSize(), 0.0,
                                                         ref stationaryStateIterations_,
                                                         ref ecType) ||
                        endCriteria.checkMaxIterations(iteration_, ref ecType))
                    {
                        // no matter what, we return the best ever point !
                        P.setCurrentValue(pb_);
                        P.setFunctionValue(yb_);
                        return(ecType);
                    }

                    iteration_ += 2;
                    amotsa(P, -1.0);
                    if (ytry_ <= ylo_)
                    {
                        amotsa(P, 2.0);
                    }
                    else
                    {
                        if (ytry_ >= ynhi_)
                        {
                            ysave_ = yhi_;
                            amotsa(P, 0.5);
                            if (ytry_ >= ysave_)
                            {
                                for (i_ = 0; i_ < n_ + 1; i_++)
                                {
                                    if (i_ != ilo_)
                                    {
                                        for (j_ = 0; j_ < n_; j_++)
                                        {
                                            sum_[j_] = 0.5 * (vertices_[i_][j_] +
                                                              vertices_[ilo_][j_]);
                                            vertices_[i_][j_] = sum_[j_];
                                        }

                                        values_[i_] = P.value(sum_);
                                    }
                                }

                                iteration_ += n_;
                                for (i_ = 0; i_ < n_; i_++)
                                {
                                    sum_[i_] = 0.0;
                                }
                                for (i_ = 0; i_ <= n_; i_++)
                                {
                                    sum_ += vertices_[i_];
                                }
                            }
                        }
                        else
                        {
                            iteration_ += 1;
                        }
                    }
                }while (iteration_ <
                        iterationT_ + (scheme_ == Scheme.ConstantFactor ? m_ : 1));

                switch (scheme_)
                {
                case Scheme.ConstantFactor:
                    T_ *= (1.0 - epsilon_);
                    break;

                case Scheme.ConstantBudget:
                    if (iteration_ <= K_)
                    {
                        T_ = T0_ *
                             Math.Pow(1.0 - Convert.ToDouble(iteration_) / Convert.ToDouble(K_), alpha_);
                    }
                    else
                    {
                        T_ = 0.0;
                    }
                    break;
                }
            }while (true);
        }
Beispiel #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);
        }