/// <summary> /// Solves the given problem. /// </summary> /// <returns></returns> public override TSolution Solve(TProblem problem, TObjective objective, out TFitness fitness) { var zero = objective.Zero; _log.Log(Logging.TraceEventType.Information, "Started generating initial solution..."); TFitness globalBestFitness; var globalBest = _generator.Solve(problem, objective, out globalBestFitness); _log.Log(Logging.TraceEventType.Information, "Initial solution generated: {0}.", globalBestFitness); // report new solution. this.ReportIntermidiateResult(globalBest); var difference = objective.Zero; if (_localSearch.Apply(problem, objective, globalBest, out difference)) { // localsearch leads to better solution, adjust the fitness. globalBestFitness = objective.Subtract(problem, globalBestFitness, difference); _log.Log(Logging.TraceEventType.Information, "Improvement found by local search: {0}.", globalBestFitness); // report new solution. this.ReportIntermidiateResult(globalBest); } var i = 0; var level = 1; while (!this.IsStopped && (_stopCondition == null || !_stopCondition.Invoke(i, level, problem, objective, globalBest))) { // keep running until stop condition is true or this solver is stopped. // shake things up a bit, or in other word change neighbourhood. var perturbedSolution = (TSolution)globalBest.Clone(); var perturbedDifference = objective.Zero; _perturber.Apply(problem, objective, perturbedSolution, level, out perturbedDifference); // improve things by using a local search procedure. var localSearchDifference = objective.Zero; _localSearch.ApplyUntil(problem, objective, perturbedSolution, out localSearchDifference); // calculate new fitness and compare. TFitness newFitness = default(TFitness); if (!objective.IsNonContinuous) { // solution fitness can be updated by adding the differences. newFitness = objective.Add(problem, globalBestFitness, perturbedDifference); newFitness = objective.Add(problem, newFitness, localSearchDifference); } else { // solution fitness needs to updated every time. newFitness = objective.Calculate(problem, perturbedSolution); } if (objective.IsBetterThan(problem, newFitness, globalBestFitness)) { // there was an improvement, keep new solution as global. globalBestFitness = newFitness; globalBest = perturbedSolution; level = 1; // reset level. _log.Log(Logging.TraceEventType.Information, "Improvement found by perturber and local search: {0}.", globalBestFitness); // report new solution. this.ReportIntermidiateResult(globalBest); } else { level = level + 1; } } _log.Log(Logging.TraceEventType.Information, "Stop condition reached, best: {0}.", globalBestFitness); fitness = globalBestFitness; return(globalBest); }