Index: branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj
===================================================================
--- branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj	(revision 17783)
+++ branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj	(revision 18006)
@@ -99,7 +99,7 @@
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="ALGLIB-3.7.0, Version=3.7.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+    <Reference Include="ALGLIB-3.17.0, Version=3.17.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\..\bin\ALGLIB-3.7.0.dll</HintPath>
+      <HintPath>..\..\bin\ALGLIB-3.17.0.dll</HintPath>
       <Private>False</Private>
     </Reference>
@@ -119,12 +119,18 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Interfaces\IMultiObjectiveConstraintsEvaluator.cs" />
+    <Compile Include="MultiObjective\NMSEMultiObjectiveConstraintsEvaluator.cs" />
     <Compile Include="MultiObjective\PearsonRSquaredNestedTreeSizeEvaluator.cs" />
     <Compile Include="MultiObjective\PearsonRSquaredNumberOfVariablesEvaluator.cs" />
     <Compile Include="MultiObjective\PearsonRSquaredAverageSimilarityEvaluator.cs" />
     <Compile Include="MultiObjective\PearsonRSquaredTreeComplexityEvaluator.cs" />
+    <Compile Include="MultiObjective\ShapeConstrainedRegressionMultiObjectiveProblem.cs" />
     <Compile Include="MultiObjective\SymbolicRegressionMultiObjectiveValidationBestSolutionAnalyzer.cs" />
     <Compile Include="Plugin.cs" />
+    <Compile Include="ShapeConstraintsAnalyzer.cs" />
     <Compile Include="SingleObjective\ConstantOptimizationAnalyzer.cs" />
+    <Compile Include="SingleObjective\Evaluators\NMSESingleObjectiveConstraintsEvaluator.cs" />
     <Compile Include="SingleObjective\Evaluators\SymbolicRegressionMeanRelativeErrorEvaluator.cs" />
+    <Compile Include="SingleObjective\ShapeConstrainedRegressionSingleObjectiveProblem.cs" />
     <Compile Include="SingleObjective\SymbolicRegressionSolutionsAnalyzer.cs" />
     <Compile Include="SymbolicRegressionPhenotypicDiversityAnalyzer.cs" />
Index: branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/Interfaces/IMultiObjectiveConstraintsEvaluator.cs
===================================================================
--- branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/Interfaces/IMultiObjectiveConstraintsEvaluator.cs	(revision 18006)
+++ branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/Interfaces/IMultiObjectiveConstraintsEvaluator.cs	(revision 18006)
@@ -0,0 +1,32 @@
+﻿#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 HEAL.Attic;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
+  [StorableType("F96C5253-5A78-491C-95AE-78F64BD1F3B1")]
+  public interface IMultiObjectiveConstraintsEvaluator : ISymbolicRegressionMultiObjectiveEvaluator {
+
+    IFixedValueParameter<IntValue> NumConstraintsParameter { get; }
+  }
+}
Index: branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/NMSEMultiObjectiveConstraintsEvaluator.cs
===================================================================
--- branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/NMSEMultiObjectiveConstraintsEvaluator.cs	(revision 18006)
+++ branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/NMSEMultiObjectiveConstraintsEvaluator.cs	(revision 18006)
@@ -0,0 +1,199 @@
+﻿#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.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
+  [Item("NMSE Evaluator with shape constraints (multi-objective)",
+    "Calculates the NMSE and constraint violations for a symbolic regression model.")]
+  [StorableType("8E9D76B7-ED9C-43E7-9898-01FBD3633880")]
+  public class NMSEMultiObjectiveConstraintsEvaluator : SymbolicRegressionMultiObjectiveEvaluator, IMultiObjectiveConstraintsEvaluator {
+    private const string NumConstraintsParameterName = "NumConstraints";
+    private const string BoundsEstimatorParameterName = "BoundsEstimator";
+
+    public IFixedValueParameter<IntValue> NumConstraintsParameter =>
+      (IFixedValueParameter<IntValue>)Parameters[NumConstraintsParameterName];
+
+    public IValueParameter<IBoundsEstimator> BoundsEstimatorParameter =>
+      (IValueParameter<IBoundsEstimator>)Parameters[BoundsEstimatorParameterName];
+
+    public int NumConstraints {
+      get => NumConstraintsParameter.Value.Value;
+      set {
+        NumConstraintsParameter.Value.Value = value;
+      }
+    }
+
+    public IBoundsEstimator BoundsEstimator {
+      get => BoundsEstimatorParameter.Value;
+      set => BoundsEstimatorParameter.Value = value;
+    }
+
+    public override IEnumerable<bool> Maximization => new bool[1 + NumConstraints]; // minimize all objectives
+
+    #region Constructors
+
+    public NMSEMultiObjectiveConstraintsEvaluator() {
+      Parameters.Add(new FixedValueParameter<IntValue>(NumConstraintsParameterName, new IntValue(0)));
+      Parameters.Add(new ValueParameter<IBoundsEstimator>(BoundsEstimatorParameterName, new IntervalArithBoundsEstimator()));
+    }
+
+    [StorableConstructor]
+    protected NMSEMultiObjectiveConstraintsEvaluator(StorableConstructorFlag _) : base(_) { }
+
+    protected NMSEMultiObjectiveConstraintsEvaluator(NMSEMultiObjectiveConstraintsEvaluator original, Cloner cloner) : base(original, cloner) { }
+
+    #endregion
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NMSEMultiObjectiveConstraintsEvaluator(this, cloner);
+    }
+
+
+    public override IOperation InstrumentedApply() {
+      var rows = GenerateRowsToEvaluate();
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
+      var problemData = ProblemDataParameter.ActualValue;
+      var interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
+      var estimationLimits = EstimationLimitsParameter.ActualValue;
+      var applyLinearScaling = ApplyLinearScalingParameter.ActualValue.Value;
+
+      if (UseConstantOptimization) {
+        SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, tree, problemData, rows,
+          false,
+          ConstantOptimizationIterations,
+          ConstantOptimizationUpdateVariableWeights,
+          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 ConstantTreeNode;
+            offsetParameter.Value = alpha;
+            var scalingParameter = scaling.GetSubtree(1) as ConstantTreeNode;
+            scalingParameter.Value = beta;
+          }
+        } // else alpha and beta are evolved
+      }
+
+      var qualities = Calculate(interpreter, tree, estimationLimits.Lower, estimationLimits.Upper, problemData,
+        rows, BoundsEstimator, DecimalPlaces);
+      QualitiesParameter.ActualValue = new DoubleArray(qualities);
+      return base.InstrumentedApply();
+    }
+
+    public override double[] Evaluate(
+      IExecutionContext context, ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData,
+      IEnumerable<int> rows) {
+      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context;
+      EstimationLimitsParameter.ExecutionContext = context;
+      ApplyLinearScalingParameter.ExecutionContext = context;
+
+      var quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree,
+        EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper,
+        problemData, rows, BoundsEstimator, DecimalPlaces);
+
+      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
+      EstimationLimitsParameter.ExecutionContext = null;
+      ApplyLinearScalingParameter.ExecutionContext = null;
+
+      return quality;
+    }
+
+
+    public static double[] Calculate(
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      ISymbolicExpressionTree solution, double lowerEstimationLimit,
+      double upperEstimationLimit,
+      IRegressionProblemData problemData, IEnumerable<int> rows, IBoundsEstimator estimator, int decimalPlaces) {
+      OnlineCalculatorError errorState;
+      var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows);
+      var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      var constraints = Enumerable.Empty<ShapeConstraint>();
+      if (problemData is ShapeConstrainedRegressionProblemData scProbData) {
+        constraints = scProbData.ShapeConstraints.EnabledConstraints;
+      }
+      var intervalCollection = problemData.VariableRanges;
+
+      double nmse;
+
+      var boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
+      nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues, out errorState);
+
+      if (errorState != OnlineCalculatorError.None) nmse = 1.0;
+
+      if (decimalPlaces >= 0)
+        nmse = Math.Round(nmse, decimalPlaces);
+
+      if (nmse > 1)
+        nmse = 1.0;
+
+      var objectives = new List<double> { nmse };
+      var violations = IntervalUtil.GetConstraintViolations(constraints, estimator, intervalCollection, solution);
+      foreach (var violation in violations) {
+        if (double.IsNaN(violation) || double.IsInfinity(violation)) {
+          objectives.Add(double.MaxValue);
+        } else {
+          objectives.Add(Math.Round(violation, decimalPlaces));
+        }
+      }
+
+      return objectives.ToArray();
+    }
+  }
+}
Index: branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/ShapeConstrainedRegressionMultiObjectiveProblem.cs
===================================================================
--- branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/ShapeConstrainedRegressionMultiObjectiveProblem.cs	(revision 18006)
+++ branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/ShapeConstrainedRegressionMultiObjectiveProblem.cs	(revision 18006)
@@ -0,0 +1,171 @@
+﻿#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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
+  [Item("Shape-constrained symbolic regression problem (multi-objective)", "Represents a multi-objective shape-constrained regression problem.")]
+  [StorableType("2956C66F-4B71-4A62-998F-B52C5E8C02CD")]
+  [Creatable(CreatableAttribute.Categories.GeneticProgrammingProblems, Priority = 150)]
+  public class ShapeConstrainedRegressionMultiObjectiveProblem : SymbolicDataAnalysisMultiObjectiveProblem<IRegressionProblemData, IMultiObjectiveConstraintsEvaluator, ISymbolicDataAnalysisSolutionCreator>, IRegressionProblem {
+    private const double PunishmentFactor = 10;
+    private const int InitialMaximumTreeDepth = 8;
+    private const int InitialMaximumTreeLength = 25;
+    private const string EstimationLimitsParameterName = "EstimationLimits";
+    private const string EstimationLimitsParameterDescription = "The lower and upper limit for the estimated value that can be returned by the symbolic regression model.";
+
+    #region parameter properties
+    public IFixedValueParameter<DoubleLimit> EstimationLimitsParameter {
+      get { return (IFixedValueParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName]; }
+    }
+    #endregion
+
+    #region properties
+    public DoubleLimit EstimationLimits {
+      get { return EstimationLimitsParameter.Value; }
+    }
+
+    #endregion
+
+    [StorableConstructor]
+    protected ShapeConstrainedRegressionMultiObjectiveProblem(StorableConstructorFlag _) : base(_) { }
+    protected ShapeConstrainedRegressionMultiObjectiveProblem(ShapeConstrainedRegressionMultiObjectiveProblem original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEventHandlers();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new ShapeConstrainedRegressionMultiObjectiveProblem(this, cloner); }
+
+    public ShapeConstrainedRegressionMultiObjectiveProblem()
+      : base(new ShapeConstrainedRegressionProblemData(), new NMSEMultiObjectiveConstraintsEvaluator(), new SymbolicDataAnalysisExpressionTreeCreator()) {
+
+      Parameters.Add(new FixedValueParameter<DoubleLimit>(EstimationLimitsParameterName, EstimationLimitsParameterDescription));
+      EstimationLimitsParameter.Hidden = true;
+
+      ApplyLinearScalingParameter.Value.Value = true;
+      SymbolicExpressionTreeGrammarParameter.Value = new LinearScalingGrammar();
+
+      MaximumSymbolicExpressionTreeDepth.Value = InitialMaximumTreeDepth;
+      MaximumSymbolicExpressionTreeLength.Value = InitialMaximumTreeLength;
+
+      InitializeOperators();
+      UpdateEstimationLimits();
+      UpdateMaximization();
+      RegisterEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
+    private void RegisterEventHandlers() {
+      Evaluator.NumConstraintsParameter.Value.ValueChanged += NumConstraintsParameter_ValueChanged;
+    }
+
+    protected override void OnEvaluatorChanged() {
+      base.OnEvaluatorChanged();
+      UpdateEvaluatorObjectives(); // update objectives in evaluator based ProblemData
+      Evaluator.NumConstraintsParameter.Value.ValueChanged += NumConstraintsParameter_ValueChanged;
+    }
+    protected override void OnProblemDataChanged() {
+      base.OnProblemDataChanged();
+
+      UpdateEstimationLimits();
+      UpdateMaximization();
+      UpdateEvaluatorObjectives();
+    }
+
+    private void NumConstraintsParameter_ValueChanged(object sender, EventArgs e) {
+      UpdateMaximization();
+    }
+
+    private void UpdateMaximization() {
+      Maximization = new BoolArray(Evaluator.Maximization.ToArray());
+    }
+
+    private void UpdateEstimationLimits() {
+      if (ProblemData.TrainingIndices.Any()) {
+        var targetValues = ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TrainingIndices).ToList();
+        var mean = targetValues.Average();
+        var range = targetValues.Max() - targetValues.Min();
+        EstimationLimits.Upper = mean + PunishmentFactor * range;
+        EstimationLimits.Lower = mean - PunishmentFactor * range;
+      } else {
+        EstimationLimits.Upper = double.MaxValue;
+        EstimationLimits.Lower = double.MinValue;
+      }
+    }
+    private void UpdateEvaluatorObjectives() {
+      if (ProblemData is ShapeConstrainedRegressionProblemData scProblemData) {
+        Evaluator.NumConstraintsParameter.Value.Value = scProblemData.ShapeConstraints.EnabledConstraints.Count();
+      } else {
+        Evaluator.NumConstraintsParameter.Value.Value = 0;
+      }
+    }
+
+    private void InitializeOperators() {
+      Operators.Add(new SymbolicRegressionMultiObjectiveTrainingBestSolutionAnalyzer());
+      Operators.Add(new SymbolicRegressionMultiObjectiveValidationBestSolutionAnalyzer());
+      Operators.Add(new SymbolicExpressionTreePhenotypicSimilarityCalculator());
+      Operators.Add(new SymbolicRegressionPhenotypicDiversityAnalyzer(Operators.OfType<SymbolicExpressionTreePhenotypicSimilarityCalculator>()));
+      ParameterizeOperators();
+    }
+
+    protected override void ParameterizeOperators() {
+      base.ParameterizeOperators();
+      if (Parameters.ContainsKey(EstimationLimitsParameterName)) {
+        var operators = Parameters.OfType<IValueParameter>().Select(p => p.Value).OfType<IOperator>().Union(Operators);
+        foreach (var op in operators.OfType<ISymbolicDataAnalysisBoundedOperator>()) {
+          op.EstimationLimitsParameter.ActualName = EstimationLimitsParameter.Name;
+        }
+      }
+
+      foreach (var op in Operators.OfType<ISolutionSimilarityCalculator>()) {
+        op.SolutionVariableName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
+        op.QualityVariableName = Evaluator.QualitiesParameter.ActualName;
+
+        if (op is SymbolicExpressionTreePhenotypicSimilarityCalculator) {
+          var phenotypicSimilarityCalculator = (SymbolicExpressionTreePhenotypicSimilarityCalculator)op;
+          phenotypicSimilarityCalculator.ProblemData = ProblemData;
+          phenotypicSimilarityCalculator.Interpreter = SymbolicExpressionTreeInterpreter;
+        }
+      }
+    }
+
+
+    public override void Load(IRegressionProblemData data) {
+      var scProblemData = new ShapeConstrainedRegressionProblemData(data.Dataset, data.AllowedInputVariables, data.TargetVariable,
+                                                                    data.TrainingPartition, data.TestPartition) {
+        Name = data.Name,
+        Description = data.Description
+      };
+
+      base.Load(scProblemData);
+    }
+  }
+}
Index: branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectiveProblem.cs
===================================================================
--- branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectiveProblem.cs	(revision 17783)
+++ branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectiveProblem.cs	(revision 18006)
@@ -60,6 +60,7 @@
     public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicRegressionMultiObjectiveProblem(this, cloner); }
 
-    public SymbolicRegressionMultiObjectiveProblem()
-      : base(new RegressionProblemData(), new SymbolicRegressionMultiObjectivePearsonRSquaredTreeSizeEvaluator(), new SymbolicDataAnalysisExpressionTreeCreator()) {
+    public SymbolicRegressionMultiObjectiveProblem() : this(new RegressionProblemData(), new SymbolicRegressionMultiObjectivePearsonRSquaredTreeSizeEvaluator(), new SymbolicDataAnalysisExpressionTreeCreator()) { }
+    public SymbolicRegressionMultiObjectiveProblem(IRegressionProblemData problemData, ISymbolicRegressionMultiObjectiveEvaluator evaluator, ISymbolicDataAnalysisSolutionCreator solutionCreator)
+      : base(problemData, evaluator, solutionCreator) {
       Parameters.Add(new FixedValueParameter<DoubleLimit>(EstimationLimitsParameterName, EstimationLimitsParameterDescription));
 
Index: branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/Plugin.cs.frame
===================================================================
--- branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/Plugin.cs.frame	(revision 17783)
+++ branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/Plugin.cs.frame	(revision 18006)
@@ -28,5 +28,5 @@
   [Plugin("HeuristicLab.Problems.DataAnalysis.Symbolic.Regression","Provides classes to perform symbolic regression (single- or multiobjective).", "3.4.12.$WCREV$")]
   [PluginFile("HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.dll", PluginFileType.Assembly)]
-  [PluginDependency("HeuristicLab.ALGLIB", "3.7.0")]
+  [PluginDependency("HeuristicLab.ALGLIB", "3.17.0")]
   [PluginDependency("HeuristicLab.Analysis", "3.3")]
   [PluginDependency("HeuristicLab.Common", "3.3")]
Index: branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/ShapeConstraintsAnalyzer.cs
===================================================================
--- branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/ShapeConstraintsAnalyzer.cs	(revision 18006)
+++ branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/ShapeConstraintsAnalyzer.cs	(revision 18006)
@@ -0,0 +1,128 @@
+﻿#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.Linq;
+using HEAL.Attic;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
+  [StorableType("4318C6BD-E0A1-45FE-AC30-96E7F73B51FB")]
+  [Item("ShapeConstraintsAnalyzer", "Analyzes the number of shape constraint violations of symbolic regression models.")]
+  public class ShapeConstraintsAnalyzer : SymbolicDataAnalysisAnalyzer, ISymbolicExpressionTreeAnalyzer {
+    private const string ProblemDataParameterName = "ProblemData";
+    private const string ConstraintViolationsParameterName = "ConstraintViolations";
+    private const string InfeasibleSolutionsParameterName = "InfeasibleSolutions";
+
+    #region parameter properties
+
+    public ILookupParameter<IRegressionProblemData> RegressionProblemDataParameter =>
+      (ILookupParameter<IRegressionProblemData>) Parameters[ProblemDataParameterName];
+
+    public IResultParameter<DataTable> ConstraintViolationsParameter =>
+      (IResultParameter<DataTable>) Parameters[ConstraintViolationsParameterName];
+
+    public IResultParameter<DataTable> InfeasibleSolutionsParameter =>
+      (IResultParameter<DataTable>)Parameters[InfeasibleSolutionsParameterName];
+
+    #endregion
+
+    #region properties
+    public IRegressionProblemData RegressionProblemData => RegressionProblemDataParameter.ActualValue;
+    public DataTable ConstraintViolations => ConstraintViolationsParameter.ActualValue;
+    public DataTable InfeasibleSolutions => InfeasibleSolutionsParameter.ActualValue;
+    #endregion
+
+    public override bool EnabledByDefault => false;
+
+    [StorableConstructor]
+    protected ShapeConstraintsAnalyzer(StorableConstructorFlag _) : base(_) { }
+
+    protected ShapeConstraintsAnalyzer(ShapeConstraintsAnalyzer original, Cloner cloner) :
+      base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ShapeConstraintsAnalyzer(this, cloner);
+    }
+
+    public ShapeConstraintsAnalyzer() {
+      Parameters.Add(new LookupParameter<IRegressionProblemData>(ProblemDataParameterName,
+        "The problem data of the symbolic data analysis problem."));
+      Parameters.Add(new ResultParameter<DataTable>(ConstraintViolationsParameterName,
+        "The number of constraint violations."));
+      Parameters.Add(new ResultParameter<DataTable>(InfeasibleSolutionsParameterName,
+        "The number of infeasible solutions."));
+
+
+      ConstraintViolationsParameter.DefaultValue = new DataTable(ConstraintViolationsParameterName) {
+        VisualProperties = {
+          XAxisTitle = "Generations",
+          YAxisTitle = "Constraint violations"
+        }
+      };
+
+      InfeasibleSolutionsParameter.DefaultValue = new DataTable(InfeasibleSolutionsParameterName) {
+        VisualProperties = {
+          XAxisTitle = "Generations",
+          YAxisTitle = "Infeasible solutions"
+        }
+      };
+    }
+
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+
+    public override IOperation Apply() {
+      var problemData = (IShapeConstrainedRegressionProblemData)RegressionProblemData;
+      var trees = SymbolicExpressionTree.ToArray();
+
+      var results = ResultCollection;
+      var constraints = problemData.ShapeConstraints.EnabledConstraints;
+      var variableRanges = problemData.VariableRanges;
+      var constraintViolationsTable = ConstraintViolations;
+      var estimator = new IntervalArithBoundsEstimator();
+
+      if (!constraintViolationsTable.Rows.Any())
+        foreach (var constraint in constraints)
+          constraintViolationsTable.Rows.Add(new DataRow(constraint.ToString()));
+
+      foreach (var constraint in constraints) {
+        var numViolations = trees.Count(tree => IntervalUtil.GetConstraintViolation(constraint, estimator, variableRanges, tree) > 0.0);
+        constraintViolationsTable.Rows[constraint.ToString()].Values.Add(numViolations);
+      }
+
+      var infeasibleSolutionsDataTable = InfeasibleSolutions;
+      if (infeasibleSolutionsDataTable.Rows.Count == 0)
+        infeasibleSolutionsDataTable.Rows.Add(new DataRow(InfeasibleSolutionsParameterName));
+
+      infeasibleSolutionsDataTable.Rows[InfeasibleSolutionsParameterName]
+        .Values
+        .Add(trees.Count(t => IntervalUtil.GetConstraintViolations(constraints, estimator, variableRanges, t).Any(x => x > 0.0)));
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NMSESingleObjectiveConstraintsEvaluator.cs
===================================================================
--- branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NMSESingleObjectiveConstraintsEvaluator.cs	(revision 18006)
+++ branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NMSESingleObjectiveConstraintsEvaluator.cs	(revision 18006)
@@ -0,0 +1,236 @@
+﻿#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.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
+  [Item("NMSE Evaluator with shape-constraints (single-objective)", "Calculates NMSE of a symbolic regression solution and checks constraints. The fitness is a combination of NMSE and constraint violations.")]
+  [StorableType("27473973-DD8D-4375-997D-942E2280AE8E")]
+  public class NMSESingleObjectiveConstraintsEvaluator : SymbolicRegressionSingleObjectiveEvaluator {
+    #region Parameter/Properties
+
+    private const string OptimizeParametersParameterName = "OptimizeParameters";
+    private const string ParameterOptimizationIterationsParameterName = "ParameterOptimizationIterations";
+    private const string UseSoftConstraintsParameterName = "UseSoftConstraintsEvaluation";
+    private const string BoundsEstimatorParameterName = "BoundsEstimator";
+    private const string PenaltyFactorParameterName = "PenaltyFactor";
+
+
+    public IFixedValueParameter<BoolValue> OptimizerParametersParameter =>
+      (IFixedValueParameter<BoolValue>)Parameters[OptimizeParametersParameterName];
+
+    public IFixedValueParameter<IntValue> ConstantOptimizationIterationsParameter =>
+      (IFixedValueParameter<IntValue>)Parameters[ParameterOptimizationIterationsParameterName];
+
+    public IFixedValueParameter<BoolValue> UseSoftConstraintsParameter =>
+      (IFixedValueParameter<BoolValue>)Parameters[UseSoftConstraintsParameterName];
+
+    public IValueParameter<IBoundsEstimator> BoundsEstimatorParameter =>
+      (IValueParameter<IBoundsEstimator>)Parameters[BoundsEstimatorParameterName];
+    public IFixedValueParameter<DoubleValue> PenaltyFactorParameter =>
+      (IFixedValueParameter<DoubleValue>)Parameters[PenaltyFactorParameterName];
+
+    public bool OptimizeParameters {
+      get => OptimizerParametersParameter.Value.Value;
+      set => OptimizerParametersParameter.Value.Value = value;
+    }
+
+    public int ConstantOptimizationIterations {
+      get => ConstantOptimizationIterationsParameter.Value.Value;
+      set => ConstantOptimizationIterationsParameter.Value.Value = value;
+    }
+
+    public bool UseSoftConstraints {
+      get => UseSoftConstraintsParameter.Value.Value;
+      set => UseSoftConstraintsParameter.Value.Value = value;
+    }
+
+    public IBoundsEstimator BoundsEstimator {
+      get => BoundsEstimatorParameter.Value;
+      set => BoundsEstimatorParameter.Value = value;
+    }
+
+    public double PenalityFactor {
+      get => PenaltyFactorParameter.Value.Value;
+      set => PenaltyFactorParameter.Value.Value = value;
+    }
+
+
+    public override bool Maximization => false; // NMSE is minimized
+
+    #endregion
+
+    #region Constructors/Cloning
+
+    [StorableConstructor]
+    protected NMSESingleObjectiveConstraintsEvaluator(StorableConstructorFlag _) : base(_) { }
+
+    protected NMSESingleObjectiveConstraintsEvaluator(
+      NMSESingleObjectiveConstraintsEvaluator original, Cloner cloner) : base(original, cloner) { }
+
+    public NMSESingleObjectiveConstraintsEvaluator() {
+      Parameters.Add(new FixedValueParameter<BoolValue>(OptimizeParametersParameterName,
+        "Define whether optimization of numeric parameters is active or not (default: false).", new BoolValue(false)));
+      Parameters.Add(new FixedValueParameter<IntValue>(ParameterOptimizationIterationsParameterName,
+        "Define how many parameter optimization steps should be performed (default: 10).", new IntValue(10)));
+      Parameters.Add(new FixedValueParameter<BoolValue>(UseSoftConstraintsParameterName,
+        "Define whether the constraints are penalized by soft or hard constraints (default: false).", new BoolValue(false)));
+      Parameters.Add(new ValueParameter<IBoundsEstimator>(BoundsEstimatorParameterName,
+        "The estimator which is used to estimate output ranges of models (default: interval arithmetic).", new IntervalArithBoundsEstimator()));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(PenaltyFactorParameterName,
+        "Punishment factor for constraint violations for soft constraint handling (fitness = NMSE + penaltyFactor * avg(violations)) (default: 1.0)", new DoubleValue(1.0)));
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NMSESingleObjectiveConstraintsEvaluator(this, cloner);
+    }
+
+    #endregion
+
+    public override IOperation InstrumentedApply() {
+      var rows = GenerateRowsToEvaluate();
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
+      var problemData = ProblemDataParameter.ActualValue;
+      var interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
+      var estimationLimits = EstimationLimitsParameter.ActualValue;
+      var applyLinearScaling = ApplyLinearScalingParameter.ActualValue.Value;
+
+      if (OptimizeParameters) {
+        SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, tree, problemData, rows,
+          false, ConstantOptimizationIterations, 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 ConstantTreeNode;
+            offsetParameter.Value = alpha;
+            var scalingParameter = scaling.GetSubtree(1) as ConstantTreeNode;
+            scalingParameter.Value = beta;
+          }
+        } // else: alpha and beta are evolved
+      }
+
+      var quality = Calculate(interpreter, tree, estimationLimits.Lower, estimationLimits.Upper, problemData, rows,
+        BoundsEstimator, UseSoftConstraints, PenalityFactor);
+      QualityParameter.ActualValue = new DoubleValue(quality);
+
+      return base.InstrumentedApply();
+    }
+
+    public static double Calculate(
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      ISymbolicExpressionTree tree,
+      double lowerEstimationLimit, double upperEstimationLimit,
+      IRegressionProblemData problemData, IEnumerable<int> rows,
+      IBoundsEstimator estimator,
+      bool useSoftConstraints = false, double penaltyFactor = 1.0) {
+
+      var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
+      var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      var constraints = Enumerable.Empty<ShapeConstraint>();
+      if (problemData is ShapeConstrainedRegressionProblemData scProbData) {
+        constraints = scProbData.ShapeConstraints.EnabledConstraints;
+      } 
+      var intervalCollection = problemData.VariableRanges;
+
+      var boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
+      var nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues,
+        out var errorState);
+
+      if (errorState != OnlineCalculatorError.None) {
+        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;
+    }
+
+    public override double Evaluate(
+      IExecutionContext context, ISymbolicExpressionTree tree, IRegressionProblemData problemData,
+      IEnumerable<int> rows) {
+      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context;
+      EstimationLimitsParameter.ExecutionContext = context;
+      ApplyLinearScalingParameter.ExecutionContext = context;
+
+      var nmse = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree,
+        EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper,
+        problemData, rows, BoundsEstimator, UseSoftConstraints, PenalityFactor);
+
+      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
+      EstimationLimitsParameter.ExecutionContext = null;
+      ApplyLinearScalingParameter.ExecutionContext = null;
+
+      return nmse;
+    }
+  }
+}
Index: branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs
===================================================================
--- branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 17783)
+++ branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 18006)
@@ -209,7 +209,7 @@
       bool updateConstantsInTree = true, Action<double[], double, object> iterationCallback = null, EvaluationsCounter counter = null) {
 
-      // numeric constants in the tree become variables for constant opt
-      // variables in the tree become parameters (fixed values) for constant opt
-      // for each parameter (variable in the original tree) we store the 
+      // Numeric constants 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
@@ -221,8 +221,8 @@
       if (!TreeToAutoDiffTermConverter.TryConvertToAutoDiff(tree, updateVariableWeights, applyLinearScaling, out parameters, out initialConstants, out func, out func_grad))
         throw new NotSupportedException("Could not optimize constants of symbolic expression tree due to not supported symbols used in the tree.");
-      if (parameters.Count == 0) return 0.0; // gkronber: constant expressions always have a R² of 0.0 
+      if (parameters.Count == 0) return 0.0; // constant expressions always have a R² of 0.0 
       var parameterEntries = parameters.ToArray(); // order of entries must be the same for x
 
-      //extract inital constants
+      // extract inital constants
       double[] c;
       if (applyLinearScaling) {
@@ -270,7 +270,6 @@
       try {
         alglib.lsfitcreatefg(x, y, c, n, m, k, false, out state);
-        alglib.lsfitsetcond(state, 0.0, 0.0, maxIterations);
+        alglib.lsfitsetcond(state, 0.0, maxIterations);
         alglib.lsfitsetxrep(state, iterationCallback != null);
-        //alglib.lsfitsetgradientcheck(state, 0.001);
         alglib.lsfitfit(state, function_cx_1_func, function_cx_1_grad, xrep, rowEvaluationsCounter);
         alglib.lsfitresults(state, out retVal, out c, out rep);
@@ -285,5 +284,7 @@
 
       //retVal == -7  => constant optimization failed due to wrong gradient
-      if (retVal != -7) {
+      //          -8  => optimizer detected  NAN / INF  in  the target
+      //                 function and/ or gradient
+      if (retVal != -7 && retVal != -8) {
         if (applyLinearScaling) {
           var tmp = new double[c.Length - 2];
@@ -309,7 +310,9 @@
         VariableTreeNodeBase variableTreeNodeBase = node as VariableTreeNodeBase;
         FactorVariableTreeNode factorVarTreeNode = node as FactorVariableTreeNode;
-        if (constantTreeNode != null)
+        if (constantTreeNode != null) {
+          if (constantTreeNode.Parent.Symbol is Power 
+              && constantTreeNode.Parent.GetSubtree(1) == constantTreeNode) continue; // exponents in powers are not optimizated (see TreeToAutoDiffTermConverter)
           constantTreeNode.Value = constants[i++];
-        else if (updateVariableWeights && variableTreeNodeBase != null)
+        } else if (updateVariableWeights && variableTreeNodeBase != null)
           variableTreeNodeBase.Weight = constants[i++];
         else if (factorVarTreeNode != null) {
Index: branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/ShapeConstrainedRegressionSingleObjectiveProblem.cs
===================================================================
--- branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/ShapeConstrainedRegressionSingleObjectiveProblem.cs	(revision 18006)
+++ branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/ShapeConstrainedRegressionSingleObjectiveProblem.cs	(revision 18006)
@@ -0,0 +1,62 @@
+﻿#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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
+  [Item("Shape-constrained symbolic regression problem (single-objective)", "Represents a single-objective shape-constrained regression problem.")]
+  [StorableType("B35ADCA7-E902-4BEE-9DDE-DF8BBC1E27FE")]
+  [Creatable(CreatableAttribute.Categories.GeneticProgrammingProblems, Priority = 150)]
+  public class ShapeConstrainedRegressionSingleObjectiveProblem : SymbolicRegressionSingleObjectiveProblem {
+    [StorableConstructor]
+    protected ShapeConstrainedRegressionSingleObjectiveProblem(StorableConstructorFlag _) : base(_) { }
+    protected ShapeConstrainedRegressionSingleObjectiveProblem(ShapeConstrainedRegressionSingleObjectiveProblem original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) { return new ShapeConstrainedRegressionSingleObjectiveProblem(this, cloner); }
+
+    public ShapeConstrainedRegressionSingleObjectiveProblem()
+      : base(new ShapeConstrainedRegressionProblemData(), new NMSESingleObjectiveConstraintsEvaluator(), new SymbolicDataAnalysisExpressionTreeCreator()) {
+
+      ApplyLinearScalingParameter.Value.Value = true;
+      Maximization.Value = false;
+      SymbolicExpressionTreeGrammarParameter.Value = new LinearScalingGrammar();
+
+      InitializeOperators();
+    }
+
+
+    private void InitializeOperators() {
+      Operators.Add(new ShapeConstraintsAnalyzer());
+      ParameterizeOperators();
+    }
+
+    public override void Load(IRegressionProblemData data) {
+      var scProblemData = new ShapeConstrainedRegressionProblemData(data.Dataset, data.AllowedInputVariables, data.TargetVariable,
+                                                                    data.TrainingPartition, data.TestPartition) {
+        Name = data.Name,
+        Description = data.Description
+      };
+
+      base.Load(scProblemData);
+    }
+  }
+}
Index: branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/SymbolicRegressionSingleObjectiveProblem.cs
===================================================================
--- branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/SymbolicRegressionSingleObjectiveProblem.cs	(revision 17783)
+++ branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/SymbolicRegressionSingleObjectiveProblem.cs	(revision 18006)
@@ -56,6 +56,9 @@
     public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicRegressionSingleObjectiveProblem(this, cloner); }
 
-    public SymbolicRegressionSingleObjectiveProblem()
-      : base(new RegressionProblemData(), new SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator(), new SymbolicDataAnalysisExpressionTreeCreator()) {
+    public SymbolicRegressionSingleObjectiveProblem() : this(new RegressionProblemData(), new SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator(), new SymbolicDataAnalysisExpressionTreeCreator()) {
+    }
+    public SymbolicRegressionSingleObjectiveProblem(IRegressionProblemData problemData, ISymbolicRegressionSingleObjectiveEvaluator evaluator, ISymbolicDataAnalysisSolutionCreator solutionCreator) :
+      base(problemData, evaluator, solutionCreator) {
+
       Parameters.Add(new FixedValueParameter<DoubleLimit>(EstimationLimitsParameterName, EstimationLimitsParameterDescription));
 
@@ -91,4 +94,9 @@
         changed = true;
       }
+
+      if (!Operators.OfType<ShapeConstraintsAnalyzer>().Any()) {
+        Operators.Add(new ShapeConstraintsAnalyzer());
+        changed = true;
+      }
       if (changed) {
         ParameterizeOperators();
@@ -113,4 +121,5 @@
       Operators.Add(new SymbolicRegressionSolutionsAnalyzer());
       Operators.Add(new SymbolicExpressionTreePhenotypicSimilarityCalculator());
+      Operators.Add(new ShapeConstraintsAnalyzer());
       Operators.Add(new SymbolicRegressionPhenotypicDiversityAnalyzer(Operators.OfType<SymbolicExpressionTreePhenotypicSimilarityCalculator>()) { DiversityResultName = "Phenotypic Diversity" });
       ParameterizeOperators();
Index: branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolution.cs
===================================================================
--- branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolution.cs	(revision 17783)
+++ branches/3087_Ceres_Integration/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolution.cs	(revision 18006)
@@ -109,5 +109,4 @@
           Add(new Result(ModelBoundsResultName, "Results concerning the derivation of symbolic regression solution", value));
         }
-
       }
     }
