Index: trunk/HeuristicLab.Encodings.RealVectorEncoding/3.3/Crossovers/CopyCrossover.cs
===================================================================
--- trunk/HeuristicLab.Encodings.RealVectorEncoding/3.3/Crossovers/CopyCrossover.cs	(revision 18220)
+++ trunk/HeuristicLab.Encodings.RealVectorEncoding/3.3/Crossovers/CopyCrossover.cs	(revision 18220)
@@ -0,0 +1,46 @@
+﻿using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Encodings.RealVectorEncoding {
+  [Item("CopyCrossover", "This operator creates an offspring by creating a clone of a randomly chosen parent. It can be used in situations where no crossover should occur after selection.")]
+  [StorableType("4F639A12-9D80-457C-B098-19970BC37560")]
+  public class CopyCrossover : RealVectorCrossover {
+    [StorableConstructor]
+    protected CopyCrossover(StorableConstructorFlag _) : base(_) { }
+    protected CopyCrossover(CopyCrossover original, Cloner cloner) : base(original, cloner) { }
+    public CopyCrossover() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CopyCrossover(this, cloner);
+    }
+
+    /// <summary>
+    /// Performs the copy crossover.
+    /// </summary>
+    /// <remarks>
+    /// There can be more than two parents.
+    /// </remarks>
+    /// <param name="random">The random number generator.</param>
+    /// <param name="parents">The list of parents.</param>
+    /// <returns>The child vector, a copy of one of the parents.</returns>
+    public static RealVector Apply(IRandom random, ItemArray<RealVector> parents) {
+      int index = random.Next(parents.Length);
+      var selectedParent = parents[index];
+      var result = (RealVector)selectedParent.Clone();
+
+      return result;
+    }
+
+    /// <summary>
+    /// Forwards the call to <see cref="Apply(IRandom, ItemArray<RealVector>)"/>.
+    /// </summary>
+    /// <param name="random">The random number generator.</param>
+    /// <param name="parents">The list of parents.</param>
+    /// <returns>The child vector, a copy of one of the parents.</returns>
+    protected override RealVector Cross(IRandom random, ItemArray<RealVector> parents) {
+      return Apply(random, parents);
+    }
+  }
+}
+
Index: trunk/HeuristicLab.Encodings.RealVectorEncoding/3.3/Crossovers/MultiRealVectorCrossover.cs
===================================================================
--- trunk/HeuristicLab.Encodings.RealVectorEncoding/3.3/Crossovers/MultiRealVectorCrossover.cs	(revision 18211)
+++ trunk/HeuristicLab.Encodings.RealVectorEncoding/3.3/Crossovers/MultiRealVectorCrossover.cs	(revision 18220)
@@ -22,4 +22,5 @@
 using System;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Collections;
 using HeuristicLab.Common;
@@ -29,5 +30,4 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 using HeuristicLab.PluginInfrastructure;
 
@@ -67,6 +67,8 @@
 
       foreach (Type type in ApplicationManager.Manager.GetTypes(typeof(IRealVectorCrossover))) {
-        if (!typeof(MultiOperator<IRealVectorCrossover>).IsAssignableFrom(type))
-          Operators.Add((IRealVectorCrossover)Activator.CreateInstance(type), true);
+        if (typeof(MultiOperator<IRealVectorCrossover>).IsAssignableFrom(type)) continue;
+        if (typeof(CopyCrossover).IsAssignableFrom(type)) continue;
+
+        Operators.Add((IRealVectorCrossover)Activator.CreateInstance(type), true);
       }
 
Index: trunk/HeuristicLab.Encodings.RealVectorEncoding/3.3/HeuristicLab.Encodings.RealVectorEncoding-3.3.csproj
===================================================================
--- trunk/HeuristicLab.Encodings.RealVectorEncoding/3.3/HeuristicLab.Encodings.RealVectorEncoding-3.3.csproj	(revision 18211)
+++ trunk/HeuristicLab.Encodings.RealVectorEncoding/3.3/HeuristicLab.Encodings.RealVectorEncoding-3.3.csproj	(revision 18220)
@@ -115,4 +115,5 @@
   <ItemGroup>
     <Compile Include="Creators\NormalDistributedRealVectorCreator.cs" />
+    <Compile Include="Crossovers\CopyCrossover.cs" />
     <Compile Include="Interfaces\IRealVectorMultiNeighborhoodShakingOperator.cs" />
     <Compile Include="ParticleOperators\RealVectorNeighborhoodParticleUpdater.cs" />
Index: trunk/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/instruction.h
===================================================================
--- trunk/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/instruction.h	(revision 18211)
+++ trunk/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/instruction.h	(revision 18220)
@@ -29,4 +29,5 @@
     CubeRoot           = 51,
     Tanh               = 52,
+    SubFunction        = 53,
     Constant           = 54
 };
Index: trunk/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/interpreter.h
===================================================================
--- trunk/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/interpreter.h	(revision 18211)
+++ trunk/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/interpreter.h	(revision 18220)
@@ -139,4 +139,9 @@
                     break;
                 }
+            case OpCodes::SubFunction:
+                {
+                  in.value = code[in.childIndex].value;
+                  break;
+                }
             default: in.value = NAN;
         }
@@ -293,6 +298,12 @@
                     break;
                 }
+            case OpCodes::SubFunction:
+                {
+                  load(in.buf, code[in.childIndex].buf);
+                  break;
+                }
+
             default: load(in.buf, NAN);
-            }
+          }
     }
 }
Index: trunk/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCreator.cs
===================================================================
--- trunk/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCreator.cs	(revision 18211)
+++ trunk/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCreator.cs	(revision 18220)
@@ -28,5 +28,5 @@
 
 namespace HeuristicLab.Optimization {
-  [Item("MultiEncodingCreator", "Contains solution creators that together create a multi-encoding.")]
+  [Item("MultiEncoding Creator", "Contains solution creators that together create a multi-encoding.")]
   [StorableType("E261B506-6F74-4BC4-8164-5ACE20FBC319")]
   public sealed class MultiEncodingCreator : MultiEncodingOperator<ISolutionCreator>, ISolutionCreator, IStochasticOperator {
Index: trunk/HeuristicLab.Optimizer/3.3/HeuristicLab.Optimizer-3.3.csproj
===================================================================
--- trunk/HeuristicLab.Optimizer/3.3/HeuristicLab.Optimizer-3.3.csproj	(revision 18211)
+++ trunk/HeuristicLab.Optimizer/3.3/HeuristicLab.Optimizer-3.3.csproj	(revision 18220)
@@ -154,4 +154,5 @@
     <EmbeddedResource Include="Documents\OSGP_SymReg.hl" />
     <EmbeddedResource Include="Documents\GP_Shape_Constrained_Regression.hl" />
+    <EmbeddedResource Include="Documents\GP_Structure_Template_Regression.hl" />
     <None Include="Plugin.cs.frame" />
     <Compile Include="ChangeNestingLevelDialog.cs">
Index: trunk/HeuristicLab.Optimizer/3.3/StartPage.cs
===================================================================
--- trunk/HeuristicLab.Optimizer/3.3/StartPage.cs	(revision 18211)
+++ trunk/HeuristicLab.Optimizer/3.3/StartPage.cs	(revision 18220)
@@ -130,5 +130,6 @@
         };
       groupLookup[standardProblemsGroup] = standardProblems;
-      var dataAnalysisProblems = new List<string> { "ALPSGP_SymReg", "SGP_SymbClass", "SGP_SymbReg", "OSGP_SymReg", "OSGP_TimeSeries", "GE_SymbReg", "GPR", "GP_Shape_Constrained_Regression" };
+      var dataAnalysisProblems = new List<string> { "ALPSGP_SymReg", "SGP_SymbClass", "SGP_SymbReg", "OSGP_SymReg", "OSGP_TimeSeries", 
+                                                    "GE_SymbReg", "GPR", "GP_Shape_Constrained_Regression", "GP_Structure_Template_Regression" };
       groupLookup[dataAnalysisGroup] = dataAnalysisProblems;
       var scripts = new List<string> { "GA_QAP_Script", "GUI_Automation_Script", "OSGA_Rastrigin_Script",
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj	(revision 18220)
@@ -47,4 +47,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>default</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -57,4 +58,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>default</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
@@ -67,4 +69,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>default</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
@@ -77,4 +80,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>default</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
@@ -87,4 +91,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>default</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
@@ -97,4 +102,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>default</LangVersion>
   </PropertyGroup>
   <ItemGroup>
@@ -127,4 +133,5 @@
     <Compile Include="MultiObjective\ShapeConstrainedRegressionMultiObjectiveProblem.cs" />
     <Compile Include="MultiObjective\SymbolicRegressionMultiObjectiveValidationBestSolutionAnalyzer.cs" />
+    <Compile Include="ParameterOptimization.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="ShapeConstraintsAnalyzer.cs" />
@@ -135,4 +142,5 @@
     <Compile Include="SingleObjective\SolutionQualityAnalyzer.cs" />
     <Compile Include="SingleObjective\SolutionRSquaredAnalyzer.cs" />
+    <Compile Include="SingleObjective\StructureTemplateSymbolicRegressionProblem.cs" />
     <Compile Include="SymbolicRegressionPhenotypicDiversityAnalyzer.cs" />
     <Compile Include="SymbolicRegressionPruningAnalyzer.cs" />
@@ -212,4 +220,8 @@
       <Private>False</Private>
     </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.RealVectorEncoding\3.3\HeuristicLab.Encodings.RealVectorEncoding-3.3.csproj">
+      <Project>{BB6D334A-4BB6-4674-9883-31A6EBB32CAB}</Project>
+      <Name>HeuristicLab.Encodings.RealVectorEncoding-3.3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding\3.4\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.csproj">
       <Project>{06D4A186-9319-48A0-BADE-A2058D462EEA}</Project>
@@ -257,8 +269,16 @@
       <Private>False</Private>
     </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.Instances.DataAnalysis\3.3\HeuristicLab.Problems.Instances.DataAnalysis-3.3.csproj">
+      <Project>{94C7714E-29D4-4D6D-B213-2C18D627AB75}</Project>
+      <Name>HeuristicLab.Problems.Instances.DataAnalysis-3.3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Problems.Instances\3.3\HeuristicLab.Problems.Instances-3.3.csproj">
       <Project>{3540E29E-4793-49E7-8EE2-FEA7F61C3994}</Project>
       <Name>HeuristicLab.Problems.Instances-3.3</Name>
       <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Random\3.3\HeuristicLab.Random-3.3.csproj">
+      <Project>{f4539fb6-4708-40c9-be64-0a1390aea197}</Project>
+      <Name>HeuristicLab.Random-3.3</Name>
     </ProjectReference>
   </ItemGroup>
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/Interfaces/ISymbolicRegressionSingleObjectiveEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/Interfaces/ISymbolicRegressionSingleObjectiveEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/Interfaces/ISymbolicRegressionSingleObjectiveEvaluator.cs	(revision 18220)
@@ -1,3 +1,6 @@
-﻿using HEAL.Attic;
+﻿using System.Collections.Generic;
+using System.Linq;
+using HEAL.Attic;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 #region License Information
 /* HeuristicLab
@@ -24,4 +27,12 @@
   [StorableType("5dd2601a-b884-48c0-85bc-bc1f437187a3")]
   public interface ISymbolicRegressionSingleObjectiveEvaluator : ISymbolicRegressionEvaluator, ISymbolicDataAnalysisSingleObjectiveEvaluator<IRegressionProblemData> {
+    double Evaluate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling = true,
+      double lowerEstimationLimit = double.MinValue, 
+      double upperEstimationLimit = double.MaxValue);
   }
 }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredAverageSimilarityEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredAverageSimilarityEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredAverageSimilarityEvaluator.cs	(revision 18220)
@@ -70,5 +70,5 @@
     public override IOperation InstrumentedApply() {
       IEnumerable<int> rows = GenerateRowsToEvaluate();
-      var solution = SymbolicExpressionTreeParameter.ActualValue;
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
       var problemData = ProblemDataParameter.ActualValue;
       var interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
@@ -77,8 +77,10 @@
 
       if (UseParameterOptimization) {
-        SymbolicRegressionParameterOptimizationEvaluator.OptimizeParameters(interpreter, solution, problemData, rows, applyLinearScaling, ParameterOptimizationIterations, updateVariableWeights: ParameterOptimizationUpdateVariableWeights, lowerEstimationLimit: estimationLimits.Lower, upperEstimationLimit: estimationLimits.Upper);
+        SymbolicRegressionParameterOptimizationEvaluator.OptimizeParameters(interpreter, tree, problemData, rows, applyLinearScaling, ParameterOptimizationIterations, updateVariableWeights: ParameterOptimizationUpdateVariableWeights, lowerEstimationLimit: estimationLimits.Lower, upperEstimationLimit: estimationLimits.Upper);
       }
 
-      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, solution, estimationLimits.Lower, estimationLimits.Upper, problemData, rows, applyLinearScaling);
+      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+        tree, problemData, rows, interpreter, applyLinearScaling,
+        estimationLimits.Lower, estimationLimits.Upper);
 
       if (DecimalPlaces >= 0)
@@ -107,5 +109,9 @@
       var applyLinearScaling = ApplyLinearScalingParameter.ActualValue.Value;
 
-      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, estimationLimits.Lower, estimationLimits.Upper, problemData, rows, applyLinearScaling);
+      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+        tree, problemData, rows,
+        SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+        applyLinearScaling,
+        estimationLimits.Lower, estimationLimits.Upper);
 
       lock (locker) {
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredNestedTreeSizeEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredNestedTreeSizeEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredNestedTreeSizeEvaluator.cs	(revision 18220)
@@ -63,9 +63,12 @@
     }
 
-    public static double[] Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling, int decimalPlaces) {
-      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, solution, lowerEstimationLimit, upperEstimationLimit, problemData, rows, applyLinearScaling);
+    public static double[] Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree tree, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling, int decimalPlaces) {
+      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+         tree, problemData, rows, 
+         interpreter, applyLinearScaling, 
+         lowerEstimationLimit, upperEstimationLimit);
       if (decimalPlaces >= 0)
         r2 = Math.Round(r2, decimalPlaces);
-      return new double[2] { r2, solution.IterateNodesPostfix().Sum(n => n.GetLength()) }; // sum of the length of the whole sub-tree for each node 
+      return new double[2] { r2, tree.IterateNodesPostfix().Sum(n => n.GetLength()) }; // sum of the length of the whole sub-tree for each node 
     }
 
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredNumberOfVariablesEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredNumberOfVariablesEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredNumberOfVariablesEvaluator.cs	(revision 18220)
@@ -62,9 +62,11 @@
     }
 
-    public static double[] Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling, int decimalPlaces) {
-      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, solution, lowerEstimationLimit, upperEstimationLimit, problemData, rows, applyLinearScaling);
+    public static double[] Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree tree, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling, int decimalPlaces) {
+      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+        tree, problemData, rows, interpreter, applyLinearScaling,
+        lowerEstimationLimit, upperEstimationLimit);
       if (decimalPlaces >= 0)
         r2 = Math.Round(r2, decimalPlaces);
-      return new double[2] { r2, solution.IterateNodesPostfix().OfType<IVariableTreeNode>().Count() }; // count the number of variables
+      return new double[2] { r2, tree.IterateNodesPostfix().OfType<IVariableTreeNode>().Count() }; // count the number of variables
     }
 
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredTreeComplexityEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredTreeComplexityEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredTreeComplexityEvaluator.cs	(revision 18220)
@@ -61,9 +61,12 @@
     }
 
-    public static double[] Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling, int decimalPlaces) {
-      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, solution, lowerEstimationLimit, upperEstimationLimit, problemData, rows, applyLinearScaling);
+    public static double[] Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree tree, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling, int decimalPlaces) {
+      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+         tree, problemData, rows, 
+         interpreter, applyLinearScaling, 
+         lowerEstimationLimit, upperEstimationLimit);
       if (decimalPlaces >= 0)
         r2 = Math.Round(r2, decimalPlaces);
-      return new double[2] { r2, SymbolicDataAnalysisModelComplexityCalculator.CalculateComplexity(solution) };
+      return new double[2] { r2, SymbolicDataAnalysisModelComplexityCalculator.CalculateComplexity(tree) };
     }
 
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectiveMeanSquaredErrorTreeSizeEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectiveMeanSquaredErrorTreeSizeEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectiveMeanSquaredErrorTreeSizeEvaluator.cs	(revision 18220)
@@ -22,9 +22,9 @@
 using System;
 using System.Collections.Generic;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Data;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
@@ -47,5 +47,5 @@
     public override IOperation InstrumentedApply() {
       IEnumerable<int> rows = GenerateRowsToEvaluate();
-      var solution = SymbolicExpressionTreeParameter.ActualValue;
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
       var problemData = ProblemDataParameter.ActualValue;
       var interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
@@ -54,20 +54,36 @@
 
       if (UseParameterOptimization) {
-        SymbolicRegressionParameterOptimizationEvaluator.OptimizeParameters(interpreter, solution, problemData, rows, applyLinearScaling, ParameterOptimizationIterations, updateVariableWeights: ParameterOptimizationUpdateVariableWeights, lowerEstimationLimit: estimationLimits.Lower, upperEstimationLimit: estimationLimits.Upper);
+        SymbolicRegressionParameterOptimizationEvaluator.OptimizeParameters(interpreter, tree, problemData, rows, applyLinearScaling, ParameterOptimizationIterations, updateVariableWeights: ParameterOptimizationUpdateVariableWeights, lowerEstimationLimit: estimationLimits.Lower, upperEstimationLimit: estimationLimits.Upper);
       }
 
-      double[] qualities = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, rows, ApplyLinearScalingParameter.ActualValue.Value, DecimalPlaces);
+      double[] qualities = Calculate(
+        tree, ProblemDataParameter.ActualValue,
+        rows, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+        ApplyLinearScalingParameter.ActualValue.Value,
+        EstimationLimitsParameter.ActualValue.Lower,
+        EstimationLimitsParameter.ActualValue.Upper,
+        DecimalPlaces);
       QualitiesParameter.ActualValue = new DoubleArray(qualities);
       return base.InstrumentedApply();
     }
 
-    public static double[] Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling, int decimalPlaces) {
-      var mse = SymbolicRegressionSingleObjectiveMeanSquaredErrorEvaluator.Calculate(interpreter, solution, lowerEstimationLimit,
-        upperEstimationLimit, problemData, rows, applyLinearScaling);
+    public static double[] Calculate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling,
+      double lowerEstimationLimit, double upperEstimationLimit,
+      int decimalPlaces) {
+      var mse = SymbolicRegressionSingleObjectiveMeanSquaredErrorEvaluator.Calculate(
+        tree, problemData, rows,
+        interpreter, applyLinearScaling,
+        lowerEstimationLimit,
+        upperEstimationLimit);
 
       if (decimalPlaces >= 0)
         mse = Math.Round(mse, decimalPlaces);
 
-      return new double[2] { mse, solution.Length };
+      return new double[2] { mse, tree.Length };
     }
 
@@ -77,5 +93,10 @@
       ApplyLinearScalingParameter.ExecutionContext = context;
 
-      double[] quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, ApplyLinearScalingParameter.ActualValue.Value, DecimalPlaces);
+      double[] quality = Calculate(
+        tree, problemData, rows,
+        SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+        ApplyLinearScalingParameter.ActualValue.Value,
+        EstimationLimitsParameter.ActualValue.Lower,
+        EstimationLimitsParameter.ActualValue.Upper, DecimalPlaces);
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectivePearsonRSquaredTreeSizeEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectivePearsonRSquaredTreeSizeEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectivePearsonRSquaredTreeSizeEvaluator.cs	(revision 18220)
@@ -61,9 +61,11 @@
     }
 
-    public static double[] Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling, int decimalPlaces) {
-      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, solution, lowerEstimationLimit, upperEstimationLimit, problemData, rows, applyLinearScaling);
+    public static double[] Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree tree, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling, int decimalPlaces) {
+      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+        tree, problemData, rows, interpreter, applyLinearScaling,
+        lowerEstimationLimit, upperEstimationLimit);
       if (decimalPlaces >= 0)
         r2 = Math.Round(r2, decimalPlaces);
-      return new double[2] { r2, solution.Length };
+      return new double[2] { r2, tree.Length };
     }
 
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/ParameterOptimization.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/ParameterOptimization.cs	(revision 18220)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/ParameterOptimization.cs	(revision 18220)
@@ -0,0 +1,182 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 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 System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
+  public static class ParameterOptimization {
+    public static double OptimizeTreeParameters(IRegressionProblemData problemData, ISymbolicExpressionTree tree, int maxIterations = 10,
+      bool updateParametersInTree = true, bool updateVariableWeights = true, IEnumerable<ISymbolicExpressionTreeNode> excludeNodes = null,
+      double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue,
+      IEnumerable<int> rows = null, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter = null,
+      Action<double[], double, object> iterationCallback = null) {
+
+      if (rows == null) rows = problemData.TrainingIndices;
+      if (interpreter == null) interpreter = new SymbolicDataAnalysisExpressionTreeBatchInterpreter();
+      if (excludeNodes == null) excludeNodes = Enumerable.Empty<ISymbolicExpressionTreeNode>();
+
+      // Numeric parameters in the tree become variables for parameter optimization.
+      // Variables in the tree become parameters (fixed values) for parameter optimization.
+      // For each parameter (variable in the original tree) we store the 
+      // variable name, variable value (for factor vars) and lag as a DataForVariable object.
+      // A dictionary is used to find parameters
+      double[] initialParameters;
+      var parameters = new List<TreeToAutoDiffTermConverter.DataForVariable>();
+
+      TreeToAutoDiffTermConverter.ParametricFunction func;
+      TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad;
+      if (!TreeToAutoDiffTermConverter.TryConvertToAutoDiff(tree,
+        updateVariableWeights, addLinearScalingTerms: false, excludeNodes,
+        out parameters, out initialParameters, out func, out func_grad))
+        throw new NotSupportedException("Could not optimize parameters of symbolic expression tree due to not supported symbols used in the tree.");
+      var parameterEntries = parameters.ToArray(); // order of entries must be the same for x
+
+      // extract initial parameters
+      double[] c = (double[])initialParameters.Clone();
+      alglib.minlmreport rep;
+
+      double originalQuality = SymbolicRegressionSingleObjectiveMeanSquaredErrorEvaluator.Calculate(
+        tree, problemData, rows,
+        interpreter, applyLinearScaling: false,
+        lowerEstimationLimit, upperEstimationLimit);
+
+
+      IDataset ds = problemData.Dataset;
+      int n = rows.Count();
+      int k = parameters.Count;
+
+      double[,] x = new double[n, k];
+      int row = 0;
+      foreach (var r in rows) {
+        int col = 0;
+        foreach (var info in parameterEntries) {
+          if (ds.VariableHasType<double>(info.variableName)) {
+            x[row, col] = ds.GetDoubleValue(info.variableName, r + info.lag);
+          } else if (ds.VariableHasType<string>(info.variableName)) {
+            x[row, col] = ds.GetStringValue(info.variableName, r) == info.variableValue ? 1 : 0;
+          } else throw new InvalidProgramException("found a variable of unknown type");
+          col++;
+        }
+        row++;
+      }
+      double[] y = ds.GetDoubleValues(problemData.TargetVariable, rows).ToArray();
+
+      alglib.ndimensional_rep xrep = (p, f, obj) => iterationCallback(p, f, obj);
+
+      try {
+        alglib.minlmcreatevj(y.Length, c, out var lmstate);
+        alglib.minlmsetcond(lmstate, 0.0, maxIterations);
+        alglib.minlmsetxrep(lmstate, iterationCallback != null);
+        // alglib.minlmoptguardgradient(lmstate, 1e-5); // for debugging gradient calculation
+        alglib.minlmoptimize(lmstate, CreateFunc(func, x, y), CreateJac(func_grad, x, y), xrep, null);
+        alglib.minlmresults(lmstate, out c, out rep);
+        // alglib.minlmoptguardresults(lmstate, out var optGuardReport);
+      } catch (ArithmeticException) {
+        return originalQuality;
+      } catch (alglib.alglibexception) {
+        return originalQuality;
+      }
+
+
+      // * TerminationType, completion code:
+      //     * -8    optimizer detected NAN/INF values either in the function itself,
+      //             or in its Jacobian
+      //     * -5    inappropriate solver was used:
+      //             * solver created with minlmcreatefgh() used  on  problem  with
+      //               general linear constraints (set with minlmsetlc() call).
+      //     * -3    constraints are inconsistent
+      //     *  2    relative step is no more than EpsX.
+      //     *  5    MaxIts steps was taken
+      //     *  7    stopping conditions are too stringent,
+      //             further improvement is impossible
+      //     *  8    terminated   by  user  who  called  MinLMRequestTermination().
+      //             X contains point which was "current accepted" when termination
+      //             request was submitted.
+      if (rep.terminationtype > 0) {
+        UpdateParameters(tree, c, updateVariableWeights, excludeNodes);
+      }
+      var quality = SymbolicRegressionSingleObjectiveMeanSquaredErrorEvaluator.Calculate(
+        tree, problemData, rows,
+        interpreter, applyLinearScaling: false,
+        lowerEstimationLimit, upperEstimationLimit);
+
+      if (!updateParametersInTree) UpdateParameters(tree, initialParameters, updateVariableWeights, excludeNodes);
+
+      if (originalQuality < quality || double.IsNaN(quality)) {
+        UpdateParameters(tree, initialParameters, updateVariableWeights, excludeNodes);
+        return originalQuality;
+      }
+      return quality;
+    }
+
+    private static void UpdateParameters(ISymbolicExpressionTree tree, double[] parameters,
+      bool updateVariableWeights, IEnumerable<ISymbolicExpressionTreeNode> excludedNodes) {
+      int i = 0;
+      foreach (var node in tree.Root.IterateNodesPrefix().OfType<SymbolicExpressionTreeTerminalNode>().Except(excludedNodes)) {
+        NumberTreeNode numberTreeNode = node as NumberTreeNode;
+        VariableTreeNodeBase variableTreeNodeBase = node as VariableTreeNodeBase;
+        FactorVariableTreeNode factorVarTreeNode = node as FactorVariableTreeNode;
+        if (numberTreeNode != null) {
+          if (numberTreeNode.Parent.Symbol is Power
+              && numberTreeNode.Parent.GetSubtree(1) == numberTreeNode) continue; // exponents in powers are not optimized (see TreeToAutoDiffTermConverter)
+          numberTreeNode.Value = parameters[i++];
+        } else if (updateVariableWeights && variableTreeNodeBase != null)
+          variableTreeNodeBase.Weight = parameters[i++];
+        else if (updateVariableWeights && factorVarTreeNode != null) {
+          for (int j = 0; j < factorVarTreeNode.Weights.Length; j++)
+            factorVarTreeNode.Weights[j] = parameters[i++];
+        }
+      }
+    }
+
+    private static alglib.ndimensional_fvec CreateFunc(TreeToAutoDiffTermConverter.ParametricFunction func, double[,] x, double[] y) {
+      int d = x.GetLength(1);
+      // row buffer
+      var xi = new double[d];
+      // function must return residuals, alglib optimizes resid²
+      return (double[] c, double[] resid, object o) => {
+        for (int i = 0; i < y.Length; i++) {
+          Buffer.BlockCopy(x, i * d * sizeof(double), xi, 0, d * sizeof(double)); // copy row. We are using BlockCopy instead of Array.Copy because x has rank 2
+          resid[i] = func(c, xi) - y[i];
+        }
+      };
+    }
+
+    private static alglib.ndimensional_jac CreateJac(TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad, double[,] x, double[] y) {
+      int numParams = x.GetLength(1);
+      // row buffer
+      var xi = new double[numParams];
+      return (double[] c, double[] resid, double[,] jac, object o) => {
+        int numVars = c.Length;
+        for (int i = 0; i < y.Length; i++) {
+          Buffer.BlockCopy(x, i * numParams * sizeof(double), xi, 0, numParams * sizeof(double)); // copy row
+          var tuple = func_grad(c, xi);
+          resid[i] = tuple.Item2 - y[i];
+          Buffer.BlockCopy(tuple.Item1, 0, jac, i * numVars * sizeof(double), numVars * sizeof(double)); // copy the gradient to jac. BlockCopy because jac has rank 2.
+        }
+      };
+    }
+
+  }
+}
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/Plugin.cs.frame
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/Plugin.cs.frame	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/Plugin.cs.frame	(revision 18220)
@@ -34,5 +34,6 @@
   [PluginDependency("HeuristicLab.Core", "3.3")]
   [PluginDependency("HeuristicLab.Data", "3.3")]
-  [PluginDependency("HeuristicLab.Encodings.SymbolicExpressionTreeEncoding", "3.4")]
+  [PluginDependency("HeuristicLab.Encodings.RealVectorEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.SymbolicExpressionTreeEncoding", "3.4")]  
   [PluginDependency("HeuristicLab.Operators", "3.3")]
   [PluginDependency("HeuristicLab.Optimization", "3.3")]
@@ -41,4 +42,6 @@
   [PluginDependency("HeuristicLab.Problems.DataAnalysis", "3.4")]
   [PluginDependency("HeuristicLab.Problems.DataAnalysis.Symbolic", "3.4")]
+  [PluginDependency("HeuristicLab.Problems.Instances", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.Instances.DataAnalysis", "3.3")]
   public class HeuristicLabProblemsDataAnalysisSymbolicRegressionPlugin : PluginBase {
   }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NMSESingleObjectiveConstraintsEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NMSESingleObjectiveConstraintsEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NMSESingleObjectiveConstraintsEvaluator.cs	(revision 18220)
@@ -125,44 +125,5 @@
       var applyLinearScaling = ApplyLinearScalingParameter.ActualValue.Value;
 
-      if (OptimizeParameters) {
-        SymbolicRegressionParameterOptimizationEvaluator.OptimizeParameters(interpreter, tree, problemData, rows,
-          false, ParameterOptimizationIterations, true,
-          estimationLimits.Lower, estimationLimits.Upper);
-      } else {
-        if (applyLinearScaling) {
-          var rootNode = new ProgramRootSymbol().CreateTreeNode();
-          var startNode = new StartSymbol().CreateTreeNode();
-          var offset = tree.Root.GetSubtree(0) //Start
-                                .GetSubtree(0); //Offset
-          var scaling = offset.GetSubtree(0);
-
-          //Check if tree contains offset and scaling nodes
-          if (!(offset.Symbol is Addition) || !(scaling.Symbol is Multiplication))
-            throw new ArgumentException($"{ItemName} can only be used with LinearScalingGrammar.");
-
-          var t = (ISymbolicExpressionTreeNode)scaling.GetSubtree(0).Clone();
-          rootNode.AddSubtree(startNode);
-          startNode.AddSubtree(t);
-          var newTree = new SymbolicExpressionTree(rootNode);
-
-          //calculate alpha and beta for scaling
-          var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(newTree, problemData.Dataset, rows);
-
-          var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
-          OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out var alpha, out var beta,
-            out var errorState);
-
-          if (errorState == OnlineCalculatorError.None) {
-            //Set alpha and beta to the scaling nodes from ia grammar
-            var offsetParameter = offset.GetSubtree(1) as NumberTreeNode;
-            offsetParameter.Value = alpha;
-            var scalingParameter = scaling.GetSubtree(1) as NumberTreeNode;
-            scalingParameter.Value = beta;
-          }
-        } // else: alpha and beta are evolved
-      }
-
-      var quality = Calculate(interpreter, tree, estimationLimits.Lower, estimationLimits.Upper, problemData, rows,
-        BoundsEstimator, UseSoftConstraints, PenalityFactor);
+      var quality = Evaluate(tree, problemData, rows, interpreter, applyLinearScaling, estimationLimits.Lower, estimationLimits.Upper);
       QualityParameter.ActualValue = new DoubleValue(quality);
 
@@ -170,48 +131,85 @@
     }
 
+    private static void CalcLinearScalingTerms(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter) {
+      var rootNode = new ProgramRootSymbol().CreateTreeNode();
+      var startNode = new StartSymbol().CreateTreeNode();
+      var offset = tree.Root.GetSubtree(0) //Start
+                            .GetSubtree(0); //Offset
+      var scaling = offset.GetSubtree(0);
+
+      //Check if tree contains offset and scaling nodes
+      if (!(offset.Symbol is Addition) || !(scaling.Symbol is Multiplication))
+        throw new ArgumentException($"Scaling can only be used with LinearScalingGrammar.");
+
+      var t = (ISymbolicExpressionTreeNode)scaling.GetSubtree(0).Clone();
+      rootNode.AddSubtree(startNode);
+      startNode.AddSubtree(t);
+      var newTree = new SymbolicExpressionTree(rootNode);
+
+      //calculate alpha and beta for scaling
+      var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(newTree, problemData.Dataset, rows);
+
+      var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out var alpha, out var beta,
+        out var errorState);
+
+      if (errorState == OnlineCalculatorError.None) {
+        //Set alpha and beta to the scaling nodes from grammar
+        var offsetParameter = offset.GetSubtree(1) as NumberTreeNode;
+        offsetParameter.Value = alpha;
+        var scalingParameter = scaling.GetSubtree(1) as NumberTreeNode;
+        scalingParameter.Value = beta;
+      }
+    }
+
     public static double Calculate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData, IEnumerable<int> rows,
       ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
-      ISymbolicExpressionTree tree,
       double lowerEstimationLimit, double upperEstimationLimit,
-      IRegressionProblemData problemData, IEnumerable<int> rows,
       IBoundsEstimator estimator,
       bool useSoftConstraints = false, double penaltyFactor = 1.0) {
 
+      var constraints = Enumerable.Empty<ShapeConstraint>();
+      if (problemData is ShapeConstrainedRegressionProblemData scProbData)
+        constraints = scProbData.ShapeConstraints.EnabledConstraints;
+
       var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
+      var boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
       var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
-      var constraints = Enumerable.Empty<ShapeConstraint>();
-      if (problemData is ShapeConstrainedRegressionProblemData scProbData) {
-        constraints = scProbData.ShapeConstraints.EnabledConstraints;
-      } 
+      var nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues, out var errorState);
+      if (errorState != OnlineCalculatorError.None)
+        return 1.0;
+
+      if (!constraints.Any())
+        return nmse;
+
       var intervalCollection = problemData.VariableRanges;
-
-      var boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
-      var nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues,
-        out var errorState);
-
-      if (errorState != OnlineCalculatorError.None) {
+      var constraintViolations = IntervalUtil.GetConstraintViolations(constraints, estimator, intervalCollection, tree);
+
+      // infinite/NaN constraints
+      if (constraintViolations.Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         return 1.0;
-      }
-
-      var constraintViolations = IntervalUtil.GetConstraintViolations(constraints, estimator, intervalCollection, tree);
-
-      if (constraintViolations.Any(x => double.IsNaN(x) || double.IsInfinity(x))) {
-        return 1.0;
-      }
-
-      if (useSoftConstraints) {
-        if (penaltyFactor < 0.0)
-          throw new ArgumentException("The parameter has to be >= 0.0.", nameof(penaltyFactor));
-
-        var weightedViolationsAvg = constraints
-          .Zip(constraintViolations, (c, v) => c.Weight * v)
-          .Average();
-
-        return Math.Min(nmse, 1.0) + penaltyFactor * weightedViolationsAvg;
-      } else if (constraintViolations.Any(x => x > 0.0)) {
-        return 1.0;
-      }
-
-      return nmse;
+
+      // hard constraints
+      if (!useSoftConstraints) {
+        if (constraintViolations.Any(x => x > 0.0))
+          return 1.0;
+        return nmse;
+      }
+
+      // soft constraints
+      if (penaltyFactor < 0.0)
+        throw new ArgumentException("The parameter has to be >= 0.0.", nameof(penaltyFactor));
+
+      var weightedViolationsAvg = constraints
+        .Zip(constraintViolations, (c, v) => c.Weight * v)
+        .Average();
+
+      return Math.Min(nmse, 1.0) + penaltyFactor * weightedViolationsAvg;
     }
 
@@ -223,7 +221,12 @@
       ApplyLinearScalingParameter.ExecutionContext = context;
 
-      var nmse = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree,
-        EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper,
-        problemData, rows, BoundsEstimator, UseSoftConstraints, PenalityFactor);
+      var nmse = Calculate(
+        tree, problemData, rows,
+        SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+        EstimationLimitsParameter.ActualValue.Lower,
+        EstimationLimitsParameter.ActualValue.Upper,
+        BoundsEstimator,
+        UseSoftConstraints,
+        PenalityFactor);
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
@@ -233,4 +236,196 @@
       return nmse;
     }
+
+    public override double Evaluate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling = true,
+      double lowerEstimationLimit = double.MinValue,
+      double upperEstimationLimit = double.MaxValue) {
+
+      if (OptimizeParameters)
+        Optimize(
+          interpreter, tree,
+          problemData, rows,
+          ParameterOptimizationIterations,
+          updateVariableWeights: true,
+          lowerEstimationLimit,
+          upperEstimationLimit);
+      else if (applyLinearScaling) // extra scaling terms, which are included in tree
+        CalcLinearScalingTerms(tree, problemData, rows, interpreter);
+
+      return Calculate(
+        tree, problemData,
+        rows, interpreter,
+        lowerEstimationLimit,
+        upperEstimationLimit,
+        BoundsEstimator,
+        UseSoftConstraints,
+        PenalityFactor);
+    }
+
+    public static double Optimize(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+          ISymbolicExpressionTree tree, IRegressionProblemData problemData, IEnumerable<int> rows,
+          int maxIterations, bool updateVariableWeights = true,
+          double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue,
+          bool updateParametersInTree = true, Action<double[], double, object> iterationCallback = null, EvaluationsCounter counter = null) {
+
+      // Numeric parameters in the tree become variables for parameter optimization.
+      // Variables in the tree become parameters (fixed values) for parameter optimization.
+      // For each parameter (variable in the original tree) we store the 
+      // variable name, variable value (for factor vars) and lag as a DataForVariable object.
+      // A dictionary is used to find parameters
+      double[] initialParameters;
+      var parameters = new List<TreeToAutoDiffTermConverter.DataForVariable>();
+
+      TreeToAutoDiffTermConverter.ParametricFunction func;
+      TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad;
+      if (!TreeToAutoDiffTermConverter.TryConvertToAutoDiff(tree, updateVariableWeights, addLinearScalingTerms: false, out parameters, out initialParameters, out func, out func_grad))
+        throw new NotSupportedException("Could not optimize parameters of symbolic expression tree due to not supported symbols used in the tree.");
+      var parameterEntries = parameters.ToArray(); // order of entries must be the same for x
+
+      // extract initial parameters
+      double[] c = (double[])initialParameters.Clone();
+
+      double originalQuality = SymbolicRegressionSingleObjectiveMeanSquaredErrorEvaluator.Calculate(
+        tree, problemData, rows,
+        interpreter, applyLinearScaling: false,
+        lowerEstimationLimit,
+        upperEstimationLimit);
+
+      if (counter == null) counter = new EvaluationsCounter();
+      var rowEvaluationsCounter = new EvaluationsCounter();
+
+      alglib.minlmreport rep;
+
+      IDataset ds = problemData.Dataset;
+      int n = rows.Count();
+      int k = parameters.Count;
+
+      double[,] x = new double[n, k];
+      int row = 0;
+      foreach (var r in rows) {
+        int col = 0;
+        foreach (var info in parameterEntries) {
+          if (ds.VariableHasType<double>(info.variableName)) {
+            x[row, col] = ds.GetDoubleValue(info.variableName, r + info.lag);
+          } else if (ds.VariableHasType<string>(info.variableName)) {
+            x[row, col] = ds.GetStringValue(info.variableName, r) == info.variableValue ? 1 : 0;
+          } else throw new InvalidProgramException("found a variable of unknown type");
+          col++;
+        }
+        row++;
+      }
+      double[] y = ds.GetDoubleValues(problemData.TargetVariable, rows).ToArray();
+
+
+      alglib.ndimensional_rep xrep = (p, f, obj) => iterationCallback(p, f, obj);
+
+      try {
+        alglib.minlmcreatevj(y.Length, c, out var lmstate);
+        alglib.minlmsetcond(lmstate, 0.0, maxIterations);
+        alglib.minlmsetxrep(lmstate, iterationCallback != null);
+        // alglib.minlmoptguardgradient(lmstate, 1e-5); // for debugging gradient calculation
+        alglib.minlmoptimize(lmstate, CreateFunc(func, x, y), CreateJac(func_grad, x, y), xrep, rowEvaluationsCounter);
+        alglib.minlmresults(lmstate, out c, out rep);
+        // alglib.minlmoptguardresults(lmstate, out var optGuardReport);
+      } catch (ArithmeticException) {
+        return originalQuality;
+      } catch (alglib.alglibexception) {
+        return originalQuality;
+      }
+
+      counter.FunctionEvaluations += rowEvaluationsCounter.FunctionEvaluations / n;
+      counter.GradientEvaluations += rowEvaluationsCounter.GradientEvaluations / n;
+
+      // * TerminationType, completion code:
+      //     * -8    optimizer detected NAN/INF values either in the function itself,
+      //             or in its Jacobian
+      //     * -5    inappropriate solver was used:
+      //             * solver created with minlmcreatefgh() used  on  problem  with
+      //               general linear constraints (set with minlmsetlc() call).
+      //     * -3    constraints are inconsistent
+      //     *  2    relative step is no more than EpsX.
+      //     *  5    MaxIts steps was taken
+      //     *  7    stopping conditions are too stringent,
+      //             further improvement is impossible
+      //     *  8    terminated   by  user  who  called  MinLMRequestTermination().
+      //             X contains point which was "current accepted" when termination
+      //             request was submitted.
+      if (rep.terminationtype > 0) {
+        UpdateParameters(tree, c, updateVariableWeights);
+      }
+      var quality = SymbolicRegressionSingleObjectiveMeanSquaredErrorEvaluator.Calculate(
+        tree, problemData, rows,
+        interpreter, applyLinearScaling: false,
+        lowerEstimationLimit, upperEstimationLimit);
+
+      if (!updateParametersInTree) UpdateParameters(tree, initialParameters, updateVariableWeights);
+
+      if (originalQuality < quality || double.IsNaN(quality)) {
+        UpdateParameters(tree, initialParameters, updateVariableWeights);
+        return originalQuality;
+      }
+      return quality;
+    }
+
+    private static void UpdateParameters(ISymbolicExpressionTree tree, double[] parameters, bool updateVariableWeights) {
+      int i = 0;
+      foreach (var node in tree.Root.IterateNodesPrefix().OfType<SymbolicExpressionTreeTerminalNode>()) {
+        NumberTreeNode numberTreeNode = node as NumberTreeNode;
+        VariableTreeNodeBase variableTreeNodeBase = node as VariableTreeNodeBase;
+        FactorVariableTreeNode factorVarTreeNode = node as FactorVariableTreeNode;
+        if (numberTreeNode != null) {
+          if (numberTreeNode.Parent.Symbol is Power
+              && numberTreeNode.Parent.GetSubtree(1) == numberTreeNode) continue; // exponents in powers are not optimized (see TreeToAutoDiffTermConverter)
+          numberTreeNode.Value = parameters[i++];
+        } else if (updateVariableWeights && variableTreeNodeBase != null)
+          variableTreeNodeBase.Weight = parameters[i++];
+        else if (factorVarTreeNode != null) {
+          for (int j = 0; j < factorVarTreeNode.Weights.Length; j++)
+            factorVarTreeNode.Weights[j] = parameters[i++];
+        }
+      }
+    }
+
+    private static alglib.ndimensional_fvec CreateFunc(TreeToAutoDiffTermConverter.ParametricFunction func, double[,] x, double[] y) {
+      int d = x.GetLength(1);
+      // row buffer
+      var xi = new double[d];
+      // function must return residuals, alglib optimizes resid²
+      return (double[] c, double[] resid, object o) => {
+        for (int i = 0; i < y.Length; i++) {
+          Buffer.BlockCopy(x, i * d * sizeof(double), xi, 0, d * sizeof(double)); // copy row. We are using BlockCopy instead of Array.Copy because x has rank 2
+          resid[i] = func(c, xi) - y[i];
+        }
+        var counter = (EvaluationsCounter)o;
+        counter.FunctionEvaluations += y.Length;
+      };
+    }
+
+    private static alglib.ndimensional_jac CreateJac(TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad, double[,] x, double[] y) {
+      int numParams = x.GetLength(1);
+      // row buffer
+      var xi = new double[numParams];
+      return (double[] c, double[] resid, double[,] jac, object o) => {
+        int numVars = c.Length;
+        for (int i = 0; i < y.Length; i++) {
+          Buffer.BlockCopy(x, i * numParams * sizeof(double), xi, 0, numParams * sizeof(double)); // copy row
+          var tuple = func_grad(c, xi);
+          resid[i] = tuple.Item2 - y[i];
+          Buffer.BlockCopy(tuple.Item1, 0, jac, i * numVars * sizeof(double), numVars * sizeof(double)); // copy the gradient to jac. BlockCopy because jac has rank 2.
+        }
+        var counter = (EvaluationsCounter)o;
+        counter.FunctionEvaluations += y.Length;
+        counter.GradientEvaluations += y.Length;
+      };
+    }
+
+    public class EvaluationsCounter {
+      public int FunctionEvaluations = 0;
+      public int GradientEvaluations = 0;
+    }
   }
 }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionLogResidualEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionLogResidualEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionLogResidualEvaluator.cs	(revision 18220)
@@ -54,8 +54,12 @@
 
     public override IOperation InstrumentedApply() {
-      var solution = SymbolicExpressionTreeParameter.ActualValue;
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
       IEnumerable<int> rows = GenerateRowsToEvaluate();
 
-      double quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, rows);
+      double quality = Calculate(
+        tree, ProblemDataParameter.ActualValue, 
+        rows, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+        EstimationLimitsParameter.ActualValue.Lower, 
+        EstimationLimitsParameter.ActualValue.Upper);
       QualityParameter.ActualValue = new DoubleValue(quality);
 
@@ -63,6 +67,12 @@
     }
 
-    public static double Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows) {
-      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows);
+    public static double Calculate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      double lowerEstimationLimit, 
+      double upperEstimationLimit) {
+      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
       IEnumerable<double> targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
       IEnumerable<double> boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
@@ -83,5 +93,9 @@
       EstimationLimitsParameter.ExecutionContext = context;
 
-      double mlr = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows);
+      double mlr = Calculate(
+        tree, problemData, rows, 
+        SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+        EstimationLimitsParameter.ActualValue.Lower, 
+        EstimationLimitsParameter.ActualValue.Upper);
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
@@ -90,4 +104,15 @@
       return mlr;
     }
+
+    public override double Evaluate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling = true,
+      double lowerEstimationLimit = double.MinValue,
+      double upperEstimationLimit = double.MaxValue) {
+      return Calculate(tree, problemData, rows, interpreter, lowerEstimationLimit, upperEstimationLimit);
+    }
   }
 }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionMeanRelativeErrorEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionMeanRelativeErrorEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionMeanRelativeErrorEvaluator.cs	(revision 18220)
@@ -47,8 +47,12 @@
 
     public override IOperation InstrumentedApply() {
-      var solution = SymbolicExpressionTreeParameter.ActualValue;
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
       IEnumerable<int> rows = GenerateRowsToEvaluate();
 
-      double quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, rows);
+      double quality = Calculate(
+        tree, ProblemDataParameter.ActualValue, rows,
+        SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+        EstimationLimitsParameter.ActualValue.Lower, 
+        EstimationLimitsParameter.ActualValue.Upper);
       QualityParameter.ActualValue = new DoubleValue(quality);
 
@@ -56,6 +60,11 @@
     }
 
-    public static double Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows) {
-      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows);
+    public static double Calculate(
+      ISymbolicExpressionTree tree, 
+      IRegressionProblemData problemData, 
+      IEnumerable<int> rows, 
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      double lowerEstimationLimit, double upperEstimationLimit) {
+      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
       IEnumerable<double> targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
       IEnumerable<double> boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
@@ -76,5 +85,9 @@
       EstimationLimitsParameter.ExecutionContext = context;
 
-      double mre = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows);
+      double mre = Calculate(
+        tree, problemData, rows,
+        SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+        EstimationLimitsParameter.ActualValue.Lower, 
+        EstimationLimitsParameter.ActualValue.Upper);
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
@@ -83,4 +96,15 @@
       return mre;
     }
+
+    public override double Evaluate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling = true,
+      double lowerEstimationLimit = double.MinValue,
+      double upperEstimationLimit = double.MaxValue) {
+      return Calculate(tree, problemData, rows, interpreter, lowerEstimationLimit, upperEstimationLimit);
+    }
   }
 }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionParameterOptimizationEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionParameterOptimizationEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionParameterOptimizationEvaluator.cs	(revision 18220)
@@ -197,5 +197,5 @@
           Parameters.Add(new FixedValueParameter<PercentValue>(ParameterOptimizationRowsPercentageParameterName, "Determines the percentage of the rows which should be used for parameter optimization", new PercentValue(1)));
         }
-        
+
       }
     }
@@ -203,15 +203,20 @@
     private static readonly object locker = new object();
     public override IOperation InstrumentedApply() {
-      var solution = SymbolicExpressionTreeParameter.ActualValue;
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
       double quality;
       if (RandomParameter.ActualValue.NextDouble() < ParameterOptimizationProbability.Value) {
         IEnumerable<int> parameterOptimizationRows = GenerateRowsToEvaluate(ParameterOptimizationRowsPercentage.Value);
         var counter = new EvaluationsCounter();
-        quality = OptimizeParameters(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, ProblemDataParameter.ActualValue,
+        quality = OptimizeParameters(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, ProblemDataParameter.ActualValue,
            parameterOptimizationRows, ApplyLinearScalingParameter.ActualValue.Value, ParameterOptimizationIterations.Value, updateVariableWeights: UpdateVariableWeights, lowerEstimationLimit: EstimationLimitsParameter.ActualValue.Lower, upperEstimationLimit: EstimationLimitsParameter.ActualValue.Upper, updateParametersInTree: UpdateParametersInTree, counter: counter);
 
         if (ParameterOptimizationRowsPercentage.Value != RelativeNumberOfEvaluatedSamplesParameter.ActualValue.Value) {
           var evaluationRows = GenerateRowsToEvaluate();
-          quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, evaluationRows, ApplyLinearScalingParameter.ActualValue.Value);
+          quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+            tree, ProblemDataParameter.ActualValue,
+            evaluationRows, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+            ApplyLinearScalingParameter.ActualValue.Value,
+            EstimationLimitsParameter.ActualValue.Lower,
+            EstimationLimitsParameter.ActualValue.Upper);
         }
 
@@ -225,9 +230,49 @@
       } else {
         var evaluationRows = GenerateRowsToEvaluate();
-        quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, evaluationRows, ApplyLinearScalingParameter.ActualValue.Value);
+        quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+          tree, ProblemDataParameter.ActualValue,
+          evaluationRows, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+          ApplyLinearScalingParameter.ActualValue.Value,
+          EstimationLimitsParameter.ActualValue.Lower,
+          EstimationLimitsParameter.ActualValue.Upper);
       }
       QualityParameter.ActualValue = new DoubleValue(quality);
 
       return base.InstrumentedApply();
+    }
+
+    public override double Evaluate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling = true,
+      double lowerEstimationLimit = double.MinValue,
+      double upperEstimationLimit = double.MaxValue) {
+
+      var random = RandomParameter.ActualValue;
+      double quality = double.NaN;
+
+      var propability = random.NextDouble();
+      if (propability < ParameterOptimizationProbability.Value) {
+        quality = OptimizeParameters(
+          interpreter, tree,
+          problemData, rows,
+          applyLinearScaling,
+          ParameterOptimizationIterations.Value,
+          updateVariableWeights: UpdateVariableWeights,
+          lowerEstimationLimit: lowerEstimationLimit,
+          upperEstimationLimit: upperEstimationLimit,
+          updateParametersInTree: UpdateParametersInTree);
+      }
+      if (double.IsNaN(quality) || ParameterOptimizationRowsPercentage.Value != RelativeNumberOfEvaluatedSamplesParameter.ActualValue.Value) {
+        quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+          tree, problemData,
+          rows, interpreter,
+          applyLinearScaling,
+          lowerEstimationLimit,
+          upperEstimationLimit);
+      }
+      return quality;
     }
 
@@ -242,5 +287,10 @@
       // because Evaluate() is used to get the quality of evolved models on 
       // different partitions of the dataset (e.g., best validation model)
-      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, ApplyLinearScalingParameter.ActualValue.Value);
+      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+        tree, problemData, rows,
+        SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+        ApplyLinearScalingParameter.ActualValue.Value,
+        EstimationLimitsParameter.ActualValue.Lower,
+        EstimationLimitsParameter.ActualValue.Upper);
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
@@ -290,5 +340,9 @@
       }
 
-      double originalQuality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, tree, lowerEstimationLimit, upperEstimationLimit, problemData, rows, applyLinearScaling);
+      double originalQuality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+        tree, problemData, rows,
+        interpreter, applyLinearScaling,
+        lowerEstimationLimit,
+        upperEstimationLimit);
 
       if (counter == null) counter = new EvaluationsCounter();
@@ -348,5 +402,8 @@
         } else UpdateParameters(tree, c, updateVariableWeights);
       }
-      var quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, tree, lowerEstimationLimit, upperEstimationLimit, problemData, rows, applyLinearScaling);
+      var quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+        tree, problemData, rows,
+        interpreter, applyLinearScaling,
+        lowerEstimationLimit, upperEstimationLimit);
 
       if (!updateParametersInTree) UpdateParameters(tree, initialParameters, updateVariableWeights);
@@ -366,5 +423,5 @@
         FactorVariableTreeNode factorVarTreeNode = node as FactorVariableTreeNode;
         if (numberTreeNode != null) {
-          if (numberTreeNode.Parent.Symbol is Power 
+          if (numberTreeNode.Parent.Symbol is Power
               && numberTreeNode.Parent.GetSubtree(1) == numberTreeNode) continue; // exponents in powers are not optimizated (see TreeToAutoDiffTermConverter)
           numberTreeNode.Value = parameters[i++];
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveEvaluator.cs	(revision 18220)
@@ -22,4 +22,7 @@
 using HeuristicLab.Common;
 using HEAL.Attic;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using System.Collections.Generic;
+
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
   [StorableType("7EB90F03-4385-474F-BDE7-3B133E8FEAAB")]
@@ -28,5 +31,13 @@
     protected SymbolicRegressionSingleObjectiveEvaluator(StorableConstructorFlag _) : base(_) { }
     protected SymbolicRegressionSingleObjectiveEvaluator(SymbolicRegressionSingleObjectiveEvaluator original, Cloner cloner) : base(original, cloner) { }
-    protected SymbolicRegressionSingleObjectiveEvaluator(): base() {}    
+    protected SymbolicRegressionSingleObjectiveEvaluator(): base() {}
+    public abstract double Evaluate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling = true,
+      double lowerEstimationLimit = double.MinValue,
+      double upperEstimationLimit = double.MaxValue);
   }
 }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveMaxAbsoluteErrorEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveMaxAbsoluteErrorEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveMaxAbsoluteErrorEvaluator.cs	(revision 18220)
@@ -43,8 +43,13 @@
 
     public override IOperation InstrumentedApply() {
-      var solution = SymbolicExpressionTreeParameter.ActualValue;
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
       IEnumerable<int> rows = GenerateRowsToEvaluate();
 
-      double quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, rows, ApplyLinearScalingParameter.ActualValue.Value);
+      double quality = Calculate(
+        tree, ProblemDataParameter.ActualValue,
+        rows, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+        ApplyLinearScalingParameter.ActualValue.Value,
+        EstimationLimitsParameter.ActualValue.Lower, 
+        EstimationLimitsParameter.ActualValue.Upper);
       QualityParameter.ActualValue = new DoubleValue(quality);
 
@@ -52,6 +57,13 @@
     }
 
-    public static double Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling) {
-      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows);
+    public static double Calculate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling,
+      double lowerEstimationLimit, 
+      double upperEstimationLimit) {
+      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
       IEnumerable<double> targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
       OnlineCalculatorError errorState;
@@ -76,5 +88,10 @@
       ApplyLinearScalingParameter.ExecutionContext = context;
 
-      double mse = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, ApplyLinearScalingParameter.ActualValue.Value);
+      double mse = Calculate(
+        tree, problemData, rows,
+        SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, 
+        ApplyLinearScalingParameter.ActualValue.Value,
+        EstimationLimitsParameter.ActualValue.Lower, 
+        EstimationLimitsParameter.ActualValue.Upper);
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
@@ -84,4 +101,15 @@
       return mse;
     }
+
+    public override double Evaluate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling = true,
+      double lowerEstimationLimit = double.MinValue,
+      double upperEstimationLimit = double.MaxValue) {
+      return Calculate(tree, problemData, rows, interpreter, applyLinearScaling, lowerEstimationLimit, upperEstimationLimit);
+    }
   }
 }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveMeanAbsoluteErrorEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveMeanAbsoluteErrorEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveMeanAbsoluteErrorEvaluator.cs	(revision 18220)
@@ -43,8 +43,13 @@
 
     public override IOperation InstrumentedApply() {
-      var solution = SymbolicExpressionTreeParameter.ActualValue;
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
       IEnumerable<int> rows = GenerateRowsToEvaluate();
 
-      double quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, rows, ApplyLinearScalingParameter.ActualValue.Value);
+      double quality = Calculate(tree, 
+        ProblemDataParameter.ActualValue, rows, 
+        SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, 
+        ApplyLinearScalingParameter.ActualValue.Value,
+        EstimationLimitsParameter.ActualValue.Lower, 
+        EstimationLimitsParameter.ActualValue.Upper);
       QualityParameter.ActualValue = new DoubleValue(quality);
 
@@ -52,6 +57,13 @@
     }
 
-    public static double Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling) {
-      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows);
+    public static double Calculate(
+      ISymbolicExpressionTree tree, 
+      IRegressionProblemData problemData, 
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, 
+      bool applyLinearScaling,
+      double lowerEstimationLimit, 
+      double upperEstimationLimit) {
+      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
       IEnumerable<double> targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
       OnlineCalculatorError errorState;
@@ -76,5 +88,10 @@
       ApplyLinearScalingParameter.ExecutionContext = context;
 
-      double mse = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, ApplyLinearScalingParameter.ActualValue.Value);
+      double mse = Calculate(
+        tree, problemData, rows, 
+        SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, 
+        ApplyLinearScalingParameter.ActualValue.Value,
+        EstimationLimitsParameter.ActualValue.Lower, 
+        EstimationLimitsParameter.ActualValue.Upper);
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
@@ -84,4 +101,15 @@
       return mse;
     }
+
+    public override double Evaluate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling = true,
+      double lowerEstimationLimit = double.MinValue,
+      double upperEstimationLimit = double.MaxValue) {
+      return Calculate(tree, problemData, rows, interpreter, applyLinearScaling, lowerEstimationLimit, upperEstimationLimit);
+    }
   }
 }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveMeanSquaredErrorEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveMeanSquaredErrorEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveMeanSquaredErrorEvaluator.cs	(revision 18220)
@@ -43,8 +43,13 @@
 
     public override IOperation InstrumentedApply() {
-      var solution = SymbolicExpressionTreeParameter.ActualValue;
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
       IEnumerable<int> rows = GenerateRowsToEvaluate();
 
-      double quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, rows, ApplyLinearScalingParameter.ActualValue.Value);
+      double quality = Calculate(
+        tree, ProblemDataParameter.ActualValue, 
+        rows, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, 
+        ApplyLinearScalingParameter.ActualValue.Value,         
+        EstimationLimitsParameter.ActualValue.Lower, 
+        EstimationLimitsParameter.ActualValue.Upper);
       QualityParameter.ActualValue = new DoubleValue(quality);
 
@@ -52,6 +57,12 @@
     }
 
-    public static double Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling) {
-      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows);
+    public static double Calculate(
+      ISymbolicExpressionTree tree, 
+      IRegressionProblemData problemData, 
+      IEnumerable<int> rows, 
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, 
+      bool applyLinearScaling,
+      double lowerEstimationLimit, double upperEstimationLimit) {
+      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
       IEnumerable<double> targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
       OnlineCalculatorError errorState;
@@ -76,5 +87,10 @@
       ApplyLinearScalingParameter.ExecutionContext = context;
 
-      double mse = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, ApplyLinearScalingParameter.ActualValue.Value);
+      double mse = Calculate(        
+        tree, problemData, rows, 
+        SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, 
+        ApplyLinearScalingParameter.ActualValue.Value,
+        EstimationLimitsParameter.ActualValue.Lower, 
+        EstimationLimitsParameter.ActualValue.Upper);
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
@@ -84,4 +100,15 @@
       return mse;
     }
+
+    public override double Evaluate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling = true,
+      double lowerEstimationLimit = double.MinValue,
+      double upperEstimationLimit = double.MaxValue) {
+      return Calculate(tree, problemData, rows, interpreter, applyLinearScaling, lowerEstimationLimit, upperEstimationLimit);
+    }
   }
 }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.cs	(revision 18220)
@@ -48,5 +48,10 @@
       IEnumerable<int> rows = GenerateRowsToEvaluate();
 
-      double quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, rows, ApplyLinearScalingParameter.ActualValue.Value);
+      double quality = Calculate(
+        solution, ProblemDataParameter.ActualValue,
+        rows, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+        ApplyLinearScalingParameter.ActualValue.Value,
+        EstimationLimitsParameter.ActualValue.Lower, 
+        EstimationLimitsParameter.ActualValue.Upper);
       QualityParameter.ActualValue = new DoubleValue(quality);
 
@@ -54,6 +59,13 @@
     }
 
-    public static double Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling) {
-      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows);
+    public static double Calculate(
+      ISymbolicExpressionTree tree, 
+      IRegressionProblemData problemData, 
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling,
+      double lowerEstimationLimit, 
+      double upperEstimationLimit) {
+      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
       IEnumerable<double> targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
       OnlineCalculatorError errorState;
@@ -78,5 +90,10 @@
       ApplyLinearScalingParameter.ExecutionContext = context;
 
-      double r2 = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, ApplyLinearScalingParameter.ActualValue.Value);
+      double r2 = Calculate(
+         tree, problemData, rows, 
+         SymbolicDataAnalysisTreeInterpreterParameter.ActualValue,
+         ApplyLinearScalingParameter.ActualValue.Value,
+         EstimationLimitsParameter.ActualValue.Lower, 
+         EstimationLimitsParameter.ActualValue.Upper);
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
@@ -86,4 +103,18 @@
       return r2;
     }
+
+    public override double Evaluate(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      bool applyLinearScaling = true,
+      double lowerEstimationLimit = double.MinValue,
+      double upperEstimationLimit = double.MaxValue) {
+      return Calculate(
+        tree, problemData, rows, 
+        interpreter, applyLinearScaling, 
+        lowerEstimationLimit, upperEstimationLimit);
+    }
   }
 }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/ShapeConstrainedRegressionSingleObjectiveProblem.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/ShapeConstrainedRegressionSingleObjectiveProblem.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/ShapeConstrainedRegressionSingleObjectiveProblem.cs	(revision 18220)
@@ -55,6 +55,6 @@
 
     public override void Load(IRegressionProblemData data) {
-      if (data is ShapeConstrainedRegressionProblemData scProblemData) {
-      } else {
+      var scProblemData = data as ShapeConstrainedRegressionProblemData;
+      if (scProblemData == null) {
         scProblemData = new ShapeConstrainedRegressionProblemData(data.Dataset, data.AllowedInputVariables, data.TargetVariable,
                                                                   data.TrainingPartition, data.TestPartition) {
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/StructureTemplateSymbolicRegressionProblem.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/StructureTemplateSymbolicRegressionProblem.cs	(revision 18220)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/StructureTemplateSymbolicRegressionProblem.cs	(revision 18220)
@@ -0,0 +1,409 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 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 System;
+using System.Collections.Generic;
+using System.Linq;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Problems.Instances;
+using HeuristicLab.Problems.Instances.DataAnalysis;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
+  [StorableType("7464E84B-65CC-440A-91F0-9FA920D730F9")]
+  [Item(Name = "Structured Symbolic Regression Problem (single-objective)", Description = "A problem with a structural definition and variable subfunctions.")]
+  [Creatable(CreatableAttribute.Categories.GeneticProgrammingProblems, Priority = 150)]
+  public class StructureTemplateSymbolicRegressionProblem : SingleObjectiveBasicProblem<MultiEncoding>, IRegressionProblem, IProblemInstanceConsumer<IRegressionProblemData> {
+
+    #region Constants
+    private const string ProblemDataParameterName = "ProblemData";
+    private const string StructureTemplateParameterName = "Structure Template";
+    private const string InterpreterParameterName = "Interpreter";
+    private const string EstimationLimitsParameterName = "EstimationLimits";
+    private const string BestTrainingSolutionParameterName = "Best Training Solution";
+    private const string ApplyLinearScalingParameterName = "Apply Linear Scaling";
+    private const string OptimizeParametersParameterName = "Optimize Parameters";
+
+    private const string SymbolicExpressionTreeName = "SymbolicExpressionTree";
+    private const string NumericParametersEncoding = "Numeric Parameters";
+
+    private const string StructureTemplateDescriptionText =
+      "Enter your expression as string in infix format into the empty input field.\n" +
+      "By checking the \"Apply Linear Scaling\" checkbox you can add the relevant scaling terms to your expression.\n" +
+      "After entering the expression click parse to build the tree.\n" +
+      "To edit the defined sub-functions, click on the corresponding-colored node in the tree view.\n" +
+      "Check the info box besides the input field for more information.";
+    #endregion
+
+    #region Parameters
+    public IValueParameter<IRegressionProblemData> ProblemDataParameter => (IValueParameter<IRegressionProblemData>)Parameters[ProblemDataParameterName];
+    public IFixedValueParameter<StructureTemplate> StructureTemplateParameter => (IFixedValueParameter<StructureTemplate>)Parameters[StructureTemplateParameterName];
+    public IValueParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> InterpreterParameter => (IValueParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[InterpreterParameterName];
+    public IFixedValueParameter<DoubleLimit> EstimationLimitsParameter => (IFixedValueParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName];
+    public IResultParameter<ISymbolicRegressionSolution> BestTrainingSolutionParameter => (IResultParameter<ISymbolicRegressionSolution>)Parameters[BestTrainingSolutionParameterName];
+
+    public IFixedValueParameter<BoolValue> ApplyLinearScalingParameter => (IFixedValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName];
+    public IFixedValueParameter<BoolValue> OptimizeParametersParameter => (IFixedValueParameter<BoolValue>)Parameters[OptimizeParametersParameterName];
+    #endregion
+
+    #region Properties
+
+    public IRegressionProblemData ProblemData {
+      get => ProblemDataParameter.Value;
+      set {
+        ProblemDataParameter.Value = value;
+        ProblemDataChanged?.Invoke(this, EventArgs.Empty);
+      }
+    }
+
+    public StructureTemplate StructureTemplate => StructureTemplateParameter.Value;
+
+    public ISymbolicDataAnalysisExpressionTreeInterpreter Interpreter => InterpreterParameter.Value;
+
+    IParameter IDataAnalysisProblem.ProblemDataParameter => ProblemDataParameter;
+    IDataAnalysisProblemData IDataAnalysisProblem.ProblemData => ProblemData;
+
+    public DoubleLimit EstimationLimits => EstimationLimitsParameter.Value;
+
+    public bool ApplyLinearScaling {
+      get => ApplyLinearScalingParameter.Value.Value;
+      set => ApplyLinearScalingParameter.Value.Value = value;
+    }
+
+    public bool OptimizeParameters {
+      get => OptimizeParametersParameter.Value.Value;
+      set => OptimizeParametersParameter.Value.Value = value;
+    }
+
+    public override bool Maximization => false;
+    #endregion
+
+    #region EventHandlers
+    public event EventHandler ProblemDataChanged;
+    #endregion
+
+    #region Constructors & Cloning
+    public StructureTemplateSymbolicRegressionProblem() {
+      var provider = new PhysicsInstanceProvider();
+      var descriptor = new SheetBendingProcess();
+      var problemData = provider.LoadData(descriptor);
+      var shapeConstraintProblemData = new ShapeConstrainedRegressionProblemData(problemData);
+
+      var structureTemplate = new StructureTemplate();
+
+      Parameters.Add(new ValueParameter<IRegressionProblemData>(
+        ProblemDataParameterName,
+        shapeConstraintProblemData));
+
+      Parameters.Add(new FixedValueParameter<StructureTemplate>(
+        StructureTemplateParameterName,
+        StructureTemplateDescriptionText,
+        structureTemplate));
+
+      Parameters.Add(new FixedValueParameter<BoolValue>(
+        ApplyLinearScalingParameterName, new BoolValue(true)
+        ));
+
+      Parameters.Add(new FixedValueParameter<BoolValue>(
+        OptimizeParametersParameterName, new BoolValue(true)
+        ));
+
+      Parameters.Add(new ValueParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(
+        InterpreterParameterName,
+        new SymbolicDataAnalysisExpressionTreeBatchInterpreter()) { Hidden = true });
+      Parameters.Add(new FixedValueParameter<DoubleLimit>(
+        EstimationLimitsParameterName,
+        new DoubleLimit(double.NegativeInfinity, double.PositiveInfinity)) { Hidden = true });
+      Parameters.Add(new ResultParameter<ISymbolicRegressionSolution>(BestTrainingSolutionParameterName, "") { Hidden = true });
+
+      this.EvaluatorParameter.Hidden = true;
+
+      Operators.Add(new SymbolicDataAnalysisVariableFrequencyAnalyzer());
+      Operators.Add(new MinAverageMaxSymbolicExpressionTreeLengthAnalyzer());
+      Operators.Add(new SymbolicExpressionSymbolFrequencyAnalyzer());
+
+      RegisterEventHandlers();
+
+      StructureTemplate.ApplyLinearScaling = ApplyLinearScaling;
+      StructureTemplate.Template =
+        "(" +
+          "(210000 / (210000 + h)) * ((sigma_y * t * t) / (wR * Rt * t)) + " +
+          "PlasticHardening(_) - Elasticity(_)" +
+        ")" +
+        " * C(_)";
+    }
+
+    public StructureTemplateSymbolicRegressionProblem(StructureTemplateSymbolicRegressionProblem original, Cloner cloner) : base(original, cloner) {
+      RegisterEventHandlers();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) =>
+      new StructureTemplateSymbolicRegressionProblem(this, cloner);
+
+    [StorableConstructor]
+    protected StructureTemplateSymbolicRegressionProblem(StorableConstructorFlag _) : base(_) { }
+
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey(ApplyLinearScalingParameterName)) {
+        Parameters.Add(new FixedValueParameter<BoolValue>(ApplyLinearScalingParameterName, new BoolValue(StructureTemplate.ApplyLinearScaling)));
+      }
+
+      if (!Parameters.ContainsKey(OptimizeParametersParameterName)) {
+        Parameters.Add(new FixedValueParameter<BoolValue>(OptimizeParametersParameterName, new BoolValue(false)));
+      }
+
+      RegisterEventHandlers();
+    }
+
+    #endregion
+
+    private void RegisterEventHandlers() {
+      if (StructureTemplate != null) {
+        StructureTemplate.Changed += OnTemplateChanged;
+      }
+
+      ProblemDataParameter.ValueChanged += ProblemDataParameterValueChanged;
+      ApplyLinearScalingParameter.Value.ValueChanged += (o, e) => StructureTemplate.ApplyLinearScaling = ApplyLinearScaling;
+    }
+
+    private void ProblemDataParameterValueChanged(object sender, EventArgs e) {
+      StructureTemplate.Reset();
+      // InfoBox for Reset?
+    }
+
+    private void OnTemplateChanged(object sender, EventArgs args) {
+      ApplyLinearScaling = StructureTemplate.ApplyLinearScaling;
+      SetupEncoding();
+    }
+
+    private void SetupEncoding() {
+      foreach (var e in Encoding.Encodings.ToArray())
+        Encoding.Remove(e);
+
+
+      var templateNumberTreeNodes = StructureTemplate.Tree.IterateNodesPrefix().OfType<NumberTreeNode>();
+      if (templateNumberTreeNodes.Any()) {
+        var templateParameterValues = templateNumberTreeNodes.Select(n => n.Value).ToArray();
+        var encoding = new RealVectorEncoding(NumericParametersEncoding, templateParameterValues.Length);
+
+        var creator = encoding.Operators.OfType<NormalDistributedRealVectorCreator>().First();
+        creator.MeanParameter.Value = new RealVector(templateParameterValues);
+        creator.SigmaParameter.Value = new DoubleArray(templateParameterValues.Length);
+        encoding.SolutionCreator = creator;
+
+
+        Encoding.Add(encoding);
+      }
+
+      foreach (var subFunction in StructureTemplate.SubFunctions) {
+        subFunction.SetupVariables(ProblemData.AllowedInputVariables);
+        // prevent the same encoding twice
+        if (Encoding.Encodings.Any(x => x.Name == subFunction.Name)) continue;
+
+        var encoding = new SymbolicExpressionTreeEncoding(
+          subFunction.Name,
+          subFunction.Grammar,
+          subFunction.MaximumSymbolicExpressionTreeLength,
+          subFunction.MaximumSymbolicExpressionTreeDepth);
+        Encoding.Add(encoding);
+      }
+
+      //set single point || copy crossover for numeric parameters
+      var multiCrossover = (IParameterizedItem)Encoding.Operators.OfType<MultiEncodingCrossover>().First();
+      foreach (var param in multiCrossover.Parameters.OfType<ConstrainedValueParameter<ICrossover>>()) {
+        if (!param.Name.Contains(NumericParametersEncoding)) continue;
+
+        var singlePointCrossover = param.ValidValues.OfType<SinglePointCrossover>().First();
+        var copyCrossover = param.ValidValues.OfType<CopyCrossover>().First();
+
+        var realvectorEncoding = (RealVectorEncoding)Encoding.Encodings.Where(e => e.Name == NumericParametersEncoding).First();
+        if (realvectorEncoding.Length == 1) { //single-point crossover throws if encoding length == 1
+          param.Value = copyCrossover;
+        } else
+          param.Value = singlePointCrossover;
+      }
+
+      //adapt crossover probability for subtree crossover
+      foreach (var param in multiCrossover.Parameters.OfType<ConstrainedValueParameter<ICrossover>>()) {
+        var subtreeCrossover = param.ValidValues.OfType<SubtreeCrossover>().FirstOrDefault();
+        if (subtreeCrossover != null) {
+          subtreeCrossover.CrossoverProbability = 1.0 / Encoding.Encodings.OfType<SymbolicExpressionTreeEncoding>().Count();
+          param.Value = subtreeCrossover;
+        }
+      }
+
+      //set multi manipulator as default manipulator for all symbolic expression tree encoding parts
+      var manipulator = (IParameterizedItem)Encoding.Operators.OfType<MultiEncodingManipulator>().First();
+      foreach (var param in manipulator.Parameters.OfType<ConstrainedValueParameter<IManipulator>>()) {
+        var m = param.ValidValues.OfType<MultiSymbolicExpressionTreeManipulator>().FirstOrDefault();
+        param.Value = m ?? param.ValidValues.First();
+      }
+    }
+
+    public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
+      base.Analyze(individuals, qualities, results, random);
+
+      var best = GetBestIndividual(individuals, qualities).Item1;
+
+      if (!results.ContainsKey(BestTrainingSolutionParameter.ActualName)) {
+        results.Add(new Result(BestTrainingSolutionParameter.ActualName, typeof(SymbolicRegressionSolution)));
+      }
+
+      var tree = (ISymbolicExpressionTree)best[SymbolicExpressionTreeName];
+      var model = new SymbolicRegressionModel(ProblemData.TargetVariable, tree, Interpreter);
+      var solution = model.CreateRegressionSolution(ProblemData);
+
+      results[BestTrainingSolutionParameter.ActualName].Value = solution;
+    }
+
+
+    public override double Evaluate(Individual individual, IRandom random) {
+      var templateTree = StructureTemplate.Tree;
+      if (templateTree == null)
+        throw new ArgumentException("No structure template defined!");
+
+      var tree = BuildTreeFromIndividual(templateTree, individual, containsNumericParameters: StructureTemplate.ContainsNumericParameters);
+      individual[SymbolicExpressionTreeName] = tree;
+
+      if (OptimizeParameters) {
+        var excludeNodes = GetTemplateTreeNodes(tree.Root).OfType<IVariableTreeNode>();
+        ParameterOptimization.OptimizeTreeParameters(ProblemData, tree, interpreter: Interpreter, excludeNodes: excludeNodes);
+      } else if (ApplyLinearScaling) {
+        LinearScaling.AdjustLinearScalingParams(ProblemData, tree, Interpreter);
+      }
+
+      UpdateIndividualFromTree(tree, individual, containsNumericParameters: StructureTemplate.ContainsNumericParameters);
+
+      //calculate NMSE
+      var estimatedValues = Interpreter.GetSymbolicExpressionTreeValues(tree, ProblemData.Dataset, ProblemData.TrainingIndices);
+      var boundedEstimatedValues = estimatedValues.LimitToRange(EstimationLimits.Lower, EstimationLimits.Upper);
+      var targetValues = ProblemData.TargetVariableTrainingValues;
+      var nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues, out var errorState);
+      if (errorState != OnlineCalculatorError.None)
+        nmse = 1.0;
+
+      //evaluate constraints
+      var constraints = Enumerable.Empty<ShapeConstraint>();
+      if (ProblemData is ShapeConstrainedRegressionProblemData scProbData)
+        constraints = scProbData.ShapeConstraints.EnabledConstraints;
+      if (constraints.Any()) {
+        var boundsEstimator = new IntervalArithBoundsEstimator();
+        var constraintViolations = IntervalUtil.GetConstraintViolations(constraints, boundsEstimator, ProblemData.VariableRanges, tree);
+
+        // infinite/NaN constraints
+        if (constraintViolations.Any(x => double.IsNaN(x) || double.IsInfinity(x)))
+          nmse = 1.0;
+
+        if (constraintViolations.Any(x => x > 0.0))
+          nmse = 1.0;
+      }
+
+      return nmse;
+    }
+
+    private static IEnumerable<ISymbolicExpressionTreeNode> GetTemplateTreeNodes(ISymbolicExpressionTreeNode rootNode) {
+      yield return rootNode;
+      foreach (var node in rootNode.Subtrees) {
+        if (node is SubFunctionTreeNode) {
+          yield return node;
+          continue;
+        }
+
+        foreach (var subNode in GetTemplateTreeNodes(node))
+          yield return subNode;
+      }
+    }
+
+    private static ISymbolicExpressionTree BuildTreeFromIndividual(ISymbolicExpressionTree template, Individual individual, bool containsNumericParameters) {
+      var resolvedTree = (ISymbolicExpressionTree)template.Clone();
+
+      //set numeric parameter values
+      if (containsNumericParameters) {
+        var realVector = individual.RealVector(NumericParametersEncoding);
+        var numberTreeNodes = resolvedTree.IterateNodesPrefix().OfType<NumberTreeNode>().ToArray();
+
+        if (realVector.Length != numberTreeNodes.Length)
+          throw new InvalidOperationException("The number of numeric parameters in the tree does not match the provided numerical values.");
+
+        for (int i = 0; i < numberTreeNodes.Length; i++)
+          numberTreeNodes[i].Value = realVector[i];
+      }
+
+      // build main tree
+      foreach (var subFunctionTreeNode in resolvedTree.IterateNodesPrefix().OfType<SubFunctionTreeNode>()) {
+        var subFunctionTree = individual.SymbolicExpressionTree(subFunctionTreeNode.Name);
+
+        // extract function tree
+        var subTree = subFunctionTree.Root.GetSubtree(0)  // StartSymbol
+                                          .GetSubtree(0); // First Symbol
+        subTree = (ISymbolicExpressionTreeNode)subTree.Clone();
+        subFunctionTreeNode.AddSubtree(subTree);
+      }
+      return resolvedTree;
+    }
+
+    private static void UpdateIndividualFromTree(ISymbolicExpressionTree tree, Individual individual, bool containsNumericParameters) {
+      var clonedTree = (ISymbolicExpressionTree)tree.Clone();
+
+      foreach (var subFunctionTreeNode in clonedTree.IterateNodesPrefix().OfType<SubFunctionTreeNode>()) {
+        var grammar = ((ISymbolicExpressionTree)individual[subFunctionTreeNode.Name]).Root.Grammar;
+        var functionTreeNode = subFunctionTreeNode.GetSubtree(0);
+        //remove function code to make numeric parameters extraction easier
+        subFunctionTreeNode.RemoveSubtree(0);
+
+
+        var rootNode = (SymbolicExpressionTreeTopLevelNode)new ProgramRootSymbol().CreateTreeNode();
+        rootNode.SetGrammar(grammar);
+        var startNode = (SymbolicExpressionTreeTopLevelNode)new StartSymbol().CreateTreeNode();
+        startNode.SetGrammar(grammar);
+
+        rootNode.AddSubtree(startNode);
+        startNode.AddSubtree(functionTreeNode);
+        var functionTree = new SymbolicExpressionTree(rootNode);
+        individual[subFunctionTreeNode.Name] = functionTree;
+      }
+
+      //set numeric parameter values
+      if (containsNumericParameters) {
+        var realVector = individual.RealVector(NumericParametersEncoding);
+        var numberTreeNodes = clonedTree.IterateNodesPrefix().OfType<NumberTreeNode>().ToArray();
+
+        if (realVector.Length != numberTreeNodes.Length)
+          throw new InvalidOperationException("The number of numeric parameters in the tree does not match the provided numerical values.");
+
+        for (int i = 0; i < numberTreeNodes.Length; i++)
+          realVector[i] = numberTreeNodes[i].Value;
+      }
+    }
+
+    public void Load(IRegressionProblemData data) {
+      ProblemData = data;
+    }
+  }
+}
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/GraphicalSymbolicDataAnalysisModelView.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/GraphicalSymbolicDataAnalysisModelView.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/GraphicalSymbolicDataAnalysisModelView.cs	(revision 18220)
@@ -20,4 +20,5 @@
 #endregion
 
+using System.Drawing;
 using System.Windows.Forms;
 using HeuristicLab.MainForm;
@@ -40,7 +41,23 @@
     protected override void OnContentChanged() {
       base.OnContentChanged();
-      symbolicExpressionTreeView.Content = null;
-      if (Content != null)
-        symbolicExpressionTreeView.Content = Content.SymbolicExpressionTree;
+      symbolicExpressionTreeChart.Tree = null;
+      if (Content != null) {
+        symbolicExpressionTreeChart.Tree = Content.SymbolicExpressionTree;
+        RepaintNodes();
+      }
+    }
+
+    protected void RepaintNodes() {
+      var tree = symbolicExpressionTreeChart.Tree;
+      if (tree != null) {
+        foreach (var n in tree.IterateNodesPrefix()) {
+          if (n.Symbol is SubFunctionSymbol) {
+            var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(n);
+            visualNode.FillColor = Color.LightCyan;
+            visualNode.LineColor = Color.SlateGray;
+          }
+        }
+        symbolicExpressionTreeChart.RepaintNodes();
+      }
     }
   }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/GraphicalSymbolicDataAnalysisModelView.designer.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/GraphicalSymbolicDataAnalysisModelView.designer.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/GraphicalSymbolicDataAnalysisModelView.designer.cs	(revision 18220)
@@ -19,4 +19,6 @@
  */
 #endregion
+
+using System.Drawing;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
@@ -45,18 +47,17 @@
     /// </summary>
     private void InitializeComponent() {
-      this.symbolicExpressionTreeView = new HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views.GraphicalSymbolicExpressionTreeView();
+      this.symbolicExpressionTreeChart = new HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views.SymbolicExpressionTreeChart();
       this.SuspendLayout();
       // 
       // expressionTreeView
       // 
-      this.symbolicExpressionTreeView.AllowDrop = true;
-      this.symbolicExpressionTreeView.Caption = "Graphical SymbolicExpressionTree View";
-      this.symbolicExpressionTreeView.Content = null;
-      this.symbolicExpressionTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.symbolicExpressionTreeView.Location = new System.Drawing.Point(0, 0);
-      this.symbolicExpressionTreeView.Name = "expressionTreeView";
-      this.symbolicExpressionTreeView.ReadOnly = false;
-      this.symbolicExpressionTreeView.Size = new System.Drawing.Size(352, 413);
-      this.symbolicExpressionTreeView.TabIndex = 0;
+      this.symbolicExpressionTreeChart.AllowDrop = true;
+      this.symbolicExpressionTreeChart.Tree = null;
+      this.symbolicExpressionTreeChart.TextFont = new System.Drawing.Font(FontFamily.GenericSerif, 8F);
+      this.symbolicExpressionTreeChart.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.symbolicExpressionTreeChart.Location = new System.Drawing.Point(0, 0);
+      this.symbolicExpressionTreeChart.Name = "expressionTreeChart";
+      this.symbolicExpressionTreeChart.Size = new System.Drawing.Size(352, 413);
+      this.symbolicExpressionTreeChart.TabIndex = 0;
       // 
       // SymbolicExpressionModelView
@@ -65,5 +66,5 @@
       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
-      this.Controls.Add(this.symbolicExpressionTreeView);
+      this.Controls.Add(this.symbolicExpressionTreeChart);
       this.Name = "SymbolicExpressionModelView";
       this.Size = new System.Drawing.Size(352, 413);
@@ -73,5 +74,5 @@
 
     #endregion
-    private HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views.GraphicalSymbolicExpressionTreeView symbolicExpressionTreeView;
+    private HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views.SymbolicExpressionTreeChart symbolicExpressionTreeChart;
 
   }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Views-3.4.csproj
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Views-3.4.csproj	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Views-3.4.csproj	(revision 18220)
@@ -122,4 +122,15 @@
       <DependentUpon>InteractiveSymbolicExpressionTreeChart.cs</DependentUpon>
     </Compile>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="StructureTemplate\StructureTemplateView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="StructureTemplate\StructureTemplateView.Designer.cs">
+      <DependentUpon>StructureTemplateView.cs</DependentUpon>
+    </Compile>
     <Compile Include="SymbolicDataAnalysisModelMathView.cs">
       <SubType>UserControl</SubType>
@@ -211,4 +222,5 @@
     </Compile>
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="Resources\structureTemplateHelp.rtf" />
   </ItemGroup>
   <ItemGroup>
@@ -310,4 +322,10 @@
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </Content>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Properties/Resources.Designer.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Properties/Resources.Designer.cs	(revision 18220)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Properties/Resources.Designer.cs	(revision 18220)
@@ -0,0 +1,63 @@
+﻿//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HeuristicLab.Problems.DataAnalysis.Symbolic.Views.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Properties/Resources.resx
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Properties/Resources.resx	(revision 18220)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Properties/Resources.resx	(revision 18220)
@@ -0,0 +1,120 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/StructureTemplate/StructureTemplateView.Designer.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/StructureTemplate/StructureTemplateView.Designer.cs	(revision 18220)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/StructureTemplate/StructureTemplateView.Designer.cs	(revision 18220)
@@ -0,0 +1,202 @@
+﻿
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
+  partial class StructureTemplateView {
+    
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
+      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(StructureTemplateView));
+      this.detailsGroupBox = new System.Windows.Forms.GroupBox();
+      this.viewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
+      this.templateStructureGroupBox = new System.Windows.Forms.GroupBox();
+      this.linearScalingCheckBox = new System.Windows.Forms.CheckBox();
+      this.infoLabel = new System.Windows.Forms.Label();
+      this.treeChart = new HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views.SymbolicExpressionTreeChart();
+      this.parseButton = new System.Windows.Forms.Button();
+      this.expressionInput = new System.Windows.Forms.TextBox();
+      this.splitContainer = new System.Windows.Forms.SplitContainer();
+      this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+      this.errorLabel = new System.Windows.Forms.Label();
+      this.detailsGroupBox.SuspendLayout();
+      this.templateStructureGroupBox.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
+      this.splitContainer.Panel1.SuspendLayout();
+      this.splitContainer.Panel2.SuspendLayout();
+      this.splitContainer.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // detailsGroupBox
+      // 
+      this.detailsGroupBox.Controls.Add(this.viewHost);
+      this.detailsGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.detailsGroupBox.Location = new System.Drawing.Point(0, 0);
+      this.detailsGroupBox.Name = "detailsGroupBox";
+      this.detailsGroupBox.Size = new System.Drawing.Size(296, 400);
+      this.detailsGroupBox.TabIndex = 9;
+      this.detailsGroupBox.TabStop = false;
+      this.detailsGroupBox.Text = "Details";
+      // 
+      // viewHost
+      // 
+      this.viewHost.Caption = "View";
+      this.viewHost.Content = null;
+      this.viewHost.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.viewHost.Enabled = false;
+      this.viewHost.Location = new System.Drawing.Point(3, 16);
+      this.viewHost.Name = "viewHost";
+      this.viewHost.ReadOnly = false;
+      this.viewHost.Size = new System.Drawing.Size(290, 381);
+      this.viewHost.TabIndex = 8;
+      this.viewHost.ViewsLabelVisible = true;
+      this.viewHost.ViewType = null;
+      // 
+      // templateStructureGroupBox
+      // 
+      this.templateStructureGroupBox.Controls.Add(this.errorLabel);
+      this.templateStructureGroupBox.Controls.Add(this.linearScalingCheckBox);
+      this.templateStructureGroupBox.Controls.Add(this.infoLabel);
+      this.templateStructureGroupBox.Controls.Add(this.treeChart);
+      this.templateStructureGroupBox.Controls.Add(this.parseButton);
+      this.templateStructureGroupBox.Controls.Add(this.expressionInput);
+      this.templateStructureGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.templateStructureGroupBox.Location = new System.Drawing.Point(0, 0);
+      this.templateStructureGroupBox.Name = "templateStructureGroupBox";
+      this.templateStructureGroupBox.Size = new System.Drawing.Size(300, 400);
+      this.templateStructureGroupBox.TabIndex = 8;
+      this.templateStructureGroupBox.TabStop = false;
+      this.templateStructureGroupBox.Text = "Template Structure";
+      // 
+      // linearScalingCheckBox
+      // 
+      this.linearScalingCheckBox.AutoSize = true;
+      this.linearScalingCheckBox.Location = new System.Drawing.Point(149, 49);
+      this.linearScalingCheckBox.Name = "linearScalingCheckBox";
+      this.linearScalingCheckBox.Size = new System.Drawing.Size(122, 17);
+      this.linearScalingCheckBox.TabIndex = 8;
+      this.linearScalingCheckBox.Text = "Apply Linear Scaling";
+      this.linearScalingCheckBox.UseVisualStyleBackColor = true;
+      this.linearScalingCheckBox.CheckStateChanged += new System.EventHandler(this.LinearScalingCheckBoxCheckStateChanged);
+      // 
+      // infoLabel
+      // 
+      this.infoLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.infoLabel.BackColor = System.Drawing.Color.White;
+      this.infoLabel.Image = HeuristicLab.Common.Resources.VSImageLibrary.Information;
+      this.infoLabel.Location = new System.Drawing.Point(275, 22);
+      this.infoLabel.Name = "infoLabel";
+      this.infoLabel.Size = new System.Drawing.Size(15, 15);
+      this.infoLabel.TabIndex = 4;
+      this.infoLabel.Text = "    ";
+      this.toolTip.SetToolTip(this.infoLabel, "Double-click to open description.");
+      this.infoLabel.DoubleClick += new System.EventHandler(this.HelpButtonDoubleClick);
+      // 
+      // treeChart
+      // 
+      this.treeChart.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.treeChart.BackgroundColor = System.Drawing.Color.White;
+      this.treeChart.LineColor = System.Drawing.Color.Black;
+      this.treeChart.Location = new System.Drawing.Point(3, 74);
+      this.treeChart.MinimumHorizontalDistance = 30;
+      this.treeChart.MinimumHorizontalPadding = 20;
+      this.treeChart.MinimumVerticalDistance = 30;
+      this.treeChart.MinimumVerticalPadding = 20;
+      this.treeChart.Name = "treeChart";
+      this.treeChart.PreferredNodeHeight = 46;
+      this.treeChart.PreferredNodeWidth = 70;
+      this.treeChart.Size = new System.Drawing.Size(291, 320);
+      this.treeChart.SuspendRepaint = false;
+      this.treeChart.TabIndex = 7;
+      this.treeChart.TextFont = new System.Drawing.Font("Times New Roman", 8F);
+      this.treeChart.Tree = null;
+      // 
+      // parseButton
+      // 
+      this.parseButton.Location = new System.Drawing.Point(3, 45);
+      this.parseButton.Name = "parseButton";
+      this.parseButton.Size = new System.Drawing.Size(140, 23);
+      this.parseButton.TabIndex = 3;
+      this.parseButton.Text = "Parse";
+      this.parseButton.UseVisualStyleBackColor = true;
+      this.parseButton.Click += new System.EventHandler(this.ParseButtonClick);
+      // 
+      // expressionInput
+      // 
+      this.expressionInput.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.expressionInput.Location = new System.Drawing.Point(3, 19);
+      this.expressionInput.Name = "expressionInput";
+      this.expressionInput.Size = new System.Drawing.Size(266, 20);
+      this.expressionInput.TabIndex = 1;
+      this.expressionInput.TextChanged += new System.EventHandler(this.ExpressionInputTextChanged);
+      this.expressionInput.KeyUp += new System.Windows.Forms.KeyEventHandler(this.ExpressionInputKeyUp);
+      // 
+      // splitContainer
+      // 
+      this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.splitContainer.Location = new System.Drawing.Point(0, 0);
+      this.splitContainer.Margin = new System.Windows.Forms.Padding(0);
+      this.splitContainer.Name = "splitContainer";
+      // 
+      // splitContainer.Panel1
+      // 
+      this.splitContainer.Panel1.Controls.Add(this.templateStructureGroupBox);
+      this.splitContainer.Panel1MinSize = 5;
+      // 
+      // splitContainer.Panel2
+      // 
+      this.splitContainer.Panel2.Controls.Add(this.detailsGroupBox);
+      this.splitContainer.Panel2MinSize = 5;
+      this.splitContainer.Size = new System.Drawing.Size(600, 400);
+      this.splitContainer.SplitterDistance = 300;
+      this.splitContainer.TabIndex = 10;
+      // 
+      // errorLabel
+      // 
+      this.errorLabel.AutoSize = true;
+      this.errorLabel.BackColor = System.Drawing.Color.White;
+      this.errorLabel.Location = new System.Drawing.Point(3, 74);
+      this.errorLabel.Name = "errorLabel";
+      this.errorLabel.Size = new System.Drawing.Size(0, 13);
+      this.errorLabel.TabIndex = 9;
+      // 
+      // StructureTemplateView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.splitContainer);
+      this.Name = "StructureTemplateView";
+      this.Size = new System.Drawing.Size(600, 400);
+      this.detailsGroupBox.ResumeLayout(false);
+      this.templateStructureGroupBox.ResumeLayout(false);
+      this.templateStructureGroupBox.PerformLayout();
+      this.splitContainer.Panel1.ResumeLayout(false);
+      this.splitContainer.Panel2.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
+      this.splitContainer.ResumeLayout(false);
+      this.ResumeLayout(false);
+
+    }
+
+
+    private System.Windows.Forms.GroupBox detailsGroupBox;
+    private MainForm.WindowsForms.ViewHost viewHost;
+    private System.Windows.Forms.GroupBox templateStructureGroupBox;
+    private System.Windows.Forms.CheckBox linearScalingCheckBox;
+    private System.Windows.Forms.Label infoLabel;
+    private Encodings.SymbolicExpressionTreeEncoding.Views.SymbolicExpressionTreeChart treeChart;
+    private System.Windows.Forms.Button parseButton;
+    private System.Windows.Forms.TextBox expressionInput;
+    private System.Windows.Forms.SplitContainer splitContainer;
+    private System.ComponentModel.IContainer components;
+    private ToolTip toolTip;
+    private Label errorLabel;
+  }
+}
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/StructureTemplate/StructureTemplateView.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/StructureTemplate/StructureTemplateView.cs	(revision 18220)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/StructureTemplate/StructureTemplateView.cs	(revision 18220)
@@ -0,0 +1,126 @@
+﻿ using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.Collections;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
+
+  [View("StructureTemplate View")]
+  [Content(typeof(StructureTemplate), true)]
+  public partial class StructureTemplateView : AsynchronousContentView {
+    public new StructureTemplate Content {
+      get => (StructureTemplate)base.Content;
+      set => base.Content = value;
+    }
+
+    public StructureTemplateView() {
+      InitializeComponent();
+      errorLabel.Text = "";
+      this.Resize += StructureTemplateViewResize;
+      splitContainer.SplitterMoved += SplitContainerSplitterMoved;
+      treeChart.SymbolicExpressionTreeNodeClicked += SymbolicExpressionTreeNodeClicked;
+      
+    }
+
+    private void SplitContainerSplitterMoved(object sender, EventArgs e) {
+      PaintTree();
+    }
+
+    private void StructureTemplateViewResize(object sender, EventArgs e) {
+      PaintTree();
+    }
+
+    private void SymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs e) {
+      var visualTreeNode = sender as VisualTreeNode<ISymbolicExpressionTreeNode>;
+      if(visualTreeNode != null && visualTreeNode.Content is SubFunctionTreeNode subFunctionTreeNode) {
+        var selectedSubFunction = Content.SubFunctions.Where(x => x.Name == subFunctionTreeNode.Name).FirstOrDefault();
+        if(subFunctionTreeNode != null && selectedSubFunction != null)
+          viewHost.Content = selectedSubFunction;
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      parseButton.Enabled = Content != null && !Locked && !ReadOnly;
+      linearScalingCheckBox.Enabled = Content != null && !Locked && !ReadOnly;
+      expressionInput.Enabled = Content != null && !Locked && !ReadOnly;
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null) return;
+      expressionInput.Text = Content.Template;
+      linearScalingCheckBox.Checked = Content.ApplyLinearScaling; 
+      PaintTree();
+      errorLabel.Text = "";
+    }
+
+    private void ParseButtonClick(object sender, EventArgs e) {
+      Parse();
+    }
+
+    private void ExpressionInputTextChanged(object sender, EventArgs e) {
+      errorLabel.Text = "Unparsed changes! Press parse button to save changes.";
+      errorLabel.ForeColor = Color.DarkOrange;
+    }
+
+    private void PaintTree() {
+      if(Content != null && Content.Tree != null) {
+        treeChart.Tree = Content.Tree;
+        foreach (var n in Content.Tree.IterateNodesPrefix()) {
+          if (n.Symbol is SubFunctionSymbol) {
+            var visualNode = treeChart.GetVisualSymbolicExpressionTreeNode(n);
+            visualNode.FillColor = Color.LightCyan;
+            visualNode.LineColor = Color.SlateGray;
+          }
+        }
+        treeChart.RepaintNodes();
+      }
+    }
+
+    private void ExpressionInputKeyUp(object sender, KeyEventArgs e) {
+      if (e.KeyCode == Keys.Enter)
+        Parse();
+    }
+
+    private void Parse() {
+      viewHost.Content = null; // reset active detail view
+      if (!string.IsNullOrEmpty(expressionInput.Text)) {
+        try {
+          Content.Template = expressionInput.Text;
+          PaintTree();
+          errorLabel.Text = "Template structure successfully parsed.";
+          errorLabel.ForeColor = Color.DarkGreen;
+        } catch (AggregateException ex) {
+          errorLabel.Text = string.Join("\n", ex.InnerExceptions.Select(x => x.Message));
+          errorLabel.ForeColor = Color.DarkRed;
+        } catch (Exception ex) {
+          errorLabel.Text = ex.Message;
+          errorLabel.ForeColor = Color.DarkRed;
+        }
+      }
+    }
+
+    private void LinearScalingCheckBoxCheckStateChanged(object sender, EventArgs e) {
+      Content.ApplyLinearScaling = linearScalingCheckBox.Checked;
+      PaintTree();
+    }
+
+    private void HelpButtonDoubleClick(object sender, EventArgs e) {
+      using (InfoBox dialog = new InfoBox("Help for structure template",
+        "HeuristicLab.Problems.DataAnalysis.Symbolic.Views.Resources.structureTemplateHelp.rtf",
+        this)) {
+        dialog.ShowDialog(this);
+      }
+    }
+  }
+}
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs	(revision 18220)
@@ -199,4 +199,7 @@
         var tanh = (ISymbolicExpressionTreeNode)branch.Clone();
         return Product(fxp, Subtract(CreateNumber(1.0), Square(tanh)));
+      }
+      if (branch.Symbol is SubFunctionSymbol) {
+        return Derive(branch.GetSubtree(0), variableName);
       }
       throw new NotSupportedException(string.Format("Symbol {0} is not supported.", branch.Symbol));
@@ -285,5 +288,6 @@
           !(n.Symbol is Cosine) &&
           !(n.Symbol is Tangent) &&
-          !(n.Symbol is StartSymbol)
+          !(n.Symbol is StartSymbol) &&
+          !(n.Symbol is SubFunctionSymbol)
         select n).Any();
       return !containsUnknownSymbol;
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs	(revision 18220)
@@ -106,6 +106,15 @@
       out ParametricFunctionGradient func_grad) {
 
+      return TryConvertToAutoDiff(tree, makeVariableWeightsVariable, addLinearScalingTerms, Enumerable.Empty<ISymbolicExpressionTreeNode>(),
+        out parameters, out initialParamValues, out func, out func_grad);
+    }
+
+    public static bool TryConvertToAutoDiff(ISymbolicExpressionTree tree, bool makeVariableWeightsVariable, bool addLinearScalingTerms, IEnumerable<ISymbolicExpressionTreeNode> excludedNodes,
+      out List<DataForVariable> parameters, out double[] initialParamValues,
+      out ParametricFunction func,
+      out ParametricFunctionGradient func_grad) {
+
       // use a transformator object which holds the state (variable list, parameter list, ...) for recursive transformation of the tree
-      var transformator = new TreeToAutoDiffTermConverter(makeVariableWeightsVariable, addLinearScalingTerms);
+      var transformator = new TreeToAutoDiffTermConverter(makeVariableWeightsVariable, addLinearScalingTerms, excludedNodes);
       AutoDiff.Term term;
       try {
@@ -134,8 +143,11 @@
     private readonly bool makeVariableWeightsVariable;
     private readonly bool addLinearScalingTerms;
-
-    private TreeToAutoDiffTermConverter(bool makeVariableWeightsVariable, bool addLinearScalingTerms) {
+    private readonly HashSet<ISymbolicExpressionTreeNode> excludedNodes;
+
+    private TreeToAutoDiffTermConverter(bool makeVariableWeightsVariable, bool addLinearScalingTerms, IEnumerable<ISymbolicExpressionTreeNode> excludedNodes) {
       this.makeVariableWeightsVariable = makeVariableWeightsVariable;
       this.addLinearScalingTerms = addLinearScalingTerms;
+      this.excludedNodes = new HashSet<ISymbolicExpressionTreeNode>(excludedNodes);
+
       this.initialParamValues = new List<double>();
       this.parameters = new Dictionary<DataForVariable, AutoDiff.Variable>();
@@ -161,5 +173,5 @@
         var par = FindOrCreateParameter(parameters, varNode.VariableName, varValue);
 
-        if (makeVariableWeightsVariable) {
+        if (makeVariableWeightsVariable && !excludedNodes.Contains(node)) {
           initialParamValues.Add(varNode.Weight);
           var w = new AutoDiff.Variable();
@@ -176,9 +188,15 @@
           var par = FindOrCreateParameter(parameters, factorVarNode.VariableName, variableValue);
 
-          initialParamValues.Add(factorVarNode.GetValue(variableValue));
-          var wVar = new AutoDiff.Variable();
-          variables.Add(wVar);
-
-          products.Add(AutoDiff.TermBuilder.Product(wVar, par));
+          if (makeVariableWeightsVariable && !excludedNodes.Contains(node)) {
+            initialParamValues.Add(factorVarNode.GetValue(variableValue));
+            var wVar = new AutoDiff.Variable();
+            variables.Add(wVar);
+
+            products.Add(AutoDiff.TermBuilder.Product(wVar, par));
+          } else {
+            var weight = factorVarNode.GetValue(variableValue);
+            products.Add(weight * par);
+          }
+
         }
         return AutoDiff.TermBuilder.Sum(products);
@@ -188,5 +206,5 @@
         var par = FindOrCreateParameter(parameters, varNode.VariableName, string.Empty, varNode.Lag);
 
-        if (makeVariableWeightsVariable) {
+        if (makeVariableWeightsVariable && !excludedNodes.Contains(node)) {
           initialParamValues.Add(varNode.Weight);
           var w = new AutoDiff.Variable();
@@ -305,4 +323,7 @@
           return t * alpha + beta;
         } else return ConvertToAutoDiff(node.GetSubtree(0));
+      }
+      if (node.Symbol is SubFunctionSymbol) {
+        return ConvertToAutoDiff(node.GetSubtree(0));
       }
       throw new ConversionException();
@@ -353,5 +374,6 @@
           !(n.Symbol is Cube) &&
           !(n.Symbol is CubeRoot) &&
-          !(n.Symbol is Power)
+          !(n.Symbol is Power) &&
+          !(n.Symbol is SubFunctionSymbol)
         select n).Any();
       return !containsUnknownSymbol;
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 18220)
@@ -35,4 +35,5 @@
     ///  Performs some basic re-writing steps to simplify the code for formatting. Tree is changed.
     ///  Removes single-argument +, * which have no effect
+    ///  Removes SubFunctions (no effect)
     ///  Replaces variables with coefficients by an explicitly multiplication
     ///  Replaces single-argument / with 1 / (..)
@@ -57,4 +58,6 @@
         mul.AddSubtree(num);
         mul.AddSubtree(varTreeNode);
+      } else if (n.Symbol is SubFunctionSymbol) {
+        parent.ReplaceSubtree(n, n.GetSubtree(0));
       } else if (n.SubtreeCount == 1 && (n.Symbol is Addition || n.Symbol is Multiplication || n.Symbol is And || n.Symbol is Or || n.Symbol is Xor)) {
         // single-argument addition or multiplication has no effect -> remove
@@ -81,6 +84,6 @@
         }
         parent.InsertSubtree(childIdx, newChild);
-      } else if (n.SubtreeCount == 2 && n.GetSubtree(1).SubtreeCount == 2 && 
-                 IsAssocOp(n.Symbol) && IsOperator(n.GetSubtree(1).Symbol) && 
+      } else if (n.SubtreeCount == 2 && n.GetSubtree(1).SubtreeCount == 2 &&
+                 IsAssocOp(n.Symbol) && IsOperator(n.GetSubtree(1).Symbol) &&
                  Priority(n.Symbol) == Priority(n.GetSubtree(1).Symbol)) {
         // f(x) <op> (g(x) <op> h(x))) is the same as  (f(x) <op> g(x)) <op> h(x) for associative <op>
@@ -104,6 +107,4 @@
                                           NumberFormatInfo numberFormat, string formatString, List<KeyValuePair<string, double>> parameters = null) {
       // This method assumes that the tree has been converted to binary and left-assoc form (see ConvertToBinaryLeftAssocRec). 
-      // An exception is thrown if the tree has a different shape.
-
       if (node.SubtreeCount == 0) {
         // no subtrees
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs	(revision 18220)
@@ -155,4 +155,6 @@
           FormatRecursively(node.GetSubtree(1), strBuilder);
           strBuilder.Append(" , 2) ) )");
+        } else if (node.Symbol is SubFunctionSymbol) {
+          FormatRecursively(node.GetSubtree(0), strBuilder);
         } else {
           throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " not supported for C# symbolic expression tree formatter.");
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs	(revision 18220)
@@ -310,4 +310,6 @@
         stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
         stringBuilder.Append("), 1.0, -1.0)");
+      } else if (symbol is SubFunctionSymbol) {
+        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
       } else {
         throw new NotImplementedException("Excel export of " + node.Symbol + " is not implemented.");
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs	(revision 18220)
@@ -279,4 +279,6 @@
         paramIdx++;
         strBuilder.Append(@" \left( " + p + @"\cdot ");
+      } else if (node.Symbol is SubFunctionSymbol) {
+        // to nothing, skip symbol
       } else {
         throw new NotImplementedException("Export of " + node.Symbol + " is not implemented.");
@@ -387,4 +389,6 @@
         paramIdx++;
         strBuilder.Append(@" +  \left( 1 - " + p + @" \right) \cdot ");
+      } else if (node.Symbol is SubFunctionSymbol) {
+        throw new InvalidOperationException();
       } else {
         throw new NotImplementedException("Export of " + node.Symbol + " is not implemented.");
@@ -511,4 +515,5 @@
       } else if (node.Symbol is VariableCondition) {
         strBuilder.Append(@"\right) ");
+      } else if (node.Symbol is SubFunctionSymbol) {
       } else {
         throw new NotImplementedException("Export of " + node.Symbol + " is not implemented.");
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMATLABFormatter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMATLABFormatter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMATLABFormatter.cs	(revision 18220)
@@ -388,4 +388,6 @@
         stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
         currentLag -= laggedNode.Lag;
+      } else if (symbol is SubFunctionSymbol) {
+        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
       } else {
         stringBuilder.Append("ERROR");
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs	(revision 18220)
@@ -122,4 +122,6 @@
         } else if (node.Symbol is Root) {
           FormatRoot(node, strBuilder);
+        } else if (node.Symbol is SubFunctionSymbol) {
+          FormatRecursively(node.GetSubtree(0), strBuilder);
         } else {
           throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " is not supported.");
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionPythonFormatter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionPythonFormatter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionPythonFormatter.cs	(revision 18220)
@@ -204,4 +204,6 @@
       else if (node is INumericTreeNode)
         FormatNumericTreeNode(node, strBuilder);
+      else if (symbol is SubFunctionSymbol)
+        FormatRecursively(node.GetSubtree(0), strBuilder);
       else
         throw new NotSupportedException("Formatting of symbol: " + symbol + " not supported for Python symbolic expression tree formatter.");
@@ -228,10 +230,6 @@
 
     private static void FormatNumericTreeNode(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
-      var symbol = node.Symbol;
-      if (node is INumericTreeNode numNode) {
-        strBuilder.Append(numNode.Value.ToString("g17", CultureInfo.InvariantCulture));
-      } else {
-        throw new NotSupportedException("Formatting of symbol: " + symbol + " not supported for Python symbolic expression tree formatter.");
-      }
+      var numNode = node as INumericTreeNode;
+      strBuilder.Append(numNode.Value.ToString("g17", CultureInfo.InvariantCulture));
     }
 
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionSmalltalkFormatter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionSmalltalkFormatter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionSmalltalkFormatter.cs	(revision 18220)
@@ -184,4 +184,6 @@
       } else if (symbol is BinaryFactorVariable || symbol is FactorVariable) {
         stringBuilder.Append("factor variables are not supported");
+      } else if (symbol is SubFunctionSymbol) {
+        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
       } else {
         stringBuilder.Append("(");
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/TSQLExpressionFormatter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/TSQLExpressionFormatter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/TSQLExpressionFormatter.cs	(revision 18220)
@@ -157,4 +157,6 @@
         } else if (node.Symbol is Root) {
           FormatRoot(level, node, strBuilder);
+        } else if (node.Symbol is SubFunctionSymbol) {
+          FormatRecursively(level, node.GetSubtree(0), strBuilder);
         } else {
           throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " not supported for TSQL symbolic expression tree formatter.");
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs	(revision 18220)
@@ -30,16 +30,16 @@
   [Item("TypeCoherentExpressionGrammar", "Represents a grammar for functional expressions in which special syntactic constraints are enforced so that boolean and real-valued expressions are not mixed.")]
   public class TypeCoherentExpressionGrammar : DataAnalysisGrammar, ISymbolicDataAnalysisGrammar {
-    private const string ArithmeticFunctionsName = "Arithmetic Functions";
-    private const string TrigonometricFunctionsName = "Trigonometric Functions";
-    private const string ExponentialFunctionsName = "Exponential and Logarithmic Functions";
-    private const string RealValuedSymbolsName = "Real Valued Symbols";
-    private const string TerminalsName = "Terminals";
-    private const string PowerFunctionsName = "Power Functions";
-    private const string ConditionsName = "Conditions";
-    private const string ComparisonsName = "Comparisons";
-    private const string BooleanOperatorsName = "Boolean Operators";
-    private const string ConditionalSymbolsName = "ConditionalSymbols";
-    private const string SpecialFunctionsName = "Special Functions";
-    private const string TimeSeriesSymbolsName = "Time Series Symbols";
+    public const string ArithmeticFunctionsName = "Arithmetic Functions";
+    public const string TrigonometricFunctionsName = "Trigonometric Functions";
+    public const string ExponentialFunctionsName = "Exponential and Logarithmic Functions";
+    public const string RealValuedSymbolsName = "Real Valued Symbols";
+    public const string TerminalsName = "Terminals";
+    public const string PowerFunctionsName = "Power Functions";
+    public const string ConditionsName = "Conditions";
+    public const string ComparisonsName = "Comparisons";
+    public const string BooleanOperatorsName = "Boolean Operators";
+    public const string ConditionalSymbolsName = "ConditionalSymbols";
+    public const string SpecialFunctionsName = "Special Functions";
+    public const string TimeSeriesSymbolsName = "Time Series Symbols";
 
     [StorableConstructor]
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 18220)
@@ -188,5 +188,8 @@
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs" />
     <Compile Include="IntervalUtil.cs" />
+    <Compile Include="LinearScaling.cs" />
     <Compile Include="Selectors\DiversitySelector.cs" />
+    <Compile Include="StructureTemplate\StructureTemplate.cs" />
+    <Compile Include="StructureTemplate\SubFunction.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionTreeAverageSimilarityCalculator.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs" />
@@ -256,4 +259,6 @@
     <Compile Include="Symbols\Constant.cs" />
     <Compile Include="Symbols\ConstantTreeNode.cs" />
+    <Compile Include="Symbols\SubFunctionSymbol.cs" />
+    <Compile Include="Symbols\SubFunctionTreeNode.cs" />
     <Compile Include="Symbols\VariableBase.cs" />
     <Compile Include="Symbols\VariableTreeNodeBase.cs" />
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 18220)
@@ -82,4 +82,5 @@
     internal static readonly BidirectionalLookup<string, ISymbol>
       knownSymbols = new BidirectionalLookup<string, ISymbol>(StringComparer.InvariantCulture, new SymbolComparer());
+    internal static readonly SubFunctionSymbol subFunctionSymbol = new SubFunctionSymbol();
 
     private Number number = new Number();
@@ -328,7 +329,8 @@
 
     private ISymbol GetSymbol(string tok) {
-      var symb = knownSymbols.GetByFirst(tok).FirstOrDefault();
-      if (symb == null) throw new ArgumentException(string.Format("Unknown token {0} found.", tok));
-      return symb;
+      if (knownSymbols.ContainsFirst(tok))
+        return knownSymbols.GetByFirst(tok).FirstOrDefault();
+      else
+        return subFunctionSymbol;
     }
 
@@ -581,4 +583,14 @@
       if (funcNode.Symbol is LaggedVariable) {
         ParseLaggedVariable(tokens, funcNode);
+      } else if (funcNode.Symbol is SubFunctionSymbol) { // SubFunction
+        var subFunction = funcNode as SubFunctionTreeNode;
+        subFunction.Name = idTok.strVal;
+        // input arguments
+        var args = ParseArgList(tokens);
+        IList<string> arguments = new List<string>();
+        foreach (var arg in args)
+          if (arg is VariableTreeNode varTreeNode)
+            arguments.Add(varTreeNode.VariableName);
+        subFunction.Arguments = arguments;
       } else {
         // functions
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs	(revision 18220)
@@ -172,5 +172,5 @@
           Expect(Token.EQ, tokens);
           var initValToken = tokens.Dequeue();
-          if(initValToken.Symbol == TokenSymbol.CONSTANT) {
+          if (initValToken.Symbol == TokenSymbol.CONSTANT) {
             t.Value = initValToken.DoubleValue;
           } else {
@@ -289,5 +289,5 @@
       if (token.Symbol != TokenSymbol.SYMB &&
           token.Symbol != TokenSymbol.LBRACKET &&  // LBRACKET and RBRACKET are used for <num=..> and as LT, GT operators
-          token.Symbol != TokenSymbol.RBRACKET  
+          token.Symbol != TokenSymbol.RBRACKET
           ) throw new FormatException("Expected function symbol, but got: " + token.StringValue);
       return knownSymbols[token.StringValue].CreateTreeNode();
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithBoundsEstimator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithBoundsEstimator.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithBoundsEstimator.cs	(revision 18220)
@@ -248,4 +248,8 @@
 
             break;
+          }
+        case OpCodes.SubFunction: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+          break;
           }
         default:
@@ -344,5 +348,6 @@
           !(n.Symbol is Power) &&
           !(n.Symbol is Absolute) &&
-          !(n.Symbol is AnalyticQuotient)
+          !(n.Symbol is AnalyticQuotient) &&
+          !(n.Symbol is SubFunctionSymbol)
         select n).Any();
       return !containsUnknownSymbols;
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 18220)
@@ -22,5 +22,4 @@
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 
@@ -79,4 +78,5 @@
     CubeRoot = 51,
     Tanh = 52,
+    SubFunction = 53,
     Constant = 54
   };
@@ -84,11 +84,11 @@
     // constants for API compatibility only
     public const byte Add = (byte)OpCode.Add;
-    public const byte Sub =(byte)OpCode.Sub;
-    public const byte Mul =(byte)OpCode.Mul;
-    public const byte Div =(byte)OpCode.Div;
-    public const byte Sin =(byte)OpCode.Sin;
-    public const byte Cos =(byte)OpCode.Cos;
-    public const byte Tan =(byte)OpCode.Tan;
-    public const byte Log =(byte)OpCode.Log;
+    public const byte Sub = (byte)OpCode.Sub;
+    public const byte Mul = (byte)OpCode.Mul;
+    public const byte Div = (byte)OpCode.Div;
+    public const byte Sin = (byte)OpCode.Sin;
+    public const byte Cos = (byte)OpCode.Cos;
+    public const byte Tan = (byte)OpCode.Tan;
+    public const byte Log = (byte)OpCode.Log;
     public const byte Exp = (byte)OpCode.Exp;
     public const byte IfThenElse = (byte)OpCode.IfThenElse;
@@ -103,5 +103,5 @@
     public const byte LagVariable = (byte)OpCode.LagVariable;
     public const byte Number = (byte)OpCode.Number;
-    public const byte Constant = (byte) OpCode.Constant;
+    public const byte Constant = (byte)OpCode.Constant;
     public const byte Arg = (byte)OpCode.Arg;
     public const byte Power = (byte)OpCode.Power;
@@ -136,8 +136,8 @@
     public const byte CubeRoot = (byte)OpCode.CubeRoot;
     public const byte Tanh = (byte)OpCode.Tanh;
-
+    public const byte SubFunction = (byte)OpCode.SubFunction;
 
     private static Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() {
-       { typeof(Addition), OpCodes.Add },
+      { typeof(Addition), OpCodes.Add },
       { typeof(Subtraction), OpCodes.Sub },
       { typeof(Multiplication), OpCodes.Mul },
@@ -192,5 +192,6 @@
       { typeof(AnalyticQuotient), OpCodes.AnalyticQuotient },
       { typeof(Cube), OpCodes.Cube },
-      { typeof(CubeRoot), OpCodes.CubeRoot }
+      { typeof(CubeRoot), OpCodes.CubeRoot },
+      { typeof(SubFunctionSymbol), OpCodes.SubFunction }
     };
 
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs	(revision 18220)
@@ -662,4 +662,7 @@
               );
           }
+        case OpCodes.SubFunction: {
+          return MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+        }
         default:
           throw new NotSupportedException("Unsupported symbol: " + node.Symbol);
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs	(revision 18220)
@@ -182,8 +182,10 @@
               break;
             }
+
           case OpCodes.Tanh: {
               Tanh(instr.buf, code[c].buf);
               break;
             }
+
           case OpCodes.Absolute: {
               Absolute(instr.buf, code[c].buf);
@@ -194,4 +196,9 @@
               Load(instr.buf, code[c].buf);
               AnalyticQuotient(instr.buf, code[c + 1].buf);
+              break;
+            }
+
+          case OpCodes.SubFunction: {
+              Load(instr.buf, code[c].buf);
               break;
             }
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 18220)
@@ -724,4 +724,8 @@
                                             " is not supported by the SymbolicDataAnalysisTreeILEmittingInterpreter");
           }
+        case OpCodes.SubFunction: {
+          CompileInstructions(il, state, ds);
+          return;
+        }
         default:
           throw new NotSupportedException("Interpretation of symbol " + currentInstr.dynamicNode.Symbol.Name +
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 18220)
@@ -529,4 +529,7 @@
             }
           }
+        case OpCodes.SubFunction: {
+            return Evaluate(dataset, ref row, state);
+          }
         default:
           throw new NotSupportedException();
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 18220)
@@ -388,4 +388,6 @@
           state.Reset();
           instr.value = interpreter.Evaluate(dataset, ref row, state);
+        } else if (instr.opCode == OpCodes.SubFunction) {
+          instr.value = code[instr.childIndex].value;
         } else {
           var errorText = string.Format("The {0} symbol is not supported by the linear interpreter. To support this symbol, please use the SymbolicDataAnalysisExpressionTreeInterpreter.", instr.dynamicNode.Symbol.Name);
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs	(revision 18220)
@@ -122,5 +122,6 @@
       (byte)OpCode.Cube,
       (byte)OpCode.Absolute,
-      (byte)OpCode.AnalyticQuotient
+      (byte)OpCode.AnalyticQuotient,
+      (byte)OpCode.SubFunction
     };
 
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/LinearScaling.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/LinearScaling.cs	(revision 18220)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/LinearScaling.cs	(revision 18220)
@@ -0,0 +1,92 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 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 System;
+using System.Linq;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public static class LinearScaling {
+
+    public static ISymbolicExpressionTree AddLinearScalingTerms(ISymbolicExpressionTree tree, double offset = 0.0, double scale = 1.0) {
+      var startNode = tree.Root.Subtrees.First();
+      var template = startNode.Subtrees.First();
+
+      var addNode = new Addition().CreateTreeNode();
+      var mulNode = new Multiplication().CreateTreeNode();
+      var offsetNode = new NumberTreeNode(offset);
+      var scaleNode = new NumberTreeNode(scale);
+
+      addNode.AddSubtree(offsetNode);
+      addNode.AddSubtree(mulNode);
+      mulNode.AddSubtree(scaleNode);
+
+      startNode.RemoveSubtree(0);
+      startNode.AddSubtree(addNode);
+      mulNode.AddSubtree(template);
+      return tree;
+    }
+
+    public static void RemoveLinearScalingTerms(ISymbolicExpressionTree tree) {
+      var startNode = tree.Root.GetSubtree(0);
+      ExtractScalingTerms(tree, out _, out NumberTreeNode scaleNode);
+
+      var evaluationNode = scaleNode.Parent.GetSubtree(1); //move up to multiplication and take second child
+      startNode.RemoveSubtree(0);
+      startNode.AddSubtree(evaluationNode);
+    }
+
+    public static void ExtractScalingTerms(ISymbolicExpressionTree tree,
+      out NumberTreeNode offset, out NumberTreeNode scale) {
+      var startNode = tree.Root.Subtrees.First();
+
+      //check for scaling terms
+      var addNode = startNode.GetSubtree(0);
+      var offsetNode = addNode.GetSubtree(0);
+      var mulNode = addNode.GetSubtree(1);
+      var scaleNode = mulNode.GetSubtree(0);
+
+
+      var error = false;
+      if (!(addNode.Symbol is Addition)) error = true;
+      if (!(mulNode.Symbol is Multiplication)) error = true;
+      if (!(offsetNode is NumberTreeNode)) error = true;
+      if (!(scaleNode is NumberTreeNode)) error = true;
+      if (error) throw new ArgumentException("Scaling terms cannot be found.");
+
+      offset = (NumberTreeNode)offsetNode;
+      scale = (NumberTreeNode)scaleNode;
+    }
+
+    public static void AdjustLinearScalingParams(IRegressionProblemData problemData, ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter) {
+      ExtractScalingTerms(tree, out NumberTreeNode offsetNode, out NumberTreeNode scaleNode);
+
+      var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, problemData.TrainingIndices);
+      var targetValues = problemData.TargetVariableTrainingValues;
+
+      OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out double a, out double b, out OnlineCalculatorError error);
+      if (error == OnlineCalculatorError.None) {
+        offsetNode.Value = a + b * offsetNode.Value;
+        scaleNode.Value = b * scaleNode.Value;
+      }
+    }
+  }
+}
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/StructureTemplate.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/StructureTemplate.cs	(revision 18220)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/StructureTemplate.cs	(revision 18220)
@@ -0,0 +1,190 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 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 System;
+using System.Collections.Generic;
+using System.Linq;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableType("E3C038DB-C6AA-457D-9F65-AF16C44CCE22")]
+  [Item("StructureTemplate", "Structure Template")]
+  public class StructureTemplate : Item {
+
+    #region Properties
+    [Storable]
+    private string template;
+    public string Template {
+      get => template;
+      set {
+        if (value == template) return;
+
+        var parsedTree = Parser.Parse(value);
+        //assignment must be done after successfully parsing the tree
+        template = value;
+
+        if (applyLinearScaling)
+          parsedTree = LinearScaling.AddLinearScalingTerms(parsedTree);
+        Tree = parsedTree;
+        OnChanged();
+      }
+    }
+
+    private ISymbolicExpressionTree _oldTree;
+    [Storable(OldName = "treeWithoutLinearScaling")]
+    private ISymbolicExpressionTree _OldTreeW {
+      set => _oldTree = value;
+    }
+
+    [Storable]
+    private ISymbolicExpressionTree tree;
+    public ISymbolicExpressionTree Tree {
+      get => tree;
+      private set {
+        containsNumericParameters = null;
+
+        var newFunctions = CreateSubFunctions(value);
+        var oldFunctions = subFunctions?.Intersect(newFunctions)
+                           ?? Enumerable.Empty<SubFunction>();
+        // adds new functions and keeps the old ones (if they match)
+        var functionsToAdd = newFunctions.Except(oldFunctions);
+        subFunctions = functionsToAdd.Concat(oldFunctions).ToList();
+        RegisterSubFunctionEventHandlers(functionsToAdd);
+
+        tree = value;
+      }
+    }
+
+    private bool? containsNumericParameters;
+    public bool ContainsNumericParameters {
+      get {
+        if (!containsNumericParameters.HasValue)
+          containsNumericParameters = Tree.IterateNodesPrefix().OfType<NumberTreeNode>().Any();
+
+        return containsNumericParameters.Value;
+      }
+    }
+
+    [Storable]
+    private IList<SubFunction> subFunctions = new List<SubFunction>();
+    public IEnumerable<SubFunction> SubFunctions => subFunctions;
+
+    [Storable]
+    private bool applyLinearScaling;
+    public bool ApplyLinearScaling {
+      get => applyLinearScaling;
+      set {
+        if (value == applyLinearScaling) return;
+
+        applyLinearScaling = value;
+        if (applyLinearScaling) LinearScaling.AddLinearScalingTerms(Tree);
+        else LinearScaling.RemoveLinearScalingTerms(Tree);
+
+        OnChanged();
+      }
+    }
+
+    protected InfixExpressionParser Parser { get; set; } = new InfixExpressionParser();
+    #endregion
+
+    #region Events
+    public event EventHandler Changed;
+
+    private void OnChanged() => Changed?.Invoke(this, EventArgs.Empty);
+    #endregion
+
+    #region Constructors
+    public StructureTemplate() {
+      Reset();
+    }
+
+    [StorableConstructor]
+    protected StructureTemplate(StorableConstructorFlag _) : base(_) { }
+
+    protected StructureTemplate(StructureTemplate original, Cloner cloner) : base(original, cloner) {
+      this.tree = cloner.Clone(original.tree);
+      this.template = original.Template;
+      this.applyLinearScaling = original.ApplyLinearScaling;
+      this.subFunctions = original.subFunctions.Select(cloner.Clone).ToList();
+      RegisterSubFunctionEventHandlers(SubFunctions);
+    }
+
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (Tree == null && _oldTree != null) {
+        if (ApplyLinearScaling) _oldTree = LinearScaling.AddLinearScalingTerms(_oldTree);
+        Tree = _oldTree;
+        _oldTree = null;
+      }
+
+      RegisterSubFunctionEventHandlers(SubFunctions);
+    }
+    #endregion
+
+    #region Cloning
+    public override IDeepCloneable Clone(Cloner cloner) =>
+      new StructureTemplate(this, cloner);
+    #endregion
+
+    public void Reset() {
+      subFunctions = new List<SubFunction>();
+      tree = null;
+      containsNumericParameters = null;
+      Template = "f(_)";
+    }
+
+    private static IList<SubFunction> CreateSubFunctions(ISymbolicExpressionTree tree) {
+      var subFunctions = new List<SubFunction>();
+      foreach (var node in tree.IterateNodesPrefix())
+        if (node is SubFunctionTreeNode subFunctionTreeNode) {
+          if (!subFunctionTreeNode.Arguments.Any())
+            throw new ArgumentException($"The sub-function '{subFunctionTreeNode}' requires inputs (e.g. {subFunctionTreeNode.Name}(var1, var2)).");
+
+          var existingSubFunction = subFunctions.Where(x => x.Name == subFunctionTreeNode.Name).FirstOrDefault();
+          if (existingSubFunction != null) {
+            // an existing subFunction must have the same signature
+            if (!existingSubFunction.Arguments.SequenceEqual(subFunctionTreeNode.Arguments))
+              throw new ArgumentException(
+                $"The sub-function '{existingSubFunction.Name}' has (at least two) different signatures " +
+                $"({existingSubFunction.Name}({string.Join(",", existingSubFunction.Arguments)}) <> " +
+                $"{subFunctionTreeNode.Name}({string.Join(",", subFunctionTreeNode.Arguments)})).");
+          } else {
+            var subFunction = new SubFunction() {
+              Name = subFunctionTreeNode.Name,
+              Arguments = subFunctionTreeNode.Arguments
+            };
+            subFunctions.Add(subFunction);
+          }
+        }
+      return subFunctions;
+    }
+
+    private void RegisterSubFunctionEventHandlers(IEnumerable<SubFunction> subFunctions) {
+      foreach (var sf in subFunctions) {
+        sf.Changed += (o, e) => OnChanged();
+      }
+    }
+  }
+}
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/SubFunction.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/SubFunction.cs	(revision 18220)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/SubFunction.cs	(revision 18220)
@@ -0,0 +1,116 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableType("598B5DCB-95AC-465A-920B-E1E6DACFFA4B")]
+  public class SubFunction : ParameterizedNamedItem {
+    #region Constants
+    private const string GrammarParameterName = "Grammar";
+    private const string MaximumSymbolicExpressionTreeDepthParameterName = "MaximumSymbolicExpressionTreeDepth";
+    private const string MaximumSymbolicExpressionTreeLengthParameterName = "MaximumSymbolicExpressionTreeLength";
+    #endregion
+
+    #region Parameters
+    public IValueParameter<ISymbolicDataAnalysisGrammar> GrammarParameter => (IValueParameter<ISymbolicDataAnalysisGrammar>)Parameters[GrammarParameterName];
+    public IFixedValueParameter<IntValue> MaximumSymbolicExpressionTreeDepthParameter => (IFixedValueParameter<IntValue>)Parameters[MaximumSymbolicExpressionTreeDepthParameterName];
+    public IFixedValueParameter<IntValue> MaximumSymbolicExpressionTreeLengthParameter => (IFixedValueParameter<IntValue>)Parameters[MaximumSymbolicExpressionTreeLengthParameterName];
+    #endregion
+
+    #region Properties
+    public ISymbolicDataAnalysisGrammar Grammar {
+      get => GrammarParameter.Value;
+      set => GrammarParameter.Value = value;
+    }
+
+    public int MaximumSymbolicExpressionTreeDepth {
+      get => MaximumSymbolicExpressionTreeDepthParameter.Value.Value;
+      set => MaximumSymbolicExpressionTreeDepthParameter.Value.Value = value;
+    }
+
+    public int MaximumSymbolicExpressionTreeLength {
+      get => MaximumSymbolicExpressionTreeLengthParameter.Value.Value;
+      set => MaximumSymbolicExpressionTreeLengthParameter.Value.Value = value;
+    }
+
+    [Storable]
+    public IEnumerable<string> Arguments { get; set; }
+    #endregion
+
+    #region Events
+    public event EventHandler Changed;
+    #endregion
+
+    #region Constructors
+    public SubFunction() {
+      var grammar = new TypeCoherentExpressionGrammar();
+      grammar.ConfigureAsDefaultRegressionGrammar();
+      grammar.Symbols.First(s => s.Name == TypeCoherentExpressionGrammar.ExponentialFunctionsName).Enabled = false;
+      Parameters.Add(new ValueParameter<ISymbolicDataAnalysisGrammar>(GrammarParameterName, grammar));
+      Parameters.Add(new FixedValueParameter<IntValue>(MaximumSymbolicExpressionTreeDepthParameterName, new IntValue(8)));
+      Parameters.Add(new FixedValueParameter<IntValue>(MaximumSymbolicExpressionTreeLengthParameterName, new IntValue(20)));
+      RegisterEventHandlers();
+    }
+
+    protected SubFunction(SubFunction original, Cloner cloner) : base(original, cloner) {
+      Arguments = original.Arguments;
+      RegisterEventHandlers();
+    }
+
+    [StorableConstructor]
+    protected SubFunction(StorableConstructorFlag _) : base(_) { }
+    public override IDeepCloneable Clone(Cloner cloner) =>
+      new SubFunction(this, cloner);
+
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+    #endregion
+
+    #region Event Handling
+    private void RegisterEventHandlers() {
+      GrammarParameter.ValueChanged += (o, e) => {
+        if (Grammar is TypeCoherentExpressionGrammar tceg) tceg.ConfigureAsDefaultRegressionGrammar();
+        OnParameterValueChanged(o, e);
+      };
+      MaximumSymbolicExpressionTreeDepthParameter.Value.ValueChanged += OnParameterValueChanged;
+      MaximumSymbolicExpressionTreeLengthParameter.Value.ValueChanged += OnParameterValueChanged;
+    }
+
+    private void OnParameterValueChanged(object sender, EventArgs e) =>
+      Changed?.Invoke(this, EventArgs.Empty);
+    #endregion
+
+
+    public override string ToString() => $"{Name}({string.Join(",", Arguments)})";
+
+    public override int GetHashCode() => ToString().GetHashCode();
+
+    public override bool Equals(object obj) => (obj is SubFunction other) && other.ToString() == ToString();
+
+    public void SetupVariables(IEnumerable<string> inputVariables) {
+      var allowedInputVariables = new List<string>(inputVariables);
+
+      foreach (var varSym in Grammar.Symbols.OfType<Variable>()) {
+        // set all variables
+        varSym.AllVariableNames = allowedInputVariables;
+
+        // set all allowed variables
+        if (Arguments.Contains("_")) {
+          varSym.VariableNames = allowedInputVariables;
+        } else {
+          varSym.VariableNames = Arguments.ToList();
+        }
+
+        varSym.Enabled = true;
+      }
+    }
+  }
+}
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SubFunctionSymbol.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SubFunctionSymbol.cs	(revision 18220)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SubFunctionSymbol.cs	(revision 18220)
@@ -0,0 +1,25 @@
+﻿using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableType("C6C2FBEE-8F4B-4FF2-80F5-D566BE55ED69")]
+  [Item("SubFunction", "Symbol that represents a sub function.")]
+  public sealed class SubFunctionSymbol : Symbol {
+    public override int MinimumArity => 0;
+    public override int MaximumArity => 1;
+
+    public SubFunctionSymbol() : base("SubFunction", "Symbol that represents a sub function.") { }
+
+    private SubFunctionSymbol(SubFunctionSymbol original, Cloner cloner) : base(original, cloner) { }
+
+    [StorableConstructor]
+    private SubFunctionSymbol(StorableConstructorFlag _) : base(_) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) =>
+      new SubFunctionSymbol(this, cloner);
+
+    public override ISymbolicExpressionTreeNode CreateTreeNode() => new SubFunctionTreeNode(this);
+  }
+}
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SubFunctionTreeNode.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SubFunctionTreeNode.cs	(revision 18220)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SubFunctionTreeNode.cs	(revision 18220)
@@ -0,0 +1,43 @@
+﻿using System.Collections.Generic;
+using System.Linq;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableType("05130B5F-0125-4367-A4E9-C42D1085024E")]
+  public sealed class SubFunctionTreeNode : SymbolicExpressionTreeNode {
+
+    #region Properties
+    public new SubFunctionSymbol Symbol => (SubFunctionSymbol)base.Symbol;
+
+    [Storable]
+    public IEnumerable<string> Arguments { get; set; } = Enumerable.Empty<string>();
+    
+    [Storable]
+    public string Name { get; set; }
+    #endregion
+
+    #region Constructors
+    public SubFunctionTreeNode(SubFunctionSymbol symbol) : base(symbol) { }
+
+    [StorableConstructor]
+    private SubFunctionTreeNode(StorableConstructorFlag _) : base(_) { }
+
+    private SubFunctionTreeNode(SubFunctionTreeNode original, Cloner cloner) : base(original, cloner) {
+      Arguments = original.Arguments;
+      Name = (string)original.Name.Clone();
+    }
+    #endregion
+
+    #region Cloning
+    public override IDeepCloneable Clone(Cloner cloner) => new SubFunctionTreeNode(this, cloner);
+    #endregion
+
+    public override string ToString() {
+      if (string.IsNullOrEmpty(Name))
+        return base.ToString();
+      return $"{Name}({string.Join(",", Arguments)})";
+    }
+  }
+}
Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeComparer.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeComparer.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeComparer.cs	(revision 18220)
@@ -22,8 +22,6 @@
 using System;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  [StorableType("eabf848e-d10c-499e-8c48-c771232ede0e")]
   // 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
Index: trunk/HeuristicLab.Problems.ExternalEvaluation.GP/3.5/ExternalEvaluationExpressionGrammar.cs
===================================================================
--- trunk/HeuristicLab.Problems.ExternalEvaluation.GP/3.5/ExternalEvaluationExpressionGrammar.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.ExternalEvaluation.GP/3.5/ExternalEvaluationExpressionGrammar.cs	(revision 18220)
@@ -21,5 +21,4 @@
 
 using System.Collections.Generic;
-using System.Linq;
 using HEAL.Attic;
 using HeuristicLab.Common;
@@ -66,5 +65,7 @@
       number.MinValue = -20;
       number.MaxValue = 20;
-      var constant = new Constant();
+      var constant = new Constant() { Enabled = false };
+
+
       variableSymbol = new HeuristicLab.Problems.DataAnalysis.Symbolic.Variable();
 
@@ -89,5 +90,5 @@
       SetSubtreeCount(@if, 3, 3);
       SetSubtreeCount(number, 0, 0);
-      SetSubtreeCount(constant,0, 0);
+      SetSubtreeCount(constant, 0, 0);
       SetSubtreeCount(variableSymbol, 0, 0);
 
@@ -104,6 +105,4 @@
           }
       }
-
-      Symbols.First(s => s is Constant).Enabled = false;
     }
   }
Index: trunk/HeuristicLab.Problems.ExternalEvaluation.GP/3.5/ExternalEvaluationSymbolicExpressionTreeStringFormatter.cs
===================================================================
--- trunk/HeuristicLab.Problems.ExternalEvaluation.GP/3.5/ExternalEvaluationSymbolicExpressionTreeStringFormatter.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.ExternalEvaluation.GP/3.5/ExternalEvaluationSymbolicExpressionTreeStringFormatter.cs	(revision 18220)
@@ -58,5 +58,7 @@
       StringBuilder strBuilder = new StringBuilder();
       if (Indent) strBuilder.Append(' ', indentLength);
-      if (node.Subtrees.Any()) { // internal node
+      if(node.Symbol is SubFunctionSymbol) {
+        return FormatRecursively(node.GetSubtree(0), indentLength);
+      } else if (node.Subtrees.Any()) { // internal node
         strBuilder.Append("(");
         if (node.Symbol is Addition) {
Index: trunk/HeuristicLab.Problems.Instances.DataAnalysis/3.3/HeuristicLab.Problems.Instances.DataAnalysis-3.3.csproj
===================================================================
--- trunk/HeuristicLab.Problems.Instances.DataAnalysis/3.3/HeuristicLab.Problems.Instances.DataAnalysis-3.3.csproj	(revision 18211)
+++ trunk/HeuristicLab.Problems.Instances.DataAnalysis/3.3/HeuristicLab.Problems.Instances.DataAnalysis-3.3.csproj	(revision 18220)
@@ -299,4 +299,5 @@
     <Compile Include="Regression\Physics\PhysicsInstanceProvider.cs" />
     <Compile Include="Regression\Physics\RocketFuelFlow.cs" />
+    <Compile Include="Regression\Physics\SheetBendingProcess.cs" />
     <Compile Include="Regression\VariableNetworks\LinearVariableNetwork.cs" />
     <Compile Include="Regression\VariableNetworks\GaussianProcessVariableNetwork.cs" />
Index: trunk/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/PhysicsInstanceProvider.cs
===================================================================
--- trunk/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/PhysicsInstanceProvider.cs	(revision 18211)
+++ trunk/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/PhysicsInstanceProvider.cs	(revision 18220)
@@ -51,5 +51,6 @@
          new AircraftLift(rand.Next()),
          new FluidDynamics(rand.Next()),
-         new AircraftMaximumLift(rand.Next())
+         new AircraftMaximumLift(rand.Next()),
+         new SheetBendingProcess(rand.Next())
       };
     }
Index: trunk/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/SheetBendingProcess.cs
===================================================================
--- trunk/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/SheetBendingProcess.cs	(revision 18220)
+++ trunk/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/SheetBendingProcess.cs	(revision 18220)
@@ -0,0 +1,73 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.Instances.DataAnalysis {
+  public sealed class SheetBendingProcess : ArtificialRegressionDataDescriptor {
+    public override string Name => "Sheet Bending Process F = E/(E+h) * ((σ_y * t^2) / w + (h * t^3) / (3 * R * w) - (4 * σ_y^3 * R^2) / (3 * w * E^2)) * (1 + 4 * t / w)";
+
+    public override string Description => 
+      "A full description of this instance is given in: " + Environment.NewLine +
+      "Mohammad Zhian Asadzadeh, Hans-Peter Gänser, Manfred Mücke, " + Environment.NewLine +
+      "\"Symbolic regression based hybrid semiparametric modelling of processes: " + Environment.NewLine +
+      "An example case of a bending process\"," + Environment.NewLine +
+      "Applications in Engineering Science, Volume 6, 2021, 100049, " + Environment.NewLine +
+      "ISSN 2666-4968, https://doi.org/10.1016/j.apples.2021.100049. " + Environment.NewLine +
+      "Function: F = E/(E+h) * ((σ_y * t^2) / w + (h * t^3) / (3 * R * w) - (4 * σ_y^3 * R^2) / (3 * w * E^2)) * (1 + 4 * t / w)" +
+      "with E = 210000," + Environment.NewLine +
+      "h ∈ [0.1, 5] [MPa]," + Environment.NewLine +
+      "σ_y ∈ [250, 1000] [MPa]," + Environment.NewLine +
+      "t ∈ [0.5, 5] [mm]," + Environment.NewLine +
+      "R/t ∈ [1, 100]," + Environment.NewLine +
+      "w/R ∈ [0.5, 1.5]";
+
+   
+
+    protected override string TargetVariable => "F";
+    protected override string[] VariableNames => new string[] { "h", "sigma_y", "t", "Rt", "wR", "F" };
+    protected override string[] AllowedInputVariables => new string[] { "h", "sigma_y", "t", "Rt", "wR" };
+
+    protected override int TrainingPartitionStart => 0;
+    protected override int TrainingPartitionEnd => 500;
+    protected override int TestPartitionStart => 500;
+    protected override int TestPartitionEnd => 1000;
+
+    public int Seed { get; }
+
+    public SheetBendingProcess() : this((int)DateTime.Now.Ticks) { }
+
+    public SheetBendingProcess(int seed) {
+      Seed = seed;
+    }
+
+    protected override List<List<double>> GenerateValues() {
+      var rand = new MersenneTwister((uint)Seed);
+
+      List<double> h = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.1, 5).ToList();
+      List<double> sigmaY = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 250, 1000).ToList();
+      List<double> t = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.5, 5).ToList();
+      List<double> Rt = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 1, 100).ToList();
+      List<double> wR = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.5, 1.5).ToList();
+      List<double> F = new List<double>();
+
+      for (int i = TrainingPartitionStart; i < TestPartitionEnd; ++i) {
+        F.Add(Calc(h[i], sigmaY[i], t[i], Rt[i], wR[i]));
+      }
+
+      return new List<List<double>> { h, sigmaY, t, Rt, wR, F };
+    }
+
+    private static double Calc(double h, double sigmaY, double t, double Rt, double wR) {
+      var E = 210000;
+      var R = Rt * t;
+      var w = wR * R;
+      var e = E / (E + h);
+      var yieldStrength = (sigmaY * (t * t)) / w;
+      var plasticHardening = (h * t * t * t) / (3 * R * w);
+      var elasticity = (4 * sigmaY * sigmaY * sigmaY * R * R) / (3 * w * E * E);
+      var C = 1 + 4 * (t / w);
+      return e * (yieldStrength + plasticHardening - elasticity) * C;
+    }
+  }
+}
Index: trunk/HeuristicLab.Tests/HeuristicLab-3.3/Samples/StructureTemplateRegressionSampleTest.cs
===================================================================
--- trunk/HeuristicLab.Tests/HeuristicLab-3.3/Samples/StructureTemplateRegressionSampleTest.cs	(revision 18220)
+++ trunk/HeuristicLab.Tests/HeuristicLab-3.3/Samples/StructureTemplateRegressionSampleTest.cs	(revision 18220)
@@ -0,0 +1,86 @@
+﻿using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HEAL.Attic;
+using HeuristicLab.Algorithms.GeneticAlgorithm;
+using HeuristicLab.Problems.Instances.DataAnalysis;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using HeuristicLab.Selection;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Tests {
+  [TestClass]
+  public class StructureTemplateRegressionSampleTest {
+    private const string SampleFileName = "GP_Structure_Template_Regression";
+    private static readonly ProtoBufSerializer serializer = new ProtoBufSerializer();
+
+    [TestMethod]
+    [TestCategory("Samples.Execute")]
+    [TestProperty("Time", "long")]
+    public void RunStructureTemplateRegressionSampleTest() {
+      var ga = CreateStructureTemplateRegressionSample();
+      ga.SetSeedRandomly.Value = false;
+      SamplesUtils.RunAlgorithm(ga);
+
+      if (Environment.Is64BitProcess) {
+        Assert.AreEqual(5.0286947997733353E-07, SamplesUtils.GetDoubleResult(ga, "BestQuality"), 1E-8);
+        Assert.AreEqual(79.100605440090362, SamplesUtils.GetDoubleResult(ga, "CurrentAverageQuality"), 1E-8);
+        Assert.AreEqual(7905.465554758197, SamplesUtils.GetDoubleResult(ga, "CurrentWorstQuality"), 1E-8);
+        Assert.AreEqual(5050, SamplesUtils.GetIntResult(ga, "EvaluatedSolutions"));
+      } else {
+        Assert.AreEqual(5.45285034915826E-07, SamplesUtils.GetDoubleResult(ga, "BestQuality"), 1E-8);
+        Assert.AreEqual(0.25447047591366467, SamplesUtils.GetDoubleResult(ga, "CurrentAverageQuality"), 1E-8);
+        Assert.AreEqual(23.211139545787372, SamplesUtils.GetDoubleResult(ga, "CurrentWorstQuality"), 1E-8);
+        Assert.AreEqual(5050, SamplesUtils.GetIntResult(ga, "EvaluatedSolutions"));
+      }
+    }
+
+    [TestMethod]
+    [TestCategory("Samples.Create")]
+    [TestProperty("Time", "medium")]
+    public void CreateStructureTemplateRegressionSampleTest() {
+      var ga = CreateStructureTemplateRegressionSample();
+      string path = Path.Combine(SamplesUtils.SamplesDirectory, SampleFileName + SamplesUtils.SampleFileExtension);
+      serializer.Serialize(ga, path);
+    }
+
+    public static GeneticAlgorithm CreateStructureTemplateRegressionSample() {
+      var alg = new GeneticAlgorithm();
+      var provider = new PhysicsInstanceProvider(seed: 0);
+      var descriptor = new SheetBendingProcess(seed: 0);
+      var problem = new StructureTemplateSymbolicRegressionProblem();
+      problem.Load(provider.LoadData(descriptor));
+      problem.StructureTemplate.Template =
+        "(" +
+          "(210000 / (210000 + h)) * ((sigma_y * t * t) / (wR * Rt * t)) + " +
+          "PlasticHardening(_) - Elasticity(_)" +
+        ")" +
+        " * C(_)";
+      foreach(var subFunction in problem.StructureTemplate.SubFunctions) {
+        subFunction.MaximumSymbolicExpressionTreeDepth = 8;
+        subFunction.MaximumSymbolicExpressionTreeLength = 20;
+        subFunction.Grammar = new ArithmeticExpressionGrammar();
+      }
+
+      #region Algorithm Configuration
+      alg.Name = "Genetic Programming - Structure Template";
+      alg.Description = "A standard genetic programming algorithm to solve a regression problem with a predefined structure template (Sheet Bending Process)";
+      alg.Problem = problem;
+
+      SamplesUtils.ConfigureGeneticAlgorithmParameters<TournamentSelector, MultiEncodingCrossover, MultiEncodingManipulator>
+        (alg, popSize: 100, elites: 1, maxGens: 50, mutationRate: 0.25, tournGroupSize: 3);
+
+      alg.Seed.Value = 0;
+      alg.Engine = new ParallelEngine.ParallelEngine();
+      #endregion
+
+      return alg;
+    }
+  }
+}
Index: trunk/HeuristicLab.Tests/HeuristicLab.Tests.csproj
===================================================================
--- trunk/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 18211)
+++ trunk/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 18220)
@@ -471,4 +471,5 @@
     <Compile Include="HeuristicLab-3.3\Samples\GAGroupingProblemSampleTest.cs" />
     <Compile Include="HeuristicLab-3.3\Samples\ShapeConstrainedRegressionSampleTest.cs" />
+    <Compile Include="HeuristicLab-3.3\Samples\StructureTemplateRegressionSampleTest.cs" />
     <Compile Include="HeuristicLab-3.3\Samples\VnsOpSampleTest.cs" />
     <Compile Include="HeuristicLab-3.3\Samples\EsGriewankSampleTest.cs" />
