// Built by Peter A Noble January 2019 Email: panoble2017@gmail.com
// Copyright

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

// g++ predict.cpp -o predict
// ./predict 83 9 weights.txt biases.txt train_x.txt train_y.txt out.txt

using namespace std;

int main (int argc, char * const argv[]) {
int inputs=0;
inputs=atoi(argv[1]);
int hidden=0;
hidden=atoi(argv[2]);
ifstream in(argv[3]); 
ifstream in2(argv[4]); 
ifstream in3(argv[5]); 
ifstream in4(argv[6]); 
	
ofstream out(argv[7]); 
int standard=100;
int num=10000;

char** code = new char*[num];
	for (int s = 0; s < num; s++)
		{		
		code[s] = new char[standard];
		strcpy(code[s],"test");
		}

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+1];
for (int t = 0; t < (hidden+1); t++)
	{
	biases[t] = 0.0;
	}		

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

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

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

int number=0;
int s=0,i=0;
double output=0.0;
double actual=0.0;
double max=1.0;
double min=0.0;
char bs[standard];
double predict=0.0;
int count=0;
//int total_count=0;
int t1=0;

in >> number;
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[inputs-1][hidden-1] << "\n" << flush; exit(1);


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

for (int d = 0; d < (hidden+1); d++)
	{
	in2 >> biases[d]; 
	}

//cout << biases[hidden] << "\n" << flush; exit(1); all wgt and biases inputs work

// input headers
for (int s = 0; s < inputs; s++)
	{
	in3 >> code[s];
	}
in4 >> bs;
//cout << code[inputs-1] << "\n" << flush; exit(1); //works

		
while(!in3.eof()) //train_x.txt
	{
	for (int s = 0; s < inputs; s++)
		{
		in3 >> matrix[s][t1];
		}
	in4 >> matrix[inputs][t1];
	t1=t1+1;
	}
//cout << matrix[inputs][0] << "\n" << flush; exit(1); //works

//original data
//move data from matrix to var
/*for (int a = 0; a < t1; a++)
	{
	for (int s = 0; s < inputs+1; s++)
		{	
		var[s][a]=matrix[s][a];
		}
	}
*/

for (int a = 0; a < t1; a++)
	//for (int a = 0; a < 2; a++)
	{
	output=0.0;
	predict=0.0;
	
	for (int s = 0; s < hidden; s++)
		{	
		array[s]=0.0;	
		for (int t = 0; t < inputs; t++)
			{		
			//array[s]=(var[t][a]*wgts[t][s])+array[s];			
			array[s]=(matrix[t][a]*wgts[t][s])+array[s];			
			//cout << matrix[t][s] << "\t";
			//out << array[s] << "\t";
			}
		//out << "\n" << flush; 
		//cout << "\n" << flush; exit(1);
		array[s]=double(double(1)/double(1+exp(-1*(array[s]+biases[s]))));
		//array[s]=(array[s]);
		}
	for (int s = 0; s < hidden; s++)
		{	
		output=((array[s]*wgts[inputs][s])+output);	
		}
		output=(output+biases[hidden]);
		//output=(output * (max-min)) + min;	
		predict = output;
		actual=(matrix[inputs][a]);

		cout <<  predict << "\t" << actual << "\n";; //exit(1);
		out << predict << "\t" << actual << "\n";; //exit(1);
	}
//	output=double(double(count)/t1);
//	cout << "Original\t" << count << "\t" << t1 << "\t" << output << "\n";
//	out << "Original\t\t" << count << "\t" << t1 << "\t" << output << "\n";

  return 0;
}
