#region License Information
/* HeuristicLab
* Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Operators;
using HeuristicLab.Optimization;
using HeuristicLab.Optimization.Operators;
using HeuristicLab.Parameters;
using HEAL.Attic;
using HeuristicLab.Selection;
namespace HeuristicLab.Algorithms.VariableNeighborhoodSearch {
///
/// An operator which represents a variable neighborhood search.
///
[Item("VariableNeighborhoodSearchMainLoop", "An operator which represents the main loop of a variable neighborhood search.")]
[StorableType("AB64D449-016E-4D18-82C6-4250DC948E01")]
public sealed class VariableNeighborhoodSearchMainLoop : AlgorithmOperator {
#region Parameter properties
public IValueLookupParameter RandomParameter {
get { return (IValueLookupParameter)Parameters["Random"]; }
}
public IValueLookupParameter MaximizationParameter {
get { return (IValueLookupParameter)Parameters["Maximization"]; }
}
public ILookupParameter QualityParameter {
get { return (ILookupParameter)Parameters["Quality"]; }
}
public IValueLookupParameter BestKnownQualityParameter {
get { return (IValueLookupParameter)Parameters["BestKnownQuality"]; }
}
public IValueLookupParameter EvaluatorParameter {
get { return (IValueLookupParameter)Parameters["Evaluator"]; }
}
public ILookupParameter IterationsParameter {
get { return (ILookupParameter)Parameters["Iterations"]; }
}
public IValueLookupParameter MaximumIterationsParameter {
get { return (IValueLookupParameter)Parameters["MaximumIterations"]; }
}
public IValueLookupParameter ResultsParameter {
get { return (IValueLookupParameter)Parameters["Results"]; }
}
public IValueLookupParameter AnalyzerParameter {
get { return (IValueLookupParameter)Parameters["Analyzer"]; }
}
public ILookupParameter EvaluatedSolutionsParameter {
get { return (ILookupParameter)Parameters["EvaluatedSolutions"]; }
}
public ILookupParameter CurrentNeighborhoodIndexParameter {
get { return (ILookupParameter)Parameters["CurrentNeighborhoodIndex"]; }
}
public ILookupParameter NeighborhoodCountParameter {
get { return (ILookupParameter)Parameters["NeighborhoodCount"]; }
}
public IValueLookupParameter LocalImprovementParameter {
get { return (IValueLookupParameter)Parameters["LocalImprovement"]; }
}
public IValueLookupParameter ShakingOperatorParameter {
get { return (IValueLookupParameter)Parameters["ShakingOperator"]; }
}
#endregion
[StorableConstructor]
private VariableNeighborhoodSearchMainLoop(StorableConstructorFlag _) : base(_) { }
public VariableNeighborhoodSearchMainLoop()
: base() {
Initialize();
}
private VariableNeighborhoodSearchMainLoop(VariableNeighborhoodSearchMainLoop original, Cloner cloner)
: base(original, cloner) {
}
public override IDeepCloneable Clone(Cloner cloner) {
return new VariableNeighborhoodSearchMainLoop(this, cloner);
}
private void Initialize() {
#region Create parameters
Parameters.Add(new ValueLookupParameter("Random", "A pseudo random number generator."));
Parameters.Add(new ValueLookupParameter("Maximization", "True if the problem is a maximization problem, otherwise false."));
Parameters.Add(new LookupParameter("Quality", "The value which represents the quality of a solution."));
Parameters.Add(new ValueLookupParameter("BestKnownQuality", "The best known quality value found so far."));
Parameters.Add(new ValueLookupParameter("Evaluator", "The operator used to evaluate solutions. This operator is executed in parallel, if an engine is used which supports parallelization."));
Parameters.Add(new LookupParameter("Iterations", "The iterations to count."));
Parameters.Add(new ValueLookupParameter("MaximumIterations", "The maximum number of generations which should be processed."));
Parameters.Add(new ValueLookupParameter("Results", "The variable collection where results should be stored."));
Parameters.Add(new ValueLookupParameter("Analyzer", "The operator used to analyze the solution."));
Parameters.Add(new LookupParameter("EvaluatedSolutions", "The number of evaluated solutions."));
Parameters.Add(new ValueLookupParameter("LocalImprovement", "The local improvement operation."));
Parameters.Add(new ValueLookupParameter("ShakingOperator", "The shaking operation."));
Parameters.Add(new LookupParameter("CurrentNeighborhoodIndex", "The index of the current shaking operation that should be applied."));
Parameters.Add(new LookupParameter("NeighborhoodCount", "The number of neighborhood operators used for shaking."));
#endregion
#region Create operators
VariableCreator variableCreator = new VariableCreator();
SubScopesProcessor subScopesProcessor0 = new SubScopesProcessor();
Assigner bestQualityInitializer = new Assigner();
Placeholder analyzer1 = new Placeholder();
ResultsCollector resultsCollector1 = new ResultsCollector();
CombinedOperator iteration = new CombinedOperator();
Assigner iterationInit = new Assigner();
SubScopesCloner createChild = new SubScopesCloner();
SubScopesProcessor childProcessor = new SubScopesProcessor();
Assigner qualityAssigner = new Assigner();
Placeholder shaking = new Placeholder();
Placeholder localImprovement = new Placeholder();
Placeholder evaluator = new Placeholder();
IntCounter evalCounter = new IntCounter();
QualityComparator qualityComparator = new QualityComparator();
ConditionalBranch improvesQualityBranch = new ConditionalBranch();
Assigner bestQualityUpdater = new Assigner();
BestSelector bestSelector = new BestSelector();
RightReducer rightReducer = new RightReducer();
IntCounter indexCounter = new IntCounter();
Assigner indexResetter = new Assigner();
Placeholder analyzer2 = new Placeholder();
Comparator indexComparator = new Comparator();
ConditionalBranch indexTermination = new ConditionalBranch();
IntCounter iterationsCounter = new IntCounter();
Comparator iterationsComparator = new Comparator();
ConditionalBranch iterationsTermination = new ConditionalBranch();
variableCreator.CollectedValues.Add(new ValueParameter("IsBetter", new BoolValue(false)));
variableCreator.CollectedValues.Add(new ValueParameter("BestQuality", new DoubleValue(0)));
bestQualityInitializer.Name = "Initialize BestQuality";
bestQualityInitializer.LeftSideParameter.ActualName = "BestQuality";
bestQualityInitializer.RightSideParameter.ActualName = QualityParameter.Name;
analyzer1.Name = "Analyzer (placeholder)";
analyzer1.OperatorParameter.ActualName = AnalyzerParameter.Name;
resultsCollector1.CopyValue = new BoolValue(false);
resultsCollector1.CollectedValues.Add(new LookupParameter("Best Quality", null, "BestQuality"));
resultsCollector1.ResultsParameter.ActualName = ResultsParameter.Name;
iteration.Name = "MainLoop Body";
iterationInit.Name = "Init k = 0";
iterationInit.LeftSideParameter.ActualName = CurrentNeighborhoodIndexParameter.Name;
iterationInit.RightSideParameter.Value = new IntValue(0);
createChild.Name = "Clone solution";
qualityAssigner.Name = "Assign quality";
qualityAssigner.LeftSideParameter.ActualName = "OriginalQuality";
qualityAssigner.RightSideParameter.ActualName = QualityParameter.Name;
shaking.Name = "Shaking operator (placeholder)";
shaking.OperatorParameter.ActualName = ShakingOperatorParameter.Name;
localImprovement.Name = "Local improvement operator (placeholder)";
localImprovement.OperatorParameter.ActualName = LocalImprovementParameter.Name;
evaluator.Name = "Evaluation operator (placeholder)";
evaluator.OperatorParameter.ActualName = EvaluatorParameter.Name;
evalCounter.Name = "Count evaluations";
evalCounter.Increment.Value = 1;
evalCounter.ValueParameter.ActualName = EvaluatedSolutionsParameter.ActualName;
qualityComparator.LeftSideParameter.ActualName = QualityParameter.Name;
qualityComparator.RightSideParameter.ActualName = "OriginalQuality";
qualityComparator.ResultParameter.ActualName = "IsBetter";
improvesQualityBranch.ConditionParameter.ActualName = "IsBetter";
bestQualityUpdater.Name = "Update BestQuality";
bestQualityUpdater.LeftSideParameter.ActualName = "BestQuality";
bestQualityUpdater.RightSideParameter.ActualName = QualityParameter.Name;
bestSelector.CopySelected = new BoolValue(false);
bestSelector.MaximizationParameter.ActualName = MaximizationParameter.Name;
bestSelector.NumberOfSelectedSubScopesParameter.Value = new IntValue(1);
bestSelector.QualityParameter.ActualName = QualityParameter.Name;
indexCounter.Name = "Count neighborhood index";
indexCounter.Increment.Value = 1;
indexCounter.ValueParameter.ActualName = CurrentNeighborhoodIndexParameter.Name;
indexResetter.Name = "Reset neighborhood index";
indexResetter.LeftSideParameter.ActualName = CurrentNeighborhoodIndexParameter.Name;
indexResetter.RightSideParameter.Value = new IntValue(0);
analyzer2.Name = "Analyzer (placeholder)";
analyzer2.OperatorParameter.ActualName = AnalyzerParameter.Name;
iterationsCounter.Name = "Iterations Counter";
iterationsCounter.Increment = new IntValue(1);
iterationsCounter.ValueParameter.ActualName = IterationsParameter.Name;
iterationsComparator.Name = "Iterations >= MaximumIterations";
iterationsComparator.Comparison = new Comparison(ComparisonType.GreaterOrEqual);
iterationsComparator.LeftSideParameter.ActualName = IterationsParameter.Name;
iterationsComparator.RightSideParameter.ActualName = MaximumIterationsParameter.Name;
iterationsComparator.ResultParameter.ActualName = "Terminate";
iterationsTermination.Name = "Iterations Termination Condition";
iterationsTermination.ConditionParameter.ActualName = "Terminate";
indexComparator.Name = "k < k_max (index condition)";
indexComparator.LeftSideParameter.ActualName = CurrentNeighborhoodIndexParameter.Name;
indexComparator.RightSideParameter.ActualName = NeighborhoodCountParameter.Name;
indexComparator.Comparison = new Comparison(ComparisonType.Less);
indexComparator.ResultParameter.ActualName = "ContinueIteration";
indexTermination.Name = "Index Termination Condition";
indexTermination.ConditionParameter.ActualName = "ContinueIteration";
#endregion
#region Create operator graph
OperatorGraph.InitialOperator = variableCreator;
variableCreator.Successor = subScopesProcessor0;
subScopesProcessor0.Operators.Add(bestQualityInitializer);
subScopesProcessor0.Successor = analyzer1;
analyzer1.Successor = resultsCollector1;
/////////
resultsCollector1.Successor = iteration;
iteration.OperatorGraph.InitialOperator = iterationInit;
iteration.Successor = iterationsCounter;
iterationInit.Successor = createChild;
createChild.Successor = childProcessor;
childProcessor.Operators.Add(new EmptyOperator());
childProcessor.Operators.Add(qualityAssigner);
childProcessor.Successor = bestSelector;
/////////
qualityAssigner.Successor = shaking;
shaking.Successor = evaluator;
evaluator.Successor = evalCounter;
evalCounter.Successor = localImprovement;
localImprovement.Successor = qualityComparator;
qualityComparator.Successor = improvesQualityBranch;
improvesQualityBranch.TrueBranch = bestQualityUpdater;
improvesQualityBranch.FalseBranch = indexCounter;
bestQualityUpdater.Successor = indexResetter;
indexResetter.Successor = null;
indexCounter.Successor = null;
/////////
bestSelector.Successor = rightReducer;
rightReducer.Successor = analyzer2;
analyzer2.Successor = indexComparator;
indexComparator.Successor = indexTermination;
indexTermination.TrueBranch = createChild;
indexTermination.FalseBranch = null;
iterationsCounter.Successor = iterationsComparator;
iterationsComparator.Successor = iterationsTermination;
iterationsTermination.TrueBranch = null;
iterationsTermination.FalseBranch = iteration;
#endregion
}
public override IOperation Apply() {
if (LocalImprovementParameter.ActualValue == null || ShakingOperatorParameter.ActualValue == null)
return null;
return base.Apply();
}
}
}