View Javadoc

1   /*
2    * SAT4J: a SATisfiability library for Java Copyright (C) 2004-2006 Daniel Le Berre
3    * 
4    * Based on the original minisat specification from:
5    * 
6    * An extensible SAT solver. Niklas E?n and Niklas S?rensson. Proceedings of the
7    * Sixth International Conference on Theory and Applications of Satisfiability
8    * Testing, LNCS 2919, pp 502-518, 2003.
9    * 
10   * This library is free software; you can redistribute it and/or modify it under
11   * the terms of the GNU Lesser General Public License as published by the Free
12   * Software Foundation; either version 2.1 of the License, or (at your option)
13   * any later version.
14   * 
15   * This library is distributed in the hope that it will be useful, but WITHOUT
16   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18   * details.
19   * 
20   * You should have received a copy of the GNU Lesser General Public License
21   * along with this library; if not, write to the Free Software Foundation, Inc.,
22   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23   * 
24   */
25  
26  package org.sat4j.core;
27  
28  import java.io.Serializable;
29  import java.util.Arrays;
30  import java.util.Comparator;
31  import java.util.Iterator;
32  import java.util.NoSuchElementException;
33  import java.util.Random;
34  
35  import org.sat4j.specs.IVec;
36  
37  /**
38   * Simple but efficient vector implementation, based on the vector
39   * implementation available in MiniSAT. Note that the elements are compared
40   * using their references, not using the equals method.
41   * 
42   * @author leberre
43   */
44  public class Vec<T> implements Serializable, IVec<T> {
45  
46      private static final long serialVersionUID = 1L;
47  
48      private static final int RANDOM_SEED = 91648253;
49  
50      /**
51       * Create a Vector with an initial capacity of 5 elements.
52       */
53      public Vec() {
54          this(5);
55      }
56  
57      /**
58       * Adapter method to translate an array of int into an IVec.
59       * 
60       * The array is used inside the Vec, so the elements may be modified outside
61       * the Vec. But it should not take much memory. The size of the created Vec
62       * is the length of the array.
63       * 
64       * @param elts
65       *            a filled array of T.
66       */
67      public Vec(T[] elts) {
68       // DLB findbugs ok
69          myarray = elts;
70          nbelem = elts.length;
71      }
72  
73      /**
74       * Create a Vector with a given capacity.
75       * 
76       * @param size
77       *            the capacity of the vector.
78       */
79      @SuppressWarnings("unchecked")
80      public Vec(int size) {
81          myarray = (T[]) new Object[size];
82      }
83  
84      /**
85       * Construit un vecteur contenant de taille size rempli a l'aide de size
86       * pad.
87       * 
88       * @param size
89       *            la taille du vecteur
90       * @param pad
91       *            l'objet servant a remplir le vecteur
92       */
93      @SuppressWarnings("unchecked")
94      public Vec(int size, T pad) {
95          myarray = (T[]) new Object[size];
96          for (int i = 0; i < size; i++) {
97              myarray[i] = pad;
98          }
99          nbelem = size;
100     }
101 
102     public int size() {
103         return nbelem;
104     }
105 
106     /**
107      * Remove nofelems from the Vector. It is assumed that the number of
108      * elements to remove is smaller or equals to the current number of elements
109      * in the vector
110      * 
111      * @param nofelems
112      *            the number of elements to remove.
113      */
114     public void shrink(int nofelems) {
115         assert nofelems <= nbelem;
116         while (nofelems-- > 0) {
117             myarray[--nbelem] = null;
118         }
119     }
120 
121     /**
122      * reduce the Vector to exactly newsize elements
123      * 
124      * @param newsize
125      *            the new size of the vector.
126      */
127     public void shrinkTo(final int newsize) {
128         assert newsize <= size();
129         for (int i = nbelem; i > newsize; i--) {
130             myarray[i - 1] = null;
131         }
132         nbelem = newsize;
133         assert size() == newsize;
134     }
135 
136     /**
137      * Pop the last element on the stack. It is assumed that the stack is not
138      * empty!
139      */
140     public void pop() {
141         assert size() > 0;
142         myarray[--nbelem] = null;
143     }
144 
145     public void growTo(final int newsize, final T pad) {
146         assert newsize >= size();
147         ensure(newsize);
148         for (int i = nbelem; i < newsize; i++) {
149             myarray[i] = pad;
150         }
151         nbelem = newsize;
152     }
153 
154     @SuppressWarnings("unchecked")
155     public final void ensure(final int nsize) {
156         if (nsize >= myarray.length) {
157             T[] narray = (T[]) new Object[Math.max(nsize, nbelem * 2)];
158             System.arraycopy(myarray, 0, narray, 0, nbelem);
159             myarray = narray;
160         }
161     }
162 
163     public IVec<T> push(final T elem) {
164         ensure(nbelem + 1);
165         myarray[nbelem++] = elem;
166         return this;
167     }
168 
169     public void unsafePush(final T elem) {
170         myarray[nbelem++] = elem;
171     }
172 
173     /**
174      * Insert an element at the very begining of the vector. The former first
175      * element is appended to the end of the vector in order to have a constant
176      * time operation.
177      * 
178      * @param elem
179      *            the element to put first in the vector.
180      */
181     public void insertFirst(final T elem) {
182         if (nbelem > 0) {
183             push(myarray[0]);
184             myarray[0] = elem;
185             return;
186         }
187         push(elem);
188     }
189 
190     public void insertFirstWithShifting(final T elem) {
191         if (nbelem > 0) {
192             ensure(nbelem + 1);
193             for (int i = nbelem; i > 0; i--) {
194                 myarray[i] = myarray[i - 1];
195             }
196             myarray[0] = elem;
197             nbelem++;
198             return;
199         }
200         push(elem);
201     }
202 
203     public void clear() {
204         Arrays.fill(myarray, 0, nbelem, null);
205         nbelem = 0;
206     }
207 
208     /**
209      * return the latest element on the stack. It is assumed that the stack is
210      * not empty!
211      * 
212      * @return the last element on the stack (the one on the top)
213      */
214     public T last() {
215         assert size() != 0;
216         return myarray[nbelem - 1];
217     }
218 
219     public T get(final int index) {
220         return myarray[index];
221     }
222 
223     public void set(int index, T elem) {
224         myarray[index] = elem;
225     }
226 
227     /**
228      * Remove an element that belongs to the Vector. The method will break if
229      * the element does not belong to the vector.
230      * 
231      * @param elem
232      *            an element from the vector.
233      */
234     public void remove(T elem) {
235         assert size() > 0;
236         int j = 0;
237         for (; myarray[j] != elem; j++) {
238             assert j < size();
239         }
240         // arraycopy is always faster than manual copy
241         System.arraycopy(myarray, j + 1, myarray, j, size() - j - 1);
242         myarray[--nbelem] = null;
243     }
244 
245     /**
246      * Delete the ith element of the vector. The latest element of the vector
247      * replaces the removed element at the ith indexer.
248      * 
249      * @param index
250      *            the indexer of the element in the vector
251      * @return the former ith element of the vector that is now removed from the
252      *         vector
253      */
254     public T delete(int index) {
255         assert index >= 0 && index < nbelem;
256         T ith = myarray[index];
257         myarray[index] = myarray[--nbelem];
258         myarray[nbelem] = null;
259         return ith;
260     }
261 
262     /**
263      * Ces operations devraient se faire en temps constant. Ce n'est pas le
264      * cas ici.
265      * 
266      * @param copy
267      */
268     public void copyTo(IVec<T> copy) {
269         final Vec<T> ncopy = (Vec<T>) copy;
270         final int nsize = nbelem + ncopy.nbelem;
271         copy.ensure(nsize);
272         System.arraycopy(myarray, 0, ncopy.myarray, ncopy.nbelem, nbelem);
273         ncopy.nbelem = nsize;
274     }
275 
276     /**
277      * @param dest
278      */
279     public <E> void copyTo(E[] dest) {
280         assert dest.length >= nbelem;
281         System.arraycopy(myarray, 0, dest, 0, nbelem);
282     }
283 
284     /*
285      * Copy one vector to another (cleaning the first), in constant time.
286      */
287     public void moveTo(IVec<T> dest) {
288         copyTo(dest);
289         clear();
290     }
291 
292     public void moveTo(int dest, int source) {
293         myarray[dest] = myarray[source];
294         myarray[source] = null;
295     }
296 
297     public T[] toArray() {
298         // DLB findbugs ok
299         return myarray;
300     }
301 
302     private int nbelem;
303 
304     private T[] myarray;
305 
306     /*
307      * (non-Javadoc)
308      * 
309      * @see java.lang.Object#toString()
310      */
311     @Override
312     public String toString() {
313         StringBuffer stb = new StringBuffer();
314         for (int i = 0; i < nbelem - 1; i++) {
315             stb.append(myarray[i]);
316             stb.append(","); //$NON-NLS-1$
317         }
318         if (nbelem > 0) {
319             stb.append(myarray[nbelem - 1]);
320         }
321         return stb.toString();
322     }
323 
324     private static Random rand = new Random(RANDOM_SEED);
325 
326     void selectionSort(int from, int to, Comparator<T> cmp) {
327         int i, j, best_i;
328         T tmp;
329 
330         for (i = from; i < to - 1; i++) {
331             best_i = i;
332             for (j = i + 1; j < to; j++) {
333                 if (cmp.compare(myarray[j], myarray[best_i]) < 0)
334                     best_i = j;
335             }
336             tmp = myarray[i];
337             myarray[i] = myarray[best_i];
338             myarray[best_i] = tmp;
339         }
340     }
341 
342     void sort(int from, int to, Comparator<T> cmp) {
343         int width = to - from;
344         if (to - from <= 15)
345             selectionSort(from, to, cmp);
346 
347         else {
348             T pivot = myarray[rand.nextInt(width) + from];
349             T tmp;
350             int i = from - 1;
351             int j = to;
352 
353             for (;;) {
354                 do
355                     i++;
356                 while (cmp.compare(myarray[i], pivot) < 0);
357                 do
358                     j--;
359                 while (cmp.compare(pivot, myarray[j]) < 0);
360 
361                 if (i >= j)
362                     break;
363 
364                 tmp = myarray[i];
365                 myarray[i] = myarray[j];
366                 myarray[j] = tmp;
367             }
368 
369             sort(from, i, cmp);
370             sort(i, to, cmp);
371         }
372     }
373 
374     /**
375      * @param comparator
376      */
377     public void sort(Comparator<T> comparator) {
378         sort(0, nbelem, comparator);
379     }
380 
381     public void sortUnique(Comparator<T> cmp) {
382         int i, j;
383         T last;
384 
385         if (nbelem == 0)
386             return;
387 
388         sort(0, nbelem, cmp);
389 
390         i = 1;
391         last = myarray[0];
392         for (j = 1; j < nbelem; j++) {
393             if (cmp.compare(last, myarray[j]) < 0) {
394                 last = myarray[i] = myarray[j];
395                 i++;
396             }
397         }
398 
399         nbelem = i;
400     }
401 
402     /*
403      * (non-Javadoc)
404      * 
405      * @see java.lang.Object#equals(java.lang.Object)
406      */
407     @Override
408     public boolean equals(Object obj) {
409         if (obj instanceof IVec) {
410             IVec<?> v = (IVec<?>) obj;
411             if (v.size() != size())
412                 return false;
413             for (int i = 0; i < size(); i++) {
414                 if (!v.get(i).equals(get(i))) {
415                     return false;
416                 }
417             }
418             return true;
419         }
420         return false;
421     }
422 
423     /*
424      * (non-Javadoc)
425      * 
426      * @see java.lang.Object#hashCode()
427      */
428     @Override
429     public int hashCode() {
430         int sum = 0;
431         for (int i = 0; i < nbelem; i++) {
432             sum += myarray[i].hashCode() / nbelem;
433         }
434         return sum;
435     }
436 
437     public Iterator<T> iterator() {
438         return new Iterator<T>() {
439             private int i = 0;
440 
441             public boolean hasNext() {
442                 return i < nbelem;
443             }
444 
445             public T next() {
446                 if (i == nbelem)
447                     throw new NoSuchElementException();
448                 return myarray[i++];
449             }
450 
451             public void remove() {
452                 throw new UnsupportedOperationException();
453             }
454         };
455     }
456 
457     public boolean isEmpty() {
458         return nbelem == 0;
459     }
460 }