Index: branches/PerformanceComparison/HeuristicLab.Analysis/3.3/Optimizers/IRRestarter.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Analysis/3.3/Optimizers/IRRestarter.cs	(revision 12822)
+++ branches/PerformanceComparison/HeuristicLab.Analysis/3.3/Optimizers/IRRestarter.cs	(revision 12825)
@@ -44,8 +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";
+    private const string EvaluatedSolutionsResultName = "EvaluatedSolutions";
+    private const string EvaluatedMovesResultName = "EvaluatedMoves";
+    private const string QualityPerClockResultName = "QualityPerClock";
+    private const string QualityPerEvaluationsResultName = "QualityPerEvaluations";
 
     public string Filename { get; set; }
@@ -124,4 +124,15 @@
         perEvaluationsAnalyzer.MoveCostPerSolutionParameter.Value = new DoubleValue(moveCostPerSolution);
         OnPropertyChanged("MoveCostPerSolution");
+      }
+    }
+
+    [Storable]
+    private bool storeSolutionInRun;
+    public bool StoreSolutionInRun {
+      get { return storeSolutionInRun; }
+      set {
+        if (storeSolutionInRun == value) return;
+        storeSolutionInRun = value;
+        OnPropertyChanged("StoreSolutionInRun");
       }
     }
@@ -196,6 +207,4 @@
       get { return algorithm; }
       set {
-        if (value != null && !value.ProblemType.IsAssignableFrom(typeof(ISingleObjectiveHeuristicOptimizationProblem)))
-          throw new ArgumentException("Algorithm is not single-objective!");
         if (algorithm == value) return;
         if (algorithm != null) {
@@ -266,4 +275,5 @@
       maximumEvaluations = original.maximumEvaluations;
       moveCostPerSolution = original.moveCostPerSolution;
+      storeSolutionInRun = original.storeSolutionInRun;
       targetValue = original.targetValue;
       maximization = original.maximization;
@@ -291,4 +301,5 @@
       maximumEvaluations = 10000000; // 10 mio
       moveCostPerSolution = 1;
+      storeSolutionInRun = false;
       targetValue = 0;
       maximization = false;
@@ -311,4 +322,5 @@
       maximumEvaluations = 10000000; // 10 mio
       moveCostPerSolution = 1;
+      storeSolutionInRun = false;
       targetValue = 0;
       maximization = false;
@@ -330,4 +342,5 @@
       maximumEvaluations = 10000000; // 10 mio
       moveCostPerSolution = 1;
+      storeSolutionInRun = false;
       targetValue = 0;
       maximization = false;
@@ -391,13 +404,12 @@
         if (!CurrentRun.Results.ContainsKey(ExecutionTimeResultName))
           CurrentRun.Results.Add(ExecutionTimeResultName, new TimeSpanValue(TimeSpan.Zero));
-        CurrentRun.Results.Add(perEvaluationsAnalyzer.EvaluatedSolutionsParameter.ActualName, new IntValue(0));
-        CurrentRun.Results.Add(perEvaluationsAnalyzer.EvaluatedMovesParameter.ActualName, new IntValue(0));
+        // use double instead of int, otherwise one might run into int.MaxValue (at least with moves)
+        CurrentRun.Results.Add(EvaluatedSolutionsResultName, new DoubleValue(0));
+        CurrentRun.Results.Add(EvaluatedMovesResultName, new DoubleValue(0));
         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));
-      }
+      }
+      if (Algorithm.ExecutionState == ExecutionState.Stopped)
+        Algorithm.Prepare(true);
       Algorithm.Start();
       ExecutionState = ExecutionState.Started;
@@ -417,5 +429,9 @@
         throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".", ExecutionState));
       forceStop = true;
-      Algorithm.Stop();
+      try {
+        Algorithm.Stop();
+      } catch (InvalidOperationException) {
+        // sometimes we hit the algorithm in an invalid state
+      }
     }
 
@@ -522,59 +538,48 @@
     }
     private void Algorithm_Stopped(object sender, EventArgs e) {
-      var bestQuality = UpdateAlgorithmResults();
+      ExecutionTime += Algorithm.ExecutionTime - lastAlgorithmExecutionTime;
+      lastAlgorithmExecutionTime = Algorithm.ExecutionTime;
 
       var execTime = ((TimeSpanValue)CurrentRun.Results[ExecutionTimeResultName]).Value;
-      double evaluationsInThisRun = 0;
-      foreach (var result in Algorithm.Results) {
-        if (result.Name == perClockAnalyzer.QualityPerClockParameter.ResultName) {
-          if (!CurrentRun.Results.ContainsKey(result.Name))
-            CurrentRun.Results.Add(result.Name, (IItem)result.Value.Clone());
-          else {
-            var dt = (IndexedDataTable<double>)CurrentRun.Results[result.Name];
-            var best = dt.Rows.First().Values.Last().Item2;
-            var resultDt = (IndexedDataTable<double>)result.Value;
-            foreach (var tupl in resultDt.Rows.First().Values) {
-              if (Maximization && tupl.Item2 > best || !Maximization && tupl.Item2 < best) {
-                dt.Rows.First().Values.Add(Tuple.Create(execTime.TotalSeconds + tupl.Item1, tupl.Item2));
-                best = tupl.Item2;
-              }
-            }
+      var solEvals = ((DoubleValue)CurrentRun.Results[EvaluatedSolutionsResultName]).Value;
+      var movEvals = ((DoubleValue)CurrentRun.Results[EvaluatedMovesResultName]).Value;
+      var restarts = ((IntValue)CurrentRun.Results[RandomRestartsResultName]).Value;
+      var improvement = false;
+
+      IResult result;
+      if (Algorithm.Results.TryGetValue(perEvaluationsAnalyzer.EvaluatedSolutionsParameter.ActualName, out result)) {
+        var evals = ((IntValue)result.Value).Value;
+        Evaluations += evals;
+        CurrentRun.Results[EvaluatedSolutionsResultName] = new DoubleValue(solEvals + evals);
+      }
+      if (Algorithm.Results.TryGetValue(perEvaluationsAnalyzer.EvaluatedMovesParameter.ActualName, out result)) {
+        var evals = ((IntValue)result.Value).Value;
+        Evaluations += moveCostPerSolution * evals;
+        CurrentRun.Results[EvaluatedMovesResultName] = new DoubleValue(movEvals + evals);
+      }
+      if (Algorithm.Results.TryGetValue(perEvaluationsAnalyzer.BestQualityParameter.ActualName, out result)) {
+        var bestQuality = ((DoubleValue)result.Value).Value;
+        if (double.IsNaN(BestSoFar)
+            || Maximization && bestQuality > BestSoFar
+            || !Maximization && bestQuality < BestSoFar) {
+          BestSoFar = bestQuality;
+          CurrentRun.Results[BestQualityResultName] = new DoubleValue(bestQuality);
+          improvement = true;
+        }
+      }
+      if (Algorithm.Results.TryGetValue(perClockAnalyzer.QualityPerClockParameter.ResultName, out result)) {
+        UpdateQualityPerClockResult((IndexedDataTable<double>)result.Value, execTime, restarts);
+      }
+      if (Algorithm.Results.TryGetValue(perEvaluationsAnalyzer.QualityPerEvaluationsParameter.ResultName, out result)) {
+        UpdateQualityPerEvaluationsResult((IndexedDataTable<double>)result.Value, solEvals, movEvals, restarts);
+      }
+      if (StoreSolutionInRun) {
+        foreach (var r in Algorithm.Results) {
+          if (r.Name.ToLower().EndsWith("solution") && improvement) {
+            CurrentRun.Results[r.Name] = (IItem)r.Value.Clone();
           }
-        } else if (result.Name == perEvaluationsAnalyzer.QualityPerEvaluationsParameter.ResultName) {
-          if (!CurrentRun.Results.ContainsKey(result.Name))
-            CurrentRun.Results.Add(result.Name, (IItem)result.Value.Clone());
-          else {
-            var dt = (IndexedDataTable<double>)CurrentRun.Results[result.Name];
-            var evalSols = ((IntValue)CurrentRun.Results[perEvaluationsAnalyzer.EvaluatedSolutionsParameter.ActualName]).Value;
-            var evalMoves = ((IntValue)CurrentRun.Results[perEvaluationsAnalyzer.EvaluatedMovesParameter.ActualName]).Value;
-            var best = dt.Rows.First().Values.Last().Item2;
-            var resultDt = (IndexedDataTable<double>)result.Value;
-            foreach (var tupl in resultDt.Rows.First().Values) {
-              if (Maximization && tupl.Item2 > best || !Maximization && tupl.Item2 < best) {
-                dt.Rows.First().Values.Add(Tuple.Create(evalSols + moveCostPerSolution * evalMoves + tupl.Item1, tupl.Item2));
-                best = tupl.Item2;
-              }
-            }
-          }
-        } else if (result.Name == perEvaluationsAnalyzer.EvaluatedSolutionsParameter.ActualName) {
-          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 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;
-          if (Maximization && best < bestQuality || !Maximization && best > bestQuality)
-            CurrentRun.Results[BestQualityResultName] = new DoubleValue(bestQuality);
-        } else if (result.Name.ToLower().EndsWith("solution") && BestSoFar == bestQuality) {
-          if (CurrentRun.Results.ContainsKey(result.Name))
-            CurrentRun.Results[result.Name] = (IItem)result.Value.Clone();
-          else CurrentRun.Results.Add(result.Name, (IItem)result.Value.Clone());
         }
       }
+
       CurrentRun.Results[ExecutionTimeResultName] = new TimeSpanValue(execTime + Algorithm.ExecutionTime);
 
@@ -584,22 +589,8 @@
 
       if (!forceStop && !IsFinished) {
-        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);
@@ -610,26 +601,64 @@
     }
 
-    private double UpdateAlgorithmResults() {
-      ExecutionTime += Algorithm.ExecutionTime - lastAlgorithmExecutionTime;
-      lastAlgorithmExecutionTime = Algorithm.ExecutionTime;
-
-      IResult evaluationsResult;
-      if (Algorithm.Results.TryGetValue(perEvaluationsAnalyzer.EvaluatedSolutionsParameter.ActualName, out evaluationsResult)) {
-        var evals = ((IntValue)evaluationsResult.Value).Value;
-        Evaluations += evals;
-      }
-      if (Algorithm.Results.TryGetValue(perEvaluationsAnalyzer.EvaluatedMovesParameter.ActualName, out evaluationsResult)) {
-        var evals = ((IntValue)evaluationsResult.Value).Value;
-        Evaluations += moveCostPerSolution * evals;
-      }
-      if (Algorithm.Results.TryGetValue(perEvaluationsAnalyzer.BestQualityParameter.ActualName, out evaluationsResult)) {
-        var bestQuality = ((DoubleValue)evaluationsResult.Value).Value;
-        if (double.IsNaN(BestSoFar)
-            || Maximization && bestQuality > BestSoFar
-            || !Maximization && bestQuality < BestSoFar)
-          BestSoFar = bestQuality;
-        return bestQuality;
-      }
-      return double.NaN;
+    private void UpdateQualityPerClockResult(IndexedDataTable<double> perClock, TimeSpan execTime, int restarts) {
+      IndexedDataTable<double> dt;
+      if (!CurrentRun.Results.ContainsKey(QualityPerClockResultName)) {
+        dt = (IndexedDataTable<double>)perClock.Clone();
+        if (!dt.Rows.ContainsKey("Restarts"))
+          dt.Rows.Add(new IndexedDataRow<double>("Restarts") {
+            VisualProperties = {
+              ChartType = DataRowVisualProperties.DataRowChartType.StepLine,
+              SecondYAxis = true
+            }
+          });
+        foreach (var v in dt.Rows.First().Values)
+          dt.Rows["Restarts"].Values.Add(Tuple.Create(v.Item1, 0.0));
+        CurrentRun.Results.Add(QualityPerClockResultName, dt);
+      } else {
+        dt = (IndexedDataTable<double>)CurrentRun.Results[QualityPerClockResultName];
+        var best = dt.Rows.First().Values.Last().Item2;
+        foreach (var tupl in perClock.Rows.First().Values) {
+          if (Maximization && tupl.Item2 > best || !Maximization && tupl.Item2 < best) {
+            dt.Rows.First().Values.Add(Tuple.Create(execTime.TotalSeconds + tupl.Item1, tupl.Item2));
+            dt.Rows["Restarts"].Values.Add(Tuple.Create(execTime.TotalSeconds + tupl.Item1, (double)restarts));
+            best = tupl.Item2;
+          }
+        }
+      }
+      if (IsFinished) {
+        dt.Rows.First().Values.Add(Tuple.Create(ExecutionTime.TotalSeconds, BestSoFar));
+        dt.Rows["Restarts"].Values.Add(Tuple.Create(ExecutionTime.TotalSeconds, (double)restarts));
+      }
+    }
+
+    private void UpdateQualityPerEvaluationsResult(IndexedDataTable<double> perEvaluations, double solEvals, double movEvals, int restarts) {
+      IndexedDataTable<double> dt;
+      if (!CurrentRun.Results.ContainsKey(QualityPerEvaluationsResultName)) {
+        dt = (IndexedDataTable<double>)perEvaluations.Clone();
+        if (!dt.Rows.ContainsKey("Restarts"))
+          dt.Rows.Add(new IndexedDataRow<double>("Restarts") {
+            VisualProperties = {
+              ChartType = DataRowVisualProperties.DataRowChartType.StepLine,
+              SecondYAxis = true
+            }
+          });
+        foreach (var v in dt.Rows.First().Values)
+          dt.Rows["Restarts"].Values.Add(Tuple.Create(v.Item1, 0.0));
+        CurrentRun.Results.Add(QualityPerEvaluationsResultName, dt);
+      } else {
+        dt = (IndexedDataTable<double>)CurrentRun.Results[QualityPerEvaluationsResultName];
+        var best = dt.Rows.First().Values.Last().Item2;
+        foreach (var tupl in perEvaluations.Rows.First().Values) {
+          if (Maximization && tupl.Item2 > best || !Maximization && tupl.Item2 < best) {
+            dt.Rows.First().Values.Add(Tuple.Create(solEvals + moveCostPerSolution * movEvals + tupl.Item1, tupl.Item2));
+            dt.Rows["Restarts"].Values.Add(Tuple.Create(solEvals + moveCostPerSolution * movEvals + tupl.Item1, (double)restarts));
+            best = tupl.Item2;
+          }
+        }
+      }
+      if (IsFinished) {
+        dt.Rows.First().Values.Add(Tuple.Create(Evaluations, BestSoFar));
+        dt.Rows["Restarts"].Values.Add(Tuple.Create(Evaluations, (double)restarts));
+      }
     }
 
Index: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/IRRestarterView.Designer.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/IRRestarterView.Designer.cs	(revision 12822)
+++ branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/IRRestarterView.Designer.cs	(revision 12825)
@@ -56,4 +56,6 @@
       this.maximizationLabel = new System.Windows.Forms.Label();
       this.maximizationCheckBox = new System.Windows.Forms.CheckBox();
+      this.storeSolutionInRunLabel = new System.Windows.Forms.Label();
+      this.storeBestSolutionCheckBox = new System.Windows.Forms.CheckBox();
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
       this.tabControl.SuspendLayout();
@@ -66,5 +68,5 @@
       // 
       this.startButton.Location = new System.Drawing.Point(0, 440);
-      this.startButton.TabIndex = 9;
+      this.startButton.TabIndex = 18;
       this.toolTip.SetToolTip(this.startButton, "Start/Resume Optimizer");
       // 
@@ -72,13 +74,15 @@
       // 
       this.executionTimeTextBox.Location = new System.Drawing.Point(412, 444);
+      this.executionTimeTextBox.TabIndex = 23;
       // 
       // executionTimeLabel
       // 
       this.executionTimeLabel.Location = new System.Drawing.Point(323, 447);
+      this.executionTimeLabel.TabIndex = 22;
       // 
       // pauseButton
       // 
       this.pauseButton.Location = new System.Drawing.Point(30, 440);
-      this.pauseButton.TabIndex = 10;
+      this.pauseButton.TabIndex = 19;
       this.toolTip.SetToolTip(this.pauseButton, "Pause Optimizer");
       // 
@@ -86,5 +90,5 @@
       // 
       this.stopButton.Location = new System.Drawing.Point(60, 440);
-      this.stopButton.TabIndex = 11;
+      this.stopButton.TabIndex = 20;
       this.toolTip.SetToolTip(this.stopButton, "Stop Optimizer");
       // 
@@ -92,5 +96,5 @@
       // 
       this.resetButton.Location = new System.Drawing.Point(90, 440);
-      this.resetButton.TabIndex = 12;
+      this.resetButton.TabIndex = 21;
       this.toolTip.SetToolTip(this.resetButton, "Reset Optimizer");
       // 
@@ -151,9 +155,9 @@
       this.tabControl.Controls.Add(this.currentRunTabPage);
       this.tabControl.Controls.Add(this.runsTabPage);
-      this.tabControl.Location = new System.Drawing.Point(0, 132);
+      this.tabControl.Location = new System.Drawing.Point(0, 152);
       this.tabControl.Name = "tabControl";
       this.tabControl.SelectedIndex = 0;
-      this.tabControl.Size = new System.Drawing.Size(546, 302);
-      this.tabControl.TabIndex = 8;
+      this.tabControl.Size = new System.Drawing.Size(546, 282);
+      this.tabControl.TabIndex = 17;
       // 
       // algorithmTabPage
@@ -166,5 +170,5 @@
       this.algorithmTabPage.Name = "algorithmTabPage";
       this.algorithmTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.algorithmTabPage.Size = new System.Drawing.Size(538, 276);
+      this.algorithmTabPage.Size = new System.Drawing.Size(538, 256);
       this.algorithmTabPage.TabIndex = 1;
       this.algorithmTabPage.Text = "Algorithm";
@@ -185,5 +189,5 @@
       this.algorithmViewHost.Name = "algorithmViewHost";
       this.algorithmViewHost.ReadOnly = false;
-      this.algorithmViewHost.Size = new System.Drawing.Size(526, 234);
+      this.algorithmViewHost.Size = new System.Drawing.Size(526, 214);
       this.algorithmViewHost.TabIndex = 2;
       this.algorithmViewHost.ViewsLabelVisible = true;
@@ -218,5 +222,5 @@
       this.currentRunTabPage.Name = "currentRunTabPage";
       this.currentRunTabPage.Padding = new System.Windows.Forms.Padding(6);
-      this.currentRunTabPage.Size = new System.Drawing.Size(538, 276);
+      this.currentRunTabPage.Size = new System.Drawing.Size(538, 256);
       this.currentRunTabPage.TabIndex = 4;
       this.currentRunTabPage.Text = "Current Run";
@@ -231,5 +235,5 @@
       this.currentRunView.Name = "currentRunView";
       this.currentRunView.ReadOnly = false;
-      this.currentRunView.Size = new System.Drawing.Size(526, 264);
+      this.currentRunView.Size = new System.Drawing.Size(526, 244);
       this.currentRunView.TabIndex = 0;
       // 
@@ -240,5 +244,5 @@
       this.runsTabPage.Name = "runsTabPage";
       this.runsTabPage.Padding = new System.Windows.Forms.Padding(6);
-      this.runsTabPage.Size = new System.Drawing.Size(538, 276);
+      this.runsTabPage.Size = new System.Drawing.Size(538, 256);
       this.runsTabPage.TabIndex = 3;
       this.runsTabPage.Text = "Runs";
@@ -253,5 +257,5 @@
       this.runsView.Name = "runsView";
       this.runsView.ReadOnly = false;
-      this.runsView.Size = new System.Drawing.Size(526, 264);
+      this.runsView.Size = new System.Drawing.Size(526, 244);
       this.runsView.TabIndex = 1;
       // 
@@ -268,5 +272,5 @@
       this.targetValueTextBox.Name = "targetValueTextBox";
       this.targetValueTextBox.Size = new System.Drawing.Size(157, 20);
-      this.targetValueTextBox.TabIndex = 6;
+      this.targetValueTextBox.TabIndex = 10;
       this.targetValueTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.targetValueTextBox_Validating);
       // 
@@ -277,5 +281,5 @@
       this.targetValueLabel.Name = "targetValueLabel";
       this.targetValueLabel.Size = new System.Drawing.Size(71, 13);
-      this.targetValueLabel.TabIndex = 5;
+      this.targetValueLabel.TabIndex = 9;
       this.targetValueLabel.Text = "Target Value:";
       // 
@@ -289,5 +293,5 @@
       this.terminationComboBox.Name = "terminationComboBox";
       this.terminationComboBox.Size = new System.Drawing.Size(409, 21);
-      this.terminationComboBox.TabIndex = 16;
+      this.terminationComboBox.TabIndex = 14;
       this.terminationComboBox.SelectedIndexChanged += new System.EventHandler(this.terminationComboBox_SelectedIndexChanged);
       // 
@@ -298,5 +302,5 @@
       this.terminationLabel.Name = "terminationLabel";
       this.terminationLabel.Size = new System.Drawing.Size(65, 13);
-      this.terminationLabel.TabIndex = 5;
+      this.terminationLabel.TabIndex = 13;
       this.terminationLabel.Text = "Termination:";
       // 
@@ -308,5 +312,5 @@
       this.moveCostPerSolutionTextBox.Name = "moveCostPerSolutionTextBox";
       this.moveCostPerSolutionTextBox.Size = new System.Drawing.Size(123, 20);
-      this.moveCostPerSolutionTextBox.TabIndex = 6;
+      this.moveCostPerSolutionTextBox.TabIndex = 8;
       this.moveCostPerSolutionTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.moveCostPerSolutionTextBox_Validating);
       // 
@@ -317,5 +321,5 @@
       this.moveCostPerSolutionLabel.Name = "moveCostPerSolutionLabel";
       this.moveCostPerSolutionLabel.Size = new System.Drawing.Size(117, 13);
-      this.moveCostPerSolutionLabel.TabIndex = 5;
+      this.moveCostPerSolutionLabel.TabIndex = 7;
       this.moveCostPerSolutionLabel.Text = "Move cost per solution:";
       // 
@@ -326,5 +330,5 @@
       this.maximizationLabel.Name = "maximizationLabel";
       this.maximizationLabel.Size = new System.Drawing.Size(70, 13);
-      this.maximizationLabel.TabIndex = 5;
+      this.maximizationLabel.TabIndex = 11;
       this.maximizationLabel.Text = "Maximization:";
       // 
@@ -335,11 +339,31 @@
       this.maximizationCheckBox.Name = "maximizationCheckBox";
       this.maximizationCheckBox.Size = new System.Drawing.Size(15, 14);
-      this.maximizationCheckBox.TabIndex = 17;
+      this.maximizationCheckBox.TabIndex = 12;
       this.maximizationCheckBox.UseVisualStyleBackColor = true;
       this.maximizationCheckBox.CheckedChanged += new System.EventHandler(this.maximizationCheckBox_CheckedChanged);
       // 
+      // storeSolutionInRunLabel
+      // 
+      this.storeSolutionInRunLabel.AutoSize = true;
+      this.storeSolutionInRunLabel.Location = new System.Drawing.Point(3, 132);
+      this.storeSolutionInRunLabel.Name = "storeSolutionInRunLabel";
+      this.storeSolutionInRunLabel.Size = new System.Drawing.Size(76, 13);
+      this.storeSolutionInRunLabel.TabIndex = 15;
+      this.storeSolutionInRunLabel.Text = "Store Solution:";
+      // 
+      // storeBestSolutionCheckBox
+      // 
+      this.storeBestSolutionCheckBox.AutoSize = true;
+      this.storeBestSolutionCheckBox.Location = new System.Drawing.Point(115, 132);
+      this.storeBestSolutionCheckBox.Name = "storeBestSolutionCheckBox";
+      this.storeBestSolutionCheckBox.Size = new System.Drawing.Size(15, 14);
+      this.storeBestSolutionCheckBox.TabIndex = 16;
+      this.storeBestSolutionCheckBox.UseVisualStyleBackColor = true;
+      this.storeBestSolutionCheckBox.CheckedChanged += new System.EventHandler(this.storeBestSolutionCheckBox_CheckedChanged);
+      // 
       // IndependentRandomRestarterView
       // 
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.storeBestSolutionCheckBox);
       this.Controls.Add(this.maximizationCheckBox);
       this.Controls.Add(this.terminationComboBox);
@@ -348,4 +372,5 @@
       this.Controls.Add(this.timeLimitLabel);
       this.Controls.Add(this.terminationLabel);
+      this.Controls.Add(this.storeSolutionInRunLabel);
       this.Controls.Add(this.targetValueLabel);
       this.Controls.Add(this.maximizationLabel);
@@ -364,4 +389,5 @@
       this.Controls.SetChildIndex(this.maximizationLabel, 0);
       this.Controls.SetChildIndex(this.targetValueLabel, 0);
+      this.Controls.SetChildIndex(this.storeSolutionInRunLabel, 0);
       this.Controls.SetChildIndex(this.terminationLabel, 0);
       this.Controls.SetChildIndex(this.timeLimitLabel, 0);
@@ -379,4 +405,5 @@
       this.Controls.SetChildIndex(this.terminationComboBox, 0);
       this.Controls.SetChildIndex(this.maximizationCheckBox, 0);
+      this.Controls.SetChildIndex(this.storeBestSolutionCheckBox, 0);
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
       this.tabControl.ResumeLayout(false);
@@ -413,4 +440,6 @@
     private System.Windows.Forms.TabPage currentRunTabPage;
     private RunView currentRunView;
+    private System.Windows.Forms.Label storeSolutionInRunLabel;
+    private System.Windows.Forms.CheckBox storeBestSolutionCheckBox;
   }
 }
Index: branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/IRRestarterView.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/IRRestarterView.cs	(revision 12822)
+++ branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/IRRestarterView.cs	(revision 12825)
@@ -77,4 +77,5 @@
           maximizationCheckBox.CheckState = CheckState.Indeterminate;
           terminationComboBox.SelectedIndex = -1;
+          storeBestSolutionCheckBox.CheckState = CheckState.Indeterminate;
 
           algorithmViewHost.Content = null;
@@ -88,4 +89,5 @@
           maximizationCheckBox.Checked = Content.Maximization;
           terminationComboBox.SelectedItem = Content.TerminationCriterium;
+          storeBestSolutionCheckBox.Checked = Content.StoreSolutionInRun;
 
           algorithmViewHost.Content = Content.Algorithm;
@@ -104,4 +106,5 @@
       maximizationCheckBox.Enabled = Content != null && !ReadOnly && !Locked;
       terminationComboBox.Enabled = Content != null && !ReadOnly && !Locked;
+      storeBestSolutionCheckBox.Enabled = Content != null && !ReadOnly && !Locked;
       newAlgorithmButton.Enabled = Content != null && !ReadOnly;
       openAlgorithmButton.Enabled = Content != null && !ReadOnly;
@@ -126,4 +129,8 @@
     #region Content events
     private void Content_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      if (InvokeRequired) {
+        Invoke((Action<object, PropertyChangedEventArgs>)Content_PropertyChanged, sender, e);
+        return;
+      }
       SuppressEvents = true;
       try {
@@ -135,4 +142,5 @@
           case "Maximization": maximizationCheckBox.Checked = Content.Maximization; break;
           case "MoveCostPerSolution": moveCostPerSolutionTextBox.Text = Content.MoveCostPerSolution.ToString(CultureInfo.CurrentCulture.NumberFormat); break;
+          case "StoreSolutionInRun": storeBestSolutionCheckBox.Checked = Content.StoreSolutionInRun; break;
           case "Algorithm": algorithmViewHost.Content = Content.Algorithm; break;
           case "CurrentRun": currentRunView.Content = Content.CurrentRun; break;
@@ -228,4 +236,13 @@
       }
       Content.TerminationCriterium = (TerminationCriterium)terminationComboBox.SelectedItem;
+    }
+
+    private void storeBestSolutionCheckBox_CheckedChanged(object sender, EventArgs e) {
+      if (SuppressEvents) return;
+      if (InvokeRequired) {
+        Invoke((Action<object, EventArgs>)storeBestSolutionCheckBox_CheckedChanged, sender, e);
+        return;
+      }
+      Content.StoreSolutionInRun = storeBestSolutionCheckBox.Checked;
     }
 
