source: branches/2966_interval_calculation/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval.cs @ 16326

Last change on this file since 16326 was 16326, checked in by mkommend, 2 years ago

#2966: Corrected namespace of intervals.

File size: 7.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Common;
26
27namespace HeuristicLab.Problems.DataAnalysis {
28  public class Interval : IEquatable<Interval> {
29    private double lowerBound;
30    public double LowerBound {
31      get { return lowerBound; }
32      private set { lowerBound = value; }
33    }
34    private double upperBound;
35    public double UpperBound {
36      get { return upperBound; }
37      private set { lowerBound = value; }
38    }
39
40    public Interval(double lowerBound, double upperBound) {
41      if (lowerBound > upperBound)
42        throw new ArgumentException("LowerBound must be smaller than UpperBound.");
43
44      this.lowerBound = lowerBound;
45      this.upperBound = upperBound;
46    }
47
48    public bool Contains(double value) {
49      return lowerBound <= value && value <= upperBound;
50    }
51
52    public override string ToString() {
53      return "Interval: [" + lowerBound + ", " + upperBound + "]";
54    }
55
56    public bool IsInfiniteOrUndefined {
57      get {
58        return double.IsInfinity(LowerBound) || double.IsInfinity(UpperBound) ||
59                double.IsNaN(LowerBound) || double.IsNaN(UpperBound);
60      }
61    }
62
63    #region Equals, GetHashCode, == , !=
64    public bool Equals(Interval other) {
65      if (other == null)
66        return false;
67
68      return this.upperBound.IsAlmost(other.upperBound) && this.lowerBound.IsAlmost(other.lowerBound);
69    }
70
71    public override bool Equals(object obj) {
72      return Equals(obj as Interval);
73    }
74
75    public override int GetHashCode() {
76      return lowerBound.GetHashCode() ^ upperBound.GetHashCode();
77    }
78
79    public static bool operator ==(Interval interval1, Interval interval2) {
80      if (ReferenceEquals(interval1, null)) return ReferenceEquals(interval2, null);
81      return interval1.Equals(interval2);
82    }
83    public static bool operator !=(Interval interval1, Interval interval2) {
84      return !(interval1 == interval2);
85    }
86    #endregion
87
88    #region operations
89
90    // [x1,x2] + [y1,y2] = [x1 + y1,x2 + y2]
91    public static Interval Add(Interval a, Interval b) {
92      return new Interval(a.lowerBound + b.lowerBound, a.upperBound + b.upperBound);
93    }
94
95    // [x1,x2] − [y1,y2] = [x1 − y2,x2 − y1]
96    public static Interval Subtract(Interval a, Interval b) {
97      return new Interval(a.lowerBound - b.upperBound, a.upperBound - b.lowerBound);
98    }
99
100    // [x1,x2] * [y1,y2] = [min(x1*y1,x1*y2,x2*y1,x2*y2),max(x1*y1,x1*y2,x2*y1,x2*y2)]
101    public static Interval Multiply(Interval a, Interval b) {
102      double v1 = a.lowerBound * b.lowerBound;
103      double v2 = a.lowerBound * b.upperBound;
104      double v3 = a.upperBound * b.lowerBound;
105      double v4 = a.upperBound * b.upperBound;
106
107      double min = Math.Min(Math.Min(v1, v2), Math.Min(v3, v4));
108      double max = Math.Max(Math.Min(v1, v2), Math.Max(v3, v4));
109      return new Interval(min, max);
110    }
111
112    //mkommend: Divisiont by intervals containing 0 is implemented as defined in
113    //http://en.wikipedia.org/wiki/Interval_arithmetic
114    public static Interval Divide(Interval a, Interval b) {
115      if (b.Contains(0.0)) {
116        if (b.lowerBound.IsAlmost(0.0)) return Interval.Multiply(a, new Interval(1.0 / b.upperBound, double.PositiveInfinity));
117        else if (b.upperBound.IsAlmost(0.0)) return Interval.Multiply(a, new Interval(double.NegativeInfinity, 1.0 / b.lowerBound));
118        else return new Interval(double.NegativeInfinity, double.PositiveInfinity);
119      }
120      return Interval.Multiply(a, new Interval(1.0 / b.upperBound, 1.0 / b.lowerBound));
121    }
122
123    public static Interval Sine(Interval a) {
124      if (Math.Abs(a.upperBound - a.lowerBound) >= Math.PI * 2) return new Interval(-1, 1);
125
126      //divide the interval by PI/2 so that the optima lie at x element of N (0,1,2,3,4,...)
127      double Pihalf = Math.PI / 2;
128      Interval scaled = Interval.Divide(a, new Interval(Pihalf, Pihalf));
129      //move to positive scale
130      if (scaled.lowerBound < 0) {
131        int periodsToMove = Math.Abs((int)scaled.lowerBound / 4) + 1;
132        scaled = Interval.Add(scaled, new Interval(periodsToMove * 4, periodsToMove * 4));
133      }
134
135      double scaledLowerBound = scaled.lowerBound % 4.0;
136      double scaledUpperBound = scaled.upperBound % 4.0;
137      if (scaledUpperBound < scaledLowerBound) scaledUpperBound += 4.0;
138      List<double> sinValues = new List<double>();
139      sinValues.Add(Math.Sin(scaledLowerBound * Pihalf));
140      sinValues.Add(Math.Sin(scaledUpperBound * Pihalf));
141
142      int startValue = (int)Math.Ceiling(scaledLowerBound);
143      while (startValue < scaledUpperBound) {
144        sinValues.Add(Math.Sin(startValue * Pihalf));
145        startValue += 1;
146      }
147
148      return new Interval(sinValues.Min(), sinValues.Max());
149    }
150    public static Interval Cosine(Interval a) {
151      return Interval.Sine(Interval.Subtract(a, new Interval(Math.PI / 2, Math.PI / 2)));
152    }
153    public static Interval Tangens(Interval a) {
154      return Interval.Divide(Interval.Sine(a), Interval.Cosine(a));
155    }
156
157    public static Interval Logarithm(Interval a) {
158      return new Interval(Math.Log(a.lowerBound), Math.Log(a.upperBound));
159    }
160    public static Interval Exponential(Interval a) {
161      return new Interval(Math.Exp(a.lowerBound), Math.Exp(a.upperBound));
162    }
163
164    public static Interval Power(Interval a, Interval b) {
165      if (a.Contains(0.0) && b.lowerBound < 0) return new Interval(double.NaN, double.NaN);
166
167      int bLower = (int)Math.Round(b.lowerBound);
168      int bUpper = (int)Math.Round(b.upperBound);
169
170      List<double> powerValues = new List<double>();
171      powerValues.Add(Math.Pow(a.upperBound, bUpper));
172      powerValues.Add(Math.Pow(a.upperBound, bUpper - 1));
173      powerValues.Add(Math.Pow(a.upperBound, bLower));
174      powerValues.Add(Math.Pow(a.upperBound, bLower + 1));
175
176      powerValues.Add(Math.Pow(a.lowerBound, bUpper));
177      powerValues.Add(Math.Pow(a.lowerBound, bUpper - 1));
178      powerValues.Add(Math.Pow(a.lowerBound, bLower));
179      powerValues.Add(Math.Pow(a.lowerBound, bLower + 1));
180
181      return new Interval(powerValues.Min(), powerValues.Max());
182    }
183
184    public static Interval Square(Interval a) {
185      return Power(a, new Interval(2, 2));
186    }
187
188    public static Interval Cubic(Interval a) {
189      return Power(a, new Interval(3, 3));
190    }
191
192    public static Interval Root(Interval a, Interval b) {
193      int lower = (int)Math.Round(b.lowerBound);
194      int higher = (int)Math.Round(b.upperBound);
195
196      return new Interval(Math.Pow(a.lowerBound, 1.0 / higher), Math.Pow(a.upperBound, 1.0 / lower));
197    }
198
199    public static Interval SquareRoot(Interval a) {
200      return Root(a, new Interval(2, 2));
201    }
202
203    public static Interval CubicRoot(Interval a) {
204      return Root(a, new Interval(3, 3));
205    }
206    #endregion
207  }
208}
Note: See TracBrowser for help on using the repository browser.