Changeset 17350
Legend:
- Unmodified
- Added
- Removed
-
trunk/HeuristicLab.Common/3.3/DoubleExtensions.cs
r17180 r17350 23 23 namespace HeuristicLab.Common { 24 24 public static class DoubleExtensions { 25 /// <summary> 26 /// Compares the similarity of value x and value y with a precision of 1.0E-12. 27 /// </summary> 28 /// <param name="x">First double value to be checked</param> 29 /// <param name="y">Second double value to compare with</param> 30 /// <returns></returns> 25 31 public static bool IsAlmost(this double x, double y) { 32 var epsilon = 1.0E-12; 33 return IsAlmost(x, y, epsilon); 34 } 35 36 /// <summary> 37 /// Compares the similarity of value x and value y with a given precision (epsilon). 38 /// </summary> 39 /// <param name="x">First double value to be checked</param> 40 /// <param name="y">Second double value to compare with</param> 41 /// <param name="epsilon">Error term to specify the precision</param> 42 /// <returns></returns> 43 public static bool IsAlmost(this double x, double y, double epsilon) { 26 44 if (double.IsInfinity(x)) { 27 45 if (x > 0) return double.IsPositiveInfinity(y); 28 46 else return double.IsNegativeInfinity(y); 29 47 } else { 30 return Math.Abs(x - y) < 1.0E-12;48 return Math.Abs(x - y) < epsilon; 31 49 } 32 50 } -
trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval.cs
r17348 r17350 37 37 protected Interval(StorableConstructorFlag _) { } 38 38 39 /// <summary> 40 /// Creates an interval with given bounds, where lower bound must be smaller than 41 /// the upper bound. Floating point precision errors trough calculations are fixed by, 42 /// checking if the intervals are almost the same (E-12). If this is the case, the bounds 43 /// will be set to the bound closer to zero. 44 /// </summary> 45 /// <param name="lowerBound">Lower bound of the interval</param> 46 /// <param name="upperBound">Upper bound of the interval</param> 39 47 public Interval(double lowerBound, double upperBound) { 48 if (lowerBound.IsAlmost(upperBound)) { 49 //If the bounds go over zero 50 if (lowerBound <= 0 && upperBound >= 0) { 51 lowerBound = 0.0; 52 upperBound = 0.0; 53 //Interval is negative 54 } else if (upperBound < 0) { 55 lowerBound = upperBound; 56 //Interval is positive 57 } else { 58 upperBound = lowerBound; 59 } 60 } 61 40 62 if (lowerBound > upperBound) 41 63 throw new ArgumentException("LowerBound must be smaller than UpperBound."); … … 58 80 double.IsNaN(LowerBound) || double.IsNaN(UpperBound); 59 81 } 82 } 83 84 /// <summary> 85 /// True if the interval is positive without zero 86 /// </summary> 87 public bool IsPositive { 88 get => LowerBound > 0.0; 89 } 90 91 /// <summary> 92 /// True if the interval is negative without zero 93 /// </summary> 94 public bool IsNegative { 95 get => UpperBound < 0.0; 60 96 } 61 97 … … 128 164 } 129 165 130 // mkommend:Division by intervals containing 0 is implemented as defined in166 //Division by intervals containing 0 is implemented as defined in 131 167 //http://en.wikipedia.org/wiki/Interval_arithmetic 132 168 public static Interval Divide(Interval a, Interval b) { … … 171 207 public static Interval Tangens(Interval a) { 172 208 return Interval.Divide(Interval.Sine(a), Interval.Cosine(a)); 173 } 209 } 174 210 public static Interval HyperbolicTangent(Interval a) { 175 211 return new Interval(Math.Tanh(a.LowerBound), Math.Tanh(a.UpperBound)); … … 206 242 if (a.UpperBound <= 0) return new Interval(a.UpperBound * a.UpperBound, a.LowerBound * a.LowerBound); // interval is negative 207 243 else if (a.LowerBound >= 0) return new Interval(a.LowerBound * a.LowerBound, a.UpperBound * a.UpperBound); // interval is positive 208 else return new Interval(0, Math.Max(a.LowerBound *a.LowerBound, a.UpperBound*a.UpperBound)); // interval goes over zero244 else return new Interval(0, Math.Max(a.LowerBound * a.LowerBound, a.UpperBound * a.UpperBound)); // interval goes over zero 209 245 } 210 246 … … 235 271 var absLower = Math.Abs(a.LowerBound); 236 272 var absUpper = Math.Abs(a.UpperBound); 237 return new Interval(Math.Min(absLower, absUpper), Math.Max(absLower, absUpper)); 273 var min = Math.Min(absLower, absUpper); 274 var max = Math.Max(absLower, absUpper); 275 276 if (a.Contains(0.0)) { 277 min = 0.0; 278 } 279 280 return new Interval(min, max); 238 281 } 239 282 240 283 public static Interval AnalyticalQuotient(Interval a, Interval b) { 241 if (b.LowerBound <= 0 && b.UpperBound >= 0) //Second interval goes over zero or is zero 242 return new Interval(a.LowerBound, a.UpperBound); 243 244 var values = new List<double> { 245 a.LowerBound / Math.Sqrt(Math.Pow(b.LowerBound, 2) + 1), 246 a.LowerBound / Math.Sqrt(Math.Pow(b.UpperBound, 2) + 1), 247 a.UpperBound / Math.Sqrt(Math.Pow(b.LowerBound, 2) + 1), 248 a.UpperBound / Math.Sqrt(Math.Pow(b.UpperBound, 2) + 1) 249 }; 250 251 return new Interval(values.Min(), values.Max()); 284 var dividend = a; 285 var divisor = Add(Square(b), new Interval(1.0, 1.0)); 286 divisor = SquareRoot(divisor); 287 288 var quotient = Divide(dividend, divisor); 289 return quotient; 252 290 } 253 291 #endregion -
trunk/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/IntervalTest.cs
r17348 r17350 14 14 [TestCategory("Problems.DataAnalysis")] 15 15 [TestProperty("Time", "short")] 16 public void TestIntervalAddOperation() {16 public void AddIntervalTest() { 17 17 //add [x1,x2] + [y1,y2] = [x1 + y1,x2 + y2] 18 18 … … 28 28 [TestCategory("Problems.DataAnalysis")] 29 29 [TestProperty("Time", "short")] 30 public void TestIntervalSubOperation() {30 public void SubtractIntervalTest() { 31 31 //subtract [x1,x2] − [y1,y2] = [x1 − y2,x2 − y1] 32 32 … … 42 42 [TestCategory("Problems.DataAnalysis")] 43 43 [TestProperty("Time", "short")] 44 public void TestIntervalMutlipyOperation() {44 public void MultiplyIntervalTest() { 45 45 //multiply [x1,x2] * [y1,y2] = [min(x1*y1,x1*y2,x2*y1,x2*y2),max(x1*y1,x1*y2,x2*y1,x2*y2)] 46 46 … … 59 59 [TestCategory("Problems.DataAnalysis")] 60 60 [TestProperty("Time", "short")] 61 public void TestIntervalDivideOperation() {61 public void DivideIntervalTest() { 62 62 //divide [x1, x2] / [y1, y2] = [x1, x2] * (1/[y1, y2]), where 1 / [y1,y2] = [1 / y2,1 / y1] if 0 not in [y_1, y_2]. 63 63 … … 80 80 [TestCategory("Problems.DataAnalysis")] 81 81 [TestProperty("Time", "short")] 82 public void TestIntervalSineOperator() {82 public void SineIntervalTest() { 83 83 //sine depends on interval 84 84 //sin([0, 2*pi]) = [-1, 1] … … 98 98 [TestCategory("Problems.DataAnalysis")] 99 99 [TestProperty("Time", "short")] 100 public void TestIntervalCosineOperator() {100 public void CosineIntervalTest() { 101 101 //Cosine uses sine Interval.Sine(Interval.Subtract(a, new Interval(Math.PI / 2, Math.PI / 2))); 102 102 Assert.AreEqual<Interval>(Interval.Cosine(new Interval(0, 2 * Math.PI)), new Interval(-1, 1)); … … 107 107 [TestCategory("Problems.DataAnalysis")] 108 108 [TestProperty("Time", "short")] 109 public void TestIntervalLogOperator() {109 public void LogIntervalTest() { 110 110 //Log([3, 5]) = [log(3), log(5)] 111 111 Assert.AreEqual<Interval>(new Interval(Math.Log(3), Math.Log(5)), Interval.Logarithm(new Interval(3, 5))); … … 122 122 [TestCategory("Problems.DataAnalysis")] 123 123 [TestProperty("Time", "short")] 124 public void TestIntervalExpOperator() {124 public void ExponentialIntervalTest() { 125 125 //Exp([0, 1]) = [exp(0), exp(1)] 126 126 Assert.AreEqual<Interval>(new Interval(1, Math.Exp(1)), Interval.Exponential(new Interval(0, 1))); … … 131 131 [TestCategory("Problems.DataAnalysis")] 132 132 [TestProperty("Time", "short")] 133 public void TestIntervalSqrOperator() {133 public void SquareIntervalTest() { 134 134 Assert.AreEqual<Interval>(new Interval(1, 4), Interval.Square(new Interval(1, 2))); 135 135 Assert.AreEqual<Interval>(new Interval(1, 4), Interval.Square(new Interval(-2, -1))); … … 140 140 [TestCategory("Problems.DataAnalysis")] 141 141 [TestProperty("Time", "short")] 142 public void TestIntervalSqrtOperator() {142 public void SquarerootIntervalTest() { 143 143 Assert.AreEqual<Interval>(new Interval(1, 2), Interval.SquareRoot(new Interval(1, 4))); 144 144 Assert.AreEqual<Interval>(new Interval(double.NaN, double.NaN), Interval.SquareRoot(new Interval(-4, -1))); … … 148 148 [TestCategory("Problems.DataAnalysis")] 149 149 [TestProperty("Time", "short")] 150 public void TestIntervalCubeOperator() {150 public void CubeIntervalTest() { 151 151 Assert.AreEqual<Interval>(new Interval(1, 8), Interval.Cube(new Interval(1, 2))); 152 152 Assert.AreEqual<Interval>(new Interval(-8, -1), Interval.Cube(new Interval(-2, -1))); … … 157 157 [TestCategory("Problems.DataAnalysis")] 158 158 [TestProperty("Time", "short")] 159 public void TestIntervalCbrtOperator() {159 public void CubeRootIntervalTest() { 160 160 Assert.AreEqual<Interval>(new Interval(1, 2), Interval.CubicRoot(new Interval(1, 8))); 161 161 Assert.AreEqual<Interval>(new Interval(-2, -2), Interval.CubicRoot(new Interval(-8, -8))); … … 170 170 [TestCategory("Problems.DataAnalysis")] 171 171 [TestProperty("Time", "short")] 172 public void TestIntervalAbsoluteOperator() { 173 Assert.AreEqual(new Interval(2, 2), Interval.Absolute(new Interval(-2, -2))); 174 Assert.AreEqual(new Interval(5, 5), Interval.Absolute(new Interval(5, 5))); 175 Assert.AreEqual(new Interval(2, 8), Interval.Absolute(new Interval(2, 8))); 176 Assert.AreEqual(new Interval(5, 14), Interval.Absolute(new Interval(-14, -5))); 177 Assert.AreEqual(new Interval(2, 7), Interval.Absolute(new Interval(-2, 7))); 178 Assert.AreEqual(new Interval(2, 22), Interval.Absolute(new Interval(-22, -2))); 179 Assert.AreEqual(new Interval(6, 22), Interval.Absolute(new Interval(-22, 6))); 180 Assert.AreEqual(new Interval(0, 0), Interval.Absolute(new Interval(0, 0))); 181 Assert.AreEqual(new Interval(0, 2), Interval.Absolute(new Interval(-2, 0))); 182 Assert.AreEqual(new Interval(0, 2), Interval.Absolute(new Interval(0, 2))); 183 } 184 185 [TestMethod] 186 [TestCategory("Problems.DataAnalysis")] 187 [TestProperty("Time", "short")] 188 public void TestIntervalAnalyticalQuotient() { 172 public void AbsoluteIntervalTest() { 173 Assert.AreEqual(new Interval(2, 5), Interval.Absolute(new Interval(-5, -2))); 174 Assert.AreEqual(new Interval(2, 5), Interval.Absolute(new Interval(2, 5))); 175 Assert.AreEqual(new Interval(0, 3), Interval.Absolute(new Interval(-3, 0))); 176 Assert.AreEqual(new Interval(0, 5), Interval.Absolute(new Interval(0, 5))); 177 Assert.AreEqual(new Interval(0, 5), Interval.Absolute(new Interval(-2, 5))); 178 } 179 180 [TestMethod] 181 [TestCategory("Problems.DataAnalysis")] 182 [TestProperty("Time", "short")] 183 public void AnalyticalQuotientIntervalTest() { 184 //Analytical Quotient ==> a / sqrt(b^2 + 1) 185 var aPos = new Interval(3, 5); 186 var aZero = new Interval(-3, 5); 187 var aNeg = new Interval(-5, -3); 188 189 var bPos = new Interval(2, 4); 190 var bZero = new Interval(-2, 4); 191 var bNeg = new Interval(-4, -2); 192 189 193 //Second interval goes over zero 190 Assert.AreEqual(new Interval(-4, 2), Interval.AnalyticalQuotient(new Interval(-4, 2), new Interval(0, 5))); 191 Assert.AreEqual(new Interval(-4, 2), Interval.AnalyticalQuotient(new Interval(-4, 2), new Interval(-4, 0))); 192 Assert.AreEqual(new Interval(-4, 2), Interval.AnalyticalQuotient(new Interval(-4, 2), new Interval(-2, 4))); 193 Assert.AreEqual(new Interval(-4, -2), Interval.AnalyticalQuotient(new Interval(-4, -2), new Interval(0, 5))); 194 Assert.AreEqual(new Interval(-4, -2), Interval.AnalyticalQuotient(new Interval(-4, -2), new Interval(-4, 0))); 195 Assert.AreEqual(new Interval(-4, -2), Interval.AnalyticalQuotient(new Interval(-4, -2), new Interval(-2, 4))); 196 Assert.AreEqual(new Interval(3, 7), Interval.AnalyticalQuotient(new Interval(3, 7), new Interval(0, 5))); 197 Assert.AreEqual(new Interval(3, 7), Interval.AnalyticalQuotient(new Interval(3, 7), new Interval(-4, 0))); 198 Assert.AreEqual(new Interval(3, 7), Interval.AnalyticalQuotient(new Interval(3, 7), new Interval(-2, 4))); 199 Assert.AreEqual(new Interval(0, 0), Interval.AnalyticalQuotient(new Interval(0, 0), new Interval(0, 5))); 200 Assert.AreEqual(new Interval(-4, -4), Interval.AnalyticalQuotient(new Interval(-4, -4), new Interval(-4, 0))); 201 Assert.AreEqual(new Interval(4, 4), Interval.AnalyticalQuotient(new Interval(4, 4), new Interval(-2, 4))); 202 203 //First interval goes over zero 204 Assert.AreEqual(new Interval(-2.0/Math.Sqrt(5), 5.0 / Math.Sqrt(5)), Interval.AnalyticalQuotient(new Interval(-2, 5), new Interval(-5, -2))); 205 Assert.AreEqual(new Interval(-2.0 / Math.Sqrt(5), 5.0 / Math.Sqrt(5)), Interval.AnalyticalQuotient(new Interval(-2, 5), new Interval(2, 5))); 206 Assert.AreEqual(new Interval(2.0/Math.Sqrt(26), 5.0/Math.Sqrt(5)), Interval.AnalyticalQuotient(new Interval(2, 5), new Interval(-5, -2))); 207 Assert.AreEqual(new Interval(2.0 / Math.Sqrt(26), 5.0 / Math.Sqrt(5)), Interval.AnalyticalQuotient(new Interval(2, 5), new Interval(2, 5))); 208 Assert.AreEqual(new Interval(-5.0/Math.Sqrt(5), -2.0/Math.Sqrt(26)), Interval.AnalyticalQuotient(new Interval(-5, -2), new Interval(-5, -2))); 209 Assert.AreEqual(new Interval(-5.0 / Math.Sqrt(5), -2.0 / Math.Sqrt(26)), Interval.AnalyticalQuotient(new Interval(-5, -2), new Interval(2, 5))); 194 Assert.AreEqual(new Interval(aPos.LowerBound/Math.Sqrt(17), aPos.UpperBound), Interval.AnalyticalQuotient(aPos, bZero)); 195 Assert.AreEqual(new Interval(aZero.LowerBound, aZero.UpperBound), Interval.AnalyticalQuotient(aZero, bZero)); 196 Assert.AreEqual(new Interval(aNeg.LowerBound, aNeg.UpperBound/Math.Sqrt(17)), Interval.AnalyticalQuotient(aNeg, bZero)); 197 //Second interval is positive 198 Assert.AreEqual(new Interval(aPos.LowerBound/Math.Sqrt(17), aPos.UpperBound/Math.Sqrt(5)), Interval.AnalyticalQuotient(aPos, bPos)); 199 Assert.AreEqual(new Interval(aZero.LowerBound/Math.Sqrt(5), aZero.UpperBound/Math.Sqrt(5)), Interval.AnalyticalQuotient(aZero, bPos)); 200 Assert.AreEqual(new Interval(aNeg.LowerBound/Math.Sqrt(5), aNeg.UpperBound/Math.Sqrt(17)), Interval.AnalyticalQuotient(aNeg, bPos)); 201 //Second interval is negative 202 Assert.AreEqual(new Interval(aPos.LowerBound/Math.Sqrt(17), aPos.UpperBound/Math.Sqrt(5)), Interval.AnalyticalQuotient(aPos, bNeg)); 203 Assert.AreEqual(new Interval(aZero.LowerBound/Math.Sqrt(5), aZero.UpperBound/Math.Sqrt(5)), Interval.AnalyticalQuotient(aZero, bNeg)); 204 Assert.AreEqual(new Interval(aNeg.LowerBound/Math.Sqrt(5), aNeg.UpperBound/Math.Sqrt(17)), Interval.AnalyticalQuotient(aNeg, bNeg)); 205 } 206 207 [TestMethod] 208 [TestCategory("Problems.DataAnalysis")] 209 [TestProperty("Time", "short")] 210 public void IsNegativeIntervalTest() { 211 Assert.IsTrue(new Interval(-2, -1).IsNegative); 212 Assert.IsFalse(new Interval(-2, 0).IsNegative); 213 Assert.IsFalse(new Interval(-2, 2).IsNegative); 214 Assert.IsFalse(new Interval(2, 4).IsNegative); 215 } 216 217 [TestMethod] 218 [TestCategory("Problems.DataAnalysis")] 219 [TestProperty("Time", "short")] 220 public void IsPositiveIntervalTest() { 221 Assert.IsTrue(new Interval(3, 5).IsPositive); 222 Assert.IsFalse(new Interval(0, 5).IsPositive); 223 Assert.IsFalse(new Interval(-1, 5).IsPositive); 224 Assert.IsFalse(new Interval(-5, -2).IsPositive); 225 } 226 227 [TestMethod] 228 [TestCategory("Problems.DataAnalysis")] 229 [TestProperty("Time", "short")] 230 public void IsAlmostIntervalTest() { 231 var negativeLowerBound = -2E-13; 232 var negativeUpperBound = -1E-13; 233 var positiveLowerBound = 3E-13; 234 var positiveUpperBound = 5E-13; 235 236 var negativeInterval = new Interval(negativeLowerBound, negativeUpperBound); 237 var positiveInterval = new Interval(positiveLowerBound, positiveUpperBound); 238 var zeroInterval = new Interval(negativeUpperBound, positiveLowerBound); 239 240 //Check for right-shift of negative interval 241 Assert.AreEqual(negativeUpperBound, negativeInterval.LowerBound); 242 Assert.AreEqual(negativeUpperBound, negativeInterval.UpperBound); 243 //Check for left-shift of positive interval 244 Assert.AreEqual(positiveLowerBound, positiveInterval.LowerBound); 245 Assert.AreEqual(positiveLowerBound, positiveInterval.UpperBound); 246 //Check for setting interval to zero 247 Assert.AreEqual(0, zeroInterval.LowerBound); 248 Assert.AreEqual(0, zeroInterval.UpperBound); 249 210 250 } 211 251 }
Note: See TracChangeset
for help on using the changeset viewer.