Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
03/12/21 16:41:42 (3 years ago)
Author:
gkronber
Message:

#3073 refactoring to prepare for trunk reintegration

Location:
branches/3073_IA_constraint_splitting_reintegration
Files:
1 edited
1 moved

Legend:

Unmodified
Added
Removed
  • branches/3073_IA_constraint_splitting_reintegration

    • Property svn:ignore
      •  

        old new  
        11bin
         2TestResults
  • branches/3073_IA_constraint_splitting_reintegration/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithBoundsEstimator.cs

    r17890 r17891  
    1212namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
    1313  [StorableType("C8539434-6FB0-47D0-9F5A-2CAE5D8B8B4F")]
    14   [Item("IA Bounds Estimator", "Interpreter for calculation of intervals of symbolic models.")]
    15   public sealed class IABoundsEstimator : ParameterizedNamedItem, IBoundsEstimator {
     14  [Item("Interval Arithmetic Bounds Estimator", "Interpreter for calculation of intervals of symbolic models.")]
     15  public sealed class IntervalArithBoundsEstimator : ParameterizedNamedItem, IBoundsEstimator {
    1616    #region Parameters
    1717
    1818    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
    19     private const string UseIntervalSplittingParameterName = "Use Interval splitting";
    20     private const string SplittingIterationsParameterName = "Splitting Iterations";
    21     private const string SplittingWidthParameterName = "Splitting width";
    2219
    2320    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter =>
    24       (IFixedValueParameter<IntValue>) Parameters[EvaluatedSolutionsParameterName];
    25 
    26     public IFixedValueParameter<BoolValue> UseIntervalSplittingParameter =>
    27       (IFixedValueParameter<BoolValue>) Parameters[UseIntervalSplittingParameterName];
    28 
    29     public IFixedValueParameter<IntValue> SplittingIterationsParameter =>
    30       (IFixedValueParameter<IntValue>) Parameters[SplittingIterationsParameterName];
    31 
    32     public IFixedValueParameter<DoubleValue> SplittingWidthParameter =>
    33       (IFixedValueParameter<DoubleValue>) Parameters[SplittingWidthParameterName];
     21      (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
    3422
    3523    public int EvaluatedSolutions {
     
    3725      set => EvaluatedSolutionsParameter.Value.Value = value;
    3826    }
    39 
    40     public bool UseIntervalSplitting {
    41       get => UseIntervalSplittingParameter.Value.Value;
    42       set => UseIntervalSplittingParameter.Value.Value = value;
    43     }
    44 
    45     public int SplittingIterations {
    46       get => SplittingIterationsParameter.Value.Value;
    47       set => SplittingIterationsParameter.Value.Value = value;
    48     }
    49 
    50     public double SplittingWidth {
    51       get => SplittingWidthParameter.Value.Value;
    52       set => SplittingWidthParameter.Value.Value = value;
    53     }
    54 
    5527    #endregion
    5628
     
    5830
    5931    [StorableConstructor]
    60     private IABoundsEstimator(StorableConstructorFlag _) : base(_) { }
    61 
    62     private IABoundsEstimator(IABoundsEstimator original, Cloner cloner) : base(original, cloner) { }
    63 
    64     public IABoundsEstimator() : base("IA Bounds Estimator",
     32    private IntervalArithBoundsEstimator(StorableConstructorFlag _) : base(_) { }
     33
     34    private IntervalArithBoundsEstimator(IntervalArithBoundsEstimator original, Cloner cloner) : base(original, cloner) { }
     35
     36    public IntervalArithBoundsEstimator() : base("IA Bounds Estimator",
    6537      "Estimates the bounds of the model with interval arithmetic") {
    6638      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName,
    6739        "A counter for the total number of solutions the estimator has evaluated.", new IntValue(0)));
    68       Parameters.Add(new FixedValueParameter<BoolValue>(UseIntervalSplittingParameterName,
    69         "Defines whether interval splitting is activated or not.", new BoolValue(false)));
    70       Parameters.Add(new FixedValueParameter<IntValue>(SplittingIterationsParameterName,
    71         "Defines the number of iterations of splitting.", new IntValue(200)));
    72       Parameters.Add(new FixedValueParameter<DoubleValue>(SplittingWidthParameterName,
    73         "Width of interval, after the splitting should stop.", new DoubleValue(0.0)));
    7440    }
    7541
    7642    public override IDeepCloneable Clone(Cloner cloner) {
    77       return new IABoundsEstimator(this, cloner);
     43      return new IntervalArithBoundsEstimator(this, cloner);
    7844    }
    7945
     
    9864      IDictionary<string, Interval> variableRanges) {
    9965      if (variableRanges == null)
    100         throw new ArgumentNullException("No variablew ranges are present!", nameof(variableRanges));
    101 
    102       //Check if all variables used in the tree are present in the dataset
     66        throw new ArgumentNullException("No variable ranges are present!", nameof(variableRanges));
     67
     68      // Check if all variables used in the tree are present in the dataset
    10369      foreach (var variable in tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(n => n.VariableName)
    10470                                   .Distinct())
     
    10874      var code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
    10975      foreach (var instr in code.Where(i => i.opCode == OpCodes.Variable)) {
    110         var variableTreeNode = (VariableTreeNode) instr.dynamicNode;
     76        var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
    11177        instr.data = variableRanges[variableTreeNode.VariableName];
    11278      }
     
    11581    }
    11682
     83    // Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side
     84    // Update instructionCounter, whenever Evaluate is called
    11785    public static Interval Evaluate(
    11886      Instruction[] instructions, ref int instructionCounter,
     
    12088      IDictionary<string, Interval> variableIntervals = null) {
    12189      var currentInstr = instructions[instructionCounter];
    122       //Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side
    123       //Update instructionCounter, whenever Evaluate is called
    12490      instructionCounter++;
    125       Interval result = null;
     91      Interval result;
    12692
    12793      switch (currentInstr.opCode) {
    128         //Variables, Constants, ...
    12994        case OpCodes.Variable: {
    130           var variableTreeNode = (VariableTreeNode) currentInstr.dynamicNode;
    131           var weightInterval = new Interval(variableTreeNode.Weight, variableTreeNode.Weight);
    132 
    133           Interval variableInterval;
    134           if (variableIntervals != null && variableIntervals.ContainsKey(variableTreeNode.VariableName))
    135             variableInterval = variableIntervals[variableTreeNode.VariableName];
    136           else
    137             variableInterval = (Interval) currentInstr.data;
    138 
    139           result = Interval.Multiply(variableInterval, weightInterval);
    140           break;
    141         }
     95            var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode;
     96            var weightInterval = new Interval(variableTreeNode.Weight, variableTreeNode.Weight);
     97
     98            Interval variableInterval;
     99            if (variableIntervals != null && variableIntervals.ContainsKey(variableTreeNode.VariableName))
     100              variableInterval = variableIntervals[variableTreeNode.VariableName];
     101            else
     102              variableInterval = (Interval)currentInstr.data;
     103
     104            result = Interval.Multiply(variableInterval, weightInterval);
     105            break;
     106          }
    142107        case OpCodes.Constant: {
    143           var constTreeNode = (ConstantTreeNode) currentInstr.dynamicNode;
    144           result = new Interval(constTreeNode.Value, constTreeNode.Value);
    145           break;
    146         }
    147         //Elementary arithmetic rules
     108            var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode;
     109            result = new Interval(constTreeNode.Value, constTreeNode.Value);
     110            break;
     111          }
    148112        case OpCodes.Add: {
    149           result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    150           for (var i = 1; i < currentInstr.nArguments; i++) {
    151             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    152             result = Interval.Add(result, argumentInterval);
    153           }
    154 
    155           break;
    156         }
     113            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     114            for (var i = 1; i < currentInstr.nArguments; i++) {
     115              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     116              result = Interval.Add(result, argumentInterval);
     117            }
     118
     119            break;
     120          }
    157121        case OpCodes.Sub: {
    158           result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    159           if (currentInstr.nArguments == 1)
    160             result = Interval.Multiply(new Interval(-1, -1), result);
    161 
    162           for (var i = 1; i < currentInstr.nArguments; i++) {
    163             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    164             result = Interval.Subtract(result, argumentInterval);
    165           }
    166 
    167           break;
    168         }
     122            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     123            if (currentInstr.nArguments == 1)
     124              result = Interval.Multiply(new Interval(-1, -1), result);
     125
     126            for (var i = 1; i < currentInstr.nArguments; i++) {
     127              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     128              result = Interval.Subtract(result, argumentInterval);
     129            }
     130
     131            break;
     132          }
    169133        case OpCodes.Mul: {
    170           result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    171           for (var i = 1; i < currentInstr.nArguments; i++) {
    172             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    173             result = Interval.Multiply(result, argumentInterval);
    174           }
    175 
    176           break;
    177         }
     134            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     135            for (var i = 1; i < currentInstr.nArguments; i++) {
     136              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     137              result = Interval.Multiply(result, argumentInterval);
     138            }
     139
     140            break;
     141          }
    178142        case OpCodes.Div: {
    179           result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    180           if (currentInstr.nArguments == 1)
    181             result = Interval.Divide(new Interval(1, 1), result);
    182 
    183           for (var i = 1; i < currentInstr.nArguments; i++) {
    184             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    185             result = Interval.Divide(result, argumentInterval);
    186           }
    187 
    188           break;
    189         }
    190         //Trigonometric functions
     143            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     144            if (currentInstr.nArguments == 1)
     145              result = Interval.Divide(new Interval(1, 1), result);
     146
     147            for (var i = 1; i < currentInstr.nArguments; i++) {
     148              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     149              result = Interval.Divide(result, argumentInterval);
     150            }
     151
     152            break;
     153          }
    191154        case OpCodes.Sin: {
    192           var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    193           result = Interval.Sine(argumentInterval);
    194           break;
    195         }
     155            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     156            result = Interval.Sine(argumentInterval);
     157            break;
     158          }
    196159        case OpCodes.Cos: {
    197           var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    198           result = Interval.Cosine(argumentInterval);
    199           break;
    200         }
     160            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     161            result = Interval.Cosine(argumentInterval);
     162            break;
     163          }
    201164        case OpCodes.Tan: {
    202           var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    203           result = Interval.Tangens(argumentInterval);
    204           break;
    205         }
     165            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     166            result = Interval.Tangens(argumentInterval);
     167            break;
     168          }
    206169        case OpCodes.Tanh: {
    207           var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    208           result = Interval.HyperbolicTangent(argumentInterval);
    209           break;
    210         }
    211         //Exponential functions
     170            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     171            result = Interval.HyperbolicTangent(argumentInterval);
     172            break;
     173          }
    212174        case OpCodes.Log: {
    213           var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    214           result = Interval.Logarithm(argumentInterval);
    215           break;
    216         }
     175            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     176            result = Interval.Logarithm(argumentInterval);
     177            break;
     178          }
    217179        case OpCodes.Exp: {
    218           var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    219           result = Interval.Exponential(argumentInterval);
    220           break;
    221         }
     180            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     181            result = Interval.Exponential(argumentInterval);
     182            break;
     183          }
    222184        case OpCodes.Square: {
    223           var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    224           result = Interval.Square(argumentInterval);
    225           break;
    226         }
     185            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     186            result = Interval.Square(argumentInterval);
     187            break;
     188          }
    227189        case OpCodes.SquareRoot: {
    228           var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    229           result = Interval.SquareRoot(argumentInterval);
    230           break;
    231         }
     190            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     191            result = Interval.SquareRoot(argumentInterval);
     192            break;
     193          }
    232194        case OpCodes.Cube: {
    233           var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    234           result = Interval.Cube(argumentInterval);
    235           break;
    236         }
     195            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     196            result = Interval.Cube(argumentInterval);
     197            break;
     198          }
    237199        case OpCodes.CubeRoot: {
    238           var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    239           result = Interval.CubicRoot(argumentInterval);
    240           break;
    241         }
     200            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     201            result = Interval.CubicRoot(argumentInterval);
     202            break;
     203          }
    242204        case OpCodes.Absolute: {
    243           var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    244           result = Interval.Absolute(argumentInterval);
    245           break;
    246         }
     205            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     206            result = Interval.Absolute(argumentInterval);
     207            break;
     208          }
    247209        case OpCodes.AnalyticQuotient: {
    248           result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    249           for (var i = 1; i < currentInstr.nArguments; i++) {
    250             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    251             result = Interval.AnalyticalQuotient(result, argumentInterval);
    252           }
    253 
    254           break;
    255         }
     210            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     211            for (var i = 1; i < currentInstr.nArguments; i++) {
     212              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     213              result = Interval.AnalyticalQuotient(result, argumentInterval);
     214            }
     215
     216            break;
     217          }
    256218        default:
    257219          throw new NotSupportedException(
     
    277239    }
    278240
    279     private static bool ContainsVariableMultipleTimes(ISymbolicExpressionTree tree, out List<String> variables) {
    280       variables = new List<string>();
    281       var varlist = tree.IterateNodesPrefix().OfType<VariableTreeNode>().GroupBy(x => x.VariableName);
    282       foreach (var group in varlist) {
    283         if (group.Count() > 1) {
    284           variables.Add(group.Key);
    285         }
    286       }
    287 
    288       return varlist.Any(group => group.Count() > 1);
    289     }
    290 
    291     // a multi-dimensional box with an associated bound
    292     // boxbounds are ordered first by bound (smaller first), then by size of box (larger first) then by distance of bottom left corner to origin
    293     private class BoxBound : IComparable<BoxBound> {
    294       public List<Interval> box;
    295       public double bound;
    296 
    297       public BoxBound(IEnumerable<Interval> box, double bound) {
    298         this.box = new List<Interval>(box);
    299         this.bound = bound;
    300       }
    301 
    302       public int CompareTo(BoxBound other) {
    303         if (bound != other.bound) return bound.CompareTo(other.bound);
    304 
    305         var thisSize = box.Aggregate(1.0, (current, dimExtent) => current * dimExtent.Width);
    306         var otherSize = other.box.Aggregate(1.0, (current, dimExtent) => current * dimExtent.Width);
    307         if (thisSize != otherSize) return -thisSize.CompareTo(otherSize);
    308 
    309         var thisDist = box.Sum(dimExtent => dimExtent.LowerBound * dimExtent.LowerBound);
    310         var otherDist = other.box.Sum(dimExtent => dimExtent.LowerBound * dimExtent.LowerBound);
    311         if (thisDist != otherDist) return thisDist.CompareTo(otherDist);
    312 
    313         // which is smaller first along the dimensions?
    314         for (int i = 0; i < box.Count; i++) {
    315           if (box[i].LowerBound != other.box[i].LowerBound) return box[i].LowerBound.CompareTo(other.box[i].LowerBound);
    316         }
    317 
    318         return 0;
    319       }
    320     }
    321 
    322     #endregion
    323 
    324     #region Splitting
    325 
    326     public static Interval EvaluateWithSplitting(Instruction[] instructions,
    327                                                  IDictionary<string, Interval> variableIntervals,
    328                                                  List<string> multipleOccurenceVariables, int splittingIterations,
    329                                                  double splittingWidth,
    330                                                  IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals =
    331                                                    null) {
    332       var min = FindBound(instructions, variableIntervals.ToDictionary(entry => entry.Key, entry => entry.Value),
    333         multipleOccurenceVariables, splittingIterations, splittingWidth, nodeIntervals,
    334         minimization: true);
    335       var max = FindBound(instructions, variableIntervals.ToDictionary(entry => entry.Key, entry => entry.Value),
    336         multipleOccurenceVariables, splittingIterations, splittingWidth, nodeIntervals,
    337         minimization: false);
    338 
    339       return new Interval(min, max);
    340     }
    341 
    342     private static double FindBound(Instruction[] instructions,
    343                                     IDictionary<string, Interval> variableIntervals,
    344                                     List<string> multipleOccurenceVariables, int splittingIterations,
    345                                     double splittingWidth,
    346                                     IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null,
    347                                     bool minimization = true, bool stopAtLimit = false, double limit = 0) {
    348       SortedSet<BoxBound> prioQ = new SortedSet<BoxBound>();
    349       var ic = 0;
    350       var stop = false;
    351       //Calculate full box
    352       var interval = Evaluate(instructions, ref ic, nodeIntervals, variableIntervals: variableIntervals);
    353       // the order of keys in a dictionary is guaranteed to be the same order as values in a dictionary
    354       // https://docs.microsoft.com/en-us/dotnet/api/system.collections.idictionary.keys?view=netcore-3.1#remarks
    355       //var box = variableIntervals.Values;
    356       //Box only contains intervals from multiple occurence variables
    357       var box = multipleOccurenceVariables.Select(k => variableIntervals[k]);
    358       if (minimization) {
    359         prioQ.Add(new BoxBound(box, interval.LowerBound));
    360         if (stopAtLimit && interval.LowerBound >= limit) stop = true;
    361       } else {
    362         prioQ.Add(new BoxBound(box, -interval.UpperBound));
    363         if (stopAtLimit && interval.UpperBound <= limit) stop = true;
    364       }
    365 
    366       var discardedBound = double.MaxValue;
    367       var runningBound = double.MaxValue;
    368       for (var depth = 0; depth < splittingIterations && prioQ.Count > 0 && !stop; ++depth) {
    369         var currentBound = prioQ.Min;
    370         prioQ.Remove(currentBound);
    371 
    372         if (currentBound.box.All(x => x.Width < splittingWidth)) {
    373           discardedBound = Math.Min(discardedBound, currentBound.bound);
    374           continue;
    375         }
    376 
    377         var newBoxes = Split(currentBound.box, splittingWidth);
    378 
    379         var innerBound = double.MaxValue;
    380         foreach (var newBox in newBoxes) {
    381           //var intervalEnum = newBox.GetEnumerator();
    382           //var keyEnum = readonlyRanges.Keys.GetEnumerator();
    383           //while (intervalEnum.MoveNext() & keyEnum.MoveNext()) {
    384           //  variableIntervals[keyEnum.Current] = intervalEnum.Current;
    385           //}
    386           //Set the splitted variables
    387           var intervalEnum = newBox.GetEnumerator();
    388           foreach (var key in multipleOccurenceVariables) {
    389             intervalEnum.MoveNext();
    390             variableIntervals[key] = intervalEnum.Current;
    391           }
    392 
    393           ic = 0;
    394           var res = Evaluate(instructions, ref ic, nodeIntervals,
    395             new ReadOnlyDictionary<string, Interval>(variableIntervals));
    396 
    397           var boxBound = new BoxBound(newBox, minimization ? res.LowerBound : -res.UpperBound);
    398           prioQ.Add(boxBound);
    399           innerBound = Math.Min(innerBound, boxBound.bound);
    400         }
    401 
    402         runningBound = innerBound;
    403 
    404         if (minimization) {
    405           if (stopAtLimit && innerBound >= limit)
    406             stop = true;
    407         } else {
    408           if (stopAtLimit && innerBound <= limit)
    409             stop = true;
    410         }
    411       }
    412 
    413       var bound = Math.Min(runningBound, discardedBound);
    414       if (bound == double.MaxValue)
    415         return minimization ? interval.LowerBound : interval.UpperBound;
    416 
    417       return minimization ? bound : -bound;
    418       //return minimization ? prioQ.First().bound : -prioQ.First().bound;
    419     }
    420 
    421     private static IEnumerable<IEnumerable<Interval>> Split(List<Interval> box) {
    422       var boxes = box.Select(region => region.Split())
    423                      .Select(split => new List<Interval> {split.Item1, split.Item2})
    424                      .ToList();
    425 
    426       return boxes.CartesianProduct();
    427     }
    428 
    429     private static IEnumerable<IEnumerable<Interval>> Split(List<Interval> box, double minWidth) {
    430       List<Interval> toList(Tuple<Interval, Interval> t) => new List<Interval> {t.Item1, t.Item2};
    431       var boxes = box.Select(region => region.Width > minWidth ? toList(region.Split()) : new List<Interval> {region})
    432                      .ToList();
    433 
    434       return boxes.CartesianProduct();
    435     }
    436 
    437     #endregion
    438 
     241    #endregion
     242 
    439243    public Interval GetModelBound(ISymbolicExpressionTree tree, IntervalCollection variableRanges) {
    440244      lock (syncRoot) {
     
    445249      var instructions = PrepareInterpreterState(tree, occuringVariableRanges);
    446250      Interval resultInterval;
    447       if (!UseIntervalSplitting) {
    448         var instructionCounter = 0;
    449         resultInterval = Evaluate(instructions, ref instructionCounter, variableIntervals: occuringVariableRanges);
    450       } else {
    451         var vars = ContainsVariableMultipleTimes(tree, out var variables);
    452         resultInterval = EvaluateWithSplitting(instructions, occuringVariableRanges, variables, SplittingIterations,
    453           SplittingWidth);
    454       }
     251      var instructionCounter = 0;
     252      resultInterval = Evaluate(instructions, ref instructionCounter, variableIntervals: occuringVariableRanges);
    455253
    456254      // because of numerical errors the bounds might be incorrect
     
    466264    }
    467265
    468     public double CheckConstraint(
     266    public double GetConstraintViolation(
    469267      ISymbolicExpressionTree tree, IntervalCollection variableRanges, ShapeConstraint constraint) {
    470268      var occuringVariableRanges = GetOccurringVariableRanges(tree, variableRanges);
    471269      var instructions = PrepareInterpreterState(tree, occuringVariableRanges);
    472       if (!UseIntervalSplitting) {
    473         var instructionCounter = 0;
    474         var modelBound = Evaluate(instructions, ref instructionCounter, variableIntervals: occuringVariableRanges);
    475         if (constraint.Interval.Contains(modelBound)) return 0.0;
    476 
    477 
    478         var error = 0.0;
    479 
    480         if (!constraint.Interval.Contains(modelBound.LowerBound)) {
    481             error += Math.Abs(modelBound.LowerBound - constraint.Interval.LowerBound);
    482         }
    483 
    484         if (!constraint.Interval.Contains(modelBound.UpperBound)) {
    485             error += Math.Abs(modelBound.UpperBound - constraint.Interval.UpperBound);
    486         }
    487 
    488         return error;
    489         // return Math.Abs(modelBound.LowerBound - constraint.Interval.LowerBound) +
    490         //Math.Abs(modelBound.UpperBound - constraint.Interval.UpperBound);
    491       }
    492 
    493       if (double.IsNegativeInfinity(constraint.Interval.LowerBound) &&
    494           double.IsPositiveInfinity(constraint.Interval.UpperBound)) {
    495         return 0.0;
    496       }
    497 
    498       ContainsVariableMultipleTimes(tree, out var variables);
    499 
    500       var upperBound = 0.0;
    501       var lowerBound = 0.0;
    502       if (double.IsNegativeInfinity(constraint.Interval.LowerBound)) {
    503         upperBound = FindBound(instructions, occuringVariableRanges, variables, SplittingIterations, SplittingWidth,
    504           minimization: false, stopAtLimit: true, limit: constraint.Interval.UpperBound);
    505 
    506         return upperBound <= constraint.Interval.UpperBound
    507           ? 0.0
    508           : Math.Abs(upperBound - constraint.Interval.UpperBound);
    509       }
    510 
    511       if (double.IsPositiveInfinity(constraint.Interval.UpperBound)) {
    512         lowerBound = FindBound(instructions, occuringVariableRanges, variables, SplittingIterations, SplittingWidth,
    513           minimization: true, stopAtLimit: true, limit: constraint.Interval.LowerBound);
    514 
    515         return lowerBound >= constraint.Interval.LowerBound
    516           ? 0.0
    517           : Math.Abs(lowerBound - constraint.Interval.LowerBound);
    518       }
    519 
    520       upperBound = FindBound(instructions, occuringVariableRanges, variables, SplittingIterations, SplittingWidth,
    521         minimization: false, stopAtLimit: true, limit: constraint.Interval.UpperBound);
    522       lowerBound = FindBound(instructions, occuringVariableRanges, variables, SplittingIterations, SplittingWidth,
    523         minimization: true, stopAtLimit: true, limit: constraint.Interval.LowerBound);
    524 
    525 
    526       var res = 0.0;
    527 
    528       res += upperBound <= constraint.Interval.UpperBound ? 0.0 : Math.Abs(upperBound - constraint.Interval.UpperBound);
    529       res += lowerBound <= constraint.Interval.LowerBound ? 0.0 : Math.Abs(lowerBound - constraint.Interval.LowerBound);
    530 
    531       return res;
     270      var instructionCounter = 0;
     271      var modelBound = Evaluate(instructions, ref instructionCounter, variableIntervals: occuringVariableRanges);
     272      if (constraint.Interval.Contains(modelBound)) return 0.0;
     273
     274
     275      var error = 0.0;
     276
     277      if (!constraint.Interval.Contains(modelBound.LowerBound)) {
     278        error += Math.Abs(modelBound.LowerBound - constraint.Interval.LowerBound);
     279      }
     280
     281      if (!constraint.Interval.Contains(modelBound.UpperBound)) {
     282        error += Math.Abs(modelBound.UpperBound - constraint.Interval.UpperBound);
     283      }
     284
     285      return error;
    532286    }
    533287
Note: See TracChangeset for help on using the changeset viewer.