/*
* Copyright (C) 2009-2012 University of Freiburg
*
* This file is part of SMTInterpol.
*
* SMTInterpol is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SMTInterpol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with SMTInterpol. If not, see <http://www.gnu.org/licenses/>.
*/
package de.uni_freiburg.informatik.ultimate.smtinterpol.dpll;
import java.util.AbstractQueue;
import java.util.Iterator;
import de.uni_freiburg.informatik.ultimate.smtinterpol.Config;
public class AtomQueue extends AbstractQueue<DPLLAtom> {
DPLLAtom[] mAtoms;
int mSize;
public AtomQueue() {
mAtoms = new DPLLAtom[100];
mSize = 0;
}
@Override
public Iterator<DPLLAtom> iterator() {
return new Iterator<DPLLAtom>() {
int mPos = 0;
@Override
public boolean hasNext() {
return mPos < mSize;
}
@Override
public DPLLAtom next() {
return mAtoms[mPos++];
}
@Override
public void remove() {
AtomQueue.this.remove(mAtoms[mPos - 1]);
}
};
}
@Override
public int size() {
return mSize;
}
private void sink(DPLLAtom atom, int pos) {
int parent;
while (pos > 0
&& mAtoms[parent = (pos - 1) / 2].compareActivityTo(atom) > 0) {
mAtoms[pos] = mAtoms[parent];
mAtoms[pos].mAtomQueueIndex = pos;
pos = parent;
}
mAtoms[pos] = atom;
atom.mAtomQueueIndex = pos;
}
@Override
public boolean offer(DPLLAtom atom) {
assert atom.mAtomQueueIndex == -1
|| mAtoms[atom.mAtomQueueIndex] == atom;
if (Config.EXPENSIVE_ASSERTS) {
for (int i = 0; i < mSize; i++) {
assert mAtoms[i].mAtomQueueIndex == i;
assert mAtoms[i].mDecideStatus == null;
}
}
if (atom.mAtomQueueIndex != -1) {
return false;
}
if (mSize >= mAtoms.length) {
final DPLLAtom[] newAtoms = new DPLLAtom[2 * mSize];
System.arraycopy(mAtoms, 0, newAtoms, 0, mSize);
mAtoms = newAtoms;
}
sink(atom, mSize++);
return true;
}
@Override
public DPLLAtom peek() {
assert mSize <= 1 || (mAtoms[0].compareActivityTo(mAtoms[1]) <= 0);
assert mSize <= 2 || (mAtoms[0].compareActivityTo(mAtoms[2]) <= 0);
return mAtoms[0];
}
@Override
public DPLLAtom poll() {
final DPLLAtom atom = mAtoms[0];
remove(atom);
return atom;
}
@Override
public boolean contains(Object o) {
if (!(o instanceof DPLLAtom)) {
return false;
}
assert (((DPLLAtom) o).mAtomQueueIndex == -1
|| mAtoms[((DPLLAtom) o).mAtomQueueIndex] == o);
return (((DPLLAtom) o).mAtomQueueIndex != -1);
}
@Override
public boolean remove(Object o) {
if (!(o instanceof DPLLAtom)) {
return false;
}
if (Config.EXPENSIVE_ASSERTS) {
for (int i = 0; i < mSize; i++) {
assert mAtoms[i].mAtomQueueIndex == i;
assert mAtoms[i].mDecideStatus == null || mAtoms[i] == o;
}
}
final DPLLAtom atom = (DPLLAtom) o;
if (atom.mAtomQueueIndex == -1) {
return false;
}
assert mAtoms[atom.mAtomQueueIndex] == atom;
// remove the element
int pos = atom.mAtomQueueIndex;
atom.mAtomQueueIndex = -1;
// Move children of pos downwards to make a free spot on a leaf.
while (2 * pos + 2 < mSize) {
int child = 2 * pos + 1;
if (mAtoms[child].compareActivityTo(mAtoms[child + 1]) > 0) {
child++;
}
mAtoms[pos] = mAtoms[child];
mAtoms[pos].mAtomQueueIndex = pos;
pos = child;
}
// Now pos is a free position in the heap that is (or will be) a leaf.
// All special cases are handled:
// pos == m_size-1: free position at end, nothing to do.
// 2*pos+1 == m_size-1: pos has still a single child, but we move
// this into the free spot.
// in all other cases: move last element to the leaf and let it sink
// into the tree.
// check if the new free position is at the end.
if (pos != --mSize) {
// move the element from the last position to the free leaf
// and then upwards
sink(mAtoms[mSize], pos);
}
mAtoms[mSize] = null;
return true;
}
}