Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
08/13/19 13:41:21 (5 years ago)
Author:
gkronber
Message:

#2994: fixed division, multiplication and cos for intervals based on failing tests

File:
1 edited

Legend:

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

    r17203 r17212  
    484484    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    485485    public AlgebraicDouble One => new AlgebraicDouble(1.0);
     486
     487    public bool IsInfinity => IsNegativeInfinity || IsPositiveInfinity;
     488    public bool IsNegativeInfinity => double.IsNegativeInfinity(Value);
     489    public bool IsPositiveInfinity => double.IsPositiveInfinity(Value);
    486490    public AlgebraicDouble() { }
    487491    public AlgebraicDouble(double value) { this.Value = value; }
     
    497501    public AlgebraicDouble AssignCos(AlgebraicDouble a) { Value = Math.Cos(a.Value); return this; }
    498502    public AlgebraicDouble AssignTanh(AlgebraicDouble a) { Value = Math.Tanh(a.Value); return this; }
    499     public AlgebraicDouble AssignLog(AlgebraicDouble a) { Value = a.Value <= 0 ? double.NegativeInfinity : Math.Log(a.Value); return this; } // alternative definiton of log to prevent NaN
     503    public AlgebraicDouble AssignLog(AlgebraicDouble a) { Value = Math.Log(a.Value); return this; }
    500504    public AlgebraicDouble AssignExp(AlgebraicDouble a) { Value = Math.Exp(a.Value); return this; }
    501505    public AlgebraicDouble AssignIntPower(AlgebraicDouble a, int p) { Value = Math.Pow(a.Value, p); return this; }
     
    803807      var v4 = high.Clone().Mul(a.high);
    804808
    805       low = Algebraic.Min(Algebraic.Min(v1, v2), Algebraic.Min(v3, v4));
    806       high = Algebraic.Max(Algebraic.Max(v1, v2), Algebraic.Max(v3, v4));
    807       return this;
     809      low = Min(Min(v1, v2), Min(v3, v4));
     810      high = Max(Max(v1, v2), Max(v3, v4));
     811
     812      return this;
     813    }
     814
     815    // algebraic min() / max() do not work for infinities
     816    // detect and handle infinite values explicitly
     817    private static MultivariateDual<AlgebraicDouble> Min(MultivariateDual<AlgebraicDouble> a, MultivariateDual<AlgebraicDouble> b) {
     818      if (a.Value.IsInfinity || b.Value.IsInfinity) return a.Value < b.Value ? a : b; // NOTE: this is not differentiable but for infinite values we do not care
     819      else return Algebraic.Min(a, b); // differentiable statement
     820    }
     821    private static MultivariateDual<AlgebraicDouble> Max(MultivariateDual<AlgebraicDouble> a, MultivariateDual<AlgebraicDouble> b) {
     822      if (a.Value.IsInfinity || b.Value.IsInfinity) return a.Value >= b.Value ? a : b; // NOTE: this is not differentiable but for infinite values we do not care
     823      else return Algebraic.Max(a, b); // differentiable statement
    808824    }
    809825
     
    815831
    816832    public AlgebraicInterval AssignCos(AlgebraicInterval a) {
    817       return AssignSin(a.Clone().Sub(new AlgebraicInterval(Math.PI / 2, Math.PI / 2)));
     833      return AssignSin(a.Clone().Add(new AlgebraicInterval(Math.PI / 2, Math.PI / 2)));
    818834    }
    819835
     
    821837      if (a.Contains(0.0)) {
    822838        if (a.low.Value.Value == 0 && a.high.Value.Value == 0) {
     839          if (this.low.Value >= 0) {
     840            // pos / 0
     841          } else if (this.high.Value <= 0) {
     842            // neg / 0
     843          } else {
     844            low = new MultivariateDual<AlgebraicDouble>(double.NegativeInfinity);
     845            high = new MultivariateDual<AlgebraicDouble>(double.PositiveInfinity);
     846          }
     847        } else if (a.low.Value.Value >= 0) {
     848          // a is positive
     849          Mul(new AlgebraicInterval(a.Clone().high.Inv(), new MultivariateDual<AlgebraicDouble>(double.PositiveInfinity)));
     850        } else if (a.high.Value <= 0) {
     851          // a is negative
     852          Mul(new AlgebraicInterval(new MultivariateDual<AlgebraicDouble>(double.NegativeInfinity), a.low.Clone().Inv()));
     853        } else {
     854          // a is interval over zero
    823855          low = new MultivariateDual<AlgebraicDouble>(double.NegativeInfinity);
    824856          high = new MultivariateDual<AlgebraicDouble>(double.PositiveInfinity);
    825         } else if (a.low.Value.Value == 0)
    826           Mul(new AlgebraicInterval(a.Clone().high.Inv(), new MultivariateDual<AlgebraicDouble>(double.PositiveInfinity)));
    827         else
    828           Mul(new AlgebraicInterval(new MultivariateDual<AlgebraicDouble>(double.NegativeInfinity), a.low.Clone().Inv()));
     857        }
    829858      } else {
    830859        Mul(new AlgebraicInterval(a.high.Clone().Inv(), a.low.Clone().Inv())); // inverting leads to inverse roles of high and low
     
    947976        low = new MultivariateDual<AlgebraicDouble>(-1.0); // zero gradient
    948977        high = new MultivariateDual<AlgebraicDouble>(1.0);
     978        return this;
    949979      }
    950980
     
    11451175    public MultivariateDual<V> AssignAbs(MultivariateDual<V> a) { v.AssignAbs(a.v); dv.Assign(a.dv).Scale(a.v.Clone().Sgn()); return this; }      // abs(f(x))' = f(x)*f'(x) / |f(x)|  doesn't work for intervals     
    11461176    public MultivariateDual<V> AssignSgn(MultivariateDual<V> a) { v.AssignSgn(a.v); dv = a.dv.Zero; return this; } // sign(f(x))' = 0;     
     1177
    11471178  }
    11481179}
Note: See TracChangeset for help on using the changeset viewer.