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

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

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

					// +1 for null
					for (int enPositioin = 0; enPositioin < enLenght; enPositioin++) {
						String en = sentencePair.getEnglishWords().get(
								enPositioin);
						// give null string a count
						frSourceProbabilities[0] = f2e.getCount(nullString, en);
						// the probability distribution of the generating source
						// of
						// a given french
						for (int i = 0; i < frLenght; i++) {
							String fr = sentencePair.getFrenchWords().get(i);
							frSourceProbabilities[i + 1] = f2e.getCount(fr, en);
						}
						// normalize
						double sum = DoubleArrays.add(frSourceProbabilities);
						// add the fractional number to counter
						for (int i = 0; i < frSourceProbabilities.length - 1; i++) {
							String fr = sentencePair.getFrenchWords().get(i);
							double p = frSourceProbabilities[i + 1]
									/ sum
									* getPositionProbability(enPositioin, i,
											enLenght, frLenght);
							f2e_new.incrementCount(fr, en, p);
							// fractional number
						}
						// add null string
						f2e_new.incrementCount(nullString, en,
								NullPositionProbabiliy
										* frSourceProbabilities[0] / sum);
					}
				}
				f2e_new.normalize();
				f2e = f2e_new;
				System.out.println("f2e training iteration "+iterationTimes+" done.");
			}
		}