
package com.kloover.ai.joone;

import org.joone.helpers.factory.JooneTools;
import org.joone.net.NeuralNet;
public class RjugPredictor {
    
    // Input: Temperature (degrees F), Level of Interest (0-10), Price of Gas ($)
    private static double[][] inputArray = new double[][] {
        {0, 8, 3.5, 1},
        {10, 2, 3.0, 0},
        {20, 6, 3.2, 1},
        {30, 1, 3.8, 0},
        {40, 9, 2.90, 1},
        {50, 9, 3.15, 0},
        {60, 3, 3.25, 1},
        {70, 4, 3.3, 0},
        {80, 9, 3.1, 1}
    };
    
    // Output: Number of attendees
    private static double[][] desiredArray = new double[][] {
        {8},
        {15},
        {16},
        {10},
        {22},
        {17},
        {12},
        {30},
        {20}
    };
    
    // Test Input: Lets assume its 60F out, the topic is interesting, and gas is $3.40 a gallon
    private static double[] testInputArray = new double[] {
        70, 9, 2.8, 0
    };
    
    public static double[][] normalizeData(double[][] unnormalizedData) {
    	double[][] retVal = new double[unnormalizedData.length][unnormalizedData[0].length];
    	double[] max = new double[unnormalizedData[0].length];
    	double[] min = new double[unnormalizedData[0].length];
    	
    	for (int i = 0; i < max.length; i++) {
    		max[i] = unnormalizedData[0][i];
    		min[i] = unnormalizedData[0][i];
    	}
    	
    	for (int i = 0; i < unnormalizedData.length; i++) {
    		for (int j = 0; j < unnormalizedData[i].length; j++) {
    			max[j] = Math.max(max[j], unnormalizedData[i][j]);
    			min[j] = Math.min(min[j], unnormalizedData[i][j]);
    		}
    	}
    	
    	for (int i = 0; i < unnormalizedData.length; i++) {
    		for (int j = 0; j < unnormalizedData[i].length; j++) {
    			retVal[i][j] = (unnormalizedData[i][j] - min[j]) / (max[j] - min[j]);
    		}
    	}

    	return retVal;
    }
    
    public static double[] normalizeInputUsingTrainingData(double[][] trainingData, double[] testInputs) {
    	double[] retVal = new double[testInputs.length];
    	double[] max = new double[trainingData[0].length];
    	double[] min = new double[trainingData[0].length];
    	
    	for (int i = 0; i < max.length; i++) {
    		max[i] = trainingData[0][i];
    		min[i] = trainingData[0][i];
    	}
    	
    	for (int i = 0; i < trainingData.length; i++) {
    		for (int j = 0; j < trainingData[i].length; j++) {
    			max[j] = Math.max(max[j], trainingData[i][j]);
    			min[j] = Math.min(min[j], trainingData[i][j]);
    		}
    	}
    	
    	for (int i = 0; i < testInputs.length; i++) {
			retVal[i] = (testInputs[i] - min[i]) / (max[i] - min[i]);
    	}

    	return retVal;
    }
    
    public static double unnormalizeData(double[][] outputVals, double normalizedValue) {
    	double max = outputVals[0][0];
    	double min = outputVals[0][0];
    	
    	for (int i = 0; i < outputVals.length; i++) {
			max = Math.max(max, outputVals[i][0]);
			min = Math.min(min, outputVals[i][0]);
    	}
    	return (normalizedValue * (max - min)) + min;
    }

    public static void main(String[] args) {

    	double[][] normalizedInputArray = normalizeData(inputArray);
    	double[][] normalizedDesiredArray = normalizeData(desiredArray);
    	
    	NeuralNet nnet = JooneTools.create_standard(new int[]{ 4, 2, 1 }, JooneTools.LINEAR);
        double rmse = JooneTools.train(nnet, normalizedInputArray, normalizedDesiredArray,
                50000, 0.01,
                1000, System.out, false);
        
        System.out.println("\nLast RMSE = " + rmse + "\nResults:");
        for (int i=0; i < inputArray.length; i++) {
            double[] output = JooneTools.interrogate(nnet, normalizedInputArray[i]);
            System.out.println("f(" + inputArray[i][0] + ", " + inputArray[i][1] + ", " + inputArray[i][2] + ") = " + unnormalizeData(desiredArray, output[0]));
        }
        
        double testRMSE = JooneTools.test(nnet, normalizedInputArray, normalizedDesiredArray);
        System.out.println("\nTest error = " + testRMSE);
        
        System.out.println("\nSo assuming today's temp is " + testInputArray[0] + "F, the topic is very interesting (" + testInputArray[1] + ") and gas is priced at $" + testInputArray[2] + " a gallon...");
        
        double[] output = JooneTools.interrogate(nnet, normalizeInputUsingTrainingData(inputArray, testInputArray));
        System.out.println("f(" + testInputArray[0] + ", " + testInputArray[1] + ", " + testInputArray[2] + ") = " + unnormalizeData(desiredArray, output[0]));
    }
}