package net.woodyfolsom.msproj.ann;

import java.io.File;
import java.util.Arrays;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.neuroph.core.NeuralNetwork;
import org.neuroph.core.learning.SupervisedTrainingElement;
import org.neuroph.core.learning.TrainingSet;

public class NeuralNetLearnerTest {
	private static final String FILENAME = "myMlPerceptron.nnet";

	@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() {
		NeuralNetLearner nnLearner = new XORLearner();

		// create training set (logical XOR function)
		TrainingSet<SupervisedTrainingElement> trainingSet = new TrainingSet<SupervisedTrainingElement>(
				2, 1);
		for (int x = 0; x < 1000; x++) {
		trainingSet.addElement(new SupervisedTrainingElement(new double[] { 0,
				0 }, new double[] { 0 }));
		trainingSet.addElement(new SupervisedTrainingElement(new double[] { 0,
				1 }, new double[] { 1 }));
		trainingSet.addElement(new SupervisedTrainingElement(new double[] { 1,
				0 }, new double[] { 1 }));
		trainingSet.addElement(new SupervisedTrainingElement(new double[] { 1,
				1 }, new double[] { 0 }));
		}
		
		nnLearner.learn(trainingSet);
		NeuralNetwork nnet = nnLearner.getNeuralNetwork();

		TrainingSet<SupervisedTrainingElement> valSet = new TrainingSet<SupervisedTrainingElement>(
				2, 1);
		valSet.addElement(new SupervisedTrainingElement(new double[] { 0,
				0 }, new double[] { 0 }));
		valSet.addElement(new SupervisedTrainingElement(new double[] { 0,
				1 }, new double[] { 1 }));
		valSet.addElement(new SupervisedTrainingElement(new double[] { 1,
				0 }, new double[] { 1 }));
		valSet.addElement(new SupervisedTrainingElement(new double[] { 1,
				1 }, new double[] { 0 }));
		
		System.out.println("Output from eval set (learned network):");
		testNetwork(nnet, valSet);

		nnet.save(FILENAME);
		nnet = NeuralNetwork.load(FILENAME);
		
		System.out.println("Output from eval set (learned network):");
		testNetwork(nnet, valSet);
	}
	
	private void testNetwork(NeuralNetwork nnet, TrainingSet<SupervisedTrainingElement> trainingSet) {
		for (SupervisedTrainingElement trainingElement : trainingSet.elements()) {

			nnet.setInput(trainingElement.getInput());
			nnet.calculate();
			double[] networkOutput = nnet.getOutput();
			System.out.print("Input: "
					+ Arrays.toString(trainingElement.getInput()));
			System.out.println(" Output: " + Arrays.toString(networkOutput));

		}
	}
}