Changeset 17303
- Timestamp:
- 10/03/19 12:30:19 (5 years ago)
- 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 182 182 <Compile Include="Interpreter\VectorAutoDiffEvaluator.cs" /> 183 183 <Compile Include="Interpreter\VectorEvaluator.cs" /> 184 <Compile Include="Interpreter\VectorOfAlgebraic.cs" /> 184 185 <Compile Include="Selectors\DiversitySelector.cs" /> 185 186 <Compile Include="SymbolicDataAnalysisExpressionTreeAverageSimilarityCalculator.cs" /> -
branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Algebraic.cs
r17295 r17303 12 12 public static T IntRoot<T>(this T a, int r) where T : IAlgebraicType<T> { a.AssignIntRoot(a.Clone(), r); return a; } 13 13 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 17 14 // public static T Max<T>(T a, T b) where T : IAlgebraicType<T> { 18 15 // // ((a + b) + abs(b - a)) / 2 -
branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicDouble.cs
r17298 r17303 5 5 // algebraic type wrapper for a double value 6 6 [DebuggerDisplay("{Value}")] 7 public sealed class AlgebraicDouble : I AlgebraicType<AlgebraicDouble> {7 public sealed class AlgebraicDouble : IComparableAlgebraicType<AlgebraicDouble> { 8 8 public static implicit operator AlgebraicDouble(double value) { return new AlgebraicDouble(value); } 9 9 public static implicit operator double(AlgebraicDouble value) { return value.Value; } … … 35 35 public AlgebraicDouble AssignIntPower(AlgebraicDouble a, int p) { Value = Math.Pow(a.Value, p); return this; } 36 36 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; } 39 39 public AlgebraicDouble AssignAbs(AlgebraicDouble a) { Value = Math.Abs(a.Value); return this; } 40 40 public AlgebraicDouble AssignSgn(AlgebraicDouble a) { Value = double.IsNaN(a.Value) ? double.NaN : Math.Sign(a.Value); return this; } … … 51 51 return Value.ToString(); 52 52 } 53 54 public int CompareTo(AlgebraicDouble other) { 55 return Value.CompareTo(other.Value); 56 } 53 57 } 54 58 } -
branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicDoubleVector.cs
r17298 r17303 6 6 // a simple vector as an algebraic type 7 7 [DebuggerDisplay("DoubleVector(len={Length}): {string.}")] 8 [Obsolete("Use VectorOfAlgebraic instead")] 8 9 public class AlgebraicDoubleVector : IAlgebraicType<AlgebraicDoubleVector> { 9 10 private double[] arr; … … 40 41 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; } 41 42 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; } 44 45 public AlgebraicDoubleVector AssignAbs(AlgebraicDoubleVector a) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Abs(a.arr[i]); } return this; } 45 46 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 47 47 var v4 = high.Clone().Mul(a.high); 48 48 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; 61 52 } 62 53 … … 133 124 if (a.Contains(0.0)) { 134 125 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)); 141 129 } 142 130 } else { … … 148 136 var lowPower = a.low.IntPower(p); 149 137 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); 152 140 } 153 141 } … … 217 205 218 206 // 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 221 208 222 209 // override min and max if necessary … … 260 247 public AlgebraicInterval AssignAbs(AlgebraicInterval a) { 261 248 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 { 262 252 var abslow = a.low.Clone().Abs(); 263 253 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); 271 255 } 272 256 return this; … … 279 263 } 280 264 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 292 304 } 293 305 } -
branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicSparseVector.cs
r17298 r17303 109 109 } 110 110 111 public AlgebraicSparseVector<K, T> AssignMin(AlgebraicSparseVector<K, T> other) {112 // assumes that keys without a matching key in other are zero and vice versa113 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 else118 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 versa125 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 else130 elems.Add(kvp.Key, kvp.Value.Zero.AssignMax(kvp.Value));131 }132 return this;133 }134 135 136 111 public AlgebraicSparseVector<K, T> Clone() { 137 112 return new AlgebraicSparseVector<K, T>(this); -
branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Dual.cs
r17295 r17303 4 4 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 5 5 public class Dual<V> : IAlgebraicType<Dual<V>> 6 where V : I AlgebraicType<V> {6 where V : IComparableAlgebraicType<V> { 7 7 [DebuggerBrowsable(DebuggerBrowsableState.Never)] 8 8 private V v; … … 54 54 55 55 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; 57 61 } 58 62 59 63 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; 61 69 } 62 70 } -
branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IAlgebraicType.cs
r17295 r17303 1 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 1 using System; 2 3 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 2 4 public interface IAlgebraicType<T> { 3 5 T Zero { get; } // Zero and One must create new objects … … 21 23 T AssignIntRoot(T a, int r); 22 24 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) 25 27 T Clone(); 26 28 } 29 30 public interface IComparableAlgebraicType<T> : IAlgebraicType<T>, IComparable<T> { 31 32 } 27 33 } -
branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/MultivariateDual.cs
r17297 r17303 17 17 public AlgebraicSparseVector<object, V> Gradient => dv; // <key,value> partial derivative identified via the key 18 18 19 19 20 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 } 20 29 21 30 /// <summary> … … 83 92 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 84 93 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 }93 94 } 94 95 } -
branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/VectorAutoDiffEvaluator.cs
r17296 r17303 5 5 6 6 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 7 public sealed class VectorAutoDiffEvaluator : InterpreterBase< MultivariateDual<AlgebraicDoubleVector>> {7 public sealed class VectorAutoDiffEvaluator : InterpreterBase<VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>> { 8 8 private const int BATCHSIZE = 128; 9 9 [ThreadStatic] … … 57 57 for (rowIndex = 0; rowIndex < roundedTotal; rowIndex += BATCHSIZE) { 58 58 Evaluate(code); 59 code[0].value.Value.CopyTo(fi, rowIndex, BATCHSIZE);60 59 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 } 68 73 } 69 74 } … … 72 77 if (remainingRows > 0) { 73 78 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; 75 83 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 } 82 91 } 92 } 83 93 } 84 94 } 85 95 86 96 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? 89 98 } 90 99 91 100 protected override void InitializeTerminalInstruction(ref Instruction instruction, ConstantTreeNode constant) { 92 var g_arr = new double[BATCHSIZE];93 101 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 } 97 106 } 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 } 99 111 } 100 112 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) 103 114 } 104 115 … … 115 126 if (node2paramIdx.ContainsKey(variable)) { 116 127 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 } 120 132 } else { 121 133 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 } 123 138 } 124 139 125 instruction.dblVal = variable.Weight; 140 instruction.dblVal = variable.Weight; 126 141 instruction.data = new object[] { data, paramIdx }; 127 142 } … … 131 146 var data = (double[])((object[])a.data)[0]; 132 147 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 } 135 151 136 152 if (paramIdx >= 0) { 137 153 // update gradient with variable values 138 var g = a.value.Gradient.Elements[paramIdx];139 154 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]]); 141 156 } 142 157 } -
branches/2994-AutoDiffForIntervals/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/AutoDiffIntervalTest.cs
r17299 r17303 102 102 //Division by 0 ==> IsInfiniteOrUndefined == true 103 103 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 104 108 } 105 109 … … 177 181 [TestProperty("Time", "short")] 178 182 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)); 186 188 } 187 189 … … 190 192 [TestProperty("Time", "short")] 191 193 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)); 198 196 } 199 197 … … 202 200 [TestProperty("Time", "short")] 203 201 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 212 207 213 208 [TestMethod] … … 228 223 [TestProperty("Time", "short")] 229 224 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)); 236 227 } 237 228 } -
branches/2994-AutoDiffForIntervals/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/IntervalCalculationComparison.cs
r17291 r17303 14 14 [TestMethod] 15 15 [TestCategory("Problems.DataAnalysis")] 16 [TestProperty("Time", " short")]16 [TestProperty("Time", "long")] 17 17 public void TestIntervalCalculationForRandomExpressions() { 18 18 var grammar = new TypeCoherentExpressionGrammar(); … … 23 23 grammar.Symbols.First(s => s is Cube).Enabled = true; 24 24 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 25 31 26 32 var varSy = (Variable)grammar.Symbols.First(s => s is Variable); … … 51 57 52 58 var formatter = new InfixExpressionFormatter(); 59 var sb = new StringBuilder(); 53 60 foreach (var interval in new[] { posIntervals, negIntervals, fullIntervals, specialIntervals }) { 54 61 int N = 10000; 55 var sb = new StringBuilder();56 62 int i = 0; 57 63 while (i < N) { … … 61 67 // Console.WriteLine(formatter.Format(t)); 62 68 69 // all NaN is ok (but don't count NaN expressions) 63 70 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 } 79 79 i++; 80 80 } 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"]}"); 84 127 } 128 } 129 if (sb.Length > 0) { 130 Console.WriteLine(sb.ToString()); 131 Assert.Fail("There were different interval calculation results"); 85 132 } 86 133 } -
branches/2994-AutoDiffForIntervals/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/IntervalTest.cs
r17290 r17303 75 75 Assert.IsTrue(Interval.Divide(a, c).IsInfiniteOrUndefined); 76 76 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) 77 80 } 78 81 … … 159 162 public void TestIntervalCbrtOperator() { 160 163 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 162 165 } 163 166 } -
branches/2994-AutoDiffForIntervals/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeInterpreterTest.cs
r17216 r17303 285 285 grammar.Symbols.First(s => s is Cube).Enabled = true; 286 286 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; 287 293 288 294 var refInterpreter = new SymbolicDataAnalysisExpressionTreeLinearInterpreter();
Note: See TracChangeset
for help on using the changeset viewer.