/// <summary> /// Perform an operation on the current solution. /// </summary> /// <param name="operation">The local search operation to be performed.</param> /// <returns>If the operation improved the best known upper bound on the cost.</returns> public virtual bool PerformOperation(LocalSearchOperation operation) { this.PerformedOperations.Add(operation); operation.Execute(); if (this.CurrentSolution.Cost < this.BestCost) { this.BestCost = this.CurrentSolution.Cost; this.BestWidth = this.CurrentSolution.Width; return(true); } return(false); }
/// <summary> /// Perform a single iteration of the local search. /// </summary> /// <returns>Should the search continue?</returns> protected virtual bool PerformIteration() { LocalSearchOperation candidate = this.GetCandidate(); if (candidate == null) { return(false); } this.focus.PerformOperation(candidate); this.UpdateFocus(); Console.WriteLine($"{this.focus.CurrentSolution.Width.ToString("N2")} {this.focus.CurrentSolution.Cost.ToString("N0")}"); return(true); }
protected override LocalSearchOperation GetCandidate() { LocalSearchOperation candidate = null; double cost = this.cost; foreach (var op in this.operators) { foreach (var operation in op.Operations(this.focus.CurrentSolution, this.randomNumberGenerator)) { this.ExploredSolutions++; if (operation.Cost - cost < -PRECISION) { candidate = operation; cost = candidate.Cost; } } } return(candidate); }
protected override bool PerformIteration() { if (this.CurrentComputationTime - this.previousCooling > this.Q) { this.previousCooling = this.CurrentComputationTime; this.T *= ALPHA; } LocalSearchOperation candidate = this.GetCandidate(); if (candidate.Cost < this.focus.CurrentSolution.Cost) { if (candidate.Cost < this.focus.BestCost) { this.iterationsWithoutImprovement = 0; Console.WriteLine($"{this.CurrentComputationTime.ToString("N0")}: {this.focus.BestWidth.ToString("N2")} {candidate.Cost.ToString("N0")} | T={this.T.ToString("N2")}"); } this.focus.PerformOperation(candidate); var focus = this.focus; if (focus != this.UpdateFocus()) { this.Q = this.computeCoolingInterval(this.T, this.targetT, (int)(this.MaximumComputationTime - this.CurrentComputationTime)); } //Console.WriteLine($"{this.CurrentComputationTime.ToString("N0")}: {this.focus.CurrentSolution.Width.ToString("N2")} {this.focus.CurrentSolution.Cost.ToString("N0")} | T={this.T.ToString("N2")}"); } else { if (++this.iterationsWithoutImprovement > this.FailedIterationsUntilReset) { this.focus.Revert(); this.iterationsWithoutImprovement = 0; Console.WriteLine($"Reset"); } else if (this.acceptDeterioration(candidate.Cost - this.focus.CurrentSolution.Cost, this.T)) { //Console.WriteLine($"Accepted deterioration of size {(candidate.Cost - this.focus.CurrentSolution.Cost).ToString("N0")}, rejection {this.iterationsWithoutImprovement}"); this.focus.PerformOperation(candidate); } } return(true); }
protected override bool PerformIteration() { LocalSearchOperation candidate = this.GetCandidate(); // If no better neighbor is found if (candidate == null) { // Revert to the best solution so far. // Note: reverting is not necessary, it might be better to remove it. Console.WriteLine($"Perturbation of size {this.CurrentPerturbationSize} after {this.Failures + 1} failures; best = {this.focus.BestCost.ToString("F2")}"); if (this.focus.CurrentSolution.Cost > this.focus.BestCost) { this.focus.Revert(); } // Perturb the solution by taking a number of random steps. for (int i = 0; i < this.CurrentPerturbationSize; i++) { LocalSearchOperation operation = this.operators[this.randomNumberGenerator.Next(this.operators.Length)].GetRandomOperation(this.focus.CurrentSolution, this.randomNumberGenerator); this.focus.PerformOperation(operation); } Console.WriteLine($"Result of perturbation: {this.focus.CurrentSolution.Width.ToString("F2")} {this.focus.CurrentSolution.Cost.ToString("F0")}"); this.Failures++; } else { if (this.focus.PerformOperation(candidate)) { this.Failures = 0; } this.UpdateFocus(); Console.WriteLine($"{this.focus.CurrentSolution.Width.ToString("F2")} {this.focus.CurrentSolution.Cost.ToString("F0")}"); } return(true); }