ParallelRearrangeNBest2.java 3.34 KB
package decoder;

import java.util.ArrayList;
import java.util.concurrent.Callable;

import extractors.Extractor;
import is2.data.DataF;
import is2.data.Edges;
import is2.data.Parse;
import is2.data.ParseNBest;

/**
 * @author Dr. Bernd Bohnet, 30.08.2009
 *
 *         This class implements a parallel edge rearrangement for
 *         non-projective parsing; The linear method was first suggest by Rayn
 *         McDonald et. al. 2005.
 */
final public class ParallelRearrangeNBest2 implements Callable<Object> {

	// new parent child combination to explore
	final static class PA {
		final float p;
		final short ch, pa;

		public short[] heads, types;

		public PA(Parse p, short ch2, short pa2) {
			this.p = (float) p.f1;
			heads = p.heads;
			types = p.labels;
			ch = ch2;
			pa = pa2;

		}
	}

	// list of parent child combinations
	private static ArrayList<PA> parents = new ArrayList<PA>();

	// some data from the dependency tree
	private short[] pos;
	private DataF x;
	private float lastNBest;
	private float threshold;
	private Extractor extractor;

	/**
	 * Initialize the parallel rearrange thread
	 * 
	 * @param pos
	 *            the part-of-speech
	 * @param x
	 *            the data
	 * @param lastNBest
	 * @param isChild2
	 *            is a child
	 * @param edgesC
	 *            the part-of-speech edge mapping
	 * @param s
	 *            the heads
	 * @param ts
	 *            the types
	 */
	public ParallelRearrangeNBest2(short[] pos, DataF x, float lastNBest, Extractor extractor, float threshold) {

		this.lastNBest = lastNBest;
		this.pos = pos;
		this.x = x;

		this.extractor = extractor;
		this.threshold = threshold;
	}

	public ArrayList<ParseNBest> parses = new ArrayList<ParseNBest>();

	@Override
	public Object call() {

		try {

			while (true) {
				PA p = getPA();

				if (p == null)
					return parses;

				short oldP = p.heads[p.ch], oldT = p.types[p.ch];
				p.heads[p.ch] = p.pa;

				short[] labels = Edges.get(pos[p.pa], pos[p.ch], p.ch < p.pa);

				for (short label : labels) {

					p.types[p.ch] = label;
					float p_new = extractor.encode3(pos, p.heads, p.types, x);

					if (p_new < lastNBest || ((p.p + this.threshold) > p_new))
						continue;

					ParseNBest x = new ParseNBest();
					x.signature(p.heads, p.types);
					x.f1 = p_new;
					parses.add(x);
				}

				// change back
				p.heads[p.ch] = oldP;
				p.types[p.ch] = oldT;

				// consider changes to labels only
				labels = Edges.get(pos[oldP], pos[p.ch], p.ch < oldP);

				for (short label : labels) {

					p.types[p.ch] = label;
					float p_new = extractor.encode3(pos, p.heads, p.types, x);

					// optimization: add only if larger than smallest of n-best
					if (p_new < lastNBest || ((p.p + this.threshold) > p_new))
						continue;

					ParseNBest x = new ParseNBest();
					x.signature(p.heads, p.types);
					x.f1 = p_new;
					parses.add(x);
				}

				p.heads[p.ch] = oldP;
				p.types[p.ch] = oldT;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return parses;
	}

	/**
	 * Add a child-parent combination which are latter explored for
	 * rearrangement
	 *
	 * @param p2
	 * @param ch2
	 * @param pa
	 */
	public static void add(Parse p, short ch2, short pa) {
		parents.add(new PA(p, ch2, pa));
	}

	public static PA getPA() {
		synchronized (parents) {
			if (parents.size() == 0)
				return null;
			return parents.remove(parents.size() - 1);
		}
	}

}