package edu.stanford.nlp.sempre.tables.test; import java.io.PrintWriter; import java.io.StringWriter; import java.util.*; import edu.stanford.nlp.sempre.*; import edu.stanford.nlp.sempre.tables.TableKnowledgeGraph; import edu.stanford.nlp.sempre.tables.lambdadcs.LambdaDCSExecutor; import edu.stanford.nlp.sempre.tables.test.CustomExample.ExampleProcessor; import fig.basic.*; import fig.exec.Execution; public class DPDParserCheckerProcessor implements ExampleProcessor { public static class Options { @Option(gloss = "Only check annotated formulas (Don't check DPDParser beam)") public boolean onlyCheckAnnotatedFormulas = false; } public static Options opts = new Options(); int n = 0, annotated = 0, oracle = 0, beamHasCorrectFormula = 0, beamNoCorrectFormula = 0, noBeam = 0; final Builder builder; final PrintWriter eventsOut; public DPDParserCheckerProcessor() { builder = new Builder(); builder.build(); eventsOut = IOUtils.openOutHard(Execution.getFile("checker.results")); } @Override public void run(CustomExample ex) { n++; String formulaFlag = "", beamFlag = ""; if (ex.targetFormula == null) { formulaFlag = "no"; } else { annotated++; if (isAnnotatedFormulaCorrect(ex)) { oracle++; formulaFlag = "good"; } else { formulaFlag = "incorrect"; } } if (!opts.onlyCheckAnnotatedFormulas) { ParserState state = builder.parser.parse(builder.params, ex, false); LogInfo.logs("utterance: %s", ex.utterance); LogInfo.logs("targetFormula: %s", ex.targetFormula); LogInfo.logs("targetValue: %s", ex.targetValue); if (state.predDerivations.isEmpty()) { noBeam++; beamFlag = "no"; } else { Derivation correctDeriv = isCorrectFormulaOnBeam(ex, state.predDerivations); if (correctDeriv != null) { LogInfo.logs("Found correct formula: %s", correctDeriv); beamHasCorrectFormula++; beamFlag = "yes"; } else { beamNoCorrectFormula++; beamFlag = "reach"; } } LogInfo.logs("RESULT: %s %s %s", ex.id, formulaFlag, beamFlag); eventsOut.printf("%s\t%s\t%s\n", ex.id.replaceAll("nt-", ""), formulaFlag, beamFlag); eventsOut.flush(); } // Save memory if (ex.predDerivations != null) { ex.predDerivations.clear(); System.gc(); } } // See if all annotated formulas (targetFormula, alternativeFormulas) are correct boolean isAnnotatedFormulaCorrect(CustomExample ex) { boolean isCorrect = isAnnotatedFormulaCorrect(ex, ex.targetFormula, "targetFormula"); for (Formula formula : ex.alternativeFormulas) { isCorrect = isCorrect && isAnnotatedFormulaCorrect(ex, formula, "alternativeFormula"); } return isCorrect; } // See if a formula executes to the targetValue boolean isAnnotatedFormulaCorrect(CustomExample ex, Formula formula, String prefix) { LogInfo.begin_track("isAnnotatedFormulaCorrect(%s): Example %s", prefix, ex.id); StopWatch watch = new StopWatch(); watch.start(); LogInfo.logs("TRUE: %s", ex.targetValue); double result = 0; try { LogInfo.logs("Inferred Type: %s", TypeInference.inferType(formula)); Value pred = builder.executor.execute(formula, ex.context).value; if (pred instanceof ListValue) pred = ((TableKnowledgeGraph) ex.context.graph).getListValueWithOriginalStrings((ListValue) pred); LogInfo.logs("Example %s: %s", ex.id, ex.getTokens()); LogInfo.logs(" targetFormula: %s", formula); LogInfo.logs(" canonicalized: %s", TableFormulaCanonicalizer.canonicalizeFormula(formula)); LogInfo.logs("TRUE: %s", ex.targetValue); LogInfo.logs("PRED: %s", pred); result = builder.valueEvaluator.getCompatibility(ex.targetValue, pred); if (result != 1) { LogInfo.warnings("TRUE != PRED. %s Either targetValue or %s is wrong.", ex.id, prefix); } } catch (Exception e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); LogInfo.logs("Example %s: %s", ex.id, ex.getTokens()); LogInfo.logs(" targetFormula: %s", formula); LogInfo.logs(" canonicalized: %s", TableFormulaCanonicalizer.canonicalizeFormula(formula)); LogInfo.logs("TRUE: %s", ex.targetValue); LogInfo.logs("PRED: ERROR %s\n%s", e, sw); LogInfo.warnings("TRUE != PRED. %s Something was wrong during the execution.", ex.id); } watch.stop(); LogInfo.logs("Parse Time: %s", watch); LogInfo.end_track(); return result == 1; } Derivation isCorrectFormulaOnBeam(CustomExample ex, List<Derivation> predDerivations) { List<Formula> formulas = new ArrayList<>(); if (ex.targetFormula != null) formulas.add(TableFormulaCanonicalizer.canonicalizeFormula(ex.targetFormula)); if (ex.alternativeFormulas != null) for (Formula formula : ex.alternativeFormulas) formulas.add(TableFormulaCanonicalizer.canonicalizeFormula(formula)); for (Derivation deriv : predDerivations) { for (Formula formula : formulas) if (formula.equals(TableFormulaCanonicalizer.canonicalizeFormula(deriv.formula))) return deriv; } return null; } public void summarize() { LogInfo.logs("N = %d | Annotated = %d | Oracle = %d", n, annotated, oracle); Execution.putOutput("train.oracle.mean", oracle * 1.0 / n); Execution.putOutput("train.correct.count", n); if (!opts.onlyCheckAnnotatedFormulas) { LogInfo.logs("No Beam = %d", noBeam); LogInfo.logs("Beam has correct formula = %d", beamHasCorrectFormula); LogInfo.logs("Beam doesn't have correct formula = %d", beamNoCorrectFormula); Execution.putOutput("train.correct.mean", beamHasCorrectFormula * 1.0 / n); } if (builder.executor instanceof LambdaDCSExecutor) { ((LambdaDCSExecutor) builder.executor).summarize(); } StopWatchSet.logStats(); } }