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     };
216 
217     public VecInt() {
218         this(5);
219     }
220 
221     public VecInt(int size) {
222         this.myarray = new int[size];
223     }
224 
225     /**
226      * Adapter method to translate an array of int into an IVecInt.
227      * 
228      * The array is used inside the VecInt, so the elements may be modified
229      * outside the VecInt. But it should not take much memory.The size of the
230      * created VecInt is the length of the array.
231      * 
232      * @param lits
233      *            a filled array of int.
234      */
235     public VecInt(int[] lits) { // NOPMD
236         this.myarray = lits;
237         this.nbelem = lits.length;
238     }
239 
240     /**
241      * Build a vector of a given initial size filled with an integer.
242      * 
243      * @param size
244      *            the initial size of the vector
245      * @param pad
246      *            the integer to fill the vector with
247      */
248     public VecInt(int size, int pad) {
249         this.myarray = new int[size];
250         for (int i = 0; i < size; i++) {
251             this.myarray[i] = pad;
252         }
253         this.nbelem = size;
254     }
255 
256     public int size() {
257         return this.nbelem;
258     }
259 
260     /**
261      * Remove the latest nofelems elements from the vector
262      * 
263      * @param nofelems
264      */
265     public void shrink(int nofelems) {
266         // assert nofelems >= 0;
267         // assert nofelems <= size();
268         this.nbelem -= nofelems;
269     }
270 
271     public void shrinkTo(int newsize) {
272         // assert newsize >= 0;
273         // assert newsize < nbelem;
274         this.nbelem = newsize;
275     }
276 
277     /**
278      * depile le dernier element du vecteur. Si le vecteur est vide, ne fait
279      * rien.
280      */
281     public IVecInt pop() {
282         // assert size() != 0;
283         --this.nbelem;
284         return this;
285     }
286 
287     public void growTo(int newsize, final int pad) {
288         // assert newsize > size();
289         ensure(newsize);
290         while (--newsize >= 0) {
291             this.myarray[this.nbelem++] = pad;
292         }
293     }
294 
295     public void ensure(int nsize) {
296         if (nsize >= this.myarray.length) {
297             int[] narray = new int[Math.max(nsize, this.nbelem * 2)];
298             System.arraycopy(this.myarray, 0, narray, 0, this.nbelem);
299             this.myarray = narray;
300         }
301     }
302 
303     public IVecInt push(int elem) {
304         ensure(this.nbelem + 1);
305         this.myarray[this.nbelem++] = elem;
306         return this;
307     }
308 
309     public void unsafePush(int elem) {
310         this.myarray[this.nbelem++] = elem;
311     }
312 
313     public void clear() {
314         this.nbelem = 0;
315     }
316 
317     public int last() {
318         // assert nbelem > 0;
319         return this.myarray[this.nbelem - 1];
320     }
321 
322     public int get(int i) {
323         // assert i >= 0 && i < nbelem;
324         return this.myarray[i];
325     }
326 
327     public int unsafeGet(int i) {
328         return this.myarray[i];
329     }
330 
331     public void set(int i, int o) {
332         assert i >= 0 && i < this.nbelem;
333         this.myarray[i] = o;
334     }
335 
336     public boolean contains(int e) {
337         final int[] workArray = this.myarray; // dvh, faster access
338         for (int i = 0; i < this.nbelem; i++) {
339             if (workArray[i] == e) {
340                 return true;
341             }
342         }
343         return false;
344     }
345 
346     /**
347      * @since 2.2
348      */
349     public int indexOf(int e) {
350         final int[] workArray = this.myarray; // dvh, faster access
351         for (int i = 0; i < this.nbelem; i++) {
352             if (workArray[i] == e) {
353                 return i;
354             }
355         }
356         return -1;
357     }
358 
359     public int containsAt(int e) {
360         return containsAt(e, -1);
361     }
362 
363     public int containsAt(int e, int from) {
364         final int[] workArray = this.myarray; // dvh, faster access
365         for (int i = from + 1; i < this.nbelem; i++) {
366             if (workArray[i] == e) {
367                 return i;
368             }
369         }
370         return -1;
371     }
372 
373     /**
374      * Copy the content of this vector into another one. Non constant time
375      * operation.
376      * 
377      * @param copy
378      */
379     public void copyTo(IVecInt copy) {
380         VecInt ncopy = (VecInt) copy;
381         int nsize = this.nbelem + ncopy.nbelem;
382         ncopy.ensure(nsize);
383         System.arraycopy(this.myarray, 0, ncopy.myarray, ncopy.nbelem,
384                 this.nbelem);
385         ncopy.nbelem = nsize;
386     }
387 
388     /**
389      * Copy the content of this vector into an array of integer. Non constant
390      * time operation.
391      * 
392      * @param is
393      */
394     public void copyTo(int[] is) {
395         // assert is.length >= nbelem;
396         System.arraycopy(this.myarray, 0, is, 0, this.nbelem);
397     }
398 
399     public void moveTo(IVecInt dest) {
400         copyTo(dest);
401         this.nbelem = 0;
402     }
403 
404     public void moveTo2(IVecInt dest) {
405         VecInt ndest = (VecInt) dest;
406         int s = ndest.nbelem;
407         int tmp[] = ndest.myarray;
408         ndest.myarray = this.myarray;
409         ndest.nbelem = this.nbelem;
410         this.myarray = tmp;
411         this.nbelem = 0;
412     }
413 
414     public void moveTo(int dest, int source) {
415         this.myarray[dest] = this.myarray[source];
416     }
417 
418     public void moveTo(int[] dest) {
419         System.arraycopy(this.myarray, 0, dest, 0, this.nbelem);
420         this.nbelem = 0;
421     }
422 
423     public void moveTo(int sourceStartingIndex, int[] dest) {
424         System.arraycopy(this.myarray, sourceStartingIndex, dest, 0,
425                 this.nbelem - sourceStartingIndex);
426         this.nbelem = 0;
427     }
428 
429     /**
430      * Insert an element at the very begining of the vector. The former first
431      * element is appended to the end of the vector in order to have a constant
432      * time operation.
433      * 
434      * @param elem
435      *            the element to put first in the vector.
436      */
437     public void insertFirst(final int elem) {
438         if (this.nbelem > 0) {
439             push(this.myarray[0]);
440             this.myarray[0] = elem;
441             return;
442         }
443         push(elem);
444     }
445 
446     /**
447      * Enleve un element qui se trouve dans le vecteur!!!
448      * 
449      * @param elem
450      *            un element du vecteur
451      */
452     public void remove(int elem) {
453         // assert size() > 0;
454         int j = 0;
455         for (; this.myarray[j] != elem; j++) {
456             assert j < size();
457         }
458         System.arraycopy(this.myarray, j + 1, this.myarray, j, size() - j - 1);
459         pop();
460     }
461 
462     /**
463      * Delete the ith element of the vector. The latest element of the vector
464      * replaces the removed element at the ith indexer.
465      * 
466      * @param i
467      *            the indexer of the element in the vector
468      * @return the former ith element of the vector that is now removed from the
469      *         vector
470      */
471     public int delete(int i) {
472         // assert i >= 0 && i < nbelem;
473         int ith = this.myarray[i];
474         this.myarray[i] = this.myarray[--this.nbelem];
475         return ith;
476     }
477 
478     private int nbelem;
479 
480     private int[] myarray;
481 
482     /*
483      * (non-Javadoc)
484      * 
485      * @see java.lang.int#toString()
486      */
487     @Override
488     public String toString() {
489         StringBuffer stb = new StringBuffer();
490         for (int i = 0; i < this.nbelem - 1; i++) {
491             stb.append(this.myarray[i]);
492             stb.append(","); //$NON-NLS-1$
493         }
494         if (this.nbelem > 0) {
495             stb.append(this.myarray[this.nbelem - 1]);
496         }
497         return stb.toString();
498     }
499 
500     void selectionSort(int from, int to) {
501         int i, j, best_i;
502         int tmp;
503 
504         for (i = from; i < to - 1; i++) {
505             best_i = i;
506             for (j = i + 1; j < to; j++) {
507                 if (this.myarray[j] < this.myarray[best_i]) {
508                     best_i = j;
509                 }
510             }
511             tmp = this.myarray[i];
512             this.myarray[i] = this.myarray[best_i];
513             this.myarray[best_i] = tmp;
514         }
515     }
516 
517     void sort(int from, int to) {
518         int width = to - from;
519         if (width <= 15) {
520             selectionSort(from, to);
521         } else {
522             final int[] locarray = this.myarray;
523             int pivot = locarray[width / 2 + from];
524             int tmp;
525             int i = from - 1;
526             int j = to;
527 
528             for (;;) {
529                 do {
530                     i++;
531                 } while (locarray[i] < pivot);
532                 do {
533                     j--;
534                 } while (pivot < locarray[j]);
535 
536                 if (i >= j) {
537                     break;
538                 }
539 
540                 tmp = locarray[i];
541                 locarray[i] = locarray[j];
542                 locarray[j] = tmp;
543             }
544 
545             sort(from, i);
546             sort(i, to);
547         }
548     }
549 
550     /**
551      * sort the vector using a custom quicksort.
552      */
553     public void sort() {
554         sort(0, this.nbelem);
555     }
556 
557     public void sortUnique() {
558         int i, j;
559         int last;
560         if (this.nbelem == 0) {
561             return;
562         }
563 
564         sort(0, this.nbelem);
565         i = 1;
566         int[] locarray = this.myarray;
567         last = locarray[0];
568         for (j = 1; j < this.nbelem; j++) {
569             if (last < locarray[j]) {
570                 last = locarray[i] = locarray[j];
571                 i++;
572             }
573         }
574 
575         this.nbelem = i;
576     }
577 
578     /**
579      * Two vectors are equals iff they have the very same elements in the order.
580      * 
581      * @param obj
582      *            an object
583      * @return true iff obj is a VecInt and has the same elements as this vector
584      *         at each index.
585      * 
586      * @see java.lang.Object#equals(java.lang.Object)
587      */
588     @Override
589     public boolean equals(Object obj) {
590         if (obj instanceof VecInt) {
591             VecInt v = (VecInt) obj;
592             if (v.nbelem != this.nbelem) {
593                 return false;
594             }
595             for (int i = 0; i < this.nbelem; i++) {
596                 if (v.myarray[i] != this.myarray[i]) {
597                     return false;
598                 }
599             }
600             return true;
601         }
602         return false;
603     }
604 
605     /*
606      * (non-Javadoc)
607      * 
608      * @see java.lang.Object#hashCode()
609      */
610     @Override
611     public int hashCode() {
612         long sum = 0;
613         for (int i = 0; i < this.nbelem; i++) {
614             sum += this.myarray[i];
615         }
616         return (int) sum / this.nbelem;
617     }
618 
619     /*
620      * (non-Javadoc)
621      * 
622      * @see org.sat4j.specs.IVecInt2#pushAll(org.sat4j.specs.IVecInt2)
623      */
624     public void pushAll(IVecInt vec) {
625         VecInt nvec = (VecInt) vec;
626         int nsize = this.nbelem + nvec.nbelem;
627         ensure(nsize);
628         System.arraycopy(nvec.myarray, 0, this.myarray, this.nbelem,
629                 nvec.nbelem);
630         this.nbelem = nsize;
631     }
632 
633     /**
634      * to detect that the vector is a subset of another one. Note that the
635      * method assumes that the two vectors are sorted!
636      * 
637      * @param vec
638      *            a vector
639      * @return true iff the current vector is a subset of vec
640      */
641     public boolean isSubsetOf(VecInt vec) {
642         int i = 0;
643         int j = 0;
644         while (i < this.nbelem && j < vec.nbelem) {
645             while (j < vec.nbelem && vec.myarray[j] < this.myarray[i]) {
646                 j++;
647             }
648             if (j == vec.nbelem || this.myarray[i] != vec.myarray[j]) {
649                 return false;
650             }
651             i++;
652         }
653         return true;
654     }
655 
656     public IteratorInt iterator() {
657         return new IteratorInt() {
658             private int i = 0;
659 
660             public boolean hasNext() {
661                 return this.i < VecInt.this.nbelem;
662             }
663 
664             public int next() {
665                 if (this.i == VecInt.this.nbelem) {
666                     throw new NoSuchElementException();
667                 }
668                 return VecInt.this.myarray[this.i++];
669             }
670         };
671     }
672 
673     public boolean isEmpty() {
674         return this.nbelem == 0;
675     }
676 
677     /**
678      * @since 2.1
679      */
680     public int[] toArray() {
681         return this.myarray;
682     }
683 
684     /**
685      * @since 2.3.1
686      * @author sroussel
687      */
688     public IVecInt[] subset(int cardinal) {
689         List<IVecInt> liste = new ArrayList<IVecInt>();
690 
691         IVecInt[] result;
692 
693         if (cardinal == 1) {
694             result = new VecInt[this.size()];
695             for (int i = 0; i < this.size(); i++) {
696                 result[i] = new VecInt(new int[] { this.get(i) });
697             }
698             return result;
699         }
700 
701         if (this.size() == 0) {
702             result = new VecInt[0];
703             return result;
704         }
705 
706         VecInt subVec = new VecInt();
707         VecInt newVec;
708         this.copyTo(subVec);
709         subVec.remove(this.get(0));
710 
711         for (IVecInt vecWithFirst : subVec.subset(cardinal - 1)) {
712             newVec = new VecInt();
713             vecWithFirst.copyTo(newVec);
714             newVec.insertFirst(this.get(0));
715             liste.add(newVec);
716         }
717 
718         for (IVecInt vecWithoutFirst : subVec.subset(cardinal)) {
719             liste.add(vecWithoutFirst);
720         }
721 
722         result = new VecInt[liste.size()];
723         for (int i = 0; i < liste.size(); i++) {
724             result[i] = liste.get(i);
725         }
726         return result;
727     }
728 }