Changeset 16744


Ignore:
Timestamp:
04/02/19 13:55:49 (3 weeks ago)
Author:
gkronber
Message:

#2994: slightly changed calculation of integer powers for intervals and added unit tests.

Location:
branches/2994-AutoDiffForIntervals
Files:
2 edited

Legend:

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

    r16738 r16744  
    285285        var g = code[0].value.Gradient;
    286286        for (int j = 0; j < nParams; ++j) {
    287           if(g.Elements.TryGetValue(j, out AlgebraicDoubleVector v)) {
     287          if (g.Elements.TryGetValue(j, out AlgebraicDoubleVector v)) {
    288288            v.CopyColumnTo(jac, j, rowIndex, BATCHSIZE);
    289289          } else {
     
    490490    public AlgebraicDouble AssignSin(AlgebraicDouble a) { Value = Math.Sin(a.Value); return this; }
    491491    public AlgebraicDouble AssignCos(AlgebraicDouble a) { Value = Math.Cos(a.Value); return this; }
    492     public AlgebraicDouble AssignLog(AlgebraicDouble a) { Value = a.Value <= 0?double.NegativeInfinity : Math.Log(a.Value); return this; } // alternative definiton of log to prevent NaN
     492    public AlgebraicDouble AssignLog(AlgebraicDouble a) { Value = a.Value <= 0 ? double.NegativeInfinity : Math.Log(a.Value); return this; } // alternative definiton of log to prevent NaN
    493493    public AlgebraicDouble AssignExp(AlgebraicDouble a) { Value = Math.Exp(a.Value); return this; }
    494494    public AlgebraicDouble AssignIntPower(AlgebraicDouble a, int p) { Value = Math.Pow(a.Value, p); return this; }
    495495    public AlgebraicDouble AssignIntRoot(AlgebraicDouble a, int r) { Value = Math.Pow(a.Value, 1.0 / r); return this; }
    496496    public AlgebraicDouble AssignAbs(AlgebraicDouble a) { Value = Math.Abs(a.Value); return this; }
    497     public AlgebraicDouble AssignSgn(AlgebraicDouble a) { Value = double.IsNaN(a.Value)? double.NaN : Math.Sign(a.Value); return this; }
     497    public AlgebraicDouble AssignSgn(AlgebraicDouble a) { Value = double.IsNaN(a.Value) ? double.NaN : Math.Sign(a.Value); return this; }
    498498    public AlgebraicDouble Clone() { return new AlgebraicDouble(Value); }
    499499
     
    828828    }
    829829
    830 //     Exponentiation by a natural power[a, b] k:
    831 //
    832 // if 0∈[a, b], then
    833 //   [a, b]^0  =  [0, 1]
    834 //   [a, b]^2n   =  [0, max(a2n, b2n)]
    835 //   [a, b]^2n+1   =  [a2n+1, b2n+1]
    836 // if [a, b]>0, then
    837 //   [a, b]^0  =  [1, 1]
    838 //   [a, b]^k>0  =  [ak, bk]
    839 // if [a, b]<0, then
    840 //   [a, b]^0  =  [1, 1]
    841 //   [a, b]^2n   =  [b2n, a2n]
    842 //   [a, b]^2n+1   =  [a2n+1, b2n+1]
    843 
    844830    public AlgebraicInterval AssignIntPower(AlgebraicInterval a, int p) {
    845       if (p == 0) {
    846         // => 1
    847         low = new MultivariateDual<AlgebraicDouble>(1.0);
    848         high = new MultivariateDual<AlgebraicDouble>(1.0);
    849         return this;
    850       }
    851       if (p == 1) return this;
    852 
    853831      if (p < 0) {  // x^-3 == 1/(x^3)
    854832        AssignIntPower(a, -p);
    855833        return AssignInv(this);
    856       } else {
     834      } else if (p == 0) {
     835        if (a.Contains(0.0)) {
     836          // => 0^0 = 0 ; might not be relevant
     837          low = new MultivariateDual<AlgebraicDouble>(0.0);
     838          high = new MultivariateDual<AlgebraicDouble>(1.0);
     839          return this;
     840        } else {
     841          // => 1
     842          low = new MultivariateDual<AlgebraicDouble>(1.0);
     843          high = new MultivariateDual<AlgebraicDouble>(1.0);
     844          return this;
     845        }
     846      } else if (p == 1) return this;
     847      else if (p % 2 == 0) {
    857848        // p is even => interval must be positive
    858         if (p % 2 == 0) {
    859           if (a.Contains(0.0)) {
    860             low = new MultivariateDual<AlgebraicDouble>(0.0);
    861             high = Algebraic.Max(a.low.IntPower(p), a.high.IntPower(p));
    862           } else {
    863             var lowPower = a.low.IntPower(p);
    864             var highPower = a.high.IntPower(p);
    865             low = Algebraic.Min(lowPower, highPower);
    866             high = Algebraic.Max(lowPower, highPower);
    867           }
     849        if (a.Contains(0.0)) {
     850          low = new MultivariateDual<AlgebraicDouble>(0.0);
     851          high = Algebraic.Max(a.low.IntPower(p), a.high.IntPower(p));
    868852        } else {
    869           // p is uneven
    870853          var lowPower = a.low.IntPower(p);
    871854          var highPower = a.high.IntPower(p);
     
    873856          high = Algebraic.Max(lowPower, highPower);
    874857        }
    875         return this;
    876       }
     858      } else {
     859        // p is uneven
     860        if (a.Contains(0.0)) {
     861          low.AssignIntPower(a.low, p);
     862          high.AssignIntPower(a.high, p);
     863        } else {
     864          var lowPower = a.low.IntPower(p);
     865          var highPower = a.high.IntPower(p);
     866          low = Algebraic.Min(lowPower, highPower);
     867          high = Algebraic.Max(lowPower, highPower);
     868        }
     869      }
     870      return this;
    877871    }
    878872
  • branches/2994-AutoDiffForIntervals/Tests/AutoDiffTest.cs

    r16738 r16744  
    107107
    108108      {
     109        // Interval tests
     110        var intervals = new Dictionary<string, Interval>();
     111        intervals.Add("x", new Interval(-2.0, 3.0));
     112        intervals.Add("p", new Interval(1.0, 2.0));
     113        intervals.Add("n", new Interval(-2.0, -1.0));
     114
     115        AssertInterval("10*x", intervals, -20, 30);
     116        AssertInterval("sqr(p)", intervals, 1, 4);
     117        AssertInterval("sqr(n)", intervals, 1, 4);
     118        AssertInterval("sqr(x)", intervals, 0, 9);
     119
     120        AssertInterval("cube(p)", intervals, 1, 8);
     121        AssertInterval("cube(n)", intervals, -8, -1);
     122        AssertInterval("cube(x)", intervals, -8, 27);
     123      }
     124
     125      {
    109126        // interval eval and auto-diff
    110127        var parser = new InfixExpressionParser();
     
    226243
    227244    }
     245
     246    private void AssertInterval(string expression, Dictionary<string, Interval> intervals, double expectedLow, double expectedHigh) {
     247      var parser = new InfixExpressionParser();
     248      var t = parser.Parse(expression);
     249      var evaluator = new IntervalEvaluator();
     250      var result = evaluator.Evaluate(t, intervals);
     251      Assert.AreEqual(expectedLow, result.LowerBound);
     252      Assert.AreEqual(expectedHigh, result.UpperBound);
     253    }
    228254  }
    229255}
Note: See TracChangeset for help on using the changeset viewer.