public NLCG( double precision, int maxIterLineSearch, int maxIterLineSearchZoom) { numericalDerivative = new OptimizationNumericalDerivative(5, 2); strongWolfeLineSearch = new StrongWolfeLineSearch(); MaxIterLineSearch = maxIterLineSearch; MaxIterLineSearchZoom = maxIterLineSearchZoom; Precision = precision; }
public BFGS( double precision, int maxIterLineSearch, int maxIterLineSearchZoom, bool earlyExit) { numericalDerivative = new OptimizationNumericalDerivative(13, 7); strongWolfeLineSearch = new StrongWolfeLineSearch(); MaxIterLineSearch = maxIterLineSearch; MaxIterLineSearchZoom = maxIterLineSearchZoom; EarlyExit = earlyExit; Precision = precision; }
/// <summary> /// Find the minimum of the objective function given lower and upper bounds /// </summary> /// <param name="objective">The objective function, must support a gradient</param> /// <param name="lowerBound">The lower bound</param> /// <param name="upperBound">The upper bound</param> /// <param name="initialGuess">The initial guess</param> /// <returns>The MinimizationResult which contains the minimum and the ExitCondition</returns> public MinimizationResult FindMinimum(IObjectiveFunction objective, Vector <double> lowerBound, Vector <double> upperBound, Vector <double> initialGuess) { _lowerBound = lowerBound; _upperBound = upperBound; if (!objective.IsGradientSupported) { throw new IncompatibleObjectiveException("Gradient not supported in objective function, but required for BFGS minimization."); } // Check that dimensions match if (lowerBound.Count != upperBound.Count || lowerBound.Count != initialGuess.Count) { throw new ArgumentException("Dimensions of bounds and/or initial guess do not match."); } // Check that initial guess is feasible for (int ii = 0; ii < initialGuess.Count; ++ii) { if (initialGuess[ii] < lowerBound[ii] || initialGuess[ii] > upperBound[ii]) { throw new ArgumentException("Initial guess is not in the feasible region"); } } objective.EvaluateAt(initialGuess); ValidateGradientAndObjective(objective); // Check that we're not already done ExitCondition currentExitCondition = ExitCriteriaSatisfied(objective, null, 0); if (currentExitCondition != ExitCondition.None) { return(new MinimizationResult(objective, 0, currentExitCondition)); } // Set up line search algorithm var lineSearcher = new StrongWolfeLineSearch(1e-4, 0.9, Math.Max(ParameterTolerance, 1e-5), maxIterations: 1000); // Declare state variables Vector <double> reducedSolution1, reducedGradient, reducedInitialPoint, reducedCauchyPoint, solution1; Matrix <double> reducedHessian; List <int> reducedMap; // First step var pseudoHessian = CreateMatrix.DiagonalIdentity <double>(initialGuess.Count); // Determine active set var gradientProjectionResult = QuadraticGradientProjectionSearch.Search(objective.Point, objective.Gradient, pseudoHessian, lowerBound, upperBound); var cauchyPoint = gradientProjectionResult.CauchyPoint; var fixedCount = gradientProjectionResult.FixedCount; var isFixed = gradientProjectionResult.IsFixed; var freeCount = lowerBound.Count - fixedCount; if (freeCount > 0) { reducedGradient = new DenseVector(freeCount); reducedHessian = new DenseMatrix(freeCount, freeCount); reducedMap = new List <int>(freeCount); reducedInitialPoint = new DenseVector(freeCount); reducedCauchyPoint = new DenseVector(freeCount); CreateReducedData(objective.Point, cauchyPoint, isFixed, lowerBound, upperBound, objective.Gradient, pseudoHessian, reducedInitialPoint, reducedCauchyPoint, reducedGradient, reducedHessian, reducedMap); // Determine search direction and maximum step size reducedSolution1 = reducedInitialPoint + reducedHessian.Cholesky().Solve(-reducedGradient); solution1 = ReducedToFull(reducedMap, reducedSolution1, cauchyPoint); } else { solution1 = cauchyPoint; } var directionFromCauchy = solution1 - cauchyPoint; var maxStepFromCauchyPoint = FindMaxStep(cauchyPoint, directionFromCauchy, lowerBound, upperBound); var solution2 = cauchyPoint + Math.Min(maxStepFromCauchyPoint, 1.0) * directionFromCauchy; var lineSearchDirection = solution2 - objective.Point; var maxLineSearchStep = FindMaxStep(objective.Point, lineSearchDirection, lowerBound, upperBound); var estStepSize = -objective.Gradient * lineSearchDirection / (lineSearchDirection * pseudoHessian * lineSearchDirection); var startingStepSize = Math.Min(Math.Max(estStepSize, 1.0), maxLineSearchStep); // Line search LineSearchResult lineSearchResult; try { lineSearchResult = lineSearcher.FindConformingStep(objective, lineSearchDirection, startingStepSize, upperBound: maxLineSearchStep); } catch (Exception e) { throw new InnerOptimizationException("Line search failed.", e); } var previousPoint = objective.Fork(); var candidatePoint = lineSearchResult.FunctionInfoAtMinimum; var gradient = candidatePoint.Gradient; var step = candidatePoint.Point - initialGuess; // Subsequent steps int totalLineSearchSteps = lineSearchResult.Iterations; int iterationsWithNontrivialLineSearch = lineSearchResult.Iterations > 0 ? 0 : 1; int iterations = DoBfgsUpdate(ref currentExitCondition, lineSearcher, ref pseudoHessian, ref lineSearchDirection, ref previousPoint, ref lineSearchResult, ref candidatePoint, ref step, ref totalLineSearchSteps, ref iterationsWithNontrivialLineSearch); if (iterations == MaximumIterations && currentExitCondition == ExitCondition.None) { throw new MaximumIterationsException(string.Format("Maximum iterations ({0}) reached.", MaximumIterations)); } return(new MinimizationWithLineSearchResult(candidatePoint, iterations, currentExitCondition, totalLineSearchSteps, iterationsWithNontrivialLineSearch)); }