package is2.parser; import is2.data.DataFES; import is2.data.Parse; import java.util.ArrayList; import java.util.concurrent.ExecutorService; /** * @author Bernd Bohnet, 01.09.2009 * * This methods do the actual work and they build the dependency trees. */ final public class Decoder { public static final boolean TRAINING = true; public static long timeDecotder; public static long timeRearrange; /** * Threshold for rearrange edges non-projective */ public static float NON_PROJECTIVITY_THRESHOLD = 0.3F; static ExecutorService executerService = java.util.concurrent.Executors.newFixedThreadPool(Parser.THREADS); // do not initialize private Decoder() { } /** * Build a dependency tree based on the data * * @param pos part-of-speech tags * @param x the data * @param projective projective or non-projective * @param edges the edges * @return a parse tree * @throws InterruptedException */ public static Parse decode(short[] pos, DataFES x, boolean projective, boolean training) throws InterruptedException { long ts = System.nanoTime(); if (executerService.isShutdown()) { executerService = java.util.concurrent.Executors.newCachedThreadPool(); } final int n = pos.length; final Open O[][][][] = new Open[n][n][2][]; final Closed C[][][][] = new Closed[n][n][2][]; ArrayList<ParallelDecoder> pe = new ArrayList<>(); for (int i = 0; i < Parser.THREADS; i++) { pe.add(new ParallelDecoder(pos, x, O, C, n)); } for (short k = 1; k < n; k++) { // provide the threads the data for (short s = 0; s < n; s++) { short t = (short) (s + k); if (t >= n) { break; } ParallelDecoder.add(s, t); } executerService.invokeAll(pe); } float bestSpanScore = (-1.0F / 0.0F); Closed bestSpan = null; for (int m = 1; m < n; m++) { if (C[0][n - 1][1][m].p > bestSpanScore) { bestSpanScore = C[0][n - 1][1][m].p; bestSpan = C[0][n - 1][1][m]; } } // build the dependency tree from the chart Parse out = new Parse(pos.length); bestSpan.create(out); out.heads[0] = -1; out.labels[0] = 0; timeDecotder += (System.nanoTime() - ts); ts = System.nanoTime(); if (!projective) { rearrange(pos, out.heads, out.labels, x, training); } timeRearrange += (System.nanoTime() - ts); return out; } /** * This is the parallel non-projective edge re-arranger * * @param pos part-of-speech tags * @param heads parent child relation * @param labs edge labels * @param x the data * @param edges the existing edges defined by part-of-speech tags * @throws InterruptedException */ public static void rearrange(short[] pos, short[] heads, short[] labs, DataFES x, boolean training) throws InterruptedException { int threads = (pos.length > Parser.THREADS) ? Parser.THREADS : pos.length; // wh what to change, nPar - new parent, nType - new type short wh = -1, nPar = -1, nType = -1; ArrayList<ParallelRearrange> pe = new ArrayList<>(); while (true) { boolean[][] isChild = new boolean[heads.length][heads.length]; for (int i = 1, l1 = 1; i < heads.length; i++, l1 = i) { while ((l1 = heads[l1]) != -1) { isChild[l1][i] = true; } } float max = Float.NEGATIVE_INFINITY; float p = Extractor.encode3(pos, heads, labs, x); pe.clear(); for (int i = 0; i < threads; i++) { pe.add(new ParallelRearrange(isChild, pos, x, heads, labs)); } for (int ch = 1; ch < heads.length; ch++) { for (short pa = 0; pa < heads.length; pa++) { if (ch == pa || pa == heads[ch] || isChild[ch][pa]) { continue; } ParallelRearrange.add(p, (short) ch, pa); } } executerService.invokeAll(pe); for (ParallelRearrange.PA rp : ParallelRearrange.order) { if (max < rp.max) { max = rp.max; wh = rp.wh; nPar = rp.nPar; nType = rp.nType; } } ParallelRearrange.order.clear(); if (max <= NON_PROJECTIVITY_THRESHOLD) { break; // bb: changed from 0.0 } heads[wh] = nPar; labs[wh] = nType; } } public static String getInfo() { return "Decoder non-projectivity threshold: " + NON_PROJECTIVITY_THRESHOLD; } }