Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAlleleFrequencyAnalyzer.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAlleleFrequencyAnalyzer.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAlleleFrequencyAnalyzer.cs	(revision 11009)
@@ -75,5 +75,4 @@
     public static Allele[] CalculateAlleles(ISymbolicExpressionTree solution, int alleleTreedepth) {
       return GetAllSubtreesOfDepth(solution, alleleTreedepth)
-        .AsParallel()
         .Select(t => GetAlleleFromSubtreeOfDepth(t, alleleTreedepth))
         .ToArray();
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveValidationBestSolutionAnalyzer.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveValidationBestSolutionAnalyzer.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveValidationBestSolutionAnalyzer.cs	(revision 11009)
@@ -121,5 +121,4 @@
 
       var qualities = tree
-        .AsParallel()
         .Select(t => evaluator.Evaluate(childContext, t, problemData, rows))
         .ToArray();
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs	(revision 11009)
@@ -148,4 +148,5 @@
       if (end > count) end = count;
 
+      if (PopulationSlice.Start > 1 || PopulationSlice.End > 1) throw new ArgumentOutOfRangeException("The slice bounds should be expressed as unit percentages.");
       if (start >= end) throw new ArgumentOutOfRangeException("Invalid PopulationSlice bounds.");
       return new IntRange(start, end);
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer.cs	(revision 11009)
@@ -35,9 +35,13 @@
   [Item("SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer", "An operator that analyzes the training best symbolic data analysis solution for single objective symbolic data analysis problems.")]
   [StorableClass]
-  public abstract class SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer<T> : SymbolicDataAnalysisSingleObjectiveAnalyzer
+  public abstract class SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer<T> : SymbolicDataAnalysisSingleObjectiveAnalyzer, IIterationBasedOperator
+
     where T : class, ISymbolicDataAnalysisSolution {
     private const string TrainingBestSolutionParameterName = "Best training solution";
     private const string TrainingBestSolutionQualityParameterName = "Best training solution quality";
+    private const string TrainingBestSolutionGenerationParameterName = "Best training solution generation";
     private const string UpdateAlwaysParameterName = "Always update best solution";
+    private const string IterationsParameterName = "Iterations";
+    private const string MaximumIterationsParameterName = "Maximum Iterations";
 
     #region parameter properties
@@ -48,6 +52,15 @@
       get { return (ILookupParameter<DoubleValue>)Parameters[TrainingBestSolutionQualityParameterName]; }
     }
+    public ILookupParameter<IntValue> TrainingBestSolutionGenerationParameter {
+      get { return (ILookupParameter<IntValue>)Parameters[TrainingBestSolutionGenerationParameterName]; }
+    }
     public IFixedValueParameter<BoolValue> UpdateAlwaysParameter {
       get { return (IFixedValueParameter<BoolValue>)Parameters[UpdateAlwaysParameterName]; }
+    }
+    public ILookupParameter<IntValue> IterationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters[IterationsParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[MaximumIterationsParameterName]; }
     }
     #endregion
@@ -73,5 +86,8 @@
       Parameters.Add(new LookupParameter<T>(TrainingBestSolutionParameterName, "The training best symbolic data analyis solution."));
       Parameters.Add(new LookupParameter<DoubleValue>(TrainingBestSolutionQualityParameterName, "The quality of the training best symbolic data analysis solution."));
+      Parameters.Add(new LookupParameter<IntValue>(TrainingBestSolutionGenerationParameterName, "The generation in which the best training solution was found."));
       Parameters.Add(new FixedValueParameter<BoolValue>(UpdateAlwaysParameterName, "Determines if the best training solution should always be updated regardless of its quality.", new BoolValue(false)));
+      Parameters.Add(new LookupParameter<IntValue>(IterationsParameterName, "The number of performed iterations."));
+      Parameters.Add(new ValueLookupParameter<IntValue>(MaximumIterationsParameterName, "The maximum number of performed iterations.") { Hidden = true });
       UpdateAlwaysParameter.Hidden = true;
     }
@@ -83,4 +99,10 @@
         UpdateAlwaysParameter.Hidden = true;
       }
+      if (!Parameters.ContainsKey(TrainingBestSolutionGenerationParameterName))
+        Parameters.Add(new LookupParameter<IntValue>(TrainingBestSolutionGenerationParameterName, "The generation in which the best training solution was found."));
+      if (!Parameters.ContainsKey(IterationsParameterName))
+        Parameters.Add(new LookupParameter<IntValue>(IterationsParameterName, "The number of performed iterations."));
+      if (!Parameters.ContainsKey(MaximumIterationsParameterName))
+        Parameters.Add(new ValueLookupParameter<IntValue>(MaximumIterationsParameterName, "The maximum number of performed iterations.") { Hidden = true });
     }
 
@@ -104,11 +126,18 @@
         TrainingBestSolution = CreateSolution(bestTree, bestQuality);
         TrainingBestSolutionQuality = new DoubleValue(bestQuality);
+        if (IterationsParameter.ActualValue != null)
+          TrainingBestSolutionGenerationParameter.ActualValue = new IntValue(IterationsParameter.ActualValue.Value);
 
         if (!results.ContainsKey(TrainingBestSolutionParameter.Name)) {
           results.Add(new Result(TrainingBestSolutionParameter.Name, TrainingBestSolutionParameter.Description, TrainingBestSolution));
           results.Add(new Result(TrainingBestSolutionQualityParameter.Name, TrainingBestSolutionQualityParameter.Description, TrainingBestSolutionQuality));
+          if (TrainingBestSolutionGenerationParameter.ActualValue != null)
+            results.Add(new Result(TrainingBestSolutionGenerationParameter.Name, TrainingBestSolutionGenerationParameter.Description, TrainingBestSolutionGenerationParameter.ActualValue));
         } else {
           results[TrainingBestSolutionParameter.Name].Value = TrainingBestSolution;
           results[TrainingBestSolutionQualityParameter.Name].Value = TrainingBestSolutionQuality;
+          if (TrainingBestSolutionGenerationParameter.ActualValue != null)
+            results[TrainingBestSolutionGenerationParameter.Name].Value = TrainingBestSolutionGenerationParameter.ActualValue;
+
         }
       }
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationBestSolutionAnalyzer.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationBestSolutionAnalyzer.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationBestSolutionAnalyzer.cs	(revision 11009)
@@ -37,5 +37,5 @@
   [Item("SymbolicDataAnalysisSingleObjectiveValidationBestSolutionAnalyzer", "An operator that analyzes the validation best symbolic data analysis solution for single objective symbolic data analysis problems.")]
   [StorableClass]
-  public abstract class SymbolicDataAnalysisSingleObjectiveValidationBestSolutionAnalyzer<S, T, U> : SymbolicDataAnalysisSingleObjectiveValidationAnalyzer<T, U>
+  public abstract class SymbolicDataAnalysisSingleObjectiveValidationBestSolutionAnalyzer<S, T, U> : SymbolicDataAnalysisSingleObjectiveValidationAnalyzer<T, U>, IIterationBasedOperator
     where S : class, ISymbolicDataAnalysisSolution
     where T : class, ISymbolicDataAnalysisSingleObjectiveEvaluator<U>
@@ -43,5 +43,8 @@
     private const string ValidationBestSolutionParameterName = "Best validation solution";
     private const string ValidationBestSolutionQualityParameterName = "Best validation solution quality";
+    private const string ValidationBestSolutionGenerationParameterName = "Best validation solution generation";
     private const string UpdateAlwaysParameterName = "Always update best solution";
+    private const string IterationsParameterName = "Iterations";
+    private const string MaximumIterationsParameterName = "Maximum Iterations";
 
     #region parameter properties
@@ -52,6 +55,15 @@
       get { return (ILookupParameter<DoubleValue>)Parameters[ValidationBestSolutionQualityParameterName]; }
     }
+    public ILookupParameter<IntValue> ValidationBestSolutionGenerationParameter {
+      get { return (ILookupParameter<IntValue>)Parameters[ValidationBestSolutionGenerationParameterName]; }
+    }
     public IFixedValueParameter<BoolValue> UpdateAlwaysParameter {
       get { return (IFixedValueParameter<BoolValue>)Parameters[UpdateAlwaysParameterName]; }
+    }
+    public ILookupParameter<IntValue> IterationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters[IterationsParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[MaximumIterationsParameterName]; }
     }
     #endregion
@@ -77,5 +89,8 @@
       Parameters.Add(new LookupParameter<S>(ValidationBestSolutionParameterName, "The validation best symbolic data analyis solution."));
       Parameters.Add(new LookupParameter<DoubleValue>(ValidationBestSolutionQualityParameterName, "The quality of the validation best symbolic data analysis solution."));
+      Parameters.Add(new LookupParameter<IntValue>(ValidationBestSolutionGenerationParameterName, "The generation in which the best validation solution was found."));
       Parameters.Add(new FixedValueParameter<BoolValue>(UpdateAlwaysParameterName, "Determines if the best validation solution should always be updated regardless of its quality.", new BoolValue(false)));
+      Parameters.Add(new LookupParameter<IntValue>(IterationsParameterName, "The number of performed iterations."));
+      Parameters.Add(new ValueLookupParameter<IntValue>(MaximumIterationsParameterName, "The maximum number of performed iterations.") { Hidden = true });
       UpdateAlwaysParameter.Hidden = true;
     }
@@ -84,7 +99,13 @@
     private void AfterDeserialization() {
       if (!Parameters.ContainsKey(UpdateAlwaysParameterName)) {
-        Parameters.Add(new FixedValueParameter<BoolValue>(UpdateAlwaysParameterName, "Determines if the best training solution should always be updated regardless of its quality.", new BoolValue(false)));
+        Parameters.Add(new FixedValueParameter<BoolValue>(UpdateAlwaysParameterName, "Determines if the best validation solution should always be updated regardless of its quality.", new BoolValue(false)));
         UpdateAlwaysParameter.Hidden = true;
       }
+      if (!Parameters.ContainsKey(ValidationBestSolutionGenerationParameterName))
+        Parameters.Add(new LookupParameter<IntValue>(ValidationBestSolutionGenerationParameterName, "The generation in which the best validation solution was found."));
+      if (!Parameters.ContainsKey(IterationsParameterName))
+        Parameters.Add(new LookupParameter<IntValue>(IterationsParameterName, "The number of performed iterations."));
+      if (!Parameters.ContainsKey(MaximumIterationsParameterName))
+        Parameters.Add(new ValueLookupParameter<IntValue>(MaximumIterationsParameterName, "The maximum number of performed iterations.") { Hidden = true });
     }
 
@@ -121,5 +142,4 @@
       var quality = tree
         .Take(topN)
-        .AsParallel()
         .Select(t => evaluator.Evaluate(childContext, t, problemData, rows))
         .ToArray();
@@ -138,11 +158,17 @@
         ValidationBestSolution = CreateSolution(bestTree, bestValidationQuality);
         ValidationBestSolutionQuality = new DoubleValue(bestValidationQuality);
+        if (IterationsParameter.ActualValue != null)
+          ValidationBestSolutionGenerationParameter.ActualValue = new IntValue(IterationsParameter.ActualValue.Value);
 
         if (!results.ContainsKey(ValidationBestSolutionParameter.Name)) {
           results.Add(new Result(ValidationBestSolutionParameter.Name, ValidationBestSolutionParameter.Description, ValidationBestSolution));
           results.Add(new Result(ValidationBestSolutionQualityParameter.Name, ValidationBestSolutionQualityParameter.Description, ValidationBestSolutionQuality));
+          if (ValidationBestSolutionGenerationParameter.ActualValue != null)
+            results.Add(new Result(ValidationBestSolutionGenerationParameter.Name, ValidationBestSolutionGenerationParameter.Description, ValidationBestSolutionGenerationParameter.ActualValue));
         } else {
           results[ValidationBestSolutionParameter.Name].Value = ValidationBestSolution;
           results[ValidationBestSolutionQualityParameter.Name].Value = ValidationBestSolutionQuality;
+          if (ValidationBestSolutionGenerationParameter.ActualValue != null)
+            results[ValidationBestSolutionGenerationParameter.Name].Value = ValidationBestSolutionGenerationParameter.ActualValue;
         }
       }
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer.cs	(revision 11009)
@@ -120,5 +120,4 @@
         .Select(i => tree[i])
         .Take(topN)
-        .AsParallel()
         .Select(t => evaluator.Evaluate(childContext, t, problemData, rows))
         .ToArray();
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs	(revision 11009)
@@ -131,5 +131,4 @@
 
       var variableFrequencies = trees
-        .AsParallel()
         .SelectMany(t => GetVariableReferences(t, aggregateLaggedVariables))
         .GroupBy(pair => pair.Key, pair => pair.Value)
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs	(revision 11009)
@@ -99,4 +99,5 @@
       var or = new Or();
       var not = new Not();
+      var xor = new Xor();
 
       var timeLag = new TimeLag();
@@ -122,5 +123,5 @@
       var allSymbols = new List<Symbol>() { add, sub, mul, div, mean, sin, cos, tan, log, square, pow, sqrt, root, exp,
         airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, fresnelCosineIntegral, fresnelSineIntegral, gamma, hypCosineIntegral, hypSineIntegral, norm, psi, sineIntegral,
-        @if, gt, lt, and, or, not, timeLag, integral, derivative, constant, variableSymbol, laggedVariable,autoregressiveVariable, variableCondition };
+        @if, gt, lt, and, or, not,xor, timeLag, integral, derivative, constant, variableSymbol, laggedVariable,autoregressiveVariable, variableCondition };
       var unaryFunctionSymbols = new List<Symbol>() { square, sqrt, sin, cos, tan, log, exp, not, timeLag, integral, derivative,
         airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, fresnelCosineIntegral, fresnelSineIntegral, gamma, hypCosineIntegral, hypSineIntegral, norm, psi, sineIntegral
@@ -128,5 +129,5 @@
 
       var binaryFunctionSymbols = new List<Symbol>() { pow, root, gt, lt, variableCondition };
-      var ternarySymbols = new List<Symbol>() { add, sub, mul, div, mean, and, or };
+      var ternarySymbols = new List<Symbol>() { add, sub, mul, div, mean, and, or, xor };
       var terminalSymbols = new List<Symbol>() { variableSymbol, constant, laggedVariable, autoregressiveVariable };
 
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs	(revision 11009)
@@ -93,4 +93,5 @@
       var or = new Or();
       var not = new Not();
+      var xor = new Xor();
       var variableCondition = new VariableCondition();
 
@@ -120,5 +121,5 @@
       var conditionSymbols = new GroupSymbol(ConditionsName, new List<ISymbol> { @if, variableCondition });
       var comparisonSymbols = new GroupSymbol(ComparisonsName, new List<ISymbol> { gt, lt });
-      var booleanOperationSymbols = new GroupSymbol(BooleanOperatorsName, new List<ISymbol> { and, or, not });
+      var booleanOperationSymbols = new GroupSymbol(BooleanOperatorsName, new List<ISymbol> { and, or, not, xor });
       var conditionalSymbols = new GroupSymbol(ConditionalSymbolsName, new List<ISymbol> { conditionSymbols, comparisonSymbols, booleanOperationSymbols });
 
@@ -148,4 +149,5 @@
       SetSubtreeCount(or, 2, 2);
       SetSubtreeCount(not, 1, 1);
+      SetSubtreeCount(xor, 2, 2);
 
       SetSubtreeCount(timeLag, 1, 1);
@@ -237,4 +239,5 @@
       Symbols.First(s => s is Average).Enabled = false;
       Symbols.First(s => s is VariableCondition).Enabled = false;
+      Symbols.First(s => s is Xor).Enabled = false;
       Symbols.First(s => s.Name == TrigonometricFunctionsName).Enabled = false;
       Symbols.First(s => s.Name == ExponentialFunctionsName).Enabled = false;
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 11009)
@@ -126,4 +126,10 @@
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Matching\SymbolicExpressionTreeCanonicalSorter.cs" />
+    <Compile Include="Matching\SymbolicExpressionTreeEqualityComparer.cs" />
+    <Compile Include="Matching\SymbolicExpressionTreeMatching.cs" />
+    <Compile Include="Matching\SymbolicExpressionTreeMaxCommonSequenceCalculator.cs" />
+    <Compile Include="Matching\SymbolicExpressionTreeNodeComparer.cs" />
+    <Compile Include="Matching\SymbolicExpressionTreeNodeSimilarityComparer.cs" />
     <Compile Include="SymbolicExpressionTreeBacktransformator.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionPruningOperator.cs" />
@@ -181,4 +187,5 @@
     <Compile Include="Symbols\AiryB.cs" />
     <Compile Include="Symbols\Bessel.cs" />
+    <Compile Include="Symbols\Xor.cs" />
     <Compile Include="Symbols\Erf.cs" />
     <Compile Include="Symbols\Norm.cs" />
@@ -324,4 +331,5 @@
       <Project>{2e257a94-d1af-435c-99b4-5ac00eadfd6a}</Project>
       <Name>HeuristicLab.Problems.DataAnalysis.Transformations-3.4</Name>
+      <Private>False</Private>
     </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Problems.DataAnalysis\3.4\HeuristicLab.Problems.DataAnalysis-3.4.csproj">
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 11009)
@@ -46,4 +46,5 @@
     public const byte OR = 14;
     public const byte NOT = 15;
+    public const byte XOR = 45;
 
 
@@ -99,4 +100,5 @@
       { typeof(Or), OpCodes.OR },
       { typeof(Not), OpCodes.NOT},
+      { typeof(Xor),OpCodes.XOR},
       { typeof(Average), OpCodes.Average},
       { typeof(InvokeFunction), OpCodes.Call },
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 11009)
@@ -447,4 +447,21 @@
             il.Emit(System.Reflection.Emit.OpCodes.Sub);
             il.Emit(System.Reflection.Emit.OpCodes.Neg); // * -1
+            return;
+          }
+        case OpCodes.XOR: {
+            CompileInstructions(il, state, ds);
+            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
+            il.Emit(System.Reflection.Emit.OpCodes.Cgt);// > 0
+
+            for (int i = 1; i < nArgs; i++) {
+              CompileInstructions(il, state, ds);
+              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
+              il.Emit(System.Reflection.Emit.OpCodes.Cgt);// > 0
+              il.Emit(System.Reflection.Emit.OpCodes.Xor);
+            }
+            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
+            il.Emit(System.Reflection.Emit.OpCodes.Mul);
+            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // - 1
+            il.Emit(System.Reflection.Emit.OpCodes.Sub);
             return;
           }
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 11009)
@@ -344,4 +344,13 @@
             return Evaluate(dataset, ref row, state) > 0.0 ? -1.0 : 1.0;
           }
+        case OpCodes.XOR: {
+            //mkommend: XOR on multiple inputs is defined as true if the number of positive signals is odd
+            // this is equal to a consecutive execution of binary XOR operations.
+            int positiveSignals = 0;
+            for (int i = 0; i < currentInstr.nArguments; i++) {
+              if (Evaluate(dataset, ref row, state) > 0.0) positiveSignals++;
+            }
+            return positiveSignals % 2 != 0 ? 1.0 : -1.0;
+          }
         case OpCodes.GT: {
             double x = Evaluate(dataset, ref row, state);
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 10980)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 11009)
@@ -311,4 +311,10 @@
         } else if (instr.opCode == OpCodes.NOT) {
           instr.value = code[instr.childIndex].value > 0.0 ? -1.0 : 1.0;
+        } else if (instr.opCode == OpCodes.XOR) {
+          int positiveSignals = 0;
+          for (int j = 0; j < instr.nArguments; j++) {
+            if (code[instr.childIndex + j].value > 0.0) positiveSignals++;
+          }
+          instr.value = positiveSignals % 2 != 0 ? 1.0 : -1.0;
         } else if (instr.opCode == OpCodes.GT) {
           double x = code[instr.childIndex].value;
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeCanonicalSorter.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeCanonicalSorter.cs	(revision 11009)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeCanonicalSorter.cs	(revision 11009)
@@ -0,0 +1,30 @@
+﻿
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public class SymbolicExpressionTreeCanonicalSorter {
+    private readonly HashSet<Type> nonSymmetricSymbols = new HashSet<Type> { typeof(Subtraction), typeof(Division) };
+
+    public void SortSubtrees(ISymbolicExpressionTree tree) {
+      SortSubtrees(tree.Root);
+    }
+
+    public void SortSubtrees(ISymbolicExpressionTreeNode node) {
+      if (node.SubtreeCount == 0) return;
+      var subtrees = node.Subtrees as List<ISymbolicExpressionTreeNode> ?? node.Subtrees.ToList();
+      if (IsSymmetric(node.Symbol)) {
+        var comparer = new SymbolicExpressionTreeNodeComparer();
+        subtrees.Sort(comparer);
+      }
+      foreach (var s in subtrees)
+        SortSubtrees(s);
+    }
+
+    private bool IsSymmetric(ISymbol s) {
+      return !nonSymmetricSymbols.Contains(s.GetType());
+    }
+  }
+}
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeEqualityComparer.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeEqualityComparer.cs	(revision 11009)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeEqualityComparer.cs	(revision 11009)
@@ -0,0 +1,19 @@
+﻿using System;
+using System.Collections.Generic;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public class SymbolicExpressionTreeEqualityComparer : IEqualityComparer<ISymbolicExpressionTree> {
+    public SymbolicExpressionTreeNodeSimilarityComparer SimilarityComparer { get; set; }
+
+    public bool Equals(ISymbolicExpressionTree a, ISymbolicExpressionTree b) {
+      if (SimilarityComparer == null) throw new Exception("SimilarityComparer needs to be initialized first.");
+      return a.Length == b.Length &&
+             SymbolicExpressionTreeMatching.Match(a.Root, b.Root, SimilarityComparer) == Math.Min(a.Length, b.Length);
+    }
+
+    public int GetHashCode(ISymbolicExpressionTree tree) {
+      return (tree.Length << 8) % 12345;
+    }
+  }
+}
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMatching.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMatching.cs	(revision 11009)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMatching.cs	(revision 11009)
@@ -0,0 +1,48 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+//using HeuristicLab.EvolutionTracking;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public static class SymbolicExpressionTreeMatching {
+    public static bool ContainsSubtree(this ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode subtree, SymbolicExpressionTreeNodeSimilarityComparer comparer) {
+      return FindMatches(root, subtree, comparer).Any();
+    }
+    public static IEnumerable<ISymbolicExpressionTreeNode> FindMatches(ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode subtree, SymbolicExpressionTreeNodeSimilarityComparer comparer) {
+      return FindMatches(tree.Root, subtree, comparer);
+    }
+
+    public static IEnumerable<ISymbolicExpressionTreeNode> FindMatches(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode subtree, SymbolicExpressionTreeNodeSimilarityComparer comp) {
+      var fragmentLength = subtree.GetLength();
+      // below, we use ">=" for Match(n, subtree, comp) >= fragmentLength because in case of relaxed conditions, 
+      // we can have multiple matches of the same node
+
+      return root.IterateNodesBreadth().Where(n => n.GetLength() >= fragmentLength && Match(n, subtree, comp) == fragmentLength);
+    }
+
+    ///<summary>
+    /// Finds the longest common subsequence in quadratic time and linear space
+    /// Variant of:
+    /// D. S. Hirschberg. A linear space algorithm for or computing maximal common subsequences. 1975.
+    /// http://dl.acm.org/citation.cfm?id=360861
+    /// </summary>
+    /// <returns>Number of pairs that were matched</returns>
+    public static int Match(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b, SymbolicExpressionTreeNodeSimilarityComparer comp) {
+      if (!comp.Equals(a, b)) return 0;
+      int m = a.SubtreeCount;
+      int n = b.SubtreeCount;
+      if (m == 0 || n == 0) return 1;
+      var matrix = new int[m + 1, n + 1];
+      for (int i = 1; i <= m; ++i) {
+        var ai = a.GetSubtree(i - 1);
+        for (int j = 1; j <= n; ++j) {
+          var bj = b.GetSubtree(j - 1);
+          int match = Match(ai, bj, comp);
+          matrix[i, j] = Math.Max(Math.Max(matrix[i, j - 1], matrix[i - 1, j]), matrix[i - 1, j - 1] + match);
+        }
+      }
+      return matrix[m, n] + 1;
+    }
+  }
+}
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMaxCommonSequenceCalculator.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMaxCommonSequenceCalculator.cs	(revision 11009)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMaxCommonSequenceCalculator.cs	(revision 11009)
@@ -0,0 +1,59 @@
+﻿using System;
+using System.Collections.Generic;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Matching {
+  public class MaxCommonSequenceCalculator<T, U>
+    where T : class
+    where U : IEqualityComparer<T> {
+
+    public U Comparer { get; set; }
+    private int[,] matrix;
+    private List<T> sequence;
+
+    /// <summary>
+    /// Calculate the maximal common subsequence between arrays a and b and return it
+    /// </summary>
+    /// <param name="a"></param>
+    /// <param name="b"></param>
+    /// <returns></returns>
+    public IEnumerable<T> Calculate(T[] a, T[] b) {
+      int m = a.Length;
+      int n = b.Length;
+
+      if (m == 0 || n == 0) return null;
+      sequence = new List<T>();
+      matrix = new int[m + 1, n + 1];
+
+      for (int i = 0; i <= m; ++i) {
+        for (int j = 0; j <= n; ++j) {
+          if (i == 0 || j == 0) {
+            matrix[i, j] = 0;
+          } else if (Comparer.Equals(a[i - 1], b[j - 1])) {
+            matrix[i, j] = matrix[i - 1, j - 1] + 1;
+          } else {
+            matrix[i, j] = Math.Max(matrix[i - 1, j], matrix[i, j - 1]);
+          }
+        }
+      }
+      recon(a, b, n, m);
+      return sequence;
+    }
+
+    private void recon(T[] a, T[] b, int i, int j) {
+      while (true) {
+        if (i == 0 || j == 0) return;
+        if (Comparer.Equals(a[i - 1], b[j - 1])) {
+          recon(a, b, i - 1, j - 1);
+          sequence.Add(a[i - 1]);
+        } else if (matrix[i - 1, j] > matrix[i, j - 1]) {
+          i = i - 1;
+          continue;
+        } else {
+          j = j - 1;
+          continue;
+        }
+        break;
+      }
+    }
+  }
+}
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeNodeComparer.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeNodeComparer.cs	(revision 11009)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeNodeComparer.cs	(revision 11009)
@@ -0,0 +1,33 @@
+﻿using System;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  // this comparer considers that a < b if the type of a is "greater" than the type of b, for example:
+  // - A function node is "greater" than a terminal node
+  // - A variable terminal is "greater" than a constant terminal
+  // - used for bringing subtrees to a "canonical" form when the operation allows reordering of arguments
+  public class SymbolicExpressionTreeNodeComparer : ISymbolicExpressionTreeNodeComparer {
+    public int Compare(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (!(a is SymbolicExpressionTreeTerminalNode)) {
+        return b is SymbolicExpressionTreeTerminalNode
+          ? -1
+          : string.Compare(a.Symbol.Name, b.Symbol.Name, StringComparison.Ordinal);
+      }
+      if (!(b is SymbolicExpressionTreeTerminalNode)) return 1;
+      // at this point we know a and b are terminal nodes
+      var va = a as VariableTreeNode;
+      if (va != null) {
+        if (b is ConstantTreeNode) return -1;
+        var vb = (VariableTreeNode)b;
+        return (va.VariableName.Equals(vb.VariableName)
+          ? va.Weight.CompareTo(vb.Weight)
+          : string.Compare(va.VariableName, vb.VariableName, StringComparison.Ordinal));
+      }
+      // at this point we know for sure that a is a constant tree node
+      if (b is VariableTreeNode) return 1;
+      var ca = (ConstantTreeNode)a;
+      var cb = (ConstantTreeNode)b;
+      return ca.Value.CompareTo(cb.Value);
+    }
+  }
+}
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeNodeSimilarityComparer.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeNodeSimilarityComparer.cs	(revision 11009)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeNodeSimilarityComparer.cs	(revision 11009)
@@ -0,0 +1,76 @@
+﻿using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [Item("SymbolicExpressionTreeNodeSimilarityComparer", "A comparison operator that checks node equality based on different similarity measures.")]
+  [StorableClass]
+  public class SymbolicExpressionTreeNodeSimilarityComparer : Item, ISymbolicExpressionTreeNodeSimilarityComparer {
+    [StorableConstructor]
+    protected SymbolicExpressionTreeNodeSimilarityComparer(bool deserializing) : base(deserializing) { }
+    protected SymbolicExpressionTreeNodeSimilarityComparer(SymbolicExpressionTreeNodeSimilarityComparer original, Cloner cloner)
+      : base(original, cloner) {
+      matchConstantValues = original.matchConstantValues;
+      matchVariableNames = original.matchVariableNames;
+      matchVariableWeights = original.matchVariableWeights;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicExpressionTreeNodeSimilarityComparer(this, cloner); }
+
+    // more flexible matching criteria 
+    [Storable]
+    private bool matchConstantValues;
+    public bool MatchConstantValues {
+      get { return matchConstantValues; }
+      set { matchConstantValues = value; }
+    }
+
+    [Storable]
+    private bool matchVariableNames;
+    public bool MatchVariableNames {
+      get { return matchVariableNames; }
+      set { matchVariableNames = value; }
+    }
+
+    [Storable]
+    private bool matchVariableWeights;
+    public bool MatchVariableWeights {
+      get { return matchVariableWeights; }
+      set { matchVariableWeights = value; }
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+    }
+
+    public SymbolicExpressionTreeNodeSimilarityComparer() {
+      matchConstantValues = true;
+      matchVariableNames = true;
+      matchVariableWeights = true;
+    }
+
+    public int GetHashCode(ISymbolicExpressionTreeNode n) {
+      return n.ToString().ToLower().GetHashCode();
+    }
+
+    public bool Equals(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (!(a is SymbolicExpressionTreeTerminalNode))
+        // if a and b are non terminal nodes, check equality of symbol names
+        return !(b is SymbolicExpressionTreeTerminalNode) && a.Symbol.Name.Equals(b.Symbol.Name);
+      var va = a as VariableTreeNode;
+      if (va != null) {
+        var vb = b as VariableTreeNode;
+        if (vb == null) return false;
+
+        return (!MatchVariableNames || va.VariableName.Equals(vb.VariableName)) && (!MatchVariableWeights || va.Weight.Equals(vb.Weight));
+      }
+      var ca = a as ConstantTreeNode;
+      if (ca != null) {
+        var cb = b as ConstantTreeNode;
+        if (cb == null) return false;
+        return (!MatchConstantValues || ca.Value.Equals(cb.Value));
+      }
+      return false;
+    }
+  }
+}
Index: branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Xor.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Xor.cs	(revision 11009)
+++ branches/DataPreprocessing/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Xor.cs	(revision 11009)
@@ -0,0 +1,48 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("Xor", "Symbol that represents the boolean XOR operator.")]
+  public sealed class Xor : Symbol {
+    private const int minimumArity = 1;
+    private const int maximumArity = byte.MaxValue;
+
+    public override int MinimumArity {
+      get { return minimumArity; }
+    }
+    public override int MaximumArity {
+      get { return maximumArity; }
+    }
+
+    [StorableConstructor]
+    private Xor(bool deserializing) : base(deserializing) { }
+    private Xor(Xor original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Xor(this, cloner);
+    }
+    public Xor() : base("Xor", "Symbol that represents the boolean XOR operator.") { }
+  }
+}
