View Javadoc
1   package org.thegalactic.context.constraint.numerical;
2   
3   /*
4    * NumericalStorage.java
5    *
6    * Copyright: 2016 The Galactic Organization, France
7    *
8    * License: http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html CeCILL-B license
9    *
10   * This file is part of java-lattices.
11   * You can redistribute it and/or modify it under the terms of the CeCILL-B license.
12   */
13  import java.util.ArrayList;
14  import java.util.List;
15  
16  /**
17   * Binary Storage.
18   */
19  public final class NumericalStorage {
20  
21      /**
22       * inf values.
23       */
24      private final List<Double> inf;
25  
26      /**
27       * sup values.
28       */
29      private final List<Double> sup;
30  
31      /**
32       * EXCEPTION_SIZE.
33       */
34      private static final String EXCEPTION_SIZE = "NumericalStorage objects must have the same size";
35  
36      /**
37       * Factory method to construct a numerical storage.
38       *
39       * @param size number of values
40       *
41       * @return a new NumericalStorage object
42       */
43      public static NumericalStorage create(final int size) {
44          return new NumericalStorage(size);
45      }
46  
47      /**
48       * This class is not designed to be publicly instantiated.
49       *
50       * @param size number of values
51       */
52      private NumericalStorage(final int size) {
53          this.inf = new ArrayList<Double>(size);
54          this.sup = new ArrayList<Double>(size);
55          // Initialise as an empty set
56          for (int index = 0; index < size; index++) {
57              this.inf.add(index, Double.POSITIVE_INFINITY);
58              this.sup.add(index, Double.NEGATIVE_INFINITY);
59          }
60      }
61  
62      /**
63       * Set the set at specified index empty.
64       *
65       * @param index index of the numerical set
66       *
67       * @return this for chaining
68       */
69      public NumericalStorage setEmpty(final int index) {
70          this.inf.set(index, Double.POSITIVE_INFINITY);
71          this.sup.set(index, Double.NEGATIVE_INFINITY);
72          return this;
73      }
74  
75      /**
76       * Is the set at specified index empty?
77       *
78       * @param index index of the numerical set
79       *
80       * @return this for chaining
81       */
82      public boolean isEmpty(final int index) {
83          return this.inf.get(index) > this.sup.get(index);
84      }
85  
86      /**
87       * Set the set at specified index a point.
88       *
89       * @param index index of the numerical set
90       * @param value the new value
91       *
92       * @return this for chaining
93       */
94      public NumericalStorage setPoint(final int index, final double value) {
95          this.inf.set(index, value);
96          this.sup.set(index, value);
97          return this;
98      }
99  
100     /**
101      * Is the set at specified index a point?
102      *
103      * @param index index of the numerical set
104      *
105      * @return this for chaining
106      */
107     public boolean isPoint(final int index) {
108         return this.inf.get(index).equals(this.sup.get(index));
109     }
110 
111     /**
112      * Set the inf mark to specified value.
113      *
114      * @param index the specified index
115      * @param value the new value
116      *
117      * @return this for chaining
118      */
119     public NumericalStorage setInf(final int index, final double value) {
120         if (this.isEmpty(index)) {
121             this.setPoint(index, value);
122         } else if (value > this.sup.get(index)) {
123             this.setEmpty(index);
124         } else {
125             this.inf.set(index, value);
126         }
127         return this;
128     }
129 
130     /**
131      * Set the sup mark to specified value.
132      *
133      * @param index the specified index
134      * @param value the new value
135      *
136      * @return this for chaining
137      */
138     public NumericalStorage setSup(final int index, final double value) {
139         if (this.isEmpty(index)) {
140             this.setPoint(index, value);
141         } else if (value < this.inf.get(index)) {
142             this.setEmpty(index);
143         } else {
144             this.sup.set(index, value);
145         }
146         return this;
147     }
148 
149     /**
150      * Get the inf value at specified index.
151      *
152      * @param index the specified index
153      *
154      * @return the inf value
155      */
156     public double getInf(final int index) {
157         return this.inf.get(index);
158     }
159 
160     /**
161      * Get the sup value at specified index.
162      *
163      * @param index the specified index
164      *
165      * @return the inf value
166      */
167     public double getSup(final int index) {
168         return this.sup.get(index);
169     }
170 
171     /**
172      * Reduce by inf value.
173      *
174      * @param index value to be reduced
175      * @param value value used to reduce
176      *
177      * @return this for chaining.
178      */
179     public NumericalStorage reduceInf(final int index, final double value) {
180         this.inf.set(index, Math.max(this.inf.get(index), value));
181         return this;
182     }
183 
184     /**
185      * Reduce by sup value.
186      *
187      * @param index value to be reduced
188      * @param value value used to reduce
189      *
190      * @return this for chaining.
191      */
192     public NumericalStorage reduceSup(final int index, final double value) {
193         this.sup.set(index, Math.min(this.sup.get(index), value));
194         return this;
195     }
196 
197     /**
198      * Extend by inf value.
199      *
200      * @param index value to be extended
201      * @param value value used to extend
202      *
203      * @return this for chaining
204      */
205     public NumericalStorage extendInf(final int index, final double value) {
206         this.inf.set(index, Math.min(this.inf.get(index), value));
207         return this;
208     }
209 
210     /**
211      * Extend by sup value.
212      *
213      * @param index value to be extended
214      * @param value value used to extend
215      *
216      * @return this for chaining
217      */
218     public NumericalStorage extendSup(final int index, final double value) {
219         this.sup.set(index, Math.max(this.sup.get(index), value));
220         return this;
221     }
222 
223     /**
224      * Extends value.
225      *
226      * @param index value to be extended
227      * @param value value used to extend
228      *
229      * @return this for chaining.
230      */
231     public NumericalStorage extend(final int index, final double value) {
232         this.extendInf(index, value);
233         this.extendSup(index, value);
234         return this;
235     }
236 
237     /**
238      * Intersection.
239      *
240      * @param storage NumericalStorage
241      *
242      * @return this for chaining
243      *
244      * @todo Is it the meet operation?
245      */
246     public NumericalStorage intersection(final NumericalStorage storage) {
247         final int size = this.inf.size();
248         if (storage.inf.size() == size) {
249             for (int index = 0; index < size; index++) {
250                 this.inf.set(index, Math.max(this.inf.get(index), storage.inf.get(index)));
251                 this.sup.set(index, Math.min(this.sup.get(index), storage.sup.get(index)));
252             }
253             return this;
254         } else {
255             throw new IllegalArgumentException(EXCEPTION_SIZE);
256         }
257     }
258 
259     /**
260      * Union.
261      *
262      * An approximation is made for union when the two intervals are disjoint.
263      * The result is the minimum interval containing both intervals.
264      *
265      * @param storage NumericalStorage
266      *
267      * @return this for chaining
268      */
269     public NumericalStorage union(final NumericalStorage storage) {
270         final int size = this.inf.size();
271         if (storage.inf.size() == size) {
272             for (int index = 0; index < size; index++) {
273                 this.inf.set(index, Math.min(this.inf.get(index), storage.inf.get(index)));
274                 this.sup.set(index, Math.max(this.sup.get(index), storage.sup.get(index)));
275             }
276             return this;
277         } else {
278             throw new IllegalArgumentException(EXCEPTION_SIZE);
279         }
280     }
281 
282     /**
283      * Get the size.
284      *
285      * @return the size
286      */
287     public int size() {
288         return this.inf.size();
289     }
290 
291     /**
292      * Returns a String representation of this object.
293      *
294      * @return a string representation of this object
295      */
296     @Override
297     public String toString() {
298         final StringBuilder builder = new StringBuilder();
299 
300         builder.append('[');
301 
302         final int size = this.inf.size();
303         for (int index = 0; index < size; index++) {
304             if (index != 0) {
305                 builder.append(", ");
306             }
307             if (this.isEmpty(index)) {
308                 builder.append('@');
309             } else if (this.isPoint(index)) {
310                 builder.append(this.inf.get(index));
311             } else {
312                 builder.append('(');
313                 builder.append(this.inf.get(index));
314                 builder.append(',');
315                 builder.append(this.sup.get(index));
316                 builder.append(')');
317             }
318         }
319 
320         builder.append(']');
321 
322         return builder.toString();
323     }
324 }