Changeset 17891 for branches/3073_IA_constraint_splitting_reintegration/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithBoundsEstimator.cs
- Timestamp:
- 03/12/21 16:41:42 (3 years ago)
- 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 1 1 bin 2 TestResults
-
- Property svn:ignore
-
branches/3073_IA_constraint_splitting_reintegration/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithBoundsEstimator.cs
r17890 r17891 12 12 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 13 13 [StorableType("C8539434-6FB0-47D0-9F5A-2CAE5D8B8B4F")] 14 [Item("I ABounds Estimator", "Interpreter for calculation of intervals of symbolic models.")]15 public sealed class I ABoundsEstimator : ParameterizedNamedItem, IBoundsEstimator {14 [Item("Interval Arithmetic Bounds Estimator", "Interpreter for calculation of intervals of symbolic models.")] 15 public sealed class IntervalArithBoundsEstimator : ParameterizedNamedItem, IBoundsEstimator { 16 16 #region Parameters 17 17 18 18 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";22 19 23 20 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]; 34 22 35 23 public int EvaluatedSolutions { … … 37 25 set => EvaluatedSolutionsParameter.Value.Value = value; 38 26 } 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 55 27 #endregion 56 28 … … 58 30 59 31 [StorableConstructor] 60 private I ABoundsEstimator(StorableConstructorFlag _) : base(_) { }61 62 private I ABoundsEstimator(IABoundsEstimator original, Cloner cloner) : base(original, cloner) { }63 64 public I ABoundsEstimator() : 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", 65 37 "Estimates the bounds of the model with interval arithmetic") { 66 38 Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, 67 39 "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)));74 40 } 75 41 76 42 public override IDeepCloneable Clone(Cloner cloner) { 77 return new I ABoundsEstimator(this, cloner);43 return new IntervalArithBoundsEstimator(this, cloner); 78 44 } 79 45 … … 98 64 IDictionary<string, Interval> variableRanges) { 99 65 if (variableRanges == null) 100 throw new ArgumentNullException("No variable wranges are present!", nameof(variableRanges));101 102 // Check if all variables used in the tree are present in the dataset66 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 103 69 foreach (var variable in tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(n => n.VariableName) 104 70 .Distinct()) … … 108 74 var code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode); 109 75 foreach (var instr in code.Where(i => i.opCode == OpCodes.Variable)) { 110 var variableTreeNode = (VariableTreeNode) 76 var variableTreeNode = (VariableTreeNode)instr.dynamicNode; 111 77 instr.data = variableRanges[variableTreeNode.VariableName]; 112 78 } … … 115 81 } 116 82 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 117 85 public static Interval Evaluate( 118 86 Instruction[] instructions, ref int instructionCounter, … … 120 88 IDictionary<string, Interval> variableIntervals = null) { 121 89 var currentInstr = instructions[instructionCounter]; 122 //Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side123 //Update instructionCounter, whenever Evaluate is called124 90 instructionCounter++; 125 Interval result = null;91 Interval result; 126 92 127 93 switch (currentInstr.opCode) { 128 //Variables, Constants, ...129 94 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 else137 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 } 142 107 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 } 148 112 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 } 157 121 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 } 169 133 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 } 178 142 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 } 191 154 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 } 196 159 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 } 201 164 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 } 206 169 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 } 212 174 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 } 217 179 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 } 222 184 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 } 227 189 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 } 232 194 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 } 237 199 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 } 242 204 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 } 247 209 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 } 256 218 default: 257 219 throw new NotSupportedException( … … 277 239 } 278 240 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 439 243 public Interval GetModelBound(ISymbolicExpressionTree tree, IntervalCollection variableRanges) { 440 244 lock (syncRoot) { … … 445 249 var instructions = PrepareInterpreterState(tree, occuringVariableRanges); 446 250 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); 455 253 456 254 // because of numerical errors the bounds might be incorrect … … 466 264 } 467 265 468 public double CheckConstraint(266 public double GetConstraintViolation( 469 267 ISymbolicExpressionTree tree, IntervalCollection variableRanges, ShapeConstraint constraint) { 470 268 var occuringVariableRanges = GetOccurringVariableRanges(tree, variableRanges); 471 269 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; 532 286 } 533 287
Note: See TracChangeset
for help on using the changeset viewer.