Index: branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/DatasetExtensions.cs
===================================================================
--- branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/DatasetExtensions.cs	(revision 17842)
+++ branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/DatasetExtensions.cs	(revision 17918)
@@ -96,4 +96,14 @@
     }
 
+    public static IntervalCollection GetIntervals(this IDataset dataset) {
+      IntervalCollection intervalCollection = new IntervalCollection();
+      foreach (var variable in dataset.DoubleVariables) { // intervals are only possible for double variables
+        var variableInterval = Interval.GetInterval(dataset.GetDoubleValues(variable));
+        intervalCollection.AddInterval(variable, variableInterval);
+      }
+
+      return intervalCollection;
+    }
+
     public static IEnumerable<KeyValuePair<string, IEnumerable<string>>> GetFactorVariableValues(
       this IDataset ds, IEnumerable<string> factorVariables, IEnumerable<int> rows) {
Index: branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj
===================================================================
--- branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 17842)
+++ branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 17918)
@@ -142,7 +142,10 @@
     <Compile Include="Implementation\Interval\Interval.cs" />
     <Compile Include="Implementation\Interval\IntervalCollection.cs" />
+    <Compile Include="Implementation\Interval\ShapeConstraint.cs" />
+    <Compile Include="Implementation\Interval\ShapeConstraintsParser.cs" />
     <Compile Include="Implementation\Regression\ConfidenceBoundRegressionSolution.cs" />
     <Compile Include="Implementation\Regression\ConstantRegressionModel.cs" />
     <Compile Include="Implementation\Regression\ConstantRegressionSolution.cs" />
+    <Compile Include="Implementation\Regression\ShapeConstraints.cs" />
     <Compile Include="Implementation\Regression\RegressionEnsembleProblemData.cs" />
     <Compile Include="Implementation\Regression\RegressionEnsembleModel.cs">
Index: branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs
===================================================================
--- branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs	(revision 17842)
+++ branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs	(revision 17918)
@@ -306,4 +306,5 @@
         classNamesCache.Add(ClassNamesParameter.Value[i, 0]);
     }
+
     public override IDeepCloneable Clone(Cloner cloner) {
       if (this == emptyProblemData) return emptyProblemData;
@@ -314,11 +315,22 @@
 
     public ClassificationProblemData(IClassificationProblemData classificationProblemData)
-      : this(classificationProblemData.Dataset, classificationProblemData.AllowedInputVariables, classificationProblemData.TargetVariable, classificationProblemData.ClassNames, classificationProblemData.PositiveClass) {
-      
+      : this(classificationProblemData, classificationProblemData.Dataset) {
+    }
+
+    /// <summary>
+    /// This method satisfies a common use case: making a copy of the problem but providing a different dataset.
+    /// One must be careful here that the dataset passed is not modified, as that would invalidate the problem data internals.
+    /// Passing a ModifiableDataset to this constructor is therefore discouraged.
+    /// </summary>
+    /// <param name="classificationProblemData">The original instance of classification problem data.</param>
+    /// <param name="dataset">The new dataset.</param>
+    public ClassificationProblemData(IClassificationProblemData classificationProblemData, IDataset dataset)
+    : this(classificationProblemData.Dataset, classificationProblemData.AllowedInputVariables, classificationProblemData.TargetVariable, classificationProblemData.ClassNames, classificationProblemData.PositiveClass) {
+
       TrainingPartition.Start = classificationProblemData.TrainingPartition.Start;
       TrainingPartition.End = classificationProblemData.TrainingPartition.End;
       TestPartition.Start = classificationProblemData.TestPartition.Start;
       TestPartition.End = classificationProblemData.TestPartition.End;
-      
+
       for (int i = 0; i < Classes; i++) {
         for (int j = 0; j < Classes; j++) {
@@ -328,9 +340,6 @@
     }
 
-    public ClassificationProblemData(IDataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable, IEnumerable<ITransformation> transformations = null)
-      : this(dataset, allowedInputVariables, targetVariable, Enumerable.Empty<string>(), null, transformations) { }
-
     public ClassificationProblemData(IDataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable,
-      IEnumerable<string> classNames,
+      IEnumerable<string> classNames = null,
       string positiveClass = null, // can be null in which case it's set as the first class name
       IEnumerable<ITransformation> transformations = null)
@@ -348,8 +357,8 @@
 
       // set the class names
-      if (classNames.Any()) {
+      if (classNames != null && classNames.Any()) {
         // better to allocate lists because we use these multiple times below
         var names = classNames.ToList();
-        var values = ClassValues.ToList();
+        var values = ClassValuesCache;
 
         if (names.Count != values.Count) {
Index: branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/Interval.cs
===================================================================
--- branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/Interval.cs	(revision 17842)
+++ branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/Interval.cs	(revision 17918)
@@ -33,4 +33,6 @@
     [Storable]
     public double UpperBound { get; private set; }
+
+    public double Width => UpperBound - LowerBound;
 
     [StorableConstructor]
@@ -67,4 +69,6 @@
     }
 
+    private Interval(double v) : this(v, v) { }
+
     public bool Contains(double value) {
       return LowerBound <= value && value <= UpperBound;
@@ -126,6 +130,6 @@
         return false;
 
-      return (UpperBound.IsAlmost(other.UpperBound) || (double.IsNaN(UpperBound) && double.IsNaN(other.UpperBound)))
-        && (LowerBound.IsAlmost(other.LowerBound) || (double.IsNaN(LowerBound) && double.IsNaN(other.LowerBound)));
+      return (UpperBound==other.UpperBound || (double.IsNaN(UpperBound) && double.IsNaN(other.UpperBound)))
+        && (LowerBound==other.LowerBound || (double.IsNaN(LowerBound) && double.IsNaN(other.LowerBound)));
     }
 
@@ -267,5 +271,5 @@
     }
 
-    public static Interval AnalyticalQuotient(Interval a, Interval b) {
+    public static Interval AnalyticQuotient(Interval a, Interval b) {
       var dividend = a;
       var divisor = Add(Square(b), new Interval(1.0, 1.0));
@@ -276,4 +280,34 @@
     }
     #endregion
+
+    #region arithmetic overloads
+    public static Interval operator +(Interval a, Interval b) => Add(a, b);
+    public static Interval operator +(Interval a, double b) => Add(a, new Interval(b));
+    public static Interval operator +(double a, Interval b) => Add(new Interval(a), b);
+    public static Interval operator -(Interval a, Interval b) => Subtract(a, b);
+    public static Interval operator -(Interval a, double b) => Subtract(a, new Interval(b));
+    public static Interval operator -(double a, Interval b) => Subtract(new Interval(a), b);
+    public static Interval operator -(Interval a) => Subtract(new Interval(0), a);
+    public static Interval operator *(Interval a, Interval b) => Multiply(a, b);
+    public static Interval operator *(Interval a, double b) => Multiply(a, new Interval(b));
+    public static Interval operator *(double a, Interval b) => Multiply(new Interval(a), b);
+    public static Interval operator /(Interval a, Interval b) => Divide(a, b);
+    public static Interval operator /(Interval a, double b) => Divide(a, new Interval(b));
+    public static Interval operator /(double a, Interval b) => Divide(new Interval(a), b);
+    public static Interval Exponential(double a) { return Exponential(new Interval(a)); }
+    public static Interval Logarithm(double a) { return Logarithm(new Interval(a)); }
+    public static Interval Sine(double a) { return Sine(new Interval(a)); }
+    public static Interval Cosine(double a) { return Cosine(new Interval(a)); }
+    public static Interval Tangens(double a) { return Tangens(new Interval(a)); }
+    public static Interval HyperbolicTangent(double a) { return HyperbolicTangent(new Interval(a)); }
+    public static Interval Square(double a) { return Square(new Interval(a)); }
+    public static Interval Cube(double a) { return Cube(new Interval(a)); }
+    public static Interval SquareRoot(double a) { return SquareRoot(new Interval(a)); }
+    public static Interval CubicRoot(double a) { return CubicRoot(new Interval(a)); }
+    public static Interval Absolute(double a) { return Absolute(new Interval(a)); }
+    public static Interval AnalyticQuotient(Interval a, double b) { return AnalyticQuotient(a, new Interval(b)); }
+    public static Interval AnalyticQuotient(double a, Interval b) { return AnalyticQuotient(new Interval(a), b); }
+    public static Interval AnalyticQuotient(double a, double b) { return AnalyticQuotient(new Interval(a), new Interval(b)); }
+    #endregion
   }
 }
Index: branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalCollection.cs
===================================================================
--- branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalCollection.cs	(revision 17842)
+++ branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalCollection.cs	(revision 17918)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -34,20 +34,33 @@
       get => HeuristicLab.Common.Resources.VSImageLibrary.Object;
     }
-    private IDictionary<string, Interval> intervals { get; } = new Dictionary<string, Interval>();
 
-    [Storable(Name = "StorableIntervalInformation")]
+    private IDictionary<string, Interval> intervals { get; set; } = new Dictionary<string, Interval>();
+
+    [Storable(OldName = "StorableIntervalInformation")]
     private KeyValuePair<string, double[]>[] StorableIntervalInformation {
+      set {
+        foreach (var varInt in value)
+          intervals.Add(varInt.Key, new Interval(varInt.Value[0], varInt.Value[1]));
+      }
+    }
+
+    [Storable]
+    private object[] StorableIntervals {
       get {
-        var l = new List<KeyValuePair<string, double[]>>();
-        foreach (var varInt in intervals)
+        var names = intervals.Keys.ToArray();
+        var lowerBounds = intervals.Values.Select(i => i.LowerBound).ToArray();
+        var upperBounds = intervals.Values.Select(i => i.UpperBound).ToArray();
 
-          l.Add(new KeyValuePair<string, double[]>(varInt.Key,
-            new double[] { varInt.Value.LowerBound, varInt.Value.UpperBound }));
-        return l.ToArray();
+        return new object[] { names, lowerBounds, upperBounds };
       }
 
       set {
-        foreach (var varInt in value)
-          intervals.Add(varInt.Key, new Interval(varInt.Value[0], varInt.Value[1]));
+        var names = (string[])value[0];
+        var lowerBounds = (double[])value[1];
+        var upperBounds = (double[])value[2];
+
+        for (int i = 0; i < names.Length; i++) {
+          intervals.Add(names[i], new Interval(lowerBounds[i], upperBounds[i]));
+        }
       }
     }
@@ -80,15 +93,22 @@
     public void SetInterval(string identifier, Interval interval) {
       intervals[identifier] = interval;
+      RaiseChanged();
     }
 
     public void AddInterval(string identifier, Interval interval) {
       intervals.Add(identifier, interval);
+      RaiseChanged();
     }
 
     public void DeleteInterval(string identifier) {
       intervals.Remove(identifier);
+      RaiseChanged();
     }
 
     public IReadOnlyDictionary<string, Interval> GetReadonlyDictionary() {
+      return intervals.ToDictionary(pair => pair.Key, pair => pair.Value);
+    }
+
+    public IDictionary<string, Interval> GetDictionary() {
       return intervals.ToDictionary(pair => pair.Key, pair => pair.Value);
     }
@@ -98,4 +118,12 @@
         yield return Tuple.Create(variableInterval.Key, variableInterval.Value);
     }
+
+    public event EventHandler Changed;
+    private void RaiseChanged() {
+      var handler = Changed;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
   }
 }
Index: branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraint.cs
===================================================================
--- branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraint.cs	(revision 17918)
+++ branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraint.cs	(revision 17918)
@@ -0,0 +1,207 @@
+﻿#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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableType("8109BE58-CCFB-4462-A2F4-EEE5DFADAFF7")]
+  [Item("ShapeConstraint", "Constraint on the shape of a function e.g. monotonicity.")]
+  public sealed class ShapeConstraint : Item {
+    [Storable]
+    private string variable;
+
+    public string Variable {
+      get => variable;
+      private set {
+        if (variable == value)
+          return;
+        variable = value;
+        OnToStringChanged();
+        OnChanged();
+      }
+    }
+
+    public bool IsDerivative => NumberOfDerivations > 0;
+
+    [Storable]
+    private int numberOfDerivations;
+
+    public int NumberOfDerivations {
+      get => numberOfDerivations;
+      set {
+        if (value < 0 || value > 3)
+          throw new ArgumentException("Number of derivation has to be between 0 - 3.");
+        if (numberOfDerivations == value)
+          return;
+        numberOfDerivations = value;
+        OnToStringChanged();
+        OnChanged();
+      }
+    }
+
+    [Storable]
+    private Interval interval;
+
+    public Interval Interval {
+      get => interval;
+      set {
+        if (interval == value)
+          return;
+        interval = value;
+        OnToStringChanged();
+        OnChanged();
+      }
+    }
+
+    [Storable]
+    private IntervalCollection regions;
+    public IntervalCollection Regions {
+      get => regions;
+      set {
+        if (regions != value) {
+          if (regions != null) regions.Changed -= regions_Changed;
+          regions = value;
+          if (regions != null) regions.Changed += regions_Changed;
+          OnToStringChanged();
+          OnChanged();
+        }
+      }
+    }
+
+
+    [Storable]
+    private double weight = 1.0;
+    public double Weight {
+      get => weight;
+      set {
+        if (weight <= 0.0) throw new ArgumentOutOfRangeException("Weight must be larger than zero.");
+        if (weight != value) {
+          weight = value;
+          OnToStringChanged();
+          OnChanged();
+        }
+      }
+    }
+
+    [StorableConstructor]
+    private ShapeConstraint(StorableConstructorFlag _) : base(_) { }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (regions != null) regions.Changed += regions_Changed;
+    }
+
+    // without derivation
+    public ShapeConstraint(Interval interval, double weight)
+      : this(string.Empty, 0,
+         interval, new IntervalCollection(), weight) { }
+
+    public ShapeConstraint(Interval interval, IntervalCollection regions, double weight)
+      : this(string.Empty, 0,
+         interval, regions, weight) { }
+
+    public ShapeConstraint(string variable, int numberOfDerivations,
+                              Interval interval, double weight)
+      : this(variable, numberOfDerivations,
+             interval, new IntervalCollection(), weight) { }
+
+    public ShapeConstraint(string variable, int numberOfDerivations,
+                              Interval interval, IntervalCollection regions, double weight) {
+      Variable = variable;
+      NumberOfDerivations = numberOfDerivations;
+      Interval = interval;
+      Regions = regions;
+      Weight = weight;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ShapeConstraint(this, cloner);
+    }
+
+    private ShapeConstraint(ShapeConstraint original, Cloner cloner)
+      : base(original, cloner) {
+      Variable = original.Variable;
+      NumberOfDerivations = original.NumberOfDerivations;
+      Interval = original.Interval;
+      Regions = cloner.Clone(original.Regions);
+      Weight = original.weight;
+    }
+
+    public event EventHandler Changed;
+
+    private void OnChanged() {
+      var handlers = Changed;
+      if (handlers != null)
+        handlers(this, EventArgs.Empty);
+    }
+
+
+    private void regions_Changed(object sender, EventArgs e) {
+      OnToStringChanged();
+      OnChanged();
+    }
+
+    public override string ToString() {
+      return GenerateExpressionString();
+    }
+
+
+    private string GenerateExpressionString() {
+      string expression;
+      string write(double val) => double.IsPositiveInfinity(val) ? "inf." : double.IsNegativeInfinity(val) ? "-inf." : $"{val}";
+      if (!IsDerivative) {
+        expression = string.Format($"f in [{write(Interval.LowerBound)} .. {write(Interval.UpperBound)}]");
+        if (Regions != null) {
+          foreach (var region in Regions.GetReadonlyDictionary())
+            expression += $", {region.Key} in [{write(region.Value.LowerBound)} .. {write(region.Value.UpperBound)}]";
+        }
+        if (Weight != 1.0) {
+          expression += $" weight: {weight}";
+        }
+
+        return expression;
+      }
+
+      var derivationString = string.Empty;
+      switch (numberOfDerivations) {
+        case 1:
+          derivationString = ""; break;
+        case 2:
+          derivationString = "²"; break;
+        case 3:
+          derivationString = "³"; break;
+      }
+      expression = string.Format($"∂{derivationString}f/∂{Variable}{derivationString} in [{write(Interval.LowerBound)} .. {write(Interval.UpperBound)}]");
+      if (Regions != null) {
+        foreach (var region in Regions.GetReadonlyDictionary())
+          expression += $", {region.Key} in [{write(region.Value.LowerBound)} .. {write(region.Value.UpperBound)}]";
+      }
+      if (Weight != 1.0) {
+        expression += $" weight: {weight}";
+      }
+      return expression;
+    }
+  }
+}
Index: branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraintsParser.cs
===================================================================
--- branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraintsParser.cs	(revision 17918)
+++ branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraintsParser.cs	(revision 17918)
@@ -0,0 +1,242 @@
+﻿#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 System.Text.RegularExpressions;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public static class ShapeConstraintsParser {
+    public static ShapeConstraints ParseConstraints(string text) {
+      if (string.IsNullOrEmpty(text)) throw new ArgumentNullException(nameof(text));
+
+      var lines = text.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
+
+      var sc = new ShapeConstraints();
+      foreach (var line in lines) {
+        var trimmedLine = line.Trim();
+        if (trimmedLine == "") continue; // If it is a comment just continue without saving anything
+        if (trimmedLine.StartsWith("#")) {
+          // disabled constraints are commented
+          var constraint = ParseConstaint(trimmedLine.TrimStart('#', ' '));
+          sc.Add(constraint);
+          sc.SetItemCheckedState(constraint, false);
+        } else {
+          var constraint = ParseConstaint(trimmedLine);
+          sc.Add(constraint);
+          sc.SetItemCheckedState(constraint, true);
+        }
+      }
+      return sc;
+    }
+
+    public static ShapeConstraint ParseConstaint(string expr) {
+      var trimmedLine = expr.TrimStart();
+      if (trimmedLine.StartsWith("f")) {
+        return ParseFunctionRangeConstraint(expr);
+      } else if (trimmedLine.StartsWith("d") || trimmedLine.StartsWith("∂")) {
+        return ParseDerivationConstraint(expr);
+      } else {
+        throw new
+          ArgumentException($"Error at in definition {expr}. Constraints have to start with (f | d | ∂ | #)",
+                            nameof(expr));
+      }
+    }
+
+    // [124 .. 145]
+    private const string intervalRegex = @"\s*[\[]" +
+                                         @"\s*(?<lowerBound>[^\s;]*)" +
+                                         @"\s*(\.{2}|\s+|;)" +
+                                         @"\s*(?<upperBound>[^\s\]]*)" +
+                                         @"\s*[\]]";
+
+    private const string variableRegex = @"(['](?<varName>.*)[']|(?<varName>[^\s²³]+))\s*";
+    private const string weightRegex = @"\s*(weight:\s*(?<weight>\S*))?";
+    public static ShapeConstraint ParseFunctionRangeConstraint(string expr) {
+      if (!expr.StartsWith("f")) throw new ArgumentException($"Invalid function range constraint {expr} (e.g. f in [1..2])");
+      var start = "f".Length;
+      var end = expr.Length;
+      var targetConstraint = expr.Substring(start, end - start);
+
+
+      // # Example for a target variable constraint:
+      // f in [0 .. 100]
+      // # Example for constraints on model parameters: 
+      // df/d'x' in [0 .. 10]
+      // ∂²f/∂'x'² in [-1 .. inf.]
+      // df/d'x' in [0 .. 10] weight: 2.0
+      // df / d'x' in [0..10], 'x' in [1 .. 3]
+      // df / d'x' in [0..10], 'x' in [1 .. 3], y in [10..30] weight: 1.2
+
+      var match = Regex.Match(targetConstraint,
+                    @"\s*\bin\b" +
+                    intervalRegex +
+                    @"(" +
+                      @"\s*,\s*" + variableRegex +
+                      @"\s *\bin\b" +
+                      intervalRegex +
+                    @")*" +
+                    weightRegex
+                    );
+
+
+      if (match.Success) {
+        // if (match.Groups.Count < 19) throw new ArgumentException("The target-constraint is not complete.", nameof(expr));
+
+        var lowerBound = ParseIntervalBounds(match.Groups["lowerBound"].Captures[0].Value);
+        var upperBound = ParseIntervalBounds(match.Groups["upperBound"].Captures[0].Value);
+        var interval = new Interval(lowerBound, upperBound);
+        var weight = 1.0;
+
+        if (match.Groups["weight"].Success && !string.IsNullOrWhiteSpace(match.Groups["weight"].Value))
+          weight = ParseAndValidateDouble(match.Groups["weight"].Value);
+
+        if (match.Groups["varName"].Success) {
+          IntervalCollection regions = new IntervalCollection();
+          // option variables found
+          for (int idx = 0; idx < match.Groups["varName"].Captures.Count; ++idx) {
+            KeyValuePair<string, Interval> region = ParseRegion(
+              variable: match.Groups["varName"].Captures[idx].Value,
+              lb: match.Groups["lowerBound"].Captures[idx + 1].Value,
+              ub: match.Groups["upperBound"].Captures[idx + 1].Value);
+            if (regions.GetReadonlyDictionary().All(r => r.Key != region.Key))
+              regions.AddInterval(region.Key, region.Value);
+            else
+              throw new ArgumentException($"The constraint {expr} has multiple regions of the same variable.");
+          }
+          return new ShapeConstraint(interval, regions, weight);
+        } else
+          return new ShapeConstraint(interval, weight);
+      } else
+        throw new ArgumentException($"The target constraint {expr} is not valid.");
+    }
+    public static ShapeConstraint ParseDerivationConstraint(string expr) {
+      var match = Regex.Match(expr,
+                                @"([d∂])" +
+                                @"(?<numDerivations>[²³]?)\s*" +
+                                @"f\s*" +
+                                @"(\/)\s*" +
+                                @"([d∂])\s*" +
+                                variableRegex +
+                                @"(?<numDerivations>[²³]?)\s*\bin\b\s*" +
+                                intervalRegex +
+                                @"(" +
+                                  @"\s*,\s*" + variableRegex +
+                                  @"\s *\bin\b" +
+                                  intervalRegex +
+                                  @")*" +
+                                weightRegex
+                                );
+
+      if (match.Success) {
+        // if (match.Groups.Count < 26)
+        //   throw new ArgumentException("The given derivation-constraint is not complete.", nameof(expr));
+
+        var derivationVariable = match.Groups["varName"].Captures[0].Value.Trim();
+
+        var enumeratorNumDeriv = match.Groups["numDerivations"].Captures[0].Value.Trim();
+        var denominatorNumDeriv = match.Groups["numDerivations"].Captures[1].Value.Trim();
+        if (enumeratorNumDeriv != "" || denominatorNumDeriv != "") {
+          if (enumeratorNumDeriv == "" || denominatorNumDeriv == "")
+            throw new ArgumentException($"Number of derivation has to be written on both sides in {expr}.");
+          if (enumeratorNumDeriv != denominatorNumDeriv)
+            throw new ArgumentException($"Derivation number is not equal on both sides in {expr}.");
+        }
+
+        var lowerBound = ParseIntervalBounds(match.Groups["lowerBound"].Captures[0].Value);
+        var upperBound = ParseIntervalBounds(match.Groups["upperBound"].Captures[0].Value);
+        var variable = derivationVariable;
+        var numberOfDerivation = ParseDerivationCount(enumeratorNumDeriv);
+        var interval = new Interval(lowerBound, upperBound);
+        var weight = 1.0;
+
+        if (match.Groups["weight"].Success && !string.IsNullOrWhiteSpace(match.Groups["weight"].Value))
+          weight = ParseAndValidateDouble(match.Groups["weight"].Value);
+
+        if (match.Groups["varName"].Captures.Count > 1) {
+          IntervalCollection regions = new IntervalCollection();
+          // option variables found
+          for (int idx = 0; idx < match.Groups["varName"].Captures.Count - 1; ++idx) {
+            KeyValuePair<string, Interval> region = ParseRegion(
+              variable: match.Groups["varName"].Captures[idx + 1].Value,
+              lb: match.Groups["lowerBound"].Captures[idx + 1].Value,
+              ub: match.Groups["upperBound"].Captures[idx + 1].Value);
+            if (regions.GetReadonlyDictionary().All(r => r.Key != region.Key))
+              regions.AddInterval(region.Key, region.Value);
+            else
+              throw new ArgumentException($"The constraint {expr} has multiple regions of the same variable.");
+          }
+          return new ShapeConstraint(variable, numberOfDerivation, interval, regions, weight);
+        } else
+          return new ShapeConstraint(variable, numberOfDerivation, interval, weight);
+      } else
+        throw new ArgumentException($"The derivation constraint {expr} is not valid.");
+    }
+
+
+    private static KeyValuePair<string, Interval> ParseRegion(string variable, string lb, string ub) {
+      var regionLb = ParseIntervalBounds(lb);
+      var regionUb = ParseIntervalBounds(ub);
+      return new KeyValuePair<string, Interval>(variable, new Interval(regionLb, regionUb));
+    }
+
+    private static double ParseIntervalBounds(string input) {
+      input = input.ToLower();
+      switch (input) {
+        case "+inf.":
+        case "inf.":
+          return double.PositiveInfinity;
+        case "-inf.":
+          return double.NegativeInfinity;
+        default: {
+            return ParseAndValidateDouble(input);
+          }
+      }
+    }
+
+    private static double ParseAndValidateDouble(string input) {
+      var valid = double.TryParse(input, out var value);
+      if (!valid) {
+        throw new ArgumentException($"Invalid value {input} (valid value format: \"" + "+inf. | inf. | -inf. | " + FormatPatterns.GetDoubleFormatPattern() + "\")");
+      }
+
+      return value;
+    }
+
+    private static int ParseDerivationCount(string input) {
+      switch (input) {
+        case "":
+          return 1;
+        case "²":
+          return 2;
+        case "³":
+          return 3;
+        default:
+          int.TryParse(input, out var value);
+          return value;
+      }
+    }
+  }
+}
Index: branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs
===================================================================
--- branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs	(revision 17842)
+++ branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs	(revision 17918)
@@ -35,5 +35,5 @@
     protected const string TargetVariableParameterName = "TargetVariable";
     protected const string VariableRangesParameterName = "VariableRanges";
-    protected const string IntervalConstraintsParameterName = "IntervalConstraints";
+    protected const string ShapeConstraintsParameterName = "ShapeConstraints";
     public string Filename { get; set; }
 
@@ -94,17 +94,22 @@
       problemData.Parameters.Add(new ConstrainedValueParameter<StringValue>(TargetVariableParameterName, new ItemSet<StringValue>()));
       problemData.Parameters.Add(new FixedValueParameter<IntervalCollection>(VariableRangesParameterName, "", new IntervalCollection()));
+      problemData.Parameters.Add(new FixedValueParameter<ShapeConstraints>(ShapeConstraintsParameterName, "", new ShapeConstraints()));
       emptyProblemData = problemData;
     }
     #endregion
 
-    public IConstrainedValueParameter<StringValue> TargetVariableParameter {
-      get { return (IConstrainedValueParameter<StringValue>)Parameters[TargetVariableParameterName]; }
-    }
-
+    #region parameter properties
+    public IConstrainedValueParameter<StringValue> TargetVariableParameter => (IConstrainedValueParameter<StringValue>)Parameters[TargetVariableParameterName];
+    public IFixedValueParameter<ShapeConstraints> ShapeConstraintsParameter => (IFixedValueParameter<ShapeConstraints>)Parameters[ShapeConstraintsParameterName];
     public IFixedValueParameter<IntervalCollection> VariableRangesParameter => (IFixedValueParameter<IntervalCollection>)Parameters[VariableRangesParameterName];
-
+    #endregion
+
+    #region properties
     public IntervalCollection VariableRanges {
       get => VariableRangesParameter.Value;
     }
+
+
+    public ShapeConstraints ShapeConstraints => ShapeConstraintsParameter.Value;
 
 
@@ -120,14 +125,9 @@
       }
     }
-
-    public IEnumerable<double> TargetVariableValues {
-      get { return Dataset.GetDoubleValues(TargetVariable); }
-    }
-    public IEnumerable<double> TargetVariableTrainingValues {
-      get { return Dataset.GetDoubleValues(TargetVariable, TrainingIndices); }
-    }
-    public IEnumerable<double> TargetVariableTestValues {
-      get { return Dataset.GetDoubleValues(TargetVariable, TestIndices); }
-    }
+    public IEnumerable<double> TargetVariableValues => Dataset.GetDoubleValues(TargetVariable);
+    public IEnumerable<double> TargetVariableTrainingValues => Dataset.GetDoubleValues(TargetVariable, TrainingIndices);
+    public IEnumerable<double> TargetVariableTestValues => Dataset.GetDoubleValues(TargetVariable, TestIndices);
+    #endregion
+
 
 
@@ -137,7 +137,16 @@
     private void AfterDeserialization() {
       if (!Parameters.ContainsKey(VariableRangesParameterName)) {
-        var intervalCollection = CalculateDatasetIntervals(this.Dataset);
+        var intervalCollection = Dataset.GetIntervals();
         Parameters.Add(new FixedValueParameter<IntervalCollection>(VariableRangesParameterName, intervalCollection));
       }
+      if (Parameters.ContainsKey("IntervalConstraints")) {
+        var param = (IFixedValueParameter<ShapeConstraints>)Parameters["IntervalConstraints"];
+        Parameters.Remove(param);
+        Parameters.Add(new FixedValueParameter<ShapeConstraints>(ShapeConstraintsParameterName, param.Value));
+      }
+      if (!Parameters.ContainsKey(ShapeConstraintsParameterName)) {
+        Parameters.Add(new FixedValueParameter<ShapeConstraints>(ShapeConstraintsParameterName, new ShapeConstraints()));
+      }
+
       RegisterParameterEvents();
     }
@@ -163,27 +172,27 @@
     }
 
-    public RegressionProblemData(IDataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable, IEnumerable<ITransformation> transformations = null)
+    public RegressionProblemData(IDataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable,
+      IEnumerable<ITransformation> transformations = null,
+      IntervalCollection variableRanges = null,
+      ShapeConstraints shapeConstraints = null)
       : base(dataset, allowedInputVariables, transformations ?? Enumerable.Empty<ITransformation>()) {
       var variables = InputVariables.Select(x => x.AsReadOnly()).ToList();
       Parameters.Add(new ConstrainedValueParameter<StringValue>(TargetVariableParameterName, new ItemSet<StringValue>(variables), variables.Where(x => x.Value == targetVariable).First()));
-      var intervalCollection = CalculateDatasetIntervals(this.Dataset);
-      Parameters.Add(new FixedValueParameter<IntervalCollection>(VariableRangesParameterName, intervalCollection));
+      if (variableRanges == null) {
+        variableRanges = Dataset.GetIntervals();
+      }
+      Parameters.Add(new FixedValueParameter<IntervalCollection>(VariableRangesParameterName, variableRanges));
+
+      if (shapeConstraints == null) {
+        shapeConstraints = new ShapeConstraints();
+      }
+      Parameters.Add(new FixedValueParameter<ShapeConstraints>(ShapeConstraintsParameterName, shapeConstraints));
       RegisterParameterEvents();
     }
-
-    private static IntervalCollection CalculateDatasetIntervals(IDataset dataset) {
-      IntervalCollection intervalCollection = new IntervalCollection();
-      foreach (var variable in dataset.DoubleVariables) {// intervals are only possible for double variables
-        var variableInterval = Interval.GetInterval(dataset.GetDoubleValues(variable));
-        intervalCollection.AddInterval(variable, variableInterval);
-      }
-
-      return intervalCollection;
-    }
-
     private void RegisterParameterEvents() {
-      TargetVariableParameter.ValueChanged += new EventHandler(TargetVariableParameter_ValueChanged);
-    }
-    private void TargetVariableParameter_ValueChanged(object sender, EventArgs e) {
+      TargetVariableParameter.ValueChanged += new EventHandler(Parameter_ValueChanged);
+      // VariableRanges and ShapeConstraints are fixed parameters
+    }
+    private void Parameter_ValueChanged(object sender, EventArgs e) {
       OnChanged();
     }
Index: branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstraints.cs
===================================================================
--- branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstraints.cs	(revision 17918)
+++ branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstraints.cs	(revision 17918)
@@ -0,0 +1,85 @@
+﻿#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 System.Collections.Generic;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Collections;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableType("A56BFB05-8F11-4766-9FBF-20C7010F1CA3")]
+  [Item("ShapeConstraints", "Represents shape constraints associated with a regression problem data e.g. monotonicity constraints.")]
+  public class ShapeConstraints : CheckedItemList<ShapeConstraint> {
+    public IEnumerable<ShapeConstraint> EnabledConstraints => base.CheckedItems.Select(checkedItem => checkedItem.Value);
+
+    protected override void OnItemsAdded(IEnumerable<IndexedItem<ShapeConstraint>> items) {
+      base.OnItemsAdded(items);
+      foreach (var item in items)
+        item.Value.Changed += Item_Changed;
+    }
+
+    protected override void OnItemsRemoved(IEnumerable<IndexedItem<ShapeConstraint>> items) {
+      base.OnItemsRemoved(items);
+      foreach (var item in items)
+        item.Value.Changed -= Item_Changed;
+    }
+
+    protected override void OnCollectionReset(
+      IEnumerable<IndexedItem<ShapeConstraint>> items,
+      IEnumerable<IndexedItem<ShapeConstraint>> oldItems) {
+      base.OnCollectionReset(items, oldItems);
+      foreach (var item in items)
+        item.Value.Changed += Item_Changed;
+      foreach (var item in oldItems)
+        item.Value.Changed -= Item_Changed;
+    }
+
+    private void Item_Changed(object sender, EventArgs e) {
+      RaiseChanged();
+    }
+
+    [StorableConstructor]
+    protected ShapeConstraints(StorableConstructorFlag _) : base(_) { }
+
+    protected ShapeConstraints(ShapeConstraints original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ShapeConstraints(this, cloner);
+    }
+
+    public ShapeConstraints() : base() {
+    }
+
+    public event EventHandler Changed;
+
+    private void RaiseChanged() {
+      var handlers = Changed;
+      if (handlers != null)
+        handlers(this, EventArgs.Empty);
+    }
+  }
+}
Index: branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionProblemData.cs
===================================================================
--- branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionProblemData.cs	(revision 17842)
+++ branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionProblemData.cs	(revision 17918)
@@ -1,3 +1,4 @@
 ﻿#region License Information
+
 /* HeuristicLab
  * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
@@ -18,4 +19,5 @@
  * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
  */
+
 #endregion
 
@@ -28,5 +30,6 @@
     string TargetVariable { get; set; }
 
-    IntervalCollection VariableRanges { get;}
+    IntervalCollection VariableRanges { get; }
+    ShapeConstraints ShapeConstraints { get; }
 
     IEnumerable<double> TargetVariableValues { get; }
