package handwriting.neural;

// Example invocation command:
// java SupervisedLearner -hidden 4 -l2 -rate 0.1 xor 100000
// 4 hidden nodes, 2 perceptrons, learning rate 0.1, learning the xor function with 100000 iterations

public class SupervisedLearner {
    static double[][] xorTargets = {{0.0}, {1.0}, {1.0}, {0.0}};
    static double[][] andTargets = {{1.0}, {0.0}, {0.0}, {0.0}};
    static double[][] inputs = {{1.0, 1.0}, {0.0, 1.0}, {1.0, 0.0}, {0.0, 0.0}};
    
    private double[][] targets;
    private Supervised net;
    private String op;
    private int iterations, hidden;
    private double rate;
    
    public SupervisedLearner() {
        iterations = 1;
        rate = 1.0;
        hidden = 2;
    }
    
    public void processArgs(String[] args) {
    	if (args.length == 0) {
    		System.out.println("Usage: java SupervisedLearner [-hidden numHiddenNodes] (-l1|-l2) [-rate learningRate] (xor|and) [numIterations]");
    		System.exit(1);
    	}
    	
        for (int i = 0; i < args.length; ++i) {
            if (args[i].substring(0, 2).equals("-l")) {
                String level = args[i].substring(2);
                if (level.equals("1")) {
                    net = new Perceptron(2, 1);
                } else if (level.equals("2")) {
                    net = new NeuralNet(2, hidden, 1);
                }
            } else if (i < args.length - 1) {
                if (args[i].equals("-rate") || args[i].equals("-r")) {
                    ++i;
                    rate = Double.parseDouble(args[i]);
                } else if (args[i].equals("-hidden") || args[i].equals("-h")) {
                    ++i;
                    hidden = Integer.parseInt(args[i]);
                    if (net != null) {
                        System.out.println("Input number of hidden nodes before network type");
                        System.exit(1);
                    }
                } else {
                    if (args[i].equals("xor")) {
                        targets = xorTargets;
                    } else if (args[i].equals("and")) {
                        targets = andTargets;
                    } else {
                        System.out.println("I don't know " + args[i]);
                        System.exit(1);
                    }
                    op = args[i];
                    ++i;
                    iterations = Integer.parseInt(args[i]);
                }
            } else {
                System.out.println("Did not understand " + args[i]);
                System.exit(1);
            }
        }
    }
    
    public void teach() {
        for (int i = 0; i < iterations; ++i) {
            for (int input = 0; input < inputs.length; ++input) {
                net.train(inputs[input], targets[input], rate);
            }
            net.updateWeights();
        }
    }
    
    public void printResults() {
        System.out.println(net);
        for (int input = 0; input < inputs.length; ++input) {
            System.out.println("Test " + input + ": " + inputs[input][0] + " " + op + " " + inputs[input][1] + " => " + net.compute(inputs[input])[0]);
        }
    }
    
    public static void main(String[] args) {
        SupervisedLearner sl = new SupervisedLearner();
        sl.processArgs(args);

        System.out.println("original");
        sl.printResults();

        sl.teach();
        sl.printResults();
    }
}
