/*******************************************************************************
* SAT4J: a SATisfiability library for Java Copyright (C) 2004-2008 Daniel Le Berre
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU Lesser General Public License Version 2.1 or later (the
* "LGPL"), in which case the provisions of the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of the LGPL, and not to allow others to use your version of
* this file under the terms of the EPL, indicate your decision by deleting
* the provisions above and replace them with the notice and other provisions
* required by the LGPL. If you do not delete the provisions above, a recipient
* may use your version of this file under the terms of the EPL or the LGPL.
*
* Based on the original MiniSat specification from:
*
* An extensible SAT solver. Niklas Een and Niklas Sorensson. Proceedings of the
* Sixth International Conference on Theory and Applications of Satisfiability
* Testing, LNCS 2919, pp 502-518, 2003.
*
* See www.minisat.se for the original solver in C++.
*
*******************************************************************************/
package org.sat4j.core;
import java.util.NoSuchElementException;
import org.sat4j.specs.IVecInt;
import org.sat4j.specs.IteratorInt;
/*
* Created on 9 oct. 2003
*/
/**
* A vector specific for primitive integers, widely used in the solver. Note
* that if the vector has a sort method, the operations on the vector DO NOT
* preserve sorting.
*
* @author leberre
*/
public class VecInt implements IVecInt {
// MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
private static final long serialVersionUID = 1L;
public static final IVecInt EMPTY = new VecInt() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public int size() {
return 0;
}
@Override
public void shrink(int nofelems) {
}
@Override
public void shrinkTo(int newsize) {
}
@Override
public IVecInt pop() {
throw new UnsupportedOperationException();
}
@Override
public void growTo(int newsize, int pad) {
}
@Override
public void ensure(int nsize) {
}
@Override
public IVecInt push(int elem) {
throw new UnsupportedOperationException();
}
@Override
public void unsafePush(int elem) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
}
@Override
public int last() {
throw new UnsupportedOperationException();
}
@Override
public int get(int i) {
throw new UnsupportedOperationException();
}
@Override
public void set(int i, int o) {
throw new UnsupportedOperationException();
}
@Override
public boolean contains(int e) {
return false;
}
@Override
public void copyTo(IVecInt copy) {
}
@Override
public void copyTo(int[] is) {
}
@Override
public void moveTo(IVecInt dest) {
}
@Override
public void moveTo2(IVecInt dest) {
}
@Override
public void moveTo(int[] dest) {
}
@Override
public void insertFirst(int elem) {
throw new UnsupportedOperationException();
}
@Override
public void remove(int elem) {
throw new UnsupportedOperationException();
}
@Override
public int delete(int i) {
throw new UnsupportedOperationException();
}
@Override
public void sort() {
}
@Override
public void sortUnique() {
}
};
public VecInt() {
this(5);
}
public VecInt(int size) {
myarray = new int[size];
}
/**
* Adapter method to translate an array of int into an IVecInt.
*
* The array is used inside the VecInt, so the elements may be modified
* outside the VecInt. But it should not take much memory.The size of the
* created VecInt is the length of the array.
*
* @param lits
* a filled array of int.
*/
public VecInt(int[] lits) {
myarray = lits;
nbelem = lits.length;
}
/**
* Build a vector of a given initial size filled with an integer.
*
* @param size
* the initial size of the vector
* @param pad
* the integer to fill the vector with
*/
public VecInt(int size, int pad) {
myarray = new int[size];
for (int i = 0; i < size; i++) {
myarray[i] = pad;
}
nbelem = size;
}
public int size() {
return nbelem;
}
/**
* Remove the latest nofelems elements from the vector
*
* @param nofelems
*/
public void shrink(int nofelems) {
// assert nofelems >= 0;
// assert nofelems <= size();
nbelem -= nofelems;
}
public void shrinkTo(int newsize) {
// assert newsize >= 0;
// assert newsize < nbelem;
nbelem = newsize;
}
/**
* depile le dernier element du vecteur. Si le vecteur est vide, ne
* fait rien.
*/
public IVecInt pop() {
// assert size() != 0;
--nbelem;
return this;
}
public void growTo(int newsize, final int pad) {
// assert newsize > size();
ensure(newsize);
while (--newsize >= 0) {
myarray[nbelem++] = pad;
}
}
public void ensure(int nsize) {
if (nsize >= myarray.length) {
int[] narray = new int[Math.max(nsize, nbelem * 2)];
System.arraycopy(myarray, 0, narray, 0, nbelem);
myarray = narray;
}
}
public IVecInt push(int elem) {
ensure(nbelem + 1);
myarray[nbelem++] = elem;
return this;
}
public void unsafePush(int elem) {
myarray[nbelem++] = elem;
}
public void clear() {
nbelem = 0;
}
public int last() {
// assert nbelem > 0;
return myarray[nbelem - 1];
}
public int get(int i) {
// assert i >= 0 && i < nbelem;
return myarray[i];
}
public int unsafeGet(int i) {
return myarray[i];
}
public void set(int i, int o) {
assert i >= 0 && i < nbelem;
myarray[i] = o;
}
public boolean contains(int e) {
final int[] workArray = myarray; // dvh, faster access
for (int i = 0; i < nbelem; i++) {
if (workArray[i] == e)
return true;
}
return false;
}
public int containsAt(int e) {
return containsAt(e, -1);
}
public int containsAt(int e, int from) {
final int[] workArray = myarray; // dvh, faster access
for (int i = from+1; i < nbelem; i++) {
if (workArray[i] == e)
return i;
}
return -1;
}
/**
* Copy the content of this vector into another one.
* Non constant time operation.
*
* @param copy
*/
public void copyTo(IVecInt copy) {
VecInt ncopy = (VecInt) copy;
int nsize = nbelem + ncopy.nbelem;
ncopy.ensure(nsize);
System.arraycopy(myarray, 0, ncopy.myarray, ncopy.nbelem, nbelem);
ncopy.nbelem = nsize;
}
/**
* Copy the content of this vector into an array of integer.
* Non constant time operation.
*
* @param is
*/
public void copyTo(int[] is) {
// assert is.length >= nbelem;
System.arraycopy(myarray, 0, is, 0, nbelem);
}
public void moveTo(IVecInt dest) {
copyTo(dest);
nbelem = 0;
}
public void moveTo2(IVecInt dest) {
VecInt ndest = (VecInt) dest;
int s = ndest.nbelem;
int tmp[] = ndest.myarray;
ndest.myarray = myarray;
ndest.nbelem = nbelem;
myarray = tmp;
nbelem = s;
nbelem = 0;
}
public void moveTo(int dest, int source) {
myarray[dest] = myarray[source];
}
public void moveTo(int[] dest) {
System.arraycopy(myarray, 0, dest, 0, nbelem);
nbelem = 0;
}
/**
* Insert an element at the very begining of the vector. The former first
* element is appended to the end of the vector in order to have a constant
* time operation.
*
* @param elem
* the element to put first in the vector.
*/
public void insertFirst(final int elem) {
if (nbelem > 0) {
push(myarray[0]);
myarray[0] = elem;
return;
}
push(elem);
}
/**
* Enleve un element qui se trouve dans le vecteur!!!
*
* @param elem
* un element du vecteur
*/
public void remove(int elem) {
//assert size() > 0;
int j = 0;
for (; myarray[j] != elem; j++) {
assert j < size();
}
System.arraycopy(myarray, j + 1, myarray, j, size() - j);
pop();
}
/**
* Delete the ith element of the vector. The latest element of the vector
* replaces the removed element at the ith indexer.
*
* @param i
* the indexer of the element in the vector
* @return the former ith element of the vector that is now removed from the
* vector
*/
public int delete(int i) {
// assert i >= 0 && i < nbelem;
int ith = myarray[i];
myarray[i] = myarray[--nbelem];
return ith;
}
private int nbelem;
private int[] myarray;
/*
* (non-Javadoc)
*
* @see java.lang.int#toString()
*/
@Override
public String toString() {
StringBuffer stb = new StringBuffer();
for (int i = 0; i < nbelem - 1; i++) {
stb.append(myarray[i]);
stb.append(","); //$NON-NLS-1$
}
if (nbelem > 0) {
stb.append(myarray[nbelem - 1]);
}
return stb.toString();
}
void selectionSort(int from, int to) {
int i, j, best_i;
int tmp;
for (i = from; i < to - 1; i++) {
best_i = i;
for (j = i + 1; j < to; j++) {
if (myarray[j] < myarray[best_i])
best_i = j;
}
tmp = myarray[i];
myarray[i] = myarray[best_i];
myarray[best_i] = tmp;
}
}
void sort(int from, int to) {
int width = to - from;
if (width <= 15)
selectionSort(from, to);
else {
final int[] locarray = myarray;
int pivot = locarray[width/2 + from];
int tmp;
int i = from - 1;
int j = to;
for (;;) {
do
i++;
while (locarray[i] < pivot);
do
j--;
while (pivot < locarray[j]);
if (i >= j)
break;
tmp = locarray[i];
locarray[i] = locarray[j];
locarray[j] = tmp;
}
sort(from, i);
sort(i, to);
}
}
/**
* sort the vector using a custom quicksort.
*/
public void sort() {
sort(0, nbelem);
}
public void sortUnique() {
int i, j;
int last;
if (nbelem == 0)
return;
sort(0, nbelem);
i = 1;
int[] locarray = myarray;
last = locarray[0];
for (j = 1; j < nbelem; j++) {
if (last < locarray[j]) {
last = locarray[i] = locarray[j];
i++;
}
}
nbelem = i;
}
/**
* Two vectors are equals iff they have the very same elements in the order.
*
* @param obj
* an object
* @return true iff obj is a VecInt and has the same elements as this vector
* at each index.
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof VecInt) {
VecInt v = (VecInt) obj;
if (v.nbelem != nbelem)
return false;
for (int i = 0; i < nbelem; i++) {
if (v.myarray[i] != myarray[i]) {
return false;
}
}
return true;
}
return false;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
long sum = 0;
for (int i = 0; i < nbelem; i++) {
sum += myarray[i];
}
return (int) sum / nbelem;
}
/*
* (non-Javadoc)
*
* @see org.sat4j.specs.IVecInt2#pushAll(org.sat4j.specs.IVecInt2)
*/
public void pushAll(IVecInt vec) {
VecInt nvec = (VecInt) vec;
int nsize = nbelem + nvec.nbelem;
ensure(nsize);
System.arraycopy(nvec.myarray, 0, myarray, nbelem, nvec.nbelem);
nbelem = nsize;
}
/**
* to detect that the vector is a subset of another one. Note that the
* method assumes that the two vectors are sorted!
*
* @param vec
* a vector
* @return true iff the current vector is a subset of vec
*/
public boolean isSubsetOf(VecInt vec) {
int i = 0;
int j = 0;
while ((i < this.nbelem) && (j < vec.nbelem)) {
while ((j < vec.nbelem) && (vec.myarray[j] < this.myarray[i])) {
j++;
}
if (j == vec.nbelem || this.myarray[i] != vec.myarray[j])
return false;
i++;
}
return true;
}
public IteratorInt iterator() {
return new IteratorInt() {
private int i = 0;
public boolean hasNext() {
return i < nbelem;
}
public int next() {
if (i == nbelem)
throw new NoSuchElementException();
return myarray[i++];
}
};
}
public boolean isEmpty() {
return nbelem == 0;
}
public int[] toArray() {
return myarray;
}
}