View Javadoc

1   /*******************************************************************************
2    * SAT4J: a SATisfiability library for Java Copyright (C) 2004, 2012 Artois University and CNRS
3    *
4    * All rights reserved. This program and the accompanying materials
5    * are made available under the terms of the Eclipse Public License v1.0
6    * which accompanies this distribution, and is available at
7    *  http://www.eclipse.org/legal/epl-v10.html
8    *
9    * Alternatively, the contents of this file may be used under the terms of
10   * either the GNU Lesser General Public License Version 2.1 or later (the
11   * "LGPL"), in which case the provisions of the LGPL are applicable instead
12   * of those above. If you wish to allow use of your version of this file only
13   * under the terms of the LGPL, and not to allow others to use your version of
14   * this file under the terms of the EPL, indicate your decision by deleting
15   * the provisions above and replace them with the notice and other provisions
16   * required by the LGPL. If you do not delete the provisions above, a recipient
17   * may use your version of this file under the terms of the EPL or the LGPL.
18   *
19   * Based on the original MiniSat specification from:
20   *
21   * An extensible SAT solver. Niklas Een and Niklas Sorensson. Proceedings of the
22   * Sixth International Conference on Theory and Applications of Satisfiability
23   * Testing, LNCS 2919, pp 502-518, 2003.
24   *
25   * See www.minisat.se for the original solver in C++.
26   *
27   * Contributors:
28   *   CRIL - initial API and implementation
29   *******************************************************************************/
30  package org.sat4j.core;
31  
32  import java.util.ArrayList;
33  import java.util.List;
34  import java.util.NoSuchElementException;
35  
36  import org.sat4j.specs.IVecInt;
37  import org.sat4j.specs.IteratorInt;
38  
39  /*
40   * Created on 9 oct. 2003
41   */
42  
43  /**
44   * A vector specific for primitive integers, widely used in the solver. Note
45   * that if the vector has a sort method, the operations on the vector DO NOT
46   * preserve sorting.
47   * 
48   * @author leberre
49   */
50  public final class VecInt implements IVecInt {
51      // MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
52      //
53      // Permission is hereby granted, free of charge, to any person obtaining a
54      // copy of this software and associated documentation files (the
55      // "Software"), to deal in the Software without restriction, including
56      // without limitation the rights to use, copy, modify, merge, publish,
57      // distribute, sublicense, and/or sell copies of the Software, and to
58      // permit persons to whom the Software is furnished to do so, subject to
59      // the following conditions:
60      //
61      // The above copyright notice and this permission notice shall be included
62      // in all copies or substantial portions of the Software.
63      //
64      // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
65      // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
66      // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
67      // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
68      // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
69      // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
70      // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
71  
72      private static final long serialVersionUID = 1L;
73  
74      public static final IVecInt EMPTY = new IVecInt() {
75  
76          /**
77  		 * 
78  		 */
79          private static final long serialVersionUID = 1L;
80  
81          public int size() {
82              return 0;
83          }
84  
85          public void shrink(int nofelems) {
86          }
87  
88          public void shrinkTo(int newsize) {
89          }
90  
91          public IVecInt pop() {
92              throw new UnsupportedOperationException();
93          }
94  
95          public void growTo(int newsize, int pad) {
96          }
97  
98          public void ensure(int nsize) {
99          }
100 
101         public IVecInt push(int elem) {
102             throw new UnsupportedOperationException();
103         }
104 
105         public void unsafePush(int elem) {
106             throw new UnsupportedOperationException();
107         }
108 
109         public void clear() {
110         }
111 
112         public int last() {
113             throw new UnsupportedOperationException();
114         }
115 
116         public int get(int i) {
117             throw new UnsupportedOperationException();
118         }
119 
120         public void set(int i, int o) {
121             throw new UnsupportedOperationException();
122         }
123 
124         public boolean contains(int e) {
125             return false;
126         }
127 
128         public void copyTo(IVecInt copy) {
129         }
130 
131         public void copyTo(int[] is) {
132         }
133 
134         public void moveTo(IVecInt dest) {
135         }
136 
137         public void moveTo2(IVecInt dest) {
138         }
139 
140         public void moveTo(int[] dest) {
141         }
142 
143         public void insertFirst(int elem) {
144             throw new UnsupportedOperationException();
145         }
146 
147         public void remove(int elem) {
148             throw new UnsupportedOperationException();
149         }
150 
151         public int delete(int i) {
152             throw new UnsupportedOperationException();
153         }
154 
155         public void sort() {
156         }
157 
158         public void sortUnique() {
159         }
160 
161         public int unsafeGet(int eleem) {
162             throw new UnsupportedOperationException();
163         }
164 
165         public int containsAt(int e) {
166             throw new UnsupportedOperationException();
167         }
168 
169         public int containsAt(int e, int from) {
170             throw new UnsupportedOperationException();
171         }
172 
173         public void moveTo(int dest, int source) {
174             throw new UnsupportedOperationException();
175         }
176 
177         public boolean isEmpty() {
178             return true;
179         }
180 
181         public IteratorInt iterator() {
182             return new IteratorInt() {
183 
184                 public boolean hasNext() {
185                     return false;
186                 }
187 
188                 public int next() {
189                     throw new UnsupportedOperationException();
190                 }
191             };
192         }
193 
194         public int[] toArray() {
195             throw new UnsupportedOperationException();
196         }
197 
198         public int indexOf(int e) {
199             return -1;
200         }
201 
202         @Override
203         public String toString() {
204             return "[]";
205         }
206 
207         public void moveTo(int sourceStartingIndex, int[] dest) {
208             throw new UnsupportedOperationException();
209         }
210 
211         public IVecInt[] subset(int cardinal) {
212             return new IVecInt[0];
213         };
214 
215         @Override
216         public boolean equals(Object o) {
217             if (o instanceof IVecInt) {
218                 return ((IVecInt) o).isEmpty();
219             }
220             return false;
221         }
222 
223         @Override
224         public int hashCode() {
225             return 0;
226         }
227     };
228 
229     public VecInt() {
230         this(5);
231     }
232 
233     public VecInt(int size) {
234         this.myarray = new int[size];
235     }
236 
237     /**
238      * Adapter method to translate an array of int into an IVecInt.
239      * 
240      * The array is used inside the VecInt, so the elements may be modified
241      * outside the VecInt. But it should not take much memory.The size of the
242      * created VecInt is the length of the array.
243      * 
244      * @param lits
245      *            a filled array of int.
246      */
247     public VecInt(int[] lits) { // NOPMD
248         this.myarray = lits;
249         this.nbelem = lits.length;
250     }
251 
252     /**
253      * Build a vector of a given initial size filled with an integer.
254      * 
255      * @param size
256      *            the initial size of the vector
257      * @param pad
258      *            the integer to fill the vector with
259      */
260     public VecInt(int size, int pad) {
261         this.myarray = new int[size];
262         for (int i = 0; i < size; i++) {
263             this.myarray[i] = pad;
264         }
265         this.nbelem = size;
266     }
267 
268     public int size() {
269         return this.nbelem;
270     }
271 
272     /**
273      * Remove the latest nofelems elements from the vector
274      * 
275      * @param nofelems
276      */
277     public void shrink(int nofelems) {
278         // assert nofelems >= 0;
279         // assert nofelems <= size();
280         this.nbelem -= nofelems;
281     }
282 
283     public void shrinkTo(int newsize) {
284         // assert newsize >= 0;
285         // assert newsize < nbelem;
286         this.nbelem = newsize;
287     }
288 
289     /**
290      * depile le dernier element du vecteur. Si le vecteur est vide, ne fait
291      * rien.
292      */
293     public IVecInt pop() {
294         // assert size() != 0;
295         --this.nbelem;
296         return this;
297     }
298 
299     public void growTo(int newsize, final int pad) {
300         // assert newsize > size();
301         ensure(newsize);
302         while (--newsize >= 0) {
303             this.myarray[this.nbelem++] = pad;
304         }
305     }
306 
307     public void ensure(int nsize) {
308         if (nsize >= this.myarray.length) {
309             int[] narray = new int[Math.max(nsize, this.nbelem * 2)];
310             System.arraycopy(this.myarray, 0, narray, 0, this.nbelem);
311             this.myarray = narray;
312         }
313     }
314 
315     public IVecInt push(int elem) {
316         ensure(this.nbelem + 1);
317         this.myarray[this.nbelem++] = elem;
318         return this;
319     }
320 
321     public void unsafePush(int elem) {
322         this.myarray[this.nbelem++] = elem;
323     }
324 
325     public void clear() {
326         this.nbelem = 0;
327     }
328 
329     public int last() {
330         // assert nbelem > 0;
331         return this.myarray[this.nbelem - 1];
332     }
333 
334     public int get(int i) {
335         // assert i >= 0 && i < nbelem;
336         return this.myarray[i];
337     }
338 
339     public int unsafeGet(int i) {
340         return this.myarray[i];
341     }
342 
343     public void set(int i, int o) {
344         assert i >= 0 && i < this.nbelem;
345         this.myarray[i] = o;
346     }
347 
348     public boolean contains(int e) {
349         final int[] workArray = this.myarray; // dvh, faster access
350         for (int i = 0; i < this.nbelem; i++) {
351             if (workArray[i] == e) {
352                 return true;
353             }
354         }
355         return false;
356     }
357 
358     /**
359      * @since 2.2
360      */
361     public int indexOf(int e) {
362         final int[] workArray = this.myarray; // dvh, faster access
363         for (int i = 0; i < this.nbelem; i++) {
364             if (workArray[i] == e) {
365                 return i;
366             }
367         }
368         return -1;
369     }
370 
371     public int containsAt(int e) {
372         return containsAt(e, -1);
373     }
374 
375     public int containsAt(int e, int from) {
376         final int[] workArray = this.myarray; // dvh, faster access
377         for (int i = from + 1; i < this.nbelem; i++) {
378             if (workArray[i] == e) {
379                 return i;
380             }
381         }
382         return -1;
383     }
384 
385     /**
386      * Copy the content of this vector into another one. Non constant time
387      * operation.
388      * 
389      * @param copy
390      */
391     public void copyTo(IVecInt copy) {
392         VecInt ncopy = (VecInt) copy;
393         int nsize = this.nbelem + ncopy.nbelem;
394         ncopy.ensure(nsize);
395         System.arraycopy(this.myarray, 0, ncopy.myarray, ncopy.nbelem,
396                 this.nbelem);
397         ncopy.nbelem = nsize;
398     }
399 
400     /**
401      * Copy the content of this vector into an array of integer. Non constant
402      * time operation.
403      * 
404      * @param is
405      */
406     public void copyTo(int[] is) {
407         // assert is.length >= nbelem;
408         System.arraycopy(this.myarray, 0, is, 0, this.nbelem);
409     }
410 
411     public void moveTo(IVecInt dest) {
412         copyTo(dest);
413         this.nbelem = 0;
414     }
415 
416     public void moveTo2(IVecInt dest) {
417         VecInt ndest = (VecInt) dest;
418         int tmp[] = ndest.myarray;
419         ndest.myarray = this.myarray;
420         ndest.nbelem = this.nbelem;
421         this.myarray = tmp;
422         this.nbelem = 0;
423     }
424 
425     public void moveTo(int dest, int source) {
426         this.myarray[dest] = this.myarray[source];
427     }
428 
429     public void moveTo(int[] dest) {
430         System.arraycopy(this.myarray, 0, dest, 0, this.nbelem);
431         this.nbelem = 0;
432     }
433 
434     public void moveTo(int sourceStartingIndex, int[] dest) {
435         System.arraycopy(this.myarray, sourceStartingIndex, dest, 0,
436                 this.nbelem - sourceStartingIndex);
437         this.nbelem = 0;
438     }
439 
440     /**
441      * Insert an element at the very begining of the vector. The former first
442      * element is appended to the end of the vector in order to have a constant
443      * time operation.
444      * 
445      * @param elem
446      *            the element to put first in the vector.
447      */
448     public void insertFirst(final int elem) {
449         if (this.nbelem > 0) {
450             push(this.myarray[0]);
451             this.myarray[0] = elem;
452             return;
453         }
454         push(elem);
455     }
456 
457     /**
458      * Enleve un element qui se trouve dans le vecteur!!!
459      * 
460      * @param elem
461      *            un element du vecteur
462      */
463     public void remove(int elem) {
464         // assert size() > 0;
465         int j = 0;
466         for (; this.myarray[j] != elem; j++) {
467             assert j < size();
468         }
469         System.arraycopy(this.myarray, j + 1, this.myarray, j, size() - j - 1);
470         pop();
471     }
472 
473     /**
474      * Delete the ith element of the vector. The latest element of the vector
475      * replaces the removed element at the ith indexer.
476      * 
477      * @param i
478      *            the indexer of the element in the vector
479      * @return the former ith element of the vector that is now removed from the
480      *         vector
481      */
482     public int delete(int i) {
483         // assert i >= 0 && i < nbelem;
484         int ith = this.myarray[i];
485         this.myarray[i] = this.myarray[--this.nbelem];
486         return ith;
487     }
488 
489     private int nbelem;
490 
491     private int[] myarray;
492 
493     /*
494      * (non-Javadoc)
495      * 
496      * @see java.lang.int#toString()
497      */
498     @Override
499     public String toString() {
500         StringBuffer stb = new StringBuffer();
501         for (int i = 0; i < this.nbelem - 1; i++) {
502             stb.append(this.myarray[i]);
503             stb.append(","); //$NON-NLS-1$
504         }
505         if (this.nbelem > 0) {
506             stb.append(this.myarray[this.nbelem - 1]);
507         }
508         return stb.toString();
509     }
510 
511     void selectionSort(int from, int to) {
512         int i, j, besti;
513         int tmp;
514 
515         for (i = from; i < to - 1; i++) {
516             besti = i;
517             for (j = i + 1; j < to; j++) {
518                 if (this.myarray[j] < this.myarray[besti]) {
519                     besti = j;
520                 }
521             }
522             tmp = this.myarray[i];
523             this.myarray[i] = this.myarray[besti];
524             this.myarray[besti] = tmp;
525         }
526     }
527 
528     void sort(int from, int to) {
529         int width = to - from;
530         if (width <= 15) {
531             selectionSort(from, to);
532         } else {
533             final int[] locarray = this.myarray;
534             int pivot = locarray[width / 2 + from];
535             int tmp;
536             int i = from - 1;
537             int j = to;
538 
539             for (;;) {
540                 do {
541                     i++;
542                 } while (locarray[i] < pivot);
543                 do {
544                     j--;
545                 } while (pivot < locarray[j]);
546 
547                 if (i >= j) {
548                     break;
549                 }
550 
551                 tmp = locarray[i];
552                 locarray[i] = locarray[j];
553                 locarray[j] = tmp;
554             }
555 
556             sort(from, i);
557             sort(i, to);
558         }
559     }
560 
561     /**
562      * sort the vector using a custom quicksort.
563      */
564     public void sort() {
565         sort(0, this.nbelem);
566     }
567 
568     public void sortUnique() {
569         int i, j;
570         int last;
571         if (this.nbelem == 0) {
572             return;
573         }
574 
575         sort(0, this.nbelem);
576         i = 1;
577         int[] locarray = this.myarray;
578         last = locarray[0];
579         for (j = 1; j < this.nbelem; j++) {
580             if (last < locarray[j]) {
581                 last = locarray[i] = locarray[j];
582                 i++;
583             }
584         }
585 
586         this.nbelem = i;
587     }
588 
589     /**
590      * Two vectors are equals iff they have the very same elements in the order.
591      * 
592      * @param obj
593      *            an object
594      * @return true iff obj is a VecInt and has the same elements as this vector
595      *         at each index.
596      * 
597      * @see java.lang.Object#equals(java.lang.Object)
598      */
599     @Override
600     public boolean equals(Object obj) {
601         if (obj instanceof IVecInt) {
602             IVecInt v = (IVecInt) obj;
603             if (v.size() != this.nbelem) {
604                 return false;
605             }
606             for (int i = 0; i < this.nbelem; i++) {
607                 if (v.get(i) != this.myarray[i]) {
608                     return false;
609                 }
610             }
611             return true;
612         }
613         return false;
614     }
615 
616     /*
617      * (non-Javadoc)
618      * 
619      * @see java.lang.Object#hashCode()
620      */
621     @Override
622     public int hashCode() {
623         long sum = 0;
624         for (int i = 0; i < this.nbelem; i++) {
625             sum += this.myarray[i];
626         }
627         return (int) sum / this.nbelem;
628     }
629 
630     /*
631      * (non-Javadoc)
632      * 
633      * @see org.sat4j.specs.IVecInt2#pushAll(org.sat4j.specs.IVecInt2)
634      */
635     public void pushAll(IVecInt vec) {
636         VecInt nvec = (VecInt) vec;
637         int nsize = this.nbelem + nvec.nbelem;
638         ensure(nsize);
639         System.arraycopy(nvec.myarray, 0, this.myarray, this.nbelem,
640                 nvec.nbelem);
641         this.nbelem = nsize;
642     }
643 
644     /**
645      * to detect that the vector is a subset of another one. Note that the
646      * method assumes that the two vectors are sorted!
647      * 
648      * @param vec
649      *            a vector
650      * @return true iff the current vector is a subset of vec
651      */
652     public boolean isSubsetOf(VecInt vec) {
653         int i = 0;
654         int j = 0;
655         while (i < this.nbelem && j < vec.nbelem) {
656             while (j < vec.nbelem && vec.myarray[j] < this.myarray[i]) {
657                 j++;
658             }
659             if (j == vec.nbelem || this.myarray[i] != vec.myarray[j]) {
660                 return false;
661             }
662             i++;
663         }
664         return true;
665     }
666 
667     public IteratorInt iterator() {
668         return new IteratorInt() {
669             private int i = 0;
670 
671             public boolean hasNext() {
672                 return this.i < VecInt.this.nbelem;
673             }
674 
675             public int next() {
676                 if (this.i == VecInt.this.nbelem) {
677                     throw new NoSuchElementException();
678                 }
679                 return VecInt.this.myarray[this.i++];
680             }
681         };
682     }
683 
684     public boolean isEmpty() {
685         return this.nbelem == 0;
686     }
687 
688     /**
689      * @since 2.1
690      */
691     public int[] toArray() {
692         return this.myarray;
693     }
694 
695     /**
696      * @since 2.3.1
697      * @author sroussel
698      */
699     public IVecInt[] subset(int cardinal) {
700         List<IVecInt> liste = new ArrayList<IVecInt>();
701 
702         IVecInt[] result;
703 
704         if (cardinal == 1) {
705             result = new VecInt[this.size()];
706             for (int i = 0; i < this.size(); i++) {
707                 result[i] = new VecInt(new int[] { this.get(i) });
708             }
709             return result;
710         }
711 
712         if (this.size() == 0) {
713             result = new VecInt[0];
714             return result;
715         }
716 
717         VecInt subVec = new VecInt();
718         VecInt newVec;
719         this.copyTo(subVec);
720         subVec.remove(this.get(0));
721 
722         for (IVecInt vecWithFirst : subVec.subset(cardinal - 1)) {
723             newVec = new VecInt();
724             vecWithFirst.copyTo(newVec);
725             newVec.insertFirst(this.get(0));
726             liste.add(newVec);
727         }
728 
729         for (IVecInt vecWithoutFirst : subVec.subset(cardinal)) {
730             liste.add(vecWithoutFirst);
731         }
732 
733         result = new VecInt[liste.size()];
734         for (int i = 0; i < liste.size(); i++) {
735             result[i] = liste.get(i);
736         }
737         return result;
738     }
739 }