//
// Built by: Peter A Noble PhD Emails: panoble2017@gmail.com pnoble@upcontracter.up.com
// October, 2018


#include <fstream>
#include <string>
#include <iostream>
#include <math.h>
#include <cstdlib>
#include <float.h>
#include <complex>
#include <iomanip>

// g++ predict_y3.cpp -o predict_y

// ./predict_y 12848 113 weights[0].txt weights[1].txt weights[2].txt weights[3].txt mnt/shuf_10.csv out.txt
// ./predict_y 12848 113 weights[0].txt weights[1].txt weights[2].txt weights[3].txt shuf_test.txt out.txt

//purpose is to predict y based on input data, weights and biases.

using namespace std;

int main (int argc, char * const argv[]) {

int inputs=atoi(argv[1]);
int hidden=atoi(argv[2]);
ifstream in(argv[3]); 
ifstream in2(argv[4]); 
ifstream in3(argv[5]); 
ifstream in4(argv[6]); 
ifstream in5(argv[7]); 
	
ofstream out(argv[8]); 

double** wgts = new double*[inputs+1];
for (int s = 0; s < inputs+1; s++)		
	{
	wgts[s] = new double[hidden];
	for (int t = 0; t < hidden; t++)
		{
		wgts[s][t] = 0.0;
		}		
	}
	
double* array = new double[hidden];
for (int t = 0; t < hidden; t++)
	{
	array[t]=0.0;			
	}

double* biases= new double[hidden];
for (int t = 0; t < (hidden); t++)
	{
	biases[t] = 0.0;
	}		

double* var= new double[inputs+1];
for (int t = 0; t < (inputs+1); t++)
	{
	var[t] = 0.0;
	}		

double last_wgt=0.0;

int number=0;
int count=0;
int s=0,i=0;
double output=0.0;
double actual=0.0;
double max=21080;
double min=-21080;
double out2=0.0;

for (int s = 0; s < hidden; s++) // gets the weights of the inner neurons
	{
	for (int t = 0; t < inputs; t++) 	
		{
		 in >> wgts[t][s];
		 //cout << wgts[t][s] << "\t";
		}
	//cout << "\n";
	}
//cout << flush; exit(1);
// above works for weight[0]

for (int s = 0; s < hidden; s++) // gets the weights of the outer neuron
	{
	in2 >> wgts[inputs][s];
	//cout << wgts[inputs][s] << "\n";
	}
//cout << flush; exit(1);
// above works for weight[1]

for (int d = 0; d < (hidden); d++)
	{
	in3 >> biases[d]; //113
	//cout << biases[d] << "\n";
	}
//cout << flush; exit(1);
// above works for weights[2]

	in4 >> last_wgt;
//cout << last_wgt << "\n" <<  flush; exit(1);
// above works for weights[3]

while(!in5.eof())
	{
	actual=0;
	for (int s = 0; s < inputs+1; s++)
		{
		in5 >> var[s];
		}
	i=i+1;
 //cout << var[inputs] << "\n" << flush; exit(0);
 
	for (int s = 0; s < hidden; s++)
		{
		out2=0.0;
		for (int t = 0; t < inputs; t++)
			{		
			out2=(var[t]*wgts[t][s])+out2;			//
			}
		array[s]=double(1)/double(1+exp(-1*(out2+wgts[inputs][s])));
		}

	output=0.0;
	for (int s = 0; s < hidden; s++)
		{	
		output=((array[s]*biases[s]))+output;	
		}
	output=output+last_wgt;;
		
	output=double(1)/double(1+exp(-1*((output))));	 
	output=(output * (max-min)) + min;	
	actual=var[inputs];
	actual=(var[inputs]*(max-min)) + min;
	cout << i << "\t" << int(output) << "\t" << int(actual) << "\n" << flush ;; 
	//if (i==10) {exit(1);}
	out << i << "\t" << int(output) << "\t" << int(actual) << "\n";; //exit(1);
	}
	
  return 0;
}
