// Path: src/utils/NumericalFunctions.java
// public class NumericalFunctions {
// 	public static double addLogs(double x, double y) {
// 		if (y <= x) {
// 			return x + Math.log1p(Math.exp(y - x));
// 		} else {
// 			return y + Math.log1p(Math.exp(x - y));
// 		}
// 	}
// 
// 	/*
// 	 * e^x + e^y = e^z - need to solve for z
// 	 * 
// 	 * z = log(e^x + e^y) = log(e^x.(e^x + e^y)/e^x) = x + log(1 + e^(y-x))
// 	 * 
// 	 * useful since e^(y-x) is presumably easier to calculate than either e^x or
// 	 * e^y
// 	 */
// 
// 	public static double adaGradUpdate(double gradient, double sumGradSquared, double learningRate) {
// 		double eps = 0.001;
// 
// 		return learningRate * gradient / (Math.sqrt(sumGradSquared) + eps);
// 	}
// }


import utils.NumericalFunctions;
				// and viterbi
				// scores on
				// disj nodes
			} else {
				inside = leftChild.score;
			}
		} else {
			inside = 0.0;
		}

		for (int i = 0; i < features.length; i++) {
			inside += features[i].getLambda();
		}

		return inside;
	}

	// also calculates the feature expectations
	public void calcOutside(double outside, double invZ, boolean gold) {
		double sum = 0.0;
		for (int i = 0; i < features.length; i++) {
			sum += features[i].getLambda();
		}
		sum += outside;

		if (leftChild != null) {
			if (rightChild != null) {
				if (leftChild.outside != 0.0) {
					// suggest this may not be
					// completely correct
// Path: src/utils/NumericalFunctions.java
// public class NumericalFunctions {
// 	public static double addLogs(double x, double y) {
// 		if (y <= x) {
// 			return x + Math.log1p(Math.exp(y - x));
// 		} else {
// 			return y + Math.log1p(Math.exp(x - y));
// 		}
// 	}
// 
// 	/*
// 	 * e^x + e^y = e^z - need to solve for z
// 	 * 
// 	 * z = log(e^x + e^y) = log(e^x.(e^x + e^y)/e^x) = x + log(1 + e^(y-x))
// 	 * 
// 	 * useful since e^(y-x) is presumably easier to calculate than either e^x or
// 	 * e^y
// 	 */
// 
// 	public static double adaGradUpdate(double gradient, double sumGradSquared, double learningRate) {
// 		double eps = 0.001;
// 
// 		return learningRate * gradient / (Math.sqrt(sumGradSquared) + eps);
// 	}
// }


// Path: src/training/ConjNode.java
import utils.NumericalFunctions;

				// and viterbi
				// scores on
				// disj nodes
			} else {
				inside = leftChild.score;
			}
		} else {
			inside = 0.0;
		}

		for (int i = 0; i < features.length; i++) {
			inside += features[i].getLambda();
		}

		return inside;
	}

	// also calculates the feature expectations
	public void calcOutside(double outside, double invZ, boolean gold) {
		double sum = 0.0;
		for (int i = 0; i < features.length; i++) {
			sum += features[i].getLambda();
		}
		sum += outside;

		if (leftChild != null) {
			if (rightChild != null) {
				if (leftChild.outside != 0.0) {
					// suggest this may not be
					// completely correct
					leftChild.outside = NumericalFunctions.addLogs(