Index: branches/PerformanceComparison/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 12809)
+++ branches/PerformanceComparison/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 12813)
@@ -105,6 +105,6 @@
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="ALGLIB-3.7.0, Version=3.7.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
-      <HintPath>..\..\bin\ALGLIB-3.7.0.dll</HintPath>
+    <Reference Include="ALGLIB-3.9.0, Version=3.9.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\ALGLIB-3.9.0.dll</HintPath>
       <Private>False</Private>
     </Reference>
Index: branches/PerformanceComparison/HeuristicLab.Analysis/3.3/Optimizers/IRRestarter.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Analysis/3.3/Optimizers/IRRestarter.cs	(revision 12809)
+++ branches/PerformanceComparison/HeuristicLab.Analysis/3.3/Optimizers/IRRestarter.cs	(revision 12813)
@@ -44,4 +44,8 @@
     private const string BestQualityResultName = "BestQuality";
     private const string RandomRestartsResultName = "RandomRestarts";
+    private const string RTsResultName = "RTs";
+    private const string RTusResultName = "RTus";
+    private const string FEsResultName = "FEs";
+    private const string FEusResultName = "FEus";
 
     public string Filename { get; set; }
@@ -192,5 +196,5 @@
       get { return algorithm; }
       set {
-        if (value != null && !typeof(ISingleObjectiveHeuristicOptimizationProblem).IsAssignableFrom(value.ProblemType))
+        if (value != null && !value.ProblemType.IsAssignableFrom(typeof(ISingleObjectiveHeuristicOptimizationProblem)))
           throw new ArgumentException("Algorithm is not single-objective!");
         if (algorithm == value) return;
@@ -391,4 +395,8 @@
         CurrentRun.Results.Add(BestQualityResultName, new DoubleValue(Maximization ? double.MinValue : double.MaxValue));
         CurrentRun.Results.Add(RandomRestartsResultName, new IntValue(0));
+        CurrentRun.Results.Add(RTsResultName, new DoubleValue(0));
+        CurrentRun.Results.Add(RTusResultName, new DoubleValue(0));
+        CurrentRun.Results.Add(FEsResultName, new DoubleValue(0));
+        CurrentRun.Results.Add(FEusResultName, new DoubleValue(0));
       }
       Algorithm.Start();
@@ -517,4 +525,5 @@
 
       var execTime = ((TimeSpanValue)CurrentRun.Results[ExecutionTimeResultName]).Value;
+      double evaluationsInThisRun = 0;
       foreach (var result in Algorithm.Results) {
         if (result.Name == perClockAnalyzer.QualityPerClockParameter.ResultName) {
@@ -549,9 +558,13 @@
           }
         } else if (result.Name == perEvaluationsAnalyzer.EvaluatedSolutionsParameter.ActualName) {
-          var evalSols = ((IntValue)CurrentRun.Results[perEvaluationsAnalyzer.EvaluatedSolutionsParameter.ActualName]).Value;
-          CurrentRun.Results[perEvaluationsAnalyzer.EvaluatedSolutionsParameter.ActualName] = new IntValue(evalSols + ((IntValue)result.Value).Value);
+          var oldEvals = ((IntValue)CurrentRun.Results[perEvaluationsAnalyzer.EvaluatedSolutionsParameter.ActualName]).Value;
+          var newEvals = ((IntValue)result.Value).Value;
+          CurrentRun.Results[perEvaluationsAnalyzer.EvaluatedSolutionsParameter.ActualName] = new IntValue(oldEvals + newEvals);
+          evaluationsInThisRun += newEvals;
         } else if (result.Name == perEvaluationsAnalyzer.EvaluatedMovesParameter.ActualName) {
-          var evalMoves = ((IntValue)CurrentRun.Results[perEvaluationsAnalyzer.EvaluatedMovesParameter.ActualName]).Value;
-          CurrentRun.Results[perEvaluationsAnalyzer.EvaluatedMovesParameter.ActualName] = new IntValue(evalMoves + ((IntValue)result.Value).Value);
+          var oldEvals = ((IntValue)CurrentRun.Results[perEvaluationsAnalyzer.EvaluatedMovesParameter.ActualName]).Value;
+          var newEvals = ((IntValue)result.Value).Value;
+          CurrentRun.Results[perEvaluationsAnalyzer.EvaluatedMovesParameter.ActualName] = new IntValue(oldEvals + newEvals);
+          evaluationsInThisRun += newEvals * moveCostPerSolution;
         } else if (result.Name == perEvaluationsAnalyzer.BestQualityParameter.ActualName) {
           var best = ((DoubleValue)CurrentRun.Results[BestQualityResultName]).Value;
@@ -566,9 +579,27 @@
       CurrentRun.Results[ExecutionTimeResultName] = new TimeSpanValue(execTime + Algorithm.ExecutionTime);
 
+      // Algorithm sets ExecutionTime to zero before firing Prepared
+      // We will thus see ExecutionTimeChanged before Prepared
+      lastAlgorithmExecutionTime = TimeSpan.Zero;
+
       if (!forceStop && !IsFinished) {
-        CurrentRun.Results[RandomRestartsResultName] = new IntValue(1 + ((IntValue)CurrentRun.Results[RandomRestartsResultName]).Value);
-        Algorithm.Prepare();
+        var restarts = ((IntValue)CurrentRun.Results[RandomRestartsResultName]).Value;
+        if (restarts == 0) {
+          CurrentRun.Results[RTusResultName] = new DoubleValue(Algorithm.ExecutionTime.TotalSeconds);
+          CurrentRun.Results[FEusResultName] = new DoubleValue(evaluationsInThisRun);
+        } else {
+          var rtus = ((DoubleValue)CurrentRun.Results[RTusResultName]).Value;
+          var feus = ((DoubleValue)CurrentRun.Results[FEusResultName]).Value;
+          CurrentRun.Results[RTusResultName] = new DoubleValue(rtus * restarts / (restarts + 1.0) + Algorithm.ExecutionTime.TotalSeconds / (restarts + 1.0));
+          CurrentRun.Results[FEusResultName] = new DoubleValue(feus * restarts / (restarts + 1.0) + evaluationsInThisRun / (restarts + 1.0));
+        }
+        CurrentRun.Results[RandomRestartsResultName] = new IntValue(restarts + 1);
+        Algorithm.Prepare(true);
         Algorithm.Start();
       } else {
+        if (Maximization && BestSoFar >= TargetValue || !Maximization && BestSoFar <= TargetValue) {
+          CurrentRun.Results[RTsResultName] = (IItem)Algorithm.Results[perClockAnalyzer.QualityPerClockParameter.ResultName].Value.Clone();
+          CurrentRun.Results[FEsResultName] = (IItem)Algorithm.Results[perEvaluationsAnalyzer.QualityPerEvaluationsParameter.ResultName].Value.Clone();
+        }
         forceStop = false;
         Runs.Add(CurrentRun);
Index: branches/PerformanceComparison/HeuristicLab.Analysis/3.3/Plugin.cs.frame
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Analysis/3.3/Plugin.cs.frame	(revision 12809)
+++ branches/PerformanceComparison/HeuristicLab.Analysis/3.3/Plugin.cs.frame	(revision 12813)
@@ -28,5 +28,5 @@
   [Plugin("HeuristicLab.Analysis", "3.3.12.$WCREV$")]
   [PluginFile("HeuristicLab.Analysis-3.3.dll", PluginFileType.Assembly)]
-  [PluginDependency("HeuristicLab.ALGLIB", "3.7.0")]
+  [PluginDependency("HeuristicLab.ALGLIB", "3.9")]
   [PluginDependency("HeuristicLab.Collections", "3.3")]
   [PluginDependency("HeuristicLab.Common", "3.3")]
Index: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionBoxPlotView.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionBoxPlotView.cs	(revision 12809)
+++ branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionBoxPlotView.cs	(revision 12813)
@@ -345,5 +345,15 @@
       switch (axisDimension) {
         case AxisDimension.Color: {
-            value = GetCategoricalValue(-1, run.Color.ToString());
+            const int colorDimension = -1;
+            if (!categoricalMapping.ContainsKey(colorDimension)) {
+              categoricalMapping[colorDimension] = Content.Where(r => r.Visible)
+                  .Select(r => r.Color.Name)
+                  .Distinct()
+                  .OrderBy(c => c, new NaturalStringComparer())
+                  .Select((c, i) => new { Color = c, Index = i })
+                  .ToDictionary(a => (object)a.Color, a => (double)a.Index);
+
+            }
+            value = GetCategoricalValue(colorDimension, run.Color.Name);
             break;
           }
