package greycat.ml.neuralnet;

import greycat.ml.common.matrix.VolatileDMatrix;
import greycat.ml.neuralnet.layer.Layer;
import greycat.ml.neuralnet.layer.Layers;
import greycat.ml.neuralnet.loss.Loss;
import greycat.ml.neuralnet.loss.Losses;
import greycat.ml.neuralnet.process.ExMatrix;
import greycat.ml.neuralnet.process.ProcessGraph;
import greycat.struct.EGraph;

public class NeuralNet {

    private EGraph backend;
    private Layer[] layers;

    private Loss lossUnit;

    public NeuralNet(EGraph p_backend) {
        backend = p_backend;
        int nb = backend.size();
        if (nb > 0) {
            for (int i = 0; i < layers.length; i++) {
                layers[i] = Layers.toLayer(backend.node(i));
            }
        }

        //todo load loss unit here
        lossUnit= Losses.getUnit(0,null);
        //check the init, first name
    }

    void learn(double[] inputs, double[] outputs) {
        ProcessGraph cg = new ProcessGraph(true);
        ExMatrix input=ExMatrix.createFromW(VolatileDMatrix.wrap(inputs,inputs.length,1));


        ExMatrix targetOutput=ExMatrix.createFromW(VolatileDMatrix.wrap(outputs,outputs.length,1));
        ExMatrix actualOutput=internalForward(cg,input);

        cg.applyLoss(lossUnit,actualOutput,targetOutput);


        cg.backpropagate();
    }

    double[] predict(double[] inputs){
        ProcessGraph cg = new ProcessGraph(false);
        ExMatrix input=ExMatrix.createFromW(VolatileDMatrix.wrap(inputs,inputs.length,1));
        ExMatrix actualOutput=internalForward(cg,input);
        return actualOutput.data();
    }


    ExMatrix internalForward(ProcessGraph cg, ExMatrix input){
        ExMatrix nextInput=input;
        for (int i = 0; i < layers.length; i++) {
            nextInput=layers[i].forward(nextInput, cg);//TODO pass input
        }
        return nextInput;
    }

    //TODO idem for forward

}

@@ -790,16 +790,17 @@
 lossUnit
+ 
 = Losses
@@ -810,16 +810,17 @@
 tUnit(0,
+ 
 null);%0A 
@@ -978,33 +978,35 @@
   ExMatrix input
-=
+ = 
 ExMatrix.createF
@@ -1030,32 +1030,33 @@
 rix.wrap(inputs,
+ 
 inputs.length,1)
@@ -1049,24 +1049,25 @@
 puts.length,
+ 
 1));%0A%0A%0A     
@@ -1090,17 +1090,19 @@
 etOutput
-=
+ = 
 ExMatrix
@@ -1143,16 +1143,17 @@
 outputs,
+ 
 outputs.
@@ -1151,32 +1151,33 @@
  outputs.length,
+ 
 1));%0A        ExM
@@ -1186,33 +1186,35 @@
 rix actualOutput
-=
+ = 
 internalForward(
@@ -1208,32 +1208,33 @@
 ernalForward(cg,
+ 
 input);%0A%0A       
@@ -1256,16 +1256,17 @@
 ossUnit,
+ 
 actualOu
@@ -1270,16 +1270,17 @@
 lOutput,
+ 
 targetOu
@@ -1360,16 +1360,17 @@
  inputs)
+ 
 %7B%0A      
@@ -1436,17 +1436,19 @@
 ix input
-=
+ = 
 ExMatrix
@@ -1488,16 +1488,17 @@
 (inputs,
+ 
 inputs.l
@@ -1503,16 +1503,17 @@
 .length,
+ 
 1));%0A   
@@ -1538,17 +1538,19 @@
 alOutput
-=
+ = 
 internal
@@ -1560,16 +1560,17 @@
 ward(cg,
+ 
 input);%0A
@@ -1674,16 +1674,17 @@
 x input)
+ 
 %7B%0A      
@@ -1703,17 +1703,19 @@
 extInput
-=
+ = 
 input;%0A 
@@ -1784,17 +1784,19 @@
 extInput
-=
+ = 
 layers%5Bi

format code