package net.woodyfolsom.msproj.ann;

import java.io.File;
import java.io.IOException;

import org.encog.ml.data.MLDataSet;
import org.encog.ml.data.basic.BasicMLDataSet;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class XORFilterTest {
	private static final String FILENAME = "xorPerceptron.net";

	@AfterClass
	public static void deleteNewNet() {
		File file = new File(FILENAME);
		if (file.exists()) {
			file.delete();
		}
	}

	@BeforeClass
	public static void deleteSavedNet() {
		File file = new File(FILENAME);
		if (file.exists()) {
			file.delete();
		}
	}

	@Test
	public void testLearnSaveLoad() throws IOException {
		NeuralNetFilter nnLearner = new XORFilter();
		System.out.println("Learned network after " + nnLearner.getActualTrainingEpochs() + " training epochs.");
		
		// create training set (logical XOR function)
		int size = 1;
		double[][] trainingInput = new double[4 * size][];
		double[][] trainingOutput = new double[4 * size][];
		for (int i = 0; i < size; i++) {
			trainingInput[i * 4 + 0] = new double[] { 0, 0 };
			trainingInput[i * 4 + 1] = new double[] { 0, 1 };
			trainingInput[i * 4 + 2] = new double[] { 1, 0 };
			trainingInput[i * 4 + 3] = new double[] { 1, 1 };
			trainingOutput[i * 4 + 0] = new double[] { 0 };
			trainingOutput[i * 4 + 1] = new double[] { 1 };
			trainingOutput[i * 4 + 2] = new double[] { 1 };
			trainingOutput[i * 4 + 3] = new double[] { 0 };
		}

		// create training data
		MLDataSet trainingSet = new BasicMLDataSet(trainingInput, trainingOutput);
		
		nnLearner.learn(trainingSet);

		double[][] validationSet = new double[4][2];

		validationSet[0] = new double[] { 0, 0 };
		validationSet[1] = new double[] { 0, 1 };
		validationSet[2] = new double[] { 1, 0 };
		validationSet[3] = new double[] { 1, 1 };

		System.out.println("Output from eval set (learned network, pre-serialization):");
		testNetwork(nnLearner, validationSet);

		nnLearner.save(FILENAME);
		nnLearner.load(FILENAME);

		System.out.println("Output from eval set (learned network, post-serialization):");
		testNetwork(nnLearner, validationSet);
	}

	private void testNetwork(NeuralNetFilter nnLearner, double[][] validationSet) {
		for (int valIndex = 0; valIndex < validationSet.length; valIndex++) {
			DoublePair dp = new DoublePair(validationSet[valIndex][0],validationSet[valIndex][1]);
			System.out.println(dp + " => " + nnLearner.compute(dp));
		}
	}
}