Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Common/3.3/ExtensionMethods.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Common/3.3/ExtensionMethods.cs	(revision 7592)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Common/3.3/ExtensionMethods.cs	(revision 7593)
@@ -220,5 +220,5 @@
 
     /// <summary>
-    /// Selects the first element in the sequence where the selected key is the maximum.
+    /// Selects the first element in the sequence that is maximal with respect to the given key.
     /// </summary>
     /// <remarks>
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.cs	(revision 7592)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.cs	(revision 7593)
@@ -67,4 +67,6 @@
       UpdateOverbookedCapacity();
       UpdateAssignment();
+      if (Content != null) assignmentView.Content = Content.Assignment;
+      else assignmentView.Content = null;
     }
 
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Evaluators/GQAPEvaluator.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Evaluators/GQAPEvaluator.cs	(revision 7592)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Evaluators/GQAPEvaluator.cs	(revision 7593)
@@ -132,5 +132,9 @@
         slack[assignment[i]] -= demands[i];
       }
-      overbookedCapacity = slack.Select((v, i) => new { V = v, Index = i }).Where(x => x.V < 0.0).Select(x => -x.V / capacities[x.Index]).Sum();
+      overbookedCapacity = EvaluateOverbooking(slack, capacities);
+    }
+
+    public static double EvaluateOverbooking(DoubleArray slack, DoubleArray capacities) {
+      return slack.Select((v, i) => new { V = v, Index = i }).Where(x => x.V < 0.0).Select(x => -x.V / capacities[x.Index]).Sum();
     }
 
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj	(revision 7592)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj	(revision 7593)
@@ -104,4 +104,6 @@
     <Compile Include="GQAPAssignment.cs" />
     <Compile Include="Operators\Crossovers\CordeauCrossover.cs" />
+    <Compile Include="SolutionCreators\SlackMinimizationSolutionCreator.cs" />
+    <Compile Include="SolutionCreators\RandomButFeasibleSolutionCreator.cs" />
     <Compile Include="SolutionCreators\GQAPSolutionCreator.cs" />
     <Compile Include="SolutionCreators\GQAPStochasticSolutionCreator.cs" />
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GreedyRandomizedSolutionCreator.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GreedyRandomizedSolutionCreator.cs	(revision 7592)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GreedyRandomizedSolutionCreator.cs	(revision 7593)
@@ -23,4 +23,5 @@
 using System.Collections.Generic;
 using System.Linq;
+using System.Threading;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -39,4 +40,7 @@
       get { return (IValueLookupParameter<IntValue>)Parameters["MaximumTries"]; }
     }
+    public IValueLookupParameter<BoolValue> CreateMostFeasibleSolutionParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["CreateMostFeasibleSolution"]; }
+    }
 
     [StorableConstructor]
@@ -46,5 +50,6 @@
     public GreedyRandomizedSolutionCreator()
       : base() {
-      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumTries", "The maximum number of tries to create a feasible solution.", new IntValue(10000)));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumTries", "The maximum number of tries to create a feasible solution after which an exception is thrown. If it is set to 0 or a negative value there will be an infinite number of attempts.", new IntValue(100000)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("CreateMostFeasibleSolution", "If this is set to true the operator will always succeed, and outputs the solution with the least violation instead of throwing an exception.", new BoolValue(false)));
     }
 
@@ -53,17 +58,26 @@
     }
 
-    protected override IntegerVector CreateRandomSolution(IRandom random, DoubleArray demands, DoubleArray capacities) {
-      int tries = 0, maxTries = MaximumTriesParameter.ActualValue.Value;
-      var assignment = new Dictionary<int, int>();
-      var slack = new Dictionary<int, double>();
-
-      while (tries < maxTries) {
-        assignment.Clear();
-        slack = capacities.Select((v, i) => new { Index = i, Value = v }).ToDictionary(x => x.Index, y => y.Value);
-        HashSet<int> CF = new HashSet<int>(), // set of chosen facilities / equipments
+    public static IntegerVector CreateSolution(IRandom random, DoubleArray demands, DoubleArray capacities, int maximumTries, bool createMostFeasibleSolution, CancellationToken cancelToken) {
+      int tries = 0;
+      var assignment = new Dictionary<int, int>(demands.Length);
+      DoubleArray slack = new DoubleArray(capacities.Length);
+      double minViolation = double.MaxValue;
+      Dictionary<int, int> bestAssignment = null;
+      HashSet<int> CF = new HashSet<int>(), // set of chosen facilities / equipments
           T = new HashSet<int>(), // set of facilities / equpiments that can be assigned to the set of chosen locations (CL)
           CL = new HashSet<int>(), // set of chosen locations
           F = new HashSet<int>(Enumerable.Range(0, demands.Length)), // set of (initially) all facilities / equipments
           L = new HashSet<int>(Enumerable.Range(0, capacities.Length)); // set of (initially) all locations
+
+      while (maximumTries <= 0 || tries < maximumTries) {
+        cancelToken.ThrowIfCancellationRequested();
+
+        assignment.Clear();
+        for (int i = 0; i < capacities.Length; i++) slack[i] = capacities[i];
+        CF.Clear();
+        T.Clear();
+        CL.Clear();
+        F.Clear(); F.UnionWith(Enumerable.Range(0, demands.Length));
+        L.Clear(); L.UnionWith(Enumerable.Range(0, capacities.Length));
 
         double threshold = 1.0;
@@ -87,11 +101,36 @@
           }
         } while (T.Any() || L.Any());
-        tries++;
-        if (!F.Any()) break;
+        if (maximumTries > 0) tries++;
+        if (!F.Any()) {
+          bestAssignment = assignment;
+          break;
+        } else if (createMostFeasibleSolution) {
+          // complete the solution and remember the one with least violation
+          while (F.Any()) {
+            var f = F.ChooseMax(x => demands[x]);
+            var l = L.ChooseMax(x => slack[x]);
+            F.Remove(f);
+            assignment.Add(f, l);
+            slack[l] -= demands[f];
+          }
+          double violation = GQAPEvaluator.EvaluateOverbooking(slack, capacities);
+          if (violation < minViolation) {
+            bestAssignment = assignment;
+            assignment = new Dictionary<int, int>(demands.Length);
+            minViolation = violation;
+          }
+        }
       }
 
-      if (assignment.Count != demands.Length) throw new InvalidOperationException(String.Format("No solution could be found in {0} tries.", maxTries));
+      if (bestAssignment == null || bestAssignment.Count != demands.Length) throw new InvalidOperationException(String.Format("No solution could be found in {0} tries.", maximumTries));
 
-      return new IntegerVector(assignment.OrderBy(x => x.Key).Select(x => x.Value).ToArray());
+      return new IntegerVector(bestAssignment.OrderBy(x => x.Key).Select(x => x.Value).ToArray());
+    }
+
+    protected override IntegerVector CreateRandomSolution(IRandom random, DoubleArray demands, DoubleArray capacities) {
+      return CreateSolution(random, demands, capacities,
+        MaximumTriesParameter.ActualValue.Value,
+        CreateMostFeasibleSolutionParameter.ActualValue.Value,
+        CancellationToken);
     }
 
@@ -102,9 +141,9 @@
     }
 
-    private static double GetMaximumSlack(Dictionary<int, double> slack, HashSet<int> CL) {
-      return slack.Where(x => CL.Contains(x.Key)).Select(x => x.Value).Max();
+    private static double GetMaximumSlack(DoubleArray slack, HashSet<int> CL) {
+      return slack.Select((val, idx) => new { idx, val }).Where(x => CL.Contains(x.idx)).Select(x => x.val).Max();
     }
 
-    private static IEnumerable<int> WithSlackGreaterOrEqual(HashSet<int> locations, double minimum, Dictionary<int, double> slack) {
+    private static IEnumerable<int> WithSlackGreaterOrEqual(HashSet<int> locations, double minimum, DoubleArray slack) {
       foreach (int l in locations) {
         if (slack[l] >= minimum) yield return l;
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/RandomButFeasibleSolutionCreator.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/RandomButFeasibleSolutionCreator.cs	(revision 7593)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/RandomButFeasibleSolutionCreator.cs	(revision 7593)
@@ -0,0 +1,112 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.GeneralizedQuadraticAssignment.Common;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("RandomButFeasibleSolutionCreator", "Creates a random, but feasible solution to the Generalized Quadratic Assignment Problem.")]
+  [StorableClass]
+  public class RandomFeasibleSolutionCreator : GQAPStochasticSolutionCreator {
+
+    public IValueLookupParameter<IntValue> MaximumTriesParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumTries"]; }
+    }
+    public IValueLookupParameter<BoolValue> CreateMostFeasibleSolutionParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["CreateMostFeasibleSolution"]; }
+    }
+
+    [StorableConstructor]
+    protected RandomFeasibleSolutionCreator(bool deserializing) : base(deserializing) { }
+    protected RandomFeasibleSolutionCreator(RandomFeasibleSolutionCreator original, Cloner cloner) : base(original, cloner) { }
+    public RandomFeasibleSolutionCreator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumTries", "The maximum number of tries to create a feasible solution after which an exception is thrown. If it is set to 0 or a negative value there will be an infinite number of attempts.", new IntValue(100000)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("CreateMostFeasibleSolution", "If this is set to true the operator will always succeed, and outputs the solution with the least violation instead of throwing an exception.", new BoolValue(false)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RandomFeasibleSolutionCreator(this, cloner);
+    }
+
+    public static IntegerVector CreateSolution(IRandom random, DoubleArray demands, DoubleArray capacities, int maximumTries, bool createMostFeasibleSolution, CancellationToken cancel) {
+      IntegerVector result = null;
+      bool isFeasible = false;
+      int counter = 0;
+      double minViolation = double.MaxValue;
+      var slack = new DoubleArray(capacities.Length);
+      var assignment = new IntegerVector(demands.Length);
+
+      while (!isFeasible) {
+        cancel.ThrowIfCancellationRequested();
+        if (maximumTries > 0) {
+          counter++;
+          if (counter > maximumTries) {
+            if (createMostFeasibleSolution) break;
+            else throw new InvalidOperationException("A feasible solution could not be obtained after " + maximumTries + " attempts.");
+          }
+        }
+        for (int i = 0; i < capacities.Length; i++) slack[i] = capacities[i];
+        foreach (var equipment in Enumerable.Range(0, demands.Length).Shuffle(random)) {
+          var freeLocations = GetFreeLocations(equipment, demands, slack);
+          assignment[equipment] = freeLocations.ChooseUniformRandom(random);
+          slack[assignment[equipment]] -= demands[equipment];
+        }
+        double violation = GQAPEvaluator.EvaluateOverbooking(slack, capacities);
+        isFeasible = violation == 0;
+        if (isFeasible || violation < minViolation) {
+          result = (IntegerVector)assignment.Clone();
+          minViolation = violation;
+        }
+      }
+      return result;
+    }
+
+    protected override IntegerVector CreateRandomSolution(IRandom random, DoubleArray demands, DoubleArray capacities) {
+      return CreateSolution(random, demands, capacities,
+        MaximumTriesParameter.ActualValue.Value,
+        CreateMostFeasibleSolutionParameter.ActualValue.Value,
+        CancellationToken);
+    }
+
+    private static IEnumerable<int> GetFreeLocations(int equipment, DoubleArray demands, DoubleArray freeCapacities) {
+      var freeLocations = freeCapacities
+        .Select((v, idx) => new KeyValuePair<int, double>(idx, v))
+        .Where(x => x.Value >= demands[equipment]);
+      if (!freeLocations.Any()) {
+        freeLocations = freeCapacities
+          .Select((v, idx) => new KeyValuePair<int, double>(idx, v))
+          .OrderByDescending(x => x.Value)
+          .Take(3); // if there are none, take the three where the free capacity is largest
+      }
+      return freeLocations.Select(x => x.Key);
+    }
+  }
+}
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/RandomSolutionCreator.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/RandomSolutionCreator.cs	(revision 7592)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/RandomSolutionCreator.cs	(revision 7593)
@@ -40,6 +40,10 @@
     }
 
+    public static IntegerVector CreateSolution(IRandom random, DoubleArray demands, DoubleArray capacities) {
+      return UniformRandomIntegerVectorCreator.Apply(random, demands.Length, 0, capacities.Length);
+    }
+
     protected override IntegerVector CreateRandomSolution(IRandom random, DoubleArray demands, DoubleArray capacities) {
-      return UniformRandomIntegerVectorCreator.Apply(random, demands.Length, 0, capacities.Length);
+      return CreateSolution(random, demands, capacities);
     }
   }
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/SlackMinimizationSolutionCreator.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/SlackMinimizationSolutionCreator.cs	(revision 7593)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/SlackMinimizationSolutionCreator.cs	(revision 7593)
@@ -0,0 +1,184 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.GeneralizedQuadraticAssignment.Common;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("SlackMinimizationSolutionCreator", "A heuristic that creates a solution to the Generalized Quadratic Assignment Problem by minimizing the amount of slack.")]
+  [StorableClass]
+  public class SlackMinimizationSolutionCreator : GQAPStochasticSolutionCreator {
+
+    public IValueLookupParameter<IntValue> MaximumTriesParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumTries"]; }
+    }
+    public IValueLookupParameter<BoolValue> CreateMostFeasibleSolutionParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["CreateMostFeasibleSolution"]; }
+    }
+    public IValueLookupParameter<IntValue> DepthParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["Depth"]; }
+    }
+
+    [StorableConstructor]
+    protected SlackMinimizationSolutionCreator(bool deserializing) : base(deserializing) { }
+    protected SlackMinimizationSolutionCreator(SlackMinimizationSolutionCreator original, Cloner cloner) : base(original, cloner) { }
+    public SlackMinimizationSolutionCreator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumTries", "The maximum number of tries to create a feasible solution after which an exception is thrown. If it is set to 0 or a negative value there will be an infinite number of attempts to create a feasible solution.", new IntValue(100000)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("CreateMostFeasibleSolution", "If this is set to true the operator will always succeed, and outputs the solution with the least violation instead of throwing an exception.", new BoolValue(false)));
+      Parameters.Add(new ValueLookupParameter<IntValue>("Depth", "How deep the algorithm should look forward.", new IntValue(3)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SlackMinimizationSolutionCreator(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey("Depth")) {
+        Parameters.Add(new ValueLookupParameter<IntValue>("Depth", "How deep the algorithm should look forward.", new IntValue(3)));
+      }
+    }
+
+    public static IntegerVector CreateSolution(IRandom random, DoubleArray demands, DoubleArray capacities, int depth, int maximumTries, bool createMostFeasibleSolution, CancellationToken cancel) {
+      IntegerVector result = null;
+      bool isFeasible = false;
+      int counter = 0;
+      double minViolation = double.MaxValue;
+      var slack = new DoubleArray(capacities.Length);
+      var assignment = new Dictionary<int, int>(demands.Length);
+
+      while (!isFeasible) {
+        cancel.ThrowIfCancellationRequested();
+        if (maximumTries > 0) {
+          counter++;
+          if (counter > maximumTries) {
+            if (createMostFeasibleSolution) break;
+            else throw new InvalidOperationException("A feasible solution could not be obtained after " + maximumTries + " attempts.");
+          }
+        }
+        assignment.Clear();
+        for (int i = 0; i < capacities.Length; i++) slack[i] = capacities[i];
+        var remainingEquipment = new HashSet<int>(Enumerable.Range(0, demands.Length));
+        while (remainingEquipment.Any()) {
+          var equipment = remainingEquipment.ChooseProportionalRandom(random, 1, x => demands[x], true, true).Single();
+          remainingEquipment.Remove(equipment);
+
+          var freeLocations = GetLocationsByFillLevel(equipment, demands[equipment], slack);
+          if (!freeLocations.Any()) break;
+          double bestSlack = double.MaxValue;
+          int bestLocation = -1;
+          int[] additionalEquipment = new int[0];
+          foreach (var location in freeLocations.Shuffle(random)) {
+            HashSet<int> newEquipment;
+            var estimatedSlack = EstimatePotentialSlack(location.Key, location.Value, remainingEquipment, demands, out newEquipment, depth);
+            if (estimatedSlack < bestSlack || (estimatedSlack == bestSlack && newEquipment.Count < additionalEquipment.Length)) {
+              bestSlack = estimatedSlack;
+              bestLocation = location.Key;
+              additionalEquipment = newEquipment.ToArray();
+            }
+          }
+          assignment[equipment] = bestLocation;
+          slack[bestLocation] -= demands[equipment];
+          foreach (var eq in additionalEquipment) {
+            remainingEquipment.Remove(eq);
+            assignment[eq] = bestLocation;
+            slack[bestLocation] -= demands[eq];
+          }
+        }
+        if (assignment.Count != demands.Length) {
+          // complete the solution
+          while (remainingEquipment.Any()) {
+            var f = remainingEquipment.ChooseMax(x => demands[x]);
+            var l = Enumerable.Range(0, capacities.Length).ChooseMax(x => slack[x]);
+            remainingEquipment.Remove(f);
+            assignment.Add(f, l);
+            slack[l] -= demands[f];
+          }
+        }
+        double violation = GQAPEvaluator.EvaluateOverbooking(slack, capacities);
+        isFeasible = violation == 0;
+        if (isFeasible || violation < minViolation) {
+          result = new IntegerVector(assignment.OrderBy(x => x.Key).Select(x => x.Value).ToArray());
+          minViolation = violation;
+        }
+      }
+      return result;
+    }
+
+    private static double EstimatePotentialSlack(int location, double slack, HashSet<int> remainingEquipment, DoubleArray demands, out HashSet<int> addedEquipment, int depth = 3) {
+      var feasibleEquipment = remainingEquipment.Where(x => demands[x] < slack).ToArray();
+      addedEquipment = new HashSet<int>();
+
+      if (!feasibleEquipment.Any()) return slack;
+      if (depth == 0) {
+        var e = feasibleEquipment.ChooseMax(x => demands[x]);
+        addedEquipment.Add(e);
+        return slack - demands[e];
+      }
+
+      double bestSlack = slack;
+      int minSlackEquipment = -1;
+      foreach (var e in feasibleEquipment) {
+        remainingEquipment.Remove(e);
+        HashSet<int> childEquipment;
+        var potentialSlack = EstimatePotentialSlack(location, slack - demands[e], remainingEquipment, demands, out childEquipment, depth - 1);
+        if (bestSlack > potentialSlack || (bestSlack == potentialSlack && childEquipment.Count < addedEquipment.Count)) {
+          bestSlack = potentialSlack;
+          minSlackEquipment = e;
+          addedEquipment.Clear();
+          foreach (var child in childEquipment) addedEquipment.Add(child);
+        }
+        remainingEquipment.Add(e);
+      }
+      if (minSlackEquipment > -1)
+        addedEquipment.Add(minSlackEquipment);
+      return bestSlack;
+    }
+
+    protected override IntegerVector CreateRandomSolution(IRandom random, DoubleArray demands, DoubleArray capacities) {
+      return CreateSolution(random, demands, capacities,
+        DepthParameter.ActualValue.Value,
+        MaximumTriesParameter.ActualValue.Value,
+        CreateMostFeasibleSolutionParameter.ActualValue.Value,
+        CancellationToken);
+    }
+
+    private static IEnumerable<KeyValuePair<int, double>> GetLocationsByFillLevel(int equipment, double demand, DoubleArray slack) {
+      var freeLocations = slack
+        .Select((v, idx) => new KeyValuePair<int, double>(idx, v))
+        .Where(x => x.Value >= demand);
+      if (!freeLocations.Any()) {
+        return Enumerable.Empty<KeyValuePair<int, double>>();
+      }
+      return freeLocations.Select(x => new KeyValuePair<int, double>(x.Key, slack[x.Key] - demand)).OrderBy(x => x.Value);
+    }
+  }
+}
Index: /branches/GeneralizedQAP/UnitTests/UnitTests.csproj
===================================================================
--- /branches/GeneralizedQAP/UnitTests/UnitTests.csproj	(revision 7592)
+++ /branches/GeneralizedQAP/UnitTests/UnitTests.csproj	(revision 7593)
@@ -78,6 +78,11 @@
       <Private>True</Private>
     </Reference>
-    <Reference Include="HeuristicLab.Problems.Instances-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
-    <Reference Include="HeuristicLab.Problems.Instances.CordeauGQAP-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+    <Reference Include="HeuristicLab.Problems.Instances-3.3">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Problems.Instances-3.3.dll</HintPath>
+      <SpecificVersion>False</SpecificVersion>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.Instances.CordeauGQAP-3.3">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Problems.Instances.CordeauGQAP-3.3.dll</HintPath>
       <SpecificVersion>False</SpecificVersion>
       <Private>False</Private>
