Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3057_DynamicALPS/TestProblems/oesr-alps-master/HeuristicLab.Algorithms.OESRALPS/DriftDetection/Histogram.cs @ 17479

Last change on this file since 17479 was 17479, checked in by kyang, 4 years ago

#3057

  1. upload the latest version of ALPS with SMS-EMOA
  2. upload the related dynamic test problems (dynamic, single-objective symbolic regression), written by David Daninel.
File size: 8.4 KB
Line 
1using HEAL.Attic;
2using System;
3using System.Collections;
4using System.Collections.Generic;
5using System.Linq;
6using System.Text;
7using System.Threading.Tasks;
8
9namespace HeuristicLab.Algorithms.OESRALPS.DriftDetection
10{
11    [StorableType("714AE0E4-A88F-44A1-A2D0-92F418252C04")]
12    public class Histogram : IEnumerable<Bucket>
13    {
14        [Storable]
15        public int MaxBucketsPerBucketContainer { get; }
16        [Storable]
17        public int NumBucketContainers { get; set; }
18        [Storable]
19        public int NumBuckets { get; set; }
20        [Storable]
21        public int NumElements { get; set; }
22        [Storable]
23        public double Total { get; set; }
24        [Storable]
25        public double Variance { get; set; }
26        [Storable]
27        internal BucketContainer Tail { get; set; }
28        [Storable]
29        internal BucketContainer Head { get; set; }
30
31        public Histogram() { }
32
33        /**
34         * Creates a new empty Histogram
35         * @param maxBucketsPerBucketContainer max number of Buckets in one bucket container. default is 5
36         */
37        public Histogram(int maxBucketsPerBucketContainer)
38        {
39            if (maxBucketsPerBucketContainer < 2)
40            {
41                throw new Exception("maxBucketsPerBucketContainer must be at least 2.");
42            }
43
44            Head = new BucketContainer(null, null, maxBucketsPerBucketContainer, 1);
45            Tail = Head;
46            NumBucketContainers = 1;
47            MaxBucketsPerBucketContainer = maxBucketsPerBucketContainer;
48        }
49
50        // TODO Evaluate
51        private Histogram(Histogram original)
52        {
53            MaxBucketsPerBucketContainer = original.MaxBucketsPerBucketContainer;
54
55            NumBucketContainers = original.NumBucketContainers;
56            NumBuckets = original.NumBuckets;
57            NumElements = original.NumElements;
58
59            Total = original.Total;
60            Variance = original.Variance;
61
62            Head = original.Head.DeepCopy();
63            BucketContainer currentBucketContainer = Head;
64            while (currentBucketContainer.Next != null)
65            {
66                currentBucketContainer = currentBucketContainer.Next;
67            }
68            Tail = currentBucketContainer;
69        }
70
71        public void AddElement(double element)
72        {
73            Bucket newBucket = new Bucket(element, 0, 1);
74            Head.AddBucket(newBucket);
75            NumBuckets++;
76            NumElements++;
77            if (NumElements > 1)
78            {
79                Variance += (NumElements - 1) * Math.Pow(element - Total / (NumElements - 1), 2) / NumElements;
80            }
81            Total += element;
82            Compress();
83        }
84
85        private void AddEmptyTailBucketContainer()
86        {
87            BucketContainer newTail = new BucketContainer(Tail, null, MaxBucketsPerBucketContainer, Tail.NumElementsPerBucket * 2);
88            Tail.Next = newTail;
89            Tail = newTail;
90            NumBucketContainers++;
91        }
92
93        private void Compress()
94        {
95            BucketContainer pointer = Head;
96            while (pointer != null)
97            {
98                if (pointer.NumBuckets == pointer.MaxBuckets)
99                {
100                    if (pointer.Next == null)
101                    {
102                        AddEmptyTailBucketContainer();
103                    }
104                    Bucket[] removedBuckets = pointer.RemoveBuckets(2);
105                    Bucket newBucket = CompressBuckets(removedBuckets[0], removedBuckets[1]);
106                    pointer.Next.AddBucket(newBucket);
107                    NumBuckets -= 1;
108                }
109                pointer = pointer.Next;
110            }
111        }
112
113        private Bucket CompressBuckets(Bucket firstBucket, Bucket secondBucket)
114        {
115            if (firstBucket.NumElements != secondBucket.NumElements)
116                throw new Exception("Number of buckets unequal.");
117
118            int elementsPerBucket = firstBucket.NumElements;
119            double newTotal = firstBucket.Total + secondBucket.Total;
120            double varianceIncrease = Math.Pow(firstBucket.Total - secondBucket.Total, 2) / (2 * elementsPerBucket);
121            double newVariance = firstBucket.Variance + secondBucket.Variance + varianceIncrease;
122            return new Bucket(newTotal, newVariance, 2 * elementsPerBucket);
123        }
124
125        public void RemoveBuckets(int num)
126        {
127            while (num > 0)
128            {
129                Bucket[] removedBuckets;
130                if (num >= Tail.NumBuckets)
131                {
132                    num -= Tail.NumBuckets;
133                    removedBuckets = Tail.RemoveBuckets(Tail.NumBuckets);
134                    Tail = Tail.Prev;
135                    Tail.Next = null;
136                    NumBucketContainers--;
137                }
138                else
139                {
140                    removedBuckets = Tail.RemoveBuckets(num);
141                    num = 0;
142                }
143                foreach (Bucket bucket in removedBuckets)
144                {
145                    NumElements -= bucket.NumElements;
146                    NumBuckets--;
147                    Total -= bucket.Total;
148                    Variance -= bucket.Variance + bucket.NumElements * NumElements * Math.Pow(bucket.Mean - Total / NumElements, 2) / (bucket.NumElements + NumElements);
149                }
150            }
151        }
152
153        public Histogram copy()
154        {
155            return new Histogram(this);
156        }
157
158        IEnumerator IEnumerable.GetEnumerator()
159        {
160            return GetEnumerator();
161        }
162
163        public IEnumerator<Bucket> GetEnumerator()
164        {
165            return new HistogramReverseEnumerator<Bucket>(this);
166        }
167
168        private class HistogramReverseEnumerator<T> : IEnumerator<Bucket>
169        {
170            private BucketContainer currentBucketContainer;
171            private int currentBucketIndex;
172
173            public HistogramReverseEnumerator(Histogram histogram)
174            {
175                currentBucketContainer = histogram.Tail;
176                currentBucketIndex = histogram.Tail.NumBuckets;
177            }
178
179            public Bucket Current => currentBucketContainer.GetBucket(currentBucketIndex);
180
181            object IEnumerator.Current => Current;
182
183            public void Dispose()
184            {
185            }
186
187            private bool HasNext()
188            {
189                return (currentBucketIndex > 0) || (currentBucketContainer.Prev != null);
190            }
191
192            public bool MoveNext()
193            {
194                if (!HasNext())
195                    return false;
196
197                currentBucketIndex--;
198                if (currentBucketIndex < 0)
199                {
200                    currentBucketContainer = currentBucketContainer.Prev;
201                    currentBucketIndex = currentBucketContainer.NumBuckets - 1;
202                }
203                return true;
204            }
205
206            public void Reset()
207            {
208            }
209        }
210
211        private class HistogramEnumerator<T> : IEnumerator<Bucket>
212        {
213            private Histogram histogram;
214            private BucketContainer currentBucketContainer;
215            private int currentBucketIndex;
216
217            public HistogramEnumerator(Histogram histogram)
218            {
219                this.histogram = histogram;
220                currentBucketContainer = histogram.Head;
221                currentBucketIndex = -1;
222            }
223
224            public Bucket Current => currentBucketContainer.GetBucket(currentBucketIndex);
225
226            object IEnumerator.Current => Current;
227
228            public void Dispose()
229            {
230            }
231
232            private bool HasNext()
233            {
234                return (currentBucketIndex < currentBucketContainer.NumBuckets - 1) || (currentBucketContainer.Next != null);
235            }
236
237            public bool MoveNext()
238            {
239                if (!HasNext())
240                    return false;
241
242                currentBucketIndex++;
243                if (currentBucketIndex > currentBucketContainer.NumBuckets - 1)
244                {
245                    currentBucketContainer = currentBucketContainer.Next;
246                    currentBucketIndex = 0;
247                }
248
249                return true;
250            }
251
252            public void Reset()
253            {
254            }
255        }
256    }
257}
Note: See TracBrowser for help on using the repository browser.