Пример #1
0
        double minimize()
        {
            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();

            lambda = new double[equalityConstraints.Length];
            mu     = new double[lesserThanConstraints.Length];
            nu     = new double[greaterThanConstraints.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;
                    }
                }

                System.Diagnostics.Debug.Assert(!Double.IsNaN(rho));
            }


            while (true)
            {
                double prevICM = ICM;

                try
                {
                    // Minimize the dual problem using current solution
                    currentValue = dualSolver.Minimize(currentSolution);
                }
                catch (LineSearchFailedException)
                {
                }
                catch (NotFiniteNumberException)
                {
                }

                // Retrieve the solution found
                currentSolution = dualSolver.Solution;

                // 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(minValue);
                        }

                        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(minValue);
                        }
                    }

                    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(minValue);
                    }

                    noProgressCounter++;

                    if (noProgressCounter > maxCount)
                    {
                        return(minValue);
                    }
                }


                // Go to next iteration
                iterations++;

                if (maxEvaluations > 0 && functionEvaluations >= maxEvaluations)
                {
                    return(minValue);
                }
            }
        }
Пример #2
0
        private AugmentedLagrangianStatus 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          = 100;

            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 = Solution.Copy();

            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 actual = equalityConstraints[i].Function(currentSolution);
                    double c      = actual - equalityConstraints[i].Value;

                    penalty += Math.Abs(c);
                    con2    += c * c;

                    feasible = feasible && Math.Abs(c) <= equalityConstraints[i].Tolerance;
                }

                // For each "lesser than" inequality constraint
                for (int i = 0; i < lesserThanConstraints.Length; i++)
                {
                    double actual = lesserThanConstraints[i].Function(currentSolution);
                    double c      = actual - lesserThanConstraints[i].Value;

                    if (c > 0)
                    {
                        penalty += c;
                        con2    += c * c;
                    }

                    feasible = feasible && c <= lesserThanConstraints[i].Tolerance;
                }

                // For each "greater than" inequality constraint
                for (int i = 0; i < greaterThanConstraints.Length; i++)
                {
                    double actual = greaterThanConstraints[i].Function(currentSolution);
                    double c      = greaterThanConstraints[i].Value - actual;
                    if (c > 0)
                    {
                        penalty += c;
                        con2    += c * c;
                    }

                    feasible = feasible && c <= greaterThanConstraints[i].Tolerance;
                }

                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(AugmentedLagrangianStatus.Cancelled);
                }

                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 actual = equalityConstraints[i].Function(currentSolution);
                    double c      = actual - 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 actual = lesserThanConstraints[i].Function(currentSolution);
                    double c      = actual - 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 actual = greaterThanConstraints[i].Function(currentSolution);
                    double c      = greaterThanConstraints[i].Value - actual;

                    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
                bool a = !minFeasible || penalty < minPenalty || currentValue < minValue;
                bool b = !minFeasible && penalty < minPenalty;
                if ((feasible && a) || b)
                {
                    AugmentedLagrangianStatus?r = null;

                    if (feasible)
                    {
                        if (relstop(minValue, currentValue, ftol_rel, ftol_abs))
                        {
                            r = AugmentedLagrangianStatus.Converged;
                        }

                        if (xtolreach(currentSolution, xtol_rel, 0))
                        {
                            r = AugmentedLagrangianStatus.Converged;
                        }
                    }

                    minValue    = currentValue;
                    minPenalty  = penalty;
                    minFeasible = feasible;

                    // Save the current solution
                    for (int i = 0; i < Solution.Length; i++)
                    {
                        Solution[i] = currentSolution[i];
                    }

                    if (r.HasValue)
                    {
                        return(r.Value);
                    }

                    noProgressCounter = 0;
                }
                else
                {
                    if (ICM == 0)
                    {
                        return(AugmentedLagrangianStatus.Converged);
                    }

                    noProgressCounter++;

                    if (noProgressCounter > maxCount)
                    {
                        return(AugmentedLagrangianStatus.NoProgress);
                    }
                }


                // Go to next iteration
                iterations++;

                if (maxEvaluations > 0 && functionEvaluations >= maxEvaluations)
                {
                    return(AugmentedLagrangianStatus.MaxEvaluations);
                }
            }
        }