Index: trunk/sources/HeuristicLab 3.3/Files.txt
===================================================================
--- trunk/sources/HeuristicLab 3.3/Files.txt	(revision 2996)
+++ trunk/sources/HeuristicLab 3.3/Files.txt	(revision 2997)
@@ -6,4 +6,5 @@
 HeuristicLab.Algorithms.SGA\3.3:HeuristicLab.Algorithms.SGA-3.3.dll
 HeuristicLab.Algorithms.SGA.Views\3.3:HeuristicLab.Algorithms.SGA.Views-3.3.dll
+HeuristicLab.Algorithms.TS\3.3:HeuristicLab.Algorithms.TS-3.3.dll
 HeuristicLab.Analysis\3.3:HeuristicLab.Analysis-3.3.dll
 HeuristicLab.Analysis.Views\3.3:HeuristicLab.Analysis.Views-3.3.dll
Index: trunk/sources/HeuristicLab.Algorithms.TS/3.3/HeuristicLab.Algorithms.TS-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.TS/3.3/HeuristicLab.Algorithms.TS-3.3.csproj	(revision 2996)
+++ trunk/sources/HeuristicLab.Algorithms.TS/3.3/HeuristicLab.Algorithms.TS-3.3.csproj	(revision 2997)
@@ -83,6 +83,13 @@
     <Compile Include="HeuristicLabAlgorithmsTSPlugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="TabuSelector.cs" />
-    <Compile Include="TSOperator.cs" />
+    <Compile Include="TabuListCreator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="TabuSelector.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="TSOperator.cs">
+      <SubType>Code</SubType>
+    </Compile>
   </ItemGroup>
   <ItemGroup>
Index: trunk/sources/HeuristicLab.Algorithms.TS/3.3/TSOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.TS/3.3/TSOperator.cs	(revision 2996)
+++ trunk/sources/HeuristicLab.Algorithms.TS/3.3/TSOperator.cs	(revision 2997)
@@ -25,4 +25,6 @@
 using HeuristicLab.Operators;
 using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Selection;
 
 namespace HeuristicLab.Algorithms.TS {
@@ -31,4 +33,5 @@
   /// </summary>
   [Item("TSOperator", "An operator which represents a Tabu Search.")]
+  [StorableClass(StorableClassType.Empty)]
   public class TSOperator : AlgorithmOperator {
     #region Parameter properties
@@ -51,8 +54,26 @@
       get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
     }
+    public ValueLookupParameter<IOperator> MoveGeneratorParameter {
+      get { return (ValueLookupParameter<IOperator>)Parameters["MoveGenerator"]; }
+    }
+    public ValueLookupParameter<IOperator> MoveQualityEvaluatorParameter {
+      get { return (ValueLookupParameter<IOperator>)Parameters["MoveQualityEvaluator"]; }
+    }
+    public ValueLookupParameter<IOperator> MoveTabuEvaluatorParameter {
+      get { return (ValueLookupParameter<IOperator>)Parameters["MoveTabuEvaluator"]; }
+    }
+    public ValueLookupParameter<IOperator> TabuSelectorParameter {
+      get { return (ValueLookupParameter<IOperator>)Parameters["TabuSelector"]; }
+    }
+    public ValueLookupParameter<IOperator> MoveTabuMakerParameter {
+      get { return (ValueLookupParameter<IOperator>)Parameters["MoveTabuMaker"]; }
+    }
+    public ValueLookupParameter<IOperator> MoveMakerParameter {
+      get { return (ValueLookupParameter<IOperator>)Parameters["MoveMaker"]; }
+    }
+
     private ScopeParameter CurrentScopeParameter {
       get { return (ScopeParameter)Parameters["CurrentScope"]; }
     }
-
     public IScope CurrentScope {
       get { return CurrentScopeParameter.ActualValue; }
@@ -69,10 +90,23 @@
       Parameters.Add(new ValueLookupParameter<IntData>("TabuTenure", "The length of the tabu list, and also means the number of iterations a move is kept tabu"));
       Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The variable collection where results should be stored."));
+
+      Parameters.Add(new ValueLookupParameter<IOperator>("MoveGenerator", "The operator that generates the moves."));
+      Parameters.Add(new ValueLookupParameter<IOperator>("MoveQualityEvaluator", "The operator that evaluates the quality of a move."));
+      Parameters.Add(new ValueLookupParameter<IOperator>("MoveTabuEvaluator", "The operator that evaluates whether a move is tabu."));
+      TabuSelector tabuSelectorOp = new TabuSelector();
+      tabuSelectorOp.NumberOfSelectedSubScopes = new IntData(1);
+      Parameters.Add(new ValueLookupParameter<IOperator>("TabuSelector", "The operator that selects among the moves the next best.", tabuSelectorOp));
+      Parameters.Add(new ValueLookupParameter<IOperator>("MoveTabuMaker", "The operator that declares a move tabu."));
+      Parameters.Add(new ValueLookupParameter<IOperator>("MoveMaker", "The operator that performs a move and updates the quality."));
+
       Parameters.Add(new ScopeParameter("CurrentScope", "The current scope which represents a population of solutions on which the TS should be applied."));
       #endregion
 
       #region Create operators
+      TabuListCreator tabuListCreator = new TabuListCreator();
       VariableCreator variableCreator = new VariableCreator();
+      BestQualityMemorizer bestQualityMemorizer = new BestQualityMemorizer();
       ResultsCollector resultsCollector = new ResultsCollector();
+      UniformSequentialSubScopesProcessor mainProcessor = new UniformSequentialSubScopesProcessor();
       Placeholder moveGenerator = new Placeholder();
       UniformSequentialSubScopesProcessor moveEvaluationProcessor = new UniformSequentialSubScopesProcessor();
@@ -80,10 +114,11 @@
       Placeholder moveTabuEvaluator = new Placeholder();
       SubScopesSorter moveQualitySorter = new SubScopesSorter();
+      BestAverageWorstQualityCalculator bestAverageWorstMoveQualityCalculator = new BestAverageWorstQualityCalculator();
       Placeholder tabuSelector = new Placeholder();
-      SequentialSubScopesProcessor moveMakingProcessor = new SequentialSubScopesProcessor();
-      EmptyOperator emptyOp = new EmptyOperator();
-      UniformSequentialSubScopesProcessor actualMoveMakingProcessor = new UniformSequentialSubScopesProcessor();
+      RightReducer rightReducer = new RightReducer();
+      UniformSequentialSubScopesProcessor moveMakingProcessor = new UniformSequentialSubScopesProcessor();
+      Placeholder moveTabuMaker = new Placeholder();
       Placeholder moveMaker = new Placeholder();
-      Placeholder moveTabuMaker = new Placeholder();
+      DataTableValuesCollector valuesCollector = new DataTableValuesCollector();
       SubScopesRemover subScopesRemover = new SubScopesRemover();
       IntCounter iterationsCounter = new IntCounter();
@@ -93,20 +128,19 @@
 
       variableCreator.CollectedValues.Add(new ValueParameter<IntData>("Iterations", new IntData(0)));
-      variableCreator.CollectedValues.Add(new ValueParameter<DoubleData>("Best Quality", new DoubleData(0)));
       variableCreator.CollectedValues.Add(new ValueParameter<DoubleData>("Best Move Quality", new DoubleData(0)));
       variableCreator.CollectedValues.Add(new ValueParameter<DoubleData>("Average Move Quality", new DoubleData(0)));
       variableCreator.CollectedValues.Add(new ValueParameter<DoubleData>("Worst Move Quality", new DoubleData(0)));
-      variableCreator.CollectedValues.Add(new ValueParameter<DataTable>("Qualities", new DataTable("Qualities")));
       variableCreator.CollectedValues.Add(new ValueParameter<DataTable>("MoveQualities", new DataTable("MoveQualities")));
 
       resultsCollector.CollectedValues.Add(new LookupParameter<IntData>("Iterations"));
-      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleData>("Best Quality"));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleData>("Best Quality") { ActualName = "BestQuality" });
       resultsCollector.CollectedValues.Add(new LookupParameter<DoubleData>("Best Move Quality"));
       resultsCollector.CollectedValues.Add(new LookupParameter<DoubleData>("Average Move Quality"));
       resultsCollector.CollectedValues.Add(new LookupParameter<DoubleData>("Worst Move Quality"));
-      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("Qualities"));
       resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("MoveQualities"));
       resultsCollector.ResultsParameter.ActualName = "Results";
 
+      mainProcessor.Name = "Solution processor (UniformSequentialSubScopesProcessor)";
+
       moveGenerator.Name = "MoveGenerator (placeholder)";
       moveGenerator.OperatorParameter.ActualName = "MoveGenerator";
@@ -121,18 +155,33 @@
       moveQualitySorter.ValueParameter.ActualName = "MoveQuality";
 
+      bestAverageWorstMoveQualityCalculator.AverageQualityParameter.ActualName = "Average Move Quality";
+      bestAverageWorstMoveQualityCalculator.BestQualityParameter.ActualName = "Best Move Quality";
+      bestAverageWorstMoveQualityCalculator.MaximizationParameter.ActualName = "Maximization";
+      bestAverageWorstMoveQualityCalculator.QualityParameter.ActualName = "MoveQuality";
+      bestAverageWorstMoveQualityCalculator.WorstQualityParameter.ActualName = "Worst Move Quality";
+
       tabuSelector.Name = "TabuSelector (placeholder)";
       tabuSelector.OperatorParameter.ActualName = "TabuSelector";
 
+      moveMakingProcessor.Name = "MoveMaking processor (UniformSequentialSubScopesProcessor)";
+
+      moveTabuMaker.Name = "MoveTabuMaker (placeholder)";
+      moveTabuMaker.OperatorParameter.ActualName = "MoveTabuMaker";
+
       moveMaker.Name = "MoveMaker (placeholder)";
       moveMaker.OperatorParameter.ActualName = "MoveMaker";
 
-      moveTabuMaker.Name = "MoveTabuMaker (placeholder)";
-      moveTabuMaker.OperatorParameter.ActualName = "MoveTabuMaker";
+      valuesCollector.CollectedValues.Add(new LookupParameter<DoubleData>("Best Move Quality"));
+      valuesCollector.CollectedValues.Add(new LookupParameter<DoubleData>("Average Move Quality"));
+      valuesCollector.CollectedValues.Add(new LookupParameter<DoubleData>("Worst Move Quality"));
+      valuesCollector.DataTableParameter.ActualName = "MoveQualities";
 
       subScopesRemover.RemoveAllSubScopes = true;
 
+      iterationsCounter.Name = "Iterations Counter";
       iterationsCounter.Increment = new IntData(1);
-      iterationsCounter.IncrementParameter.ActualName = "Iterations";
-
+      iterationsCounter.ValueParameter.ActualName = "Iterations";
+
+      iterationsComparator.Name = "Iterations Comparator";
       iterationsComparator.Comparison = new ComparisonData(Comparison.Less);
       iterationsComparator.LeftSideParameter.ActualName = "Iterations";
@@ -140,25 +189,31 @@
       iterationsComparator.ResultParameter.ActualName = "IterationsCondition";
 
+      iterationsTermination.Name = "Iterations Termination Condition";
       iterationsTermination.ConditionParameter.ActualName = "IterationsCondition";
       #endregion
 
       #region Create operator graph
-      OperatorGraph.InitialOperator = variableCreator;
-      variableCreator.Successor = resultsCollector;
-      resultsCollector.Successor = moveGenerator;
+      OperatorGraph.InitialOperator = tabuListCreator;
+      tabuListCreator.Successor = variableCreator;
+      variableCreator.Successor = bestQualityMemorizer;
+      bestQualityMemorizer.Successor = resultsCollector;
+      resultsCollector.Successor = mainProcessor;
+      mainProcessor.Operator = moveGenerator;
+      mainProcessor.Successor = valuesCollector;
       moveGenerator.Successor = moveEvaluationProcessor;
       moveEvaluationProcessor.Operator = moveQualityEvaluator;
+      moveEvaluationProcessor.Successor = moveQualitySorter;
       moveQualityEvaluator.Successor = moveTabuEvaluator;
-      moveEvaluationProcessor.Successor = moveQualitySorter;
-      moveQualitySorter.Successor = tabuSelector;
-      tabuSelector.Successor = moveMakingProcessor;
-      moveMakingProcessor.Operators.AddRange(new Operator[] { emptyOp, actualMoveMakingProcessor });
-      actualMoveMakingProcessor.Operator = moveTabuMaker;
+      moveQualitySorter.Successor = bestAverageWorstMoveQualityCalculator;
+      bestAverageWorstMoveQualityCalculator.Successor = tabuSelector;
+      tabuSelector.Successor = rightReducer;
+      rightReducer.Successor = moveMakingProcessor;
+      moveMakingProcessor.Operator = moveTabuMaker;
+      moveMakingProcessor.Successor = subScopesRemover;
       moveTabuMaker.Successor = moveMaker;
-      moveMakingProcessor.Successor = subScopesRemover;
-      subScopesRemover.Successor = iterationsCounter;
+      valuesCollector.Successor = iterationsCounter;
       iterationsCounter.Successor = iterationsComparator;
       iterationsComparator.Successor = iterationsTermination;
-      iterationsTermination.TrueBranch = resultsCollector;
+      iterationsTermination.TrueBranch = bestQualityMemorizer;
       iterationsTermination.FalseBranch = finished;
       #endregion
Index: trunk/sources/HeuristicLab.Algorithms.TS/3.3/TabuListCreator.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.TS/3.3/TabuListCreator.cs	(revision 2997)
+++ trunk/sources/HeuristicLab.Algorithms.TS/3.3/TabuListCreator.cs	(revision 2997)
@@ -0,0 +1,60 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Selection;
+
+namespace HeuristicLab.Algorithms.TS {
+  [Item("TabuListCreator", "An operator that creates a new empty tabu list. It can also replace an existing tabu list with a new empty one.")]
+  [StorableClass(StorableClassType.Empty)]
+  public class TabuListCreator : SingleSuccessorOperator {
+    public ValueLookupParameter<ItemList<IItem>> TabuListParameter {
+      get { return (ValueLookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
+    }
+    protected ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+    public IScope CurrentScope {
+      get { return CurrentScopeParameter.ActualValue; }
+    }
+
+    public TabuListCreator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<ItemList<IItem>>("TabuList", "The tabu list.", new ItemList<IItem>()));
+      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope."));
+    }
+
+    public override IOperation Apply() {
+      IVariable var;
+      CurrentScope.Variables.TryGetValue(TabuListParameter.ActualName, out var);
+      if (var != null)
+        var.Value = (IItem)TabuListParameter.ActualValue.Clone();
+      else
+        CurrentScope.Variables.Add(new Variable(TabuListParameter.ActualName, (IItem)TabuListParameter.ActualValue.Clone()));
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.TS/3.3/TabuSelector.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.TS/3.3/TabuSelector.cs	(revision 2996)
+++ trunk/sources/HeuristicLab.Algorithms.TS/3.3/TabuSelector.cs	(revision 2997)
@@ -40,10 +40,4 @@
   public class TabuSelector : Selector {
     /// <summary>
-    /// The quality of the current solution.
-    /// </summary>
-    public LookupParameter<DoubleData> QualityParameter {
-      get { return (LookupParameter<DoubleData>)Parameters["Quality"]; }
-    }
-    /// <summary>
     /// The best found quality so far.
     /// </summary>
@@ -76,4 +70,8 @@
     }
 
+    public IntData NumberOfSelectedSubScopes {
+      set { NumberOfSelectedSubScopesParameter.Value = value; }
+    }
+
     /// <summary>
     /// Initializes a new intsance with 6 parameters (<c>Quality</c>, <c>BestQuality</c>,
@@ -82,5 +80,4 @@
     public TabuSelector()
       : base() {
-      Parameters.Add(new LookupParameter<DoubleData>("Quality", "The quality of the current solution."));
       Parameters.Add(new LookupParameter<DoubleData>("BestQuality", "The best found quality so far."));
       Parameters.Add(new ValueLookupParameter<BoolData>("Aspiration", "Whether the default aspiration criterion should be used or not. The default aspiration criterion accepts a tabu move if it results in a better solution than the best solution found so far.", new BoolData(true)));
@@ -101,5 +98,4 @@
       bool maximization = MaximizationParameter.ActualValue.Value;
       double bestQuality = BestQualityParameter.ActualValue.Value;
-      double quality = QualityParameter.ActualValue.Value;
       ItemArray<DoubleData> moveQualities = MoveQualityParameter.ActualValue;
       ItemArray<BoolData> moveTabus = MoveTabuParameter.ActualValue;
@@ -110,7 +106,6 @@
       List<int> scopesToRemove = new List<int>();
       for (int i = 0; i < scopes.Count; i++) {
-        if (count > 0 && (!moveTabus[i].Value || aspiration &&
-          (maximization && moveQualities[i].Value + quality > bestQuality
-          || !maximization && moveQualities[i].Value + quality < bestQuality))) {
+        if (count > 0 && (!moveTabus[i].Value
+          || aspiration && IsBetter(maximization, moveQualities[i].Value, bestQuality))) {
           scopesToRemove.Add(i);
           if (copy) selected[selected.Length - count] = (IScope)scopes[i].Clone();
@@ -133,4 +128,8 @@
       return selected;
     }
+
+    private bool IsBetter(bool maximization, double moveQuality, double bestQuality) {
+      return (maximization && moveQuality > bestQuality || !maximization && moveQuality < bestQuality);
+    }
   }
 }
Index: trunk/sources/HeuristicLab.Analysis/3.3/BestQualityMemorizer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/BestQualityMemorizer.cs	(revision 2997)
+++ trunk/sources/HeuristicLab.Analysis/3.3/BestQualityMemorizer.cs	(revision 2997)
@@ -0,0 +1,70 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  /// <summary>
+  /// An operator that updates the best quality found so far with those qualities in the subscopes.
+  /// </summary>
+  [Item("BestQualityMemorizer", "An operator that updates the best quality found so far with those qualities in the subscopes.")]
+  [StorableClass(StorableClassType.Empty)]
+  public class BestQualityMemorizer : SingleSuccessorOperator {
+    public IValueLookupParameter<BoolData> MaximizationParameter {
+      get { return (IValueLookupParameter<BoolData>)Parameters["Maximization"]; }
+    }
+    public ILookupParameter<ItemArray<DoubleData>> QualityParameter {
+      get { return (ILookupParameter<ItemArray<DoubleData>>)Parameters["Quality"]; }
+    }
+    public IValueLookupParameter<DoubleData> BestQualityParameter {
+      get { return (IValueLookupParameter<DoubleData>)Parameters["BestQuality"]; }
+    }
+
+    public BestQualityMemorizer()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<BoolData>("Maximization", "True if the current problem is a maximization problem, otherwise false."));
+      Parameters.Add(new SubScopesLookupParameter<DoubleData>("Quality", "The value contained in each sub-scope which represents the solution quality."));
+      Parameters.Add(new ValueLookupParameter<DoubleData>("BestQuality", "The quality value of the best solution."));
+    }
+
+    public override IOperation Apply() {
+      ItemArray<DoubleData> qualities = QualityParameter.ActualValue;
+      bool maximization = MaximizationParameter.ActualValue.Value;
+      DoubleData best = BestQualityParameter.ActualValue;
+      double max = (best != null) ? (best.Value) : ((maximization) ? (double.MinValue) : (double.MaxValue));
+      
+      foreach (DoubleData quality in qualities)
+        if (IsBetter(maximization, quality.Value, max)) max = quality.Value;
+
+      if (best == null) BestQualityParameter.ActualValue = new DoubleData(max);
+      else best.Value = max;
+      return base.Apply();
+    }
+
+    private bool IsBetter(bool maximization, double quality, double max) {
+      return (maximization && quality > max || !maximization && quality < max);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 2996)
+++ trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 2997)
@@ -85,4 +85,5 @@
     <None Include="HeuristicLabAnalysisPlugin.cs.frame" />
     <Compile Include="BestAverageWorstQualityCalculator.cs" />
+    <Compile Include="BestQualityMemorizer.cs" />
     <Compile Include="DataRow.cs" />
     <Compile Include="HeuristicLabAnalysisPlugin.cs" />
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/HeuristicLab.Encodings.Permutation-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/HeuristicLab.Encodings.Permutation-3.3.csproj	(revision 2996)
+++ trunk/sources/HeuristicLab.Encodings.Permutation/3.3/HeuristicLab.Encodings.Permutation-3.3.csproj	(revision 2997)
@@ -96,4 +96,5 @@
     <Compile Include="Interfaces\IPermutationCrossover.cs" />
     <Compile Include="Interfaces\IPermutationManipulator.cs" />
+    <Compile Include="Interfaces\IPermutationMoveGenerator.cs" />
     <Compile Include="Interfaces\IPermutationOperator.cs" />
     <Compile Include="Manipulators\InsertionManipulator.cs" />
@@ -104,7 +105,25 @@
     <Compile Include="Manipulators\TranslocationInversionManipulator.cs" />
     <Compile Include="Manipulators\TranslocationManipulator.cs" />
-    <Compile Include="Moves\Permutation2IndexMove.cs" />
-    <Compile Include="Moves\Permutation2OptExhaustiveMoveGenerator.cs" />
-    <Compile Include="Moves\Permutation2OptMove.cs" />
+    <Compile Include="Moves\ExhaustiveTwoOptMoveGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Moves\TwoIndexMove.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Moves\TwoOptMove.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Moves\TwoOptMoveMaker.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Moves\TwoOptMoveTabuAttribute.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Moves\TwoOptMoveTabuEvaluator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Moves\TwoOptMoveTabuMaker.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="PermutationManipulator.cs" />
     <Compile Include="PermutationCrossover.cs" />
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Interfaces/IPermutationMoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Interfaces/IPermutationMoveGenerator.cs	(revision 2997)
+++ trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Interfaces/IPermutationMoveGenerator.cs	(revision 2997)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Encodings.Permutation {
+  /// <summary>
+  /// An interface which represents an operator for manipulating solutions.
+  /// </summary>
+  public interface IPermutationMoveGenerator : IPermutationOperator, IMoveGenerator {
+    ILookupParameter<Permutation> PermutationParameter { get; }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Manipulators/InversionManipulator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Manipulators/InversionManipulator.cs	(revision 2996)
+++ trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Manipulators/InversionManipulator.cs	(revision 2997)
@@ -47,5 +47,8 @@
       } while (breakPoint2 == breakPoint1);
       if (breakPoint2 < breakPoint1) { int h = breakPoint1; breakPoint1 = breakPoint2; breakPoint2 = h; }
+      Apply(permutation, breakPoint1, breakPoint2);
+    }
 
+    public static void Apply(Permutation permutation, int breakPoint1, int breakPoint2) {
       for (int i = 0; i <= (breakPoint2 - breakPoint1) / 2; i++) {  // invert permutation between breakpoints
         int temp = permutation[breakPoint1 + i];
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/ExhaustiveTwoOptMoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/ExhaustiveTwoOptMoveGenerator.cs	(revision 2997)
+++ trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/ExhaustiveTwoOptMoveGenerator.cs	(revision 2997)
@@ -0,0 +1,71 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.Permutation {
+  [Item("ExhaustiveTwoOptMoveGenerator", "Generates all possible 2-opt moves from a given permutation.")]
+  [StorableClass(StorableClassType.Empty)]
+  public class ExhaustiveTwoOptMoveGenerator : SingleSuccessorOperator, IPermutationMoveGenerator {
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public LookupParameter<TwoOptMove> MoveParameter {
+      get { return (LookupParameter<TwoOptMove>)Parameters["Move"]; }
+    }
+    private ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    public ExhaustiveTwoOptMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The permutation for which moves should be generated."));
+      Parameters.Add(new LookupParameter<TwoOptMove>("Move", "The moves that should be generated in subscopes."));
+      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope where the moves should be added as subscopes."));
+    }
+
+    public override IOperation Apply() {
+      Permutation p = PermutationParameter.ActualValue;
+      int length = p.Length;
+      int totalMoves = (length) * (length - 1) / 2 - 3;
+      Scope[] moveScopes = new Scope[totalMoves];
+      int count = 0;
+      for (int i = 0; i < length - 1; i++)
+        for (int j = i + 1; j < length; j++) {
+          // doesn't make sense to inverse the whole permutation or the whole but one
+          if (i == 0 && j >= length - 2) continue;
+          else if (i == 1 && j >= length - 1) continue;
+          Scope s = new Scope(count.ToString());
+          s.Variables.Add(new Variable(MoveParameter.ActualName, new TwoOptMove(i, j)));
+          moveScopes[count] = s;
+          count++;
+        }
+      // FIXME: remove the line below
+      if (count != totalMoves) throw new InvalidOperationException(Name + ": totalMoves != count");
+      CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes);
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/Permutation2IndexMove.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/Permutation2IndexMove.cs	(revision 2996)
+++ 	(revision )
@@ -1,49 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-
-namespace HeuristicLab.Encodings.Permutation {
-  [Item("Permutation2IndexMove", "A move on a permutation that is specified by 2 indices")]
-  [StorableClass(StorableClassType.MarkedOnly)]
-  public class Permutation2IndexMove : Item {
-    [Storable]
-    public int Index1 { get; protected set; }
-    [Storable]
-    public int Index2 { get; protected set; }
-    [Storable]
-    public Permutation Permutation { get; protected set; }
-
-    protected Permutation2IndexMove() {
-      Index1 = -1;
-      Index2 = -1;
-      Permutation = null;
-    }
-
-    public Permutation2IndexMove(int index1, int index2, Permutation permutation)
-      : base() {
-      Index1 = index1;
-      Index2 = index2;
-      Permutation = permutation;
-    }
-  }
-}
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/Permutation2OptExhaustiveMoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/Permutation2OptExhaustiveMoveGenerator.cs	(revision 2996)
+++ 	(revision )
@@ -1,32 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using HeuristicLab.Core;
-using HeuristicLab.Operators;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-
-namespace HeuristicLab.Encodings.Permutation.Moves {
-  public class Permutation2OptExhaustiveMoveGenerator : SingleSuccessorOperator {
-    public override IOperation Apply() {
-      return base.Apply();
-    }
-  }
-}
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/Permutation2OptMove.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/Permutation2OptMove.cs	(revision 2996)
+++ 	(revision )
@@ -1,40 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-
-namespace HeuristicLab.Encodings.Permutation {
-  [Item("Permutation2OptMove", "Item that describes a 2-Opt move.")]
-  public class Permutation2OptMove : Permutation2IndexMove {
-    protected Permutation2OptMove()
-      : base() {
-    }
-
-    public Permutation2OptMove(int index1, int index2)
-      : base(index1, index2, null) {
-    }
-
-    public Permutation2OptMove(int index1, int index2, Permutation permutation)
-      : base(index1, index2, permutation) {
-    }
-  }
-}
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoIndexMove.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoIndexMove.cs	(revision 2997)
+++ trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoIndexMove.cs	(revision 2997)
@@ -0,0 +1,59 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.Permutation {
+  [Item("TwoIndexMove", "A move on a permutation that is specified by 2 indices")]
+  [StorableClass(StorableClassType.MarkedOnly)]
+  public class TwoIndexMove : Item {
+    [Storable]
+    public int Index1 { get; protected set; }
+    [Storable]
+    public int Index2 { get; protected set; }
+    [Storable]
+    public Permutation Permutation { get; protected set; }
+
+    public TwoIndexMove()
+      : base() {
+      Index1 = -1;
+      Index2 = -1;
+      Permutation = null;
+    }
+
+    public TwoIndexMove(int index1, int index2, Permutation permutation)
+      : base() {
+      Index1 = index1;
+      Index2 = index2;
+      Permutation = permutation;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      TwoIndexMove clone = (TwoIndexMove)base.Clone(cloner);
+      clone.Index1 = Index1;
+      clone.Index2 = Index2;
+      if (Permutation != null)
+        clone.Permutation = (Permutation)Permutation.Clone(cloner);
+      return clone;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMove.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMove.cs	(revision 2997)
+++ trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMove.cs	(revision 2997)
@@ -0,0 +1,41 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.Permutation {
+  [Item("TwoOptMove", "Item that describes a 2-Opt move.")]
+  [StorableClass(StorableClassType.Empty)]
+  public class TwoOptMove : TwoIndexMove {
+    public TwoOptMove()
+      : base() {
+    }
+
+    public TwoOptMove(int index1, int index2)
+      : base(index1, index2, null) {
+    }
+
+    public TwoOptMove(int index1, int index2, Permutation permutation)
+      : base(index1, index2, permutation) {
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMoveMaker.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMoveMaker.cs	(revision 2997)
+++ trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMoveMaker.cs	(revision 2997)
@@ -0,0 +1,66 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.Permutation {
+  [Item("TwoOptMoveMaker", "Peforms a 2-opt move on a given permutation and updates the quality.")]
+  [StorableClass(StorableClassType.Empty)]
+  public class TwoOptMoveMaker : SingleSuccessorOperator {
+    public LookupParameter<DoubleData> QualityParameter {
+      get { return (LookupParameter<DoubleData>)Parameters["Quality"]; }
+    }
+    public LookupParameter<TwoOptMove> MoveParameter {
+      get { return (LookupParameter<TwoOptMove>)Parameters["Move"]; }
+    }
+    public LookupParameter<DoubleData> MoveQualityParameter {
+      get { return (LookupParameter<DoubleData>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+
+    public TwoOptMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleData>("Quality", "The quality of the solution."));
+      Parameters.Add(new LookupParameter<TwoOptMove>("Move", "The move to evaluate."));
+      Parameters.Add(new LookupParameter<DoubleData>("MoveQuality", "The relative quality of the move."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
+    }
+
+    public override IOperation Apply() {
+      TwoOptMove move = MoveParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      DoubleData moveQuality = MoveQualityParameter.ActualValue;
+      DoubleData quality = QualityParameter.ActualValue;
+
+      InversionManipulator.Apply(permutation, move.Index1, move.Index2);
+      quality.Value = moveQuality.Value;
+
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMoveTabuAttribute.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMoveTabuAttribute.cs	(revision 2997)
+++ trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMoveTabuAttribute.cs	(revision 2997)
@@ -0,0 +1,51 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.Permutation {
+  [Item("TwoOptMoveTabuAttribute", "Specifies the tabu attributes for a 2-opt move.")]
+  [StorableClass(StorableClassType.MarkedOnly)]
+  public class TwoOptMoveTabuAttribute : Item {
+    [Storable]
+    public int Edge1Source { get; private set; }
+    [Storable]
+    public int Edge1Target { get; private set; }
+    [Storable]
+    public int Edge2Source { get; private set; }
+    [Storable]
+    public int Edge2Target { get; private set; }
+
+    [StorableConstructor]
+    private TwoOptMoveTabuAttribute()
+      : base() {
+    }
+
+    public TwoOptMoveTabuAttribute(int edge1Source, int edge1Target, int edge2Source, int edge2Target)
+      : base() {
+      Edge1Source = edge1Source;
+      Edge1Target = edge1Target;
+      Edge2Source = edge2Source;
+      Edge2Target = edge2Target;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMoveTabuEvaluator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMoveTabuEvaluator.cs	(revision 2997)
+++ trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMoveTabuEvaluator.cs	(revision 2997)
@@ -0,0 +1,88 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.Permutation {
+  [Item("TwoOptMoveTabuEvaluator", "Evaluates whether a given 2-opt move is tabu.")]
+  [StorableClass(StorableClassType.Empty)]
+  public class TwoOptMoveTabuEvaluator : SingleSuccessorOperator {
+    public LookupParameter<TwoOptMove> MoveParameter {
+      get { return (LookupParameter<TwoOptMove>)Parameters["Move"]; }
+    }
+    public LookupParameter<Permutation> PermutationParameter {
+      get { return (LookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public LookupParameter<ItemList<IItem>> TabuListParameter {
+      get { return (LookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
+    }
+    public LookupParameter<BoolData> MoveTabuParameter {
+      get { return (LookupParameter<BoolData>)Parameters["MoveTabu"]; }
+    }
+    private ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+
+    public TwoOptMoveTabuEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<TwoOptMove>("Move", "The move to evaluate."));
+      Parameters.Add(new LookupParameter<BoolData>("MoveTabu", "The variable to store if a move was tabu."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
+      Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list."));
+      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope."));
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      TwoOptMove move = MoveParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      int length = permutation.Length;
+      int E1S = permutation.GetCircular(move.Index1 - 1);
+      int E1T = permutation[move.Index1];
+      int E2S = permutation[move.Index2];
+      int E2T = permutation.GetCircular(move.Index2 + 1);
+      bool isTabu = false;
+      foreach (IItem tabuMove in tabuList) {
+        TwoOptMoveTabuAttribute attribute = (tabuMove as TwoOptMoveTabuAttribute);
+        if (attribute != null) {
+          // if previously deleted Edge1Source-Target is readded
+          if (attribute.Edge1Source == E1S && attribute.Edge1Target == E2S || attribute.Edge1Source == E2S && attribute.Edge1Target == E1S
+            // if previously deleted Edge2Source-Target is readded
+            || attribute.Edge2Source == E1T && attribute.Edge2Target == E2T || attribute.Edge2Source == E2T && attribute.Edge2Target == E1T
+            // if previously added Edge1Source-Edge2Source is deleted
+            || attribute.Edge1Source == E1S && attribute.Edge2Source == E1T || attribute.Edge1Source == E1T && attribute.Edge2Source == E1S
+            // if previously added Edge1Target-Edge2Target is deleted
+            || attribute.Edge1Target == E2S && attribute.Edge2Target == E2T || attribute.Edge1Target == E2T && attribute.Edge2Target == E2S) {
+            isTabu = true;
+            break;
+          }
+        }
+      }
+      MoveTabuParameter.ActualValue = new BoolData(isTabu);
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMoveTabuMaker.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMoveTabuMaker.cs	(revision 2997)
+++ trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Moves/TwoOptMoveTabuMaker.cs	(revision 2997)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.Permutation.Moves {
+  [Item("TwoOptMoveTabuMaker", "Declares a given 2-opt move as tabu, by adding its attributes to the tabu list. It also removes the oldest entry in the tabu list when its size is greater than tenure.")]
+  [StorableClass(StorableClassType.Empty)]
+  public class TwoOptMoveTabuMaker : SingleSuccessorOperator {
+    public LookupParameter<TwoOptMove> MoveParameter {
+      get { return (LookupParameter<TwoOptMove>)Parameters["Move"]; }
+    }
+    public LookupParameter<ItemList<IItem>> TabuListParameter {
+      get { return (LookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
+    }
+    public ValueLookupParameter<IntData> TabuTenureParameter {
+      get { return (ValueLookupParameter<IntData>)Parameters["TabuTenure"]; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+
+    public TwoOptMoveTabuMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<TwoOptMove>("Move", "The move that was made."));
+      Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list where move attributes are stored."));
+      Parameters.Add(new ValueLookupParameter<IntData>("TabuTenure", "The tenure of the tabu list."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      TwoOptMove move = MoveParameter.ActualValue;
+      IntData tabuTenure = TabuTenureParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      
+      if (tabuList.Count >= tabuTenure.Value) {
+        for (int i = 0; i < tabuTenure.Value - 1; i++)
+          tabuList[i] = tabuList[i + 1];
+        tabuList.RemoveAt(tabuList.Count - 1);
+      }
+
+      TwoOptMoveTabuAttribute attribute = new TwoOptMoveTabuAttribute(
+        permutation.GetCircular(move.Index1 - 1), permutation[move.Index1],
+        permutation[move.Index2], permutation.GetCircular(move.Index2 + 1));
+      tabuList.Add(attribute);
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Permutation.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Permutation.cs	(revision 2996)
+++ trunk/sources/HeuristicLab.Encodings.Permutation/3.3/Permutation.cs	(revision 2997)
@@ -85,4 +85,10 @@
     }
 
+    public int GetCircular(int position) {
+      if (position >= Length) position = position % Length;
+      while (position < 0) position += Length;
+      return this[position];
+    }
+
     #region IStringConvertibleArrayData Members
     int IStringConvertibleArrayData.Length {
Index: trunk/sources/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj	(revision 2996)
+++ trunk/sources/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj	(revision 2997)
@@ -86,4 +86,5 @@
     <None Include="HeuristicLabOptimizationPlugin.cs.frame" />
     <Compile Include="Algorithm.cs" />
+    <Compile Include="Interfaces\IMoveGenerator.cs" />
     <Compile Include="Interfaces\IMultiObjectiveSelector.cs" />
     <Compile Include="Interfaces\ISingleObjectiveSelector.cs" />
Index: trunk/sources/HeuristicLab.Optimization/3.3/Interfaces/IMoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Optimization/3.3/Interfaces/IMoveGenerator.cs	(revision 2997)
+++ trunk/sources/HeuristicLab.Optimization/3.3/Interfaces/IMoveGenerator.cs	(revision 2997)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an operator for generating moves.
+  /// </summary>
+  public interface IMoveGenerator : IOperator { }
+}
Index: trunk/sources/HeuristicLab.Problems.TSP/3.3/HeuristicLab.Problems.TSP-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.TSP/3.3/HeuristicLab.Problems.TSP-3.3.csproj	(revision 2996)
+++ trunk/sources/HeuristicLab.Problems.TSP/3.3/HeuristicLab.Problems.TSP-3.3.csproj	(revision 2997)
@@ -93,4 +93,7 @@
     <Compile Include="Interfaces\ITSPPathEvaluator.cs" />
     <Compile Include="HeuristicLabProblemsTSPPlugin.cs" />
+    <Compile Include="MoveEvaluators\TwoOptMoveTSPEvaluator.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="TSPLIBParser.cs" />
     <Compile Include="TSP.cs" />
Index: trunk/sources/HeuristicLab.Problems.TSP/3.3/MoveEvaluators/TwoOptMoveTSPEvaluator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.TSP/3.3/MoveEvaluators/TwoOptMoveTSPEvaluator.cs	(revision 2997)
+++ trunk/sources/HeuristicLab.Problems.TSP/3.3/MoveEvaluators/TwoOptMoveTSPEvaluator.cs	(revision 2997)
@@ -0,0 +1,89 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.Permutation;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System;
+
+namespace HeuristicLab.Problems.TSP {
+  /// <summary>
+  /// An operator to evaluate 2-opt moves.
+  /// </summary>
+  [Item("TwoOptMoveTSPEvaluator", "Evaluates a 2-opt move (rounded euclidean distances) by summing up the length of all added edges and subtracting the length of all deleted edges.")]
+  [StorableClass(StorableClassType.Empty)]
+  public class TwoOptMoveTSPEvaluator : SingleSuccessorOperator {
+    public ILookupParameter<DoubleData> QualityParameter {
+      get { return (ILookupParameter<DoubleData>)Parameters["Quality"]; }
+    }
+    public LookupParameter<TwoOptMove> MoveParameter {
+      get { return (LookupParameter<TwoOptMove>)Parameters["Move"]; }
+    }
+    public LookupParameter<DoubleData> MoveQualityParameter {
+      get { return (LookupParameter<DoubleData>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<DoubleMatrixData> CoordinatesParameter {
+      get { return (ILookupParameter<DoubleMatrixData>)Parameters["Coordinates"]; }
+    }
+
+    public TwoOptMoveTSPEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleData>("Quality", "The evaluated quality of the TSP solution."));
+      Parameters.Add(new LookupParameter<TwoOptMove>("Move", "The move to evaluate."));
+      Parameters.Add(new LookupParameter<DoubleData>("MoveQuality", "Where to store the move quality."));
+      Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
+      Parameters.Add(new LookupParameter<DoubleMatrixData>("Coordinates", "The city's coordinates."));
+    }
+
+    public override IOperation Apply() {
+      TwoOptMove move = MoveParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      DoubleMatrixData coordinates = CoordinatesParameter.ActualValue;
+      double moveQuality = QualityParameter.ActualValue.Value;
+      int edge1source = permutation.GetCircular(move.Index1 - 1);
+      int edge1target = permutation[move.Index1];
+      int edge2source = permutation[move.Index2];
+      int edge2target = permutation.GetCircular(move.Index2 + 1);
+      // remove two edges
+      moveQuality -= CalculateDistance(coordinates[edge1source ,0], coordinates[edge1source, 1],
+        coordinates[edge1target, 0], coordinates[edge1target, 1]);
+      moveQuality -= CalculateDistance(coordinates[edge2source, 0], coordinates[edge2source, 1],
+        coordinates[edge2target, 0], coordinates[edge2target, 1]);
+      // add two edges
+      moveQuality += CalculateDistance(coordinates[edge1source, 0], coordinates[edge1source, 1],
+        coordinates[edge2source, 0], coordinates[edge2source, 1]);
+      moveQuality += CalculateDistance(coordinates[edge1target, 0], coordinates[edge1target, 1],
+        coordinates[edge2target, 0], coordinates[edge2target, 1]);
+      MoveQualityParameter.ActualValue = new DoubleData(moveQuality);
+      return base.Apply();
+    }
+
+    private double CalculateDistance(double x1, double y1, double x2, double y2) {
+      return Math.Round(Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
+    }
+  }
+}
