Index: branches/ALPS/HeuristicLab.Algorithms.ALPS.SteadyState/3.3/AlpsSsMover.cs
===================================================================
--- branches/ALPS/HeuristicLab.Algorithms.ALPS.SteadyState/3.3/AlpsSsMover.cs	(revision 12171)
+++ branches/ALPS/HeuristicLab.Algorithms.ALPS.SteadyState/3.3/AlpsSsMover.cs	(revision 12174)
@@ -34,4 +34,5 @@
   [StorableClass]
   public class AlpsSsMover : SingleSuccessorOperator, IStochasticOperator {
+    #region Parameter Properties
     private ILookupParameter<IntValue> LayerParameter {
       get { return (ILookupParameter<IntValue>)Parameters["Layer"]; }
@@ -40,6 +41,6 @@
       get { return (ILookupParameter<IntValue>)Parameters["TargetIndex"]; }
     }
-    private ILookupParameter<IntValue> PopulationSizeParameter {
-      get { return (ILookupParameter<IntValue>)Parameters["PopulationSize"]; }
+    private ILookupParameter<IntValue> LayerSizeParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["LayerSize"]; }
     }
     private ILookupParameter<IntValue> NumberOfLayersParameter {
@@ -55,4 +56,23 @@
       get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
     }
+    public IScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (ValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public IScopeTreeLookupParameter<IntValue> EvalsCreatedParameter {
+      get { return (IScopeTreeLookupParameter<IntValue>)Parameters["EvalsCreated"]; }
+    }
+    public IScopeTreeLookupParameter<IntValue> EvalsMovedQualityParameter {
+      get { return (IScopeTreeLookupParameter<IntValue>)Parameters["EvalsMoved"]; }
+    }
+    private ILookupParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
+    }
+    private ILookupParameter<IntArray> AgeLimitsParameter {
+      get { return (ILookupParameter<IntArray>)Parameters["AgeLimits"]; }
+    }
+    #endregion
 
     [StorableConstructor]
@@ -69,21 +89,37 @@
       Parameters.Add(new LookupParameter<IntValue>("Layer"));
       Parameters.Add(new LookupParameter<IntValue>("TargetIndex"));
-      Parameters.Add(new LookupParameter<IntValue>("PopulationSize"));
+      Parameters.Add(new LookupParameter<IntValue>("LayerSize"));
       Parameters.Add(new LookupParameter<IntValue>("NumberOfLayers"));
       Parameters.Add(new LookupParameter<IScope>("WorkingScope"));
       Parameters.Add(new LookupParameter<IScope>("Layers"));
       Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality"));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, otherwise false."));
+      Parameters.Add(new ScopeTreeLookupParameter<IntValue>("EvalsCreated"));
+      Parameters.Add(new ScopeTreeLookupParameter<IntValue>("EvalsMoved"));
+      Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions"));
+      Parameters.Add(new LookupParameter<IntArray>("AgeLimits"));
     }
 
     private int n;
     private int m;
+    private int evals;
+    private int popSize;
     private IScope layers;
     private IRandom rand;
+    private string qualityVariableName;
+    private IntArray ageLimits;
+    private bool maximization;
     public override IOperation Apply() {
       int i = LayerParameter.ActualValue.Value;
       int j = TargetIndexParameter.ActualValue.Value;
       n = NumberOfLayersParameter.ActualValue.Value;
-      m = PopulationSizeParameter.ActualValue.Value;
+      m = LayerSizeParameter.ActualValue.Value;
+      evals = EvaluatedSolutionsParameter.ActualValue.Value;
+      popSize = n * m;
       rand = RandomParameter.ActualValue;
+      qualityVariableName = QualityParameter.TranslatedName;
+      ageLimits = AgeLimitsParameter.ActualValue;
+      maximization = MaximizationParameter.ActualValue.Value;
 
       layers = LayersParameter.ActualValue;
@@ -110,5 +146,28 @@
       }
     }
-    private int? FindReplaceable(IScope layer, IScope individual) {
+    private int? FindReplaceable(IScope layer, IScope individualToReplace) {
+      int layerNumber = ((IntValue)layer.Variables["Layer"].Value).Value;
+
+      var individuals = (
+        from individual in layer.SubScopes
+        let quality = ((DoubleValue)individual.Variables[qualityVariableName].Value).Value
+        let evalsCreated = ((IntValue)individual.Variables["EvalsCreated"].Value).Value
+        let age = (evals - evalsCreated) / popSize
+        select new { individual, quality, age }
+        ).Select((x, index) => new { index, x.individual, x.quality, x.age })
+        .ToList();
+
+      var ageLimit = layerNumber < n - 1 ? ageLimits[layerNumber] : int.MaxValue;
+
+      var toOldIndividual = individuals.FirstOrDefault(x => x.age >= ageLimit);
+      if (toOldIndividual != null)
+        return toOldIndividual.index;
+
+      double replaceQuality = ((DoubleValue)individualToReplace.Variables[qualityVariableName].Value).Value;
+      var sortedIndividuals = maximization ? individuals.OrderBy(x => x.quality) : individuals.OrderByDescending(x => x.quality);
+      var worstIndividual = sortedIndividuals.FirstOrDefault(x => maximization ? x.quality < replaceQuality : x.quality > replaceQuality);
+      if (worstIndividual != null)
+        return worstIndividual.index;
+
       return Enumerable.Range(0, layer.SubScopes.Count).SampleRandom(rand);
     }
