protected override bool Optimize()
{
double ICM = Double.PositiveInfinity;
double minPenalty = Double.PositiveInfinity;
double minValue = Double.PositiveInfinity;
double penalty;
double currentValue;
bool minFeasible = false;
int noProgressCounter = 0;
int maxCount = 20;
iterations = 0;
// magic parameters from Birgin & Martinez
const double tau = 0.5, gam = 10;
const double lam_min = -1e20;
const double lam_max = 1e20;
const double mu_max = 1e20;
const double nu_max = 1e20;
double[] currentSolution = (double[])Solution.Clone();
Array.Clear(lambda, 0, lambda.Length);
Array.Clear(mu, 0, mu.Length);
Array.Clear(nu, 0, nu.Length);
rho = 1;
// Starting rho suggested by B & M
if (lambda.Length > 0 || mu.Length > 0 || nu.Length > 0)
{
double con2 = 0;
penalty = 0;
// Evaluate function
functionEvaluations++;
currentValue = dualSolver.Function(currentSolution);
bool feasible = true;
// For each equality constraint
for (int i = 0; i < equalityConstraints.Length; i++)
{
double c = equalityConstraints[i].Function(currentSolution) - equalityConstraints[i].Value;
penalty += Math.Abs(c);
feasible = feasible && Math.Abs(c) <= equalityConstraints[i].Tolerance;
con2 += c * c;
}
// For each "lesser than" inequality constraint
for (int i = 0; i < lesserThanConstraints.Length; i++)
{
double c = lesserThanConstraints[i].Function(currentSolution) - lesserThanConstraints[i].Value;
penalty += c > 0 ? c : 0;
feasible = feasible && c <= lesserThanConstraints[i].Tolerance;
if (c > 0) con2 += c * c;
}
// For each "greater than" inequality constraint
for (int i = 0; i < greaterThanConstraints.Length; i++)
{
double c = -greaterThanConstraints[i].Function(currentSolution) + greaterThanConstraints[i].Value;
penalty += c > 0 ? c : 0;
feasible = feasible && c <= greaterThanConstraints[i].Tolerance;
if (c > 0) con2 += c * c;
}
minValue = currentValue;
minPenalty = penalty;
minFeasible = feasible;
double num = 2.0 * Math.Abs(minValue);
if (num < 1e-300)
rho = rhoMin;
else if (con2 < 1e-300)
rho = rhoMax;
else
{
rho = num / con2;
if (rho < rhoMin)
rho = rhoMin;
else if (rho > rhoMax)
rho = rhoMax;
}
Accord.Diagnostics.Debug.Assert(!Double.IsNaN(rho));
}
while (true)
{
if (Token.IsCancellationRequested)
return false;
double prevICM = ICM;
// Minimize the dual problem using current solution
for (int i = 0; i < dualSolver.Solution.Length; i++)
dualSolver.Solution[i] = currentSolution[i];
dualSolver.Minimize();
// Retrieve the solution found
for (int i = 0; i < currentSolution.Length; i++)
{
if (!Double.IsNaN(dualSolver.Solution[i]))
currentSolution[i] = dualSolver.Solution[i];
}
// Evaluate function
functionEvaluations++;
currentValue = dualSolver.Function(currentSolution);
ICM = 0;
penalty = 0;
bool feasible = true;
// Update lambdas
for (int i = 0; i < equalityConstraints.Length; i++)
{
double c = equalityConstraints[i].Function(currentSolution) - equalityConstraints[i].Value;
double newLambda = lambda[i] + rho * c;
penalty += Math.Abs(c);
feasible = feasible && Math.Abs(c) <= equalityConstraints[i].Tolerance;
ICM = Math.Max(ICM, Math.Abs(c));
lambda[i] = Math.Min(Math.Max(lam_min, newLambda), lam_max);
}
// Update mus
for (int i = 0; i < lesserThanConstraints.Length; i++)
{
double c = lesserThanConstraints[i].Function(currentSolution) - lesserThanConstraints[i].Value;
double newMu = mu[i] + rho * c;
penalty += c > 0 ? c : 0;
feasible = feasible && c <= lesserThanConstraints[i].Tolerance;
ICM = Math.Max(ICM, Math.Abs(Math.Max(c, -mu[i] / rho)));
mu[i] = Math.Min(Math.Max(0.0, newMu), mu_max);
}
// Update nus
for (int i = 0; i < greaterThanConstraints.Length; i++)
{
double c = -greaterThanConstraints[i].Function(currentSolution) + greaterThanConstraints[i].Value;
double newNu = nu[i] + rho * c;
penalty += c > 0 ? c : 0;
feasible = feasible && c <= greaterThanConstraints[i].Tolerance;
ICM = Math.Max(ICM, Math.Abs(Math.Max(c, -nu[i] / rho)));
nu[i] = Math.Min(Math.Max(0.0, newNu), nu_max);
}
// Update rho
if (ICM > tau * prevICM)
{
rho *= gam;
}
// Check if we should stop
if (
(feasible &&
(!minFeasible || penalty < minPenalty || currentValue < minValue)
) || (!minFeasible && penalty < minPenalty)
)
{
if (feasible)
{
if (relstop(minValue, currentValue, ftol_rel, ftol_abs))
return true;
bool xtolreach = true;
for (int i = 0; i < currentSolution.Length; i++)
{
if (!relstop(Solution[i], currentSolution[i], xtol_rel, 0))
xtolreach = false;
}
if (xtolreach)
return true;
}
minValue = currentValue;
minPenalty = penalty;
minFeasible = feasible;
// Save the current solution
for (int i = 0; i < Solution.Length; i++)
Solution[i] = currentSolution[i];
noProgressCounter = 0;
}
else
{
if (ICM == 0)
return true;
noProgressCounter++;
if (noProgressCounter > maxCount)
return true;
}
// Go to next iteration
iterations++;
if (maxEvaluations > 0 && functionEvaluations >= maxEvaluations)
return true;
}
}