package net.woodyfolsom.msproj.ann2;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.bind.JAXBException;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class MultiLayerPerceptronTest {
	static final File TEST_FILE = new File("data/test/mlp.net");
	static final double EPS = 0.001;
	
	@BeforeClass
	public static void setUp() {
		if (TEST_FILE.exists()) {
			TEST_FILE.delete();
		}
	}

	@AfterClass
	public static void tearDown() {
		if (TEST_FILE.exists()) {
			TEST_FILE.delete();
		}
	}

	@Test
	public void testConstructor() {
		new MultiLayerPerceptron(true, 2, 4, 1);
		new MultiLayerPerceptron(false, 2, 1);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testConstructorTooFewLayers() {
		new MultiLayerPerceptron(true, 2);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testConstructorTooFewNeurons() {
		new MultiLayerPerceptron(true, 2, 4, 0, 1);
	}

	@Test
	public void testPersistence() throws JAXBException, IOException {
		FeedforwardNetwork mlp = new MultiLayerPerceptron(true, 2, 4, 1);
		FileOutputStream fos = new FileOutputStream(TEST_FILE);
		assertTrue(mlp.save(fos));
		fos.close();
		FileInputStream fis = new FileInputStream(TEST_FILE);
		FeedforwardNetwork mlp2 = new MultiLayerPerceptron();
		assertTrue(mlp2.load(fis));
		assertEquals(mlp, mlp2);
		fis.close();
	}
	
	@Test
	public void testCompute() {
		FeedforwardNetwork mlp = new MultiLayerPerceptron(true, 2, 2, 1);
		NNDataPair expected = new NNDataPair(new NNData(new String[]{"x","y"}, new double[]{0.0,0.0}),new NNData(new String[]{"xor"}, new double[]{0.0}));
		NNDataPair actual = new NNDataPair(new NNData(new String[]{"x","y"}, new double[]{0.0,0.0}),new NNData(new String[]{"xor"}, new double[]{0.5}));
		NNData actualOutput = mlp.compute(actual);
		assertEquals(expected.getIdeal(), actualOutput);
	}
	
	@Test
	public void testXORnetwork() {
		FeedforwardNetwork mlp = new MultiLayerPerceptron(true, 2, 2, 1);
		mlp.setWeights(new double[] {
				0.341232, 0.129952, -0.923123,	//hidden neuron 1 from input0, input1, bias 
				-0.115223, 0.570345, -0.328932, //hidden neuron 2 from input0, input1, bias
				-0.993423, 0.164732, 0.752621}); //output
		
		for (Connection connection : mlp.getConnections()) {
			System.out.println(connection);
		}
		NNDataPair expected = new NNDataPair(new NNData(new String[]{"x","y"}, new double[]{0.0,0.0}),new NNData(new String[]{"xor"}, new double[]{0.367610}));
		NNDataPair actual = new NNDataPair(new NNData(new String[]{"x","y"}, new double[]{0.0,0.0}),new NNData(new String[]{"xor"}, new double[]{0.0}));
		NNData actualOutput = mlp.compute(actual);
		assertEquals(expected.getIdeal().getValues()[0], actualOutput.getValues()[0], EPS);		
	}
	/**
	 * 
Hidden Neuron 1:	w2(0,1) = 0.341232	w2(1,1) = 0.129952	w2(2,1) =-0.923123
Hidden Neuron 2:	w2(0,2) =-0.115223	w2(1,2) = 0.570345	w2(2,2) =-0.328932
Output Neuron:	w3(0,1) =-0.993423	w3(1,1) = 0.164732	w3(2,1) = 0.752621

	 */
}
