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.Iterator;
30  import java.util.NoSuchElementException;
31  import java.util.Random;
32  
33  import org.sat4j.specs.IVecInt;
34  
35  /*
36   * Created on 9 oct. 2003
37   */
38  
39  /**
40   * A vector specific for primitive integers, widely used in the solver. Note
41   * that if the vector has a sort method, the operations on the vector DO NOT
42   * preserve sorting.
43   * 
44   * @author leberre
45   */
46  public class VecInt implements Serializable, IVecInt {
47  
48      private static final long serialVersionUID = 1L;
49  
50      private static final int RANDOM_SEED = 91648253;
51  
52      @SuppressWarnings("PMD")
53      public static final IVecInt EMPTY = new VecInt() {
54  
55          /**
56           * 
57           */
58          private static final long serialVersionUID = 1L;
59  
60          @Override
61          public int size() {
62              return 0;
63          }
64  
65          @Override
66          public void shrink(int nofelems) {
67          }
68  
69          @Override
70          public void shrinkTo(int newsize) {
71          }
72  
73          @Override
74          public IVecInt pop() {
75              throw new UnsupportedOperationException();
76          }
77  
78          @Override
79          public void growTo(int newsize, int pad) {
80          }
81  
82          @Override
83          public void ensure(int nsize) {
84          }
85  
86          @Override
87          public IVecInt push(int elem) {
88              throw new UnsupportedOperationException();
89          }
90  
91          @Override
92          public void unsafePush(int elem) {
93              throw new UnsupportedOperationException();
94          }
95  
96          @Override
97          public void clear() {
98          }
99  
100         @Override
101         public int last() {
102             throw new UnsupportedOperationException();
103         }
104 
105         @Override
106         public int get(int i) {
107             throw new UnsupportedOperationException();
108         }
109 
110         @Override
111         public void set(int i, int o) {
112             throw new UnsupportedOperationException();
113         }
114 
115         @Override
116         public boolean contains(int e) {
117             return false;
118         }
119 
120         @Override
121         public void copyTo(IVecInt copy) {
122             throw new UnsupportedOperationException();
123         }
124 
125         @Override
126         public void copyTo(int[] is) {
127         }
128 
129         @Override
130         public void moveTo(IVecInt dest) {
131         }
132 
133         @Override
134         public void moveTo2(IVecInt dest) {
135         }
136 
137         @Override
138         public void moveTo(int[] dest) {
139         }
140 
141         @Override
142         public void insertFirst(int elem) {
143             throw new UnsupportedOperationException();
144         }
145 
146         @Override
147         public void remove(int elem) {
148             throw new UnsupportedOperationException();
149         }
150 
151         @Override
152         public int delete(int i) {
153             throw new UnsupportedOperationException();
154         }
155 
156         @Override
157         public void sort() {
158         }
159 
160         @Override
161         public void sortUnique() {
162         }
163     };
164 
165     public VecInt() {
166         this(5);
167     }
168 
169     public VecInt(int size) {
170         myarray = new int[size];
171     }
172 
173     /**
174      * Adapter method to translate an array of int into an IVecInt.
175      * 
176      * The array is used inside the VecInt, so the elements may be modified
177      * outside the VecInt. But it should not take much memory.The size of the
178      * created VecInt is the length of the array.
179      * 
180      * @param lits
181      *            a filled array of int.
182      */
183     public VecInt(int[] lits) {
184         myarray = lits;
185         nbelem = lits.length;
186     }
187 
188     /**
189      * Build a vector of a given initial size filled with an integer.
190      * 
191      * @param size
192      *            the initial size of the vector
193      * @param pad
194      *            the integer to fill the vector with
195      */
196     public VecInt(int size, int pad) {
197         myarray = new int[size];
198         for (int i = 0; i < size; i++) {
199             myarray[i] = pad;
200         }
201         nbelem = size;
202     }
203 
204     public int size() {
205         return nbelem;
206     }
207 
208     /**
209      * Remove the latest nofelems elements from the vector
210      * 
211      * @param nofelems
212      */
213     public void shrink(int nofelems) {
214         assert nofelems >= 0;
215         assert nofelems <= size();
216         nbelem -= nofelems;
217     }
218 
219     public void shrinkTo(int newsize) {
220         assert newsize >= 0;
221         assert newsize < nbelem;
222         nbelem = newsize;
223     }
224 
225     /**
226      * depile le dernier element du vecteur. Si le vecteur est vide, ne
227      * fait rien.
228      */
229     public IVecInt pop() {
230         assert size() != 0;
231         --nbelem;
232         return this;
233     }
234 
235     public void growTo(int newsize, final int pad) {
236         assert newsize > size();
237         ensure(newsize);
238         while (--newsize >= 0) {
239             myarray[nbelem++] = pad;
240         }
241     }
242 
243     public void ensure(int nsize) {
244         if (nsize >= myarray.length) {
245             int[] narray = new int[Math.max(nsize, nbelem * 2)];
246             System.arraycopy(myarray, 0, narray, 0, nbelem);
247             myarray = narray;
248         }
249     }
250 
251     public IVecInt push(int elem) {
252         ensure(nbelem + 1);
253         myarray[nbelem++] = elem;
254         return this;
255     }
256 
257     public void unsafePush(int elem) {
258         myarray[nbelem++] = elem;
259     }
260 
261     public void clear() {
262         nbelem = 0;
263     }
264 
265     public int last() {
266         assert nbelem > 0;
267         return myarray[nbelem - 1];
268     }
269 
270     public int get(int i) {
271         assert i >= 0 && i < nbelem;
272         return myarray[i];
273     }
274 
275     public int unsafeGet(int i) {
276         return myarray[i];
277     }
278 
279     public void set(int i, int o) {
280         assert i >= 0 && i < nbelem;
281         myarray[i] = o;
282     }
283 
284     public boolean contains(int e) {
285         final int[] workArray = myarray; // dvh, faster access
286         for (int i = 0; i < nbelem; i++) {
287             if (workArray[i] == e)
288                 return true;
289         }
290         return false;
291     }
292 
293     /**
294      * C'est operations devraient se faire en temps constant. Ce n'est pas le
295      * cas ici.
296      * 
297      * @param copy
298      */
299     public void copyTo(IVecInt copy) {
300         /*
301          * int nsize = nbelem + copy.nbelem; copy.ensure(nsize); for (int i = 0;
302          * i < nbelem; i++) { copy.myarray[i + copy.nbelem] = myarray[i]; }
303          * copy.nbelem = nsize;
304          */
305         VecInt ncopy = (VecInt) copy;
306         int nsize = nbelem + ncopy.nbelem;
307         ncopy.ensure(nsize);
308         System.arraycopy(myarray, 0, ncopy.myarray, ncopy.nbelem, nbelem);
309         ncopy.nbelem = nsize;
310     }
311 
312     /**
313      * @param is
314      */
315     public void copyTo(int[] is) {
316         assert is.length >= nbelem;
317         System.arraycopy(myarray, 0, is, 0, nbelem);
318     }
319 
320     /*
321      * Copie un vecteur dans un autre (en vidant le premier), en temps constant.
322      */
323     public void moveTo(IVecInt dest) {
324         copyTo(dest);
325         nbelem = 0;
326     }
327 
328     public void moveTo2(IVecInt dest) {
329         VecInt ndest = (VecInt) dest;
330         int s = ndest.nbelem;
331         int tmp[] = ndest.myarray;
332         ndest.myarray = myarray;
333         ndest.nbelem = nbelem;
334         myarray = tmp;
335         nbelem = s;
336         nbelem = 0;
337     }
338 
339     public void moveTo(int dest, int source) {
340         myarray[dest] = myarray[source];
341     }
342 
343     public void moveTo(int[] dest) {
344         System.arraycopy(myarray, 0, dest, 0, nbelem);
345         nbelem = 0;
346     }
347 
348     /**
349      * Insert an element at the very begining of the vector. The former first
350      * element is appended to the end of the vector in order to have a constant
351      * time operation.
352      * 
353      * @param elem
354      *            the element to put first in the vector.
355      */
356     public void insertFirst(final int elem) {
357         if (nbelem > 0) {
358             push(myarray[0]);
359             myarray[0] = elem;
360             return;
361         }
362         push(elem);
363     }
364 
365     /**
366      * Enleve un element qui se trouve dans le vecteur!!!
367      * 
368      * @param elem
369      *            un element du vecteur
370      */
371     public void remove(int elem) {
372         assert size() > 0;
373         int j = 0;
374         for (; myarray[j] != elem; j++) {
375             assert j < size();
376         }
377         System.arraycopy(myarray, j + 1, myarray, j, size() - j);
378         pop();
379     }
380 
381     /**
382      * Delete the ith element of the vector. The latest element of the vector
383      * replaces the removed element at the ith indexer.
384      * 
385      * @param i
386      *            the indexer of the element in the vector
387      * @return the former ith element of the vector that is now removed from the
388      *         vector
389      */
390     public int delete(int i) {
391         assert i >= 0 && i < nbelem;
392         int ith = myarray[i];
393         myarray[i] = myarray[--nbelem];
394         return ith;
395     }
396 
397     private int nbelem;
398 
399     private int[] myarray;
400 
401     /*
402      * (non-Javadoc)
403      * 
404      * @see java.lang.int#toString()
405      */
406     @Override
407     public String toString() {
408         StringBuffer stb = new StringBuffer();
409         for (int i = 0; i < nbelem - 1; i++) {
410             stb.append(myarray[i]);
411             stb.append(","); //$NON-NLS-1$
412         }
413         if (nbelem > 0) {
414             stb.append(myarray[nbelem - 1]);
415         }
416         return stb.toString();
417     }
418 
419     private static Random rand = new Random(RANDOM_SEED);
420 
421     void selectionSort(int from, int to) {
422         int i, j, best_i;
423         int tmp;
424 
425         for (i = from; i < to - 1; i++) {
426             best_i = i;
427             for (j = i + 1; j < to; j++) {
428                 if (myarray[j] < myarray[best_i])
429                     best_i = j;
430             }
431             tmp = myarray[i];
432             myarray[i] = myarray[best_i];
433             myarray[best_i] = tmp;
434         }
435     }
436 
437     void sort(int from, int to) {
438         int width = to - from;
439         if (to - from <= 15)
440             selectionSort(from, to);
441 
442         else {
443             final int[] locarray = myarray;
444             int pivot = locarray[rand.nextInt(width) + from];
445             int tmp;
446             int i = from - 1;
447             int j = to;
448 
449             for (;;) {
450                 do
451                     i++;
452                 while (locarray[i] < pivot);
453                 do
454                     j--;
455                 while (pivot < locarray[j]);
456 
457                 if (i >= j)
458                     break;
459 
460                 tmp = locarray[i];
461                 locarray[i] = locarray[j];
462                 locarray[j] = tmp;
463             }
464 
465             sort(from, i);
466             sort(i, to);
467         }
468     }
469 
470     /**
471      * sort the vector using a custom quicksort.
472      */
473     public void sort() {
474         sort(0, nbelem);
475     }
476 
477     public void sortUnique() {
478         int i, j;
479         int last;
480         if (nbelem == 0)
481             return;
482 
483         sort(0, nbelem);
484         i = 1;
485         int[] locarray = myarray;
486         last = locarray[0];
487         for (j = 1; j < nbelem; j++) {
488             if (last < locarray[j]) {
489                 last = locarray[i] = locarray[j];
490                 i++;
491             }
492         }
493 
494         nbelem = i;
495     }
496 
497     /**
498      * Two vectors are equals iff they have the very same elements in the order.
499      * 
500      * @param obj
501      *            an object
502      * @return true iff obj is a VecInt and has the same elements as this vector
503      *         at each index.
504      * 
505      * @see java.lang.Object#equals(java.lang.Object)
506      */
507     @Override
508     public boolean equals(Object obj) {
509         if (obj instanceof VecInt) {
510             VecInt v = (VecInt) obj;
511             if (v.nbelem != nbelem)
512                 return false;
513             for (int i = 0; i < nbelem; i++) {
514                 if (v.myarray[i] != myarray[i]) {
515                     return false;
516                 }
517             }
518             return true;
519         }
520         return false;
521     }
522 
523     /*
524      * (non-Javadoc)
525      * 
526      * @see java.lang.Object#hashCode()
527      */
528     @Override
529     public int hashCode() {
530         long sum = 0;
531         for (int i = 0; i < nbelem; i++) {
532             sum += myarray[i];
533         }
534         return (int) sum / nbelem;
535     }
536 
537     /*
538      * (non-Javadoc)
539      * 
540      * @see org.sat4j.specs.IVecInt2#pushAll(org.sat4j.specs.IVecInt2)
541      */
542     public void pushAll(IVecInt vec) {
543         VecInt nvec = (VecInt) vec;
544         int nsize = nbelem + nvec.nbelem;
545         ensure(nsize);
546         System.arraycopy(nvec.myarray, 0, myarray, nbelem, nvec.nbelem);
547         nbelem = nsize;
548     }
549 
550     /**
551      * to detect that the vector is a subset of another one. Note that the
552      * method assumes that the two vectors are sorted!
553      * 
554      * @param vec
555      *            a vector
556      * @return true iff the current vector is a subset of vec
557      */
558     public boolean isSubsetOf(VecInt vec) {
559         int i = 0;
560         int j = 0;
561         while ((i < this.nbelem) && (j < vec.nbelem)) {
562             while ((j < vec.nbelem) && (vec.myarray[j] < this.myarray[i])) {
563                 j++;
564             }
565             if (j == vec.nbelem || this.myarray[i] != vec.myarray[j])
566                 return false;
567             i++;
568         }
569         return true;
570     }
571 
572     public Iterator<Integer> iterator() {
573         return new Iterator<Integer>() {
574             private int i = 0;
575 
576             public boolean hasNext() {
577                 return i < nbelem;
578             }
579 
580             public Integer next() {
581                 if (i == nbelem)
582                     throw new NoSuchElementException();
583                 return myarray[i++];
584             }
585 
586             public void remove() {
587                 throw new UnsupportedOperationException();
588             }
589         };
590     }
591 
592     public boolean isEmpty() {
593         return nbelem == 0;
594     }
595 }