You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@joshua.apache.org by mj...@apache.org on 2016/09/17 12:28:00 UTC

[11/14] incubator-joshua git commit: Reworked Decoder API a little bit. Flags during decoding are now taken from the Sentence object to allow sentence-specific flags

Reworked Decoder API a little bit. Flags during decoding are now taken from the Sentence object to allow sentence-specific flags


Project: http://git-wip-us.apache.org/repos/asf/incubator-joshua/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-joshua/commit/2e3b10b9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-joshua/tree/2e3b10b9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-joshua/diff/2e3b10b9

Branch: refs/heads/7_confsystem
Commit: 2e3b10b92cc3a30a9e7c2dd92906ff9be244afa6
Parents: 26dcdb6
Author: Hieber, Felix <fh...@amazon.de>
Authored: Fri Sep 16 13:30:11 2016 +0200
Committer: Hieber, Felix <fh...@amazon.de>
Committed: Fri Sep 16 13:30:11 2016 +0200

----------------------------------------------------------------------
 .../java/org/apache/joshua/decoder/Decoder.java | 65 +++++++++++++-------
 .../apache/joshua/decoder/DecoderConfig.java    | 15 +----
 .../org/apache/joshua/decoder/DecoderTask.java  | 13 ++--
 .../apache/joshua/decoder/JoshuaDecoder.java    |  4 +-
 .../joshua/decoder/StructuredTranslation.java   |  2 +-
 .../org/apache/joshua/decoder/Translation.java  | 59 +++++++++---------
 .../joshua/decoder/chart_parser/Chart.java      |  7 ++-
 .../apache/joshua/decoder/ff/tm/Grammar.java    |  5 +-
 .../decoder/ff/tm/hash_based/TextGrammar.java   | 12 ++--
 .../ff/tm/hash_based/TextGrammarFactory.java    | 35 ++++++-----
 .../decoder/ff/tm/packed/PackedGrammar.java     |  3 +-
 .../decoder/hypergraph/KBestExtractor.java      | 12 ++--
 .../joshua/decoder/phrase/PhraseTable.java      | 11 ++--
 .../apache/joshua/decoder/phrase/Stacks.java    |  6 +-
 .../joshua/decoder/segment_file/Sentence.java   | 26 ++++----
 .../org/apache/joshua/server/ServerThread.java  |  8 +--
 16 files changed, 154 insertions(+), 129 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/Decoder.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/Decoder.java b/joshua-core/src/main/java/org/apache/joshua/decoder/Decoder.java
index 1b21bb5..4943f0f 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/Decoder.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/Decoder.java
@@ -97,11 +97,20 @@ import com.typesafe.config.ConfigValueFactory;
 public class Decoder {
 
   private static final Logger LOG = LoggerFactory.getLogger(Decoder.class);
+  
+  /*
+   * The immutable configuration used to initialize the decoder.
+   * Sentences may have specific overrides, but the decoder flags are immutable.
+   */
+  private final Config flags;
 
   /*
    * Holds the common (immutable) decoder state (features, grammars etc.) after initialization
    */
   private final DecoderConfig decoderConfig;
+
+  private final int numParallelDecoders;
+  private final SearchAlgorithm searchAlgorithm;
   
   private static final ImmutableList<String> GRAMMAR_PACKAGES = ImmutableList.of(
       "org.apache.joshua.decoder.ff.tm.hash_based",
@@ -118,12 +127,22 @@ public class Decoder {
    *
    * @param joshuaConfiguration a populated {@link org.apache.joshua.decoder.JoshuaConfiguration}
    */
-  public Decoder(Config config) {
-    this.decoderConfig = initialize(config); 
+  public Decoder(Config flags) {
+    this.flags = flags;
+    this.searchAlgorithm = SearchAlgorithm.valueOf(flags.getString("search_algorithm"));
+    this.numParallelDecoders = flags.getInt("num_parallel_decoders");
+    this.decoderConfig = initialize(flags);
+  }
+  
+  /**
+   * Returns the flags this decoder was initialized with.
+   */
+  public Config getFlags() {
+    return flags;
   }
   
   /**
-   * Returns the default Decoder flags.
+   * Returns the default configuration for {@link Decoder}.
    */
   public static Config getDefaultFlags() {
     final ConfigParseOptions options = ConfigParseOptions.defaults().setAllowMissing(false);
@@ -131,11 +150,11 @@ public class Decoder {
   }
   
   /**
-   * Returns a fully-specified decoder flags {@link Config} from the given
-   * Config. This is the preferable way to include default configuration and ensures 
+   * Returns fully-specified decoder flags with the given
+   * Config as override. This is the preferable way to include default configuration and ensures 
    * certain format correctness at runtime.
    */
-  public static Config createDecoderFlags(final Config userFlags) {
+  public static Config getFlags(final Config userFlags) {
     final Config defaultFlags = Decoder.getDefaultFlags();
     final Config allFlags = userFlags.resolveWith(defaultFlags).withFallback(defaultFlags);
     return allFlags
@@ -143,16 +162,13 @@ public class Decoder {
       .withValue("goal_symbol", ConfigValueFactory.fromAnyRef(ensureNonTerminalBrackets(allFlags.getString("goal_symbol"))));
   }
   
-  public static Config createDecoderFlagsFromFile(final File fileName) {
-    final ConfigParseOptions options = ConfigParseOptions.defaults().setAllowMissing(false);
-    return createDecoderFlags(ConfigFactory.parseFile(fileName, options));
-  }
-  
   /**
-   * Returns the DecoderConfig
+   * Returns fully-specified decoder flags with overrides
+   * loaded from the given file in TypeSafeConfig syntax.
    */
-  public DecoderConfig getDecoderConfig() {
-    return decoderConfig;
+  public static Config getFlagsFromFile(final File fileName) {
+    final ConfigParseOptions options = ConfigParseOptions.defaults().setAllowMissing(false);
+    return getFlags(ConfigFactory.parseFile(fileName, options));
   }
 
   /**
@@ -178,7 +194,6 @@ public class Decoder {
             .setNameFormat("TranslationWorker-%d")
             .setDaemon(true)
             .build();
-    int numParallelDecoders = this.decoderConfig.getFlags().getInt("num_parallel_decoders");
     ExecutorService executor = Executors.newFixedThreadPool(numParallelDecoders, threadFactory);
     try {
       for (; ; ) {
@@ -205,9 +220,8 @@ public class Decoder {
 
 
   /**
-   * Decode call for a single sentence.
-   * Creates a sentence-specific {@link DecoderConfig} including
-   * sentence-specific OOVGrammar.
+   * Decode call for a single sentence
+   * using the flags specified in the Sentence object.
    *
    * @param sentence {@link org.apache.joshua.lattice.Lattice} input
    * @return the sentence {@link org.apache.joshua.decoder.Translation}
@@ -219,11 +233,18 @@ public class Decoder {
   }
   
   /**
+   * Returns the current weights in the decoder;
+   */
+  public FeatureVector getWeights() {
+    return decoderConfig.getWeights();
+  }
+  
+  /**
    * Creates a sentence-specific {@link DecoderConfig}.
    * Most importantly, adds an OOV grammar for the words of this
    * sentence.
    */
-  private static DecoderConfig createSentenceDecoderConfig(
+  private DecoderConfig createSentenceDecoderConfig(
       final Sentence sentence, final DecoderConfig globalConfig) {
     
     // create a new list of grammars that includes the OOVgrammar
@@ -236,13 +257,13 @@ public class Decoder {
         break;
     case stack:
       grammars 
-        .add(TextGrammarFactory.createEndRulePhraseTable(sentence, globalConfig))
+        .add(TextGrammarFactory.createEndRulePhraseTable())
         .add(TextGrammarFactory.createOovPhraseTable(sentence, globalConfig));
       break;
     }
     
     return new DecoderConfig(
-        globalConfig.getFlags(),
+        this.searchAlgorithm,
         globalConfig.getFeatureFunctions(),
         grammars.addAll(globalConfig.getGrammars()).build(),
         globalConfig.getCustomGrammar(),
@@ -316,7 +337,7 @@ public class Decoder {
     // TODO(fhieber): right now we still rely on static variables for vocab etc.
     // this should be changed and then we pass the instance of vocab etc. in here
     return new DecoderConfig(
-        config,
+        searchAlgorithm,
         featureFunctions,
         ImmutableList.copyOf(grammars),
         customGrammar,

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/DecoderConfig.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/DecoderConfig.java b/joshua-core/src/main/java/org/apache/joshua/decoder/DecoderConfig.java
index 71ee40c..8dc4dd1 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/DecoderConfig.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/DecoderConfig.java
@@ -26,10 +26,9 @@ import org.apache.joshua.decoder.ff.tm.Grammar;
 import org.apache.joshua.decoder.ff.tm.OwnerMap;
 
 import com.google.common.collect.ImmutableList;
-import com.typesafe.config.Config;
 
 /**
- * This is the central config/state object that holds references to relevant attributes
+ * This is the central state object that holds references to relevant attributes
  * of the decoder (features, grammars, etc.).
  * A sentence-specific instance of this object is created before
  * translating a single sentence.
@@ -38,9 +37,6 @@ import com.typesafe.config.Config;
  */
 public class DecoderConfig {
   
-  /** Decoder flags */ 
-  private final Config flags;
-  
   /** Decoder feature functions */
   private final ImmutableList<FeatureFunction> featureFunctions;
   
@@ -65,7 +61,7 @@ public class DecoderConfig {
   private final SearchAlgorithm searchAlgorithm;
   
   public DecoderConfig(
-      final Config flags,
+      final SearchAlgorithm searchAlgorithm,
       final ImmutableList<FeatureFunction> featureFunctions,
       final ImmutableList<Grammar> grammars,
       final Grammar customGrammar,
@@ -73,7 +69,7 @@ public class DecoderConfig {
       final FeatureVector weights,
       final FeatureMap featureMap,
       final OwnerMap ownerMap) {
-    this.flags = flags;
+    this.searchAlgorithm = searchAlgorithm;
     this.featureFunctions = featureFunctions;
     this.grammars = grammars;
     this.customGrammar = customGrammar;
@@ -81,11 +77,6 @@ public class DecoderConfig {
     this.weights = weights;
     this.featureMap = featureMap;
     this.ownerMap = ownerMap;
-    this.searchAlgorithm = SearchAlgorithm.valueOf(flags.getString("search_algorithm"));
-  }
-
-  public Config getFlags() {
-    return flags;
   }
 
   public ImmutableList<FeatureFunction> getFeatureFunctions() {

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/DecoderTask.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/DecoderTask.java b/joshua-core/src/main/java/org/apache/joshua/decoder/DecoderTask.java
index d820d7d..5953c7e 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/DecoderTask.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/DecoderTask.java
@@ -26,6 +26,7 @@ import org.apache.joshua.decoder.hypergraph.GrammarBuilderWalkerFunction;
 import org.apache.joshua.decoder.hypergraph.HyperGraph;
 import org.apache.joshua.decoder.phrase.Stacks;
 import org.apache.joshua.decoder.segment_file.Sentence;
+import org.apache.joshua.util.FormatUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -56,13 +57,15 @@ public class DecoderTask {
   private final boolean segmentOovs;
   private final boolean useDotChart;
   private final boolean doParsing;
+  private final String goalSymbol;
 
   public DecoderTask(final DecoderConfig sentenceConfig, final Sentence sentence) {
     this.sentenceConfig = sentenceConfig;
     this.sentence = sentence;
-    this.segmentOovs = sentenceConfig.getFlags().getBoolean("segment_oovs");
-    this.useDotChart = sentenceConfig.getFlags().getBoolean("use_dot_chart");
-    this.doParsing = sentenceConfig.getFlags().getBoolean("parse");
+    this.segmentOovs = sentence.getFlags().getBoolean("segment_oovs");
+    this.useDotChart = sentence.getFlags().getBoolean("use_dot_chart");
+    this.doParsing = sentence.getFlags().getBoolean("parse");
+    this.goalSymbol = FormatUtils.ensureNonTerminalBrackets(sentence.getFlags().getString("goal_symbol"));
   }
 
   /**
@@ -135,14 +138,14 @@ public class DecoderTask {
   private Translation parse(final HyperGraph hypergraph) {
     long startTime = System.currentTimeMillis();
     // Step 1. Traverse the hypergraph to create a grammar for the second-pass parse.
-    final Grammar newGrammar = getGrammarFromHyperGraph(sentenceConfig.getFlags().getString("goal_symbol"), hypergraph);
+    final Grammar newGrammar = getGrammarFromHyperGraph(goalSymbol, hypergraph);
     newGrammar.sortGrammar(sentenceConfig.getFeatureFunctions());
     long sortTime = System.currentTimeMillis();
     LOG.info("Sentence {}: New grammar has {} rules.", sentence.id(),
         newGrammar.getNumRules());
 
     /* Step 2. Create a new chart and parse with the instantiated grammar. */
-    final Sentence targetSentence = new Sentence(sentence.target(), sentence.id(), sentenceConfig.getFlags());
+    final Sentence targetSentence = new Sentence(sentence.target(), sentence.id(), sentence.getFlags());
     final Chart chart = new Chart(targetSentence, sentenceConfig);
     int goalSymbol = GrammarBuilderWalkerFunction.goalSymbol(hypergraph);
     String goalSymbolString = Vocabulary.word(goalSymbol);

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/JoshuaDecoder.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/JoshuaDecoder.java b/joshua-core/src/main/java/org/apache/joshua/decoder/JoshuaDecoder.java
index 1c90924..705f1f7 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/JoshuaDecoder.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/JoshuaDecoder.java
@@ -81,7 +81,7 @@ public class JoshuaDecoder {
     if (configFile == null) {
       return commandLineOverrides.withFallback(Decoder.getDefaultFlags()).resolve();
     } else {
-      return commandLineOverrides.withFallback(Decoder.createDecoderFlagsFromFile(configFile)).resolve();
+      return commandLineOverrides.withFallback(Decoder.getFlagsFromFile(configFile)).resolve();
     }
   }
   
@@ -124,7 +124,7 @@ public class JoshuaDecoder {
         new TcpServer(decoder, port).start();
 
       } else if (serverType == ServerType.HTTP) {
-        checkState(decoder.getDecoderConfig().getFlags().getBoolean("use_structured_output"));
+        checkState(config.getBoolean("use_structured_output"));
 
         HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
         LOG.info("HTTP Server running and listening on port {}.", port);

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/StructuredTranslation.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/StructuredTranslation.java b/joshua-core/src/main/java/org/apache/joshua/decoder/StructuredTranslation.java
index 454e0bb..0dae9b1 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/StructuredTranslation.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/StructuredTranslation.java
@@ -128,7 +128,7 @@ public class StructuredTranslation {
   private String maybeProjectCase(String hypothesis) {
     String output = hypothesis;
 
-    if (sourceSentence.getConfig().getBoolean("project_case")) {
+    if (sourceSentence.getFlags().getBoolean("project_case")) {
       String[] tokens = hypothesis.split("\\s+");
       List<List<Integer>> points = getTranslationWordAlignments();
       for (int i = 0; i < points.size(); i++) {

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/Translation.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/Translation.java b/joshua-core/src/main/java/org/apache/joshua/decoder/Translation.java
index 4ccf79c..b889b91 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/Translation.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/Translation.java
@@ -50,7 +50,7 @@ import org.slf4j.LoggerFactory;
 
 public class Translation {
   private static final Logger LOG = LoggerFactory.getLogger(Translation.class);
-  private final Sentence source;
+  private final Sentence sourceSentence;
 
   /**
    * This stores the output of the translation so we don't have to hold onto the hypergraph while we
@@ -65,21 +65,26 @@ public class Translation {
    */
   private List<StructuredTranslation> structuredTranslations = null;
 
-  public Translation(final Sentence source,
+  public Translation(final Sentence sourceSentence,
       final HyperGraph hypergraph, DecoderConfig config) {
-    this.source = source;
+    this.sourceSentence = sourceSentence;
+    final boolean useStructuredOutput = sourceSentence.getFlags().getBoolean("use_structured_output");
+    final int topN = sourceSentence.getFlags().getInt("top_n");
+    final String outputFormat = sourceSentence.getFlags().getString("output_format");
+    final boolean rescoreForest = sourceSentence.getFlags().getBoolean("rescore_forest");
+    final double rescoreForestWeight = sourceSentence.getFlags().getDouble("rescore_forest_weight");
 
     /**
      * Structured output from Joshua provides a way to programmatically access translation results
      * from downstream applications, instead of writing results as strings to an output buffer.
      */
-    if (config.getFlags().getBoolean("use_structured_output")) {
+    if (useStructuredOutput) {
 
-      if (config.getFlags().getInt("top_n") == 0) {
+      if (topN == 0) {
         /*
          * Obtain Viterbi StructuredTranslation
          */
-        StructuredTranslation translation = fromViterbiDerivation(source, hypergraph, config.getFeatureFunctions());
+        StructuredTranslation translation = fromViterbiDerivation(sourceSentence, hypergraph, config.getFeatureFunctions());
         this.output = translation.getTranslationString();
         structuredTranslations = Collections.singletonList(translation);
 
@@ -87,11 +92,11 @@ public class Translation {
         /*
          * Get K-Best list of StructuredTranslations
          */
-        final KBestExtractor kBestExtractor = new KBestExtractor(source, config, false);
-        structuredTranslations = kBestExtractor.KbestExtractOnHG(hypergraph, config.getFlags().getInt("top_n"));
+        final KBestExtractor kBestExtractor = new KBestExtractor(sourceSentence, config, false);
+        structuredTranslations = kBestExtractor.KbestExtractOnHG(hypergraph, topN);
         if (structuredTranslations.isEmpty()) {
             structuredTranslations = Collections
-                .singletonList(StructuredTranslationFactory.fromEmptyOutput(source));
+                .singletonList(StructuredTranslationFactory.fromEmptyOutput(sourceSentence));
             this.output = "";
         } else {
             this.output = structuredTranslations.get(0).getTranslationString();
@@ -110,31 +115,30 @@ public class Translation {
 
           long startTime = System.currentTimeMillis();
 
-          if (config.getFlags().getInt("top_n") == 0) {
+          if (topN == 0) {
 
             /* construct Viterbi output */
             final String best = getViterbiString(hypergraph);
 
-            LOG.info("Translation {}: {} {}", source.id(), hypergraph.goalNode.getScore(), best);
+            LOG.info("Translation {}: {} {}", sourceSentence.id(), hypergraph.goalNode.getScore(), best);
 
             /*
              * Setting topN to 0 turns off k-best extraction, in which case we need to parse through
              * the output-string, with the understanding that we can only substitute variables for the
              * output string, sentence number, and model score.
              */
-            String outputFormat = config.getFlags().getString("output_format");
             String translation = outputFormat
                 .replace("%s", removeSentenceMarkers(best))
                 .replace("%S", DeNormalize.processSingleLine(best))
                 .replace("%c", String.format("%.3f", hypergraph.goalNode.getScore()))
-                .replace("%i", String.format("%d", source.id()));
+                .replace("%i", String.format("%d", sourceSentence.id()));
 
             if (outputFormat.contains("%a")) {
               translation = translation.replace("%a", getViterbiWordAlignments(hypergraph));
             }
 
             if (outputFormat.contains("%f")) {
-              final FeatureVector features = getViterbiFeatures(hypergraph, config.getFeatureFunctions(), source);
+              final FeatureVector features = getViterbiFeatures(hypergraph, config.getFeatureFunctions(), sourceSentence);
               translation = translation.replace("%f", features.textFormat());
             }
 
@@ -144,28 +148,27 @@ public class Translation {
           } else {
 
             final KBestExtractor kBestExtractor = new KBestExtractor(
-                source, config, false);
-            kBestExtractor.lazyKBestExtractOnHG(hypergraph, config.getFlags().getInt("top_n"), out);
+                sourceSentence, config, false);
+            kBestExtractor.lazyKBestExtractOnHG(hypergraph, topN, out);
 
-            if (config.getFlags().getBoolean("rescore_forest")) {
+            if (rescoreForest) {
               final int bleuFeatureHash = hashFeature("BLEU");
               // TODO(fhieber): this is fishy, why would we want to change the decoder weights HERE?
-              config.getWeights().add(bleuFeatureHash, (float) config.getFlags().getDouble("rescore_forest_weight"));
-              kBestExtractor.lazyKBestExtractOnHG(hypergraph, config.getFlags().getInt("top_n"), out);
+              config.getWeights().add(bleuFeatureHash, (float) rescoreForestWeight);
+              kBestExtractor.lazyKBestExtractOnHG(hypergraph, topN, out);
 
-              config.getWeights().add(bleuFeatureHash, -(float) config.getFlags().getDouble("rescore_forest_weight"));
-              kBestExtractor.lazyKBestExtractOnHG(hypergraph, config.getFlags().getInt("top_n"), out);
+              config.getWeights().add(bleuFeatureHash, -(float) rescoreForestWeight);
+              kBestExtractor.lazyKBestExtractOnHG(hypergraph, topN, out);
             }
           }
 
           float seconds = (System.currentTimeMillis() - startTime) / 1000.0f;
-          LOG.info("Input {}: {}-best extraction took {} seconds", id(),
-              config.getFlags().getInt("top_n"), seconds);
+          LOG.info("Input {}: {}-best extraction took {} seconds", id(), topN, seconds);
 
         } else {
 
           // Failed translations and blank lines get empty formatted outputs
-          out.write(getFailedTranslationOutput(source, config.getFlags().getString("output_format")));
+          out.write(getFailedTranslationOutput(sourceSentence, outputFormat));
           out.newLine();
 
         }
@@ -181,23 +184,23 @@ public class Translation {
     }
 
     // Force any StateMinimizingLanguageModel pool mappings to be cleaned
-    source.getStateManager().clearStatePool();
+    sourceSentence.getStateManager().clearStatePool();
 
   }
 
   public Sentence getSourceSentence() {
-    return this.source;
+    return this.sourceSentence;
   }
 
   public int id() {
-    return source.id();
+    return sourceSentence.id();
   }
 
   @Override
   public String toString() {
     return output;
   }
-
+  
   private String getFailedTranslationOutput(final Sentence source, final String outputFormat) {
     return outputFormat
         .replace("%s", source.source())

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/chart_parser/Chart.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/chart_parser/Chart.java b/joshua-core/src/main/java/org/apache/joshua/decoder/chart_parser/Chart.java
index 7bfd830..9eb27ee 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/chart_parser/Chart.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/chart_parser/Chart.java
@@ -41,6 +41,7 @@ import org.apache.joshua.lattice.Arc;
 import org.apache.joshua.lattice.Lattice;
 import org.apache.joshua.lattice.Node;
 import org.apache.joshua.util.ChartSpan;
+import org.apache.joshua.util.FormatUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -103,14 +104,14 @@ public class Chart {
   public Chart(final Sentence sentence, final DecoderConfig config) {
     
     this.config = config;
-    this.numTranslationOptions = config.getFlags().getInt("num_translation_options");
-    this.popLimit = config.getFlags().getInt("pop_limit");
+    this.numTranslationOptions = sentence.getFlags().getInt("num_translation_options");
+    this.popLimit = sentence.getFlags().getInt("pop_limit");
     
     this.inputLattice = sentence.getLattice();
     this.sourceLength = inputLattice.size() - 1;
     this.sentence = sentence;
     this.cells = new ChartSpan<>(sourceLength, null);
-    this.goalSymbolID = Vocabulary.id(config.getFlags().getString("goal_symbol"));
+    this.goalSymbolID = Vocabulary.id(FormatUtils.ensureNonTerminalBrackets(sentence.getFlags().getString("goal_symbol")));
     this.goalBin = new Cell(this, this.goalSymbolID);
 
     // each grammar will have a dot chart

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/Grammar.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/Grammar.java b/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/Grammar.java
index 67271de..fcee52c 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/Grammar.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/Grammar.java
@@ -20,9 +20,10 @@ package org.apache.joshua.decoder.ff.tm;
 
 import java.util.List;
 
-import org.apache.joshua.decoder.DecoderConfig;
 import org.apache.joshua.decoder.ff.FeatureFunction;
 
+import com.typesafe.config.Config;
+
 /**
  * Grammar is a class for wrapping a trie of TrieGrammar in order to store holistic metadata.
  * 
@@ -100,7 +101,7 @@ public interface Grammar {
   /**
    * Add an OOV rule for the requested word for the grammar.
    */
-  void addOOVRules(int word, DecoderConfig config);
+  void addOOVRules(int sourceWord, Config sentenceFlags, List<FeatureFunction> featureFunctions);
   
   /**
    * Add a rule to the grammar.

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/hash_based/TextGrammar.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/hash_based/TextGrammar.java b/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/hash_based/TextGrammar.java
index 5923965..b4b6f71 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/hash_based/TextGrammar.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/hash_based/TextGrammar.java
@@ -18,13 +18,14 @@
  */
 package org.apache.joshua.decoder.ff.tm.hash_based;
 
+import static org.apache.joshua.util.FormatUtils.ensureNonTerminalBrackets;
+
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Optional;
 
 import org.apache.joshua.corpus.Vocabulary;
-import org.apache.joshua.decoder.DecoderConfig;
 import org.apache.joshua.decoder.ff.FeatureFunction;
 import org.apache.joshua.decoder.ff.FeatureVector;
 import org.apache.joshua.decoder.ff.tm.AbstractGrammar;
@@ -162,13 +163,14 @@ public class TextGrammar extends AbstractGrammar {
    * @param featureFunctions {@link java.util.List} of {@link org.apache.joshua.decoder.ff.FeatureFunction}'s
    */
   @Override
-  public void addOOVRules(int sourceWord, DecoderConfig config) {
+  public void addOOVRules(int sourceWord, Config sentenceFlags, List<FeatureFunction> featureFunctions) {
 
     // TODO: _OOV shouldn't be outright added, since the word might not be OOV for the LM (but now
     // almost
     // certainly is)
-    final int targetWord = config.getFlags().getBoolean("mark_oovs") ? Vocabulary.id(Vocabulary
+    final int targetWord = sentenceFlags.getBoolean("mark_oovs") ? Vocabulary.id(Vocabulary
         .word(sourceWord) + "_OOV") : sourceWord;
+    final int lhs = Vocabulary.id(ensureNonTerminalBrackets(sentenceFlags.getString("default_non_terminal")));
 
     final int[] sourceWords = { sourceWord };
     final int[] targetWords = { targetWord };
@@ -176,7 +178,7 @@ public class TextGrammar extends AbstractGrammar {
     final FeatureVector features = new FeatureVector(0);
 
     final Rule oovRule = new Rule(
-          Vocabulary.id(config.getFlags().getString("default_non_terminal")),
+          lhs,
           sourceWords,
           targetWords,
           0,
@@ -184,7 +186,7 @@ public class TextGrammar extends AbstractGrammar {
           alignment,
           getOwner());
     addRule(oovRule);
-    oovRule.estimateRuleCost(config.getFeatureFunctions());
+    oovRule.estimateRuleCost(featureFunctions);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/hash_based/TextGrammarFactory.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/hash_based/TextGrammarFactory.java b/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/hash_based/TextGrammarFactory.java
index e72f703..6bcbff7 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/hash_based/TextGrammarFactory.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/hash_based/TextGrammarFactory.java
@@ -37,7 +37,6 @@ public class TextGrammarFactory {
     final Config config = ConfigFactory.parseMap(
         ImmutableMap.of("owner", GLUE_OWNER, "span_limit", "-1"), "Glue Grammar Config");
     final TextGrammar glueGrammar = new TextGrammar(config);
-    final HieroFormatReader reader = new HieroFormatReader(glueGrammar.getOwner());
     final String goalNT = FormatUtils.cleanNonTerminal(goalSymbol);
     final String defaultNT = FormatUtils.cleanNonTerminal(defaultNonTerminal);
     
@@ -49,11 +48,13 @@ public class TextGrammarFactory {
         String.format("[%s] ||| [%s,1] %s ||| [%s,1] %s ||| 0", goalNT, goalNT,
             Vocabulary.STOP_SYM, goalNT, Vocabulary.STOP_SYM) };
     
-    for (String ruleString : ruleStrings) {
-      Rule rule = reader.parseLine(ruleString);
-      glueGrammar.addRule(rule);
-      // glue rules do not any features
-      rule.estimateRuleCost(emptyList());
+    try(HieroFormatReader reader = new HieroFormatReader(glueGrammar.getOwner());) {
+      for (String ruleString : ruleStrings) {
+        Rule rule = reader.parseLine(ruleString);
+        glueGrammar.addRule(rule);
+        // glue rules do not any features
+        rule.estimateRuleCost(emptyList());
+      }
     }
     return glueGrammar;
   }
@@ -75,16 +76,17 @@ public class TextGrammarFactory {
     final Config config = ConfigFactory.parseMap(
         ImmutableMap.of("owner", "lattice", "span_limit", "-1"), "Epsilon Grammar Config");
     final TextGrammar latticeGrammar = new TextGrammar(config);
-    final HieroFormatReader reader = new HieroFormatReader(latticeGrammar.getOwner());
     final String goalNT = FormatUtils.cleanNonTerminal(goalSymbol);
     final String defaultNT = FormatUtils.cleanNonTerminal(defaultNonTerminal);
 
     //FIXME: arguments changed to match string format on best effort basis.  Author please review.
     final String ruleString = String.format("[%s] ||| [%s,1] <eps> ||| [%s,1] ||| ", goalNT, defaultNT, defaultNT);
     
-    final Rule rule = reader.parseLine(ruleString);
-    latticeGrammar.addRule(rule);
-    rule.estimateRuleCost(emptyList());
+    try(HieroFormatReader reader = new HieroFormatReader(latticeGrammar.getOwner());) {
+      final Rule rule = reader.parseLine(ruleString);
+      latticeGrammar.addRule(rule);
+      rule.estimateRuleCost(emptyList());
+    }
     return latticeGrammar;
   }
   
@@ -92,9 +94,9 @@ public class TextGrammarFactory {
     final Config grammarConfig = ConfigFactory.parseMap(
         ImmutableMap.of("owner", OOV_OWNER, "span_limit", "20"), "OOV grammar config");
     final TextGrammar oovGrammar = new TextGrammar(grammarConfig);
-    final Set<Integer> words = getOovCandidateWords(sentence, config.getFlags().getBoolean("true_oovs_only"));
+    final Set<Integer> words = getOovCandidateWords(sentence);
     for (int sourceWord: words) {
-      oovGrammar.addOOVRules(sourceWord, config);
+      oovGrammar.addOOVRules(sourceWord, sentence.getFlags(), config.getFeatureFunctions());
     }
     // Sort all the rules (not much to actually do, this just marks it as sorted)
     oovGrammar.sortGrammar(config.getFeatureFunctions());
@@ -105,9 +107,9 @@ public class TextGrammarFactory {
     final Config grammarConfig = ConfigFactory.parseMap(
         ImmutableMap.of("owner", OOV_OWNER, "span_limit", "0"), "OOV phrase table config");
     final PhraseTable oovPhraseTable = new PhraseTable(grammarConfig);
-    final Set<Integer> words = getOovCandidateWords(sentence, config.getFlags().getBoolean("true_oovs_only"));
+    final Set<Integer> words = getOovCandidateWords(sentence);
     for (int sourceWord: words) {
-      oovPhraseTable.addOOVRules(sourceWord, config);
+      oovPhraseTable.addOOVRules(sourceWord, sentence.getFlags(), config.getFeatureFunctions());
     }
     // Sort all the rules (not much to actually do, this just marks it as sorted)
     oovPhraseTable.sortGrammar(config.getFeatureFunctions());
@@ -118,8 +120,9 @@ public class TextGrammarFactory {
    * Returns a set of integer ids for which OOV rules will be created.
    * The set is determined by the flag trueOovsOnly.
    */
-  private static Set<Integer> getOovCandidateWords(final Sentence sentence, boolean trueOovsOnly) {
+  private static Set<Integer> getOovCandidateWords(final Sentence sentence) {
     final Set<Integer> words = new HashSet<>();
+    final boolean trueOovsOnly = sentence.getFlags().getBoolean("true_oovs_only");
     for (Node<Token> node : sentence.getLattice()) {
       for (Arc<Token> arc : node.getOutgoingArcs()) {
         int sourceWord = arc.getLabel().getWord();
@@ -137,7 +140,7 @@ public class TextGrammarFactory {
     return words;
   }
   
-  public static PhraseTable createEndRulePhraseTable(Sentence sentence, DecoderConfig config) {
+  public static PhraseTable createEndRulePhraseTable() {
     final Config grammarConfig = ConfigFactory.parseMap(
         ImmutableMap.of("owner", UNKNOWN_OWNER, "span_limit", "0"), "End Rule Phrase Table Config");
     final PhraseTable endRulePhraseTable = new PhraseTable(grammarConfig);

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/packed/PackedGrammar.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/packed/PackedGrammar.java b/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/packed/PackedGrammar.java
index de809f6..615856b 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/packed/PackedGrammar.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/ff/tm/packed/PackedGrammar.java
@@ -80,7 +80,6 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.joshua.corpus.Vocabulary;
-import org.apache.joshua.decoder.DecoderConfig;
 import org.apache.joshua.decoder.ff.FeatureFunction;
 import org.apache.joshua.decoder.ff.FeatureVector;
 import org.apache.joshua.decoder.ff.tm.AbstractGrammar;
@@ -961,7 +960,7 @@ public class PackedGrammar extends AbstractGrammar {
   }
   
   @Override
-  public void addOOVRules(int word, DecoderConfig config) {
+  public void addOOVRules(int sourceWord, Config sentenceFlags, List<FeatureFunction> featureFunctions) {
     throw new RuntimeException("PackedGrammar.addOOVRules(): I can't add OOV rules");
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/hypergraph/KBestExtractor.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/hypergraph/KBestExtractor.java b/joshua-core/src/main/java/org/apache/joshua/decoder/hypergraph/KBestExtractor.java
index 6494143..679b5ce 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/hypergraph/KBestExtractor.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/hypergraph/KBestExtractor.java
@@ -126,13 +126,13 @@ public class KBestExtractor {
       boolean isMonolingual) {
 
     this.config = config;
-    this.outputFormat = config.getFlags().getString("output_format");
-    this.extractUniqueNbest = config.getFlags().getBoolean("use_unique_nbest");
+    this.outputFormat = sentence.getFlags().getString("output_format");
+    this.extractUniqueNbest = sentence.getFlags().getBoolean("use_unique_nbest");
 
     this.defaultSide = (isMonolingual ? Side.SOURCE : Side.TARGET);
     this.sentence = sentence;
 
-    if (config.getFlags().getBoolean("rescore_forest")) {
+    if (sentence.getFlags().getBoolean("rescore_forest")) {
       references = new BLEU.References(sentence.references());
     }
   }
@@ -270,7 +270,7 @@ public class KBestExtractor {
   private String maybeProjectCase(String hypothesis, DerivationState state) {
     String output = hypothesis;
 
-    if (config.getFlags().getBoolean("project_case")) {
+    if (sentence.getFlags().getBoolean("project_case")) {
       String[] tokens = hypothesis.split("\\s+");
       List<List<Integer>> points = state.getWordAlignmentList();
       for (int i = 0; i < points.size(); i++) {
@@ -507,7 +507,7 @@ public class KBestExtractor {
                 + virtualTailNode.nbests.get(newRanks[i] - 1).getModelCost();
             nextState.setCost(cost);
 
-            if (config.getFlags().getBoolean("rescore_forest"))
+            if (sentence.getFlags().getBoolean("rescore_forest"))
               nextState.bleu = nextState.computeBLEU();
 
             candHeap.add(nextState);
@@ -621,7 +621,7 @@ public class KBestExtractor {
       cost = hyperEdge.getBestDerivationScore();
 
       DerivationState state = new DerivationState(parentNode, hyperEdge, ranks, cost, edgePos);
-      if (config.getFlags().getBoolean("rescore_forest"))
+      if (sentence.getFlags().getBoolean("rescore_forest"))
         state.bleu = state.computeBLEU();
 
       return state;

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/phrase/PhraseTable.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/phrase/PhraseTable.java b/joshua-core/src/main/java/org/apache/joshua/decoder/phrase/PhraseTable.java
index 6e9ef23..c024623 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/phrase/PhraseTable.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/phrase/PhraseTable.java
@@ -18,12 +18,13 @@
  */
 package org.apache.joshua.decoder.phrase;
 
+import static org.apache.joshua.util.Constants.defaultNT;
+
 import java.io.File;
 import java.util.List;
 import java.util.Optional;
 
 import org.apache.joshua.corpus.Vocabulary;
-import org.apache.joshua.decoder.DecoderConfig;
 import org.apache.joshua.decoder.ff.FeatureFunction;
 import org.apache.joshua.decoder.ff.FeatureVector;
 import org.apache.joshua.decoder.ff.tm.Grammar;
@@ -104,14 +105,14 @@ public class PhraseTable implements Grammar {
   }
   
   @Override
-  public void addOOVRules(int sourceWord, DecoderConfig config) {
+  public void addOOVRules(int sourceWord, Config sentenceFlags, List<FeatureFunction> featureFunctions) {
     // TODO: _OOV shouldn't be outright added, since the word might not be OOV for the LM (but now almost
     // certainly is)
-    int targetWord = config.getFlags().getBoolean("mark_oovs")
+    int targetWord = sentenceFlags.getBoolean("mark_oovs")
         ? Vocabulary.id(Vocabulary.word(sourceWord) + "_OOV")
         : sourceWord;   
 
-    int nt_i = Vocabulary.id("[X]");
+    int nt_i = Vocabulary.id(defaultNT);
     Rule oovRule = new Rule(
         nt_i,
         new int[] { nt_i, sourceWord },
@@ -120,7 +121,7 @@ public class PhraseTable implements Grammar {
         new FeatureVector(0),
         new byte[] {0,0}, backend.getOwner());
     addRule(oovRule);
-    oovRule.estimateRuleCost(config.getFeatureFunctions());
+    oovRule.estimateRuleCost(featureFunctions);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/phrase/Stacks.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/phrase/Stacks.java b/joshua-core/src/main/java/org/apache/joshua/decoder/phrase/Stacks.java
index d4f09a0..7b8729d 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/phrase/Stacks.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/phrase/Stacks.java
@@ -90,9 +90,9 @@ public class Stacks {
     this.sentence = sentence;
     this.config = config;
     this.featureFunctions = config.getFeatureFunctions();
-    this.popLimit = config.getFlags().getInt("pop_limit");
-    this.numTranslationOptions = config.getFlags().getInt("num_translation_options");
-    this.reorderingLimit = config.getFlags().getInt("reordering_limit");
+    this.popLimit = sentence.getFlags().getInt("pop_limit");
+    this.numTranslationOptions = sentence.getFlags().getInt("num_translation_options");
+    this.reorderingLimit = sentence.getFlags().getInt("reordering_limit");
     
     // collect grammars that are phrase tables
     final ImmutableList.Builder<PhraseTable> phraseTablesBuilder = new ImmutableList.Builder<>();

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/decoder/segment_file/Sentence.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/decoder/segment_file/Sentence.java b/joshua-core/src/main/java/org/apache/joshua/decoder/segment_file/Sentence.java
index 5926433..2c6aa9f 100644
--- a/joshua-core/src/main/java/org/apache/joshua/decoder/segment_file/Sentence.java
+++ b/joshua-core/src/main/java/org/apache/joshua/decoder/segment_file/Sentence.java
@@ -78,7 +78,7 @@ public class Sentence {
   /* List of constraints */
   private final List<ConstraintSpan> constraints;
   
-  private final Config config;
+  private final Config flags;
   
   private final boolean latticeDecoding;
   private final int maximumSentenceLength;
@@ -92,16 +92,16 @@ public class Sentence {
    * 
    * @param inputString representing the input sentence
    * @param id ID to associate with the input string
-   * @param joshuaConfiguration a populated {@link org.apache.joshua.decoder.JoshuaConfiguration}
+   * @param Config flags
    */
-  public Sentence(String inputString, int id, Config config) {
+  public Sentence(String inputString, int id, Config flags) {
   
     inputString = Regex.spaces.replaceAll(inputString, " ").trim();
     
-    this.config = config;
-    this.latticeDecoding = this.config.getBoolean("lattice_decoding");
-    this.maximumSentenceLength = this.config.getInt("maximum_sentence_length");
-    this.searchAlgorithm = SearchAlgorithm.valueOf(this.config.getString("search_algorithm"));
+    this.flags = flags;
+    this.latticeDecoding = this.flags.getBoolean("lattice_decoding");
+    this.maximumSentenceLength = this.flags.getInt("maximum_sentence_length");
+    this.searchAlgorithm = SearchAlgorithm.valueOf(this.flags.getString("search_algorithm"));
     
     this.constraints = new LinkedList<>();
 
@@ -141,8 +141,8 @@ public class Sentence {
     }
   }
   
-  public Config getConfig() {
-    return config;
+  public Config getFlags() {
+    return flags;
   }
 
   /**
@@ -224,7 +224,7 @@ public class Sentence {
             for (int i = 0; i <= chars.length - width; i++) {
               int j = i + width;
               if (width != chars.length) {
-                Token token = new Token(word.substring(i, j), config);
+                Token token = new Token(word.substring(i, j), flags);
                 if (vocabulary.contains(id)) {
                   nodes.get(i).addArc(nodes.get(j), 0.0f, token);
                   wordChart.set(i, j, true);
@@ -427,7 +427,7 @@ public class Sentence {
    */
   public Lattice<String> stringLattice() {
     assert isLinearChain();
-    return Lattice.createStringLatticeFromString(source(), config);
+    return Lattice.createStringLatticeFromString(source(), flags);
   }
 
   public List<ConstraintSpan> constraints() {
@@ -440,10 +440,10 @@ public class Sentence {
         if (searchAlgorithm == SearchAlgorithm.stack) {
           throw new RuntimeException("* FATAL: lattice decoding currently not supported for stack-based search algorithm.");
         }
-        this.sourceLattice = Lattice.createTokenLatticeFromPLF(rawSource(), config);
+        this.sourceLattice = Lattice.createTokenLatticeFromPLF(rawSource(), flags);
       } else
         this.sourceLattice = Lattice.createTokenLatticeFromString(String.format("%s %s %s", Vocabulary.START_SYM,
-            rawSource(), Vocabulary.STOP_SYM), config);
+            rawSource(), Vocabulary.STOP_SYM), flags);
     }
     return this.sourceLattice;
   }

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/2e3b10b9/joshua-core/src/main/java/org/apache/joshua/server/ServerThread.java
----------------------------------------------------------------------
diff --git a/joshua-core/src/main/java/org/apache/joshua/server/ServerThread.java b/joshua-core/src/main/java/org/apache/joshua/server/ServerThread.java
index 81fdeaf..bc472d0 100644
--- a/joshua-core/src/main/java/org/apache/joshua/server/ServerThread.java
+++ b/joshua-core/src/main/java/org/apache/joshua/server/ServerThread.java
@@ -87,7 +87,7 @@ public class ServerThread extends Thread implements HttpHandler {
     try {
       BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), FILE_ENCODING));
 
-      TranslationRequestStream request = new TranslationRequestStream(reader, decoder.getDecoderConfig().getFlags());
+      TranslationRequestStream request = new TranslationRequestStream(reader, decoder.getFlags());
 
       try {
         TranslationResponseStream translationResponseStream = decoder.decodeAll(request);
@@ -161,7 +161,7 @@ public class ServerThread extends Thread implements HttpHandler {
     String meta = params.get("meta");
     
     BufferedReader reader = new BufferedReader(new StringReader(query));
-    TranslationRequestStream request = new TranslationRequestStream(reader, decoder.getDecoderConfig().getFlags());
+    TranslationRequestStream request = new TranslationRequestStream(reader, decoder.getFlags());
     
     TranslationResponseStream translationResponseStream = decoder.decodeAll(request);
     JSONMessage message = new JSONMessage();
@@ -193,7 +193,7 @@ public class ServerThread extends Thread implements HttpHandler {
     String type = tokens[0];
     String args = tokens.length > 1 ? tokens[1] : "";
     
-    final FeatureVector weights = decoder.getDecoderConfig().getWeights();
+    final FeatureVector weights = decoder.getWeights();
     
     if (type.equals("get_weight")) {
       String weight = tokens[1];
@@ -237,7 +237,7 @@ public class ServerThread extends Thread implements HttpHandler {
       /* Prepend source and target side nonterminals for phrase-based decoding. Probably better
        * handled in each grammar type's addRule() function.
        */
-      String ruleString = (decoder.getDecoderConfig().getSearchAlgorithm() == SearchAlgorithm.stack)
+      String ruleString = (SearchAlgorithm.valueOf(decoder.getFlags().getString("search_algorithm")) == SearchAlgorithm.stack)
           ? String.format("%s ||| [X,1] %s ||| [X,1] %s ||| -1 %s %s", lhs, source, target, featureStr, alignmentStr)
           : String.format("%s ||| %s ||| %s ||| -1 %s %s", lhs, source, target, featureStr, alignmentStr);