edu.stanford.nlp.util.FixedPrioritiesPriorityQueue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of stanford-corenlp Show documentation
Show all versions of stanford-corenlp Show documentation
Stanford CoreNLP provides a set of natural language analysis tools which can take raw English language text input and give the base forms of words, their parts of speech, whether they are names of companies, people, etc., normalize dates, times, and numeric quantities, mark up the structure of sentences in terms of phrases and word dependencies, and indicate which noun phrases refer to the same entities. It provides the foundational building blocks for higher level text understanding applications.
package edu.stanford.nlp.util;
import java.io.Serializable;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
/**
* A priority queue based on a binary heap. This implementation trades
* flexibility for speed: while it is up to 2x faster than {@link
* BinaryHeapPriorityQueue} and nearly as fast as {@link
* java.util.PriorityQueue}, it does not support removing or changing the
* priority of an element. Also, while {@link #getPriority(Object key)
* getPriority(Object key)} is supported, performance will be linear, not
* constant.
*
* @author Dan Klein, Bill MacCartney
*/
public class FixedPrioritiesPriorityQueue
extends AbstractSet
implements PriorityQueue, Iterator, Serializable, Cloneable {
private static final long serialVersionUID = 1L;
private int size;
private int capacity;
private List elements;
private double[] priorities;
// constructors ----------------------------------------------------------
public FixedPrioritiesPriorityQueue() {
this(15);
}
public FixedPrioritiesPriorityQueue(int capacity) {
int legalCapacity = 0;
while (legalCapacity < capacity) {
legalCapacity = 2 * legalCapacity + 1;
}
grow(legalCapacity);
}
// iterator methods ------------------------------------------------------
/**
* Returns true if the priority queue is non-empty
*/
public boolean hasNext() {
return ! isEmpty();
}
/**
* Returns the element in the queue with highest priority, and pops it from
* the queue.
*/
public E next() throws NoSuchElementException {
return removeFirst();
}
/**
* Not supported -- next() already removes the head of the queue.
*/
public void remove() {
throw new UnsupportedOperationException();
}
// PriorityQueue methods -------------------------------------------------
/**
* Adds a key to the queue with the given priority. If the key is already in
* the queue, it will be added an additional time, NOT promoted/demoted.
*
*/
public boolean add(E key, double priority) {
if (size == capacity) {
grow(2 * capacity + 1);
}
elements.add(key);
priorities[size] = priority;
heapifyUp(size);
size++;
return true;
}
/**
* Not supported in this implementation.
*/
public boolean changePriority(E key, double priority) {
throw new UnsupportedOperationException();
}
/**
* Returns the highest-priority element without removing it from the
* queue.
*/
public E getFirst() {
if (size() > 0)
return elements.get(0);
throw new NoSuchElementException();
}
/**
* Note that this method will be linear (not constant) time in this
* implementation! Better not to use it.
*/
public double getPriority(Object key) {
for (int i = 0, sz = elements.size(); i < sz; i++) {
if (elements.get(i).equals(key)) {
return priorities[i];
}
}
throw new NoSuchElementException();
}
/**
* Gets the priority of the highest-priority element of the queue.
*/
public double getPriority() {
// check empty other way around
if (size() > 0)
return priorities[0];
throw new NoSuchElementException();
}
/**
* Not supported in this implementation.
*/
public boolean relaxPriority(E key, double priority) {
throw new UnsupportedOperationException();
}
/**
* Returns the highest-priority element and removes it from the queue.
*/
public E removeFirst() throws NoSuchElementException {
E first = getFirst();
swap(0, size - 1);
size--;
elements.remove(size);
heapifyDown(0);
return first;
}
public List toSortedList() {
// initialize with size
List list = new ArrayList<>();
while (hasNext()) {
list.add(next());
}
return list;
}
// Set methods -----------------------------------------------------------
/**
* Number of elements in the queue.
*/
@Override
public int size() {
return size;
}
@Override
public void clear() {
size = 0;
grow(15);
}
@Override
public Iterator iterator() {
return Collections.unmodifiableCollection(toSortedList()).iterator();
}
// -----------------------------------------------------------------------
private void grow(int newCapacity) {
List newElements = new ArrayList<>(newCapacity);
double[] newPriorities = new double[newCapacity];
if (size > 0) {
newElements.addAll(elements);
System.arraycopy(priorities, 0, newPriorities, 0, priorities.length);
}
elements = newElements;
priorities = newPriorities;
capacity = newCapacity;
}
private static int parent(int loc) {
return (loc - 1) / 2;
}
private static int leftChild(int loc) {
return 2 * loc + 1;
}
private static int rightChild(int loc) {
return 2 * loc + 2;
}
private void heapifyUp(int loc) {
if (loc == 0) return;
int parent = parent(loc);
if (priorities[loc] > priorities[parent]) {
swap(loc, parent);
heapifyUp(parent);
}
}
private void heapifyDown(int loc) {
int max = loc;
int leftChild = leftChild(loc);
if (leftChild < size()) {
double priority = priorities[loc];
double leftChildPriority = priorities[leftChild];
if (leftChildPriority > priority)
max = leftChild;
int rightChild = rightChild(loc);
if (rightChild < size()) {
double rightChildPriority = priorities[rightChild(loc)];
if (rightChildPriority > priority && rightChildPriority > leftChildPriority)
max = rightChild;
}
}
if (max == loc)
return;
swap(loc, max);
heapifyDown(max);
}
private void swap(int loc1, int loc2) {
double tempPriority = priorities[loc1];
E tempElement = elements.get(loc1);
priorities[loc1] = priorities[loc2];
elements.set(loc1, elements.get(loc2));
priorities[loc2] = tempPriority;
elements.set(loc2, tempElement);
}
// -----------------------------------------------------------------------
/**
* Returns a representation of the queue in decreasing priority order.
*/
@Override
public String toString() {
return toString(size(), null);
}
/** {@inheritDoc} */
public String toString(int maxKeysToPrint) {
return toString(maxKeysToPrint, "%.3f");
}
/**
* Returns a representation of the queue in decreasing priority order,
* displaying at most maxKeysToPrint elements.
*
*/
public String toString(int maxKeysToPrint, String dblFmt) {
if (maxKeysToPrint <= 0) maxKeysToPrint = Integer.MAX_VALUE;
FixedPrioritiesPriorityQueue pq = clone();
StringBuilder sb = new StringBuilder("[");
int numKeysPrinted = 0;
while (numKeysPrinted < maxKeysToPrint && pq.hasNext()) {
double priority = pq.getPriority();
E element = pq.next();
sb.append(element);
sb.append('=');
if (dblFmt == null) {
sb.append(priority);
} else {
sb.append(String.format(dblFmt, priority));
}
if (numKeysPrinted < size() - 1)
sb.append(", ");
numKeysPrinted++;
}
if (numKeysPrinted < size()) {
sb.append("...");
}
sb.append("]");
return sb.toString();
}
/**
* Returns a clone of this priority queue. Modifications to one will not
* affect modifications to the other.
*/
@Override
public final FixedPrioritiesPriorityQueue clone() {
FixedPrioritiesPriorityQueue clonePQ;
try {
clonePQ = ErasureUtils.uncheckedCast(super.clone());
} catch (CloneNotSupportedException cnse) {
throw new AssertionError("Should be able to clone.");
}
clonePQ.elements = new ArrayList<>(capacity);
clonePQ.priorities = new double[capacity];
if (size() > 0) {
clonePQ.elements.addAll(elements);
System.arraycopy(priorities, 0, clonePQ.priorities, 0, size());
}
return clonePQ;
}
}