Changeset 17212
- Timestamp:
- 08/13/19 13:41:21 (5 years ago)
- Location:
- branches/2994-AutoDiffForIntervals
- Files:
-
- 1 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Interpreter.cs
r17203 r17212 484 484 [DebuggerBrowsable(DebuggerBrowsableState.Never)] 485 485 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); 486 490 public AlgebraicDouble() { } 487 491 public AlgebraicDouble(double value) { this.Value = value; } … … 497 501 public AlgebraicDouble AssignCos(AlgebraicDouble a) { Value = Math.Cos(a.Value); return this; } 498 502 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 NaN503 public AlgebraicDouble AssignLog(AlgebraicDouble a) { Value = Math.Log(a.Value); return this; } 500 504 public AlgebraicDouble AssignExp(AlgebraicDouble a) { Value = Math.Exp(a.Value); return this; } 501 505 public AlgebraicDouble AssignIntPower(AlgebraicDouble a, int p) { Value = Math.Pow(a.Value, p); return this; } … … 803 807 var v4 = high.Clone().Mul(a.high); 804 808 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 808 824 } 809 825 … … 815 831 816 832 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))); 818 834 } 819 835 … … 821 837 if (a.Contains(0.0)) { 822 838 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 823 855 low = new MultivariateDual<AlgebraicDouble>(double.NegativeInfinity); 824 856 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 } 829 858 } else { 830 859 Mul(new AlgebraicInterval(a.high.Clone().Inv(), a.low.Clone().Inv())); // inverting leads to inverse roles of high and low … … 947 976 low = new MultivariateDual<AlgebraicDouble>(-1.0); // zero gradient 948 977 high = new MultivariateDual<AlgebraicDouble>(1.0); 978 return this; 949 979 } 950 980 … … 1145 1175 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 1146 1176 public MultivariateDual<V> AssignSgn(MultivariateDual<V> a) { v.AssignSgn(a.v); dv = a.dv.Zero; return this; } // sign(f(x))' = 0; 1177 1147 1178 } 1148 1179 } -
branches/2994-AutoDiffForIntervals/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/AutoDiffIntervalTest.cs
r17205 r17212 11 11 private readonly AlgebraicInterval d = new AlgebraicInterval(1, 3); 12 12 private readonly AlgebraicInterval e = new AlgebraicInterval(4, 6); 13 private readonly IntervalEvaluator eval = new 13 private readonly IntervalEvaluator eval = new IntervalEvaluator(); 14 14 15 15 [TestMethod] … … 20 20 21 21 // [-1,1] + [-2,2] = [-3,3] 22 Assert .AreEqual(Add(a, b), new AlgebraicInterval(-3, 3));22 AssertAreEqualInterval(Add(a, b), new AlgebraicInterval(-3, 3)); 23 23 //([-1, 1] + [-2, 2]) + [0, 3] = [-3, 6] 24 Assert .AreEqual(Add(Add(a, b), c), new AlgebraicInterval(-3, 6));24 AssertAreEqualInterval(Add(Add(a, b), c), new AlgebraicInterval(-3, 6)); 25 25 //([-1, 1] + [0, 3]) + [-2, 2] = [-3, 6] 26 Assert.AreEqual(Add(Add(a, c), b), new AlgebraicInterval(-3, 6)); 26 AssertAreEqualInterval(Add(Add(a, c), b), new AlgebraicInterval(-3, 6)); 27 } 28 29 private void AssertAreEqualInterval(AlgebraicInterval a, AlgebraicInterval b) { 30 if (double.IsNaN(a.LowerBound.Value)) { 31 Assert.IsTrue(double.IsNaN(b.LowerBound.Value)); 32 } else { 33 Assert.AreEqual(a.LowerBound.Value.Value, b.LowerBound.Value.Value, 1e-10); 34 } 35 36 if (double.IsNaN(a.UpperBound.Value)) { 37 Assert.IsTrue(double.IsNaN(b.UpperBound.Value)); 38 } else { 39 Assert.AreEqual(a.UpperBound.Value.Value, b.UpperBound.Value.Value, 1e-10); 40 } 27 41 } 28 42 … … 38 52 39 53 //[-1, 1] - [-2, 2] = [-3, 3] 40 Assert .AreEqual(Subtract(a, b), new AlgebraicInterval(-3, 3));54 AssertAreEqualInterval(Subtract(a, b), new AlgebraicInterval(-3, 3)); 41 55 //([-1, 1] - [-2, 2]) - [0, 3] = [-6, 3] 42 Assert .AreEqual(Subtract(Subtract(a, b), c), new AlgebraicInterval(-6, 3));56 AssertAreEqualInterval(Subtract(Subtract(a, b), c), new AlgebraicInterval(-6, 3)); 43 57 //([-1, 1] - [0, 3]) - [-2, 2] = [-6, 3] 44 Assert .AreEqual(Subtract(Subtract(a, c), b), new AlgebraicInterval(-6, 3));58 AssertAreEqualInterval(Subtract(Subtract(a, c), b), new AlgebraicInterval(-6, 3)); 45 59 } 46 60 … … 56 70 57 71 //[-1, 1] * [-2, 2] = [-2, 2] 58 Assert .AreEqual(Multiply(a, b), new AlgebraicInterval(-2, 2));72 AssertAreEqualInterval(Multiply(a, b), new AlgebraicInterval(-2, 2)); 59 73 //([-1, 1] * [-2, 2]) * [0, 3] = [-6, 6] 60 Assert .AreEqual(Multiply(Multiply(a, b), c), new AlgebraicInterval(-6, 6));74 AssertAreEqualInterval(Multiply(Multiply(a, b), c), new AlgebraicInterval(-6, 6)); 61 75 //([-1, 1] * [0, 3]) * [-2, 2] = [-6, 6] 62 Assert .AreEqual(Multiply(Multiply(a, c), b), new AlgebraicInterval(-6, 6));76 AssertAreEqualInterval(Multiply(Multiply(a, c), b), new AlgebraicInterval(-6, 6)); 63 77 64 78 // [-2, 0] * [-2, 0] = [0, 4] 65 Assert .AreEqual(new AlgebraicInterval(0, 4), Multiply(new AlgebraicInterval(-2, 0), new AlgebraicInterval(-2, 0)));79 AssertAreEqualInterval(new AlgebraicInterval(0, 4), Multiply(new AlgebraicInterval(-2, 0), new AlgebraicInterval(-2, 0))); 66 80 } 67 81 … … 77 91 78 92 //[4, 6] / [1, 3] = [4/3, 6] 79 Assert .AreEqual(Divide(e, d), new AlgebraicInterval(4.0 / 3.0, 6));93 AssertAreEqualInterval(Divide(e, d), new AlgebraicInterval(4.0 / 3.0, 6)); 80 94 //([4, 6] / [1, 3]) / [1, 3] = [4/9, 6] 81 Assert .AreEqual(Divide(Divide(e, d), d), new AlgebraicInterval(4.0 / 9.0, 6));95 AssertAreEqualInterval(Divide(Divide(e, d), d), new AlgebraicInterval(4.0 / 9.0, 6)); 82 96 //[4, 6] / [0, 3] = [4/3, +Inf] 83 Assert .AreEqual(Divide(e, c), new AlgebraicInterval(4.0 / 3.0, double.PositiveInfinity));97 AssertAreEqualInterval(Divide(e, c), new AlgebraicInterval(4.0 / 3.0, double.PositiveInfinity)); 84 98 //[-1, 1] / [0, 3] = [+Inf, -Inf] 85 Assert.AreEqual(Divide(a, c), new AlgebraicInterval(double.NegativeInfinity, double.PositiveInfinity)); 86 //Devision by 0 ==> IsInfiniteOrUndefined == true 87 88 //Devision by 0 ==> IsInfiniteOrUndefined == true 89 90 Assert.AreEqual(Divide(d, b), new AlgebraicInterval(double.NegativeInfinity, double.PositiveInfinity)); 99 AssertAreEqualInterval(Divide(a, c), new AlgebraicInterval(double.NegativeInfinity, double.PositiveInfinity)); 100 101 //Division by 0 ==> IsInfiniteOrUndefined == true 102 AssertAreEqualInterval(Divide(d, b), new AlgebraicInterval(double.NegativeInfinity, double.PositiveInfinity)); 91 103 } 92 104 … … 101 113 //sine depends on interval 102 114 //sin([0, 2*pi]) = [-1, 1] 103 Assert .AreEqual(Sine(new AlgebraicInterval(0, 2 * Math.PI)), new AlgebraicInterval(-1, 1));115 AssertAreEqualInterval(Sine(new AlgebraicInterval(0, 2 * Math.PI)), new AlgebraicInterval(-1, 1)); 104 116 //sin([-pi/2, pi/2]) = [sin(-pi/2), sin(pi/2)] 105 Assert .AreEqual(Sine(new AlgebraicInterval(-1 * Math.PI / 2, Math.PI / 2)), new AlgebraicInterval(-1, 1));117 AssertAreEqualInterval(Sine(new AlgebraicInterval(-1 * Math.PI / 2, Math.PI / 2)), new AlgebraicInterval(-1, 1)); 106 118 //sin([0, pi/2]) = [sin(0), sin(pi/2)] 107 Assert .AreEqual(Sine(new AlgebraicInterval(0, Math.PI / 2)), new AlgebraicInterval(0, 1));119 AssertAreEqualInterval(Sine(new AlgebraicInterval(0, Math.PI / 2)), new AlgebraicInterval(0, 1)); 108 120 //sin([pi, 3*pi/2]) = [sin(pi), sin(3*pi/2)] 109 Assert .AreEqual(Sine(new AlgebraicInterval(Math.PI, 3 * Math.PI / 2)), new AlgebraicInterval(-1, 0));110 Assert .AreEqual(Sine(new AlgebraicInterval(1, 2)), new AlgebraicInterval(Math.Min(Math.Sin(1), Math.Sin(2)), 1));111 Assert .AreEqual(Sine(new AlgebraicInterval(1, 3)), new AlgebraicInterval(Math.Min(Math.Sin(1), Math.Sin(3)), 1));112 Assert .AreEqual(Sine(new AlgebraicInterval(Math.PI, 5 * Math.PI / 2)), new AlgebraicInterval(-1, 1));121 AssertAreEqualInterval(Sine(new AlgebraicInterval(Math.PI, 3 * Math.PI / 2)), new AlgebraicInterval(-1, 0)); 122 AssertAreEqualInterval(Sine(new AlgebraicInterval(1, 2)), new AlgebraicInterval(Math.Min(Math.Sin(1), Math.Sin(2)), 1)); 123 AssertAreEqualInterval(Sine(new AlgebraicInterval(1, 3)), new AlgebraicInterval(Math.Min(Math.Sin(1), Math.Sin(3)), 1)); 124 AssertAreEqualInterval(Sine(new AlgebraicInterval(Math.PI, 5 * Math.PI / 2)), new AlgebraicInterval(-1, 1)); 113 125 } 114 126 … … 122 134 public void TestIntervalCosineOperator() { 123 135 //Cosine uses sine Sine(Subtract(a, new AlgebraicInterval(Math.PI / 2, Math.PI / 2))); 124 Assert .AreEqual(Cosine(new AlgebraicInterval(0, 2 * Math.PI)), new AlgebraicInterval(-1, 1));125 Assert .AreEqual(new AlgebraicInterval(-1, 1), Cosine(new AlgebraicInterval(Math.PI, 4 * Math.PI / 2)));136 AssertAreEqualInterval(Cosine(new AlgebraicInterval(0, 2 * Math.PI)), new AlgebraicInterval(-1, 1)); 137 AssertAreEqualInterval(new AlgebraicInterval(-1, 1), Cosine(new AlgebraicInterval(Math.PI, 4 * Math.PI / 2))); 126 138 } 127 139 … … 135 147 public void TestIntervalLogOperator() { 136 148 //Log([3, 5]) = [log(3), log(5)] 137 Assert .AreEqual(new AlgebraicInterval(Math.Log(3), Math.Log(5)), Logarithm(new AlgebraicInterval(3, 5)));149 AssertAreEqualInterval(new AlgebraicInterval(Math.Log(3), Math.Log(5)), Logarithm(new AlgebraicInterval(3, 5))); 138 150 //Log([0.5, 1]) = [log(0.5), log(1)] 139 Assert .AreEqual(new AlgebraicInterval(Math.Log(0.5), 0), Logarithm(new AlgebraicInterval(0.5, 1)));151 AssertAreEqualInterval(new AlgebraicInterval(Math.Log(0.5), 0), Logarithm(new AlgebraicInterval(0.5, 1))); 140 152 //Log([-1, 5]) = [NaN, log(5)] 141 153 var result = Logarithm(new AlgebraicInterval(-1, 5)); 142 Assert .AreEqual(new AlgebraicInterval(double.NaN, Math.Log(5)),result);143 154 AssertAreEqualInterval(new AlgebraicInterval(double.NaN, Math.Log(5)), result); 155 144 156 } 145 157 … … 153 165 public void TestIntervalExpOperator() { 154 166 //Exp([0, 1]) = [exp(0), exp(1)] 155 Assert .AreEqual(new AlgebraicInterval(1, Math.Exp(1)), Exponential(new AlgebraicInterval(0, 1)));167 AssertAreEqualInterval(new AlgebraicInterval(1, Math.Exp(1)), Exponential(new AlgebraicInterval(0, 1))); 156 168 } 157 169 … … 164 176 [TestProperty("Time", "short")] 165 177 public void TestIntervalSqrOperator() { 166 Assert .AreEqual(new AlgebraicInterval(1, 4), Square(new AlgebraicInterval(1, 2)));167 Assert .AreEqual(new AlgebraicInterval(1, 4), Square(new AlgebraicInterval(-2, -1)));168 Assert .AreEqual(new AlgebraicInterval(0, 4), Square(new AlgebraicInterval(-2, 2)));178 AssertAreEqualInterval(new AlgebraicInterval(1, 4), Square(new AlgebraicInterval(1, 2))); 179 AssertAreEqualInterval(new AlgebraicInterval(1, 4), Square(new AlgebraicInterval(-2, -1))); 180 AssertAreEqualInterval(new AlgebraicInterval(0, 4), Square(new AlgebraicInterval(-2, 2))); 169 181 } 170 182 … … 177 189 [TestProperty("Time", "short")] 178 190 public void TestIntervalSqrtOperator() { 179 Assert .AreEqual(new AlgebraicInterval(1, 2), SquareRoot(new AlgebraicInterval(1, 4)));180 Assert .AreEqual(new AlgebraicInterval(double.NaN, double.NaN), SquareRoot(new AlgebraicInterval(-4, -1)));191 AssertAreEqualInterval(new AlgebraicInterval(1, 2), SquareRoot(new AlgebraicInterval(1, 4))); 192 AssertAreEqualInterval(new AlgebraicInterval(double.NaN, double.NaN), SquareRoot(new AlgebraicInterval(-4, -1))); 181 193 } 182 194 … … 189 201 [TestProperty("Time", "short")] 190 202 public void TestIntervalCubeOperator() { 191 Assert .AreEqual(new AlgebraicInterval(1, 8), Cube(new AlgebraicInterval(1, 2)));192 Assert .AreEqual(new AlgebraicInterval(-8, -1), Cube(new AlgebraicInterval(-2, -1)));193 Assert .AreEqual(new AlgebraicInterval(-8, 8), Cube(new AlgebraicInterval(-2, 2)));203 AssertAreEqualInterval(new AlgebraicInterval(1, 8), Cube(new AlgebraicInterval(1, 2))); 204 AssertAreEqualInterval(new AlgebraicInterval(-8, -1), Cube(new AlgebraicInterval(-2, -1))); 205 AssertAreEqualInterval(new AlgebraicInterval(-8, 8), Cube(new AlgebraicInterval(-2, 2))); 194 206 } 195 207 … … 202 214 [TestProperty("Time", "short")] 203 215 public void TestIntervalCbrtOperator() { 204 Assert .AreEqual(new AlgebraicInterval(1, 2), CubicRoot(new AlgebraicInterval(1, 8)));205 Assert .AreEqual(new AlgebraicInterval(double.NaN, double.NaN), CubicRoot(new AlgebraicInterval(-8, -1)));216 AssertAreEqualInterval(new AlgebraicInterval(1, 2), CubicRoot(new AlgebraicInterval(1, 8))); 217 AssertAreEqualInterval(new AlgebraicInterval(double.NaN, double.NaN), CubicRoot(new AlgebraicInterval(-8, -1))); 206 218 } 207 219 -
branches/2994-AutoDiffForIntervals/HeuristicLab.Tests/HeuristicLab.Tests.csproj
r17205 r17212 112 112 <HintPath>..\bin\ALGLIB-3.7.0.dll</HintPath> 113 113 <Private>False</Private> 114 </Reference> 115 <Reference Include="HEAL.Attic, Version=1.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL"> 116 <SpecificVersion>False</SpecificVersion> 117 <HintPath>..\bin\HEAL.Attic.dll</HintPath> 114 118 </Reference> 115 119 <Reference Include="HeuristicLab.Algorithms.ALPS-3.3"> … … 605 609 <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\DeriveTest.cs" /> 606 610 <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\InfixExpressionParserTest.cs" /> 611 <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\AutoDiffIntervalInterpreterTest.cs" /> 607 612 <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\IntervalInterpreterTest.cs" /> 608 613 <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\SymbolicExpressionTreeBottomUpSimilarityCalculatorTest.cs" />
Note: See TracChangeset
for help on using the changeset viewer.