private List <Configuration> GenerateFirstSamples(IOptimizationProblem problem) { List <Configuration> returnList = new List <Configuration>(); int dimensionsCount = problem.DimensionsCount; returnList.Add(new Configuration(dimensionsCount)); for (int i = 0; i < dimensionsCount; i++) { double min = problem.GetMinForDimension(i); double max = problem.GetMaxForDimension(i); double step = problem.GetStepForDimension(i); List <Configuration> newConfigurations = new List <Configuration>(); foreach (Configuration conf in returnList) { for (double j = min; j < max; j += step) { Configuration configuration = conf.Clone(); configuration.SetValueForDimension(i, j); newConfigurations.Add(configuration); } conf.SetValueForDimension(i, max); } returnList.AddRange(newConfigurations); } return(returnList); }
/// <summary> /// Initializes the algorithm. /// </summary> /// <param name="problem">The problem.</param> /// <param name="location">The theta.</param> /// <param name="residuals">The initial residuals.</param> /// <param name="searchDirection">The initial search direction.</param> /// <returns>The state to be passed to the <see cref="UpdateDirection" /> function.</returns> protected override object InitializeAlgorithm(IOptimizationProblem <double, IDifferentiableCostFunction <double> > problem, Vector <double> location, Vector <double> residuals, out Vector <double> searchDirection) { // the initial search direction is along the residuals, // which makes the initial step a regular gradient descent. searchDirection = residuals; // return some state information return(null); }
/// <summary> /// Metoda de optimizare care gaseste solutia problemei /// </summary> /// public Chromosome Solve(IOptimizationProblem p, int populationSize, int maxGenerations, double crossoverRate, double mutationRate) { //throw new Exception("Aceasta metoda trebuie completata"); Chromosome[] population = new Chromosome[populationSize]; for (int i = 0; i < population.Length; i++) { population[i] = p.MakeChromosome(); p.ComputeFitness(population[i]); } for (int gen = 0; gen < maxGenerations; gen++) { Chromosome[] newPopulation = new Chromosome[populationSize]; //newPopulation[0] = Selection.GetBest(population); // elitism List <Chromosome> indivizi = new List <Chromosome>(); for (int i = 0; i < populationSize; i++) { indivizi.Add(population[i]); for (int j = 0; j < 3; ++j) { do { Chromosome c = Selection.Tournament(population); if (indivizi.Contains(c) == false) { indivizi.Add(c); break; } } while (true); } Chromosome individ_potential = Crossover.Arithmetic(population[i], indivizi, crossoverRate, mutationRate); indivizi.Clear(); p.ComputeFitness(individ_potential); if (individ_potential.Fitness >= population[i].Fitness) { newPopulation[i] = individ_potential; } else { newPopulation[i] = population[i]; } } for (int i = 0; i < populationSize; i++) { population[i] = newPopulation[i]; } } return(Selection.GetBest(population)); }
/// <summary> /// Initializes the algorithm. /// </summary> /// <param name="problem">The problem.</param> /// <param name="location">The theta.</param> /// <param name="residuals">The initial residuals.</param> /// <param name="searchDirection">The initial search direction.</param> /// <returns>The state to be passed to the <see cref="UpdateDirection" /> function.</returns> protected override object InitializeAlgorithm(IOptimizationProblem <double, IDifferentiableCostFunction <double> > problem, Vector <double> location, Vector <double> residuals, out Vector <double> searchDirection) { searchDirection = -residuals.Normalize(2); // at this point, no previous gradient exists var previousGradient = Vector <double> .Build.Dense(residuals.Count, Vector <double> .Zero); // no state required return(new State(previousGradient, problem)); }
private Tuple <double, Configuration> Optimize(IOptimizationProblem problem, int depth) { if (depth > _searchDepth) { return(null); } List <Configuration> firstSamples = GenerateFirstSamples(problem); List <Tuple <double, Configuration> > evaluations = new List <Tuple <double, Configuration> >(firstSamples.Count); foreach (Configuration sample in firstSamples) { evaluations.Add(new Tuple <double, Configuration>(problem.Evaluate(sample), sample)); } //REEVALUATE FIRST x percent if evaluation function is unstable for (int j = 1; j < 11; j++) { evaluations.Sort((x, y) => x.Item1.CompareTo(y.Item1)); int maxIndex = evaluations.Count / (2 * j); for (int i = 0; i < maxIndex; i++) { evaluations[i] = new Tuple <double, Configuration>((evaluations[i].Item1 + problem.Evaluate(evaluations[i].Item2)) / 2, evaluations[i].Item2); } } evaluations.Sort((x, y) => x.Item1.CompareTo(y.Item1)); List <IOptimizationProblem> newProblems = new List <IOptimizationProblem>(_spaceCoverageIndex); for (int i = 0; i < _spaceCoverageIndex; i++) { if (i < evaluations.Count) { newProblems.Add(new SubOptimizationProblem(evaluations[i].Item2, problem)); } } Tuple <double, Configuration> best = evaluations[0]; foreach (IOptimizationProblem newProblem in newProblems) { Tuple <double, Configuration> optimal = Optimize(newProblem, depth + 1); if (optimal != null) { if (optimal.Item1 < best.Item1) { best = optimal; } } } return(best); }
/// <summary> /// Initializes the algorithm. /// </summary> /// <param name="problem">The problem.</param> /// <param name="location">The theta.</param> /// <param name="residuals">The initial residuals.</param> /// <param name="searchDirection">The initial search direction.</param> /// <returns>The state to be passed to the <see cref="UpdateDirection" /> function.</returns> protected override object InitializeAlgorithm(IOptimizationProblem <double, IDifferentiableCostFunction <double> > problem, Vector <double> location, Vector <double> residuals, out Vector <double> searchDirection) { // determine a preconditioner var preconditioner = GetPreconditioner(problem, location); // get the preconditioned residuals var preconditionedResiduals = preconditioner.Inverse() * residuals; // the initial search direction is along the residuals, // which makes the initial step a regular gradient descent. searchDirection = preconditionedResiduals; // return some state information return(new State(problem, preconditionedResiduals)); }
/// <summary> /// Minimizes the specified problem. /// </summary> /// <param name="problem">The problem.</param> public override IOptimizationResult <double> Minimize(IOptimizationProblem <double, IDifferentiableCostFunction <double> > problem) { var maxIterations = MaxIterations; var increaseFactor = _stepIncreaseFactor; var decreaseFactor = _stepDecreaseFactor; var initialStepSize = _initialStepSize; // ReSharper disable once ExceptionNotDocumented var threshold = ErrorTolerance; // obtain the initial cost var costFunction = problem.CostFunction; var cost = 0D; var previousCost = double.MaxValue; // obtain the initial coefficients var coefficients = problem.GetInitialCoefficients(); var coefficientCount = coefficients.Count; // we need to store that last iteration's gradients var previousGradient = Vector <double> .Build.Dense(coefficientCount, Vector <double> .Zero); var secondPreviousGradient = Vector <double> .Build.Dense(coefficientCount, Vector <double> .Zero); // initialize the step widths var stepWidths = Vector <double> .Build.Dense(coefficientCount, initialStepSize); // loop over all allowed iterations for (var i = 0; i < maxIterations; ++i) { // obtain the cost cost = costFunction.CalculateCost(coefficients); // determine the change in cost var costChange = cost - previousCost; if (Math.Abs(costChange) <= threshold) { Debug.WriteLine("Stopping REGD at iteration {0}/{1} because costChange |{2}| <= {3}", i, maxIterations, costChange, threshold); break; } // determine changes in gradient direction var gradient = costFunction.Jacobian(coefficients); var gradientDirectionIndicator = gradient.PointwiseMultiply(previousGradient); var previousGradientDirectionIndicator = previousGradient.PointwiseMultiply(secondPreviousGradient); // update step sizes for each individual coefficient for (var p = 0; p < coefficientCount; ++p) { var gradientInOppositeDirection = gradientDirectionIndicator[p] < 0; var gradientInSameDirection = gradientDirectionIndicator[p] > 0; var previousGradientInSameDirection = previousGradientDirectionIndicator[p] >= 0; if (gradientInOppositeDirection) { // decrease step size for this coefficient stepWidths[p] *= decreaseFactor; } else if (gradientInSameDirection && previousGradientInSameDirection) // TODO check that condition { // increase step size for this coefficient stepWidths[p] *= increaseFactor; } else { // keep step size for this coefficient stepWidths[p] *= 1.0D; } } // determine the coefficient delta to apply var delta = gradient.MapIndexed((index, g) => Math.Sign(g) * stepWidths[index]); coefficients -= delta; // store values for the next iteration previousCost = cost; secondPreviousGradient = previousGradient; previousGradient = gradient; } return(new OptimizationResult <double>(cost, coefficients)); }
/// <summary> /// Initializes a new instance of the <see cref="State"/> class. /// </summary> /// <param name="previousGradient">The previous gradient.</param> public State(Vector <double> previousGradient, IOptimizationProblem <double, IDifferentiableCostFunction <double> > problem) { PreviousGradient = previousGradient; Problem = problem; }
public double[] Optimize(IOptimizationProblem problem) { Tuple <double, Configuration> configuration = Optimize(problem, 0); return(configuration.Item2.Value); }
public SubOptimizationProblem(Configuration sample, IOptimizationProblem parentProblem) { _sample = sample; _parentProblem = parentProblem; }
/// <summary> /// Minimizes the specified problem. /// </summary> /// <param name="problem">The problem.</param> /// <returns>IOptimizationResult<TData>.</returns> public abstract IOptimizationResult <TData> Minimize(IOptimizationProblem <TData, TCostFunction> problem);
/// <summary> /// Minimizes the specified problem. /// </summary> /// <param name="problem">The problem.</param> /// <returns>IOptimizationResult<TData>.</returns> public sealed override IOptimizationResult <double> Minimize(IOptimizationProblem <double, TCostFunction> problem) { var maxIterations = MaxIterations; // The idea is that we should stop the operation if ||residuals|| < epsilon. // Since the norm calculation requires taking the square root, // we instead square epsilon and compare against that. var epsilonSquare = ErrorToleranceSquared; // fetch a starting point and obtain the problem size var location = problem.GetInitialCoefficients(); var problemDimension = location.Count; // we want to restart nonlinear CG at least every n steps, // and use this variable as a counter. var iterationsUntilReset = problemDimension; // now we determine the initial residuals, which are defined to // be the opposite gradient direction var costFunction = problem.CostFunction; var residuals = -costFunction.Jacobian(location); // the initial search direction is along the residuals, // which makes the initial step a regular gradient descent. // However, some CG algorithms (especially when using a preconditioner) // might yield slightly different directions, so we'll leave that to // the initialization function. Vector <double> direction; // = residuals // initialize the algorithm object state = InitializeAlgorithm(problem, location, residuals, out direction); // determine the initial error var delta = residuals * residuals; var initialDelta = delta; var previousAlpha = 0.0D; // loop for the maximum iteration count for (var i = 0; i < maxIterations; ++i) { // stop if the gradient change is below the threshold if (delta <= epsilonSquare * initialDelta) // TODO the scaling with initialDelta does do some trouble every now and then ... { Debug.WriteLine("Stopping CG/S/FR at iteration {0}/{1} because cost |{2}| <= {3}", i, maxIterations, delta, epsilonSquare * initialDelta); break; } // var cost = costFunction.CalculateCost(x); // perform a line search to find the minimum along the given direction var alpha = PerformLineSearch(costFunction, location, direction, previousAlpha); previousAlpha = alpha; location += alpha * direction; // obtain the new residuals residuals = -costFunction.Jacobian(location); // obtain the update parameter var shouldContinue = UpdateDirection(state, location, residuals, ref direction, ref delta); // Conjugate Gradient can generate only n conjugate search directions // in n-dimensional space, so we'll reset the algorithm every n steps in order // to give nonlinear optimization a chance. // Alternatively, when the implementation decides that the resulting search direction // would be non-A-conjugate (e.g. non-orthogonal to all previous search directions), // reset is triggered as well. var shouldReset = (--iterationsUntilReset == 0) || !shouldContinue; if (shouldReset) { // reset the search direction to point towards the current // residuals (which are opposite of the gradient!) direction = residuals.Normalize(2); // reset the counter iterationsUntilReset = problemDimension; // reset the previous alpha previousAlpha = 0.0D; } } // that's it. var cost = costFunction.CalculateCost(location); return(new OptimizationResult <double>(cost, location)); }
/// <summary> /// Initializes the algorithm. /// </summary> /// <param name="problem">The problem.</param> /// <param name="location">The location.</param> /// <param name="residuals">The initial residuals.</param> /// <param name="searchDirection">The initial search direction.</param> /// <returns>The state to be passed to the <see cref="UpdateDirection" /> function.</returns> protected abstract object InitializeAlgorithm([NotNull] IOptimizationProblem <double, TCostFunction> problem, Vector <double> location, Vector <double> residuals, out Vector <double> searchDirection);
/// <summary> /// Initializes a new instance of the <see cref="State"/> class. /// </summary> /// <param name="problem">The problem.</param> /// <param name="previousPreconditionedResiduals">The previous preconditioned residuals.</param> public State(IOptimizationProblem <double, IDifferentiableCostFunction <double> > problem, Vector <double> previousPreconditionedResiduals) { Problem = problem; PreviousPreconditionedResiduals = previousPreconditionedResiduals; }
/// <summary> /// Gets a preconditioner for the residuals. /// </summary> /// <param name="problem">The problem.</param> /// <param name="theta">The coefficients to optimize.</param> /// <returns>MathNet.Numerics.LinearAlgebra.Matrix<System.Double>.</returns> private Matrix <double> GetPreconditioner([NotNull, UsedImplicitly] IOptimizationProblem <double, IDifferentiableCostFunction <double> > problem, Vector <double> theta) { // sadly we have no clue. return(Matrix <double> .Build.DiagonalIdentity(theta.Count)); }