Changeset 17303


Ignore:
Timestamp:
10/03/19 12:30:19 (11 days ago)
Author:
gkronber
Message:

#2994 continued refactoring and extended unit tests. Interval calculation still fails for some edge cases (mainly for undefined behaviour). VectorEvaluator and VectorAutoDiffEvaluator produce the same results as the LinearInterpreter. TODO: check gradient calculation

Location:
branches/2994-AutoDiffForIntervals
Files:
1 added
14 edited

Legend:

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

    r17297 r17303  
    182182    <Compile Include="Interpreter\VectorAutoDiffEvaluator.cs" />
    183183    <Compile Include="Interpreter\VectorEvaluator.cs" />
     184    <Compile Include="Interpreter\VectorOfAlgebraic.cs" />
    184185    <Compile Include="Selectors\DiversitySelector.cs" />
    185186    <Compile Include="SymbolicDataAnalysisExpressionTreeAverageSimilarityCalculator.cs" />
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Algebraic.cs

    r17295 r17303  
    1212    public static T IntRoot<T>(this T a, int r) where T : IAlgebraicType<T> { a.AssignIntRoot(a.Clone(), r); return a; }
    1313
    14     internal static T Min<T>(T a, T b) where T : IAlgebraicType<T> { return a.Clone().AssignMin(b); }
    15     internal static T Max<T>(T a, T b) where T : IAlgebraicType<T> { return a.Clone().AssignMax(b); }
    16 
    1714    // public static T Max<T>(T a, T b) where T : IAlgebraicType<T> {
    1815    //   // ((a + b) + abs(b - a)) / 2
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicDouble.cs

    r17298 r17303  
    55  // algebraic type wrapper for a double value
    66  [DebuggerDisplay("{Value}")]
    7   public sealed class AlgebraicDouble : IAlgebraicType<AlgebraicDouble> {
     7  public sealed class AlgebraicDouble : IComparableAlgebraicType<AlgebraicDouble> {
    88    public static implicit operator AlgebraicDouble(double value) { return new AlgebraicDouble(value); }
    99    public static implicit operator double(AlgebraicDouble value) { return value.Value; }
     
    3535    public AlgebraicDouble AssignIntPower(AlgebraicDouble a, int p) { Value = Math.Pow(a.Value, p); return this; }
    3636    public AlgebraicDouble AssignIntRoot(AlgebraicDouble a, int r) { Value = IntRoot(a.Value, r); return this; }
    37     public AlgebraicDouble AssignMin(AlgebraicDouble other) { Value = Math.Min(Value, other.Value); return this; }
    38     public AlgebraicDouble AssignMax(AlgebraicDouble other) { Value = Math.Max(Value, other.Value); return this; }
     37    //public AlgebraicDouble AssignMin(AlgebraicDouble other) { Value = Math.Min(Value, other.Value); return this; }
     38    //public AlgebraicDouble AssignMax(AlgebraicDouble other) { Value = Math.Max(Value, other.Value); return this; }
    3939    public AlgebraicDouble AssignAbs(AlgebraicDouble a) { Value = Math.Abs(a.Value); return this; }
    4040    public AlgebraicDouble AssignSgn(AlgebraicDouble a) { Value = double.IsNaN(a.Value) ? double.NaN : Math.Sign(a.Value); return this; }
     
    5151      return Value.ToString();
    5252    }
     53
     54    public int CompareTo(AlgebraicDouble other) {
     55      return Value.CompareTo(other.Value);
     56    }
    5357  }
    5458}
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicDoubleVector.cs

    r17298 r17303  
    66  // a simple vector as an algebraic type
    77  [DebuggerDisplay("DoubleVector(len={Length}): {string.}")]
     8  [Obsolete("Use VectorOfAlgebraic instead")]
    89  public class AlgebraicDoubleVector : IAlgebraicType<AlgebraicDoubleVector> {
    910    private double[] arr;
     
    4041    public AlgebraicDoubleVector AssignIntPower(AlgebraicDoubleVector a, int p) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Pow(a.arr[i], p); } return this; }
    4142    public AlgebraicDoubleVector AssignIntRoot(AlgebraicDoubleVector a, int r) { for (int i = 0; i < arr.Length; ++i) { arr[i] = IntRoot(a.arr[i], r); } return this; }
    42     public AlgebraicDoubleVector AssignMin(AlgebraicDoubleVector other) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Min(arr[i], other.arr[i]); } return this; }
    43     public AlgebraicDoubleVector AssignMax(AlgebraicDoubleVector other) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Max(arr[i], other.arr[i]); } return this; }
     43    //public AlgebraicDoubleVector AssignMin(AlgebraicDoubleVector other) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Min(arr[i], other.arr[i]); } return this; }
     44    //public AlgebraicDoubleVector AssignMax(AlgebraicDoubleVector other) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Max(arr[i], other.arr[i]); } return this; }
    4445    public AlgebraicDoubleVector AssignAbs(AlgebraicDoubleVector a) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Abs(a.arr[i]); } return this; }
    4546    public AlgebraicDoubleVector AssignSgn(AlgebraicDoubleVector a) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Sign(a.arr[i]); } return this; }
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicInterval.cs

    r17295 r17303  
    4747      var v4 = high.Clone().Mul(a.high);
    4848
    49       low = Min(Min(v1, v2), Min(v3, v4));
    50       high = Max(Max(v1, v2), Max(v3, v4));
    51 
    52       return this;
    53     }
    54 
    55 
    56     private static MultivariateDual<AlgebraicDouble> Min(MultivariateDual<AlgebraicDouble> a, MultivariateDual<AlgebraicDouble> b) {
    57       return a.Value < b.Value ? a : b;
    58     }
    59     private static MultivariateDual<AlgebraicDouble> Max(MultivariateDual<AlgebraicDouble> a, MultivariateDual<AlgebraicDouble> b) {
    60       return a.Value > b.Value ? a : b;
     49      AssignLowAndHigh(v1, v2, v3, v4);
     50
     51      return this;
    6152    }
    6253
     
    133124        if (a.Contains(0.0)) {
    134125          low = new MultivariateDual<AlgebraicDouble>(0.0);
    135           high = a.low.IntPower(p).AssignMax(a.high.IntPower(p));
    136         } else {
    137           var lowPower = a.low.IntPower(p);
    138           var highPower = a.high.IntPower(p);
    139           low = lowPower.AssignMin(highPower);
    140           high = lowPower.AssignMax(highPower);
     126          AssignMax(high, a.low.IntPower(p), a.high.IntPower(p));
     127        } else {
     128          AssignLowAndHigh(a.low.IntPower(p), a.high.IntPower(p));
    141129        }
    142130      } else {
     
    148136          var lowPower = a.low.IntPower(p);
    149137          var highPower = a.high.IntPower(p);
    150           low = lowPower.AssignMin(highPower);
    151           high = lowPower.AssignMax(highPower);
     138          AssignMin(low, lowPower, highPower);
     139          AssignMax(high, lowPower, highPower);
    152140        }
    153141      }
     
    217205
    218206      // assume low and high are in the same quadrant
    219       low = Algebraic.Min(a.LowerBound.Clone().Sin(), a.UpperBound.Clone().Sin());
    220       high = Algebraic.Max(a.LowerBound.Clone().Sin(), a.UpperBound.Clone().Sin());
     207      AssignLowAndHigh(a.LowerBound.Clone().Sin(), a.UpperBound.Clone().Sin()); // AssignLowAndHigh determines the lower and higher value
    221208
    222209      // override min and max if necessary
     
    260247    public AlgebraicInterval AssignAbs(AlgebraicInterval a) {
    261248      if (a.Contains(0.0)) {
     249        low.Assign(new MultivariateDual<AlgebraicDouble>(0.0)); // lost gradient for lower bound
     250        AssignMax(high, a.low.Clone().Abs(), a.high.Clone().Abs());
     251      } else {
    262252        var abslow = a.low.Clone().Abs();
    263253        var abshigh = a.high.Clone().Abs();
    264         a.high.Assign(Algebraic.Max(abslow, abshigh));
    265         a.low.Assign(new MultivariateDual<AlgebraicDouble>(0.0)); // lost gradient for lower bound
    266       } else {
    267         var abslow = a.low.Clone().Abs();
    268         var abshigh = a.high.Clone().Abs();
    269         a.low.Assign(Algebraic.Min(abslow, abshigh));
    270         a.high.Assign(Algebraic.Max(abslow, abshigh));
     254        AssignLowAndHigh(abslow, abshigh);
    271255      }
    272256      return this;
     
    279263    }
    280264
    281     public AlgebraicInterval AssignMin(AlgebraicInterval other) {
    282       low.AssignMin(other.low);
    283       high.AssignMin(other.high);
    284       return this;
    285     }
    286 
    287     public AlgebraicInterval AssignMax(AlgebraicInterval other) {
    288       low.AssignMax(other.low);
    289       high.AssignMax(other.high);
    290       return this;
    291     }
     265
     266    #region helper
     267    private void AssignMin(MultivariateDual<AlgebraicDouble> dest, MultivariateDual<AlgebraicDouble> a, MultivariateDual<AlgebraicDouble> b) {
     268      if (a.Value.CompareTo(b.Value) <= 0) {
     269        dest.Assign(a);
     270      } else {
     271        dest.Assign(b);
     272      }
     273    }
     274    private void AssignMax(MultivariateDual<AlgebraicDouble> dest, MultivariateDual<AlgebraicDouble> a, MultivariateDual<AlgebraicDouble> b) {
     275      if (a.Value.CompareTo(b.Value) <= 0) {
     276        dest.Assign(b);
     277      } else {
     278        dest.Assign(a);
     279      }
     280    }
     281
     282    // determines the smaller and larger value and sets low and high accordingly
     283    private void AssignLowAndHigh(MultivariateDual<AlgebraicDouble> a, MultivariateDual<AlgebraicDouble> b) {
     284      // we must make sure that low and high are different objects when a == b
     285      if (a.Value.CompareTo(b.Value) == 0) {
     286        low.Assign(a);
     287        high.Assign(b);
     288      } else {
     289        AssignMin(low, a, b);
     290        AssignMax(high, a, b);
     291      }
     292    }
     293    private void AssignLowAndHigh(params MultivariateDual<AlgebraicDouble>[] xs) {
     294      if (xs.Length <= 2) throw new ArgumentException("need at least 3 arguments");
     295      AssignLowAndHigh(xs[0], xs[1]);
     296      for(int i=2;i<xs.Length;i++) {
     297        // we must make sure that low and high are different objects when a == b
     298        if (low.Value.CompareTo(xs[i].Value) > 0) low.Assign(xs[i]);
     299        if (high.Value.CompareTo(xs[i].Value) < 0) high.Assign(xs[i]);
     300      }
     301    }
     302    #endregion
     303
    292304  }
    293305}
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicSparseVector.cs

    r17298 r17303  
    109109    }
    110110
    111     public AlgebraicSparseVector<K, T> AssignMin(AlgebraicSparseVector<K, T> other) {
    112       // assumes that keys without a matching key in other are zero and vice versa
    113       foreach (var kvp in elems) if (!other.elems.ContainsKey(kvp.Key)) kvp.Value.AssignMin(kvp.Value.Zero); // min(v, 0)
    114       foreach (var kvp in other.elems) {
    115         if (elems.TryGetValue(kvp.Key, out T value))
    116           value.AssignMin(kvp.Value);
    117         else
    118           elems.Add(kvp.Key, kvp.Value.Zero.AssignMin(kvp.Value));
    119       }
    120       return this;
    121     }
    122 
    123     public AlgebraicSparseVector<K, T> AssignMax(AlgebraicSparseVector<K, T> other) {
    124       // assumes that keys without a matching key in other are zero and vice versa
    125       foreach (var kvp in elems) if (!other.elems.ContainsKey(kvp.Key)) kvp.Value.AssignMax(kvp.Value.Zero); // max(v, 0)
    126       foreach (var kvp in other.elems) {
    127         if (elems.TryGetValue(kvp.Key, out T value))
    128           value.AssignMax(kvp.Value);
    129         else
    130           elems.Add(kvp.Key, kvp.Value.Zero.AssignMax(kvp.Value));
    131       }
    132       return this;
    133     }
    134 
    135 
    136111    public AlgebraicSparseVector<K, T> Clone() {
    137112      return new AlgebraicSparseVector<K, T>(this);
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Dual.cs

    r17295 r17303  
    44namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
    55  public class Dual<V> : IAlgebraicType<Dual<V>>
    6     where V : IAlgebraicType<V> {
     6    where V : IComparableAlgebraicType<V> {
    77    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    88    private V v;
     
    5454
    5555    public Dual<V> AssignMin(Dual<V> other) {
    56       throw new NotImplementedException();
     56      if(v.CompareTo(other.v) > 0) {
     57        v.Assign(other.v);
     58        dv.Assign(other.dv);
     59      }
     60      return this;
    5761    }
    5862
    5963    public Dual<V> AssignMax(Dual<V> other) {
    60       throw new NotImplementedException();
     64      if (v.CompareTo(other.v) <= 0) {
     65        v.Assign(other.v);
     66        dv.Assign(other.dv);
     67      }
     68      return this;
    6169    }
    6270  }
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IAlgebraicType.cs

    r17295 r17303  
    1 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
     1using System;
     2
     3namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
    24  public interface IAlgebraicType<T> {
    35    T Zero { get; } // Zero and One must create new objects
     
    2123    T AssignIntRoot(T a, int r);
    2224    T AssignSgn(T a); // set this to sign(a)
    23     T AssignMin(T other); // set this min(this, other)
    24     T AssignMax(T other); // set this max(this, other)
     25    //T AssignMin(T other); // set this min(this, other)
     26    //T AssignMax(T other); // set this max(this, other)
    2527    T Clone();
    2628  }
     29
     30  public interface IComparableAlgebraicType<T> : IAlgebraicType<T>, IComparable<T> {
     31
     32  }
    2733}
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/MultivariateDual.cs

    r17297 r17303  
    1717    public AlgebraicSparseVector<object, V> Gradient => dv; // <key,value> partial derivative identified via the key
    1818
     19
    1920    private MultivariateDual(MultivariateDual<V> orig) { this.v = orig.v.Clone(); this.dv = orig.dv.Clone(); }
     21
     22    /// <summary>
     23    /// Constructor which sets value and derivative to zero
     24    /// </summary>
     25    public MultivariateDual() {
     26      v = new V(); // assumed to be zero
     27      dv = new AlgebraicSparseVector<object, V>();
     28    }
    2029
    2130    /// <summary>
     
    8392    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     
    8493    public MultivariateDual<V> AssignSgn(MultivariateDual<V> a) { v.AssignSgn(a.v); dv = a.dv.Zero; return this; } // sign(f(x))' = 0;     
    85 
    86     public MultivariateDual<V> AssignMin(MultivariateDual<V> other) {
    87       throw new NotImplementedException();
    88     }
    89 
    90     public MultivariateDual<V> AssignMax(MultivariateDual<V> other) {
    91       throw new NotImplementedException();
    92     }
    9394  }
    9495}
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/VectorAutoDiffEvaluator.cs

    r17296 r17303  
    55
    66namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
    7   public sealed class VectorAutoDiffEvaluator : InterpreterBase<MultivariateDual<AlgebraicDoubleVector>> {
     7  public sealed class VectorAutoDiffEvaluator : InterpreterBase<VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>> {
    88    private const int BATCHSIZE = 128;
    99    [ThreadStatic]
     
    5757      for (rowIndex = 0; rowIndex < roundedTotal; rowIndex += BATCHSIZE) {
    5858        Evaluate(code);
    59         code[0].value.Value.CopyTo(fi, rowIndex, BATCHSIZE);
    6059
    61         // TRANSPOSE into JAC
    62         var g = code[0].value.Gradient;
    63         for (int j = 0; j < nParams; ++j) {
    64           if (g.Elements.TryGetValue(j, out AlgebraicDoubleVector v)) {
    65             v.CopyColumnTo(jac, j, rowIndex, BATCHSIZE);
    66           } else {
    67             for (int r = 0; r < BATCHSIZE; r++) jac[rowIndex + r, j] = 0.0;
     60        // code[0].value.Value.CopyTo(fi, rowIndex, BATCHSIZE);
     61        var v = code[0].value;
     62        for (int k = 0; k < BATCHSIZE; k++) {
     63          fi[rowIndex + k] = v[k].Value.Value;
     64
     65          // copy gradient to Jacobian
     66          var g = v[k].Gradient;
     67          for (int j = 0; j < nParams; ++j) {
     68            if (g.Elements.TryGetValue(j, out AlgebraicDouble gj)) {
     69              jac[rowIndex + k, j] = gj.Value;
     70            } else {
     71              jac[rowIndex + k, j] = 0.0;
     72            }
    6873          }
    6974        }
     
    7277      if (remainingRows > 0) {
    7378        Evaluate(code);
    74         code[0].value.Value.CopyTo(fi, roundedTotal, remainingRows);
     79        // code[0].value.Value.CopyTo(fi, roundedTotal, remainingRows);
     80        var v = code[0].value;
     81        for (int k = 0; k < remainingRows; k++) {
     82          fi[roundedTotal + k] = v[k].Value.Value;
    7583
    76         var g = code[0].value.Gradient;
    77         for (int j = 0; j < nParams; ++j)
    78           if (g.Elements.TryGetValue(j, out AlgebraicDoubleVector v)) {
    79             v.CopyColumnTo(jac, j, roundedTotal, remainingRows);
    80           } else {
    81             for (int r = 0; r < remainingRows; r++) jac[roundedTotal + r, j] = 0.0;
     84          var g = v[k].Gradient;
     85          for (int j = 0; j < nParams; ++j) {
     86            if (g.Elements.TryGetValue(j, out AlgebraicDouble gj)) {
     87              jac[roundedTotal + k, j] = gj.Value;
     88            } else {
     89              jac[roundedTotal + k, j] = 0.0;
     90            }
    8291          }
     92        }
    8393      }
    8494    }
    8595
    8696    protected override void InitializeInternalInstruction(ref Instruction instruction, ISymbolicExpressionTreeNode node) {
    87       var zero = new AlgebraicDoubleVector(BATCHSIZE);
    88       instruction.value = new MultivariateDual<AlgebraicDoubleVector>(zero);
     97      instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE).Zero; // XXX zero needed?
    8998    }
    9099
    91100    protected override void InitializeTerminalInstruction(ref Instruction instruction, ConstantTreeNode constant) {
    92       var g_arr = new double[BATCHSIZE];
    93101      if (node2paramIdx.TryGetValue(constant, out var paramIdx)) {
    94         for (int i = 0; i < BATCHSIZE; i++) g_arr[i] = 1.0;
    95         var g = new AlgebraicDoubleVector(g_arr);
    96         instruction.value = new MultivariateDual<AlgebraicDoubleVector>(new AlgebraicDoubleVector(BATCHSIZE), paramIdx, g); // only a single column for the gradient
     102        instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE);
     103        for (int k = 0; k < BATCHSIZE; k++) {
     104          instruction.value[k] = new MultivariateDual<AlgebraicDouble>(constant.Value, paramIdx, 1.0); // gradient is 1.0 for all elements
     105        }
    97106      } else {
    98         instruction.value = new MultivariateDual<AlgebraicDoubleVector>(new AlgebraicDoubleVector(BATCHSIZE));
     107        instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE);
     108        for (int k = 0; k < BATCHSIZE; k++) {
     109          instruction.value[k] = new MultivariateDual<AlgebraicDouble>(constant.Value); // zero gradient
     110        }
    99111      }
    100112
    101       instruction.dblVal = constant.Value;
    102       instruction.value.Value.AssignConstant(instruction.dblVal);
     113      instruction.dblVal = constant.Value; // also store the parameter value in the instruction (not absolutely necessary, will not be used)
    103114    }
    104115
     
    115126      if (node2paramIdx.ContainsKey(variable)) {
    116127        paramIdx = node2paramIdx[variable];
    117         var f = new AlgebraicDoubleVector(BATCHSIZE);
    118         var g = new AlgebraicDoubleVector(BATCHSIZE);
    119         instruction.value = new MultivariateDual<AlgebraicDoubleVector>(f, paramIdx, g);
     128        instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE);
     129        for(int k=0;k<BATCHSIZE;k++) {
     130          instruction.value[k] = new MultivariateDual<AlgebraicDouble>(0.0, paramIdx, 0.0); // values are set in LoadVariable()
     131        }
    120132      } else {
    121133        var f = new AlgebraicDoubleVector(BATCHSIZE);
    122         instruction.value = new MultivariateDual<AlgebraicDoubleVector>(f);
     134        instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE);
     135        for (int k = 0; k < BATCHSIZE; k++) {
     136          instruction.value[k] = new MultivariateDual<AlgebraicDouble>(0.0); // values are set in LoadVariable()
     137        }
    123138      }
    124139
    125       instruction.dblVal = variable.Weight;
     140      instruction.dblVal = variable.Weight; 
    126141      instruction.data = new object[] { data, paramIdx };
    127142    }
     
    131146      var data = (double[])((object[])a.data)[0];
    132147
    133       for (int i = rowIndex; i < rows.Length && i - rowIndex < BATCHSIZE; i++) a.value.Value[i - rowIndex] = data[rows[i]];
    134       a.value.Scale(a.dblVal);
     148      for (int i = rowIndex; i < rows.Length && i - rowIndex < BATCHSIZE; i++) {
     149        a.value[i - rowIndex].Value.Assign(a.dblVal * data[rows[i]]);
     150      }
    135151
    136152      if (paramIdx >= 0) {
    137153        // update gradient with variable values
    138         var g = a.value.Gradient.Elements[paramIdx];
    139154        for (int i = rowIndex; i < rows.Length && i - rowIndex < BATCHSIZE; i++) {
    140           g[i - rowIndex] = data[rows[i]];
     155          a.value[i - rowIndex].Gradient.Elements[paramIdx].Assign(data[rows[i]]);
    141156        }
    142157      }
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/AutoDiffIntervalTest.cs

    r17299 r17303  
    102102      //Division by 0 ==> IsInfiniteOrUndefined == true
    103103      AssertAreEqualInterval(Divide(d, b), new AlgebraicInterval(double.NegativeInfinity, double.PositiveInfinity));
     104
     105      // [0, 1] / [0, 1]
     106      AssertAreEqualInterval(new AlgebraicInterval(0, 1).Div(new AlgebraicInterval(0, 1)), new AlgebraicInterval(1, double.PositiveInfinity)); // returns [NaN, PositiveInfinity]
     107
    104108    }
    105109
     
    177181    [TestProperty("Time", "short")]
    178182    public void TestIntervalSqrOperator() {
    179       AssertAreEqualInterval(new AlgebraicInterval(1, 4), Square(new AlgebraicInterval(1, 2)));
    180       AssertAreEqualInterval(new AlgebraicInterval(1, 4), Square(new AlgebraicInterval(-2, -1)));
    181       AssertAreEqualInterval(new AlgebraicInterval(0, 4), Square(new AlgebraicInterval(-2, 2)));
    182     }
    183 
    184     private AlgebraicInterval Square(AlgebraicInterval algebraicInterval) {
    185       return algebraicInterval.IntPower(2);
     183      AssertAreEqualInterval(new AlgebraicInterval(1, 4), new AlgebraicInterval(1, 2).IntPower(2));
     184      AssertAreEqualInterval(new AlgebraicInterval(1, 4), new AlgebraicInterval(-2, -1).IntPower(2));
     185      AssertAreEqualInterval(new AlgebraicInterval(0, 4), new AlgebraicInterval(-2, 2).IntPower(2));
     186
     187      AssertAreEqualInterval(new AlgebraicInterval(0, 16), new AlgebraicInterval(-2, 2).Mul(new AlgebraicInterval(2, 2)).IntPower(2));
    186188    }
    187189
     
    190192    [TestProperty("Time", "short")]
    191193    public void TestIntervalSqrtOperator() {
    192       AssertAreEqualInterval(new AlgebraicInterval(1, 2), SquareRoot(new AlgebraicInterval(1, 4)));
    193       AssertAreEqualInterval(new AlgebraicInterval(double.NaN, double.NaN), SquareRoot(new AlgebraicInterval(-4, -1)));
    194     }
    195 
    196     private AlgebraicInterval SquareRoot(AlgebraicInterval algebraicInterval) {
    197       return algebraicInterval.IntRoot(2);
     194      AssertAreEqualInterval(new AlgebraicInterval(1, 2), new AlgebraicInterval(1, 4).IntRoot(2));
     195      AssertAreEqualInterval(new AlgebraicInterval(double.NaN, double.NaN), new AlgebraicInterval(-4, -1).IntRoot(2));
    198196    }
    199197
     
    202200    [TestProperty("Time", "short")]
    203201    public void TestIntervalCubeOperator() {
    204       AssertAreEqualInterval(new AlgebraicInterval(1, 8), Cube(new AlgebraicInterval(1, 2)));
    205       AssertAreEqualInterval(new AlgebraicInterval(-8, -1), Cube(new AlgebraicInterval(-2, -1)));
    206       AssertAreEqualInterval(new AlgebraicInterval(-8, 8), Cube(new AlgebraicInterval(-2, 2)));
    207     }
    208 
    209     private AlgebraicInterval Cube(AlgebraicInterval algebraicInterval) {
    210       return algebraicInterval.IntPower(3);
    211     }
     202      AssertAreEqualInterval(new AlgebraicInterval(1, 8), new AlgebraicInterval(1, 2).IntPower(3));
     203      AssertAreEqualInterval(new AlgebraicInterval(-8, -1), new AlgebraicInterval(-2, -1).IntPower(3));
     204      AssertAreEqualInterval(new AlgebraicInterval(-8, 8), new AlgebraicInterval(-2, 2).IntPower(3));
     205    }
     206
    212207
    213208    [TestMethod]
     
    228223    [TestProperty("Time", "short")]
    229224    public void TestIntervalCbrtOperator() {
    230       AssertAreEqualInterval(new AlgebraicInterval(1, 2), CubicRoot(new AlgebraicInterval(1, 8)));
    231       AssertAreEqualInterval(new AlgebraicInterval(-2, -1), CubicRoot(new AlgebraicInterval(-8, -1)));
    232     }
    233 
    234     private AlgebraicInterval CubicRoot(AlgebraicInterval algebraicInterval) {
    235       return algebraicInterval.IntRoot(3);
     225      AssertAreEqualInterval(new AlgebraicInterval(1, 2), new AlgebraicInterval(1, 8).IntRoot(3));
     226      AssertAreEqualInterval(new AlgebraicInterval(-2, -1), new AlgebraicInterval(-8, -1).IntRoot(3));
    236227    }
    237228  }
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/IntervalCalculationComparison.cs

    r17291 r17303  
    1414    [TestMethod]
    1515    [TestCategory("Problems.DataAnalysis")]
    16     [TestProperty("Time", "short")]
     16    [TestProperty("Time", "long")]
    1717    public void TestIntervalCalculationForRandomExpressions() {
    1818      var grammar = new TypeCoherentExpressionGrammar();
     
    2323      grammar.Symbols.First(s => s is Cube).Enabled = true;
    2424      grammar.Symbols.First(s => s is CubeRoot).Enabled = true;
     25      grammar.Symbols.First(s => s is Sine).Enabled = true;
     26      grammar.Symbols.First(s => s is Cosine).Enabled = true;
     27      grammar.Symbols.First(s => s is Exponential).Enabled = true;
     28      grammar.Symbols.First(s => s is Logarithm).Enabled = true;
     29      grammar.Symbols.First(s => s is Absolute).Enabled = false; // XXX not yet supported by old interval calculator
     30      grammar.Symbols.First(s => s is AnalyticQuotient).Enabled = false; // not yet supported by old interval calculator
    2531
    2632      var varSy = (Variable)grammar.Symbols.First(s => s is Variable);
     
    5157
    5258      var formatter = new InfixExpressionFormatter();
     59      var sb = new StringBuilder();
    5360      foreach (var interval in new[] { posIntervals, negIntervals, fullIntervals, specialIntervals }) {
    5461        int N = 10000;
    55         var sb = new StringBuilder();
    5662        int i = 0;
    5763        while (i < N) {
     
    6167          // Console.WriteLine(formatter.Format(t));
    6268
     69          // all NaN is ok (but don't count NaN expressions)
    6370          if (double.IsNaN(r1.LowerBound) && double.IsNaN(r2.LowerBound) && double.IsNaN(r1.UpperBound) && double.IsNaN(r2.UpperBound)) continue;
    64 
    65           if (!double.IsNaN(r1.LowerBound) && !double.IsNaN(r2.LowerBound))
    66             if ((double.IsPositiveInfinity(r1.LowerBound) && !double.IsPositiveInfinity(r2.LowerBound)) ||
    67               (double.IsNegativeInfinity(r1.LowerBound) && !double.IsNegativeInfinity(r2.LowerBound)) ||
    68                (Math.Abs(r1.LowerBound - r2.LowerBound) > Math.Abs(r1.LowerBound * 1e-4))
    69               ) {
    70               sb.AppendLine($"{r1} <> {r2} for {formatter.Format(t)} x={interval["x"]} y={interval["y"]}");
    71             }
    72           if (!double.IsNaN(r1.UpperBound) && !double.IsNaN(r2.UpperBound))
    73             if ((double.IsPositiveInfinity(r1.UpperBound) && !double.IsPositiveInfinity(r2.UpperBound)) ||
    74               (double.IsNegativeInfinity(r1.UpperBound) && !double.IsNegativeInfinity(r2.UpperBound)) ||
    75                (Math.Abs(r1.UpperBound - r2.UpperBound) > Math.Abs(r1.UpperBound * 1e-4))
    76               ) {
    77               sb.AppendLine($"{r1} <> {r2} for {formatter.Format(t)} x={interval["x"]} y={interval["y"]}");
    78             }
     71          if (r1.LowerBound == r2.LowerBound && r1.UpperBound == r2.UpperBound) {
     72            /* exactly the same value (incl. Inf / -Inf) => ok */
     73          } else if ((Math.Abs(r1.LowerBound - r2.LowerBound) < Math.Max(1e-10, Math.Abs(r1.LowerBound * 1e-4))) &&
     74                     (Math.Abs(r1.UpperBound - r2.UpperBound) < Math.Max(1e-10, Math.Abs(r1.UpperBound * 1e-4)))) {
     75            /* approximately the same value => OK */
     76          } else {
     77            sb.AppendLine($"{r1} <> {r2} for {formatter.Format(t)} x={interval["x"]} y={interval["y"]}");
     78          }
    7979          i++;
    8080        }
    81         if (sb.Length > 0) {
    82           Console.WriteLine(sb.ToString());
    83           Assert.Fail("There were different interval calculation results");
     81      }
     82      if (sb.Length > 0) {
     83        Console.WriteLine(sb.ToString());
     84        Assert.Fail("There were different interval calculation results");
     85      }
     86    }
     87
     88    [TestMethod]
     89    [TestCategory("Problems.DataAnalysis")]
     90    [TestProperty("Time", "short")]
     91    public void TestExampleIntervalExpressions() {
     92      var parser = new InfixExpressionParser();
     93      var eval1 = new IntervalEvaluator();
     94      var eval2 = new IntervalInterpreter();
     95      IDictionary<string, Interval> interval = new Dictionary<string, Interval>() {
     96        { "x", new Interval(1, 2) },
     97        { "y", new Interval(0, 1) },
     98        { "z", new Interval(double.NegativeInfinity, double.PositiveInfinity) },
     99      };
     100
     101      var exprs = new string[] {
     102        "CUBE((0.642971622547268*'x')) * (-16.5400720573962)",
     103        "sqr(y / y)", // one interpreter produces [NaN, inf], the other [NaN, 0]
     104        "cuberoot(-x)", // the old interpreter calculates cuberoot incorrectly
     105        "sqr(log(-x))", // Interval: [NaN, NaN] <> Interval (old): [NaN, 0]
     106        "log(1.8*'y' - 1.4*'y')", // Interval: [NaN, 0,587786664902119] <> Interval (old): [0,587786664902119, NaN]
     107        "log(z)", // Interval: [NaN, ∞] <> Interval (old): [∞, NaN]
     108        "sqr(sqrt(-1))" // Interval: [NaN, NaN] <> Interval (old): [NaN, 0]
     109      };
     110
     111      var formatter = new InfixExpressionFormatter();
     112      var sb = new StringBuilder();
     113      foreach (var expr in exprs) {
     114        var t = parser.Parse(expr);
     115
     116        var r1 = eval1.Evaluate(t, interval);
     117        var r2 = eval2.GetSymbolicExpressionTreeInterval(t, interval);
     118        // Console.WriteLine(formatter.Format(t));
     119
     120        // all NaN is ok
     121        if (double.IsNaN(r1.LowerBound) && double.IsNaN(r2.LowerBound) && double.IsNaN(r1.UpperBound) && double.IsNaN(r2.UpperBound)) continue;
     122        if (r1.LowerBound == r2.LowerBound && r1.UpperBound == r2.UpperBound) continue;  // Inf, -Inf and exactly the same value are ok
     123
     124        if ((Math.Abs(r1.LowerBound - r2.LowerBound) < Math.Abs(r1.LowerBound * 1e-4)) &&
     125            (Math.Abs(r1.UpperBound - r2.UpperBound) < Math.Abs(r1.UpperBound * 1e-4))) { /* OK */ } else {
     126          sb.AppendLine($"{r1} <> {r2} for {formatter.Format(t)} x={interval["x"]} y={interval["y"]}");
    84127        }
     128      }
     129      if (sb.Length > 0) {
     130        Console.WriteLine(sb.ToString());
     131        Assert.Fail("There were different interval calculation results");
    85132      }
    86133    }
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/IntervalTest.cs

    r17290 r17303  
    7575      Assert.IsTrue(Interval.Divide(a, c).IsInfiniteOrUndefined);
    7676      Assert.AreEqual<Interval>(Interval.Divide(d, b), new Interval(double.NegativeInfinity, double.PositiveInfinity));
     77
     78      // [0, 1] / [0, 1]
     79      Assert.AreEqual(Interval.Divide(new Interval(0, 1), new Interval(0, 1)), new Interval(1, double.PositiveInfinity)); // returns [NaN, NaN] because of (0 / 0)
    7780    }
    7881
     
    159162    public void TestIntervalCbrtOperator() {
    160163      Assert.AreEqual<Interval>(new Interval(1, 2), Interval.CubicRoot(new Interval(1, 8)));
    161       Assert.AreEqual<Interval>(new Interval(-2, -1), Interval.CubicRoot(new Interval(-8, -1)));
     164      Assert.AreEqual<Interval>(new Interval(-2, -1), Interval.CubicRoot(new Interval(-8, -1))); // XXX should be fixed for old interval calculation
    162165    }
    163166  }
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeInterpreterTest.cs

    r17216 r17303  
    285285      grammar.Symbols.First(s => s is Cube).Enabled = true;
    286286      grammar.Symbols.First(s => s is CubeRoot).Enabled = true;
     287      grammar.Symbols.First(s => s is Exponential).Enabled = true;
     288      grammar.Symbols.First(s => s is Logarithm).Enabled = true;
     289      grammar.Symbols.First(s => s is Sine).Enabled = true;
     290      grammar.Symbols.First(s => s is Cosine).Enabled = true;
     291      grammar.Symbols.First(s => s is Absolute).Enabled = true;
     292      grammar.Symbols.First(s => s is AnalyticQuotient).Enabled = true;
    287293
    288294      var refInterpreter = new SymbolicDataAnalysisExpressionTreeLinearInterpreter();
Note: See TracChangeset for help on using the changeset viewer.