public ObjectiveChecker1D(IObjectiveFunction1D objective, Action <IEvaluation1D> value_checker, Action <IEvaluation1D> gradient_checker, Action <IEvaluation1D> hessian_checker)
 {
     this.InnerObjective          = objective;
     this.ValueChecker            = value_checker;
     this.DerivativeChecker       = gradient_checker;
     this.SecondDerivativeChecker = hessian_checker;
 }
        public MinimizationOutput1D FindMinimum(IObjectiveFunction1D objective, double lower_bound, double upper_bound)
        {
            if (!(objective is ObjectiveChecker1D))
            {
                objective = new ObjectiveChecker1D(objective, this.ValueChecker, null, null);
            }

            if (upper_bound <= lower_bound)
            {
                throw new OptimizationException("Lower bound must be lower than upper bound.");
            }

            double        middle_point_x = lower_bound + (upper_bound - lower_bound) / (1 + _golden_ratio);
            IEvaluation1D lower          = objective.Evaluate(lower_bound);
            IEvaluation1D middle         = objective.Evaluate(middle_point_x);
            IEvaluation1D upper          = objective.Evaluate(upper_bound);

            int expansion_steps = 0;

            while ((expansion_steps < this.MaximumExpansionSteps) && (upper.Value < middle.Value || lower.Value < middle.Value))
            {
                if (lower.Value < middle.Value)
                {
                    lower_bound = 0.5 * (upper_bound + lower_bound) - this.LowerExpansionFactor * 0.5 * (upper_bound - lower_bound);
                    lower       = objective.Evaluate(lower_bound);
                }

                if (upper.Value < middle.Value)
                {
                    upper_bound = 0.5 * (upper_bound + lower_bound) + this.UpperExpansionFactor * 0.5 * (upper_bound - lower_bound);
                    upper       = objective.Evaluate(upper_bound);
                }

                middle_point_x = lower_bound + (upper_bound - lower_bound) / (1 + _golden_ratio);
                middle         = objective.Evaluate(middle_point_x);

                expansion_steps += 1;
            }

            if (upper.Value < middle.Value || lower.Value < middle.Value)
            {
                throw new OptimizationException("Lower and upper bounds do not necessarily bound a minimum.");
            }

            int iterations = 0;

            while (Math.Abs(upper.Point - lower.Point) > this.XTolerance && iterations < this.MaximumIterations)
            {
                double test_x = lower.Point + (upper.Point - middle.Point);
                var    test   = objective.Evaluate(test_x);

                if (test.Point < middle.Point)
                {
                    if (test.Value > middle.Value)
                    {
                        lower = test;
                    }
                    else
                    {
                        upper  = middle;
                        middle = test;
                    }
                }
                else
                {
                    if (test.Value > middle.Value)
                    {
                        upper = test;
                    }
                    else
                    {
                        lower  = middle;
                        middle = test;
                    }
                }

                iterations += 1;
            }

            if (iterations == this.MaximumIterations)
            {
                throw new MaximumIterationsException("Max iterations reached.");
            }
            else
            {
                return(new MinimizationOutput1D(middle, iterations, ExitCondition.BoundTolerance));
            }
        }
Esempio n. 3
0
        public MinimizationResult1D FindMinimum(IObjectiveFunction1D objective, double lowerBound, double upperBound)
        {
            if (upperBound <= lowerBound)
            {
                throw new OptimizationException("Lower bound must be lower than upper bound.");
            }

            double        middlePointX = lowerBound + (upperBound - lowerBound) / (1 + Constants.GoldenRatio);
            IEvaluation1D lower        = objective.Evaluate(lowerBound);
            IEvaluation1D middle       = objective.Evaluate(middlePointX);
            IEvaluation1D upper        = objective.Evaluate(upperBound);

            ValueChecker(lower.Value, lowerBound);
            ValueChecker(middle.Value, middlePointX);
            ValueChecker(upper.Value, upperBound);

            int expansion_steps = 0;

            while ((expansion_steps < this.MaximumExpansionSteps) && (upper.Value < middle.Value || lower.Value < middle.Value))
            {
                if (lower.Value < middle.Value)
                {
                    lowerBound = 0.5 * (upperBound + lowerBound) - this.LowerExpansionFactor * 0.5 * (upperBound - lowerBound);
                    lower      = objective.Evaluate(lowerBound);
                }

                if (upper.Value < middle.Value)
                {
                    upperBound = 0.5 * (upperBound + lowerBound) + this.UpperExpansionFactor * 0.5 * (upperBound - lowerBound);
                    upper      = objective.Evaluate(upperBound);
                }

                middlePointX = lowerBound + (upperBound - lowerBound) / (1 + Constants.GoldenRatio);
                middle       = objective.Evaluate(middlePointX);

                expansion_steps += 1;
            }

            if (upper.Value < middle.Value || lower.Value < middle.Value)
            {
                throw new OptimizationException("Lower and upper bounds do not necessarily bound a minimum.");
            }

            int iterations = 0;

            while (Math.Abs(upper.Point - lower.Point) > XTolerance && iterations < MaximumIterations)
            {
                double testX = lower.Point + (upper.Point - middle.Point);
                var    test  = objective.Evaluate(testX);
                ValueChecker(test.Value, testX);

                if (test.Point < middle.Point)
                {
                    if (test.Value > middle.Value)
                    {
                        lower = test;
                    }
                    else
                    {
                        upper  = middle;
                        middle = test;
                    }
                }
                else
                {
                    if (test.Value > middle.Value)
                    {
                        upper = test;
                    }
                    else
                    {
                        lower  = middle;
                        middle = test;
                    }
                }

                iterations += 1;
            }

            if (iterations == MaximumIterations)
            {
                throw new MaximumIterationsException("Max iterations reached.");
            }

            return(new MinimizationResult1D(middle, iterations, ExitCondition.BoundTolerance));
        }