Index: /branches/ALPS/HeuristicLab.Algorithms.ALPS/3.3/Alps.cs
===================================================================
--- /branches/ALPS/HeuristicLab.Algorithms.ALPS/3.3/Alps.cs	(revision 12530)
+++ /branches/ALPS/HeuristicLab.Algorithms.ALPS/3.3/Alps.cs	(revision 12531)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Analysis;
@@ -87,4 +88,7 @@
       get { return (IValueLookupParameter<PercentValue>)Parameters["MatingPoolSelectionPercentage"]; }
     }
+    private IValueParameter<MultiTerminator> TerminatorParameter {
+      get { return (IValueParameter<MultiTerminator>)Parameters["Terminator"]; }
+    }
     #endregion
 
@@ -135,4 +139,7 @@
       get { return MatingPoolSelectionPercentageParameter.Value; }
       set { MatingPoolSelectionPercentageParameter.Value = value; }
+    }
+    public MultiTerminator Terminators {
+      get { return TerminatorParameter.Value; }
     }
     #endregion
@@ -152,4 +159,12 @@
     [Storable]
     private BestAverageWorstQualityAnalyzer layerQualityAnalyzer;
+    #endregion
+    #region Preconfigured Terminators
+    [Storable]
+    private ComparisonTerminator<IntValue> evaluationsTerminator;
+    [Storable]
+    private SingleObjectiveQualityTerminator qualityTerminator;
+    [Storable]
+    private ExecutionTimeTerminator executionTimeTerminator;
     #endregion
 
@@ -161,4 +176,7 @@
       qualityAnalyzer = cloner.Clone(original.qualityAnalyzer);
       layerQualityAnalyzer = cloner.Clone(original.layerQualityAnalyzer);
+      evaluationsTerminator = cloner.Clone(original.evaluationsTerminator);
+      qualityTerminator = cloner.Clone(original.qualityTerminator);
+      executionTimeTerminator = cloner.Clone(original.executionTimeTerminator);
       Initialize();
     }
@@ -178,4 +196,5 @@
       Parameters.Add(new ValueParameter<IntValue>("MatingPoolRange", "The range of layers used for creating a mating pool. (1 = current + previous layer)", new IntValue(1)) { Hidden = true });
       Parameters.Add(new ValueParameter<PercentValue>("MatingPoolSelectionPercentage", "Percentage of the previous layers used for creating a mating pool.", new PercentValue(1.0, restrictToUnitInterval: true)) { Hidden = true });
+      Parameters.Add(new ValueParameter<MultiTerminator>("Terminator", "The termination criteria which sould be checked.", new MultiTerminator()));
 
       qualityAnalyzer = new BestAverageWorstQualityAnalyzer();
@@ -187,4 +206,8 @@
       ParameterizeAnalyzers();
       UpdateAnalyzers();
+
+      CreateTerminators();
+      ParameterizeTerminators();
+      UpdateTerminators();
 
       Initialize();
@@ -206,7 +229,20 @@
       ParameterizeSolutionsCreator();
       ParameterizeAnalyzers();
+      ParameterizeTerminators();
       UpdateAnalyzers();
+      UpdateTerminators();
       Problem.Evaluator.QualityParameter.ActualNameChanged += Evaluator_QualityParameter_ActualNameChanged;
     }
+    protected override void RegisterProblemEvents() {
+      base.RegisterProblemEvents();
+      var maximizationParameter = (IValueParameter<BoolValue>)Problem.MaximizationParameter;
+      if (maximizationParameter != null) maximizationParameter.ValueChanged += new EventHandler(MaximizationParameter_ValueChanged);
+    }
+    protected override void DeregisterProblemEvents() {
+      var maximizationParameter = (IValueParameter<BoolValue>)Problem.MaximizationParameter;
+      if (maximizationParameter != null) maximizationParameter.ValueChanged -= new EventHandler(MaximizationParameter_ValueChanged);
+      base.DeregisterProblemEvents();
+    }
+
     protected override void Problem_SolutionCreatorChanged(object sender, EventArgs e) {
       base.Problem_SolutionCreatorChanged(sender, e);
@@ -226,8 +262,15 @@
         ParameterizeStochasticOperator(@operator);
       UpdateAnalyzers();
+      UpdateTerminators();
       base.Problem_OperatorsChanged(sender, e);
     }
     protected virtual void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
       ParameterizeAnalyzers();
+    }
+    private void MaximizationParameter_ValueChanged(object sender, EventArgs e) {
+      ParameterizeTerminators();
+    }
+    private void QualityAnalyzer_CurrentBestQualityParameter_NameChanged(object sender, EventArgs e) {
+      ParameterizeTerminators();
     }
 
@@ -296,4 +339,5 @@
       Analyzer.Operators.ItemsAdded += AnalyzerOperators_ItemsAdded;
       LayerAnalyzer.Operators.ItemsAdded += LayerAnalyzerOperators_ItemsAdded;
+      qualityAnalyzer.CurrentBestQualityParameter.NameChanged += new EventHandler(QualityAnalyzer_CurrentBestQualityParameter_NameChanged);
     }
     private void ParameterizeSolutionsCreator() {
@@ -323,5 +367,7 @@
       }
     }
-
+    private void ParameterizeTerminators() {
+      qualityTerminator.Parameterize(qualityAnalyzer.CurrentBestQualityParameter, Problem);
+    }
     private void ParameterizeAgeInheritanceReduction() {
       AgeInheritanceReduction.Value = GetAgeInheritanceReduction(AgeInheritance.Value);
@@ -364,4 +410,25 @@
       }
     }
+    protected virtual void UpdateTerminators() {
+      var newTerminators = new Dictionary<ITerminator, bool> {
+        {evaluationsTerminator, Terminators.Operators.Contains(evaluationsTerminator) && Terminators.Operators.ItemChecked(evaluationsTerminator)},
+        {qualityTerminator, Terminators.Operators.Contains(qualityTerminator) && Terminators.Operators.ItemChecked(qualityTerminator) },
+        {executionTimeTerminator, Terminators.Operators.Contains(executionTimeTerminator) && Terminators.Operators.ItemChecked(executionTimeTerminator)}
+      };
+      if (Problem != null) {
+        foreach (var terminator in Problem.Operators.OfType<ITerminator>())
+          newTerminators.Add(terminator, !Terminators.Operators.Contains(terminator) || Terminators.Operators.ItemChecked(terminator));
+      }
+
+      Terminators.Operators.Clear();
+
+      foreach (var newTerminator in newTerminators)
+        Terminators.Operators.Add(newTerminator.Key, newTerminator.Value);
+    }
+    protected virtual void CreateTerminators() {
+      evaluationsTerminator = new ComparisonTerminator<IntValue>("EvaluatedSolutions", ComparisonType.Less, new IntValue(int.MaxValue)) { Name = "Evaluations" };
+      qualityTerminator = new SingleObjectiveQualityTerminator() { Name = "Quality" };
+      executionTimeTerminator = new ExecutionTimeTerminator(this, new TimeSpanValue(TimeSpan.FromMinutes(5)));
+    }
     #endregion
   }
Index: /branches/ALPS/HeuristicLab.Algorithms.ALPS/3.3/AlpsGeneticAlgorithm.cs
===================================================================
--- /branches/ALPS/HeuristicLab.Algorithms.ALPS/3.3/AlpsGeneticAlgorithm.cs	(revision 12530)
+++ /branches/ALPS/HeuristicLab.Algorithms.ALPS/3.3/AlpsGeneticAlgorithm.cs	(revision 12531)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Common;
@@ -43,7 +44,4 @@
       get { return (IValueParameter<IntArray>)Parameters["PopulationSize"]; }
     }
-    private IValueParameter<IntValue> MaximumGenerationsParameter {
-      get { return (IValueParameter<IntValue>)Parameters["MaximumGenerations"]; }
-    }
     public IConstrainedValueParameter<ISelector> SelectorParameter {
       get { return (IConstrainedValueParameter<ISelector>)Parameters["Selector"]; }
@@ -74,9 +72,4 @@
       set { PopulationSizeParameter.Value = value; }
     }
-    public IntValue MaximumGenerations {
-      get { return MaximumGenerationsParameter.Value; }
-      set { MaximumGenerationsParameter.Value = value; }
-    }
-
     public ISelector Selector {
       get { return SelectorParameter.Value; }
@@ -112,4 +105,7 @@
     }
     #endregion
+
+    [Storable]
+    private ComparisonTerminator<IntValue> generationsTerminator;
 
     [StorableConstructor]
@@ -118,4 +114,5 @@
     private AlpsGeneticAlgorithm(AlpsGeneticAlgorithm original, Cloner cloner)
       : base(original, cloner) {
+      generationsTerminator = cloner.Clone(original.generationsTerminator);
       Initialize();
     }
@@ -126,5 +123,4 @@
       : base() {
       Parameters.Add(new ValueParameter<IntArray>("PopulationSize", "The size of the population of solutions each layer.", new IntArray(new[] { 100 })));
-      Parameters.Add(new ValueParameter<IntValue>("MaximumGenerations", "The maximum number of generations that should be processed.", new IntValue(1000)));
       Parameters.Add(new ConstrainedValueParameter<ISelector>("Selector", "The operator used to select solutions for reproduction."));
       Parameters.Add(new ConstrainedValueParameter<ICrossover>("Crossover", "The operator used to cross solutions."));
@@ -274,5 +270,5 @@
           @operator.IterationsParameter.ActualName = "Generations";
           @operator.IterationsParameter.Hidden = true;
-          @operator.MaximumIterationsParameter.ActualName = MaximumGenerationsParameter.Name;
+          @operator.MaximumIterationsParameter.ActualName = generationsTerminator.ThresholdParameter.Name;
           @operator.MaximumIterationsParameter.Hidden = true;
         }
@@ -291,4 +287,18 @@
 
     #region Updates
+    protected override void UpdateTerminators() {
+      var newTerminators = new Dictionary<ITerminator, bool> {
+        {generationsTerminator, !Terminators.Operators.Contains(generationsTerminator) || Terminators.Operators.ItemChecked(generationsTerminator)},
+      };
+
+      base.UpdateTerminators();
+
+      foreach (var newTerminator in newTerminators)
+        Terminators.Operators.Insert(0, newTerminator.Key, newTerminator.Value);
+    }
+    protected override void CreateTerminators() {
+      generationsTerminator = new ComparisonTerminator<IntValue>("Generations", ComparisonType.Less, new IntValue(1000)) { Name = "Generations" };
+      base.CreateTerminators();
+    }
     private void UpdateCrossovers() {
       var oldCrossover = CrossoverParameter.Value;
Index: /branches/ALPS/HeuristicLab.Algorithms.ALPS/3.3/AlpsGeneticAlgorithmMainLoop.cs
===================================================================
--- /branches/ALPS/HeuristicLab.Algorithms.ALPS/3.3/AlpsGeneticAlgorithmMainLoop.cs	(revision 12530)
+++ /branches/ALPS/HeuristicLab.Algorithms.ALPS/3.3/AlpsGeneticAlgorithmMainLoop.cs	(revision 12531)
@@ -100,6 +100,5 @@
       var layerAnalyzerPlaceholder = new Placeholder() { Name = "LayerAnalyzer (Placeholder)" };
       var analyzerPlaceholder = new Placeholder() { Name = "Analyzer (Placeholder)" };
-      var generationsComparator = new Comparator() { Name = "Generations >= MaximumGenerations" };
-      var terminateBranch = new ConditionalBranch() { Name = "Terminate?" };
+      var termination = new TerminationOperator();
 
       OperatorGraph.InitialOperator = variableCreator;
@@ -165,14 +164,7 @@
 
       analyzerPlaceholder.OperatorParameter.ActualName = AnalyzerParameter.Name;
-      analyzerPlaceholder.Successor = generationsComparator;
-
-      generationsComparator.Comparison = new Comparison(ComparisonType.GreaterOrEqual);
-      generationsComparator.LeftSideParameter.ActualName = "Generations";
-      generationsComparator.RightSideParameter.ActualName = MaximumGenerationsParameter.Name;
-      generationsComparator.ResultParameter.ActualName = "TerminateGenerations";
-      generationsComparator.Successor = terminateBranch;
-
-      terminateBranch.ConditionParameter.ActualName = "TerminateGenerations";
-      terminateBranch.FalseBranch = matingPoolPreProcessor;
+      analyzerPlaceholder.Successor = termination;
+
+      termination.ContinueBranch = matingPoolPreProcessor;
     }
 
