package edu.stanford.nlp.sempre.tables.alignment;
import java.io.PrintWriter;
import java.util.*;
import edu.stanford.nlp.sempre.*;
import edu.stanford.nlp.sempre.tables.TableFormulaEvaluator;
import edu.stanford.nlp.sempre.tables.alignment.BitextData.BitextDataGroup;
import fig.basic.*;
import fig.exec.*;
public class AlignerMain implements Runnable {
public static class Options {
@Option public int verbose = 0;
@Option public AlignerName aligner = AlignerName.IBM1_Z_TO_X;
@Option(gloss = "probability that the target aligns to null source")
public NullWordHandling nullWordHandling = NullWordHandling.UNIFORM;
@Option(gloss = "if nullWordHandling == FIXED, use this as the null word probability")
public double fixedNullWordProb = 0.1;
}
public static Options opts = new Options();
public static enum AlignerName {
IBM1_X_TO_Z, // IBM model 1 from x to z
IBM1_Z_TO_X, // IBM model 1 from z to x
}
public static enum NullWordHandling {
FIXED, // Fixed as a constant
UNIFORM, // = 1 / (source length + 1)
TRAINED, // Treat as a word
}
public static final double epsilon = 1e-6;
public static void main(String[] args) {
Execution.run(args, "AlignerMainMain", new AlignerMain(), Master.getOptionsParser());
}
protected TableFormulaEvaluator evaluator;
protected AlignmentComputer alignmentComputer;
protected BitextData bitextData;
@Override
public void run() {
Builder builder = new Builder();
builder.build();
evaluator = (TableFormulaEvaluator) builder.valueEvaluator;
Dataset dataset = new Dataset();
dataset.read();
// Train the aligner. Only the "train" group is used.
bitextData = new BitextData(dataset.examples("train"));
switch (opts.aligner) {
case IBM1_X_TO_Z: alignmentComputer = new IBM1XToZAlignmentComputer(); break;
case IBM1_Z_TO_X: alignmentComputer = new IBM1ZToXAlignmentComputer(); break;
default: throw new RuntimeException("Unknown aligner: " + opts.aligner);
}
// Align and dump the results
alignmentComputer.align(bitextData);
dumpModel();
//computeAllScores();
evaluate(dataset.examples("dev"), "dev");
evaluate(dataset.examples("test"), "test");
}
/**
* Dump the model parameters into a file.
*/
protected void dumpModel() {
String filename = Execution.getFile("alignment");
LogInfo.begin_track("Writing to %s", filename);
try (PrintWriter out = new PrintWriter(filename)) {
alignmentComputer.dump(out);
} catch (Exception e) {
e.printStackTrace();
LogInfo.fail(e);
}
LogInfo.end_track();
}
/**
* Compute the candidate scores for all examples in the dataset.
*/
protected void computeAllScores() {
PrintWriter out = IOUtils.openOutHard(Execution.getFile("aligned-formulas.gz"));
for (BitextDataGroup group : bitextData.bitextDataGroups) {
List<Pair<Formula, Double>> scores = alignmentComputer.score(group);
Collections.sort(scores, new Pair.ReverseSecondComparator<Formula, Double>());
// Log to stdout
LogInfo.begin_track("%s", group.id);
LogInfo.logs("Tokens: %s", group.tokens);
for (Pair<Formula, Double> pair : scores)
LogInfo.logs("%10.3f : %s", pair.getSecond(), pair.getFirst());
LogInfo.end_track();
// Dump to gzip file
out.printf("########## Example %s ##########\n", group.id);
out.println("(example");
out.println(" " + LispTree.proto.newList("id", group.id));
out.println(" " + LispTree.proto.newList("utterance", group.ex.utterance));
out.println(" " + LispTree.proto.newList("targetValue", group.ex.targetValue.toLispTree()));
out.println(" " + group.ex.context.toLispTree());
out.println(" (derivations");
for (Pair<Formula, Double> pair : scores) {
if (pair.getSecond().isInfinite()) continue;
LispTree tree = LispTree.proto.newList();
tree.addChild(LispTree.proto.newLeaf("derivation"));
tree.addChild(LispTree.proto.newList("formula", pair.getFirst().toLispTree()));
tree.addChild(LispTree.proto.newList("score", String.format("%.3f", pair.getSecond())));
out.println(" " + tree);
}
out.println(" )");
out.println(")");
}
out.close();
}
protected void evaluate(List<Example> examples, String group) {
if (examples == null || examples.isEmpty()) return;
LogInfo.begin_track("AlignerMain.evaluate(%s)", group);
Evaluation totalEvaluation = new Evaluation();
for (Example ex : examples) {
LogInfo.begin_track("%s", ex.id);
LogInfo.logs("Utterance: %s", ex.utterance);
List<Pair<Formula, Double>> scores = alignmentComputer.score(new BitextDataGroup(ex));
Collections.sort(scores, new Pair.ReverseSecondComparator<Formula, Double>());
boolean correct = false, oracle = false;
if (scores.isEmpty()) {
LogInfo.logs("The beam is empty.");
} else {
Formula bestFormula = scores.get(0).getFirst();
evaluator.log(ex, bestFormula);
double compatibility = evaluator.getCompatibilityAnnotationStrict(ex, bestFormula);
if (compatibility > 0)
correct = true;
for (Pair<Formula, Double> pair : scores) {
if (evaluator.getCompatibilityAnnotationStrict(ex, pair.getFirst()) > 0) {
oracle = true;
break;
}
}
}
Evaluation evaluation = new Evaluation();
evaluation.add("correct", correct);
evaluation.add("oracle", oracle);
evaluation.add("numCandidates", scores.size());
if (!scores.isEmpty())
evaluation.add("parsedNumCandidates", scores.size());
LogInfo.logs("Current: %s", evaluation.summary());
totalEvaluation.add(evaluation);
LogInfo.logs("Cumulative(%s): %s", group, totalEvaluation.summary());
LogInfo.end_track();
}
totalEvaluation.logStats(group);
totalEvaluation.putOutput(group);
LogInfo.end_track();
}
}