package edu.stanford.nlp.sempre; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import fig.basic.LogInfo; import fig.basic.MapUtils; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Actually does the parsing. Main method is infer(), whose job is to fill in * * @author Roy Frostig * @author Percy Liang */ public abstract class ChartParserState extends ParserState { // cell (start, end, category) -> list of derivations (sorted by decreasing score) [beam] protected final Map<String, List<Derivation>>[][] chart; // For visualizing how chart is filled protected List<CatSpan> chartFillingList = new ArrayList<>(); protected String[][] phrases; // the phrases in the example @SuppressWarnings({ "unchecked" }) public ChartParserState(Parser parser, Params params, Example ex, boolean computeExpectedCounts) { super(parser, params, ex, computeExpectedCounts); // Initialize the chart. this.chart = (HashMap<String, List<Derivation>>[][]) Array.newInstance(HashMap.class, numTokens, numTokens + 1); this.phrases = new String[numTokens][numTokens + 1]; for (int start = 0; start < numTokens; start++) { StringBuilder sb = new StringBuilder(); for (int end = start + 1; end <= numTokens; end++) { if (end - start > 1) sb.append(' '); sb.append(this.ex.languageInfo.tokens.get(end - 1)); phrases[start][end] = sb.toString(); chart[start][end] = new HashMap<>(); } } } public void clearChart() { for (int start = 0; start < numTokens; start++) { for (int end = start + 1; end <= numTokens; end++) { chart[start][end].clear(); } } } // Call this method in infer() protected void setPredDerivations() { predDerivations.clear(); predDerivations.addAll(MapUtils.get(chart[0][numTokens], Rule.rootCat, Derivation.emptyList)); } private void visualizeChart() { for (int len = 1; len <= numTokens; ++len) { for (int i = 0; i + len <= numTokens; ++i) { for (String cat : chart[i][i + len].keySet()) { List<Derivation> derivations = chart[i][i + len].get(cat); for (Derivation deriv : derivations) { LogInfo.logs("ParserState.visualize: %s(%s:%s): %s", cat, i, i + len, deriv); } } } } } protected void addToChart(Derivation deriv) { if (parser.verbose(3)) LogInfo.logs("addToChart %s: %s", deriv.cat, deriv); if (Parser.opts.pruneErrorValues && deriv.value instanceof ErrorValue) return; List<Derivation> derivations = chart[deriv.start][deriv.end].get(deriv.cat); if (chart[deriv.start][deriv.end].get(deriv.cat) == null) chart[deriv.start][deriv.end].put(deriv.cat, derivations = new ArrayList<>()); derivations.add(deriv); totalGeneratedDerivs++; if (Parser.opts.visualizeChartFilling) { chartFillingList.add(new CatSpan(deriv.start, deriv.end, deriv.cat)); } } public Map<String, List<Derivation>>[][] getChart() { return chart; } // TODO(joberant): move to visualization utility class public static class CatSpan { @JsonProperty public final int start; @JsonProperty public final int end; @JsonProperty public final String cat; @JsonCreator public CatSpan(@JsonProperty("start") int start, @JsonProperty("end") int end, @JsonProperty("cat") String cat) { this.start = start; this.end = end; this.cat = cat; } } public static class ChartFillingData { @JsonProperty public final String id; @JsonProperty public final String utterance; @JsonProperty public final int numOfTokens; @JsonProperty public final List<CatSpan> catSpans; @JsonCreator public ChartFillingData(@JsonProperty("id") String id, @JsonProperty("catspans") List<CatSpan> catSpans, @JsonProperty("utterance") String utterance, @JsonProperty("numOfTokens") int numOfTokens) { this.id = id; this.utterance = utterance; this.numOfTokens = numOfTokens; this.catSpans = catSpans; } } }