Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking.Views/3.3/Container3DView.xaml.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking.Views/3.3/Container3DView.xaml.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking.Views/3.3/Container3DView.xaml.cs	(revision 15646)
@@ -141,5 +141,5 @@
         var selectedModel = new GeometryModel3D { Geometry = new MeshGeometry3D(), Material = material };
         AddSolidCube((MeshGeometry3D)selectedModel.Geometry, selectedPos.X, selectedPos.Y, selectedPos.Z,
-          selectedItem.Value.DepthInView,
+          selectedItem.Value.WidthInView,
           selectedItem.Value.HeightInView,
           selectedItem.Value.DepthInView);
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Algorithms/ExtremePointAlgorithm.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Algorithms/ExtremePointAlgorithm.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Algorithms/ExtremePointAlgorithm.cs	(revision 15646)
@@ -202,8 +202,8 @@
     /// <param name="token"></param>
     /// <returns></returns>
-    private Tuple<Solution, double, SortingMethod?, FittingMethod?, ExtremePointCreationMethod?> 
-          GetBest(PackingShape bin, 
-                  IList<PackingItem> items, 
-                  SortingMethod[] sortings, 
+    private Tuple<Solution, double, SortingMethod?, FittingMethod?, ExtremePointCreationMethod?>
+          GetBest(PackingShape bin,
+                  IList<PackingItem> items,
+                  SortingMethod[] sortings,
                   FittingMethod[] fittings,
                   ExtremePointCreationMethod[] epCreationMethods,
@@ -222,5 +222,5 @@
             };
             Permutation sortedItems;
-                    
+
             if (SortByMaterialParameter.Value.Value) {
               sortedItems = SortItemsByMaterialAndSortingMethod(bin, items, sort, DeltaParameter.Value.Value);
@@ -229,5 +229,5 @@
             }
 
-            var result = Optimize(new OptimaizationParamters() {
+            var solution = Optimize(new OptimaizationParamters() {
               SortedItems = sortedItems,
               Bin = bin,
@@ -238,5 +238,17 @@
               ExtremePointGeneration = epCreation
             });
-          
+
+            if (solution.IsBetterThan(bestSolution, Problem.SolutionEvaluator, Problem.Maximization)) {
+              bestSolution = solution;
+              best = Problem.SolutionEvaluator.Evaluate(solution);
+              bestSorting = sort;
+              bestFitting = fit;
+              bestEPCreation = epCreation;
+            }
+
+
+            var x = Problem.SolutionEvaluator.Evaluate1(solution);
+
+            /*
             if (double.IsNaN(result.Item2) || double.IsInfinity(result.Item2)) {
               continue;
@@ -250,4 +262,6 @@
               bestEPCreation = epCreation;
             }
+            return true;*/
+
             if (token.IsCancellationRequested) {
               return Tuple.Create(bestSolution, best, bestSorting, bestFitting, bestEPCreation);
@@ -267,10 +281,10 @@
     /// <param name="parameters"></param>
     /// <returns></returns>
-    private static Tuple<Solution, double> Optimize(OptimaizationParamters parameters) { 
-      
+    private static Solution Optimize(OptimaizationParamters parameters) {
+
       var sol = parameters.Decoder.Decode(parameters.SortedItems, parameters.Bin, parameters.Items, parameters.StackingConstraints);
-      var fit = parameters.Evaluator.Evaluate(sol);
-
-      return Tuple.Create(sol, fit);
+      //var fit = parameters.Evaluator.Evaluate(sol);
+
+      return sol; //Tuple.Create(sol, fit);
     }
 
@@ -284,8 +298,47 @@
       public ExtremePointCreationMethod ExtremePointGeneration { get; set; }
     }
-    
+
 
     /// <summary>
     /// Returns a new permutation of the given items depending on the sorting method
+    /// </summary>
+    /// <param name="bin"></param>
+    /// <param name="items"></param>
+    /// <param name="sortingMethod"></param>
+    /// <param name="delta"></param>
+    /// <returns></returns>
+    private Permutation SortItemsByMaterialAndSortingMethod(PackingShape bin, IList<PackingItem> items, SortingMethod sortingMethod, double delta) {
+      Permutation sorted = null;
+
+      switch (sortingMethod) {
+        case SortingMethod.Given:
+          sorted = new Permutation(PermutationTypes.Absolute, Enumerable.Range(0, items.Count).ToArray());
+          break;
+        case SortingMethod.VolumeHeight:
+          sorted = items.SortByVolumeHeight();
+          break;
+        case SortingMethod.HeightVolume:
+          sorted = items.SortByMaterialHeightVolume();
+          break;
+        case SortingMethod.AreaHeight:
+          sorted = items.SortByMaterialAreaHeight();
+          break;
+        case SortingMethod.HeightArea:
+          sorted = items.SortByMaterialHeightArea();
+          break;
+        case SortingMethod.ClusteredAreaHeight:
+          sorted = items.SortByMaterialClusteredAreaHeight(bin, delta);
+          break;
+        case SortingMethod.ClusteredHeightArea:
+          sorted = items.SortByMaterialClusteredHeightArea(bin, delta);
+          break;
+        default:
+          throw new ArgumentException("Unknown sorting method: " + sortingMethod);
+      }
+      return sorted;
+    }
+
+    /// <summary>
+    /// Returns a new permutation of the given items depending on the material and sorting method
     /// </summary>
     /// <param name="bin"></param>
@@ -296,5 +349,5 @@
     private Permutation SortItemsBySortingMethod(PackingShape bin, IList<PackingItem> items, SortingMethod sortingMethod, double delta) {
       Permutation sorted = null;
-      
+
       switch (sortingMethod) {
         case SortingMethod.Given:
@@ -305,17 +358,17 @@
           break;
         case SortingMethod.HeightVolume:
-          sorted = items.SortByMaterialHeightVolume();
+          sorted = items.SortByHeightVolume();
           break;
         case SortingMethod.AreaHeight:
-          sorted = items.SortByMaterialAreaHeight();
+          sorted = items.SortByAreaHeight();
           break;
         case SortingMethod.HeightArea:
-          sorted = items.SortByMaterialHeightArea();
+          sorted = items.SortByHeightArea();
           break;
         case SortingMethod.ClusteredAreaHeight:
-          sorted = items.SortByMaterialClusteredAreaHeight(bin, delta);
+          sorted = items.SortByClusteredAreaHeight(bin, delta);
           break;
         case SortingMethod.ClusteredHeightArea:
-          sorted = items.SortByMaterialClusteredHeightArea(bin, delta);
+          sorted = items.SortByClusteredHeightArea(bin, delta);
           break;
         default:
@@ -324,43 +377,4 @@
       return sorted;
     }
-
-    /// <summary>
-    /// Returns a new permutation of the given items depending on the material and sorting method
-    /// </summary>
-    /// <param name="bin"></param>
-    /// <param name="items"></param>
-    /// <param name="sortingMethod"></param>
-    /// <param name="delta"></param>
-    /// <returns></returns>
-    private Permutation SortItemsByMaterialAndSortingMethod(PackingShape bin, IList<PackingItem> items, SortingMethod sortingMethod, double delta) {
-      Permutation sorted = null;
-
-      switch (sortingMethod) {
-        case SortingMethod.Given:
-          sorted = new Permutation(PermutationTypes.Absolute, Enumerable.Range(0, items.Count).ToArray());
-          break;
-        case SortingMethod.VolumeHeight:
-          sorted = items.SortByVolumeHeight();
-          break;
-        case SortingMethod.HeightVolume:
-          sorted = items.SortByHeightVolume();
-          break;
-        case SortingMethod.AreaHeight:
-          sorted = items.SortByAreaHeight();
-          break;
-        case SortingMethod.HeightArea:
-          sorted = items.SortByHeightArea();
-          break;
-        case SortingMethod.ClusteredAreaHeight:
-          sorted = items.SortByClusteredAreaHeight(bin, delta);
-          break;
-        case SortingMethod.ClusteredHeightArea:
-          sorted = items.SortByClusteredHeightArea(bin, delta);
-          break;
-        default:
-          throw new ArgumentException("Unknown sorting method: " + sortingMethod);
-      }
-      return sorted;
-    }
   }
 }
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/BinPacking3D.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/BinPacking3D.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/BinPacking3D.cs	(revision 15646)
@@ -34,5 +34,5 @@
   [StorableClass]
   public class BinPacking3D : BinPacking<PackingPosition, PackingShape, PackingItem> {
-    
+
     [Storable]
     public IDictionary<PackingPosition, IEnumerable<ResidualSpace>> ExtremePoints { get; protected set; }
@@ -42,6 +42,6 @@
       : base(binShape) {
       ExtremePoints = new SortedList<PackingPosition, IEnumerable<ResidualSpace>>();
-      
-      ExtremePoints.Add(binShape.Origin, new List<ResidualSpace>() {ResidualSpace.Create(binShape.Width, binShape.Height, binShape.Depth)});
+
+      ExtremePoints.Add(binShape.Origin, new List<ResidualSpace>() { ResidualSpace.Create(binShape.Width, binShape.Height, binShape.Depth) });
     }
 
@@ -66,5 +66,5 @@
     }
 
-    
+
 
     /// <summary>
@@ -96,23 +96,58 @@
 
 
-      /*
-    /// <summary>
-    /// Updates the extreme points of the bin. 
-    /// As there is no need to project the extreme points to the next side of an item, the extreme points are only generated for the current item.
-    /// </summary>
-    /// <param name="item"></param>
-    /// <param name="position"></param>
-    private void UpdateExtremePointsWithStackingConstriants(PackingItem newItem, PackingPosition position) {
-      int newWidth = position.Rotated ? newItem.Depth : newItem.Width;
-      int newDepth = position.Rotated ? newItem.Width : newItem.Depth;
-      var ep1 = new PackingPosition(position.AssignedBin, position.X + newWidth, position.Y, position.Z);
-      var ep2 = new PackingPosition(position.AssignedBin, position.X, position.Y + newItem.Height, position.Z);
-      var ep3 = new PackingPosition(position.AssignedBin, position.X, position.Y, position.Z + newDepth);
-      AddExtremePoint(ep1);
-      AddExtremePoint(ep2);
-      AddExtremePoint(ep3);
-    }*/
-
-     
+    /*
+  /// <summary>
+  /// Updates the extreme points of the bin. 
+  /// As there is no need to project the extreme points to the next side of an item, the extreme points are only generated for the current item.
+  /// </summary>
+  /// <param name="item"></param>
+  /// <param name="position"></param>
+  private void UpdateExtremePointsWithStackingConstriants(PackingItem newItem, PackingPosition position) {
+    int newWidth = position.Rotated ? newItem.Depth : newItem.Width;
+    int newDepth = position.Rotated ? newItem.Width : newItem.Depth;
+    var ep1 = new PackingPosition(position.AssignedBin, position.X + newWidth, position.Y, position.Z);
+    var ep2 = new PackingPosition(position.AssignedBin, position.X, position.Y + newItem.Height, position.Z);
+    var ep3 = new PackingPosition(position.AssignedBin, position.X, position.Y, position.Z + newDepth);
+    AddExtremePoint(ep1);
+    AddExtremePoint(ep2);
+    AddExtremePoint(ep3);
+  }*/
+
+
+    #region MassPoint
+
+    /// <summary>
+    /// This property contains the value of the mass point for the current bin packing.
+    /// </summary>
+    public Tuple<double, double, double> MassPoint { get { return CalculateMassPoint(); } }
+
+    private Tuple<double, double, double> CalculateMassPoint() {
+      var packingMassPoint = new { X = 0.0, Y = 0.0, Z = 0.0 };
+      var totalWeight = 0.0;
+      foreach (var item in Items) {
+        var position = Positions[item.Key];
+        var w = item.Value.Width;
+        var h = item.Value.Height;
+        var d = item.Value.Depth;
+
+        var massPoint = new { X = position.X + w / 2.0, Y = position.Y + h / 2.0, Z = position.Z + d / 2.0 };
+        var weight = Math.Max(item.Value.Weight, 1);
+        if (packingMassPoint == null) {
+          packingMassPoint = massPoint;
+          totalWeight += weight;
+        } else {
+          var newTotalWeight = totalWeight + weight;
+          packingMassPoint = new {
+            X = (massPoint.X * weight + packingMassPoint.X * totalWeight) / newTotalWeight,
+            Y = (massPoint.Y * weight + packingMassPoint.Y * totalWeight) / newTotalWeight,
+            Z = (massPoint.Z * weight + packingMassPoint.Z * totalWeight) / newTotalWeight
+          };
+          totalWeight = newTotalWeight;
+        }
+      }
+      
+      return Tuple.Create<double, double, double>(packingMassPoint.X, packingMassPoint.Y, packingMassPoint.Z);
+    }
+    #endregion
 
     #region Position feasability
@@ -128,10 +163,8 @@
     /// <returns></returns>
     public override bool IsPositionFeasible(PackingItem item, PackingPosition position, bool stackingConstraints) {
-      //var b1 = CheckItemDimensions(item, position);
-      var b2 = ItemCanBePlaced(item, position);
-      var b3 = CheckStackingConstraints(item, position, stackingConstraints);
-
-      return b2 && b3;
-    }
+      return ItemCanBePlaced(item, position) && CheckStackingConstraints(item, position, stackingConstraints);
+    }
+
+
 
     /// <summary>
@@ -142,10 +175,8 @@
     /// <returns></returns>
     private bool ItemCanBePlaced(PackingItem givenItem, PackingPosition givenItemPosition) {
-      var width = givenItemPosition.Rotated ? givenItem.Depth : givenItem.Width;
-      var depth = givenItemPosition.Rotated ? givenItem.Width : givenItem.Depth;
       // Check if the boundings of the bin would injured
-      if (givenItemPosition.X + width > BinShape.Width ||
+      if (givenItemPosition.X + givenItem.Width > BinShape.Width ||
           givenItemPosition.Y + givenItem.Height > BinShape.Height ||
-          givenItemPosition.Z + depth > BinShape.Depth) {
+          givenItemPosition.Z + givenItem.Depth > BinShape.Depth) {
         return false;
       }
@@ -201,5 +232,5 @@
     private bool HasOnePointWithAnItemBelow(PackingItem item, PackingPosition position) {
       bool p1, p2, p3, p4;
-      PointsLiesOnAnItem(item, position, out p1, out p2, out p3, out p4);
+      PointsLiesOnAnStackableItem(item, position, out p1, out p2, out p3, out p4);
 
       return p1 || p2 || p3 || p4;
@@ -215,5 +246,5 @@
     public override bool IsStaticStable(PackingItem item, PackingPosition position) {
       bool p1, p2, p3, p4;
-      PointsLiesOnAnItem(item, position, out p1, out p2, out p3, out p4);
+      PointsLiesOnAnStackableItem(item, position, out p1, out p2, out p3, out p4);
       return p1 && p2 && p3 && p4;
     }
@@ -234,5 +265,5 @@
     /// <param name="p3"></param>
     /// <param name="p4"></param>
-    private void PointsLiesOnAnItem(PackingItem item, PackingPosition position, out bool p1, out bool p2, out bool p3, out bool p4) {
+    private void PointsLiesOnAnStackableItem(PackingItem item, PackingPosition position, out bool p1, out bool p2, out bool p3, out bool p4) {
       IEnumerable<Tuple<PackingPosition, PackingItem>> itemsP1;
       IEnumerable<Tuple<PackingPosition, PackingItem>> itemsP2;
@@ -242,8 +273,8 @@
       GetItemsUnderItemWithContact(item, position, out itemsP1, out itemsP2, out itemsP3, out itemsP4);
 
-      p1 = itemsP1.Where(x => position.X < x.Item1.X + x.Item2.Width && position.Z < x.Item1.Z + x.Item2.Depth).Any();
-      p2 = itemsP2.Where(x => position.X + item.Width > x.Item1.X && position.Z < x.Item1.Z + x.Item2.Depth).Any();
-      p3 = itemsP3.Where(x => position.X + item.Width > x.Item1.X && position.Z + item.Depth > x.Item1.Z).Any();
-      p4 = itemsP4.Where(x => position.X < x.Item1.X + x.Item2.Width && position.Z + item.Depth > x.Item1.Z).Any();
+      p1 = itemsP1.Where(x => x.Item2.IsStackabel && position.X < x.Item1.X + x.Item2.Width && position.Z < x.Item1.Z + x.Item2.Depth).Any();
+      p2 = itemsP2.Where(x => x.Item2.IsStackabel && position.X + item.Width > x.Item1.X && position.Z < x.Item1.Z + x.Item2.Depth).Any();
+      p3 = itemsP3.Where(x => x.Item2.IsStackabel && position.X + item.Width > x.Item1.X && position.Z + item.Depth > x.Item1.Z).Any();
+      p4 = itemsP4.Where(x => x.Item2.IsStackabel && position.X < x.Item1.X + x.Item2.Width && position.Z + item.Depth > x.Item1.Z).Any();
     }
 
@@ -315,5 +346,5 @@
 
     #region Get items
-    
+
     private IEnumerable<Tuple<PackingPosition, PackingItem>> GetItemsBelow(PackingPosition pos) {
       var line = new Line3D(pos, new Vector3D(0, 1, 0));
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Evaluators/BinUtilizationEvaluator.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Evaluators/BinUtilizationEvaluator.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Evaluators/BinUtilizationEvaluator.cs	(revision 15646)
@@ -67,4 +67,45 @@
     }
 
+    private static int GetBinCount(Solution solution) {
+      return solution.NrOfBins;
+    }
+
+    private static int GetNumberOfResidualSpaces(Solution solution) {
+      var cnt = 0;
+      foreach (var binPacking in solution.Bins) {
+        foreach (var item in ((BinPacking3D)binPacking).ExtremePoints) {
+          cnt += item.Value.Count();
+        }
+      }
+      return cnt;
+    }
+
+    public Tuple<int, double, int> Evaluate1(Solution solution) {
+
+
+      var res = Tuple.Create<int, double, int>(
+        GetBinCount(solution),
+        CalculateBinUtilizationFirstBin(solution),
+        GetNumberOfResidualSpaces(solution)
+        );
+
+      return res;
+    }
+
+    private static double CalculateBinUtilizationFirstBin(Solution solution) {
+      if (solution.NrOfBins <= 0) {
+        return 0.0;
+      }
+
+      double totalUsedSpace = 0;
+      double totalUsableSpace = 0;
+
+      totalUsableSpace += solution.Bins[0].BinShape.Volume;
+      totalUsedSpace += solution.Bins[0].Items.Sum(kvp => kvp.Value.Volume);
+
+      return totalUsedSpace / totalUsableSpace;
+    }
+
+
     #endregion
   }
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Evaluators/IEvaluator.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Evaluators/IEvaluator.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Evaluators/IEvaluator.cs	(revision 15646)
@@ -21,4 +21,5 @@
 
 using HeuristicLab.Core;
+using System;
 
 namespace HeuristicLab.Problems.BinPacking3D {
@@ -34,4 +35,11 @@
     /// <returns>Returns the value of the evaluated solution depending on the implementation</returns>
     double Evaluate(Solution solution);
+
+    /// <summary>
+    /// Returns a tuple of (number of bins, bin utilization, number of residual spaces)
+    /// </summary>
+    /// <param name="solution"></param>
+    /// <returns></returns>
+    Tuple<int, double, int> Evaluate1(Solution solution);
   }
 }
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Evaluators/PackingRatioEvaluator.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Evaluators/PackingRatioEvaluator.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Evaluators/PackingRatioEvaluator.cs	(revision 15646)
@@ -84,4 +84,44 @@
     }
 
+    private static int GetBinCount(Solution solution) {
+      return solution.NrOfBins;
+    }
+
+    private static int GetNumberOfResidualSpaces(Solution solution) {
+      var cnt = 0;
+      foreach (var binPacking in solution.Bins) {
+        foreach (var item in ((BinPacking3D)binPacking).ExtremePoints) {
+          cnt += item.Value.Count();
+        }
+      }
+      return cnt;
+    }
+
+    public Tuple<int, double, int> Evaluate1(Solution solution) {
+
+
+      var res = Tuple.Create<int, double, int>(
+        GetBinCount(solution),
+        CalculateBinUtilizationFirstBin(solution),
+        GetNumberOfResidualSpaces(solution)
+        );
+
+      return res;
+    }
+
+    private static double CalculateBinUtilizationFirstBin(Solution solution) {
+      if (solution.NrOfBins <= 0) {
+        return 0.0;
+      }
+
+      double totalUsedSpace = 0;
+      double totalUsableSpace = 0;
+
+      totalUsableSpace += solution.Bins[0].BinShape.Volume;
+      totalUsedSpace += solution.Bins[0].Items.Sum(kvp => kvp.Value.Volume);
+
+      return totalUsedSpace / totalUsableSpace;
+    }
+
     #endregion
   }
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/ExtremePointCreation/LineProjectionBasedEPCreator.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/ExtremePointCreation/LineProjectionBasedEPCreator.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/ExtremePointCreation/LineProjectionBasedEPCreator.cs	(revision 15646)
@@ -166,5 +166,5 @@
     protected override void GenerateNewExtremePointsForItem(BinPacking3D binPacking, PackingItem newItem, PackingPosition position) {
       PointProjectionForNewItem(binPacking, newItem, position);
-      EdgeProjectionForNewItem(binPacking, newItem, position);
+      //EdgeProjectionForNewItem(binPacking, newItem, position);
     }
 
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Instances/ThreeDInstanceParser.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Instances/ThreeDInstanceParser.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Instances/ThreeDInstanceParser.cs	(revision 15646)
@@ -58,5 +58,6 @@
               PackingItem item = new PackingItem(width, height, length, Bin, weight, material) {
                 RotateEnabled = rotate == 0 ? false : true,
-                TiltEnabled = tilt == 0 ? false : true
+                TiltEnabled = tilt == 0 ? false : true,
+                IsStackabel = stack == 0 ? false : true
               };
               Items.Add(item);
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Material/FrictionalCoefficientTable.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Material/FrictionalCoefficientTable.cs	(revision 15646)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Material/FrictionalCoefficientTable.cs	(revision 15646)
@@ -0,0 +1,30 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HeuristicLab.Problems.BinPacking3D.Material {
+  public class FrictionalCoefficientTable {
+    private FrictionalCoefficientTable _instance;
+
+    //private MaterialType 
+
+    private FrictionalCoefficientTable() {
+
+    }
+
+    public FrictionalCoefficientTable Instance {
+      get {
+        if (_instance == null) {
+          _instance = new FrictionalCoefficientTable();
+        }
+        return _instance;
+      }
+    }
+
+
+
+
+  }
+}
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Material/MaterialType.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Material/MaterialType.cs	(revision 15646)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Material/MaterialType.cs	(revision 15646)
@@ -0,0 +1,13 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HeuristicLab.Problems.BinPacking3D.Material {
+  public enum MaterialType {
+    Wooden,
+    Steel,
+    Paperboard
+  }
+}
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Packer/BinPackerMinRSLeft.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Packer/BinPackerMinRSLeft.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Packer/BinPackerMinRSLeft.cs	(revision 15646)
@@ -45,6 +45,12 @@
     #endregion
 
+
+
     public BinPackerMinRSLeft() : base() { }
 
+    /// <summary>
+    /// This proportion of the residual space left to the item height is used for deciding if a not stackable item should be placed.
+    /// </summary>
+    private const double NOT_STACKABLE_RS_LEFT_TO_ITEM_HEIGHT_PROPORTION = 1.1;
 
     public override IList<BinPacking3D> PackItems(Permutation sortedItems, PackingShape binShape, IList<PackingItem> items, ExtremePointCreationMethod epCreationMethod, ExtremePointPruningMethod epPruningMethod, bool useStackingConstraints) {
@@ -57,10 +63,11 @@
           BinPacking3D packingBin = new BinPacking3D(binShape);
           PackRemainingItems(ref remainingIds, ref packingBin, workingItems, epCreationMethod, useStackingConstraints);
-          packingList.Add(packingBin);
-        }
-      } catch(BinPacking3DException e) {
-      }
-      
+          packingList.Add(packingBin);          
+        }
+      } catch (BinPacking3DException e) {
+      }
+
       ExtremePointPruningFactory.CreatePruning().PruneExtremePoints(epPruningMethod, packingList);
+
       return packingList;
     }
@@ -76,16 +83,70 @@
     protected void PackRemainingItems(ref IList<int> remainingIds, ref BinPacking3D packingBin, IList<PackingItem> items, ExtremePointCreationMethod epCreationMethod, bool useStackingConstraints) {
       IExtremePointCreator extremePointCreator = ExtremePointCreatorFactory.CreateExtremePointCreator(epCreationMethod, useStackingConstraints);
+      var remainingNotStackableItems = new List<int>();
       foreach (var itemId in new List<int>(remainingIds)) {
         var item = items[itemId];
-        PackingPosition position = FindPackingPositionForItem(packingBin, item, useStackingConstraints);
-        // if a valid packing position could be found, the current item can be added to the given bin
-        if (position != null) {
-          PackItem(packingBin, itemId, item, position, extremePointCreator, useStackingConstraints);
-          remainingIds.Remove(itemId);
-        }
-      }
-    }
-
-    
+
+        // If an item is not stackable it should have a minimum waste of the residual space.
+        // As long as there are stackable items left, put the non stackable items into a collection 
+        // and try to find positions where they don't waste too much space.
+        // If there are no stackable items left the non stackable have to be treated as a stackable one.
+        if (!item.IsStackabel && useStackingConstraints && remainingIds.Where(x => items[x].IsStackabel).Any()) {
+          remainingNotStackableItems.Add(itemId);          
+        } else {
+          PackingPosition position = FindPackingPositionForItem(packingBin, item, useStackingConstraints);
+          // if a valid packing position could be found, the current item can be added to the given bin
+          if (position != null) {            
+            PackItem(packingBin, itemId, item, position, extremePointCreator, useStackingConstraints);
+            remainingIds.Remove(itemId);
+          }
+        }
+
+        // try to find a valid position for a non stackable item
+        var stackableLeft = remainingIds.Where(x => items[x].IsStackabel).Any();
+        foreach (var saId in new List<int>(remainingNotStackableItems)) {
+          item = items[saId];
+          PackingPosition position = null;
+          if (stackableLeft) {
+            position  = FindPackingPositionForNotStackableItem(packingBin, item, useStackingConstraints);
+          } else {
+            position = FindPackingPositionForItem(packingBin, item, useStackingConstraints);
+          }
+          
+          if (position != null) {            
+            PackItem(packingBin, saId, item, position, extremePointCreator, useStackingConstraints);
+            remainingIds.Remove(saId);
+            remainingNotStackableItems.Remove(saId);
+          }
+        }
+        
+      }
+    }
+
+    /// <summary>
+    /// Tries to find a valid position for a non stackable item.
+    /// Positions will only be valid if the height difference of its residual space is smaller then the hight of the item.
+    /// </summary>
+    /// <param name="packingBin"></param>
+    /// <param name="packingItem"></param>
+    /// <param name="useStackingConstraints"></param>
+    /// <returns></returns>
+    private PackingPosition FindPackingPositionForNotStackableItem(BinPacking3D packingBin, PackingItem packingItem, bool useStackingConstraints) {
+      if (!CheckItemDimensions(packingBin, packingItem)) {
+        throw new BinPacking3DException($"The dimensions of the given item exceeds the bin dimensions. " +
+          $"Bin: ({packingBin.BinShape.Width} {packingBin.BinShape.Depth} {packingBin.BinShape.Height})" +
+          $"Item: ({packingItem.Width} {packingItem.Depth} {packingItem.Height})");
+      }
+      var rsds = CalculateResidalSpaceDifferences(packingBin, packingItem, useStackingConstraints).ToList();
+      var rsd = rsds.Where(x => x != null && (x.Y / (double)x.Item.Height) < NOT_STACKABLE_RS_LEFT_TO_ITEM_HEIGHT_PROPORTION).OrderByDescending(x => x.Y % x.Item.Height).FirstOrDefault();
+
+      if (rsd == null) {
+        return null;
+      }
+
+      packingItem.Rotated = rsd.Item.Rotated;
+      packingItem.Tilted = rsd.Item.Tilted;
+      return rsd.Position;
+    }
+
     protected override PackingPosition FindPackingPositionForItem(BinPacking3D packingBin, PackingItem packingItem, bool useStackingConstraints) {
       if (!CheckItemDimensions(packingBin, packingItem)) {
@@ -95,20 +156,6 @@
       }
 
-      var rsds = new SortedSet<ResidualSpaceDifference>();
-
-      rsds.Add(FindResidualSpaceDifferenceForItem(packingBin, packingItem, useStackingConstraints, rotated: false, tilted: false));
-
-      if (packingItem.TiltEnabled) {
-        rsds.Add(FindResidualSpaceDifferenceForItem(packingBin, packingItem, useStackingConstraints, rotated: false, tilted: true));
-      }
-      if (packingItem.RotateEnabled) {
-        rsds.Add(FindResidualSpaceDifferenceForItem(packingBin, packingItem, useStackingConstraints, rotated: true, tilted: false));
-      }
-      if (packingItem.RotateEnabled && packingItem.TiltEnabled) {
-        rsds.Add(FindResidualSpaceDifferenceForItem(packingBin, packingItem, useStackingConstraints, rotated: true, tilted: true));
-      }
-
-      var rsd = rsds.Where(x => x != null).FirstOrDefault();
-      
+      var rsd = CalculateResidalSpaceDifferences(packingBin, packingItem, useStackingConstraints).Where(x => x != null).FirstOrDefault();
+
       if (rsd == null) {
         return null;
@@ -120,4 +167,37 @@
     }
 
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="packingBin"></param>
+    /// <param name="packingItem"></param>
+    /// <param name="useStackingConstraints"></param>
+    /// <returns></returns>
+    private SortedSet<ResidualSpaceDifference> CalculateResidalSpaceDifferences(BinPacking3D packingBin, PackingItem packingItem, bool useStackingConstraints) {
+      var rsds = new SortedSet<ResidualSpaceDifference>();
+
+      rsds.Add(FindResidualSpaceDifferenceForItem(packingBin, packingItem, useStackingConstraints, rotated: false, tilted: false));
+
+      if (packingItem.TiltEnabled) {
+        rsds.Add(FindResidualSpaceDifferenceForItem(packingBin, packingItem, useStackingConstraints, rotated: false, tilted: true));
+      }
+      if (packingItem.RotateEnabled) {
+        rsds.Add(FindResidualSpaceDifferenceForItem(packingBin, packingItem, useStackingConstraints, rotated: true, tilted: false));
+      }
+      if (packingItem.RotateEnabled && packingItem.TiltEnabled) {
+        rsds.Add(FindResidualSpaceDifferenceForItem(packingBin, packingItem, useStackingConstraints, rotated: true, tilted: true));
+      }
+      return rsds;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="packingBin"></param>
+    /// <param name="packingItem"></param>
+    /// <param name="useStackingConstraints"></param>
+    /// <param name="rotated"></param>
+    /// <param name="tilted"></param>
+    /// <returns></returns>
     protected ResidualSpaceDifference FindResidualSpaceDifferenceForItem(BinPacking3D packingBin, PackingItem packingItem, bool useStackingConstraints, bool rotated, bool tilted) {
       PackingItem newItem = new PackingItem(packingItem) {
@@ -125,21 +205,18 @@
         Tilted = tilted
       };
-
+      
       var rsds = new SortedSet<ResidualSpaceDifference>();
-
       foreach (var ep in packingBin.ExtremePoints) {
         var position = ep.Key;
-        if (packingBin.IsPositionFeasible(newItem, position, useStackingConstraints)) {
-          foreach (var rs in ep.Value) {
-            var rsd = ResidualSpaceDifference.Create(position, newItem, rs);
-            if (rsd != null) {
-              rsds.Add(rsd);
-            }
+        foreach (var rs in ep.Value) {
+          var rsd = ResidualSpaceDifference.Create(position, newItem, rs);
+          if (rsd != null) {
+            rsds.Add(rsd);
           }
         }
       }
-      return rsds.FirstOrDefault();
-    }
-
+      return rsds.Where(rsd => packingBin.IsPositionFeasible(rsd.Item, rsd.Position, useStackingConstraints)).FirstOrDefault();
+    }
+        
     protected override bool CheckItemDimensions(BinPacking3D packingBin, PackingItem item) {
       bool ok = false;
@@ -167,5 +244,5 @@
         OriginalWidth = width,
         OriginalHeight = height,
-        OriginalDepth =  depth
+        OriginalDepth = depth
       });
     }
@@ -212,5 +289,5 @@
         if (x != 0) {
           return x;
-        } else if (y != 0 ) {
+        } else if (y != 0) {
           return y;
         } else if (z != 0) {
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/PackingItem.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/PackingItem.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/PackingItem.cs	(revision 15646)
@@ -43,5 +43,5 @@
       get { return (IFixedValueParameter<IntValue>)Parameters["Material"]; }
     }
-    
+
     public PackingShape TargetBin {
       get { return TargetBinParameter.Value; }
@@ -60,4 +60,24 @@
 
 
+    public IFixedValueParameter<DoubleValue> SupportedWeightParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters["SupportedWeight"]; }
+    }
+    public double SupportedWeight {
+      get { return SupportedWeightParameter.Value.Value; }
+      set { SupportedWeightParameter.Value.Value = value; }
+    }
+
+    public IValueParameter<BoolValue> IsStackableParameter {
+      get { return (IValueParameter<BoolValue>)Parameters["IsStackable"]; }
+    }
+
+    /// <summary>
+    /// Indicates that another item can be stacked on the current one.
+    /// </summary>
+    public bool IsStackabel {
+      get { return IsStackableParameter.Value.Value; }
+      set { IsStackableParameter.Value.Value = value; }
+    }
+
     public IValueParameter<BoolValue> RotateEnabledParameter {
       get { return (IValueParameter<BoolValue>)Parameters["RotateEnabled"]; }
@@ -75,5 +95,5 @@
       get { return (IValueParameter<BoolValue>)Parameters["Tilted"]; }
     }
-    
+
     /// <summary>
     /// Enables that the current item can be rotated.
@@ -110,9 +130,9 @@
       set { TiltedParameter.Value.Value = value; }
     }
-    
+
     public IFixedValueParameter<IntValue> LoadSecuringHeightParameter {
       get { return (IFixedValueParameter<IntValue>)Parameters["LoadSecuringHeight"]; }
     }
-    
+
     public IFixedValueParameter<IntValue> LoadSecuringWidthParameter {
       get { return (IFixedValueParameter<IntValue>)Parameters["LoadSecuringWidth"]; }
@@ -195,5 +215,5 @@
           return WidthParameter.Value.Value;
         }
-      } 
+      }
     }
 
@@ -255,5 +275,5 @@
       set { DepthParameter.Value.Value = value; }
     }
-    
+
     public bool SupportsStacking(IPackingItem other) {
       return ((other.Material < this.Material) || (other.Material.Equals(this.Material) && other.Weight <= this.Weight));
@@ -273,12 +293,18 @@
       Parameters.Add(new FixedValueParameter<DoubleValue>("Weight"));
       Parameters.Add(new FixedValueParameter<IntValue>("Material"));
+
+      Parameters.Add(new FixedValueParameter<DoubleValue>("SupportedWeight"));      
+
       Parameters.Add(new FixedValueParameter<BoolValue>("RotateEnabled"));
       Parameters.Add(new FixedValueParameter<BoolValue>("Rotated"));
       Parameters.Add(new FixedValueParameter<BoolValue>("TiltEnabled"));
       Parameters.Add(new FixedValueParameter<BoolValue>("Tilted"));
-      
+      Parameters.Add(new FixedValueParameter<BoolValue>("IsStackable"));
+
       Parameters.Add(new FixedValueParameter<IntValue>("LoadSecuringHeight"));
       Parameters.Add(new FixedValueParameter<IntValue>("LoadSecuringWidth"));
       Parameters.Add(new FixedValueParameter<IntValue>("LoadSecuringDepth"));
+
+      IsStackabel = true;
 
       RegisterEvents();
@@ -294,16 +320,15 @@
 
     public PackingItem(int width, int height, int depth, PackingShape targetBin, double weight, int material)
-      : this(width, height, depth, targetBin) {    
+      : this(width, height, depth, targetBin) {
       this.Weight = weight;
       this.Material = material;
     }
 
-    
-
-    public PackingItem(PackingItem packingItem) 
-      : this() {
+
+
+    public PackingItem(PackingItem packingItem) : this() {
       OriginalWidth = packingItem.OriginalWidth;
       OriginalHeight = packingItem.OriginalHeight;
-      OriginalDepth =  packingItem.OriginalDepth;
+      OriginalDepth = packingItem.OriginalDepth;
       TargetBin = (PackingShape)packingItem.TargetBin.Clone();
       Weight = packingItem.Weight;
@@ -311,4 +336,5 @@
       Rotated = packingItem.Rotated;
       Tilted = packingItem.Tilted;
+      IsStackabel = packingItem.IsStackabel;
 
       LoadSecuringDepth = packingItem.LoadSecuringDepth;
@@ -337,5 +363,5 @@
       return string.Format("CuboidPackingItem ({0}, {1}, {2}; weight={3}, mat={4})", this.Width, this.Height, this.Depth, this.Weight, this.Material);
     }
-    
+
   }
 }
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Solution.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Solution.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Solution.cs	(revision 15646)
@@ -24,4 +24,5 @@
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.BinPacking;
+using System;
 
 namespace HeuristicLab.Problems.BinPacking3D {
@@ -39,4 +40,36 @@
       return new Solution(this, cloner);
     }
+
+    public bool IsBetterThan(Solution other, IEvaluator evaluator, bool problemMaximization = true) {
+      var evaluatedThis = evaluator.Evaluate1(this);
+
+      if (double.IsInfinity(evaluatedThis.Item2) || double.IsNaN(evaluatedThis.Item2)) {
+        return false;
+      }
+
+      if (other == null) {
+        return true;
+      }
+
+      var evaluatedOther = evaluator.Evaluate1(other);
+      if (evaluatedThis.Item1 < evaluatedOther.Item1) {
+        return true;
+      } else if (evaluatedThis.Item1 > evaluatedOther.Item1) {
+        return false;
+      }
+      
+      if (evaluatedThis.Item2 > evaluatedOther.Item2) {
+        return true;
+      }
+      if (evaluatedThis.Item2 < evaluatedOther.Item2) {
+        return false;
+      }
+
+      if (evaluatedThis.Item3 > evaluatedOther.Item3) {
+        return false;
+      }
+      return true;
+
+    }
   }
 }
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Sorting/IPackingItemClusteredSorter.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Sorting/IPackingItemClusteredSorter.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Sorting/IPackingItemClusteredSorter.cs	(revision 15646)
@@ -32,4 +32,5 @@
 
     Permutation SortPackingItemsByMaterial(IList<PackingItem> items, PackingShape bin, double delta);
+    
   }
 }
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Sorting/PackingItemAreaHeightSorter.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Sorting/PackingItemAreaHeightSorter.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Sorting/PackingItemAreaHeightSorter.cs	(revision 15646)
@@ -36,5 +36,5 @@
     public Permutation SortPackingItemsByMaterial(IList<PackingItem> items, PackingShape bin) {
       return items.SortByMaterialAreaHeight();
-    }
+    }    
   }
 }
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Sorting/PackingItemHeightVolumeSorter.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Sorting/PackingItemHeightVolumeSorter.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Sorting/PackingItemHeightVolumeSorter.cs	(revision 15646)
@@ -36,5 +36,5 @@
     public Permutation SortPackingItemsByMaterial(IList<PackingItem> items, PackingShape bin) {
       return items.SortByMaterialHeightVolume();
-    }
+    }    
   }
 }
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Sorting/PermutationPackingItemSorter.cs
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Sorting/PermutationPackingItemSorter.cs	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/Sorting/PermutationPackingItemSorter.cs	(revision 15646)
@@ -136,5 +136,6 @@
       return new Permutation(PermutationTypes.Absolute,
                     items.Select((v, i) => new { Index = i, Item = v })
-                         .OrderByDescending(x => x.Item.Material)
+                         ./*OrderByDescending(x => x.Item.IsStackabel ? 1 : 0)
+                         .*/OrderByDescending(x => x.Item.Material)
                          .ThenByDescending(x => x.Item.Depth * x.Item.Width * x.Item.Height)
                          .ThenByDescending(x => x.Item.Height)
@@ -150,5 +151,6 @@
       return new Permutation(PermutationTypes.Absolute,
                     items.Select((v, i) => new { Index = i, Item = v })
-                         .OrderByDescending(x => x.Item.Material)
+                         ./*OrderByDescending(x => x.Item.IsStackabel ? 1 : 0)
+                         .*/OrderByDescending(x => x.Item.Material)
                          .ThenByDescending(x => x.Item.Height)
                          .ThenByDescending(x => x.Item.Depth * x.Item.Width * x.Item.Height)
@@ -164,5 +166,6 @@
       return new Permutation(PermutationTypes.Absolute,
                     items.Select((v, i) => new { Index = i, Item = v })
-                         .OrderByDescending(x => x.Item.Material)
+                         ./*OrderByDescending(x => x.Item.IsStackabel ? 1 : 0)
+                         .*/OrderByDescending(x => x.Item.Material)
                          .ThenByDescending(x => x.Item.Depth * x.Item.Width)
                          .ThenByDescending(x => x.Item.Height)
@@ -178,5 +181,6 @@
       return new Permutation(PermutationTypes.Absolute,
                     items.Select((v, i) => new { Index = i, Item = v })
-                         .OrderByDescending(x => x.Item.Material)
+                         ./*OrderByDescending(x => x.Item.IsStackabel ? 1 : 0)
+                         .*/OrderByDescending(x => x.Item.Material)
                          .ThenByDescending(x => x.Item.Height)
                          .ThenByDescending(x => x.Item.Depth * x.Item.Width)
Index: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/HeuristicLab.Problems.BinPacking-3.3.csproj
===================================================================
--- branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/HeuristicLab.Problems.BinPacking-3.3.csproj	(revision 15618)
+++ branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/HeuristicLab.Problems.BinPacking-3.3.csproj	(revision 15646)
@@ -113,4 +113,6 @@
     <Compile Include="3D\ExtremePointPruning\IExtremePointPruning.cs" />
     <Compile Include="3D\Geometry\Edge3D.cs" />
+    <Compile Include="3D\Material\FrictionalCoefficientTable.cs" />
+    <Compile Include="3D\Material\MaterialType.cs" />
     <Compile Include="3D\Packer\BinPacker.cs" />
     <Compile Include="3D\Packer\BinPackerFactory.cs" />
