package decoder; import extractors.Extractor; import is2.data.DataF; import is2.data.Edges; import is2.data.Parse; import is2.data.ParseNBest; import java.util.ArrayList; import java.util.concurrent.Callable; /** * @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<>(); // 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<>(); @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 (int l = 0; l < labels.length; l++) { p.types[p.ch] = labels[l]; 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 (int l = 0; l < labels.length; l++) { p.types[p.ch] = labels[l]; float p_new = (float) 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.isEmpty()) { return null; } return parents.remove(parents.size() - 1); } } }