#include <yarp/os/Port.h>
#include <yarp/os/BufferedPort.h>
#include <yarp/os/Bottle.h>


#include "functions.h"
#include "mlp.h"
#include "yarp.h"
#include "cacla.h"
#include "esn.h"

gsl_matrix *test_in;
int target = 0, action = 0;
char command[10] = "csbrgb";

#define DATA "5905"

void esnTrain_13(){
	gsl_matrix *output;

	FILE *f;
	fopen_s(&f, "./lang/lang_desired_3_randstart.txt", "r");
	gsl_matrix *desired_3 = gsl_matrix_alloc(3, 900);
	gsl_matrix_fscanf(f, desired_3);
	fclose(f);

	fopen_s(&f, "./lang/lang_hidden_3_randstart.txt", "r");
	gsl_matrix *input_3 = gsl_matrix_alloc(40, 900);
	gsl_matrix_fscanf(f, input_3);
	fclose(f);

	fopen_s(&f, "./lang/lang_desired_1.txt", "r");
	gsl_matrix *desired_1 = gsl_matrix_alloc(6, 216);
	gsl_matrix_fscanf(f, desired_1);
	fclose(f);

	fopen_s(&f, "./lang/lang_hidden_1.txt", "r");
	gsl_matrix *input_1 = gsl_matrix_alloc(50, 216);
	gsl_matrix_fscanf(f, input_1);
	fclose(f);

	fopen_s(&f, "./lang/desired.txt", "r");
	gsl_matrix *action_1 = gsl_matrix_alloc(3, 216);
	gsl_matrix_fscanf(f, action_1);
	fclose(f);

	gsl_matrix *input = gsl_matrix_alloc(input_1->size1 + input_3->size1, input_1->size2 * (input_3->size2 / 3)); 
	gsl_matrix *desired = gsl_matrix_alloc(desired_1->size1 + desired_3->size1, input_1->size2 * (desired_3->size2 / 3)); 

	for(int i = 0; i < input_1->size2; i++){//input_1->size2
		int act1 = 0;
		if(gsl_matrix_get(action_1, 1, i) == 1.0){
			act1 = 1;
		}
		if(gsl_matrix_get(action_1, 2, i) == 1.0){
			act1 = 2;
		}		

		gsl_matrix_view inputView = gsl_matrix_submatrix(input, 0, i * (input_3->size2 / 3), input_3->size1, input_3->size2 / 9);
		gsl_matrix_view desiredView = gsl_matrix_submatrix(desired, 0, i * (desired_3->size2 / 3), desired_3->size1, desired_3->size2 / 9);
		gsl_matrix_view input_3view = gsl_matrix_submatrix(input_3, 0, act1 * (input_3->size2 / 9), input_3->size1, input_3->size2 / 9);
		gsl_matrix_view desired_3view = gsl_matrix_submatrix(desired_3, 0, act1 * (desired_3->size2 / 9), desired_3->size1, desired_3->size2 / 9);
		gsl_matrix_memcpy(&inputView.matrix, &input_3view.matrix);
		gsl_matrix_memcpy(&desiredView.matrix, &desired_3view.matrix);

		inputView = gsl_matrix_submatrix(input, 0, i * (input_3->size2 / 3) + (input_3->size2 / 9), input_3->size1, input_3->size2 / 9);
		desiredView = gsl_matrix_submatrix(desired, 0, i * (desired_3->size2 / 3) + (desired_3->size2 / 9), desired_3->size1, desired_3->size2 / 9);
		input_3view = gsl_matrix_submatrix(input_3, 0, act1 * (input_3->size2 / 9) + (input_3->size2 / 3), input_3->size1, input_3->size2 / 9);
		desired_3view = gsl_matrix_submatrix(desired_3, 0, act1 * (desired_3->size2 / 9) + (desired_3->size2 / 3), desired_3->size1, desired_3->size2 / 9);
		gsl_matrix_memcpy(&inputView.matrix, &input_3view.matrix);
		gsl_matrix_memcpy(&desiredView.matrix, &desired_3view.matrix);

		inputView = gsl_matrix_submatrix(input, 0, i * (input_3->size2 / 3) + 2*(input_3->size2 / 9), input_3->size1, input_3->size2 / 9);
		desiredView = gsl_matrix_submatrix(desired, 0, i * (desired_3->size2 / 3) + 2*(desired_3->size2 / 9), desired_3->size1, desired_3->size2 / 9);
		input_3view = gsl_matrix_submatrix(input_3, 0, act1 * (input_3->size2 / 9) + 2*(input_3->size2 / 3), input_3->size1, input_3->size2 / 9);
		desired_3view = gsl_matrix_submatrix(desired_3, 0, act1 * (desired_3->size2 / 9) + 2*(desired_3->size2 / 3), desired_3->size1, desired_3->size2 / 9);
		gsl_matrix_memcpy(&inputView.matrix, &input_3view.matrix);
		gsl_matrix_memcpy(&desiredView.matrix, &desired_3view.matrix);

	}

	for(int i = 0; i < input->size2; i++){
		gsl_matrix_view inputView = gsl_matrix_submatrix(input, input_3->size1, i , input_1->size1, 1);
		gsl_matrix_view desiredView = gsl_matrix_submatrix(desired, desired_3->size1, i, desired_1->size1, 1);

		gsl_matrix_view inputSourceView = gsl_matrix_submatrix(input_1, 0, i / (input_3->size2 / 3), input_1->size1, 1);
		gsl_matrix_view desiredSourceView = gsl_matrix_submatrix(desired_1, 0, i / (desired_3->size2 / 3), desired_1->size1, 1);

		gsl_matrix_memcpy(&inputView.matrix, &inputSourceView.matrix);
		gsl_matrix_memcpy(&desiredView.matrix, &desiredSourceView.matrix);
		
	}
	////print_matrix_to_file(input, "./lang/test.txt");


	esn_network *esn = new esn_network(50, desired->size1, input->size1, 0.20, 0.907, 1.0, 1.0, 0.0, false);
/*	
	printf("training \n");
	esn->train_offline(input, desired, 1, 0);
	esn->saveNetwork();
*/
	esn->loadNetwork();

	//esn->train_offline(NULL, desired);
	printf("runing \n");
	
	gsl_matrix_view inputView = gsl_matrix_submatrix(input, 0, 0*900, input->size1, input->size2);
	gsl_matrix_view desiredView = gsl_matrix_submatrix(desired, 0, 0*900, desired->size1, input->size2);

	output = esn->runNetwork(&inputView.matrix, &desiredView.matrix, (&inputView.matrix)->size2, 0);
	
	gsl_matrix_view outputMaxView = gsl_matrix_submatrix(output, 3, 0, 6, (&inputView.matrix)->size2);
	gsl_matrix_view desiredMaxView = gsl_matrix_submatrix(&desiredView.matrix, 3, 0, 6, (&desiredView.matrix)->size2);
	
	print_matrix_to_file(output, "./lang/out_13_randstart.txt");
	maxOnehot(&outputMaxView.matrix);

	print_matrix_to_file(&outputMaxView.matrix, "./lang/out_max_randstart.txt");
	print_matrix_to_file(&desiredMaxView.matrix, "./lang/des_max_randstart.txt");

	printf("Trenovacia uspesnost: %f \n", successfulness(&desiredMaxView.matrix, &outputMaxView.matrix));

	
	print_matrix_to_file(&desiredView.matrix, "./lang/des_13_randstart.txt");
	//esn->print_matrix(output);

	//print_matrix_to_file(esn->get_matrix_W(), "./lang/res_13.txt");
	//print_matrix_to_file(esn->get_matrix_Wout(), "./lang/wout_13.txt");
	
	gsl_matrix_free(output);
	gsl_matrix_free(desired);
	gsl_matrix_free(input);
	
	delete esn;
	printf("done \n");
}
void esnTrain_3(){
	gsl_matrix *output;

	FILE *f;
	fopen_s(&f, "./lang/lang_desired_3.txt", "r");
	gsl_matrix *desired = gsl_matrix_alloc(3, 900);
	gsl_matrix_fscanf(f, desired);
	fclose(f);


	fopen_s(&f, "./lang/lang_hidden_3.txt", "r");
	gsl_matrix *input = gsl_matrix_alloc(40, 900);
	gsl_matrix_fscanf(f, input);
	fclose(f);

	esn_network *esn = new esn_network(20, desired->size1, input->size1, 0.20, 0.97, 0.80, 1.0, 0.0, false);
	
	printf("training \n");
	esn->train_offline(input, desired, 1, 0);
	//esn->train_offline(NULL, desired);
	printf("runing \n");
	output = esn->runNetwork(input, desired, input->size2, 0);

	print_matrix_to_file(output, "./lang/out_3.txt");
	print_matrix_to_file(desired, "./lang/des_3.txt");
	//esn->print_matrix(output);

	print_matrix_to_file(esn->get_matrix_W(), "./lang/res_3.txt");
	print_matrix_to_file(esn->get_matrix_Wout(), "./lang/wout_3.txt");
	
	gsl_matrix_free(output);
	gsl_matrix_free(desired);
	gsl_matrix_free(input);
	
	delete esn;
	printf("done \n");
}
void esnTrain_1(){
	gsl_matrix *output;

	FILE *f;
	fopen_s(&f, "./lang/lang_desired_1.txt", "r");
	gsl_matrix *desired = gsl_matrix_alloc(6, 216);
	gsl_matrix_fscanf(f, desired);
	fclose(f);


	fopen_s(&f, "./lang/lang_hidden_1.txt", "r");
	gsl_matrix *input = gsl_matrix_alloc(25, 216);
	gsl_matrix_fscanf(f, input);
	fclose(f);

	esn_network *esn = new esn_network(100, desired->size1, input->size1, 0.20, 0.009755, 0.50, 0.5, 0.0, FALSE);
	
	printf("training \n");
	esn->train_offline(input, desired, 0);
	//esn->train_offline(NULL, desired);
	printf("runing \n");

	output = esn->runNetwork(input, desired, input->size2, 0);



	print_matrix_to_file(output, "./lang/out_1.txt");
	print_matrix_to_file(desired, "./lang/des_1.txt");
	//esn->print_matrix(output);

	print_matrix_to_file(esn->get_matrix_W(), "./lang/res_1.txt");
	print_matrix_to_file(esn->get_matrix_Wout(), "./lang/wout_1.txt");
	
	gsl_matrix_free(output);
	gsl_matrix_free(desired);
	gsl_matrix_free(input);
	
	delete esn;
	printf("done \n");
}
void criticDataTrain(){
	std::string filename= "./critic/";
	filename += DATA;
	filename += "/critic_input.txt";

	FILE *f;
	fopen_s(&f, filename.c_str(), "r");
	gsl_matrix *input = gsl_matrix_alloc(12, atoi(DATA));
	gsl_matrix_fscanf(f, input);
	fclose(f);

	filename= "./critic/";
	filename += DATA;
	filename += "/critic_desired.txt";

	fopen_s(&f, filename.c_str(), "r");
	gsl_matrix *desired = gsl_matrix_alloc(1, atoi(DATA));
	gsl_matrix_fscanf(f, desired);
	fclose(f);

	filename= "./critic/";
	filename += DATA;
	filename += "/error_critic.txt";

	FILE *fo;
	fopen_s(&fo, filename.c_str(), "w");

	shuffleCols(input, desired);
	gsl_matrix *train_in, *train_des, *test_in, *test_des;

	splitDataset(input, desired, &train_in, &train_des, &test_in, &test_des, 0.9);

	//for(double alpha = 1; 1.0 / pow(2,alpha) > 0.000001; alpha = alpha + 1){
	for(int nc = 5; nc < 71; nc = nc + 5){
		//fprintf(fo, "alpha: %f \n", 1.0 / pow(2, alpha));
		fprintf(fo, "nc: %d \n", nc);

		gsl_vector *neurons = gsl_vector_alloc(3);
		gsl_vector_set(neurons, 0, 12);
		gsl_vector_set(neurons, 1, nc);
		gsl_vector_set(neurons, 2, 1);

		mlp *nn = new mlp(neurons, new activ_function_tanh(), false);
		gsl_matrix *train_out;
		gsl_matrix *test_out;	


		//nn->loadNetwork("save_critic/");
		//nn->loadNetwork("./cacla/critic/"); //model

		for(int a = 0; a < 250 ; a++){
			shuffleCols(train_in, train_des);
			nn->trainNetwork(train_in, train_des, 0.01); //0.009  1.0 / pow(2, alpha)
			
			train_out = nn->runNetwork(train_in);
			test_out = nn->runNetwork(test_in);

			if(a == 249){
				printf("%f | ", nn->compute_error(train_des, train_out));
				printf("%f\n", nn->compute_error(test_des, test_out));
				
				fprintf(fo, "%f ", nn->compute_error(train_des, train_out));
				fprintf(fo, "%f\n", nn->compute_error(test_des, test_out));
			}
		}

		//nn->saveNetwork("save_critic/");
		//nn->saveNetwork("./cacla/critic/");

		filename= "./critic/";
		filename += DATA;
		filename += "/train_critic_out.txt";
		print_matrix_to_file(train_out, filename.c_str());

		filename= "./critic/";
		filename += DATA;
		filename += "/train_critic_des.txt";
		print_matrix_to_file(train_des, filename.c_str());

		filename= "./critic/";
		filename += DATA;
		filename += "/test_critic_out.txt";
		print_matrix_to_file(test_out, filename.c_str());

		filename= "./critic/";
		filename += DATA;
		filename += "/test_critic_des.txt";
		print_matrix_to_file(test_des, filename.c_str());
		//print_matrix_to_file(test_in, "./critic/test_critic_in.txt");

		//print_matrix_to_file(test_out, "test_out_max.txt");

		//printf("Testovacia uspesnotst: %f \n", successfulness(test_des, test_out));

		//printf("test chyba: %f\n", nn->compute_error(test_des, test_out));


		gsl_matrix_free(train_out);
		gsl_matrix_free(test_out);
	}
	fclose(fo);

	gsl_matrix_free(train_in);
	gsl_matrix_free(train_des);
	gsl_matrix_free(test_in);
	gsl_matrix_free(test_des);


	gsl_matrix_free(input);
	gsl_matrix_free(desired);
}
void actorDataTrain(){
	std::string filename= "./critic/";
	filename += DATA;
	filename += "/actor_input.txt";

	FILE *f;
	fopen_s(&f, filename.c_str(), "r");
	gsl_matrix *input = gsl_matrix_alloc(12, atoi(DATA));
	gsl_matrix_fscanf(f, input);
	fclose(f);

	filename= "./critic/";
	filename += DATA;
	filename += "/actor_desired.txt";

	fopen_s(&f, filename.c_str(), "r");
	gsl_matrix *desired = gsl_matrix_alloc(4, atoi(DATA));
	gsl_matrix_fscanf(f, desired);
	fclose(f);

	filename= "./critic/";
	filename += DATA;
	filename += "/error_actor.txt";

	FILE *fo;
	fopen_s(&fo, filename.c_str(), "w");

	//shuffleCols(input, desired);

	gsl_matrix *train_in, *train_des, *test_in, *test_des;

	splitDataset(input, desired, &train_in, &train_des, &test_in, &test_des, 0.6);

	//for(double alpha = 1; 1.0 / pow(2,alpha) > 0.000001; alpha = alpha + 1){
	for(int nc = 1; nc < 5; nc = nc + 1){
		//fprintf(fo, "alpha: %f \n", 1.0 / pow(2, alpha));
		fprintf(fo, "nc: %d \n", nc);

		gsl_vector *neurons = gsl_vector_alloc(3);
		gsl_vector_set(neurons, 0, 12);
		gsl_vector_set(neurons, 1, nc);
		gsl_vector_set(neurons, 2, 4);

		mlp *nn = new mlp(neurons, new activ_function_tanh(), false);
		gsl_matrix *train_out;
		gsl_matrix *test_out;	


		//nn->loadNetwork("save_critic/");
		//nn->loadNetwork("./cacla/actor/"); //model

		for(int a = 0; a < 200; a++){
			//shuffleCols(train_in, train_des);
			nn->trainNetwork(train_in, train_des, 0.01); // 0.001  1.0 / pow(2, alpha)
			//		nn->trainNetwork(test_in, test_des, 0.001);
			
			if(a == 199){
				train_out = nn->runNetwork(train_in);
				test_out = nn->runNetwork(test_in);
			
				printf("%f | ", nn->compute_error(train_des, train_out));
				printf("%f\n", nn->compute_error(test_des, test_out));

				fprintf(fo, "%f ", nn->compute_error(train_des, train_out));
				fprintf(fo, "%f\n", nn->compute_error(test_des, test_out));
			}	
		}

		//nn->saveNetwork("./cacla/actor/");

		filename= "./critic/";
		filename += DATA;
		filename += "/train_actor_out.txt";
		print_matrix_to_file(train_out, filename.c_str());

		filename= "./critic/";
		filename += DATA;
		filename += "/train_actor_des.txt";
		print_matrix_to_file(train_des, filename.c_str());

		filename= "./critic/";
		filename += DATA;
		filename += "/test_actor_out.txt";
		print_matrix_to_file(test_out, filename.c_str());

		filename= "./critic/";
		filename += DATA;
		filename += "/test_actor_des.txt";
		print_matrix_to_file(test_des, filename.c_str());
		//print_matrix_to_file(test_in, "./critic/test_critic_in.txt");

		//print_matrix_to_file(test_out, "test_out_max.txt");

		//printf("Testovacia uspesnotst: %f \n", successfulness(test_des, test_out));

		//printf("test chyba: %f\n", nn->compute_error(test_des, test_out));
		gsl_matrix_free(train_out);
		gsl_matrix_free(test_out);
	}

	fclose(fo);

	gsl_matrix_free(train_in);
	gsl_matrix_free(train_des);
	gsl_matrix_free(test_in);
	gsl_matrix_free(test_des);


	gsl_matrix_free(input);
	gsl_matrix_free(desired);
}
void nntrain_nn3(){

	FILE *f;
	fopen_s(&f, "./nn3/input.txt", "r");
	gsl_matrix *input = gsl_matrix_alloc(2, 1000);
	gsl_matrix_fscanf(f, input);
	fclose(f);

	fopen_s(&f, "./nn3/desired.txt", "r");
	gsl_matrix *desired = gsl_matrix_alloc(3, 1000);
	gsl_matrix_fscanf(f, desired);
	fclose(f);

	//shuffleCols(input, desired);

	gsl_matrix *train_in, *train_des, *test_in, *test_des;

	splitDataset(input, desired, &train_in, &train_des, &test_in, &test_des, 0.8);

	gsl_vector *neurons = gsl_vector_alloc(4);
	gsl_vector_set(neurons, 0, 2);
	gsl_vector_set(neurons, 1, 30);
	gsl_vector_set(neurons, 2, 20);
	gsl_vector_set(neurons, 3, 3);

	mlp *nn = new mlp(neurons, new activ_function_tanh, true);
	gsl_matrix *train_out;
	gsl_matrix *test_out;	


//	nn->loadNetwork("./nn3/save/");
	
	FILE *fo;
	fopen_s(&fo, "./nn3/error.txt", "w");
	for(int a = 0; a < 1500; a++){
		shuffleCols(train_in, train_des);
		nn->trainNetwork(train_in, train_des, 0.01);
		//nn->trainNetwork(test_in, test_des, 0.08);

		train_out = nn->runNetwork(train_in);		
		test_out = nn->runNetwork(test_in);
		
		maxOnehot(test_out);
		fprintf(fo, "%f ", nn->compute_error(train_des, train_out));
		fprintf(fo, "%f\n", nn->compute_error(test_des, test_out));	

		printf("%d>%f | ", a, nn->compute_error(train_des, train_out));
		printf("%f\n", nn->compute_error(test_des, test_out));

		gsl_matrix_free(test_out);
		gsl_matrix_free(train_out);
	}
	
	train_out = nn->runNetwork(train_in);
	test_out = nn->runNetwork(test_in);

	nn->saveNetwork("./nn3/save/");
	
	print_matrix_to_file(train_out, "./nn3/train_out.txt");
	print_matrix_to_file(train_des, "./nn3/train_des.txt");
	print_matrix_to_file(train_in, "./nn3/train_in.txt");

	print_matrix_to_file(test_out, "./nn3/test_out.txt");
	print_matrix_to_file(test_des, "./nn3/test_des.txt");
	print_matrix_to_file(test_in, "./nn3/test_in.txt");

	maxOnehot(test_out);
	maxOnehot(train_out);

	print_matrix_to_file(test_out, "./nn3/test_out_max.txt");

	printf("Testovacia uspesnost: %f \n", successfulness(test_des, test_out));
	printf("Trenovacia uspesnost: %f \n", successfulness(train_des, train_out));
	
	printf("test chyba: %f\n", nn->compute_error(test_des, test_out));
	fclose(fo);



	gsl_matrix_free(train_in);
	gsl_matrix_free(train_des);
	gsl_matrix_free(test_in);
	gsl_matrix_free(test_des);
	gsl_matrix_free(train_out);
	gsl_matrix_free(test_out);

	gsl_matrix_free(input);
	gsl_matrix_free(desired);
}

void nntrain_exper(){

	FILE *f;
	fopen_s(&f, "./experimental/input.txt", "r");
	gsl_matrix *input = gsl_matrix_alloc(9+9+6+1, 216);
	gsl_matrix_fscanf(f, input);
	fclose(f);

	fopen_s(&f, "./experimental/desired.txt", "r");
	gsl_matrix *desired = gsl_matrix_alloc(3, 216);
	gsl_matrix_fscanf(f, desired);
	fclose(f);

	//shuffleCols(input, desired);
shuffleCols(input, desired);
	gsl_matrix *train_in, *train_des, *test_in, *test_des;

	splitDataset(input, desired, &train_in, &train_des, &test_in, &test_des, 0.8);

	gsl_vector *neurons = gsl_vector_alloc(4);
	gsl_vector_set(neurons, 0, 9+9+6+1);
	gsl_vector_set(neurons, 1, 30);
	gsl_vector_set(neurons, 2, 20);
	gsl_vector_set(neurons, 3, 3);

	mlp *nn = new mlp(neurons, new activ_function_tanh, true);
	gsl_matrix *train_out;
	gsl_matrix *test_out;	


//	nn->loadNetwork("./experimental/save/");
	
	FILE *fo;
	fopen_s(&fo, "./experimental/error.txt", "w");
	for(int a = 0; a < 400; a++){
		shuffleCols(train_in, train_des);
		nn->trainNetwork(train_in, train_des, 0.01);
		//nn->trainNetwork(test_in, test_des, 0.08);

		train_out = nn->runNetwork(train_in);		
		test_out = nn->runNetwork(test_in);
		
		maxOnehot(test_out);
		fprintf(fo, "%f ", nn->compute_error(train_des, train_out));
		fprintf(fo, "%f\n", nn->compute_error(test_des, test_out));	

		printf("%d>%f | ", a, nn->compute_error(train_des, train_out));
		printf("%f\n", nn->compute_error(test_des, test_out));

		gsl_matrix_free(test_out);
		gsl_matrix_free(train_out);
	}
	
	train_out = nn->runNetwork(train_in);
	test_out = nn->runNetwork(test_in);

	nn->saveNetwork("./experimental/save/");
	
	print_matrix_to_file(train_out, "./experimental/train_out.txt");
	print_matrix_to_file(train_des, "./experimental/train_des.txt");
	print_matrix_to_file(train_in, "./experimental/train_in.txt");

	print_matrix_to_file(test_out, "./experimental/test_out.txt");
	print_matrix_to_file(test_des, "./experimental/test_des.txt");
	print_matrix_to_file(test_in, "./experimental/test_in.txt");

	maxOnehot(test_out);
	maxOnehot(train_out);

	print_matrix_to_file(test_out, "./experimental/test_out_max.txt");

	printf("Testovacia uspesnost: %f \n", successfulness(test_des, test_out));
	printf("Trenovacia uspesnost: %f \n", successfulness(train_des, train_out));
	
	printf("test chyba: %f\n", nn->compute_error(test_des, test_out));
	fclose(fo);



	gsl_matrix_free(train_in);
	gsl_matrix_free(train_des);
	gsl_matrix_free(test_in);
	gsl_matrix_free(test_des);
	gsl_matrix_free(train_out);
	gsl_matrix_free(test_out);

	gsl_matrix_free(input);
	gsl_matrix_free(desired);
}

void nntrain_1(){

	FILE *f;
	fopen_s(&f, "./lang/hidden_1.txt", "r");
	gsl_matrix *input = gsl_matrix_alloc(20, 216);
	gsl_matrix_fscanf(f, input);
	fclose(f);

	fopen_s(&f, "./lang/desired_1.txt", "r");
	gsl_matrix *desired = gsl_matrix_alloc(6, 216);
	gsl_matrix_fscanf(f, desired);
	fclose(f);

	//shuffleCols(input, desired);

	gsl_matrix *train_in, *train_des, *test_in, *test_des;

	splitDataset(input, desired, &train_in, &train_des, &test_in, &test_des, 0.9);

	gsl_vector *neurons = gsl_vector_alloc(3);
	gsl_vector_set(neurons, 0, 20);
	gsl_vector_set(neurons, 1, 20);
	gsl_vector_set(neurons, 2, 6);

	mlp *nn = new mlp(neurons, new activ_function_logistic(), false);
	gsl_matrix *train_out;
	gsl_matrix *test_out;	


//	nn->loadNetwork("./lang/save/");
	
	FILE *fo;
	fopen_s(&fo, "./lang/error.txt", "w");
	for(int a = 0; a < 5000; a++){
		shuffleCols(train_in, train_des);
		nn->trainNetwork(train_in, train_des, 0.08);
		//nn->trainNetwork(test_in, test_des, 0.08);

		train_out = nn->runNetwork(train_in);		
		test_out = nn->runNetwork(test_in);
		
		maxOnehot(test_out);
		fprintf(fo, "%f ", nn->compute_error(train_des, train_out));
		fprintf(fo, "%f\n", nn->compute_error(test_des, test_out));	

		printf("%d>%f | ", a, nn->compute_error(train_des, train_out));
		printf("%f\n", nn->compute_error(test_des, test_out));

		gsl_matrix_free(test_out);
		gsl_matrix_free(train_out);
	}
	
	train_out = nn->runNetwork(train_in);
	test_out = nn->runNetwork(test_in);

	nn->saveNetwork("./lang/save/");
	
	print_matrix_to_file(train_out, "./lang/train_out.txt");
	print_matrix_to_file(train_des, "./lang/train_des.txt");
	print_matrix_to_file(train_in, "./lang/train_in.txt");

	print_matrix_to_file(test_out, "./lang/test_out.txt");
	print_matrix_to_file(test_des, "./lang/test_des.txt");
	print_matrix_to_file(test_in, "./lang/test_in.txt");

	maxOnehot(test_out);
	maxOnehot(train_out);

	print_matrix_to_file(test_out, "./lang/test_out_max.txt");

	printf("Testovacia uspesnost: %f \n", successfulness(test_des, test_out));
	printf("Trenovacia uspesnost: %f \n", successfulness(train_des, train_out));
	
	printf("test chyba: %f\n", nn->compute_error(test_des, test_out));
	fclose(fo);



	gsl_matrix_free(train_in);
	gsl_matrix_free(train_des);
	gsl_matrix_free(test_in);
	gsl_matrix_free(test_des);
	gsl_matrix_free(train_out);
	gsl_matrix_free(test_out);

	gsl_matrix_free(input);
	gsl_matrix_free(desired);
}

void nntrain(){
	int mult=20;

	FILE *f;
	fopen_s(&f, "input.txt", "r");
	gsl_matrix *input = gsl_matrix_alloc(1200 + 9 * mult + 6 * mult + 1, 216);//1651
	gsl_matrix_fscanf(f, input);
	fclose(f);

	fopen_s(&f, "desired.txt", "r");
	gsl_matrix *desired = gsl_matrix_alloc(3, 216);
	gsl_matrix_fscanf(f, desired);
	fclose(f);

	//shuffleCols(input, desired);
	//shuffleCols(input, desired);

	gsl_matrix *train_in, *train_des, *test_in, *test_des;

	splitDataset(input, desired, &train_in, &train_des, &test_in, &test_des, 0.7);

	gsl_vector *neurons = gsl_vector_alloc(3);
	gsl_vector_set(neurons, 0, 1200 + 9 * mult + 6 * mult + 1);
	gsl_vector_set(neurons, 1, 50);
//gsl_vector_set(neurons, 2, 20);
	gsl_vector_set(neurons, 2, 3);

	mlp *nn = new mlp(neurons, new activ_function_logistic(), false);
	gsl_matrix *train_out;
	gsl_matrix *test_out;	

	nn->loadNetwork("save/");
	
	FILE *fo;
	fopen_s(&fo, "./m1/error.txt", "w");
	for(int a = 0; a < 0; a++){
		//shuffleCols(train_in, train_des);
		nn->trainNetwork(train_in, train_des, 0.1);	
		//nn->trainNetwork(test_in, test_des, 0.08);

		if((a % 10) == 0 || TRUE){
			train_out = nn->runNetwork(train_in);
			test_out = nn->runNetwork(test_in);

			//maxOnehot(test_out);

			double train_err = nn->compute_error(train_des, train_out);
			double test_err = nn->compute_error(test_des, test_out);
			fprintf(fo, "%f ", train_err);
			fprintf(fo, "%f\n", test_err);	

			printf("%d>%f | ", a, train_err);
			printf("%f\n", test_err);

			gsl_matrix_free(test_out);
			gsl_matrix_free(train_out);
		}
	}
	
	train_out = nn->runNetwork(train_in);
	test_out = nn->runNetwork(test_in);

	nn->saveNetwork("save/");
	
	print_matrix_to_file(train_out, "train_out.txt");
	print_matrix_to_file(train_des, "train_des.txt");
	print_matrix_to_file(train_in, "train_in.txt");

	print_matrix_to_file(test_out, "test_out.txt");
	print_matrix_to_file(test_des, "test_des.txt");
	print_matrix_to_file(test_in, "test_in.txt");

	maxOnehot(test_out);
	maxOnehot(train_out);

	print_matrix_to_file(test_out, "test_out_max.txt");

	printf("Testovacia uspesnost: %f \n", successfulness(test_des, test_out));
	printf("Trenovacia uspesnost: %f \n", successfulness(train_des, train_out));
	
	printf("test chyba: %f\n", nn->compute_error(test_des, test_out));
	fclose(fo);


	int repeat = 1;
	gsl_matrix *lang_out = nn->runNetwork(input);
	gsl_matrix *lang_hidden = gsl_matrix_calloc(nn->activationHidden->size1, repeat * nn->activationHidden->size2);
	gsl_vector *col = gsl_vector_alloc(nn->activationHidden->size1);

	for(int i = 0; i < nn->activationHidden->size2; i++){
		gsl_matrix_get_col(col, nn->activationHidden, i);
		for(int j = 0; j < repeat; j++){
			gsl_matrix_set_col(lang_hidden, repeat * i + j, col);
		}
	}
	gsl_vector_free(col);

	print_matrix_to_file(lang_hidden, "./lang/lang_hidden_1.txt");
	gsl_matrix_free(lang_out);
	gsl_matrix_free(lang_hidden);

	gsl_matrix *lang_desired = gsl_matrix_calloc(6, repeat * input->size2);
	for(int i = 0; i < input->size2; i++){
		for(int j = 0; j < repeat; j++){
			gsl_matrix_set(lang_desired, 0, repeat * i + j, gsl_matrix_get(input, 1200 + 9*mult + 0*mult, i));
			gsl_matrix_set(lang_desired, 1, repeat * i + j, gsl_matrix_get(input, 1200 + 9*mult + 1*mult, i));
			gsl_matrix_set(lang_desired, 2, repeat * i + j, gsl_matrix_get(input, 1200 + 9*mult + 2*mult, i));
			gsl_matrix_set(lang_desired, 3, repeat * i + j, gsl_matrix_get(input, 1200 + 9*mult + 3*mult, i));
			gsl_matrix_set(lang_desired, 4, repeat * i + j, gsl_matrix_get(input, 1200 + 9*mult + 4*mult, i));
			gsl_matrix_set(lang_desired, 5, repeat * i + j, gsl_matrix_get(input, 1200 + 9*mult + 5*mult, i));
		}
	}

	print_matrix_to_file(lang_desired, "./lang/lang_desired_1.txt");
	gsl_matrix_free(lang_desired);

	gsl_matrix_free(train_in);
	gsl_matrix_free(train_des);
	gsl_matrix_free(test_in);
	gsl_matrix_free(test_des);
	gsl_matrix_free(train_out);
	gsl_matrix_free(test_out);

	gsl_matrix_free(input);
	gsl_matrix_free(desired);
}

void esn_lingvm(){

	FILE *f;
	fopen_s(&f, "input.txt", "r");
	gsl_matrix *input = gsl_matrix_alloc(1390, 216);
	gsl_matrix_fscanf(f, input);
	fclose(f);

	fopen_s(&f, "desired.txt", "r");
	gsl_matrix *desired = gsl_matrix_alloc(3, 216);
	gsl_matrix_fscanf(f, desired);
	fclose(f);

	//shuffleCols(input, desired);

	gsl_matrix *train_in, *train_des, *test_in, *test_des;

	splitDataset(input, desired, &train_in, &train_des, &test_in, &test_des, 0.7);



	esn_network *esn = new esn_network(50, desired->size1, input->size1, 0.20, 0.009755, 0.50, 0.5, 0.0, FALSE);
	
	printf("training \n");
	esn->train_offline(train_in, train_des, 0);
	//esn->train_offline(NULL, desired);
	printf("runing \n");


	gsl_matrix *train_out;
	gsl_matrix *test_out;

	train_out = esn->runNetwork(train_in, train_des, train_in->size2, 0);
	test_out = esn->runNetwork(test_in, test_des, test_in->size2, 0);
		
	print_matrix_to_file(train_out, "./esn_lingv/train_out.txt");
	print_matrix_to_file(train_des, "./esn_lingv/train_des.txt");
	print_matrix_to_file(train_in, "./esn_lingv/train_in.txt");

	print_matrix_to_file(test_out, "./esn_lingv/test_out.txt");
	print_matrix_to_file(test_des, "./esn_lingv/test_des.txt");
	print_matrix_to_file(test_in, "./esn_lingv/test_in.txt");


	maxOnehot(test_out);
	maxOnehot(train_out);

	print_matrix_to_file(test_out, "test_out_max.txt");

	printf("Testovacia uspesnost: %f \n", successfulness(test_des, test_out));
	printf("Trenovacia uspesnost: %f \n", successfulness(train_des, train_out));

	gsl_matrix_free(train_in);
	gsl_matrix_free(train_des);
	gsl_matrix_free(test_in);
	gsl_matrix_free(test_des);
	gsl_matrix_free(train_out);
	gsl_matrix_free(test_out);

	gsl_matrix_free(input);
	gsl_matrix_free(desired);
}


void setObjects(){
	//char command[10];
	scanf("%s", command);

	simulator *sim = new simulator();

	//sim->moveDefaultObjectsAway();
	sim->lookAtTable();
	sim->world_del_all();
	sim->createTable();
	test_in = sim->setObjects(command, target, action);

	delete sim;
}

void generateDF(){
	simulator *sim = new simulator();

	sim->createDatasetFiles();
	//sim->createcombinationFiles();
	delete sim;
}

int getCommandCode(char *ctarget){
	
	if(strcmp(ctarget ,"r") == 0){
		return 0 + 3;
	}
	if(strcmp(ctarget, "g") == 0){
		return 1 + 3;
	}
	if(strcmp(ctarget, "b") == 0){
		return 2 + 3;
	}
	if(strcmp(ctarget, "cyl") == 0){
		return 1;
	}
	if(strcmp(ctarget, "sph") == 0){
		return 2;
	}

	if(strcmp(ctarget, "box") == 0){
		return 0;
	}
	return -1;
}

void nnreset(){

	gsl_vector *neurons = gsl_vector_alloc(3);
	gsl_vector_set(neurons, 0, 1200 + 9 * 20 + 6 * 20 + 1);
	gsl_vector_set(neurons, 1, 50);
//gsl_vector_set(neurons, 2, 20);
	gsl_vector_set(neurons, 2, 3);


	mlp *nn = new mlp(neurons, new activ_function_logistic(), false);
	nn->saveNetwork("save/");
}
void nntest(){
	
	char ctarget[10];
	scanf("%s", ctarget);
	target = getCommandCode(ctarget);

	gsl_vector *neurons = gsl_vector_alloc(3);
	gsl_vector_set(neurons, 0, 1216);
	gsl_vector_set(neurons, 1, 10);
	gsl_vector_set(neurons, 2, 3);

	mlp *nn = new mlp(neurons, new activ_function_logistic(), false);
	
	simulator *sim = new simulator();

	//sim->moveDefaultObjectsAway();
	sim->lookAtTable();
	sim->world_del_all();

	gsl_matrix *test_out;	
	nn->loadNetwork("save/");
	
	test_in = sim->setObjects(command, target, action);
	test_out = nn->runNetwork(test_in);
	maxOnehot(test_out);
	print_matrix(test_out);

	gsl_matrix_free(test_out);
	delete sim;
//	delete nn;
}

int main (void)
{
	srand(time(NULL));

	char c;
	while((c = getchar()) != 'q'){
		
		// nastavenie objektov na scene
		if(c == 'o'){
			setObjects();
		}

		// vytvorenie vstupnych suborov pre modul 1
		if(c == 'g'){
			generateDF();
		}

		// trenovanie modulu 1
		if(c == 't'){
			nntrain();
		}

		// testovanie modulu 1
		if(c == 'c'){
			nntest();
		}

		// nahodne nastavenie vah siete prveho modulu
		if(c == 'r'){
			nnreset();
		}

		// trenovanie vykonavania akcii
		if(c == 'l'){
			simulator *sim = new simulator(); 
			cacla *cacla1 = new cacla(new mlp(createNeuronVector(12, 40, 4), new activ_function_tanh(), false), new mlp(createNeuronVector(12, 20, 1), new activ_function_tanh(), false), sim);
	
			cacla1->learnActions();

			delete cacla1;
			delete sim;
		}

		// vykonavianie natrenvanyh akcii
		if(c == 'm'){
			simulator *sim = new simulator(); 
			cacla *cacla1 = new cacla(new mlp(createNeuronVector(12, 40, 4), new activ_function_tanh(), false), new mlp(createNeuronVector(12, 20, 1), new activ_function_tanh(), false), sim);

			cacla1->performActions();

			delete cacla1;
			delete sim;
		}

		// trenovanie kritika na zistenie vhodnych parametrov 
		if(c == 'p'){
			criticDataTrain();
		}

		// trenovanie aktera na zistenie vhodnych parametrov
		if(c == 'a'){
			actorDataTrain();
		}

		// vytvorenie suborov na trenovanie modulu 2
		if(c == 'h'){
			simulator *sim = new simulator(); 
			cacla *cacla1 = new cacla(new mlp(createNeuronVector(12, 40, 4), new activ_function_tanh(), false), new mlp(createNeuronVector(12, 20, 1), new activ_function_tanh(), false), sim);

			cacla1->generateLanguageFiles();

			delete cacla1;
			delete sim;
		}

		//-------------------------
		
		// uloha modulu 3 pomocou MLP a nie ESN
		if(c == 'w'){
			nntrain_1(); 
		}
		
		//esn poduloha, len skryta vrstva z modulu 2
		if(c == '1'){
			esnTrain_1(); 
		}	
		
		//esn poduloha, len skryta vrstva z modulu 2
		if(c == '3'){
			esnTrain_3(); 
		}

		//vysledna skombinovana uloha 1 2
		if(c == '5'){
			esnTrain_13(); 
		}
		
		// uloha modulu 1 pomocou esn
		if(c == '9'){
			esn_lingvm(); 
		}
		if(c == '7'){
			nntrain_exper();
		}
	}
	
	return 0;
}
