void traine2f() {
			// EM Algorithm
			// init e2f;
			e2f = new CounterMap<String, String>();
			for (SentencePair sentencePair : trainingSentencePairs) {
				for (String fr : sentencePair.getFrenchWords()) {
					for (String en : sentencePair.getEnglishWords()) {
						if (!e2f.containsKeyValue(en, fr)) {
							e2f.incrementCount(en, fr, 1.0);
						}
					}
					e2f.incrementCount(nullString, fr, 1.0);
				}
			}
			// uniform e2f
			e2f.normalize();

			// until not converged
			int iterationTimes = 20;
			while (iterationTimes-- > 0) {
				// init another e2f
				CounterMap<String, String> e2f_new = new CounterMap<String, String>();

				for (SentencePair sentencePair : trainingSentencePairs) {
					int enLenght = sentencePair.getEnglishWords().size();
					int frLenght = sentencePair.getFrenchWords().size();
					double[] enSourceProbabilities = new double[enLenght + 1];

					// +1 for null
					for (int frPositioin = 0; frPositioin < frLenght; frPositioin++) {
						String fr = sentencePair.getFrenchWords().get(
								frPositioin);
						// give null string a count
						enSourceProbabilities[0] = e2f.getCount(nullString, fr);
						// the probability distribution of the generating source
						// of
						// a given french
						for (int i = 0; i < enLenght; i++) {
							String en = sentencePair.getEnglishWords().get(i);
							enSourceProbabilities[i + 1] = e2f.getCount(en, fr);
						}
						// normalize
						double sum = DoubleArrays.add(enSourceProbabilities);
						// add the fractional number to counter
						for (int i = 0; i < enSourceProbabilities.length - 1; i++) {
							String en = sentencePair.getEnglishWords().get(i);
							double p = enSourceProbabilities[i + 1]
									/ sum
									* getPositionProbability(i, frPositioin,
											enLenght, frLenght);
							e2f_new.incrementCount(en, fr, p);
							// fractional number
						}
						// add null string
						e2f_new.incrementCount(nullString, fr,
								NullPositionProbabiliy
										* enSourceProbabilities[0] / sum);
					}
				}
				e2f_new.normalize();
				e2f = null; // for garbage collection
				e2f = e2f_new;
			}
		}