Index: branches/gp-crossover/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs
===================================================================
--- branches/gp-crossover/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs	(revision 7105)
+++ branches/gp-crossover/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs	(revision 7106)
@@ -24,4 +24,5 @@
 using System.Linq;
 using System.Text;
+using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Common;
@@ -34,8 +35,37 @@
   [Item("SemanticSimilarityCrossover", "An operator which performs subtree swapping based on semantic similarity.")]
   public sealed class SymbolicDataAnalysisExpressionSemanticSimilarityCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
+    private const string SemanticSimilarityLowerBoundParameterName = "SemanticSimilarityLowerBound";
+    private const string SemanticSimilarityUpperBoundParameterName = "SemanticSimilarityUpperBound";
+
+    #region Parameter properties
+    public IValueParameter<DoubleValue> SemanticSimilarityLowerBoundParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters[SemanticSimilarityLowerBoundParameterName]; }
+    }
+    public IValueParameter<DoubleValue> SemanticSimilarityUpperBoundParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters[SemanticSimilarityUpperBoundParameterName]; }
+    }
+    #endregion
+
+    #region Properties
+    public DoubleValue SemanticSimilarityLowerBound {
+      get { return SemanticSimilarityLowerBoundParameter.Value; }
+    }
+    public DoubleValue SemanticSimilarityUpperBound {
+      get { return SemanticSimilarityUpperBoundParameter.Value; }
+    }
+    #endregion
+
     [StorableConstructor]
     private SymbolicDataAnalysisExpressionSemanticSimilarityCrossover(bool deserializing) : base(deserializing) { }
     private SymbolicDataAnalysisExpressionSemanticSimilarityCrossover(SymbolicDataAnalysisExpressionSemanticSimilarityCrossover<T> original, Cloner cloner) : base(original, cloner) { }
-    public SymbolicDataAnalysisExpressionSemanticSimilarityCrossover() : base() { }
+    public SymbolicDataAnalysisExpressionSemanticSimilarityCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DoubleValue>(SemanticSimilarityLowerBoundParameterName, "The lower bound of the semantic similarity interval."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>(SemanticSimilarityUpperBoundParameterName, "The lower bound of the semantic similarity interval."));
+
+      // Set some decent default values for the lower and upper bound parameters
+      SemanticSimilarityLowerBoundParameter.Value = new DoubleValue(0.0001);
+      SemanticSimilarityUpperBoundParameter.Value = new DoubleValue(10);
+    }
     public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicDataAnalysisExpressionSemanticSimilarityCrossover<T>(this, cloner); }
 
@@ -44,5 +74,5 @@
       IEnumerable<int> rows = GenerateRowsToEvaluate();
       T problemData = ProblemDataParameter.ActualValue;
-      return Cross(random, parent0, parent1, interpreter, problemData, rows, MaximumSymbolicExpressionTreeDepth.Value, MaximumSymbolicExpressionTreeLength.Value);
+      return Cross(random, parent0, parent1, interpreter, problemData, rows, MaximumSymbolicExpressionTreeDepth.Value, MaximumSymbolicExpressionTreeLength.Value, SemanticSimilarityLowerBoundParameter.Value.Value, SemanticSimilarityUpperBoundParameter.Value.Value);
     }
     /// <summary>
@@ -51,6 +81,6 @@
     /// </summary>
     public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1,
-                                                ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, T problemData, IEnumerable<int> rows, int maxDepth, int maxLength) {
-      List<CutPoint> crossoverPoints0 = new List<CutPoint>();
+                                                ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, T problemData, IEnumerable<int> rows, int maxDepth, int maxLength, double lower, double upper) {
+      var crossoverPoints0 = new List<CutPoint>();
       parent0.Root.ForEachNodePostfix((n) => {
         if (n.Subtrees.Any() && n != parent0.Root)
@@ -58,9 +88,9 @@
             crossoverPoints0.Add(new CutPoint(n, child));
       });
-      CutPoint crossoverPoint0 = crossoverPoints0[random.Next(crossoverPoints0.Count)];
+      var crossoverPoint0 = crossoverPoints0[random.Next(crossoverPoints0.Count)];
       int level = parent0.Root.GetBranchLevel(crossoverPoint0.Child);
       int length = parent0.Root.GetLength() - crossoverPoint0.Child.GetLength();
 
-      List<ISymbolicExpressionTreeNode> allowedBranches = new List<ISymbolicExpressionTreeNode>();
+      var allowedBranches = new List<ISymbolicExpressionTreeNode>();
       parent1.Root.ForEachNodePostfix((n) => {
         if (n.Subtrees.Any() && n != parent1.Root)
@@ -83,22 +113,25 @@
       var tree0 = CreateTreeFromNode(random, crossoverPoint0.Child, rootSymbol, startSymbol);
       IEnumerable<double> estimatedValues0 = interpreter.GetSymbolicExpressionTreeValues(tree0, dataset, rows);
-
+      crossoverPoint0.Child.Parent = crossoverPoint0.Parent; // restore parent
       ISymbolicExpressionTreeNode selectedBranch = null;
 
       // pick the first node that fulfills the semantic similarity conditions
       foreach (var node in allowedBranches) {
-        var tree1 = CreateTreeFromNode(random, node, startSymbol, rootSymbol);
+        var parent = node.Parent;
+        var tree1 = CreateTreeFromNode(random, node, startSymbol, rootSymbol); // this will affect node.Parent 
         IEnumerable<double> estimatedValues1 = interpreter.GetSymbolicExpressionTreeValues(tree1, dataset, rows);
+        node.Parent = parent; // restore parent
 
-        //double ssd = SSD(estimatedValues0, estimatedValues1);
         OnlineCalculatorError errorState;
         double ssd = OnlineMeanAbsoluteErrorCalculator.Calculate(estimatedValues0, estimatedValues1, out errorState);
 
-        // TODO: introduce parameters alpha and beta for establishing the interval boundaries. the best values need to be determined experimentally
-        if (0.0001 < ssd && ssd < 10) {
+        if (lower < ssd && ssd < upper) {
           selectedBranch = node;
           break;
         }
       }
+
+      if (selectedBranch == null)
+        return parent0;
 
       // perform the actual swap
