Example #1
0
    EndCriteria::Type LevenbergMarquardt::minimize(Problem& P,
                                                   const EndCriteria& endCriteria) {
        EndCriteria::Type ecType = EndCriteria::None;
        P.reset();
        Array x_ = P.currentValue();
        currentProblem_ = &P;
        initCostValues_ = P.costFunction().values(x_);
        int m = initCostValues_.size();
        int n = x_.size();
        boost::scoped_array<double> xx(new double[n]);
        std::copy(x_.begin(), x_.end(), xx.get());
        boost::scoped_array<double> fvec(new double[m]);
        boost::scoped_array<double> diag(new double[n]);
        int mode = 1;
        double factor = 1;
        int nprint = 0;
        int info = 0;
        int nfev =0;
        boost::scoped_array<double> fjac(new double[m*n]);
        int ldfjac = m;
        boost::scoped_array<int> ipvt(new int[n]);
        boost::scoped_array<double> qtf(new double[n]);
        boost::scoped_array<double> wa1(new double[n]);
        boost::scoped_array<double> wa2(new double[n]);
        boost::scoped_array<double> wa3(new double[n]);
        boost::scoped_array<double> wa4(new double[m]);
        // requirements; check here to get more detailed error messages.
        QL_REQUIRE(n > 0, "no variables given");
        QL_REQUIRE(m >= n,
                   "less functions (" << m <<
                   ") than available variables (" << n << ")");
        QL_REQUIRE(endCriteria.functionEpsilon() >= 0.0,
                   "negative f tolerance");
        QL_REQUIRE(xtol_ >= 0.0, "negative x tolerance");
        QL_REQUIRE(gtol_ >= 0.0, "negative g tolerance");
        QL_REQUIRE(endCriteria.maxIterations() > 0,
                   "null number of evaluations");

        // call lmdif to minimize the sum of the squares of m functions
        // in n variables by the Levenberg-Marquardt algorithm.
        MINPACK::LmdifCostFunction lmdifCostFunction = 
            boost::bind(&LevenbergMarquardt::fcn, this, _1, _2, _3, _4, _5);
        MINPACK::lmdif(m, n, xx.get(), fvec.get(),
                       static_cast<double>(endCriteria.functionEpsilon()),
                       static_cast<double>(xtol_),
                       static_cast<double>(gtol_),
                       static_cast<int>(endCriteria.maxIterations()),
                       static_cast<double>(epsfcn_),
                       diag.get(), mode, factor,
                       nprint, &info, &nfev, fjac.get(),
                       ldfjac, ipvt.get(), qtf.get(),
                       wa1.get(), wa2.get(), wa3.get(), wa4.get(),
                       lmdifCostFunction);
        info_ = info;
        // check requirements & endCriteria evaluation
        QL_REQUIRE(info != 0, "MINPACK: improper input parameters");
        //QL_REQUIRE(info != 6, "MINPACK: ftol is too small. no further "
        //                               "reduction in the sum of squares "
        //                               "is possible.");
        if (info != 6) ecType = QuantLib::EndCriteria::StationaryFunctionValue;
        //QL_REQUIRE(info != 5, "MINPACK: number of calls to fcn has "
        //                               "reached or exceeded maxfev.");
        endCriteria.checkMaxIterations(nfev, ecType);
        QL_REQUIRE(info != 7, "MINPACK: xtol is too small. no further "
                                       "improvement in the approximate "
                                       "solution x is possible.");
        QL_REQUIRE(info != 8, "MINPACK: gtol is too small. fvec is "
                                       "orthogonal to the columns of the "
                                       "jacobian to machine precision.");
        // set problem
        std::copy(xx.get(), xx.get()+n, x_.begin());
        P.setCurrentValue(x_);
        P.setFunctionValue(P.costFunction().value(x_));
        
        return ecType;
    }
    EndCriteria::Type HybridSimulatedAnnealing<Sampler, Probability, Temperature, Reannealing>::minimize(Problem &P, const EndCriteria &endCriteria) {
        EndCriteria::Type ecType = EndCriteria::None;
        P.reset();
        reannealing_.setProblem(P);
        Array x = P.currentValue();
        Size n = x.size();
        Size k = 1;
        Size kStationary = 1;
        Size kReAnneal = 1;
        Size kReset = 1;
        Size maxK = endCriteria.maxIterations();
        Size maxKStationary = endCriteria.maxStationaryStateIterations();
        bool temperatureBreached = false;
        Array currentTemperature(n, startTemperature_);
        Array annealStep(n, 1.0);
        Array bestPoint(x);
        Array currentPoint(x);
        Array startingPoint(x);
        Array newPoint(x);
        Real bestValue = P.value(bestPoint);
        Real currentValue = bestValue;
        Real startingValue = bestValue; //to reset to starting point if desired
        while (k <= maxK && kStationary <= maxKStationary && !temperatureBreached)
        {
            //Draw a new sample point
            sampler_(newPoint, currentPoint, currentTemperature);

            //Evaluate new point
            Real newValue = P.value(newPoint);

            //Determine if new point is accepted
            if (probability_(currentValue, newValue, currentTemperature)) {
                if (optimizeScheme_ == EveryNewPoint) {
                    P.setCurrentValue(newPoint);
                    P.setFunctionValue(newValue);
                    localOptimizer_->minimize(P, endCriteria);
                    newPoint = P.currentValue();
                    newValue = P.functionValue();
                }
                currentPoint = newPoint;
                currentValue = newValue;
            }

            //Check if we have a new best point
            if (newValue < bestValue) {
                if (optimizeScheme_ == EveryBestPoint) {
                    P.setCurrentValue(newPoint);
                    P.setFunctionValue(newValue);
                    localOptimizer_->minimize(P, endCriteria);
                    newPoint = P.currentValue();
                    newValue = P.functionValue();
                }
                kStationary = 0;
                bestValue = newValue;
                bestPoint = newPoint;
            }

            //Increase steps
            k++;
            kStationary++;
            for (Size i = 0; i < annealStep.size(); i++)
                annealStep[i]++;

            //Reanneal if necessary
            if (kReAnneal == reAnnealSteps_) {
                kReAnneal = 0;
                reannealing_(annealStep, currentPoint, currentValue, currentTemperature);
            }
            kReAnneal++;

            //Reset if necessary
            if (kReset == resetSteps_) {
                kReset = 0;
                switch (resetScheme_) {
                case NoResetScheme:
                    break;
                case ResetToBestPoint:
                    currentPoint = startingPoint;
                    currentValue = startingValue;
                    break;
                case ResetToOrigin:
                    currentPoint = bestPoint;
                    currentValue = bestValue;
                    break;
                }
            }
            kReset++;

            //Update the current temperature according to current step
            temperature_(currentTemperature, currentTemperature, annealStep);

            //Check if temperature condition is breached
            for (Size i = 0; i < n; i++)
                temperatureBreached = temperatureBreached && currentTemperature[i] < endTemperature_;
        }
        //Change end criteria type if appropriate
        if (k > maxK)
            ecType = EndCriteria::MaxIterations;
        else if (kStationary > maxKStationary)
            ecType = EndCriteria::StationaryPoint;

        //Set result to best point
        P.setCurrentValue(bestPoint);
        P.setFunctionValue(bestValue);
        return ecType;
    }
    EndCriteria::Type FireflyAlgorithm::minimize(Problem &P, const EndCriteria &endCriteria) {
        QL_REQUIRE(!P.constraint().empty(), "Firefly Algorithm is a constrained optimizer");
        EndCriteria::Type ecType = EndCriteria::None;
        P.reset();
        Size iteration = 0;
        Size iterationStat = 0;
        Size maxIteration = endCriteria.maxIterations();
        Size maxIStationary = endCriteria.maxStationaryStateIterations();
        
        startState(P, endCriteria);

        bool isFA = Mfa_ > 0 ? true : false;
        //Variables for DE
        Array z(N_, 0.0);
        Size indexBest, indexR1, indexR2;

        //Set best value & position
        Real bestValue = values_[0].first;
        Size bestPosition = 0;
        for (Size i = 1; i < M_; i++) {
            if (values_[i].first < bestValue) {
                bestPosition = i;
                bestValue = values_[i].first;
            }
        }
        Array bestX = x_[bestPosition];

        //Run optimization
        do {
            iteration++;
            iterationStat++;
            //Check if stopping criteria is met
            if (iteration > maxIteration || iterationStat > maxIStationary)
                break;

            //Divide into two subpopulations
            //First sort values
            std::sort(values_.begin(), values_.end());

            //Differential evolution
            if(Mfa_ < M_){
                Size indexBest = values_[0].second;
                Array& xBest = x_[indexBest];
                for (Size i = Mfa_; i < M_; i++) { 
                    if (!isFA) {
                        //Pure DE requires random index
                        indexBest = drawIndex_();
                        xBest = x_[indexBest];
                    }
                    do { 
                        indexR1 = drawIndex_(); 
                    } while(indexR1 == indexBest);
                    do { 
                        indexR2 = drawIndex_(); 
                    } while(indexR2 == indexBest || indexR2 == indexR1);
                    
                    Size index = values_[i].second;
                    Array& x   = x_[index];
                    Array& xR1 = x_[indexR1];
                    Array& xR2 = x_[indexR2];
                    for (Size j = 0; j < N_; j++) {
                        if (rng_.nextReal() <= crossover_) {
                            //Change x[j] according to crossover
                            z[j] = xBest[j] + mutation_*(xR1[j] - xR2[j]);
                        } else {
                            z[j] = x[j];
                        }
                    }
                    Real val = P.value(z);
                    if (val < values_[index].first) {
                        //Accept new point
                        x = z;
                        values_[index].first = val;
                        //mark best
                        if (val < bestValue) {
                            bestValue = val;
                            bestX = x;
                            iterationStat = 0;
                        }
                    }
                }
            }
                
            //Firefly algorithm
            if(isFA){
                //According to the intensity, determine best global position
                intensity_->findBrightest();

                //Prepare random walk
                randomWalk_->walk();

                //Loop over particles
                for (Size i = 0; i < Mfa_; i++) {
                    Size index = values_[i].second;
                    Array& x   = x_[index];
                    Array& xI  = xI_[index];
                    Array& xRW = xRW_[index];

                    //Loop over dimensions
                    for (Size j = 0; j < N_; j++) {
                        //Update position
                        x[j] += xI[j] + xRW[j];
                        //Enforce bounds on positions
                        if (x[j] < lX_[j]) {
                            x[j] = lX_[j];
                        }
                        else if (x[j] > uX_[j]) {
                            x[j] = uX_[j];
                        }
                    }
                    //Evaluate x & mark best
                    values_[index].first = P.value(x);
                    if (values_[index].first < bestValue) {
                        bestValue = values_[index].first;
                        bestX = x;
                        iterationStat = 0;
                    }
                }
            }
        } while (true);
        if (iteration > maxIteration)
            ecType = EndCriteria::MaxIterations;
        else
            ecType = EndCriteria::StationaryPoint;

        //Set result to best point
        P.setCurrentValue(bestX);
        P.setFunctionValue(bestValue);
        return ecType;
    }
    EndCriteria::Type DifferentialEvolution::minimize(Problem& P,
											const EndCriteria& endCriteria) {

		EndCriteria::Type ecType = EndCriteria::MaxIterations;
	    QL_REQUIRE(P.currentValue().size() == nParam_,
			"Number of parameters mismatch between problem and DE optimizer");
        P.reset();		
		init();

		Real bestCost = QL_MAX_REAL;
		Size bestPop  = 0;
		for (Size p = 0; p < nPop_; ++p) {
			Array tmp(currGen_[p].pop_);
			try {
				currGen_[p].cost_ = P.costFunction().value(tmp);
			} catch (Error&) {
				currGen_[p].cost_ = QL_MAX_REAL;
			}
			if (currGen_[p].cost_ < bestCost) {
				bestPop = p;
				bestCost = currGen_[p].cost_;
			}
		}

		Size lastChange = 0;
		Size lastParamChange = 0;
		for(Size i=0; i<endCriteria.maxIterations(); ++i) {

			Size newBestPop = bestPop;
			Real newBestCost = bestCost;

			for (Size p=0; p<nPop_; ++p) {
				// Find 3 different populations randomly
				Size r1;
				do {
					r1 = static_cast <Size> (uniformRng_.nextInt32() % nPop_);
				}		
				while(r1 == p || r1 == bestPop);

				Size r2;
				do {
					r2 = static_cast <Size> (uniformRng_.nextInt32() % nPop_);
				}
				while ( r2 == p || r2 == bestPop || r2 == r1);

				Size r3;
				do {
					r3 = static_cast <Size> (uniformRng_.nextInt32() % nPop_);
				} while ( r3 == p || r3 == bestPop || r3 == r1 || r3 == r2);

				for(Size j=0; j<nParam_; ++j) {
					nextGen_[p].pop_[j] = currGen_[p].pop_[j];
				}

				Size j = static_cast <Size> (uniformRng_.nextInt32() % nParam_);
				Size L = 0;
				do {
					const double tmp = 
						currGen_[      p].pop_[j] * a0_
					  + currGen_[     r1].pop_[j] * a1_
					  + currGen_[     r2].pop_[j] * a2_
					  + currGen_[     r3].pop_[j] * a3_
					  + currGen_[bestPop].pop_[j] * aBest_;

					nextGen_[p].pop_[j] =
						std::min(maxParams_[j], std::max(minParams_[j], tmp));

					j = (j+1)%nParam_;
					++L;
				} while ((uniformRng_.nextReal() < CR_) && (L < nParam_));

				// Evaluate the new population
				Array tmp(nextGen_[p].pop_);
				try {
					nextGen_[p].cost_ = P.costFunction().value(tmp);
                } catch (Error&) {
					nextGen_[p].cost_ = QL_MAX_REAL;
                }

				// Not better, discard it and keep the old one.
				if (nextGen_[p].cost_ >= currGen_[p].cost_) {
					nextGen_[p] = currGen_[p];
				}
				// Better, keep it.
				else {
					// New best?
					if (nextGen_[p].cost_ < newBestCost) {
						newBestPop = p;
						newBestCost = nextGen_[p].cost_;
					}
				}
			}

			if(std::abs(newBestCost-bestCost) > endCriteria.functionEpsilon()) {
				lastChange = i;
			}
			const Array absDiff = Abs(nextGen_[newBestPop].pop_-currGen_[bestPop].pop_);
			if(*std::max_element(absDiff.begin(), absDiff.end()) > endCriteria.rootEpsilon()) {
				lastParamChange = i;
			}

			bestPop = newBestPop;
			bestCost = newBestCost;
			currGen_ = nextGen_;

            if(i-lastChange > endCriteria.maxStationaryStateIterations()) {
				ecType = EndCriteria::StationaryFunctionValue;
				break;
			}
			if(i-lastParamChange > endCriteria.maxStationaryStateIterations()) {
				ecType = EndCriteria::StationaryPoint;
				break;
			}

            if (adaptive_) adaptParameters();
		}
		
		const Array res(currGen_[bestPop].pop_);
        P.setCurrentValue(res);
        P.setFunctionValue(bestCost);
        
        return ecType;
    }
 inline void setSize(Size M, Size N, Real c0, const EndCriteria &endCriteria) {
     N_ = N;
     c0_ = c0;
     iteration_ = 0;
     maxIterations_ = endCriteria.maxIterations();
 }