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

[3/7] incubator-joshua git commit: static analysis based code improvements on mira package

static analysis based code improvements on mira package


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

Branch: refs/heads/master
Commit: 0fc2f497e222b75eb448440af41afbd114c27e0d
Parents: 23ebc37
Author: Tommaso Teofili <to...@apache.org>
Authored: Mon Sep 26 13:52:38 2016 +0200
Committer: Tommaso Teofili <to...@apache.org>
Committed: Mon Sep 26 13:52:38 2016 +0200

----------------------------------------------------------------------
 .../java/org/apache/joshua/mira/MIRACore.java   | 296 ++++++++++-------
 .../java/org/apache/joshua/mira/Optimizer.java  | 333 +++++++++----------
 2 files changed, 333 insertions(+), 296 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/0fc2f497/src/main/java/org/apache/joshua/mira/MIRACore.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/joshua/mira/MIRACore.java b/src/main/java/org/apache/joshua/mira/MIRACore.java
index a4a6b84..9ba046d 100755
--- a/src/main/java/org/apache/joshua/mira/MIRACore.java
+++ b/src/main/java/org/apache/joshua/mira/MIRACore.java
@@ -33,6 +33,7 @@ import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.text.DecimalFormat;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -62,12 +63,11 @@ public class MIRACore {
   private static final Logger LOG = LoggerFactory.getLogger(MIRACore.class);
 
   private final JoshuaConfiguration joshuaConfiguration;
-  private TreeSet<Integer>[] indicesOfInterest_all;
 
   private final static DecimalFormat f4 = new DecimalFormat("###0.0000");
 
-  private final static double NegInf = (-1.0 / 0.0);
-  private final static double PosInf = (+1.0 / 0.0);
+  private final static double NegInf = Double.NEGATIVE_INFINITY;
+  private final static double PosInf = Double.POSITIVE_INFINITY;
   private final static double epsilon = 1.0 / 1000000;
 
   private int verbosity; // anything of priority <= verbosity will be printed
@@ -83,7 +83,6 @@ public class MIRACore {
   // number of documents in the dev set
   // this should be 1, unless doing doc-level optimization
 
-  private int[] docOfSentence;
   // docOfSentence[i] stores which document contains the i'th sentence.
   // docOfSentence is 0-indexed, as are the documents (i.e. first doc is indexed 0)
 
@@ -129,9 +128,9 @@ public class MIRACore {
   /* *********************************************************** */
 
   // private double[] lambda;
-  private ArrayList<Double> lambda = new ArrayList<Double>();
+  private ArrayList<Double> lambda = new ArrayList<>();
   // the current weight vector. NOTE: indexing starts at 1.
-  private ArrayList<Double> bestLambda = new ArrayList<Double>();
+  private final ArrayList<Double> bestLambda = new ArrayList<>();
   // the best weight vector across all iterations
 
   private boolean[] isOptimizable;
@@ -153,7 +152,6 @@ public class MIRACore {
   private Decoder myDecoder;
   // COMMENT OUT if decoder is not Joshua
 
-  private String decoderCommand;
   // the command that runs the decoder; read from decoderCommandFileName
 
   private int decVerbosity;
@@ -163,7 +161,6 @@ public class MIRACore {
   private int validDecoderExitValue;
   // return value from running the decoder command that indicates success
 
-  private int numOptThreads;
   // number of threads to run things in parallel
 
   private int saveInterFiles;
@@ -244,9 +241,9 @@ public class MIRACore {
   private double prevMetricScore = 0; // final metric score of the previous iteration, used only
                                       // when returnBest = true
 
-  private String dirPrefix; // where are all these files located?
   private String paramsFileName, docInfoFileName, finalLambdaFileName;
-  private String sourceFileName, refFileName, decoderOutFileName;
+  private String refFileName;
+  private String decoderOutFileName;
   private String decoderConfigFileName, decoderCommandFileName;
   private String fakeFileNameTemplate, fakeFileNamePrefix, fakeFileNameSuffix;
 
@@ -260,21 +257,21 @@ public class MIRACore {
     this.joshuaConfiguration = joshuaConfiguration;
   }
 
-  public MIRACore(String[] args, JoshuaConfiguration joshuaConfiguration) throws FileNotFoundException, IOException {
+  public MIRACore(String[] args, JoshuaConfiguration joshuaConfiguration) throws IOException {
     this.joshuaConfiguration = joshuaConfiguration;
     EvaluationMetric.set_knownMetrics();
     processArgsArray(args);
     initialize(0);
   }
 
-  public MIRACore(String configFileName, JoshuaConfiguration joshuaConfiguration) throws FileNotFoundException, IOException {
+  public MIRACore(String configFileName, JoshuaConfiguration joshuaConfiguration) throws IOException {
     this.joshuaConfiguration = joshuaConfiguration;
     EvaluationMetric.set_knownMetrics();
     processArgsArray(cfgFileToArgsArray(configFileName));
     initialize(0);
   }
 
-  private void initialize(int randsToSkip) throws FileNotFoundException, IOException {
+  private void initialize(int randsToSkip) throws IOException {
     println("NegInf: " + NegInf + ", PosInf: " + PosInf + ", epsilon: " + epsilon, 4);
 
     randGen = new Random(seed);
@@ -336,8 +333,8 @@ public class MIRACore {
     // and one line for the normalization method
     // indexing starts at 1 in these arrays
     for (int p = 0; p <= numParams; ++p)
-      lambda.add(new Double(0));
-    bestLambda.add(new Double(0));
+      lambda.add(0d);
+    bestLambda.add(0d);
     // why only lambda is a list? because the size of lambda
     // may increase over time, but other arrays are specified in
     // the param config file, only used for initialization
@@ -355,6 +352,7 @@ public class MIRACore {
 
     String[][] refSentences = new String[numSentences][refsPerSen];
 
+    String decoderCommand;
     try {
 
       // read in reference sentences
@@ -489,10 +487,10 @@ public class MIRACore {
 
     @SuppressWarnings("unchecked")
     TreeSet<Integer>[] temp_TSA = new TreeSet[numSentences];
-    indicesOfInterest_all = temp_TSA;
+    TreeSet<Integer>[] indicesOfInterest_all = temp_TSA;
 
     for (int i = 0; i < numSentences; ++i) {
-      indicesOfInterest_all[i] = new TreeSet<Integer>();
+      indicesOfInterest_all[i] = new TreeSet<>();
     }
   } // void initialize(...)
 
@@ -517,9 +515,9 @@ public class MIRACore {
     if (folder.exists()) {
       File[] listOfFiles = folder.listFiles();
 
-      for (int i = 0; i < listOfFiles.length; i++) {
-        if (listOfFiles[i].isFile()) {
-          files = listOfFiles[i].getName();
+      for (File listOfFile : listOfFiles) {
+        if (listOfFile.isFile()) {
+          files = listOfFile.getName();
           if (files.startsWith("MIRA.temp")) {
             deleteFile(files);
           }
@@ -622,11 +620,11 @@ public class MIRACore {
     // save feats and stats for all candidates(old & new)
     HashMap<String, String>[] feat_hash = new HashMap[numSentences];
     for (int i = 0; i < numSentences; i++)
-      feat_hash[i] = new HashMap<String, String>();
+      feat_hash[i] = new HashMap<>();
 
     HashMap<String, String>[] stats_hash = new HashMap[numSentences];
     for (int i = 0; i < numSentences; i++)
-      stats_hash[i] = new HashMap<String, String>();
+      stats_hash[i] = new HashMap<>();
 
     while (!done) { // NOTE: this "loop" will only be carried out once
       println("--- Starting MIRA iteration #" + iteration + " @ " + (new Date()) + " ---", 1);
@@ -714,7 +712,7 @@ public class MIRACore {
         candCount[i] = 0;
         lastUsedIndex[i] = -1;
         // suffStats_array[i].clear();
-        suffStats_array[i] = new ConcurrentHashMap<Integer, int[]>();
+        suffStats_array[i] = new ConcurrentHashMap<>();
       }
 
       // initLambda[0] is not used!
@@ -843,7 +841,7 @@ public class MIRACore {
         // (It's not actually a bug, but only because existingCandStats gets
         // cleared before moving to the next source sentence.)
         // FIX: should be made an array, indexed by i
-        HashMap<String, String> existingCandStats = new HashMap<String, String>();
+        HashMap<String, String> existingCandStats = new HashMap<>();
         // VERY IMPORTANT:
         // A CANDIDATE X MAY APPEARED IN ITER 1, ITER 3
         // BUT IF THE USER SPECIFIED TO CONSIDER ITERATIONS FROM ONLY ITER 2, THEN
@@ -930,7 +928,7 @@ public class MIRACore {
 
           String[] sentsCurrIt_currSrcSent = new String[sizeOfNBest + 1];
 
-          Vector<String> unknownCands_V = new Vector<String>();
+          Vector<String> unknownCands_V = new Vector<>();
           // which candidates (of the i'th source sentence) have not been seen before
           // this iteration?
 
@@ -1108,7 +1106,7 @@ public class MIRACore {
                   // initialized as zero anyway
                   if (featId > numParams) {
                     ++numParams;
-                    lambda.add(new Double(0));
+                    lambda.add(0d);
                   }
                 }
               }
@@ -1221,7 +1219,7 @@ public class MIRACore {
               lambda.set(p, bestLambda.get(p));
             // and set the rest of lambda to be 0
             for (int p = 0; p < lambda.size() - bestLambda.size(); ++p)
-              lambda.set(p + bestLambda.size(), new Double(0));
+              lambda.set(p + bestLambda.size(), 0d);
           }
 
           return null; // this means that the old values should be kept by the caller
@@ -1268,7 +1266,7 @@ public class MIRACore {
         }
       }
 
-      Vector<String> output = new Vector<String>();
+      Vector<String> output = new Vector<>();
 
       // note: initialLambda[] has length = numParamsOld
       // augmented with new feature weights, initial values are 0
@@ -1312,8 +1310,8 @@ public class MIRACore {
 
       /************* end optimization **************/
 
-      for (int i = 0; i < output.size(); i++)
-        println(output.get(i));
+      for (String anOutput : output)
+        println(anOutput);
 
       // check if any parameter has been updated
       boolean anyParamChanged = false;
@@ -1391,7 +1389,7 @@ public class MIRACore {
       // (interpolation with previous wt vector)
       double interCoef = 1.0; // no interpolation for now
       for (int i = 1; i <= numParams; i++)
-        lambda.set(i, interCoef * finalLambda[i] + (1 - interCoef) * lambda.get(i).doubleValue());
+        lambda.set(i, interCoef * finalLambda[i] + (1 - interCoef) * lambda.get(i));
 
       println("Next iteration will decode with lambda: " + lambdaToString(lambda), 1);
       println("", 1);
@@ -1425,9 +1423,9 @@ public class MIRACore {
 
     retStr += "(listing the first " + featToPrint + " lambdas)";
     for (int c = 1; c <= featToPrint - 1; ++c) {
-      retStr += "" + String.format("%.4f", lambdaA.get(c).doubleValue()) + ", ";
+      retStr += "" + String.format("%.4f", lambdaA.get(c)) + ", ";
     }
-    retStr += "" + String.format("%.4f", lambdaA.get(numParams).doubleValue()) + "}";
+    retStr += "" + String.format("%.4f", lambdaA.get(numParams)) + "}";
 
     return retStr;
   }
@@ -1460,7 +1458,7 @@ public class MIRACore {
       println("Running external decoder...", 1);
 
       try {
-        ArrayList<String> cmd = new ArrayList<String>();
+        ArrayList<String> cmd = new ArrayList<>();
         cmd.add(decoderCommandFileName);
 
         if (passIterationToDecoder)
@@ -1609,7 +1607,7 @@ public class MIRACore {
         if (c_match == -1) {
           outFile.println(line);
         } else {
-          if (Math.abs(params.get(c_match).doubleValue()) > 1e-20)
+          if (Math.abs(params.get(c_match)) > 1e-20)
             outFile.println(Vocabulary.word(c_match) + " " + params.get(c_match));
         }
 
@@ -1618,7 +1616,7 @@ public class MIRACore {
 
       // now append weights of new features
       for (int c = origFeatNum + 1; c <= numParams; ++c) {
-        if (Math.abs(params.get(c).doubleValue()) > 1e-20)
+        if (Math.abs(params.get(c)) > 1e-20)
           outFile.println(Vocabulary.word(c) + " " + params.get(c));
       }
 
@@ -1649,16 +1647,20 @@ public class MIRACore {
 
       // read default value
       lambda.set(c, inFile_init.nextDouble());
-      defaultLambda[c] = lambda.get(c).doubleValue();
+      defaultLambda[c] = lambda.get(c);
 
       // read isOptimizable
       dummy = inFile_init.next();
-      if (dummy.equals("Opt")) {
+      switch (dummy) {
+      case "Opt":
         isOptimizable[c] = true;
-      } else if (dummy.equals("Fix")) {
+        break;
+      case "Fix":
         isOptimizable[c] = false;
-      } else {
-        throw new RuntimeException("Unknown isOptimizable string " + dummy + " (must be either Opt or Fix)");
+        break;
+      default:
+        throw new RuntimeException(
+            "Unknown isOptimizable string " + dummy + " (must be either Opt or Fix)");
       }
 
       if (!isOptimizable[c]) { // skip next two values
@@ -1727,9 +1729,11 @@ public class MIRACore {
     dummy = (origLine.substring(origLine.indexOf("=") + 1)).trim();
     String[] dummyA = dummy.split("\\s+");
 
-    if (dummyA[0].equals("none")) {
+    switch (dummyA[0]) {
+    case "none":
       normalizationOptions[0] = 0;
-    } else if (dummyA[0].equals("absval")) {
+      break;
+    case "absval":
       normalizationOptions[0] = 1;
       normalizationOptions[1] = Double.parseDouble(dummyA[1]);
       String pName = dummyA[2];
@@ -1745,37 +1749,43 @@ public class MIRACore {
         throw new RuntimeException("Unrecognized feature name " + normalizationOptions[2]
             + " for absval normalization method.");
       }
-    } else if (dummyA[0].equals("maxabsval")) {
+      break;
+    case "maxabsval":
       normalizationOptions[0] = 2;
       normalizationOptions[1] = Double.parseDouble(dummyA[1]);
       if (normalizationOptions[1] <= 0) {
-        throw new RuntimeException("Value for the maxabsval normalization method must be positive.");
+        throw new RuntimeException(
+            "Value for the maxabsval normalization method must be positive.");
       }
-    } else if (dummyA[0].equals("minabsval")) {
+      break;
+    case "minabsval":
       normalizationOptions[0] = 3;
       normalizationOptions[1] = Double.parseDouble(dummyA[1]);
       if (normalizationOptions[1] <= 0) {
-        throw new RuntimeException("Value for the minabsval normalization method must be positive.");
+        throw new RuntimeException(
+            "Value for the minabsval normalization method must be positive.");
       }
-    } else if (dummyA[0].equals("LNorm")) {
+      break;
+    case "LNorm":
       normalizationOptions[0] = 4;
       normalizationOptions[1] = Double.parseDouble(dummyA[1]);
       normalizationOptions[2] = Double.parseDouble(dummyA[2]);
       if (normalizationOptions[1] <= 0 || normalizationOptions[2] <= 0) {
-        throw new RuntimeException("Both values for the LNorm normalization method must be"
-            + " positive.");
+        throw new RuntimeException(
+            "Both values for the LNorm normalization method must be" + " positive.");
       }
-    } else {
+      break;
+    default:
       throw new RuntimeException("Unrecognized normalization method " + dummyA[0] + "; "
           + "must be one of none, absval, maxabsval, and LNorm.");
-    } // if (dummyA[0])
+    }
 
     inFile_init.close();
   } // processParamFile()
 
   private void processDocInfo() {
     // sets numDocuments and docOfSentence[]
-    docOfSentence = new int[numSentences];
+    int[] docOfSentence = new int[numSentences];
 
     if (docInfoFileName == null) {
       for (int i = 0; i < numSentences; ++i)
@@ -1832,7 +1842,7 @@ public class MIRACore {
 
           boolean format3 = false;
 
-          HashSet<String> seenStrings = new HashSet<String>();
+          HashSet<String> seenStrings = new HashSet<>();
           BufferedReader inFile = new BufferedReader(new FileReader(docInfoFileName));
           for (int i = 0; i < numSentences; ++i) {
             // set format3 = true if a duplicate is found
@@ -1844,8 +1854,8 @@ public class MIRACore {
 
           inFile.close();
 
-          HashSet<String> seenDocNames = new HashSet<String>();
-          HashMap<String, Integer> docOrder = new HashMap<String, Integer>();
+          HashSet<String> seenDocNames = new HashSet<>();
+          HashMap<String, Integer> docOrder = new HashMap<>();
           // maps a document name to the order (0-indexed) in which it was seen
 
           inFile = new BufferedReader(new FileReader(docInfoFileName));
@@ -1972,7 +1982,7 @@ public class MIRACore {
       try {
         PrintWriter outFile_lambdas = new PrintWriter(finalLambdaFileName);
         for (int c = 1; c <= numParams; ++c) {
-          outFile_lambdas.println(Vocabulary.word(c) + " ||| " + lambda.get(c).doubleValue());
+          outFile_lambdas.println(Vocabulary.word(c) + " ||| " + lambda.get(c));
         }
         outFile_lambdas.close();
 
@@ -1986,7 +1996,7 @@ public class MIRACore {
   private String[] cfgFileToArgsArray(String fileName) {
     checkFile(fileName);
 
-    Vector<String> argsVector = new Vector<String>();
+    Vector<String> argsVector = new Vector<>();
 
     BufferedReader inFile = null;
     try {
@@ -1998,7 +2008,7 @@ public class MIRACore {
 
         if (line != null && line.length() > 0 && line.charAt(0) != '#') {
 
-          if (line.indexOf("#") != -1) { // discard comment
+          if (line.contains("#")) { // discard comment
             line = line.substring(0, line.indexOf("#"));
           }
 
@@ -2021,7 +2031,7 @@ public class MIRACore {
 
           // cmu modification(from meteor for zmert)
           // Parse args
-          ArrayList<String> argList = new ArrayList<String>();
+          ArrayList<String> argList = new ArrayList<>();
           StringBuilder arg = new StringBuilder();
           boolean quoted = false;
           for (int i = 0; i < line.length(); i++) {
@@ -2054,9 +2064,7 @@ public class MIRACore {
             argsVector.add(paramA[1]);
           } else if (paramA.length > 2 && (paramA[0].equals("-m") || paramA[0].equals("-docSet"))) {
             // -m (metricName), -docSet are allowed to have extra optinos
-            for (int opt = 0; opt < paramA.length; ++opt) {
-              argsVector.add(paramA[opt]);
-            }
+            Collections.addAll(argsVector, paramA);
           } else {
             throw new RuntimeException("Malformed line in config file:" + origLine);
           }
@@ -2085,8 +2093,8 @@ public class MIRACore {
   private void processArgsArray(String[] args, boolean firstTime) {
     /* set default values */
     // Relevant files
-    dirPrefix = null;
-    sourceFileName = null;
+    String dirPrefix = null;
+    String sourceFileName = null;
     refFileName = "reference.txt";
     refsPerSen = 1;
     textNormMethod = 1;
@@ -2109,7 +2117,7 @@ public class MIRACore {
     //
     // /* possibly other early stopping criteria here */
     //
-    numOptThreads = 1;
+    int numOptThreads = 1;
     saveInterFiles = 3;
     compressFiles = 0;
     oneModificationPerIteration = false;
@@ -2135,30 +2143,39 @@ public class MIRACore {
     while (i < args.length) {
       String option = args[i];
       // Relevant files
-      if (option.equals("-dir")) {
+      switch (option) {
+      case "-dir":
         dirPrefix = args[i + 1];
-      } else if (option.equals("-s")) {
+        break;
+      case "-s":
         sourceFileName = args[i + 1];
-      } else if (option.equals("-r")) {
+        break;
+      case "-r":
         refFileName = args[i + 1];
-      } else if (option.equals("-rps")) {
+        break;
+      case "-rps":
         refsPerSen = Integer.parseInt(args[i + 1]);
         if (refsPerSen < 1) {
           throw new RuntimeException("refsPerSen must be positive.");
         }
-      } else if (option.equals("-txtNrm")) {
+        break;
+      case "-txtNrm":
         textNormMethod = Integer.parseInt(args[i + 1]);
         if (textNormMethod < 0 || textNormMethod > 4) {
           throw new RuntimeException("textNormMethod should be between 0 and 4");
         }
-      } else if (option.equals("-p")) {
+        break;
+      case "-p":
         paramsFileName = args[i + 1];
-      } else if (option.equals("-docInfo")) {
+        break;
+      case "-docInfo":
         docInfoFileName = args[i + 1];
-      } else if (option.equals("-fin")) {
+        break;
+      case "-fin":
         finalLambdaFileName = args[i + 1];
         // MERT specs
-      } else if (option.equals("-m")) {
+        break;
+      case "-m":
         metricName = args[i + 1];
         metricName_display = metricName;
         if (EvaluationMetric.knownMetricName(metricName)) {
@@ -2171,7 +2188,8 @@ public class MIRACore {
         } else {
           throw new RuntimeException("Unknown metric name " + metricName + ".");
         }
-      } else if (option.equals("-docSet")) {
+        break;
+      case "-docSet":
         String method = args[i + 1];
 
         if (method.equals("all")) {
@@ -2216,48 +2234,56 @@ public class MIRACore {
         } else {
           throw new RuntimeException("Unknown docSet method " + method + ".");
         }
-      } else if (option.equals("-maxIt")) {
+        break;
+      case "-maxIt":
         maxMERTIterations = Integer.parseInt(args[i + 1]);
         if (maxMERTIterations < 1) {
           throw new RuntimeException("maxIt must be positive.");
         }
-      } else if (option.equals("-minIt")) {
+        break;
+      case "-minIt":
         minMERTIterations = Integer.parseInt(args[i + 1]);
         if (minMERTIterations < 1) {
           throw new RuntimeException("minIt must be positive.");
         }
-      } else if (option.equals("-prevIt")) {
+        break;
+      case "-prevIt":
         prevMERTIterations = Integer.parseInt(args[i + 1]);
         if (prevMERTIterations < 0) {
           throw new RuntimeException("prevIt must be non-negative.");
         }
-      } else if (option.equals("-stopIt")) {
+        break;
+      case "-stopIt":
         stopMinIts = Integer.parseInt(args[i + 1]);
         if (stopMinIts < 1) {
           throw new RuntimeException("stopIts must be positive.");
         }
-      } else if (option.equals("-stopSig")) {
+        break;
+      case "-stopSig":
         stopSigValue = Double.parseDouble(args[i + 1]);
-      }
+        break;
       //
       // /* possibly other early stopping criteria here */
       //
-      else if (option.equals("-thrCnt")) {
+      case "-thrCnt":
         numOptThreads = Integer.parseInt(args[i + 1]);
         if (numOptThreads < 1) {
           throw new RuntimeException("threadCount must be positive.");
         }
-      } else if (option.equals("-save")) {
+        break;
+      case "-save":
         saveInterFiles = Integer.parseInt(args[i + 1]);
         if (saveInterFiles < 0 || saveInterFiles > 3) {
           throw new RuntimeException("save should be between 0 and 3");
         }
-      } else if (option.equals("-compress")) {
+        break;
+      case "-compress":
         compressFiles = Integer.parseInt(args[i + 1]);
         if (compressFiles < 0 || compressFiles > 1) {
           throw new RuntimeException("compressFiles should be either 0 or 1");
         }
-      } else if (option.equals("-opi")) {
+        break;
+      case "-opi":
         int opi = Integer.parseInt(args[i + 1]);
         if (opi == 1) {
           oneModificationPerIteration = true;
@@ -2266,7 +2292,8 @@ public class MIRACore {
         } else {
           throw new RuntimeException("oncePerIt must be either 0 or 1.");
         }
-      } else if (option.equals("-rand")) {
+        break;
+      case "-rand":
         int rand = Integer.parseInt(args[i + 1]);
         if (rand == 1) {
           randInit = true;
@@ -2275,20 +2302,21 @@ public class MIRACore {
         } else {
           throw new RuntimeException("randInit must be either 0 or 1.");
         }
-      } else if (option.equals("-seed")) {
+        break;
+      case "-seed":
         if (args[i + 1].equals("time")) {
           seed = System.currentTimeMillis();
         } else {
           seed = Long.parseLong(args[i + 1]);
         }
-      }
+        break;
       /*
        * else if (option.equals("-ud")) { useDisk = Integer.parseInt(args[i+1]); if (useDisk < 0 ||
        * useDisk > 2) { println("useDisk should be between 0 and 2"); System.exit(10); } }
        */
 
       // for mira:
-      else if (option.equals("-needShuffle")) {
+      case "-needShuffle":
         int shuffle = Integer.parseInt(args[i + 1]);
         if (shuffle == 1)
           needShuffle = true;
@@ -2297,9 +2325,9 @@ public class MIRACore {
         else {
           throw new RuntimeException("-needShuffle must be either 0 or 1.");
         }
-      }
+        break;
       // average weights after each epoch or not
-      else if (option.equals("-needAvg")) {
+      case "-needAvg":
         int avg = Integer.parseInt(args[i + 1]);
         if (avg == 1)
           needAvg = true;
@@ -2308,9 +2336,9 @@ public class MIRACore {
         else {
           throw new RuntimeException("-needAvg must be either 0 or 1.");
         }
-      }
+        break;
       // return the best weight during tuning or not
-      else if (option.equals("-returnBest")) {
+      case "-returnBest":
         int retBest = Integer.parseInt(args[i + 1]);
         if (retBest == 1)
           returnBest = true;
@@ -2319,9 +2347,9 @@ public class MIRACore {
         else {
           throw new RuntimeException("-returnBest must be either 0 or 1.");
         }
-      }
+        break;
       // run perceptron or not
-      else if (option.equals("-runPercep")) {
+      case "-runPercep":
         int per = Integer.parseInt(args[i + 1]);
         if (per == 1)
           runPercep = true;
@@ -2330,27 +2358,27 @@ public class MIRACore {
         else {
           throw new RuntimeException("-runPercep must be either 0 or 1.");
         }
-      }
+        break;
       // oracle selection mode
-      else if (option.equals("-oracleSelection")) {
+      case "-oracleSelection":
         oraSelectMode = Integer.parseInt(args[i + 1]);
-      }
+        break;
       // prediction selection mode
-      else if (option.equals("-predictionSelection")) {
+      case "-predictionSelection":
         predSelectMode = Integer.parseInt(args[i + 1]);
-      }
+        break;
       // MIRA internal iterations
-      else if (option.equals("-miraIter")) {
+      case "-miraIter":
         miraIter = Integer.parseInt(args[i + 1]);
-      }
+        break;
       // mini-batch size
-      else if (option.equals("-batchSize")) {
+      case "-batchSize":
         batchSize = Integer.parseInt(args[i + 1]);
-      }
+        break;
       // relaxation coefficient
-      else if (option.equals("-C")) {
+      case "-C":
         C = Double.parseDouble(args[i + 1]);
-      }
+        break;
       // else if (option.equals("-sentForScaling")) {
       // sentForScale = Double.parseDouble(args[i + 1]);
       // if(sentForScale>1 || sentForScale<0) {
@@ -2358,12 +2386,13 @@ public class MIRACore {
       // System.exit(10);
       // }
       // }
-      else if (option.equals("-scoreRatio")) {
+      case "-scoreRatio":
         scoreRatio = Double.parseDouble(args[i + 1]);
         if (scoreRatio <= 0) {
           throw new RuntimeException("-scoreRatio must be positive");
         }
-      } else if (option.equals("-needScaling")) {
+        break;
+      case "-needScaling":
         int scale = Integer.parseInt(args[i + 1]);
         if (scale == 1)
           needScale = true;
@@ -2372,7 +2401,8 @@ public class MIRACore {
         else {
           throw new RuntimeException("-needScaling must be either 0 or 1.");
         }
-      } else if (option.equals("-usePseudoCorpus")) {
+        break;
+      case "-usePseudoCorpus":
         int use = Integer.parseInt(args[i + 1]);
         if (use == 1)
           usePseudoBleu = true;
@@ -2381,51 +2411,61 @@ public class MIRACore {
         else {
           throw new RuntimeException("-usePseudoCorpus must be either 0 or 1.");
         }
-      } else if (option.equals("-corpusDecay")) {
+        break;
+      case "-corpusDecay":
         R = Double.parseDouble(args[i + 1]);
-      }
+        break;
 
       // Decoder specs
-      else if (option.equals("-cmd")) {
+      case "-cmd":
         decoderCommandFileName = args[i + 1];
-      } else if (option.equals("-passIt")) {
+        break;
+      case "-passIt":
         int val = Integer.parseInt(args[i + 1]);
         if (val < 0 || val > 1) {
           throw new RuntimeException("passIterationToDecoder should be either 0 or 1");
         }
-        passIterationToDecoder = (val == 1) ? true : false;
-      } else if (option.equals("-decOut")) {
+        passIterationToDecoder = (val == 1);
+        break;
+      case "-decOut":
         decoderOutFileName = args[i + 1];
-      } else if (option.equals("-decExit")) {
+        break;
+      case "-decExit":
         validDecoderExitValue = Integer.parseInt(args[i + 1]);
-      } else if (option.equals("-dcfg")) {
+        break;
+      case "-dcfg":
         decoderConfigFileName = args[i + 1];
-      } else if (option.equals("-N")) {
+        break;
+      case "-N":
         sizeOfNBest = Integer.parseInt(args[i + 1]);
         if (sizeOfNBest < 1) {
           throw new RuntimeException("N must be positive.");
         }
-      }
+        break;
       // Output specs
-      else if (option.equals("-v")) {
+      case "-v":
         verbosity = Integer.parseInt(args[i + 1]);
         if (verbosity < 0 || verbosity > 4) {
           throw new RuntimeException("verbosity should be between 0 and 4");
         }
-      } else if (option.equals("-decV")) {
+        break;
+      case "-decV":
         decVerbosity = Integer.parseInt(args[i + 1]);
         if (decVerbosity < 0 || decVerbosity > 1) {
           throw new RuntimeException("decVerbosity should be either 0 or 1");
         }
-      } else if (option.equals("-fake")) {
+        break;
+      case "-fake":
         fakeFileNameTemplate = args[i + 1];
         int QM_i = fakeFileNameTemplate.indexOf("?");
         if (QM_i <= 0) {
-          throw new RuntimeException("fakeFileNameTemplate must contain '?' to indicate position of iteration number");
+          throw new RuntimeException(
+              "fakeFileNameTemplate must contain '?' to indicate position of iteration number");
         }
         fakeFileNamePrefix = fakeFileNameTemplate.substring(0, QM_i);
         fakeFileNameSuffix = fakeFileNameTemplate.substring(QM_i + 1);
-      } else {
+        break;
+      default:
         throw new RuntimeException("Unknown option " + option);
       }
 
@@ -2785,7 +2825,7 @@ public class MIRACore {
     str = " " + str + " ";
     str = str.replaceAll("\\s+", " ");
 
-    TreeSet<Integer> splitIndices = new TreeSet<Integer>();
+    TreeSet<Integer> splitIndices = new TreeSet<>();
 
     for (int i = 0; i < str.length(); ++i) {
       char ch = str.charAt(i);
@@ -2832,7 +2872,7 @@ public class MIRACore {
     // remove spaces around dashes
     if (normMethod == 2 || normMethod == 4) {
 
-      TreeSet<Integer> skipIndices = new TreeSet<Integer>();
+      TreeSet<Integer> skipIndices = new TreeSet<>();
       str = " " + str + " ";
 
       for (int i = 0; i < str.length(); ++i) {
@@ -2903,7 +2943,7 @@ public class MIRACore {
   }
 
   private ArrayList<Double> randomLambda() {
-    ArrayList<Double> retLambda = new ArrayList<Double>(1 + numParams);
+    ArrayList<Double> retLambda = new ArrayList<>(1 + numParams);
 
     for (int c = 1; c <= numParams; ++c) {
       if (isOptimizable[c]) {

http://git-wip-us.apache.org/repos/asf/incubator-joshua/blob/0fc2f497/src/main/java/org/apache/joshua/mira/Optimizer.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/joshua/mira/Optimizer.java b/src/main/java/org/apache/joshua/mira/Optimizer.java
index f51a5b3..6592a5d 100755
--- a/src/main/java/org/apache/joshua/mira/Optimizer.java
+++ b/src/main/java/org/apache/joshua/mira/Optimizer.java
@@ -42,13 +42,12 @@ public class Optimizer {
     feat_hash = _feat_hash; // feature hash table
     stats_hash = _stats_hash; // suff. stats hash table
     finalLambda = new double[initialLambda.length];
-    for (int i = 0; i < finalLambda.length; i++)
-      finalLambda[i] = initialLambda[i];
+	  System.arraycopy(initialLambda, 0, finalLambda, 0, finalLambda.length);
   }
 
   // run MIRA for one epoch
   public double[] runOptimizer() {
-    List<Integer> sents = new ArrayList<Integer>();
+    List<Integer> sents = new ArrayList<>();
     for (int i = 0; i < sentNum; ++i)
         sents.add(i);
     double[] avgLambda = new double[initialLambda.length]; // only needed if averaging is required
@@ -90,7 +89,7 @@ public class Optimizer {
 	  loss = 0;
 	  thisBatchSize = batchSize;
 	  ++numBatch;
-	  HashMap<Integer, Double> featDiff = new HashMap<Integer, Double>();
+	  HashMap<Integer, Double> featDiff = new HashMap<>();
 	  for(int b = 0; b < batchSize; ++b ) {
 	      //find out oracle and prediction
 	      s = sents.get(sentCount);
@@ -120,51 +119,48 @@ public class Optimizer {
 
 	      //accumulate difference feature vector
 	      if ( b == 0 ) {
-		  for (int i = 0; i < vecOraFeat.length; i++) {
-		      featInfo = vecOraFeat[i].split("=");
-		      diffFeatId = Integer.parseInt(featInfo[0]);
-		      featDiff.put(diffFeatId, Double.parseDouble(featInfo[1]));
-		  }
-		  for (int i = 0; i < vecPredFeat.length; i++) {
-		      featInfo = vecPredFeat[i].split("=");
-		      diffFeatId = Integer.parseInt(featInfo[0]);
-		      if (featDiff.containsKey(diffFeatId)) { //overlapping features
-			  diff = featDiff.get(diffFeatId)-Double.parseDouble(featInfo[1]);
-			  if ( Math.abs(diff) > 1e-20 )
-			      featDiff.put(diffFeatId, diff);
-			  else
-			      featDiff.remove(diffFeatId);
+		      for (String aVecOraFeat : vecOraFeat) {
+			      featInfo = aVecOraFeat.split("=");
+			      diffFeatId = Integer.parseInt(featInfo[0]);
+			      featDiff.put(diffFeatId, Double.parseDouble(featInfo[1]));
+		      }
+		      for (String aVecPredFeat : vecPredFeat) {
+			      featInfo = aVecPredFeat.split("=");
+			      diffFeatId = Integer.parseInt(featInfo[0]);
+			      if (featDiff.containsKey(diffFeatId)) { //overlapping features
+				      diff = featDiff.get(diffFeatId) - Double.parseDouble(featInfo[1]);
+				      if (Math.abs(diff) > 1e-20)
+					      featDiff.put(diffFeatId, diff);
+				      else
+					      featDiff.remove(diffFeatId);
+			      } else //features only firing in the 2nd feature vector
+				      featDiff.put(diffFeatId, -1.0 * Double.parseDouble(featInfo[1]));
 		      }
-		      else //features only firing in the 2nd feature vector
-			  featDiff.put(diffFeatId, -1.0*Double.parseDouble(featInfo[1]));
-		  }
 	      } else {
-		  for (int i = 0; i < vecOraFeat.length; i++) {
-		      featInfo = vecOraFeat[i].split("=");
-		      diffFeatId = Integer.parseInt(featInfo[0]);
-		      if (featDiff.containsKey(diffFeatId)) { //overlapping features
-			  diff = featDiff.get(diffFeatId)+Double.parseDouble(featInfo[1]);
-			  if ( Math.abs(diff) > 1e-20 )
-			      featDiff.put(diffFeatId, diff);
-			  else
-			      featDiff.remove(diffFeatId);
+		      for (String aVecOraFeat : vecOraFeat) {
+			      featInfo = aVecOraFeat.split("=");
+			      diffFeatId = Integer.parseInt(featInfo[0]);
+			      if (featDiff.containsKey(diffFeatId)) { //overlapping features
+				      diff = featDiff.get(diffFeatId) + Double.parseDouble(featInfo[1]);
+				      if (Math.abs(diff) > 1e-20)
+					      featDiff.put(diffFeatId, diff);
+				      else
+					      featDiff.remove(diffFeatId);
+			      } else //features only firing in the new oracle feature vector
+				      featDiff.put(diffFeatId, Double.parseDouble(featInfo[1]));
 		      }
-		      else //features only firing in the new oracle feature vector
-			  featDiff.put(diffFeatId, Double.parseDouble(featInfo[1]));
-		  }
-		  for (int i = 0; i < vecPredFeat.length; i++) {
-		      featInfo = vecPredFeat[i].split("=");
-		      diffFeatId = Integer.parseInt(featInfo[0]);
-		      if (featDiff.containsKey(diffFeatId)) { //overlapping features
-			  diff = featDiff.get(diffFeatId)-Double.parseDouble(featInfo[1]);
-			  if ( Math.abs(diff) > 1e-20 )
-			      featDiff.put(diffFeatId, diff);
-			  else
-			      featDiff.remove(diffFeatId);
+		      for (String aVecPredFeat : vecPredFeat) {
+			      featInfo = aVecPredFeat.split("=");
+			      diffFeatId = Integer.parseInt(featInfo[0]);
+			      if (featDiff.containsKey(diffFeatId)) { //overlapping features
+				      diff = featDiff.get(diffFeatId) - Double.parseDouble(featInfo[1]);
+				      if (Math.abs(diff) > 1e-20)
+					      featDiff.put(diffFeatId, diff);
+				      else
+					      featDiff.remove(diffFeatId);
+			      } else //features only firing in the new prediction feature vector
+				      featDiff.put(diffFeatId, -1.0 * Double.parseDouble(featInfo[1]));
 		      }
-		      else //features only firing in the new prediction feature vector
-			  featDiff.put(diffFeatId, -1.0*Double.parseDouble(featInfo[1]));
-		  }
 	      }
 	      if (!runPercep) { // otherwise eta=1.0
 		  // remember the model scores here are already scaled
@@ -183,10 +179,10 @@ public class Optimizer {
 	  if (!runPercep) { // otherwise eta=1.0
 	      featNorm = 0;
 	      Collection<Double> allDiff = featDiff.values();
-	      for (Iterator<Double> it = allDiff.iterator(); it.hasNext();) {
-		  diff = it.next();
-		  featNorm += diff * diff / ( thisBatchSize * thisBatchSize );
-	      }
+		  for (Double anAllDiff : allDiff) {
+			  diff = anAllDiff;
+			  featNorm += diff * diff / (thisBatchSize * thisBatchSize);
+		  }
 	  }
 	  if( loss <= 0 )
 	      eta = 0;
@@ -269,7 +265,7 @@ public class Optimizer {
     finalMetricScore = bestMetricScore;
 
     // non-optimizable weights should remain unchanged
-    ArrayList<Double> cpFixWt = new ArrayList<Double>();
+    ArrayList<Double> cpFixWt = new ArrayList<>();
     for (int i = 1; i < isOptimizable.length; ++i) {
 	if (!isOptimizable[i])
 	    cpFixWt.add(finalLambda[i]);
@@ -302,21 +298,22 @@ public class Optimizer {
 	  // find out the 1-best candidate for each sentence
 	  // this depends on the training mode
 	  maxModelScore = NegInf;
-	  for (Iterator<String> it = candSet.iterator(); it.hasNext();) {
-	      modelScore = 0.0;
-	      candStr = it.next().toString();
-	      feat_str = feat_hash[i].get(candStr).split("\\s+");
-	      String[] feat_info;
-	      for (int f = 0; f < feat_str.length; f++) {
-		  feat_info = feat_str[f].split("=");
-		  modelScore += Double.parseDouble(feat_info[1]) * finalLambda[Vocabulary.id(feat_info[0])];
-	      }
-	      if (maxModelScore < modelScore) {
-		  maxModelScore = modelScore;
-		  tmpStatsVal = stats_hash[i].get(candStr).split("\\s+"); // save the
-		  // suff stats
+	      for (String aCandSet : candSet) {
+		      modelScore = 0.0;
+		      candStr = aCandSet;
+		      feat_str = feat_hash[i].get(candStr).split("\\s+");
+		      String[] feat_info;
+		      for (String aFeat_str : feat_str) {
+			      feat_info = aFeat_str.split("=");
+			      modelScore +=
+					      Double.parseDouble(feat_info[1]) * finalLambda[Vocabulary.id(feat_info[0])];
+		      }
+		      if (maxModelScore < modelScore) {
+			      maxModelScore = modelScore;
+			      tmpStatsVal = stats_hash[i].get(candStr).split("\\s+"); // save the
+			      // suff stats
+		      }
 	      }
-	  }
 
 	  for (int j = 0; j < suffStatsCount; j++)
 	      corpusStatsVal[j] += Integer.parseInt(tmpStatsVal[j]); // accumulate
@@ -361,107 +358,107 @@ public class Optimizer {
 	      worstPredScore = PosInf;
       }
 
-      for (Iterator<String> it = candSet.iterator(); it.hasNext();) {
-	  cand = it.next().toString();
-	  candMetric = computeSentMetric(sentId, cand); // compute metric score
-
-	  // start to compute model score
-	  candScore = 0;
-	  featStr = feat_hash[sentId].get(cand).split("\\s+");
-	  feats = "";
-
-	  for (int i = 0; i < featStr.length; i++) {
-	      featInfo = featStr[i].split("=");
-	      actualFeatId = Vocabulary.id(featInfo[0]);
-	      candScore += Double.parseDouble(featInfo[1]) * lambda[actualFeatId];
-	      if ((actualFeatId < isOptimizable.length && isOptimizable[actualFeatId])
-		  || actualFeatId >= isOptimizable.length)
-		  feats += actualFeatId + "=" + Double.parseDouble(featInfo[1]) + " ";
-	  }
-
-	  candScore *= featScale; // scale the model score
-
-	  // is this cand oracle?
-	  if (oraSelectMode == 1) {// "hope", b=1, r=1
-	      if (evalMetric.getToBeMinimized()) {// if the smaller the metric score, the better
-		  if (bestOraScore <= (candScore - candMetric)) {
-		      bestOraScore = candScore - candMetric;
-		      oraMetric = candMetric;
-		      oraScore = candScore;
-		      oraFeat = feats;
-		      oraCand = cand;
-		  }
-	      } else {
-		  if (bestOraScore <= (candScore + candMetric)) {
-		      bestOraScore = candScore + candMetric;
-		      oraMetric = candMetric;
-		      oraScore = candScore;
-		      oraFeat = feats;
-		      oraCand = cand;
+	  for (String aCandSet : candSet) {
+		  cand = aCandSet;
+		  candMetric = computeSentMetric(sentId, cand); // compute metric score
+
+		  // start to compute model score
+		  candScore = 0;
+		  featStr = feat_hash[sentId].get(cand).split("\\s+");
+		  feats = "";
+
+		  for (String aFeatStr : featStr) {
+			  featInfo = aFeatStr.split("=");
+			  actualFeatId = Vocabulary.id(featInfo[0]);
+			  candScore += Double.parseDouble(featInfo[1]) * lambda[actualFeatId];
+			  if ((actualFeatId < isOptimizable.length && isOptimizable[actualFeatId])
+					  || actualFeatId >= isOptimizable.length)
+				  feats += actualFeatId + "=" + Double.parseDouble(featInfo[1]) + " ";
 		  }
-	      }
-	  } else {// best metric score(ex: max BLEU), b=1, r=0
-	      if (evalMetric.getToBeMinimized()) {// if the smaller the metric score, the better
-		  if (bestOraScore >= candMetric) {
-		      bestOraScore = candMetric;
-		      oraMetric = candMetric;
-		      oraScore = candScore;
-		      oraFeat = feats;
-		      oraCand = cand;
-		  }
-	      } else {
-		  if (bestOraScore <= candMetric) {
-		      bestOraScore = candMetric;
-		      oraMetric = candMetric;
-		      oraScore = candScore;
-		      oraFeat = feats;
-		      oraCand = cand;
-		  }
-	      }
-	  }
 
-	  // is this cand prediction?
-	  if (predSelectMode == 1) {// "fear"
-	      if (evalMetric.getToBeMinimized()) {// if the smaller the metric score, the better
-		  if (worstPredScore <= (candScore + candMetric)) {
-		      worstPredScore = candScore + candMetric;
-		      predMetric = candMetric;
-		      predScore = candScore;
-		      predFeat = feats;
-		  }
-	      } else {
-		  if (worstPredScore <= (candScore - candMetric)) {
-		      worstPredScore = candScore - candMetric;
-		      predMetric = candMetric;
-		      predScore = candScore;
-		      predFeat = feats;
+		  candScore *= featScale; // scale the model score
+
+		  // is this cand oracle?
+		  if (oraSelectMode == 1) {// "hope", b=1, r=1
+			  if (evalMetric.getToBeMinimized()) {// if the smaller the metric score, the better
+				  if (bestOraScore <= (candScore - candMetric)) {
+					  bestOraScore = candScore - candMetric;
+					  oraMetric = candMetric;
+					  oraScore = candScore;
+					  oraFeat = feats;
+					  oraCand = cand;
+				  }
+			  } else {
+				  if (bestOraScore <= (candScore + candMetric)) {
+					  bestOraScore = candScore + candMetric;
+					  oraMetric = candMetric;
+					  oraScore = candScore;
+					  oraFeat = feats;
+					  oraCand = cand;
+				  }
+			  }
+		  } else {// best metric score(ex: max BLEU), b=1, r=0
+			  if (evalMetric.getToBeMinimized()) {// if the smaller the metric score, the better
+				  if (bestOraScore >= candMetric) {
+					  bestOraScore = candMetric;
+					  oraMetric = candMetric;
+					  oraScore = candScore;
+					  oraFeat = feats;
+					  oraCand = cand;
+				  }
+			  } else {
+				  if (bestOraScore <= candMetric) {
+					  bestOraScore = candMetric;
+					  oraMetric = candMetric;
+					  oraScore = candScore;
+					  oraFeat = feats;
+					  oraCand = cand;
+				  }
+			  }
 		  }
-	      }
-	  } else if (predSelectMode == 2) {// model prediction(max model score)
-	      if (worstPredScore <= candScore) {
-		  worstPredScore = candScore;
-		  predMetric = candMetric;
-		  predScore = candScore;
-		  predFeat = feats;
-	      }
-	  } else {// worst metric score(ex: min BLEU)
-	      if (evalMetric.getToBeMinimized()) {// if the smaller the metric score, the better
-		  if (worstPredScore <= candMetric) {
-		      worstPredScore = candMetric;
-		      predMetric = candMetric;
-		      predScore = candScore;
-		      predFeat = feats;
-		  }
-	      } else {
-		  if (worstPredScore >= candMetric) {
-		      worstPredScore = candMetric;
-		      predMetric = candMetric;
-		      predScore = candScore;
-		      predFeat = feats;
+
+		  // is this cand prediction?
+		  if (predSelectMode == 1) {// "fear"
+			  if (evalMetric.getToBeMinimized()) {// if the smaller the metric score, the better
+				  if (worstPredScore <= (candScore + candMetric)) {
+					  worstPredScore = candScore + candMetric;
+					  predMetric = candMetric;
+					  predScore = candScore;
+					  predFeat = feats;
+				  }
+			  } else {
+				  if (worstPredScore <= (candScore - candMetric)) {
+					  worstPredScore = candScore - candMetric;
+					  predMetric = candMetric;
+					  predScore = candScore;
+					  predFeat = feats;
+				  }
+			  }
+		  } else if (predSelectMode == 2) {// model prediction(max model score)
+			  if (worstPredScore <= candScore) {
+				  worstPredScore = candScore;
+				  predMetric = candMetric;
+				  predScore = candScore;
+				  predFeat = feats;
+			  }
+		  } else {// worst metric score(ex: min BLEU)
+			  if (evalMetric.getToBeMinimized()) {// if the smaller the metric score, the better
+				  if (worstPredScore <= candMetric) {
+					  worstPredScore = candMetric;
+					  predMetric = candMetric;
+					  predScore = candScore;
+					  predFeat = feats;
+				  }
+			  } else {
+				  if (worstPredScore >= candMetric) {
+					  worstPredScore = candMetric;
+					  predMetric = candMetric;
+					  predScore = candScore;
+					  predFeat = feats;
+				  }
+			  }
 		  }
-	      }
 	  }
-      }
 
       oraPredScore[0] = oraMetric;
       oraPredScore[1] = oraScore;
@@ -608,14 +605,14 @@ public class Optimizer {
       return finalMetricScore;
   }
 
-  private Vector<String> output;
+  private final Vector<String> output;
   private double[] initialLambda;
-  private double[] finalLambda;
+  private final double[] finalLambda;
   private double finalMetricScore;
-  private HashMap<String, String>[] feat_hash;
-  private HashMap<String, String>[] stats_hash;
-  private int paramDim;
-  private boolean[] isOptimizable;
+  private final HashMap<String, String>[] feat_hash;
+  private final HashMap<String, String>[] stats_hash;
+  private final int paramDim;
+  private final boolean[] isOptimizable;
   public static int sentNum;
   public static int miraIter; // MIRA internal iterations
   public static int oraSelectMode;
@@ -636,6 +633,6 @@ public class Optimizer {
   public static double[] normalizationOptions;
   public static double[][] bleuHistory;
 
-  private final static double NegInf = (-1.0 / 0.0);
-  private final static double PosInf = (+1.0 / 0.0);
+  private final static double NegInf = Double.NEGATIVE_INFINITY;
+  private final static double PosInf = Double.POSITIVE_INFINITY;
 }