Index: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/BinPacking2D.cs
===================================================================
--- branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/BinPacking2D.cs	(revision 14148)
+++ branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/BinPacking2D.cs	(revision 14149)
@@ -76,11 +76,4 @@
         ExtremePoints.Add(new PackingPosition(0, sourcePointY.X, sourcePointY.Y));
       }
-
-      //ExtremePoints.RemoveWhere(ep => IsPointOccupied(ep));
-
-      //ExtremePoints = new HashSet<TwoDimensionalPacking>(ExtremePoints.
-      //  OrderBy(ep => ep.X).
-      //  ThenBy(ep => ep.Y).
-      //  ThenBy(ep => ShortestPossibleSideFromPoint(ep)));
     }
 
Index: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/HeuristicLab.Problems.BinPacking2D-3.3.csproj
===================================================================
--- branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/HeuristicLab.Problems.BinPacking2D-3.3.csproj	(revision 14148)
+++ branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/HeuristicLab.Problems.BinPacking2D-3.3.csproj	(revision 14149)
@@ -168,8 +168,6 @@
     <Compile Include="Instances\RandomDataDescriptor.cs" />
     <Compile Include="Instances\RandomInstanceProvider.cs" />
+    <Compile Include="Interfaces\IDecoder.cs" />
     <Compile Include="Interfaces\IEvaluator.cs" />
-    <Compile Include="Interfaces\IPermutationDecoder.cs">
-      <SubType>Code</SubType>
-    </Compile>
     <Compile Include="PackingItem.cs" />
     <Compile Include="PackingPosition.cs" />
@@ -180,7 +178,9 @@
     <Compile Include="PermutationEncoding\Swap2MoveEvaluator.cs" />
     <Compile Include="PermutationEncoding\TranslocationMoveEvaluator.cs" />
+    <Compile Include="ProblemBase.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Solution.cs" />
+    <Compile Include="MoveEvaluatorBase.cs" />
   </ItemGroup>
   <ItemGroup>
Index: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/Interfaces/IDecoder.cs
===================================================================
--- branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/Interfaces/IDecoder.cs	(revision 14149)
+++ branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/Interfaces/IDecoder.cs	(revision 14149)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Joseph Helm and 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.Collections;
+using System.Collections.Generic;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Problems.BinPacking;
+
+namespace HeuristicLab.Problems.BinPacking2D {
+  public interface IDecoder<in T> : IItem {
+    Solution Decode(T encodedSolution, PackingShape binShape, IList<PackingItem> items);
+  }
+}
Index: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/Interfaces/IPermutationDecoder.cs
===================================================================
--- branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/Interfaces/IPermutationDecoder.cs	(revision 14148)
+++ 	(revision )
@@ -1,32 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 Joseph Helm and 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.Collections;
-using System.Collections.Generic;
-using HeuristicLab.Core;
-using HeuristicLab.Encodings.PermutationEncoding;
-using HeuristicLab.Problems.BinPacking;
-
-namespace HeuristicLab.Problems.BinPacking2D {
-  public interface IPermutationDecoder : IItem {
-    Solution Decode(Permutation permutation, PackingShape binShape, IList<PackingItem> items);
-  }
-}
Index: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/MoveEvaluatorBase.cs
===================================================================
--- branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/MoveEvaluatorBase.cs	(revision 14149)
+++ branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/MoveEvaluatorBase.cs	(revision 14149)
@@ -0,0 +1,96 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Joseph Helm and 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.BinPacking2D {
+  [StorableClass]
+  public abstract class MoveEvaluatorBase<TSol, TMove> : SingleSuccessorOperator,
+    ISingleObjectiveMoveEvaluator, ISingleObjectiveMoveOperator
+    where TSol : class, IItem
+    where TMove : class, IItem {
+    public ILookupParameter<TSol> EncodedSolutionParameter {
+      get { return (ILookupParameter<TSol>)Parameters["EncodedSolution"]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<ReadOnlyItemList<PackingItem>> PackingItemMeasuresParameter {
+      get { return (LookupParameter<ReadOnlyItemList<PackingItem>>)Parameters["Items"]; }
+    }
+    public ILookupParameter<PackingShape> PackingBinMeasuresParameter {
+      get { return (LookupParameter<PackingShape>)Parameters["BinShape"]; }
+    }
+    public ILookupParameter<IDecoder<TSol>> PackingSolutionDecoderParameter {
+      get { return (ILookupParameter<IDecoder<TSol>>)Parameters["Decoder"]; }
+    }
+    public ILookupParameter<IEvaluator> PackingPlanEvaluatorParameter {
+      get { return (ILookupParameter<IEvaluator>)Parameters["SolutionEvaluator"]; }
+    }
+    public ILookupParameter<TMove> MoveParameter {
+      get { return (ILookupParameter<TMove>)Parameters["Move"]; }
+    }
+
+
+    [StorableConstructor]
+    protected MoveEvaluatorBase(bool deserializing) : base(deserializing) { }
+    protected MoveEvaluatorBase(MoveEvaluatorBase<TSol, TMove> original, Cloner cloner) : base(original, cloner) { }
+    protected MoveEvaluatorBase()
+      : base() {
+      Parameters.Add(new LookupParameter<TSol>("EncodedSolution", "The encoded solution candidate to evaluate"));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of a packing solution."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The evaluated quality of a move on a packing solution."));
+      Parameters.Add(new LookupParameter<ReadOnlyItemList<PackingItem>>("Items", "Packing-item data taken from the bin-packing problem-instance."));
+      Parameters.Add(new LookupParameter<PackingShape>("BinShape", "Packing-bin data taken from the bin-packing problem-instance."));
+      Parameters.Add(new LookupParameter<IDecoder<TSol>>("Decoder", "The decoding operator that is used to calculate a packing plan from the used representation."));
+      Parameters.Add(new LookupParameter<IEvaluator>("SolutionEvaluator", "The actual packing plan evaluation operator."));
+      Parameters.Add(new LookupParameter<TMove>("Move", "The move to evaluate."));
+    }
+
+    public override IOperation Apply() {
+      var move = MoveParameter.ActualValue;
+      var encSolCandidate = EncodedSolutionParameter.ActualValue;
+      var binShape = PackingBinMeasuresParameter.ActualValue;
+      var items = PackingItemMeasuresParameter.ActualValue;
+
+
+      double moveQuality = EvaluateMove(encSolCandidate, move, binShape, items);
+
+      if (MoveQualityParameter.ActualValue == null)
+        MoveQualityParameter.ActualValue = new DoubleValue(moveQuality);
+      else
+        MoveQualityParameter.ActualValue.Value = moveQuality;
+      return base.Apply();
+    }
+
+    public abstract double EvaluateMove(TSol encodedSolutionCandidate, TMove move, PackingShape binShape, ReadOnlyItemList<PackingItem> items);
+  }
+}
Index: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/BottomLeftPermutationDecoder.cs
===================================================================
--- branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/BottomLeftPermutationDecoder.cs	(revision 14148)
+++ branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/BottomLeftPermutationDecoder.cs	(revision 14149)
@@ -29,5 +29,5 @@
   [Item("Bottom-left Permutation Decoder (2d)", "Decodes the permutation and creates a packing solution candidate")]
   [StorableClass]
-  public class BottomLeftPermutationDecoder : Item, IPermutationDecoder {
+  public class BottomLeftPermutationDecoder : Item, IDecoder<Permutation> {
 
     [StorableConstructor]
@@ -42,5 +42,5 @@
 
     public Solution Decode(Permutation permutation, PackingShape binShape, IList<PackingItem> items) {
-      Solution result = new Solution(binShape, true, false);
+      Solution result = new Solution(binShape, useExtremePoints: false, stackingConstraints: false);
       IList<int> remainingIDs = new List<int>(permutation);
       while (remainingIDs.Count > 0) {
Index: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/ExtremePointPermutationDecoder.cs
===================================================================
--- branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/ExtremePointPermutationDecoder.cs	(revision 14148)
+++ branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/ExtremePointPermutationDecoder.cs	(revision 14149)
@@ -29,5 +29,5 @@
   [Item("Extreme-point Permutation Decoder (2d)", "Decodes the permutation and creates a packing solution candidate")]
   [StorableClass]
-  public class ExtremePointPermutationDecoder : Item, IPermutationDecoder {
+  public class ExtremePointPermutationDecoder : Item, IDecoder<Permutation> {
 
     [StorableConstructor]
@@ -42,5 +42,5 @@
 
     public Solution Decode(Permutation permutation, PackingShape binShape, IList<PackingItem> items) {
-      Solution result = new Solution(binShape, true, false);
+      Solution result = new Solution(binShape, useExtremePoints: true, stackingConstraints: false);
       IList<int> remainingIDs = new List<int>(permutation);
       while (remainingIDs.Count > 0) {
Index: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/PermutationProblem.cs
===================================================================
--- branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/PermutationProblem.cs	(revision 14148)
+++ branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/PermutationProblem.cs	(revision 14149)
@@ -22,6 +22,4 @@
 #endregion
 
-using System;
-using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Common;
@@ -32,141 +30,31 @@
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Problems.BinPacking;
-using HeuristicLab.Problems.BinPacking2D;
 using HeuristicLab.Problems.Instances;
-using HeuristicLab.Random;
 
-namespace HeuristicLab.Problems.BinPacking2d {
+namespace HeuristicLab.Problems.BinPacking2D {
   [Item("Bin Packing Problem (2D, permutation encoding) (BPP)", "Represents a two-dimensional bin-packing problem using only bins with identical measures and bins/items with rectangular shapes.")]
   [StorableClass]
   [Creatable(Category = CreatableAttribute.Categories.CombinatorialProblems, Priority = 300)]
-  public sealed class PackingSequenceProblem : SingleObjectiveBasicProblem<PermutationEncoding>, IProblemInstanceConsumer<BPPData>, IProblemInstanceExporter<BPPData> {
-    private readonly string SolutionEvaluatorParameterName = "SolutionEvaluator";
-    #region Default Instance
-    private static readonly BPPData DefaultInstance = new BPPData() {
-      Name = "2D BPP Default Instance",
-      Description = "The default instance for 2D Bin Packing.",
-      BinShape = new PackingShape(20, 16),
-      Items = new PackingItem[] {
-        new PackingItem(3,  8, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
-        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0}
-      },
-    };
-    #endregion
-
-    #region parameter properties
-    public IValueParameter<IPermutationDecoder> DecoderParameter {
-      get { return (IValueParameter<IPermutationDecoder>)Parameters["Decoder"]; }
-    }
-    public IValueParameter<BinPacking2D.IEvaluator> SolutionEvaluatorParameter {
-      get { return (IValueParameter<BinPacking2D.IEvaluator>)Parameters[SolutionEvaluatorParameterName]; }
-    }
-    public IValueParameter<ReadOnlyItemList<PackingItem>> ItemsParameter {
-      get { return (IValueParameter<ReadOnlyItemList<PackingItem>>)Parameters["Items"]; }
-    }
-    public IValueParameter<PackingShape> BinShapeParameter {
-      get { return (IValueParameter<PackingShape>)Parameters["BinShape"]; }
-    }
-    public IValueParameter<Solution> BestKnownSolutionParameter {
-      get { return (IValueParameter<Solution>)Parameters["BestKnownSolution"]; }
-    }
-    public IFixedValueParameter<IntValue> LowerBoundParameter {
-      get { return (IFixedValueParameter<IntValue>)Parameters["LowerBound"]; }
-    }
-    #endregion
-
-    #region properties
-    public IPermutationDecoder Decoder {
-      get { return DecoderParameter.Value; }
-      set { DecoderParameter.Value = value; }
-    }
-    public new BinPacking2D.IEvaluator SolutionEvaluator {
-      get { return SolutionEvaluatorParameter.Value; }
-      set { SolutionEvaluatorParameter.Value = value; }
-    }
-    public ReadOnlyItemList<PackingItem> Items {
-      get { return ItemsParameter.Value; }
-      set { ItemsParameter.Value = value; }
-    }
-    public PackingShape BinShape {
-      get { return BinShapeParameter.Value; }
-      set { BinShapeParameter.Value = value; }
-    }
-    public Solution BestKnownSolution {
-      get { return BestKnownSolutionParameter.Value; }
-      set { BestKnownSolutionParameter.Value = value; }
-    }
-    public int LowerBound {
-      get { return LowerBoundParameter.Value.Value; }
-    }
-    public int NumberOfItems {
-      get { return Items == null ? 0 : Items.Count; }
-    }
-    #endregion
-
+  public sealed class PermutationProblem : ProblemBase<PermutationEncoding, Permutation> {
     // persistence
     [StorableConstructor]
-    private PackingSequenceProblem(bool deserializing) : base(deserializing) { }
+    private PermutationProblem(bool deserializing) : base(deserializing) { }
 
     // cloning
-    private PackingSequenceProblem(PackingSequenceProblem original, Cloner cloner)
+    private PermutationProblem(PermutationProblem original, Cloner cloner)
       : base(original, cloner) {
       RegisterEventHandlers();
     }
 
-    public PackingSequenceProblem()
+    public PermutationProblem()
       : base() {
-      var defaultEvaluator = new PackingRatioEvaluator();
-      var defaultDecoder = new ExtremePointPermutationDecoder();
-      Parameters.Add(new ValueParameter<IPermutationDecoder>("Decoder", "The decoder translates a permutation to a packing solution candidiates", defaultDecoder));
-      Parameters.Add(new ValueParameter<BinPacking2D.IEvaluator>(SolutionEvaluatorParameterName, "The evaluator calculates qualities of solution candidates", defaultEvaluator));
-      Parameters.Add(new ValueParameter<ReadOnlyItemList<PackingItem>>("Items", "The items which must be packed into bins"));
-      Parameters.Add(new ValueParameter<PackingShape>("BinShape", "The size of bins into which items must be packed"));
-      Parameters.Add(new OptionalValueParameter<Solution>("BestKnownSolution", "The best solution found so far"));
-      Parameters.Add(new FixedValueParameter<IntValue>("LowerBound", "A lower bound for the number of bins that is necessary to pack all items"));
+      Decoder = new ExtremePointPermutationDecoder(); // default decoder
 
-      Load(DefaultInstance);
-
-      Encoding = new PermutationEncoding("PackingSequence", Items.Count, PermutationTypes.Absolute);
+      Encoding = new PermutationEncoding(EncodedSolutionName, Items.Count, PermutationTypes.Absolute);
       AddOperators();
       RegisterEventHandlers();
     }
     public override IDeepCloneable Clone(Cloner cloner) {
-      return new PackingSequenceProblem(this, cloner);
+      return new PermutationProblem(this, cloner);
     }
 
@@ -192,103 +80,4 @@
       ItemsParameter.ValueChanged += (sender, args) => Encoding.Length = Items.Count;
     }
-
-    public override bool Maximization { get { return true; } }
-
-
-    public override double Evaluate(Individual individual, IRandom random) {
-      var permutation = individual.Permutation("PackingSequence");
-      var decoder = Decoder;
-      var solution = decoder.Decode(permutation, BinShape, Items);
-      return SolutionEvaluator.Evaluate(solution);
-    }
-
-    public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
-      base.Analyze(individuals, qualities, results, random);
-      Analyze(individuals.Select(i => i.Permutation("PackingSequence")).ToArray(), qualities, results, random);
-    }
-
-    public void Analyze(Permutation[] individuals, double[] qualities, ResultCollection results, IRandom random) {
-      var bestSolutionResultName = "Best Packing Solution";
-      var numContainersResultName = "Nr of Containers";
-      var binUtilResultName = "Overall Bin Utilization";
-
-      if (!results.ContainsKey(bestSolutionResultName)) results.Add(new Result(bestSolutionResultName, typeof(Solution)));
-      if (!results.ContainsKey(numContainersResultName)) results.Add(new Result(numContainersResultName, typeof(IntValue)));
-      if (!results.ContainsKey(binUtilResultName)) results.Add(new Result(binUtilResultName, typeof(DoubleValue)));
-
-
-      // find index of item with max quality
-      int bestIdx = 0;
-      for (int j = 1; j < qualities.Length; j++)
-        if (qualities[j] > qualities[bestIdx]) bestIdx = j;
-
-
-      // update best solution so far
-      var bestSolution = results[bestSolutionResultName].Value as Solution;
-      if (bestSolution == null ||
-        bestSolution.Quality.Value < qualities[bestIdx]) {
-
-        var newBestSolution = Decoder.Decode(individuals[bestIdx], BinShape, Items);
-        newBestSolution.Quality = new DoubleValue(qualities[bestIdx]);
-        results[bestSolutionResultName].Value = newBestSolution;
-        results[numContainersResultName].Value = new IntValue(newBestSolution.NrOfBins);
-        results[binUtilResultName].Value = new DoubleValue(BinUtilizationEvaluator.CalculateBinUtilization(newBestSolution));
-
-        // update best known solution
-        var bestKnownQuality = BestKnownQualityParameter.Value;
-        if (bestKnownQuality == null ||
-            bestKnownQuality.Value < qualities[bestIdx]) {
-          BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[bestIdx]);
-          BestKnownSolutionParameter.ActualValue = newBestSolution;
-        }
-      }
-    }
-
-
-    #region Problem instance handling
-    public void Load(BPPData data) {
-      BestKnownSolutionParameter.Value = null;
-      BestKnownQualityParameter.Value = null;
-
-      if (data.BestKnownQuality.HasValue)
-        BestKnownQuality = data.BestKnownQuality.Value;
-
-      BinShape = data.BinShape;
-      var items = new ItemList<PackingItem>(data.Items);
-      items.Sort((x, y) => y.CompareTo(x));
-      Items = items.AsReadOnly();
-
-      ApplyHorizontalOrientation();
-      LowerBoundParameter.Value.Value = CalculateLowerBound();
-    }
-
-
-    public BPPData Export() {
-      return new BPPData {
-        Name = Name,
-        Description = Description,
-        BinShape = BinShape,
-        Items = Items.ToArray()
-      };
-    }
-    #endregion
-
-
-    #region helpers
-    private void ApplyHorizontalOrientation() {
-      BinShape.ApplyHorizontalOrientation();
-      foreach (var shape in Items) {
-        shape.ApplyHorizontalOrientation();
-      }
-    }
-
-    private int CalculateLowerBound() {
-      //This is the obvious continuous lower bound calculation; Martello and Vigo proposed a better way but it has not been implemented yet;
-      int itemsVol = Items.Select(x => x.Volume).Sum();
-      int binVol = BinShape.Volume;
-      return (itemsVol + binVol - 1) / (binVol);
-    }
-
-    #endregion
   }
 }
Index: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/Swap2MoveEvaluator.cs
===================================================================
--- branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/Swap2MoveEvaluator.cs	(revision 14148)
+++ branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/Swap2MoveEvaluator.cs	(revision 14149)
@@ -22,9 +22,5 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Data;
 using HeuristicLab.Encodings.PermutationEncoding;
-using HeuristicLab.Operators;
-using HeuristicLab.Optimization;
-using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -32,33 +28,10 @@
   [Item("Swap2MoveEvaluator", "Move evaluator for 2-opt moves.")]
   [StorableClass]
-  public sealed class Swap2MoveEvaluator : SingleSuccessorOperator,
-    ISingleObjectiveMoveEvaluator, ISingleObjectiveMoveOperator, IPermutationSwap2MoveOperator {
-    public override bool CanChangeName {
-      get { return false; }
+  public sealed class Swap2MoveEvaluator : MoveEvaluatorBase<Permutation, Swap2Move>, IPermutationSwap2MoveOperator {
+    public ILookupParameter<Swap2Move> Swap2MoveParameter {
+      get { return MoveParameter; }
     }
     public ILookupParameter<Permutation> PermutationParameter {
-      get { return (ILookupParameter<Permutation>)Parameters["PackingSequence"]; }
-    }
-    public ILookupParameter<DoubleValue> QualityParameter {
-      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
-    }
-    public ILookupParameter<DoubleValue> MoveQualityParameter {
-      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
-    }
-    public ILookupParameter<ReadOnlyItemList<PackingItem>> PackingItemMeasuresParameter {
-      get { return (LookupParameter<ReadOnlyItemList<PackingItem>>)Parameters["Items"]; }
-    }
-    public ILookupParameter<PackingShape> PackingBinMeasuresParameter {
-      get { return (LookupParameter<PackingShape>)Parameters["BinShape"]; }
-    }
-    public ILookupParameter<IPermutationDecoder> PackingSolutionDecoderParameter {
-      get { return (ILookupParameter<IPermutationDecoder>)Parameters["Decoder"]; }
-    }
-    public ILookupParameter<IEvaluator> PackingPlanEvaluatorParameter {
-      get { return (ILookupParameter<IEvaluator>)Parameters["SolutionEvaluator"]; }
-    }
-
-    public ILookupParameter<Swap2Move> Swap2MoveParameter {
-      get { return (ILookupParameter<Swap2Move>)Parameters["Swap2Move"]; }
+      get { return EncodedSolutionParameter; }
     }
 
@@ -68,12 +41,4 @@
     public Swap2MoveEvaluator()
       : base() {
-      Parameters.Add(new LookupParameter<Permutation>("PackingSequence", "The encoded solution candidate to evaluate"));
-      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of a packing solution."));
-      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The evaluated quality of a move on a packing solution."));
-      Parameters.Add(new LookupParameter<ReadOnlyItemList<PackingItem>>("Items", "Packing-item data taken from the bin-packing problem-instance."));
-      Parameters.Add(new LookupParameter<PackingShape>("BinShape", "Packing-bin data taken from the bin-packing problem-instance."));
-      Parameters.Add(new LookupParameter<IPermutationDecoder>("Decoder", "The decoding operator that is used to calculate a packing plan from the used representation."));
-      Parameters.Add(new LookupParameter<IEvaluator>("SolutionEvaluator", "The actual packing plan evaluation operator."));
-      Parameters.Add(new LookupParameter<Swap2Move>("Swap2Move", "The move to evaluate."));
     }
 
@@ -82,24 +47,10 @@
     }
 
-
-    public override IOperation Apply() {
-      var move = Swap2MoveParameter.ActualValue;
-      var permutation = PermutationParameter.ActualValue;
-      var binShape = PackingBinMeasuresParameter.ActualValue;
-      var items = PackingItemMeasuresParameter.ActualValue;
-
+    public override double EvaluateMove(Permutation permutation, Swap2Move move, PackingShape binShape, ReadOnlyItemList<PackingItem> items) {
       // uses full evaluation
       Swap2Manipulator.Apply(permutation, move.Index1, move.Index2);
       var solution = PackingSolutionDecoderParameter.ActualValue.Decode(permutation, binShape, items);
 
-      var quality = PackingPlanEvaluatorParameter.ActualValue.Evaluate(solution);
-
-      double moveQuality = quality;
-
-      if (MoveQualityParameter.ActualValue == null)
-        MoveQualityParameter.ActualValue = new DoubleValue(moveQuality);
-      else
-        MoveQualityParameter.ActualValue.Value = moveQuality;
-      return base.Apply();
+      return PackingPlanEvaluatorParameter.ActualValue.Evaluate(solution);
     }
   }
Index: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/TranslocationMoveEvaluator.cs
===================================================================
--- branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/TranslocationMoveEvaluator.cs	(revision 14148)
+++ branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/PermutationEncoding/TranslocationMoveEvaluator.cs	(revision 14149)
@@ -22,9 +22,5 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Data;
 using HeuristicLab.Encodings.PermutationEncoding;
-using HeuristicLab.Operators;
-using HeuristicLab.Optimization;
-using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -32,35 +28,11 @@
   [Item("TranslocationMoveEvaluator", "Move evaluator for insertion or translocation moves.")]
   [StorableClass]
-  public sealed class TranslocationMoveEvaluator : SingleSuccessorOperator,
-    ISingleObjectiveMoveEvaluator, ISingleObjectiveMoveOperator, IPermutationTranslocationMoveOperator {
-    public override bool CanChangeName {
-      get { return false; }
+  public sealed class TranslocationMoveEvaluator : MoveEvaluatorBase<Permutation, TranslocationMove>, IPermutationTranslocationMoveOperator {
+    public ILookupParameter<TranslocationMove> TranslocationMoveParameter {
+      get { return MoveParameter; }
     }
     public ILookupParameter<Permutation> PermutationParameter {
-      get { return (ILookupParameter<Permutation>)Parameters["PackingSequence"]; }
+      get { return EncodedSolutionParameter; }
     }
-    public ILookupParameter<DoubleValue> QualityParameter {
-      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
-    }
-    public ILookupParameter<DoubleValue> MoveQualityParameter {
-      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
-    }
-    public ILookupParameter<ReadOnlyItemList<PackingItem>> PackingItemMeasuresParameter {
-      get { return (LookupParameter<ReadOnlyItemList<PackingItem>>)Parameters["Items"]; }
-    }
-    public ILookupParameter<PackingShape> PackingBinMeasuresParameter {
-      get { return (LookupParameter<PackingShape>)Parameters["BinShape"]; }
-    }
-    public ILookupParameter<IPermutationDecoder> PackingSolutionDecoderParameter {
-      get { return (ILookupParameter<IPermutationDecoder>)Parameters["Decoder"]; }
-    }
-    public ILookupParameter<IEvaluator> PackingPlanEvaluatorParameter {
-      get { return (ILookupParameter<IEvaluator>)Parameters["SolutionEvaluator"]; }
-    }
-
-    public ILookupParameter<TranslocationMove> TranslocationMoveParameter {
-      get { return (ILookupParameter<TranslocationMove>)Parameters["TranslocationMove"]; }
-    }
-
     [StorableConstructor]
     private TranslocationMoveEvaluator(bool deserializing) : base(deserializing) { }
@@ -68,12 +40,4 @@
     public TranslocationMoveEvaluator()
       : base() {
-      Parameters.Add(new LookupParameter<Permutation>("PackingSequence", "The encoded solution candidate to evaluate"));
-      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of a packing solution."));
-      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The evaluated quality of a move on a packing solution."));
-      Parameters.Add(new LookupParameter<ReadOnlyItemList<PackingItem>>("Items", "Packing-item data taken from the bin-packing problem-instance."));
-      Parameters.Add(new LookupParameter<PackingShape>("BinShape", "Packing-bin data taken from the bin-packing problem-instance."));
-      Parameters.Add(new LookupParameter<IPermutationDecoder>("Decoder", "The decoding operator that is used to calculate a packing plan from the used representation."));
-      Parameters.Add(new LookupParameter<IEvaluator>("SolutionEvaluator", "The actual packing plan evaluation operator."));
-      Parameters.Add(new LookupParameter<TranslocationMove>("TranslocationMove", "The move to evaluate."));
     }
 
@@ -82,25 +46,12 @@
     }
 
-
-    public override IOperation Apply() {
-      var move = TranslocationMoveParameter.ActualValue;
-      var permutation = PermutationParameter.ActualValue;
-      var binShape = PackingBinMeasuresParameter.ActualValue;
-      var items = PackingItemMeasuresParameter.ActualValue;
+    public override double EvaluateMove(Permutation permutation, TranslocationMove move, PackingShape binShape,
+      ReadOnlyItemList<PackingItem> items) {
 
       // uses full evaluation
-
       TranslocationManipulator.Apply(permutation, move.Index1, move.Index2, move.Index3);
       var solution = PackingSolutionDecoderParameter.ActualValue.Decode(permutation, binShape, items);
 
-      var quality = PackingPlanEvaluatorParameter.ActualValue.Evaluate(solution);
-
-      double moveQuality = quality;
-
-      if (MoveQualityParameter.ActualValue == null)
-        MoveQualityParameter.ActualValue = new DoubleValue(moveQuality);
-      else
-        MoveQualityParameter.ActualValue.Value = moveQuality;
-      return base.Apply();
+      return PackingPlanEvaluatorParameter.ActualValue.Evaluate(solution);
     }
   }
Index: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/ProblemBase.cs
===================================================================
--- branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/ProblemBase.cs	(revision 14149)
+++ branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.2D/3.3/ProblemBase.cs	(revision 14149)
@@ -0,0 +1,259 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.Instances;
+
+namespace HeuristicLab.Problems.BinPacking2D {
+  [StorableClass]
+  public abstract class ProblemBase<TEnc, TSol> :
+    SingleObjectiveBasicProblem<TEnc>, IProblemInstanceConsumer<BPPData>, IProblemInstanceExporter<BPPData>
+    where TEnc : class, IEncoding
+    where TSol : class, IItem {
+    private readonly string SolutionEvaluatorParameterName = "SolutionEvaluator";
+    public readonly string EncodedSolutionName = "EncodedSolution";
+    #region Default Instance
+    private static readonly BPPData DefaultInstance = new BPPData() {
+      Name = "2D BPP Default Instance",
+      Description = "The default instance for 2D Bin Packing.",
+      BinShape = new PackingShape(20, 16),
+      Items = new PackingItem[] {
+        new PackingItem(3,  8, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
+        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0}
+      },
+    };
+    #endregion
+
+    #region parameter properties
+    public IValueParameter<IDecoder<TSol>> DecoderParameter {
+      get { return (IValueParameter<IDecoder<TSol>>)Parameters["Decoder"]; }
+    }
+    public IValueParameter<IEvaluator> SolutionEvaluatorParameter {
+      get { return (IValueParameter<IEvaluator>)Parameters[SolutionEvaluatorParameterName]; }
+    }
+    public IValueParameter<ReadOnlyItemList<PackingItem>> ItemsParameter {
+      get { return (IValueParameter<ReadOnlyItemList<PackingItem>>)Parameters["Items"]; }
+    }
+    public IValueParameter<PackingShape> BinShapeParameter {
+      get { return (IValueParameter<PackingShape>)Parameters["BinShape"]; }
+    }
+    public IValueParameter<Solution> BestKnownSolutionParameter {
+      get { return (IValueParameter<Solution>)Parameters["BestKnownSolution"]; }
+    }
+    public IFixedValueParameter<IntValue> LowerBoundParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters["LowerBound"]; }
+    }
+    #endregion
+
+    #region properties
+    public IDecoder<TSol> Decoder {
+      get { return DecoderParameter.Value; }
+      set { DecoderParameter.Value = value; }
+    }
+    public IEvaluator SolutionEvaluator {
+      get { return SolutionEvaluatorParameter.Value; }
+      set { SolutionEvaluatorParameter.Value = value; }
+    }
+    public ReadOnlyItemList<PackingItem> Items {
+      get { return ItemsParameter.Value; }
+      set { ItemsParameter.Value = value; }
+    }
+    public PackingShape BinShape {
+      get { return BinShapeParameter.Value; }
+      set { BinShapeParameter.Value = value; }
+    }
+    public Solution BestKnownSolution {
+      get { return BestKnownSolutionParameter.Value; }
+      set { BestKnownSolutionParameter.Value = value; }
+    }
+    public int LowerBound {
+      get { return LowerBoundParameter.Value.Value; }
+    }
+    public int NumberOfItems {
+      get { return Items == null ? 0 : Items.Count; }
+    }
+    #endregion
+
+    // persistence
+    [StorableConstructor]
+    protected ProblemBase(bool deserializing) : base(deserializing) { }
+
+    // cloning
+    protected ProblemBase(ProblemBase<TEnc, TSol> original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    protected ProblemBase()
+      : base() {
+      var defaultEvaluator = new PackingRatioEvaluator();
+      Parameters.Add(new ValueParameter<IDecoder<TSol>>("Decoder", "The decoder translates a permutation to a packing solution candidiates"));
+      Parameters.Add(new ValueParameter<IEvaluator>(SolutionEvaluatorParameterName, "The evaluator calculates qualities of solution candidates", defaultEvaluator));
+      Parameters.Add(new ValueParameter<ReadOnlyItemList<PackingItem>>("Items", "The items which must be packed into bins"));
+      Parameters.Add(new ValueParameter<PackingShape>("BinShape", "The size of bins into which items must be packed"));
+      Parameters.Add(new OptionalValueParameter<Solution>("BestKnownSolution", "The best solution found so far"));
+      Parameters.Add(new FixedValueParameter<IntValue>("LowerBound", "A lower bound for the number of bins that is necessary to pack all items"));
+
+      Load(DefaultInstance);
+    }
+
+    public override bool Maximization { get { return true; } }
+
+
+    public override double Evaluate(Individual individual, IRandom random) {
+      var encodedSolutionCand = (TSol)individual[EncodedSolutionName];
+      var decoder = Decoder;
+      var solution = decoder.Decode(encodedSolutionCand, BinShape, Items);
+      return SolutionEvaluator.Evaluate(solution);
+    }
+
+    public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
+      base.Analyze(individuals, qualities, results, random);
+      Analyze(individuals.Select(i => (TSol)i[EncodedSolutionName]).ToArray(), qualities, results, random);
+    }
+
+    public virtual void Analyze(TSol[] individuals, double[] qualities, ResultCollection results, IRandom random) {
+      var bestSolutionResultName = "Best Packing Solution";
+      var numContainersResultName = "Nr of Containers";
+      var binUtilResultName = "Overall Bin Utilization";
+
+      if (!results.ContainsKey(bestSolutionResultName)) results.Add(new Result(bestSolutionResultName, typeof(Solution)));
+      if (!results.ContainsKey(numContainersResultName)) results.Add(new Result(numContainersResultName, typeof(IntValue)));
+      if (!results.ContainsKey(binUtilResultName)) results.Add(new Result(binUtilResultName, typeof(DoubleValue)));
+
+
+      // find index of item with max quality
+      int bestIdx = 0;
+      for (int j = 1; j < qualities.Length; j++)
+        if (qualities[j] > qualities[bestIdx]) bestIdx = j;
+
+
+      // update best solution so far
+      var bestSolution = results[bestSolutionResultName].Value as Solution;
+      if (bestSolution == null ||
+        bestSolution.Quality.Value < qualities[bestIdx]) {
+
+        var newBestSolution = Decoder.Decode(individuals[bestIdx], BinShape, Items);
+        newBestSolution.Quality = new DoubleValue(qualities[bestIdx]);
+        results[bestSolutionResultName].Value = newBestSolution;
+        results[numContainersResultName].Value = new IntValue(newBestSolution.NrOfBins);
+        results[binUtilResultName].Value = new DoubleValue(BinUtilizationEvaluator.CalculateBinUtilization(newBestSolution));
+
+        // update best known solution
+        var bestKnownQuality = BestKnownQualityParameter.Value;
+        if (bestKnownQuality == null ||
+            bestKnownQuality.Value < qualities[bestIdx]) {
+          BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[bestIdx]);
+          BestKnownSolutionParameter.ActualValue = newBestSolution;
+        }
+      }
+    }
+
+
+    #region Problem instance handling
+    public void Load(BPPData data) {
+      BestKnownSolutionParameter.Value = null;
+      BestKnownQualityParameter.Value = null;
+
+      if (data.BestKnownQuality.HasValue)
+        BestKnownQuality = data.BestKnownQuality.Value;
+
+      BinShape = data.BinShape;
+      var items = new ItemList<PackingItem>(data.Items);
+      items.Sort((x, y) => y.CompareTo(x));
+      Items = items.AsReadOnly();
+
+      ApplyHorizontalOrientation();
+      LowerBoundParameter.Value.Value = CalculateLowerBound();
+    }
+
+
+    public BPPData Export() {
+      return new BPPData {
+        Name = Name,
+        Description = Description,
+        BinShape = BinShape,
+        Items = Items.ToArray()
+      };
+    }
+    #endregion
+
+
+    #region helpers
+    private void ApplyHorizontalOrientation() {
+      BinShape.ApplyHorizontalOrientation();
+      foreach (var shape in Items) {
+        shape.ApplyHorizontalOrientation();
+      }
+    }
+
+    private int CalculateLowerBound() {
+      //This is the obvious continuous lower bound calculation; Martello and Vigo proposed a better way but it has not been implemented yet;
+      int itemsVol = Items.Select(x => x.Volume).Sum();
+      int binVol = BinShape.Volume;
+      return (itemsVol + binVol - 1) / (binVol);
+    }
+
+    #endregion
+  }
+}
