#region License Information /* HeuristicLab * Copyright (C) 2002-2009 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 System; using System.Collections.Generic; using System.Text; using System.Xml; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.SequentialEngine; using HeuristicLab.Operators; using HeuristicLab.Random; using HeuristicLab.Logging; using HeuristicLab.Selection; using HeuristicLab.Selection.OffspringSelection; using HeuristicLab.Evolutionary; namespace HeuristicLab.SA { /// /// Class for the heuristic optimization technique "simulated annealing". /// public class SA : ItemBase, IEditable { #region Create Operators /// /// Creates operators for the current instance. /// /// The engine where to add the operators. public static void Create(IEngine engine) { engine.OperatorGraph.Clear(); CombinedOperator co = CreateSA(); co.Name = "SA"; engine.OperatorGraph.AddOperator(co); engine.OperatorGraph.InitialOperator = co; engine.Reset(); } private static CombinedOperator CreateSA() { CombinedOperator op = new CombinedOperator(); SequentialProcessor sp = new SequentialProcessor(); op.OperatorGraph.AddOperator(sp); op.OperatorGraph.InitialOperator = sp; CombinedOperator co1 = CreateVariableInjection(); co1.Name = "Variable Injection"; op.OperatorGraph.AddOperator(co1); sp.AddSubOperator(co1); // place holder for ProblemInjector EmptyOperator eo1 = new EmptyOperator(); eo1.Name = "ProblemInjector"; op.OperatorGraph.AddOperator(eo1); co1.AddSubOperator(eo1); CombinedOperator co2 = CreateSolutionInitialization(); co2.Name = "Solution Initialization"; op.OperatorGraph.AddOperator(co2); sp.AddSubOperator(co2); // place holder for SolutionGenerator EmptyOperator eo2 = new EmptyOperator(); eo2.Name = "SolutionGenerator"; op.OperatorGraph.AddOperator(eo2); co2.AddSubOperator(eo2); // place holder for Evaluator EmptyOperator eo3 = new EmptyOperator(); eo3.Name = "Evaluator"; op.OperatorGraph.AddOperator(eo3); co2.AddSubOperator(eo3); CombinedOperator co3 = CreateSAMain(); co3.Name = "SA Main"; op.OperatorGraph.AddOperator(co3); sp.AddSubOperator(co3); EmptyOperator eo4 = new EmptyOperator(); eo4.Name = "AnnealingScheme"; op.OperatorGraph.AddOperator(eo4); co3.AddSubOperator(eo4); // place holder for Mutator EmptyOperator eo5 = new EmptyOperator(); eo5.Name = "Mutator"; op.OperatorGraph.AddOperator(eo5); co3.AddSubOperator(eo5); // place holder for Evaluator co3.AddSubOperator(eo3); return op; } private static CombinedOperator CreateVariableInjection() { CombinedOperator op = new CombinedOperator(); SequentialProcessor sp = new SequentialProcessor(); op.OperatorGraph.AddOperator(sp); op.OperatorGraph.InitialOperator = sp; RandomInjector ri = new RandomInjector(); op.OperatorGraph.AddOperator(ri); sp.AddSubOperator(ri); OperatorExtractor oe = new OperatorExtractor(); oe.Name = "ProblemInjector"; oe.GetVariableInfo("Operator").ActualName = "ProblemInjector"; op.OperatorGraph.AddOperator(oe); sp.AddSubOperator(oe); VariableInjector vi = new VariableInjector(); vi.AddVariable(new Variable("EvaluatedSolutions", new IntData(0))); vi.AddVariable(new Variable("Iteration", new IntData(0))); vi.AddVariable(new Variable("MaximumIterations", new IntData(1000))); vi.AddVariable(new Variable("Temperature", new DoubleData(100))); vi.AddVariable(new Variable("MinimumTemperature", new DoubleData(0))); vi.AddVariable(new Variable("AnnealingParameter", new DoubleData(0.95))); vi.AddVariable(new Variable("SuccessRatioLimit", new DoubleData(1))); vi.AddVariable(new Variable("MaximumIterationEffort", new DoubleData(1))); op.OperatorGraph.AddOperator(vi); sp.AddSubOperator(vi); return op; } private static CombinedOperator CreateSolutionInitialization() { CombinedOperator op = new CombinedOperator(); SequentialProcessor sp1 = new SequentialProcessor(); op.OperatorGraph.AddOperator(sp1); op.OperatorGraph.InitialOperator = sp1; SubScopesCreater ssc = new SubScopesCreater(); ssc.GetVariableInfo("SubScopes").Local = true; ssc.AddVariable(new Variable("SubScopes", new IntData(1))); op.OperatorGraph.AddOperator(ssc); sp1.AddSubOperator(ssc); UniformSequentialSubScopesProcessor ussp = new UniformSequentialSubScopesProcessor(); op.OperatorGraph.AddOperator(ussp); sp1.AddSubOperator(ussp); SequentialProcessor sp2 = new SequentialProcessor(); op.OperatorGraph.AddOperator(sp2); ussp.AddSubOperator(sp2); OperatorExtractor oe1 = new OperatorExtractor(); oe1.Name = "SolutionGenerator (Extractor)"; oe1.GetVariableInfo("Operator").ActualName = "SolutionGenerator"; op.OperatorGraph.AddOperator(oe1); sp2.AddSubOperator(oe1); OperatorExtractor oe2 = new OperatorExtractor(); oe2.Name = "Evaluator (Extractor)"; oe2.GetVariableInfo("Operator").ActualName = "Evaluator"; op.OperatorGraph.AddOperator(oe2); sp2.AddSubOperator(oe2); Counter c = new Counter(); c.GetVariableInfo("Value").ActualName = "EvaluatedSolutions"; op.OperatorGraph.AddOperator(c); sp2.AddSubOperator(c); return op; } private static CombinedOperator CreateSAMain() { CombinedOperator op = new CombinedOperator(); SequentialProcessor sp = new SequentialProcessor(); op.OperatorGraph.AddOperator(sp); op.OperatorGraph.InitialOperator = sp; SequentialProcessor sp1 = new SequentialProcessor(); op.OperatorGraph.AddOperator(sp1); sp.AddSubOperator(sp1); LeftSelector ls = new LeftSelector(); ls.GetVariable("CopySelected").GetValue().Data = true; ls.GetVariableInfo("Selected").Local = true; ls.AddVariable(new Variable("Selected", new IntData(1))); op.OperatorGraph.AddOperator(ls); sp1.AddSubOperator(ls); SequentialSubScopesProcessor ssp = new SequentialSubScopesProcessor(); op.OperatorGraph.AddOperator(ssp); sp1.AddSubOperator(ssp); EmptyOperator eo = new EmptyOperator(); op.OperatorGraph.AddOperator(eo); ssp.AddSubOperator(eo); CombinedOperator co1 = CreateCreateMutant(); co1.Name = "Create Mutant"; op.OperatorGraph.AddOperator(co1); ssp.AddSubOperator(co1); OffspringSelector oss = new OffspringSelector(); oss.GetVariableInfo("SelectionPressureLimit").ActualName = "MaximumIterationEffort"; op.OperatorGraph.AddOperator(oss); sp1.AddSubOperator(oss); oss.AddSubOperator(sp1); LessThanComparator ltc = new LessThanComparator(); ltc.Name = "SuccessRatio"; ltc.GetVariableInfo("LeftSide").ActualName = "SuccessRatio"; ltc.GetVariableInfo("RightSide").ActualName = "SuccessRatioLimit"; ltc.GetVariableInfo("Result").ActualName = "SuccessfulOS"; op.OperatorGraph.AddOperator(ltc); sp.AddSubOperator(ltc); ConditionalBranch cb = new ConditionalBranch(); cb.GetVariableInfo("Condition").ActualName = "SuccessfulOS"; op.OperatorGraph.AddOperator(cb); sp.AddSubOperator(cb); LeftReducer lr = new LeftReducer(); lr.Name = "No Replacement"; op.OperatorGraph.AddOperator(lr); cb.AddSubOperator(lr); RightReducer rr = new RightReducer(); rr.Name = "Replacement"; op.OperatorGraph.AddOperator(rr); cb.AddSubOperator(rr); QualityLogger ql = new QualityLogger(); op.OperatorGraph.AddOperator(ql); sp.AddSubOperator(ql); BestAverageWorstQualityCalculator bawqc = new BestAverageWorstQualityCalculator(); bawqc.GetVariableInfo("AverageQuality").Local = true; bawqc.GetVariableInfo("WorstQuality").Local = true; op.OperatorGraph.AddOperator(bawqc); sp.AddSubOperator(bawqc); DataCollector dc = new DataCollector(); ItemList names = dc.GetVariable("VariableNames").GetValue>(); names.Add(new StringData("BestQuality")); op.OperatorGraph.AddOperator(dc); sp.AddSubOperator(dc); LinechartInjector lci = new LinechartInjector(); lci.GetVariableInfo("Linechart").ActualName = "Quality Linechart"; lci.GetVariable("NumberOfLines").GetValue().Data = 1; op.OperatorGraph.AddOperator(lci); sp.AddSubOperator(lci); Counter c = new Counter(); c.GetVariableInfo("Value").ActualName = "Iteration"; op.OperatorGraph.AddOperator(c); sp.AddSubOperator(c); VariableAssigner va = new VariableAssigner(); va.Name = "Reset SelectionPressure"; va.GetVariableInfo("Variable").ActualName = "SelectionPressure"; va.GetVariableInfo("Value").Local = true; va.AddVariable(new Variable("Value", new DoubleData(1))); op.OperatorGraph.AddOperator(va); sp.AddSubOperator(va); OperatorExtractor oe = new OperatorExtractor(); oe.Name = "AnnealingScheme (Extractor)"; oe.GetVariableInfo("Operator").ActualName = "AnnealingScheme"; op.OperatorGraph.AddOperator(oe); sp.AddSubOperator(oe); GreaterThanComparator gtc = new GreaterThanComparator(); gtc.Name = "Temperature > MinimumTemperature"; gtc.GetVariableInfo("LeftSide").ActualName = "Temperature"; gtc.GetVariableInfo("RightSide").ActualName = "MinimumTemperature"; gtc.GetVariableInfo("Result").ActualName = "TemperatureCondition"; op.OperatorGraph.AddOperator(gtc); sp.AddSubOperator(gtc); ConditionalBranch cb1 = new ConditionalBranch(); cb1.GetVariableInfo("Condition").ActualName = "TemperatureCondition"; op.OperatorGraph.AddOperator(cb1); sp.AddSubOperator(cb1); SequentialProcessor sp2 = new SequentialProcessor(); op.OperatorGraph.AddOperator(sp2); cb1.AddSubOperator(sp2); LessThanComparator ltc1 = new LessThanComparator(); ltc1.Name = "Iteration < MaximumIterations"; ltc1.GetVariableInfo("LeftSide").ActualName = "Iteration"; ltc1.GetVariableInfo("RightSide").ActualName = "MaximumIterations"; ltc1.GetVariableInfo("Result").ActualName = "IterationsCondition"; op.OperatorGraph.AddOperator(ltc1); sp2.AddSubOperator(ltc1); ConditionalBranch cb2 = new ConditionalBranch(); cb2.GetVariableInfo("Condition").ActualName = "IterationsCondition"; op.OperatorGraph.AddOperator(cb2); sp2.AddSubOperator(cb2); cb2.AddSubOperator(sp); return op; } private static CombinedOperator CreateCreateMutant() { CombinedOperator op = new CombinedOperator(); SequentialProcessor sp1 = new SequentialProcessor(); op.OperatorGraph.AddOperator(sp1); op.OperatorGraph.InitialOperator = sp1; ChildrenInitializer ci = new ChildrenInitializer(); ci.GetVariable("ParentsPerChild").GetValue().Data = 1; op.OperatorGraph.AddOperator(ci); sp1.AddSubOperator(ci); UniformSequentialSubScopesProcessor ussp = new UniformSequentialSubScopesProcessor(); op.OperatorGraph.AddOperator(ussp); sp1.AddSubOperator(ussp); SequentialProcessor sp2 = new SequentialProcessor(); op.OperatorGraph.AddOperator(sp2); ussp.AddSubOperator(sp2); VariablesCopier vc = new VariablesCopier(); op.OperatorGraph.AddOperator(vc); sp2.AddSubOperator(vc); OperatorExtractor oe = new OperatorExtractor(); oe.Name = "Mutator (Extractor)"; oe.GetVariableInfo("Operator").ActualName = "Mutator"; op.OperatorGraph.AddOperator(oe); sp2.AddSubOperator(oe); OperatorExtractor oe1 = new OperatorExtractor(); oe1.Name = "Evaluator (Extractor)"; oe1.GetVariableInfo("Operator").ActualName = "Evaluator"; op.OperatorGraph.AddOperator(oe1); sp2.AddSubOperator(oe1); Counter c = new Counter(); c.GetVariableInfo("Value").ActualName = "EvaluatedSolutions"; op.OperatorGraph.AddOperator(c); sp2.AddSubOperator(c); TemperatureBasedFitnessComparer tbfc = new TemperatureBasedFitnessComparer(); op.OperatorGraph.AddOperator(tbfc); sp2.AddSubOperator(tbfc); SubScopesRemover sr = new SubScopesRemover(); sr.GetVariableInfo("SubScopeIndex").Local = true; op.OperatorGraph.AddOperator(sr); sp2.AddSubOperator(sr); return op; } #endregion #region Properties private IEngine myEngine; /// /// Gets the engine of the current instance. /// public IEngine Engine { get { return myEngine; } } private BoolData mySetSeedRandomly; /// /// Gets or sets the flag whether to set the seed randomly or not. /// public bool SetSeedRandomly { get { return mySetSeedRandomly.Data; } set { mySetSeedRandomly.Data = value; } } private IntData mySeed; /// /// Gets or sets the value of the seed of the current instance. /// public int Seed { get { return mySeed.Data; } set { mySeed.Data = value; } } private IntData myMaximumIterations; /// /// Gets or sets the number of maximum iterations. /// public int MaximumIterations { get { return myMaximumIterations.Data; } set { myMaximumIterations.Data = value; } } private DoubleData myTemperature; /// /// Gets or sets the initial temperature. /// public double Temperature { get { return myTemperature.Data; } set { myTemperature.Data = value; } } private DoubleData myMinimumTemperature; /// /// Gets or sets the minimum temperature. /// public double MinimumTemperature { get { return myMinimumTemperature.Data; } set { myMinimumTemperature.Data = value; } } private DoubleData myAnnealingParameter; /// /// Gets or sets the annealing parameter. /// public double AnnealingParameter { get { return myAnnealingParameter.Data; } set { myAnnealingParameter.Data = value; } } private DoubleData myMaximumIterationEffort; /// /// Gets or sets how much solutions should be created in one temperature in attempt to find a better one. /// public double MaximumIterationEffort { get { return myMaximumIterationEffort.Data; } set { myMaximumIterationEffort.Data = value; } } private CombinedOperator mySA; private IOperator myVariableInjection; /// /// Gets or sets the problem injector of the current instance. /// public IOperator ProblemInjector { get { return myVariableInjection.SubOperators[0]; } set { value.Name = "ProblemInjector"; mySA.OperatorGraph.RemoveOperator(ProblemInjector.Guid); mySA.OperatorGraph.AddOperator(value); myVariableInjection.AddSubOperator(value, 0); } } private IOperator myPopulationInitialization; /// /// Gets or sets the solution generator of the current instance. /// public IOperator SolutionGenerator { get { return myPopulationInitialization.SubOperators[0]; } set { value.Name = "SolutionGenerator"; mySA.OperatorGraph.RemoveOperator(SolutionGenerator.Guid); mySA.OperatorGraph.AddOperator(value); myPopulationInitialization.AddSubOperator(value, 0); } } /// /// Gets or sets the evaluator of the current instance. /// public IOperator Evaluator { get { return myPopulationInitialization.SubOperators[1]; } set { value.Name = "Evaluator"; mySA.OperatorGraph.RemoveOperator(Evaluator.Guid); mySA.OperatorGraph.AddOperator(value); myPopulationInitialization.AddSubOperator(value, 1); mySAMain.AddSubOperator(value, 2); } } private IOperator mySAMain; /// /// Gets or sets the mutation operator of the current instance. /// public IOperator Mutator { get { return mySAMain.SubOperators[1]; } set { value.Name = "Mutator"; mySA.OperatorGraph.RemoveOperator(Mutator.Guid); mySA.OperatorGraph.AddOperator(value); mySAMain.AddSubOperator(value, 1); } } /// /// Gets or sets the annealing schema to be used /// public IOperator AnnealingScheme { get { return mySAMain.SubOperators[0]; } set { value.Name = "AnnealingScheme"; mySA.OperatorGraph.RemoveOperator(AnnealingScheme.Guid); mySA.OperatorGraph.AddOperator(value); mySAMain.AddSubOperator(value, 0); } } #endregion /// /// Initializes a new instance of . /// public SA() { myEngine = new SequentialEngine.SequentialEngine(); Create(myEngine); SetReferences(); } /// /// Creates a new instance of the class. /// /// The created instance of the . public override IView CreateView() { return new SAEditor(this); } /// /// Creates a new instance of the class. /// /// The created instance of the . public virtual IEditor CreateEditor() { return new SAEditor(this); } /// /// Clones the current instance (deep clone). /// /// Deep clone through method of helper class /// . /// Dictionary of all already cloned objects. (Needed to avoid cycles.) /// The cloned object as . public override object Clone(IDictionary clonedObjects) { SA clone = new SA(); clonedObjects.Add(Guid, clone); clone.myEngine = (IEngine)Auxiliary.Clone(Engine, clonedObjects); return clone; } #region SetReferences Method private void SetReferences() { // SA CombinedOperator co1 = (CombinedOperator)Engine.OperatorGraph.InitialOperator; mySA = co1; // SequentialProcessor in SA SequentialProcessor sp1 = (SequentialProcessor)co1.OperatorGraph.InitialOperator; // Variable Injection CombinedOperator co2 = (CombinedOperator)sp1.SubOperators[0]; myVariableInjection = co2; // SequentialProcessor in Variable Injection SequentialProcessor sp2 = (SequentialProcessor)co2.OperatorGraph.InitialOperator; // RandomInjector RandomInjector ri = (RandomInjector)sp2.SubOperators[0]; mySetSeedRandomly = ri.GetVariable("SetSeedRandomly").GetValue(); mySeed = ri.GetVariable("Seed").GetValue(); // VariableInjector VariableInjector vi = (VariableInjector)sp2.SubOperators[2]; myMaximumIterations = vi.GetVariable("MaximumIterations").GetValue(); myMaximumIterationEffort = vi.GetVariable("MaximumIterationEffort").GetValue(); myTemperature = vi.GetVariable("Temperature").GetValue(); myMinimumTemperature = vi.GetVariable("MinimumTemperature").GetValue(); myAnnealingParameter = vi.GetVariable("AnnealingParameter").GetValue(); // Population Initialization CombinedOperator co3 = (CombinedOperator)sp1.SubOperators[1]; myPopulationInitialization = co3; // SA Main CombinedOperator co4 = (CombinedOperator)sp1.SubOperators[2]; mySAMain = co4; } #endregion #region Persistence Methods /// /// Saves the current instance as in the specified . /// /// The engine of the current instance is saved as a child node with the tag name /// Engine. /// The (tag)name of the . /// The where the data is saved. /// A dictionary of all already persisted objects. (Needed to avoid cycles.) /// The saved . public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary persistedObjects) { XmlNode node = base.GetXmlNode(name, document, persistedObjects); node.AppendChild(PersistenceManager.Persist("Engine", Engine, document, persistedObjects)); return node; } /// /// Loads the persisted instance from the specified . /// /// The elements of the current instance must be saved in a special way, see /// . /// The where the instance is saved. /// The dictionary of all already restored objects. (Needed to avoid cycles.) public override void Populate(XmlNode node, IDictionary restoredObjects) { base.Populate(node, restoredObjects); myEngine = (IEngine)PersistenceManager.Restore(node.SelectSingleNode("Engine"), restoredObjects); SetReferences(); } #endregion } }