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/IntervalArithCompiledExpressionBoundsEstimator.cs

    r17890 r17891  
    11using HEAL.Attic;
    2 
    32using HeuristicLab.Common;
    43using HeuristicLab.Core;
     
    65using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    76using HeuristicLab.Parameters;
    8 
    97using System;
    108using System.Collections.Generic;
     
    1210using System.Linq.Expressions;
    1311
    14 namespace HeuristicLab.Problems.DataAnalysis.Symbolic
    15 {
     12namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
    1613  [StorableType("60015D64-5D8B-408A-90A1-E4111BC114D4")]
    17   [Item("IA Compiled Expression Bounds Estimator", "Compile a symbolic model into a lambda and use it to evaluate model bounds.")]
    18   public class IACompiledExpressionBoundsEstimator : ParameterizedNamedItem, IBoundsEstimator
    19   {
     14  [Item("Interval Arithmetic Compiled Expression Bounds Estimator", "Compile a symbolic model into a lambda and use it to evaluate model bounds.")]
     15  public class IntervalArithCompiledExpressionBoundsEstimator : ParameterizedNamedItem, IBoundsEstimator {
    2016    // interval method names
    2117    private static readonly Dictionary<byte, string> methodName = new Dictionary<byte, string>() {
     
    3935
    4036    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
    41     private const string UseIntervalSplittingParameterName = "Use Interval splitting";
    42     private const string MaxSplitParameterName = "MaxSplit";
    43     private const string MinWidthParameterName = "MinWidth";
    44 
    4537    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
    4638      get => (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
    4739    }
    48 
    49     public IFixedValueParameter<BoolValue> UseIntervalSplittingParameter {
    50       get => (IFixedValueParameter<BoolValue>)Parameters[UseIntervalSplittingParameterName];
    51     }
    52 
    53     public IFixedValueParameter<IntValue> MaxSplitParameter {
    54       get => (IFixedValueParameter<IntValue>)Parameters[MaxSplitParameterName];
    55     }
    56 
    57     public IFixedValueParameter<DoubleValue> MinWidthParameter {
    58       get => (IFixedValueParameter<DoubleValue>)Parameters[MinWidthParameterName];
    59     }
    60 
    61     public int MaxSplit {
    62       get => MaxSplitParameter.Value.Value;
    63       set => MaxSplitParameter.Value.Value = value;
    64     }
    65 
    66     public double MinWidth {
    67       get => MinWidthParameter.Value.Value;
    68       set => MinWidthParameter.Value.Value = value;
    69     }
    70 
    7140    public int EvaluatedSolutions {
    7241      get => EvaluatedSolutionsParameter.Value.Value;
     
    7443    }
    7544
    76     public bool UseIntervalSplitting {
    77       get => UseIntervalSplittingParameter.Value.Value;
    78       set => UseIntervalSplittingParameter.Value.Value = value;
    79     }
    80 
    8145    private readonly object syncRoot = new object();
    8246
    83     public IACompiledExpressionBoundsEstimator() : base("IA Bounds Estimator",
     47    public IntervalArithCompiledExpressionBoundsEstimator() : base("Interval Arith Bounds Estimator",
    8448      "Estimates the bounds of the model with interval arithmetic, by first compiling the model into a lambda.") {
    8549      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName,
    8650        "A counter for the total number of solutions the estimator has evaluated.", new IntValue(0)));
    87       Parameters.Add(new FixedValueParameter<BoolValue>(UseIntervalSplittingParameterName,
    88         "Defines whether interval splitting is activated or not.", new BoolValue(false)));
    89       Parameters.Add(new FixedValueParameter<IntValue>(MaxSplitParameterName,
    90         "Defines the number of iterations of splitting.", new IntValue(200)));
    91       Parameters.Add(new FixedValueParameter<DoubleValue>(MinWidthParameterName,
    92         "Width of interval, after the splitting should stop.", new DoubleValue(0.0)));
    9351    }
    9452
    9553    [StorableConstructor]
    96     private IACompiledExpressionBoundsEstimator(StorableConstructorFlag _) : base(_) { }
    97 
    98     private IACompiledExpressionBoundsEstimator(IACompiledExpressionBoundsEstimator original, Cloner cloner) : base(original, cloner) { }
     54    private IntervalArithCompiledExpressionBoundsEstimator(StorableConstructorFlag _) : base(_) { }
     55
     56    private IntervalArithCompiledExpressionBoundsEstimator(IntervalArithCompiledExpressionBoundsEstimator original, Cloner cloner) : base(original, cloner) { }
    9957
    10058    public override IDeepCloneable Clone(Cloner cloner) {
    101       return new IACompiledExpressionBoundsEstimator(this, cloner);
    102     }
    103 
    104 
    105 
    106     public double CheckConstraint(ISymbolicExpressionTree tree, IntervalCollection variableRanges, ShapeConstraint constraint) {
    107       if (!UseIntervalSplitting) {
    108         var modelBound = GetModelBound(tree, variableRanges);
    109         if (constraint.Interval.Contains(modelBound)) return 0.0;
    110         return Math.Abs(modelBound.LowerBound - constraint.Interval.LowerBound) +
    111                Math.Abs(modelBound.UpperBound - constraint.Interval.UpperBound);
    112       }
    113 
    114       if (double.IsNegativeInfinity(constraint.Interval.LowerBound) &&
    115           double.IsPositiveInfinity(constraint.Interval.UpperBound)) {
    116         return 0.0;
    117       }
    118 
    119       //ContainsVariableMultipleTimes(tree, out var variables);
    120 
    121       lock (syncRoot) { EvaluatedSolutions++; }
    122 
    123       double upperBound;
    124       if (double.IsNegativeInfinity(constraint.Interval.LowerBound)) {
    125         upperBound = EstimateUpperBound(tree, variableRanges.GetReadonlyDictionary(), MaxSplit, MinWidth);
    126 
    127         return upperBound <= constraint.Interval.UpperBound
    128           ? 0.0
    129           : Math.Abs(upperBound - constraint.Interval.UpperBound);
    130       }
    131 
    132       double lowerBound;
    133       if (double.IsPositiveInfinity(constraint.Interval.UpperBound)) {
    134         lowerBound = EstimateLowerBound(tree, variableRanges.GetReadonlyDictionary(), MaxSplit, MinWidth);
    135 
    136         return lowerBound <= constraint.Interval.LowerBound
    137           ? 0.0
    138           : Math.Abs(lowerBound - constraint.Interval.LowerBound);
    139       }
    140 
    141       var ranges = variableRanges.GetReadonlyDictionary();
    142       lowerBound = EstimateLowerBound(tree, ranges, MaxSplit, MinWidth);
    143       upperBound = EstimateUpperBound(tree, ranges, MaxSplit, MinWidth);
    144 
    145       var res = 0.0;
    146 
    147       res += upperBound <= constraint.Interval.UpperBound ? 0.0 : Math.Abs(upperBound - constraint.Interval.UpperBound);
    148       res += lowerBound <= constraint.Interval.LowerBound ? 0.0 : Math.Abs(lowerBound - constraint.Interval.LowerBound);
    149 
    150       return res;
     59      return new IntervalArithCompiledExpressionBoundsEstimator(this, cloner);
     60    }
     61
     62    public double GetConstraintViolation(ISymbolicExpressionTree tree, IntervalCollection variableRanges, ShapeConstraint constraint) {
     63      var modelBound = GetModelBound(tree, variableRanges);
     64      if (constraint.Interval.Contains(modelBound)) return 0.0;
     65      return Math.Abs(modelBound.LowerBound - constraint.Interval.LowerBound) +
     66             Math.Abs(modelBound.UpperBound - constraint.Interval.UpperBound);
    15167    }
    15268
     
    15773    public Interval GetModelBound(ISymbolicExpressionTree tree, IntervalCollection variableRanges) {
    15874      lock (syncRoot) { EvaluatedSolutions++; }
    159       var resultInterval = UseIntervalSplitting
    160         ? EstimateBounds(tree, variableRanges.GetReadonlyDictionary(), MaxSplit, MinWidth)
    161         : EstimateBounds(tree, variableRanges.GetReadonlyDictionary());
     75      var resultInterval = EstimateBounds(tree, variableRanges.GetReadonlyDictionary());
    16276
    16377      if (resultInterval.IsInfiniteOrUndefined || resultInterval.LowerBound <= resultInterval.UpperBound)
     
    298212        }
    299213      }
    300       Array.Resize<Interval>(ref inputIntervals, count);
     214      Array.Resize(ref inputIntervals, count);
    301215      return variableIndices;
    302216    }
     
    309223    }
    310224
    311     public static Interval EstimateBounds(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges, int n = 0, double w = 1e-5) {
     225    public static Interval EstimateBounds(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges) {
    312226      var variableIndices = GetVariableIndices(tree, variableRanges, out Interval[] x);
    313227      var f = Compile(tree, variableRanges, variableIndices);
    314       if (n == 0) return f(x);
    315       var inf = EstimateBound(x, f, true, n, w);
    316       var sup = EstimateBound(x, f, false, n, w);
    317       return inf < sup ? new Interval(inf, sup) : new Interval(sup, inf);
    318     }
    319     public  double EstimateLowerBound(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges, int n = 1000, double w = 1e-5) {
    320       var variableIndices = GetVariableIndices(tree, variableRanges, out Interval[] x);
    321       var f = Compile(tree, variableRanges, variableIndices);
    322       var inf = EstimateBound(x, f, true, n, w);
    323       return inf;
    324     }
    325 
    326     public double EstimateUpperBound(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges, int n = 1000, double w = 1e-5) {
    327       var variableIndices = GetVariableIndices(tree, variableRanges, out Interval[] x);
    328       var f = Compile(tree, variableRanges, variableIndices);
    329       var sup = EstimateBound(x, f, false, n, w);
    330       return sup;
    331     }
    332 
    333     static double EstimateBound(Interval[] x, Func<Interval[], Interval> f, bool m = false, int n = 1000, double w = 1e-4) {
    334       double getBound(Interval iv) => m ? iv.LowerBound : -iv.UpperBound;
    335       double getVolume(Interval[] box) => box.Aggregate(1.0, (acc, iv) => acc * iv.Width);
    336 
    337       var splits = Enumerable.Range(0, x.Length).Select(_ => new List<Interval>()).ToArray();
    338       var newbox = new Interval[x.Length];
    339 
    340       int compare(Tuple<double, double, Interval[]> a, Tuple<double, double, Interval[]> b) {
    341         var res = a.Item1.CompareTo(b.Item1);
    342         if (res == 0) {
    343           res = b.Item2.CompareTo(a.Item2);
    344         }
    345         return res;
    346       }
    347 
    348       var q = new SortedSet<Tuple<double, double, Interval[]>>(Comparer<Tuple<double, double, Interval[]>>.Create(compare)) {
    349         Tuple.Create(getBound(f(x)), getVolume(x), x)
    350       };
    351 
    352 
    353       var bestBound = double.MaxValue;
    354 
    355       // examine all the ordered pairs in the cartesian product
    356       void next_pair(int i) {
    357         if (i == splits.Length) {
    358           var tmp = newbox.ToArray(); // make a copy to put in the queue
    359           q.Add(Tuple.Create(getBound(f(tmp)), getVolume(tmp), tmp));
    360           return;
    361         }
    362 
    363         foreach (var iv in splits[i]) {
    364           newbox[i] = iv;
    365           next_pair(i + 1);
    366         }
    367       }
    368 
    369       while (q.Count > 0 && n-- > 0) {
    370         var currentBound = q.Min; q.Remove(currentBound);
    371         var bound = currentBound.Item1;
    372         var box = currentBound.Item3;
    373 
    374         if (!box.Any(b => b.Width > w)) {
    375           bestBound = Math.Min(bestBound, bound);
    376           continue;
    377         }
    378 
    379         // do the splits
    380         for (int i = 0; i < box.Length; ++i) {
    381           splits[i].Clear();
    382           var iv = box[i];
    383           if (iv.Width > w) {
    384             var t = iv.Split();
    385             splits[i].Add(t.Item1);
    386             splits[i].Add(t.Item2);
    387           } else {
    388             splits[i].Add(iv);
    389           }
    390         }
    391         next_pair(0);
    392       }
    393       if (q.Count > 0) {
    394         bestBound = Math.Min(bestBound, q.First().Item1);
    395       }
    396       return m ? bestBound : -bestBound;
     228      return f(x);
    397229    }
    398230    #endregion
Note: See TracChangeset for help on using the changeset viewer.