import io.Preface;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import training.Feature;
import training.Forest;

public class TrainLogLinear {
	public static void main(String[] args) {
		double LEARNING_RATE = 0.5;

		if ( args.length < 5 ) {
			System.err.println("TrainLogLinear requires 5 arguments: <forestFile> <weightsFile> <numIters> <fromSentence> <toSentence>");
			return;
		}

		String forestFile = args[0];
		String weightsFile = args[1];
		String numItersStr = args[2];
		String fromSent = args[3];
		String toSent = args[4];

		int fromSentence = Integer.parseInt(fromSent);
		int toSentence = Integer.parseInt(toSent);
		int numIterations = Integer.parseInt(numItersStr);

		try ( BufferedReader in = new BufferedReader(new FileReader(forestFile));
			  PrintWriter out = new PrintWriter(new FileWriter(weightsFile)) ) {

			Preface.readPreface(in);

			String line = in.readLine();
			int numFeatures = Integer.parseInt(line);
			Feature[] features = new Feature[numFeatures];

			for ( int i = 0; i < numFeatures; i++ ) {
				features[i] = new Feature(i);
			}

			ArrayList<Forest> forests = new ArrayList<Forest>();

			for ( int numForest = 1; numForest <= (toSentence - fromSentence + 1) ; numForest++ ) {
				System.out.println("Reading forest " + numForest);

				if ( (line = in.readLine()) == null) {
					break;
				}

				int numNodes = Integer.parseInt(line);
				forests.add(new Forest(in, features, numNodes));
			}

			for ( int iteration = 1; iteration <= numIterations; iteration++ ) {
				double logLikelihood = 0.0;

				for ( Forest forest : forests ) {
					forest.resetNodeValues();

					for ( int i = 0; i < numFeatures; i++ ) {
						features[i].resetExpValues();
					}

					double Z = forest.calcInside(false);
					forest.calcOutside(-Z, false);
					// outside also calculates the feature expectations

					forest.resetNodeValues();
					// presumably we need to reset here?
					double goldZ = forest.calcInside(true);
					forest.calcOutside(-goldZ, true);

					logLikelihood += forest.logLikelihood();

					for ( int i = 0; i < numFeatures; i++ ) {
						features[i].adaGradUpdate(LEARNING_RATE);
					}
				}

				System.out.println("Log-likelihood after iteration " + iteration + ": " + logLikelihood);
			}

			for ( int i = 0; i < features.length; i++ ) {
				out.println(i + " " + features[i].getLambda());
			}
		} catch (FileNotFoundException e) {
			System.err.println(e);
		} catch (IOException e) {
			System.err.println(e);
		}
	}
}

@@ -1,12 +1,31 @@
+import io.Forests;%0A
 import io.Pr
@@ -214,36 +214,8 @@
 ter;
-%0Aimport java.util.ArrayList;
 %0A%0Aim
@@ -1231,33 +1231,23 @@
 %09%09%7D%0A%0A%09%09%09
-ArrayList%3C
 Forest
-%3E
+s
  forests
@@ -1257,456 +1257,339 @@
 new 
-ArrayList%3CForest%3E();%0A%0A%09%09%09for ( int numForest = 1; numForest %3C= (toSentence - fromSentence + 1) ; numForest++ ) %7B%0A%09%09%09%09System.out.println(%22Reading forest %22 + numForest);%0A%0A%09%09%09%09if ( (line = in.readLine()) == null) %7B%0A%09%09%09%09%09break;%0A%09%09%09%09%7D%0A%0A%09%09%09%09
+Forests(in, features);%0A%0A%09%09%09for ( int iteration = 1; iteration %3C= numIterations; iteration++ ) %7B%0A%09%09%09%09double logLikelihood = 0.0;%0A%0A%09%09%09%09forests.skip(fromSentence - 1);%0A%0A%09%09%09%09for ( 
 int num
-Nod
+For
 es
+t
  = 
-Integer.parseInt(line);%0A%09%09%09%09forests.add(new Forest(in, features, numNodes));%0A%09%09%09%7D%0A%0A%09%09%09for ( int iteration = 1; iteration %3C= numIterations; iteration++ ) %7B%0A%09%09%09%09double logLikelihood = 0.0
+fromSentence; numForest %3C= toSentence && forests.hasNext() ; numForest++ ) %7B%0A%09%09%09%09%09System.out.println(%22Reading forest %22 + numForest)
 ;%0A%0A%09%09%09%09
-for ( 
+%09
 Fore
@@ -1602,17 +1602,17 @@
 est 
-:
+=
  forests
  ) %7B
@@ -1607,20 +1607,25 @@
  forests
- ) %7B
+.next();%0A
 %0A%09%09%09%09%09fo
@@ -2096,39 +2096,34 @@
 r ( 
-int i = 0; i %3C numF
+Feature feature : f
 eatures
-; i++
  ) %7B
@@ -2136,20 +2136,16 @@
 %09feature
-s%5Bi%5D
 .adaGrad
@@ -2391,72 +2391,8 @@
 %09%09%7D%0A
-%09%09%7D catch (FileNotFoundException e) %7B%0A%09%09%09System.err.println(e);%0A
 %09%09%7D 

Refactor TrainLogLinear