Index: /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj
===================================================================
--- /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj	(revision 18212)
+++ /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj	(revision 18213)
@@ -263,4 +263,8 @@
       <Private>False</Private>
     </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Random\3.3\HeuristicLab.Random-3.3.csproj">
+      <Project>{F4539FB6-4708-40C9-BE64-0A1390AEA197}</Project>
+      <Name>HeuristicLab.Random-3.3</Name>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
Index: /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/ShapeConstraintsAnalyzer.cs
===================================================================
--- /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/ShapeConstraintsAnalyzer.cs	(revision 18212)
+++ /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/ShapeConstraintsAnalyzer.cs	(revision 18213)
@@ -20,4 +20,6 @@
 #endregion
 
+using System.Collections;
+using System.Collections.Generic;
 using System.Linq;
 using HEAL.Attic;
@@ -28,4 +30,5 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
+using HeuristicLab.Random;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
@@ -36,4 +39,6 @@
     private const string ConstraintViolationsParameterName = "ConstraintViolations";
     private const string InfeasibleSolutionsParameterName = "InfeasibleSolutions";
+    private const string AverageConstraintViolationsParameterName = "AverageConstraintViolations";
+    private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicExpressionTreeInterpreter";
 
     #region parameter properties
@@ -48,10 +53,17 @@
       (IResultParameter<DataTable>)Parameters[InfeasibleSolutionsParameterName];
 
+    public IResultParameter<DataTable> AverageConstraintViolationsParameter =>
+      (IResultParameter<DataTable>)Parameters[AverageConstraintViolationsParameterName];
+
+    public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> SymbolicDataAnalysisTreeInterpreterParameter =>
+      (ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[SymbolicDataAnalysisTreeInterpreterParameterName];
+    
     #endregion
 
-    #region properties
+      #region properties
     public IRegressionProblemData RegressionProblemData => RegressionProblemDataParameter.ActualValue;
     public DataTable ConstraintViolations => ConstraintViolationsParameter.ActualValue;
     public DataTable InfeasibleSolutions => InfeasibleSolutionsParameter.ActualValue;
+    public DataTable AverageConstraintViolations => AverageConstraintViolationsParameter.ActualValue;
     #endregion
 
@@ -75,4 +87,9 @@
       Parameters.Add(new ResultParameter<DataTable>(InfeasibleSolutionsParameterName,
         "The number of infeasible solutions."));
+      Parameters.Add(new ResultParameter<DataTable>(AverageConstraintViolationsParameterName,
+        "The average violations of each constraint."));
+      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName, 
+        "The interpreter that should be used to calculate the output values of the symbolic data analysis tree.") { Hidden = true });
+
 
 
@@ -90,27 +107,71 @@
         }
       };
+
+      AverageConstraintViolationsParameter.DefaultValue = new DataTable(SymbolicDataAnalysisTreeInterpreterParameterName) {
+        VisualProperties = {
+          XAxisTitle = "Generations",
+          YAxisTitle = "Average Constraint Violations"
+        }
+      };
     }
 
 
     [StorableHook(HookType.AfterDeserialization)]
-    private void AfterDeserialization() { }
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey(SymbolicDataAnalysisTreeInterpreterParameterName))
+        Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName,
+          "The interpreter that should be used to calculate the output values of the symbolic data analysis tree.") { Hidden = true });
+    }
 
     public override IOperation Apply() {
       var problemData = (IShapeConstrainedRegressionProblemData)RegressionProblemData;
       var trees = SymbolicExpressionTree.ToArray();
-
+      
       var results = ResultCollection;
-      var constraints = problemData.ShapeConstraints.EnabledConstraints;
+      var modelConstraints = problemData.ShapeConstraints.EnabledConstraints;
+      var extendedConstraints = problemData.CheckedExtendedConstraints;
       var variableRanges = problemData.VariableRanges;
       var constraintViolationsTable = ConstraintViolations;
+      var averageConstraintViolations = AverageConstraintViolations;
+      var interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
       var estimator = new IntervalArithBoundsEstimator();
+      
+      if (!constraintViolationsTable.Rows.Any()) {
+        foreach (var constraint in modelConstraints) {
+          constraintViolationsTable.Rows.Add(new DataRow(constraint.ToString()));
+          averageConstraintViolations.Rows.Add(new DataRow(constraint.ToString()));
+        }
 
-      if (!constraintViolationsTable.Rows.Any())
-        foreach (var constraint in constraints)
-          constraintViolationsTable.Rows.Add(new DataRow(constraint.ToString()));
+        foreach (var extendedConstraint in extendedConstraints.SelectMany(x => x.ShapeConstraints.EnabledConstraints)) {
+          constraintViolationsTable.Rows.Add(new DataRow(extendedConstraint.ToString()));
+          averageConstraintViolations.Rows.Add(new DataRow(extendedConstraint.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 violationsPerTree = new Dictionary<ISymbolicExpressionTree, int>();
+      var violationsPerConstraint = new Dictionary<string, IList<double>>();
+
+      foreach(var tree in trees) {
+        var violations = NMSESingleObjectiveConstraintsEvaluator.CalculateShapeConstraintsViolations(problemData, tree, interpreter, estimator, new MersenneTwister());
+        foreach(var violation in violations) {
+          var constraint = violation.Item1;
+          var error = violation.Item2;
+          if (!violationsPerConstraint.ContainsKey(constraint.ToString()))
+            violationsPerConstraint.Add(constraint.ToString(), new List<double>());
+          violationsPerConstraint[constraint.ToString()].Add(error);
+        }
+        violationsPerTree.Add(tree, violations.Count(x => x.Item2 > 0));
+      }
+
+      foreach (var constraint in modelConstraints) {
+        var errors = violationsPerConstraint[constraint.ToString()];
+        constraintViolationsTable.Rows[constraint.ToString()].Values.Add(errors.Count(x => x > 0));
+        averageConstraintViolations.Rows[constraint.ToString()].Values.Add(errors.Sum() / errors.Count());
+      }
+
+      foreach (var extendedConstraint in extendedConstraints.SelectMany(x => x.ShapeConstraints.EnabledConstraints)) {
+        var errors = violationsPerConstraint[extendedConstraint.ToString()];
+        constraintViolationsTable.Rows[extendedConstraint.ToString()].Values.Add(errors.Count(x => x > 0));
+        averageConstraintViolations.Rows[extendedConstraint.ToString()].Values.Add(errors.Sum() / errors.Count());
       }
 
@@ -121,5 +182,5 @@
       infeasibleSolutionsDataTable.Rows[InfeasibleSolutionsParameterName]
         .Values
-        .Add(trees.Count(t => IntervalUtil.GetConstraintViolations(constraints, estimator, variableRanges, t).Any(x => x > 0.0)));
+        .Add(trees.Count(t => violationsPerTree[t] > 0));
 
       return base.Apply();
Index: /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NMSESingleObjectiveConstraintsEvaluator.cs
===================================================================
--- /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NMSESingleObjectiveConstraintsEvaluator.cs	(revision 18212)
+++ /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NMSESingleObjectiveConstraintsEvaluator.cs	(revision 18213)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
@@ -29,4 +30,5 @@
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Parameters;
+using HeuristicLab.Random;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
@@ -41,5 +43,4 @@
     private const string BoundsEstimatorParameterName = "BoundsEstimator";
     private const string PenaltyFactorParameterName = "PenaltyFactor";
-    private const string ExtendedConstraintsParameterName = "ExtendedConstraints";
 
 
@@ -58,6 +59,4 @@
       (IFixedValueParameter<DoubleValue>)Parameters[PenaltyFactorParameterName];
 
-    public IFixedValueParameter<IItemList<ExtendedConstraint>> ExtendedConstraintsParameter =>
-      (IFixedValueParameter<IItemList<ExtendedConstraint>>)Parameters[ExtendedConstraintsParameterName];
 
 
@@ -86,10 +85,4 @@
       set => PenaltyFactorParameter.Value.Value = value;
     }
-
-    public IEnumerable<ExtendedConstraint> ExtendedConstraints {
-      get => ExtendedConstraintsParameter.Value;
-    }
-      
-
 
     public override bool Maximization => false; // NMSE is minimized
@@ -116,5 +109,4 @@
       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)));
-      Parameters.Add(new FixedValueParameter<ItemList<ExtendedConstraint>>(ExtendedConstraintsParameterName, "", new ItemList<ExtendedConstraint>()));
     }
 
@@ -135,4 +127,5 @@
       var estimationLimits = EstimationLimitsParameter.ActualValue;
       var applyLinearScaling = ApplyLinearScalingParameter.ActualValue.Value;
+      var random = RandomParameter.ActualValue;
 
       if (OptimizeParameters) {
@@ -175,5 +168,5 @@
 
       var quality = Calculate(interpreter, tree, estimationLimits.Lower, estimationLimits.Upper, problemData, rows,
-        BoundsEstimator, UseSoftConstraints, PenalityFactor, ExtendedConstraints);
+        BoundsEstimator, random, UseSoftConstraints, PenalityFactor);
       QualityParameter.ActualValue = new DoubleValue(quality);
 
@@ -186,29 +179,24 @@
       double lowerEstimationLimit, double upperEstimationLimit,
       IRegressionProblemData problemData, IEnumerable<int> rows,
-      IBoundsEstimator estimator,
-      bool useSoftConstraints = false, double penaltyFactor = 1.0,
-      IEnumerable<ExtendedConstraint> extendedConstraints = null) {
-
-      var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
+      IBoundsEstimator estimator, IRandom random,
+      bool useSoftConstraints = false, double penaltyFactor = 1.0) {
+
+      var trainingEstimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
       var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
-      var constraints = Enumerable.Empty<ShapeConstraint>();
+
+      var trainingBoundedEstimatedValues = trainingEstimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
+      var nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, trainingBoundedEstimatedValues,
+        out var errorState);
+
+      if (errorState != OnlineCalculatorError.None)
+        return double.MaxValue;
+
+      var violations = Enumerable.Empty<double>();
       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;
-      }
+        violations = CalculateShapeConstraintsViolations(scProbData, tree, interpreter, estimator, random).Select(x => x.Item2);
+      }
+
+      if (violations.Any(x => double.IsNaN(x) || double.IsInfinity(x)))
+        return double.MaxValue;
 
       if (useSoftConstraints) {
@@ -216,14 +204,66 @@
           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;
+        return nmse + penaltyFactor * violations.Average();
+      }
+      return violations.Any(x => x > 0.0) ? 1.0 : nmse;
+    }
+
+    public static IEnumerable<Tuple<ShapeConstraint, double>> CalculateShapeConstraintsViolations(
+      IShapeConstrainedRegressionProblemData problemData, ISymbolicExpressionTree tree, 
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IBoundsEstimator estimator,
+      IRandom random) {
+      IList<Tuple<ShapeConstraint, double>> violations = new List<Tuple<ShapeConstraint, double>>();
+      
+      var baseConstraints = problemData.ShapeConstraints.EnabledConstraints;
+      var intervalCollection = problemData.VariableRanges;
+      var extendedShapeConstraints = problemData.CheckedExtendedConstraints;
+      var allEstimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, problemData.AllIndices);
+
+      foreach (var constraint in baseConstraints)
+        violations.Add(Tuple.Create(constraint, IntervalUtil.GetConstraintViolation(constraint, estimator, intervalCollection, tree) * constraint.Weight));
+
+      IDictionary<string, IList> dict = new Dictionary<string, IList>();
+      foreach (var varName in problemData.Dataset.VariableNames) {
+        if (varName != problemData.TargetVariable)
+          dict.Add(varName, problemData.Dataset.GetDoubleValues(varName).ToList());
+        else dict.Add(varName, allEstimatedValues.ToList());
+      }
+      var tmpDataset = new Dataset(dict.Keys, dict.Values);
+
+      foreach (var extendedConstraint in extendedShapeConstraints) {
+        var enabledConstraints = extendedConstraint.ShapeConstraints.EnabledConstraints;
+        if (enabledConstraints.Any()) {
+          var extendedConstraintExprValues = interpreter.GetSymbolicExpressionTreeValues(extendedConstraint.Tree, tmpDataset, problemData.AllIndices);
+          var extendedConstraintExprInterval = new Interval(extendedConstraintExprValues.Min(), extendedConstraintExprValues.Max());
+
+          foreach (var constraint in enabledConstraints) {
+            if (constraint.Regions.Count > 0) {
+              // adapt dataset
+              foreach (var kvp in constraint.Regions.GetReadonlyDictionary()) {
+                var lb = double.IsNegativeInfinity(kvp.Value.LowerBound) ? double.MinValue : kvp.Value.LowerBound;
+                var ub = double.IsPositiveInfinity(kvp.Value.UpperBound) ? double.MaxValue : kvp.Value.UpperBound;
+
+                var vals = Enumerable.Range(0, dict[kvp.Key].Count - 2)
+                                     .Select(x => UniformDistributedRandom.NextDouble(random, lb, ub))
+                                     .ToList();
+                vals.Add(lb);
+                vals.Add(ub);
+                vals.Sort();
+                dict[kvp.Key] = vals;
+              }
+              // calc again with new regions
+              tmpDataset = new Dataset(dict.Keys, dict.Values);
+              // calc target again
+              allEstimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, tmpDataset, problemData.AllIndices);
+              dict[problemData.TargetVariable] = allEstimatedValues.ToList();
+              tmpDataset = new Dataset(dict.Keys, dict.Values);
+              extendedConstraintExprValues = interpreter.GetSymbolicExpressionTreeValues(extendedConstraint.Tree, tmpDataset, problemData.AllIndices);
+              extendedConstraintExprInterval = new Interval(extendedConstraintExprValues.Min(), extendedConstraintExprValues.Max());
+            }
+            violations.Add(Tuple.Create(constraint, IntervalUtil.GetIntervalError(constraint.Interval, extendedConstraintExprInterval, constraint.Threshold) * constraint.Weight));
+          }
+        }
+      }
+      return violations;
     }
 
@@ -234,12 +274,14 @@
       EstimationLimitsParameter.ExecutionContext = context;
       ApplyLinearScalingParameter.ExecutionContext = context;
+      RandomParameter.ExecutionContext = context;
 
       var nmse = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree,
         EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper,
-        problemData, rows, BoundsEstimator, UseSoftConstraints, PenalityFactor, ExtendedConstraints);
+        problemData, rows, BoundsEstimator, RandomParameter.Value, UseSoftConstraints, PenalityFactor);
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
       EstimationLimitsParameter.ExecutionContext = null;
       ApplyLinearScalingParameter.ExecutionContext = null;
+      RandomParameter.ExecutionContext = null;
 
       return nmse;
Index: /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/ExtendedConstraint.cs
===================================================================
--- /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/ExtendedConstraint.cs	(revision 18213)
+++ /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/ExtendedConstraint.cs	(revision 18213)
@@ -0,0 +1,57 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableType("819EF151-C9A4-48A9-A664-AF6E906DD553")]
+  public class ExtendedConstraint : ParameterizedNamedItem, IExtendedConstraint {
+    #region Constants
+    private const string ExpressionParameterName = "Expression";
+    private const string ShapeConstraintsParameterName = "Shape Constraints";
+    #endregion
+
+    #region Parameters
+    public IFixedValueParameter<StringValue> ExpressionParameter => 
+      (IFixedValueParameter<StringValue>)Parameters[ExpressionParameterName];
+
+    public IFixedValueParameter<ShapeConstraints> ShapeConstraintsParameter =>
+      (IFixedValueParameter<ShapeConstraints>)Parameters[ShapeConstraintsParameterName];
+    #endregion
+
+    #region Properties
+    public string Expression => ExpressionParameter.Value.Value;
+    public ISymbolicExpressionTree Tree => string.IsNullOrEmpty(Expression) ? null : Parser.Parse(Expression);
+    public ShapeConstraints ShapeConstraints => ShapeConstraintsParameter.Value;
+    private InfixExpressionParser Parser => new InfixExpressionParser();
+    #endregion
+
+    #region Constructors & Cloning
+    public ExtendedConstraint() {
+      Parameters.Add(new FixedValueParameter<StringValue>(ExpressionParameterName, new StringValue("")));
+      Parameters.Add(new FixedValueParameter<ShapeConstraints>(ShapeConstraintsParameterName, new ShapeConstraints()));
+    }
+
+    protected ExtendedConstraint(ExtendedConstraint original, Cloner cloner) : base(original, cloner) { }
+
+    [StorableConstructor]
+    protected ExtendedConstraint(StorableConstructorFlag _) : base(_) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) =>
+      new ExtendedConstraint(this, cloner);
+
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+    #endregion
+
+    public override string ToString() => string.IsNullOrEmpty(Expression) ? ItemName : Expression;
+  }
+}
Index: /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 18212)
+++ /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 18213)
@@ -160,4 +160,5 @@
     <Compile Include="Creators\SymbolicDataAnalysisExpressionBalancedTreeCreator.cs" />
     <Compile Include="Crossovers\SymbolicDataAnalysisExpressionDiversityPreservingCrossover.cs" />
+    <Compile Include="ExtendedConstraint.cs" />
     <Compile Include="Formatters\InfixExpressionFormatter.cs" />
     <Compile Include="Formatters\SymbolicDataAnalysisExpressionPythonFormatter.cs" />
Index: /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/IntervalUtil.cs
===================================================================
--- /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/IntervalUtil.cs	(revision 18212)
+++ /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/IntervalUtil.cs	(revision 18213)
@@ -28,13 +28,7 @@
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   public static class IntervalUtil {
-    public static IEnumerable<double> GetConstraintViolations(
-      IEnumerable<ShapeConstraint> constraints, IBoundsEstimator estimator, IntervalCollection intervalCollection,
-      ISymbolicExpressionTree solution) {
-      return constraints.Select(constraint => GetConstraintViolation(constraint, estimator, intervalCollection, solution)).ToList();
-    }
-
-    public static double GetConstraintViolation(
+    private static void Prepare(
       ShapeConstraint constraint, IBoundsEstimator estimator, IntervalCollection variableRanges,
-      ISymbolicExpressionTree tree) {
+      ISymbolicExpressionTree tree, out ISymbolicExpressionTree preparedTree, out IntervalCollection preparedRanges) {
       var varRanges = variableRanges.GetReadonlyDictionary();
 
@@ -55,17 +49,66 @@
       }
 
-      if (!constraint.IsDerivative) {
-        return estimator.GetConstraintViolation(tree, regionRanges, constraint);
-      } else {
+      if (constraint.IsDerivative) {
         for (var i = 0; i < constraint.NumberOfDerivations; ++i) {
-          if (!estimator.IsCompatible(tree) || !DerivativeCalculator.IsCompatible(tree)) {
+          if (!estimator.IsCompatible(tree) || !DerivativeCalculator.IsCompatible(tree))
             throw new ArgumentException("The tree contains an unsupported symbol.");
-          }
 
           tree = DerivativeCalculator.Derive(tree, constraint.Variable);
         }
+      }
 
-        return estimator.GetConstraintViolation(tree, regionRanges, constraint);
+      preparedTree = tree;
+      preparedRanges = regionRanges;
+    }
+
+    public static IEnumerable<double> GetConstraintViolations(
+      IEnumerable<ShapeConstraint> constraints, IBoundsEstimator estimator, IntervalCollection intervalCollection,
+      ISymbolicExpressionTree solution) {
+      return constraints.Select(constraint => GetConstraintViolation(constraint, estimator, intervalCollection, solution)).ToList();
+    }
+
+    public static double GetConstraintViolation(
+      ShapeConstraint constraint, IBoundsEstimator estimator, IntervalCollection variableRanges,
+      ISymbolicExpressionTree tree) {
+
+      Prepare(constraint, estimator, variableRanges, tree,
+        out ISymbolicExpressionTree preparedTree, out IntervalCollection preparedRanges);
+
+      var bounds = estimator.GetModelBound(preparedTree, preparedRanges);
+
+      return GetIntervalError(constraint.Interval, bounds, constraint.Threshold);
+
+      //return estimator.GetConstraintViolation(preparedTree, preparedRanges, constraint);
+    }
+
+    public static double GetIntervalError(Interval target, Interval estimation, Interval? threshold = null) {
+      if(threshold == null)
+        threshold = new Interval(0, 0);
+
+      var error = 0d;
+      if (!target.Contains(estimation.LowerBound)) {
+        var lbError = Math.Abs(estimation.LowerBound - target.LowerBound);
+        error += CalcBoundViolation(lbError, threshold.LowerBound);
       }
+
+      if (!target.Contains(estimation.UpperBound)) {
+        var ubError = Math.Abs(estimation.UpperBound - target.UpperBound);
+        error += CalcBoundViolation(ubError, threshold.UpperBound);
+      }
+
+      return error == 0 ? 0 : error / 2.0;
+
+    }
+
+    private static double CalcBoundViolation(double error, double threshold) {
+      threshold = Math.Abs(threshold);
+
+      if (double.IsNaN(error)) return 1.0;
+      if (double.IsInfinity(error) && !double.IsInfinity(threshold)) return 1.0;
+      if (double.IsInfinity(threshold)) return 0;
+      if (error <= 0) return 0;
+      if (error > threshold) return 1.0;      
+      if (threshold > 0) return Math.Min(1.0, error / threshold);
+      return 1.0;
     }
   }
Index: /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj
===================================================================
--- /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 18212)
+++ /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 18213)
@@ -188,4 +188,5 @@
     <Compile Include="Interfaces\Regression\IConfidenceRegressionModel.cs" />
     <Compile Include="Interfaces\Regression\IConfidenceRegressionSolution.cs" />
+    <Compile Include="Interfaces\Regression\IExtendedConstraint.cs" />
     <Compile Include="Interfaces\Regression\IRegressionEnsembleModel.cs">
       <SubType>Code</SubType>
@@ -308,4 +309,8 @@
       <Private>False</Private>
     </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding\3.4\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.csproj">
+      <Project>{06D4A186-9319-48A0-BADE-A2058D462EEA}</Project>
+      <Name>HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
       <Project>{14AB8D24-25BC-400C-A846-4627AA945192}</Project>
Index: /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstrainedRegressionProblemData.cs
===================================================================
--- /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstrainedRegressionProblemData.cs	(revision 18212)
+++ /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstrainedRegressionProblemData.cs	(revision 18213)
@@ -34,4 +34,5 @@
   public class ShapeConstrainedRegressionProblemData : RegressionProblemData, IShapeConstrainedRegressionProblemData {
     protected const string ShapeConstraintsParameterName = "ShapeConstraints";
+    protected const string ExtendedConstraintsParameterName = "ExtendedConstraints";
 
     #region default data
@@ -97,6 +98,6 @@
       defaultTargetVariable = "y_noise";
       defaultShapeConstraints = new ShapeConstraints {
-        new ShapeConstraint(new Interval(0, 2), 1.0),
-        new ShapeConstraint("x", 1, new Interval(0, double.PositiveInfinity), 1.0)
+        new ShapeConstraint(new Interval(0, 2), 1.0, new Interval(0,0)),
+        new ShapeConstraint("x", 1, new Interval(0, double.PositiveInfinity), 1.0, new Interval(0,0))
       };
       defaultVariableRanges = defaultDataset.GetVariableRanges();
@@ -116,4 +117,5 @@
       problemData.Parameters.Add(new FixedValueParameter<IntervalCollection>(VariableRangesParameterName, "", new IntervalCollection()));
       problemData.Parameters.Add(new FixedValueParameter<ShapeConstraints>(ShapeConstraintsParameterName, "", new ShapeConstraints()));
+      problemData.Parameters.Add(new FixedValueParameter<CheckedItemList<IExtendedConstraint>>(ExtendedConstraintsParameterName, "", new CheckedItemList<IExtendedConstraint>()));
       emptyProblemData = problemData;
     }
@@ -122,4 +124,9 @@
     public IFixedValueParameter<ShapeConstraints> ShapeConstraintParameter => (IFixedValueParameter<ShapeConstraints>)Parameters[ShapeConstraintsParameterName];
     public ShapeConstraints ShapeConstraints => ShapeConstraintParameter.Value;
+
+    public IFixedValueParameter<CheckedItemList<IExtendedConstraint>> ExtendedConstraintsParameter =>
+      (IFixedValueParameter<CheckedItemList<IExtendedConstraint>>)Parameters[ExtendedConstraintsParameterName];
+    public CheckedItemList<IExtendedConstraint> ExtendedConstraints => ExtendedConstraintsParameter.Value; 
+    public IEnumerable<IExtendedConstraint> CheckedExtendedConstraints => ExtendedConstraints.CheckedItems.Select(x => x.Value);
 
     [StorableConstructor]
@@ -132,4 +139,7 @@
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
+      if (!Parameters.ContainsKey(ExtendedConstraintsParameterName))
+        Parameters.Add(new FixedValueParameter<CheckedItemList<IExtendedConstraint>>(ExtendedConstraintsParameterName, "", new CheckedItemList<IExtendedConstraint>()));
+
       RegisterEventHandlers();
     }
@@ -158,4 +168,5 @@
       if (sc == null) sc = new ShapeConstraints();
       Parameters.Add(new FixedValueParameter<ShapeConstraints>(ShapeConstraintsParameterName, "Specifies the shape constraints for the regression problem.", (ShapeConstraints)sc.Clone()));
+      Parameters.Add(new FixedValueParameter<CheckedItemList<IExtendedConstraint>>(ExtendedConstraintsParameterName, "", new CheckedItemList<IExtendedConstraint>()));
       RegisterEventHandlers();
     }
@@ -169,4 +180,11 @@
       ShapeConstraints.ItemsMoved += ShapeConstraints_Changed;
       ShapeConstraints.ItemsReplaced += ShapeConstraints_Changed;
+
+      ExtendedConstraints.CheckedItemsChanged += ShapeConstraints_Changed;
+      ExtendedConstraints.CollectionReset += ShapeConstraints_Changed;
+      ExtendedConstraints.ItemsAdded += ShapeConstraints_Changed;
+      ExtendedConstraints.ItemsRemoved += ShapeConstraints_Changed;
+      ExtendedConstraints.ItemsMoved += ShapeConstraints_Changed;
+      ExtendedConstraints.ItemsReplaced += ShapeConstraints_Changed;
     }
 
Index: /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstraint.cs
===================================================================
--- /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstraint.cs	(revision 18212)
+++ /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstraint.cs	(revision 18213)
@@ -106,4 +106,17 @@
     }
 
+    [Storable]
+    private Interval threshold = new Interval(0, 0);
+    public Interval Threshold {
+      get => threshold;
+      set {
+        if (threshold == value)
+          return;
+        threshold = value;
+        OnToStringChanged();
+        OnChanged();
+      }
+    }
+
     [StorableConstructor]
     private ShapeConstraint(StorableConstructorFlag _) : base(_) { }
@@ -115,19 +128,19 @@
 
     // without derivation
-    public ShapeConstraint(Interval interval, double weight)
+    public ShapeConstraint(Interval interval, double weight, Interval threshold)
       : this(string.Empty, 0,
-         interval, new IntervalCollection(), weight) { }
-
-    public ShapeConstraint(Interval interval, IntervalCollection regions, double weight)
+         interval, new IntervalCollection(), weight, threshold) { }
+
+    public ShapeConstraint(Interval interval, IntervalCollection regions, double weight, Interval threshold)
       : this(string.Empty, 0,
-         interval, regions, weight) { }
+         interval, regions, weight, threshold) { }
 
     public ShapeConstraint(string variable, int numberOfDerivations,
-                              Interval interval, double weight)
+                              Interval interval, double weight, Interval threshold)
       : this(variable, numberOfDerivations,
-             interval, new IntervalCollection(), weight) { }
+             interval, new IntervalCollection(), weight, threshold) { }
 
     public ShapeConstraint(string variable, int numberOfDerivations,
-                              Interval interval, IntervalCollection regions, double weight) {
+                              Interval interval, IntervalCollection regions, double weight, Interval threshold) {
       Variable = variable;
       NumberOfDerivations = numberOfDerivations;
@@ -135,4 +148,5 @@
       Regions = regions;
       Weight = weight;
+      Threshold = threshold;
     }
 
@@ -148,4 +162,5 @@
       Regions = cloner.Clone(original.Regions);
       Weight = original.weight;
+      Threshold = original.threshold;
     }
 
@@ -175,32 +190,27 @@
       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)}]";
+      } else { 
+        var derivationString = string.Empty;
+        switch (numberOfDerivations) {
+          case 1:
+            derivationString = ""; break;
+          case 2:
+            derivationString = "²"; break;
+          case 3:
+            derivationString = "³"; break;
         }
-        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) {
+        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) {
+
+      if (Weight != 1.0)
         expression += $" weight: {weight}";
-      }
+
+      if (Threshold.LowerBound != 0 || Threshold.UpperBound != 0)
+        expression += $" threshold in [{write(Threshold.LowerBound)} .. {write(Threshold.UpperBound)}]";
+
       return expression;
     }
Index: /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstraintsParser.cs
===================================================================
--- /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstraintsParser.cs	(revision 18212)
+++ /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstraintsParser.cs	(revision 18213)
@@ -75,4 +75,5 @@
     private const string variableRegex = @"(['](?<varName>.*)[']|(?<varName>[^\s²³]+))\s*";
     private const string weightRegex = @"\s*(weight:\s*(?<weight>\S*))?";
+    private const string thresholdRegex = @"\s*(threshold\s*in\s*(?<threshold> " + intervalRegex + @"))?";
     public static ShapeConstraint ParseFunctionRangeConstraint(string expr) {
       if (!expr.StartsWith("f")) throw new ArgumentException($"Invalid function range constraint {expr} (e.g. f in [1..2])");
@@ -89,5 +90,5 @@
       // 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
+      // df / d'x' in [0..10], 'x' in [1 .. 3], y in [10..30] weight: 1.2 threshold in [-10 .. 10]
 
       var match = Regex.Match(targetConstraint,
@@ -99,5 +100,6 @@
                       intervalRegex +
                     @")*" +
-                    weightRegex
+                    weightRegex +
+                    thresholdRegex
                     );
 
@@ -110,7 +112,18 @@
         var interval = new Interval(lowerBound, upperBound);
         var weight = 1.0;
+        var threshold = new Interval(0, 0);
+        int intervalIdx = 1;
+        var lowerboundCount = match.Groups["lowerBound"].Captures.Count;
+        var upperboundCount = match.Groups["upperBound"].Captures.Count;
 
         if (match.Groups["weight"].Success && !string.IsNullOrWhiteSpace(match.Groups["weight"].Value))
           weight = ParseAndValidateDouble(match.Groups["weight"].Value);
+
+        if (match.Groups["threshold"].Success) {
+          var thresholdLb = ParseIntervalBounds(match.Groups["lowerBound"].Captures[lowerboundCount - intervalIdx].Value);
+          var thresholdUb = ParseIntervalBounds(match.Groups["upperBound"].Captures[lowerboundCount - intervalIdx].Value);
+          intervalIdx++;
+          threshold = new Interval(thresholdLb, thresholdUb);
+        }
 
         if (match.Groups["varName"].Success) {
@@ -127,7 +140,7 @@
               throw new ArgumentException($"The constraint {expr} has multiple regions of the same variable.");
           }
-          return new ShapeConstraint(interval, regions, weight);
+          return new ShapeConstraint(interval, regions, weight, threshold);
         } else
-          return new ShapeConstraint(interval, weight);
+          return new ShapeConstraint(interval, weight, threshold);
       } else
         throw new ArgumentException($"The target constraint {expr} is not valid.");
@@ -148,5 +161,6 @@
                                   intervalRegex +
                                   @")*" +
-                                weightRegex
+                                weightRegex +
+                                thresholdRegex
                                 );
 
@@ -172,7 +186,18 @@
         var interval = new Interval(lowerBound, upperBound);
         var weight = 1.0;
+        var threshold = new Interval(0, 0);
+        int intervalIdx = 1;
+        var lowerboundCount = match.Groups["lowerBound"].Captures.Count;
+        var upperboundCount = match.Groups["upperBound"].Captures.Count;
 
         if (match.Groups["weight"].Success && !string.IsNullOrWhiteSpace(match.Groups["weight"].Value))
           weight = ParseAndValidateDouble(match.Groups["weight"].Value);
+
+        if (match.Groups["threshold"].Success) {
+          var thresholdLb = ParseIntervalBounds(match.Groups["lowerBound"].Captures[lowerboundCount - intervalIdx].Value);
+          var thresholdUb = ParseIntervalBounds(match.Groups["upperBound"].Captures[lowerboundCount - intervalIdx].Value);
+          intervalIdx++;
+          threshold = new Interval(thresholdLb, thresholdUb);
+        }
 
         if (match.Groups["varName"].Captures.Count > 1) {
@@ -189,7 +214,7 @@
               throw new ArgumentException($"The constraint {expr} has multiple regions of the same variable.");
           }
-          return new ShapeConstraint(variable, numberOfDerivation, interval, regions, weight);
+          return new ShapeConstraint(variable, numberOfDerivation, interval, regions, weight, threshold);
         } else
-          return new ShapeConstraint(variable, numberOfDerivation, interval, weight);
+          return new ShapeConstraint(variable, numberOfDerivation, interval, weight, threshold);
       } else
         throw new ArgumentException($"The derivation constraint {expr} is not valid.");
Index: /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IExtendedConstraint.cs
===================================================================
--- /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IExtendedConstraint.cs	(revision 18213)
+++ /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IExtendedConstraint.cs	(revision 18213)
@@ -0,0 +1,17 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HEAL.Attic;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableType("FCF2341A-DE9C-48D7-8313-C6A1BAD675DF")]
+  public interface IExtendedConstraint : IItem {
+    string Expression { get; }
+    ISymbolicExpressionTree Tree { get; }
+    ShapeConstraints ShapeConstraints { get; }
+  }
+}
Index: /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IShapeConstrainedRegressionProblemData.cs
===================================================================
--- /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IShapeConstrainedRegressionProblemData.cs	(revision 18212)
+++ /branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IShapeConstrainedRegressionProblemData.cs	(revision 18213)
@@ -20,4 +20,5 @@
 #endregion
 
+using System.Collections.Generic;
 using HEAL.Attic;
 
@@ -26,4 +27,5 @@
   public interface IShapeConstrainedRegressionProblemData : IRegressionProblemData {
     ShapeConstraints ShapeConstraints { get; }
+    IEnumerable<IExtendedConstraint> CheckedExtendedConstraints { get; }
   }
 }
