protected void fillInitialPopulation(List <Candidate> population, Problem p) { // use initial values provided by the user population.First().values = p.currentValue().Clone(); population.First().cost = p.costFunction().value(population.First().values); if (Double.IsNaN(population.First().cost)) { population.First().cost = Double.MaxValue; } // rest of the initial population is random for (int j = 1; j < population.Count; ++j) { for (int i = 0; i < p.currentValue().size(); ++i) { double l = lowerBound_[i], u = upperBound_[i]; population[j].values[i] = l + (u - l) * rng_.nextReal(); } population[j].cost = p.costFunction().value(population[j].values); if (Double.IsNaN(population[j].cost)) { population[j].cost = Double.MaxValue; } } }
public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria) { EndCriteria.Type ecType = EndCriteria.Type.None; upperBound_ = P.constraint().upperBound(P.currentValue()); lowerBound_ = P.constraint().lowerBound(P.currentValue()); currGenSizeWeights_ = new Vector(configuration().populationMembers, configuration().stepsizeWeight); currGenCrossover_ = new Vector(configuration().populationMembers, configuration().crossoverProbability); List <Candidate> population = new InitializedList <Candidate>(configuration().populationMembers); population.ForEach((ii, vv) => population[ii] = new Candidate(P.currentValue().size())); fillInitialPopulation(population, P); //original quantlib use partial_sort as only first elements is needed double fxOld = population.Min(x => x.cost); bestMemberEver_ = (Candidate)population.First(x => x.cost.IsEqual(fxOld)).Clone(); int iteration = 0, stationaryPointIteration = 0; // main loop - calculate consecutive emerging populations while (!endCriteria.checkMaxIterations(iteration++, ref ecType)) { calculateNextGeneration(population, P.costFunction()); double fxNew = population.Min(x => x.cost); Candidate tmp = (Candidate)population.First(x => x.cost.IsEqual(fxNew)).Clone(); if (fxNew < bestMemberEver_.cost) { bestMemberEver_ = tmp; } if (endCriteria.checkStationaryFunctionValue(fxOld, fxNew, ref stationaryPointIteration, ref ecType)) { break; } fxOld = fxNew; } P.setCurrentValue(bestMemberEver_.values); P.setFunctionValue(bestMemberEver_.cost); return(ecType); }
public Matrix jacFcn(int m, int n, Vector x, int iflag) { Vector xt = new Vector(x); Matrix fjac; // constraint handling needs some improvement in the future: // starting point should not be close to a constraint violation if (currentProblem_.constraint().test(xt)) { Matrix tmp = new Matrix(m, n); currentProblem_.costFunction().jacobian(tmp, xt); Matrix tmpT = Matrix.transpose(tmp); fjac = new Matrix(tmpT); } else { Matrix tmpT = Matrix.transpose(initJacobian_); fjac = new Matrix(tmpT); } return(fjac); }
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); }