Changeset 17203


Ignore:
Timestamp:
08/13/19 09:28:45 (10 days ago)
Author:
gkronber
Message:

#2994: re-wrote implementation of interval arithmetic for Sin()

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Interpreter.cs

    r17200 r17203  
    940940
    941941    public AlgebraicInterval AssignSin(AlgebraicInterval a) {
    942       if (Math.Abs(a.UpperBound.Value.Value - a.LowerBound.Value.Value) >= Math.PI * 2) {
    943         low = new MultivariateDual<AlgebraicDouble>(-1.0);
     942      var lower = a.LowerBound.Value.Value;
     943      var size = a.UpperBound.Value.Value - lower;
     944      if (size < 0) throw new InvalidProgramException(); // ASSERT interval >= 0;
     945
     946      if (size >= Math.PI * 2) {
     947        low = new MultivariateDual<AlgebraicDouble>(-1.0); // zero gradient
    944948        high = new MultivariateDual<AlgebraicDouble>(1.0);
    945949      }
    946950
    947       //divide the interval by PI/2 so that the optima lie at x element of N (0,1,2,3,4,...)
    948       double Pihalf = Math.PI / 2;
    949       var scaled = a.Clone().Scale(1.0 / Pihalf);
    950       //move to positive scale
    951       if (scaled.LowerBound.Value.Value < 0) {
    952         int periodsToMove = Math.Abs((int)scaled.LowerBound.Value.Value / 4) + 1;
    953         scaled.Add(new AlgebraicInterval(periodsToMove * 4, periodsToMove * 4));
    954       }
    955 
    956       double scaledLowerBound = scaled.LowerBound.Value.Value % 4.0;
    957       double scaledUpperBound = scaled.UpperBound.Value.Value % 4.0;
    958       if (scaledUpperBound < scaledLowerBound) scaledUpperBound += 4.0;
    959       List<double> sinValues = new List<double>();
    960       sinValues.Add(Math.Sin(scaledLowerBound * Pihalf));
    961       sinValues.Add(Math.Sin(scaledUpperBound * Pihalf));
    962 
    963       int startValue = (int)Math.Ceiling(scaledLowerBound);
    964       while (startValue < scaledUpperBound) {
    965         sinValues.Add(Math.Sin(startValue * Pihalf));
    966         startValue += 1;
    967       }
    968 
    969       low = new MultivariateDual<AlgebraicDouble>(sinValues.Min()); // TODO, XXX FIX CALCULATION TO SUPPORT GRADIENTS!
    970       high = new MultivariateDual<AlgebraicDouble>(sinValues.Max());
     951      // assume low and high are in the same quadrant
     952      low = Algebraic.Min(a.LowerBound.Clone().Sin(), a.UpperBound.Clone().Sin());
     953      high = Algebraic.Max(a.LowerBound.Clone().Sin(), a.UpperBound.Clone().Sin());
     954
     955      // override min and max if necessary
     956
     957      // shift interval 'a' into the range [-2pi .. 2pi] without changing the size of the interval to simplify the checks
     958      lower = lower % (2 * Math.PI); // lower in [-2pi .. 2pi]     
     959
     960      // handle min = -1 and max = 1 cases explicitly
     961      var pi_2 = Math.PI / 2.0;
     962      var maxima = new double[] { -3 * pi_2, pi_2 };
     963      var minima = new double[] { -pi_2, 3 * pi_2 };
     964
     965      // override min and max if necessary
     966      if (maxima.Any(m => lower < m && lower + size > m)) {
     967        // max = 1
     968        high = new MultivariateDual<AlgebraicDouble>(1.0); // zero gradient
     969      }
     970
     971      if (minima.Any(m => lower < m && lower + size > m)) {
     972        // min = -1;
     973        low = new MultivariateDual<AlgebraicDouble>(-1.0); // zero gradient
     974      }
    971975      return this;
    972976    }
Note: See TracChangeset for help on using the changeset viewer.