Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis/3.3/Operators/DynOpEqHistogramInitializer.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis/3.3/Operators/DynOpEqHistogramInitializer.cs	(revision 4221)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis/3.3/Operators/DynOpEqHistogramInitializer.cs	(revision 4222)
@@ -60,4 +60,7 @@
       get { return (ILookupParameter<ItemList<IntValue>>)Parameters["TotalCounts"]; }
     }
+    public ILookupParameter<BoolValue> MaximizationParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
 
     public DynOpEqHistogramInitializer()
@@ -71,4 +74,5 @@
       Parameters.Add(new LookupParameter<ItemList<IntValue>>("AcceptedCounts"));
       Parameters.Add(new LookupParameter<ItemList<IntValue>>("TotalCounts"));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization"));
     }
 
@@ -76,38 +80,71 @@
       if (BinCapacityParameter.ActualValue == null) {
         InitDefaultCapacityHistogram();
-      }
-      ItemList<ItemList<DoubleValue>> acceptedBinQualities = AcceptedBinQualitiesParameter.ActualValue;
-      ItemList<IntValue> acceptedCounts = AcceptedCountsParameter.ActualValue;
-      ItemList<IntValue> totalCounts = TotalCountsParameter.ActualValue;
-
-      int popSize = PopulationSizeParameter.ActualValue.Value;
-      //double minQuality = (from binAccepted in acceptedBinQualities
-      //                     where binAccepted.Count > 0
-      //                     select binAccepted.Min(x => x.Value)).Min();
-      //double maxQuality = (from binAccepted in acceptedBinQualities
-      //                     where binAccepted.Count > 0
-      //                     select binAccepted.Max(x => x.Value)).Max();
-      //double range = maxQuality - minQuality;
-      double avgQualitySum = (from binAccepted in acceptedBinQualities
-                              //select binAccepted.Count)
-                              where binAccepted.Count > 0
-                              select (from quality in binAccepted
-                                      select quality.Value).Average())
-                                    .Sum();
-      ItemList<IntValue> binCapacity = BinCapacityParameter.ActualValue;
-      for (int i = 0; i < binCapacity.Count; i++) {
-        double avgBinQuality = (from quality in acceptedBinQualities[i]
-                                select quality.Value)
-                               .DefaultIfEmpty(0.0)
-                               .Average();
-
-        //double avgBinQuality = acceptedBinQualities[i].Count;
-        binCapacity[i].Value = (int)Math.Ceiling(popSize * (avgBinQuality / avgQualitySum));
-        acceptedBinQualities[i].Clear();
-        acceptedCounts[i].Value = 0;
-      }
-      for (int i = 0; i < totalCounts.Count; i++)
-        totalCounts[i].Value = 0;
+      } else {
+        ItemList<ItemList<DoubleValue>> acceptedBinQualities = AcceptedBinQualitiesParameter.ActualValue;
+        ItemList<IntValue> acceptedCounts = AcceptedCountsParameter.ActualValue;
+        ItemList<IntValue> totalCounts = TotalCountsParameter.ActualValue;
+
+        int popSize = PopulationSizeParameter.ActualValue.Value;
+
+        ScaleBinQualities(acceptedBinQualities, 0, 1, MaximizationParameter.ActualValue.Value);
+
+        double avgQualitySum = (from binAccepted in acceptedBinQualities
+                                where binAccepted.Count > 0
+                                select (from quality in binAccepted
+                                        select quality.Value).Average())
+                                      .Sum();
+        ItemList<IntValue> binCapacity = BinCapacityParameter.ActualValue;
+        int totalCapacity = 0;
+        for (int i = 0; i < binCapacity.Count; i++) {
+          double avgBinQuality = (from quality in acceptedBinQualities[i]
+                                  select quality.Value)
+                                 .DefaultIfEmpty(0.0)
+                                 .Average();
+
+          binCapacity[i].Value = Math.Max(1, (int)Math.Round(popSize * (avgBinQuality / avgQualitySum)));
+          // rounding can lead to loss of capacity
+          // this is problematic if the bin capacities are strict
+          totalCapacity += binCapacity[i].Value;
+          acceptedBinQualities[i].Clear();
+          acceptedCounts[i].Value = 0;
+        }
+        // distribute the remaining slots starting with the largest bins
+        IEnumerator<IntValue> orderedBinCapacities = binCapacity.OrderBy(x => -x.Value).GetEnumerator();
+
+        while (totalCapacity < popSize & orderedBinCapacities.MoveNext()) {
+          orderedBinCapacities.Current.Value = orderedBinCapacities.Current.Value + 1;
+          totalCapacity++;
+        }
+        if (totalCapacity < popSize) throw new InvalidProgramException("The sum of bin capacities doesn't match the population size");
+        for (int i = 0; i < totalCounts.Count; i++)
+          totalCounts[i].Value = 0;
+      }
       return base.Apply();
+    }
+
+    public static void ScaleBinQualities(ItemList<ItemList<DoubleValue>> acceptedBinQualities, double min, double max, bool maximization) {
+      double minValue = (from bin in acceptedBinQualities
+                         from value in bin
+                         select value.Value).Min();
+      double maxValue = (from bin in acceptedBinQualities
+                         from value in bin
+                         select value.Value).Max();
+
+      if (!maximization) {
+        double tmp = minValue;
+        minValue = maxValue;
+        maxValue = tmp;
+      }
+
+      double valuesRange = maxValue - minValue;
+      double targetRange = max - min;
+
+      foreach (var bin in acceptedBinQualities) {
+        foreach (var value in bin) {
+          double unitScaledValue = (value.Value - minValue) / valuesRange;
+          double targetScaledValue = unitScaledValue * targetRange + min;
+          value.Value = targetScaledValue;
+        }
+      }
     }
 
@@ -129,5 +166,4 @@
         } else {
           CreateNewBin(binIndex);
-          AddToBin(binIndex, quality[i].Value);
         }
       }
@@ -148,6 +184,6 @@
 
     private void AddToBin(int binIndex, double quality) {
-      ItemList<ItemList<DoubleValue>> acceptedQualities = AcceptedBinQualitiesParameter.ActualValue;
-      acceptedQualities[binIndex].Add(new DoubleValue(quality));
+      ItemList<IntValue> binCapacity = BinCapacityParameter.ActualValue;
+      binCapacity[binIndex].Value = binCapacity[binIndex].Value + 1;
     }
 
