View Javadoc

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