// Path: src/main/java/edu/berkeley/nlp/lm/collections/BoundedList.java
// public class BoundedList<E> extends AbstractList<E>
// {
// 	private final E leftBoundary;
// 
// 	private final E rightBoundary;
// 
// 	private final List<E> list;
// 
// 	/**
// 	 * Returns the object at the given index, provided the index is between 0
// 	 * (inclusive) and size() (exclusive). If the index is < 0, then a left
// 	 * boundary object is returned. If the index is >= size(), a right boundary
// 	 * object is returned. The default boundary objects are both null, unless
// 	 * other objects are specified on construction.
// 	 */
// 	@Override
// 	public E get(final int index) {
// 		if (index < 0) return leftBoundary;
// 		if (index >= list.size()) return rightBoundary;
// 		return list.get(index);
// 	}
// 
// 	@Override
// 	public int size() {
// 		return list.size();
// 	}
// 
// 	public BoundedList(final List<E> list, final E leftBoundary, final E rightBoundary) {
// 		this.list = list;
// 		this.leftBoundary = leftBoundary;
// 		this.rightBoundary = rightBoundary;
// 	}
// 
// 	@Override
// 	public List<E> subList(final int fromIndex, final int toIndex) {
// 		final List<E> retVal = new ArrayList<E>(toIndex - fromIndex);
// 		for (int i = fromIndex; i < toIndex; ++i) {
// 			retVal.add(get(i));
// 		}
// 		return retVal;
// 	}
// 
// }


import java.util.List;
import edu.berkeley.nlp.lm.collections.BoundedList;
import edu.berkeley.nlp.lm.util.Annotations.OutputParameter;
package edu.berkeley.nlp.lm;



/**
 * Interface for language models which expose the internal context-encoding for
 * more efficient queries. (Note: language model implementations may internally
 * use a context-encoding without implementing this interface). A
 * context-encoding encodes an n-gram as a integer representing the last word,
 * and an offset which serves as a logical pointer to the (n-1) prefix words.
 * The integers represent words of type <code>W</code> in the vocabulary, and the mapping
 * from the vocabulary to integers is managed by an instance of the {@link WordIndexer} class.
 * 
 * @author adampauls
 * 
 * @param <W>
 */
public interface ContextEncodedNgramLanguageModel<W> extends NgramLanguageModel<W>
{

	/**
	 * Simple class for returning context offsets
	 * 
	 * @author adampauls
	 * 
	 */
	public static class LmContextInfo
	{

		/**
		 * Offset of context (prefix) of an n-gram
		 */
		public long offset = -1L;

		/**
		 * The (0-based) length of <code>context</code> (i.e.
		 * <code>order == 0</code> iff <code>context</code> refers to a
		 * unigram).
		 * 
		 * Use -1 for an empty context.
		 */
		public int order = -1;

	}

	/**
	 * Get the score for an n-gram, and also get the context offset of the
	 * n-gram's suffix.
	 * 
	 * @param contextOffset
	 *            Offset of context (prefix) of an n-gram
	 * @param contextOrder
	 *            The (0-based) length of <code>context</code> (i.e.
	 *            <code>order == 0</code> iff <code>context</code> refers to a
	 *            unigram).
	 * @param word
	 *            Last word of the n-gram
	 * @param outputContext
	 *            Offset of the suffix of the input n-gram. If the parameter is
	 *            <code>null</code> it will be ignored. This can be passed to
	 *            future queries for efficient access.
	 * @return
	 */
	public float getLogProb(long contextOffset, int contextOrder, int word, @OutputParameter LmContextInfo outputContext);

	/**
	 * Gets the offset which refers to an n-gram. If the n-gram is not in the
	 * model, then it returns the shortest suffix of the n-gram which is. This
	 * operation is not necessarily fast.
	 * 
	 */
	public LmContextInfo getOffsetForNgram(int[] ngram, int startPos, int endPos);

	/**
	 * Gets the n-gram referred to by a context-encoding. This operation is not
	 * necessarily fast.
	 * 
	 */
	public int[] getNgramForOffset(long contextOffset, int contextOrder, int word);

	public static class DefaultImplementations
	{

		public static <T> float scoreSentence(final List<T> sentence, final ContextEncodedNgramLanguageModel<T> lm) {
// Path: src/main/java/edu/berkeley/nlp/lm/collections/BoundedList.java
// public class BoundedList<E> extends AbstractList<E>
// {
// 	private final E leftBoundary;
// 
// 	private final E rightBoundary;
// 
// 	private final List<E> list;
// 
// 	/**
// 	 * Returns the object at the given index, provided the index is between 0
// 	 * (inclusive) and size() (exclusive). If the index is < 0, then a left
// 	 * boundary object is returned. If the index is >= size(), a right boundary
// 	 * object is returned. The default boundary objects are both null, unless
// 	 * other objects are specified on construction.
// 	 */
// 	@Override
// 	public E get(final int index) {
// 		if (index < 0) return leftBoundary;
// 		if (index >= list.size()) return rightBoundary;
// 		return list.get(index);
// 	}
// 
// 	@Override
// 	public int size() {
// 		return list.size();
// 	}
// 
// 	public BoundedList(final List<E> list, final E leftBoundary, final E rightBoundary) {
// 		this.list = list;
// 		this.leftBoundary = leftBoundary;
// 		this.rightBoundary = rightBoundary;
// 	}
// 
// 	@Override
// 	public List<E> subList(final int fromIndex, final int toIndex) {
// 		final List<E> retVal = new ArrayList<E>(toIndex - fromIndex);
// 		for (int i = fromIndex; i < toIndex; ++i) {
// 			retVal.add(get(i));
// 		}
// 		return retVal;
// 	}
// 
// }


// Path: src/main/java/edu/berkeley/nlp/lm/ContextEncodedNgramLanguageModel.java
import java.util.List;
import edu.berkeley.nlp.lm.collections.BoundedList;
import edu.berkeley.nlp.lm.util.Annotations.OutputParameter;

package edu.berkeley.nlp.lm;



/**
 * Interface for language models which expose the internal context-encoding for
 * more efficient queries. (Note: language model implementations may internally
 * use a context-encoding without implementing this interface). A
 * context-encoding encodes an n-gram as a integer representing the last word,
 * and an offset which serves as a logical pointer to the (n-1) prefix words.
 * The integers represent words of type <code>W</code> in the vocabulary, and the mapping
 * from the vocabulary to integers is managed by an instance of the {@link WordIndexer} class.
 * 
 * @author adampauls
 * 
 * @param <W>
 */
public interface ContextEncodedNgramLanguageModel<W> extends NgramLanguageModel<W>
{

	/**
	 * Simple class for returning context offsets
	 * 
	 * @author adampauls
	 * 
	 */
	public static class LmContextInfo
	{

		/**
		 * Offset of context (prefix) of an n-gram
		 */
		public long offset = -1L;

		/**
		 * The (0-based) length of <code>context</code> (i.e.
		 * <code>order == 0</code> iff <code>context</code> refers to a
		 * unigram).
		 * 
		 * Use -1 for an empty context.
		 */
		public int order = -1;

	}

	/**
	 * Get the score for an n-gram, and also get the context offset of the
	 * n-gram's suffix.
	 * 
	 * @param contextOffset
	 *            Offset of context (prefix) of an n-gram
	 * @param contextOrder
	 *            The (0-based) length of <code>context</code> (i.e.
	 *            <code>order == 0</code> iff <code>context</code> refers to a
	 *            unigram).
	 * @param word
	 *            Last word of the n-gram
	 * @param outputContext
	 *            Offset of the suffix of the input n-gram. If the parameter is
	 *            <code>null</code> it will be ignored. This can be passed to
	 *            future queries for efficient access.
	 * @return
	 */
	public float getLogProb(long contextOffset, int contextOrder, int word, @OutputParameter LmContextInfo outputContext);

	/**
	 * Gets the offset which refers to an n-gram. If the n-gram is not in the
	 * model, then it returns the shortest suffix of the n-gram which is. This
	 * operation is not necessarily fast.
	 * 
	 */
	public LmContextInfo getOffsetForNgram(int[] ngram, int startPos, int endPos);

	/**
	 * Gets the n-gram referred to by a context-encoding. This operation is not
	 * necessarily fast.
	 * 
	 */
	public int[] getNgramForOffset(long contextOffset, int contextOrder, int word);

	public static class DefaultImplementations
	{

		public static <T> float scoreSentence(final List<T> sentence, final ContextEncodedNgramLanguageModel<T> lm) {
			final List<T> sentenceWithBounds = new BoundedList<T>(sentence, lm.getWordIndexer().getStartSymbol(), lm.getWordIndexer().getEndSymbol());