/*****

*Property of the University of British Columbia (UBC),

*Copyright 2001, by UBC.

*

*By receiving this code, you are agreeing to the following terms:

*1. You will use this code for academic purposes only.

*2. For academic use only, you may distribute the binary or executable code

*   to persons at UBC or the Univ. of Western Australia who have previously 

*   read and agreed to these terms, but you must distribute the SOURCE code

*   with it. 

*3. Each file of source code so distributed must have this header attached.

*4. If the code is revised, the programmer's name and revision date must be added

*   to the Revision List below, as well as the revisions identified in the code.

*5. You will not make this code more widely available via any method such as 

*   publishing in print, email mail-list, usenet posting, website etc.

*6. UBC reserves all rights to this work and all derivative works.

*

*For other proposed purposes please contact:

*The University-Industry Liaison Office 

*IRC Room 331 - 2194 Health Sciences Mall 

*University of British Columbia 

*Vancouver, BC, Canada V6T 1Z3 

*Tel: (604) 822-8580 

*Fax: (604) 822-8589 

*

*or contact: 

*Peter D. Lawrence, Professor at peterl@ece.ubc.ca or 

*Greg Z. Grudic, Assistant Professor, at grudic@cs.colorado.edu

*

*Revision List: 

*Greg Grudic, August 28, 1998.

*Robin Atkins, August 31, 2000.

*Peter Lawrence (pdl), Dec. 27, 2001.

*****/







/*

%

% File:		processdata.c

% Program: 	Builds a Poly_Cascade approximation using the SPORE algorithm.

%

% Author:	Greg Grudic

%

% Description:

% Loads data from DataTrain, reads expected inputs and outputs from appr.ini.

% Builds k poly_cascades for each output, saving to pcX.s where X is the 

% index 0..9 for 10 cascades for example. Tests the approximations by loading

% DataTest and comparing the actual outputs with the approximated output

% and reporting the average error over k approximations for however many test 

%samples.

%

%

% Defines:

% ERASE_APPROX_RIGHT_AWAY

% This define is a memory management issue: it tells Build_Cascade whether

% it should delete the aproximations for each output variable 

% from memory right away as soon as it is done with them, or if it should

% wait until the end and delete them all at once. Cuurently the code works

% with it defined.

%

% BUILD_APPR

% This tells the program whether or not to build the approximations.

%

% TEST_APPROX (This name changed by pdl)

% This tells the program whether or not to test the approximations.

%

% Functions:

% Build_Approximation: Reads data from DataTrain into orig_lrn_data.

% Splits up this data into training and validation sets. Builds and saves one 

% at a time the ten approximations, for each output. All 

% output is displayed on screen and written to Results.txt.

%

% Test_Approximation: Reads data from DataTest into orig_lrn_data (re-use of name).

% Loads the ten approximations one at a time, each with true outputs.

% Passes the inputs from DataTest into Evaluate_Poly_Cascade and compares the

% guess of the outputs to the outputs from DataTest. The error is added to

% Robin_Error and averaged at the end. All output is displayed on screen and 

% written to Results.txt.

% 

% Changes by Robin:

% Added the loop to go through all k approximations instead of just one in

% both Build_Approximation and Test_Approximation. This also involved other

% changes to the code such as calling Split_Up_Data, how the time is calculated, 

% how the errors are averaged, which pcX.s file to load, and when to free memory 

% allocated to the poly_cascade.

%

% Changed the way the defines are placed so we don't waste time loading

% training data if we just want to evaluate the approximations.

%

% Completely changed Test_Approximation to simply calculate Robin_Error

% instead of all of Greg's error counters.

%

%

% pdl changes:

% 

% Eliminated reading of validation data in the two Initialize_Data... functions.

%

% Allowed the use of k = MAX_APPROX = 1 by arbitrarily setting the number of 

% samples in the the validation set to be 10% of the number in DataTrain 

% since num_val_ex=num_train_ex/MAX_APPROX for k>1. See Split_Up_Data function.

% Added the capability to write out the DataTrain and DataTest datasets for k=1.

% This is primarily for testing purposes.

%

% Added Get_Lrn_Ex_Input2 and related files to solve a bug in DataTest Phase

%

%  

*/




#include "b_pc.h"
#include <sys/types.h>
#include <time.h>


FILE *fp_RES_OUTPUT;

FILE *fp_TRAIN_OUTPUT;  /*pdl*/

FILE *fp_VAL_OUTPUT;    /*pdl*/


/* .........Main Program..........*/


int main(int argc, char **argv)
{
  /* function prototypes */

  void Build_Approximation(unsigned short xsubi_i[3]);
  void Test_Approximation(void);

	
  /* variables */

	unsigned short xsubi[3];
	int i_tmp, run;


	
  /* handle command-line arguments */

	if ( argc > 1 )
    {
			/* assign users random number seeds */

      sscanf(argv[1],"%d",&(i_tmp));
      xsubi[0] = i_tmp;
      sscanf(argv[2],"%d",&(i_tmp));
      xsubi[1] = i_tmp;
      sscanf(argv[3],"%d",&(i_tmp));
      xsubi[2] = i_tmp;
    }
  else
    {
			/* assign default random number seeds */

			xsubi[0] = 1;

			xsubi[1] = 1;

			xsubi[2] = 1;

    }
  


  /* open output file Results.txt - all info displayed on screen is also 

	written to this file */

	if ((fp_RES_OUTPUT = fopen("Results.txt","w")) == NULL)
    {
      printf("Cannot open file Results.txt\n");
      exit(-1);
    }

 
  



	if ((SPLIT_OUTPUT == TRUE) && (MAX_APPROX == 1))

	{

		/*pdl: open output file DataTrainSplit to record Training Data used */

		if ((fp_TRAIN_OUTPUT = fopen("DataTrainSplit","w")) == NULL)

		{

		  printf("Cannot open file DataTrainSplit\n");

		  exit(-1);

		}



		/*pdl: open output file DataValSplit to record Validation Data used */

		if ((fp_VAL_OUTPUT = fopen("DataValSplit","w")) == NULL)

		{

		  printf("Cannot open file DataValSplit\n");

		  exit(-1);

		}

	}




  /* display random seed info */

	fprintf(fp_RES_OUTPUT,"Random Seed: %d %d %d\n",xsubi[0],xsubi[1],xsubi[2]);
  printf("Random Seed: %d %d %d\n",xsubi[0],xsubi[1],xsubi[2]);



  /* Repeat the Training/Testing process to estimate confidence intervals.*/
  

  for ( run = 0; run < 10; run++) 

  {


		/* build the approximations? */

	#ifdef BUILD_APPR

		Build_Approximation(xsubi);
	#endif  



		/* test the approximations? */

	#ifdef TEST_APPROX

		Test_Approximation();

	#endif
  }

	/* close the output file */

	fclose(fp_RES_OUTPUT);





	if ((SPLIT_OUTPUT == TRUE) && (MAX_APPROX == 1))

	{

		/* close the output file */

		fclose(fp_TRAIN_OUTPUT);



		 /* close the output file */

		fclose(fp_VAL_OUTPUT);

	}


  
	return(1);
}



  /*Functions Called*/ 

void Build_Approximation(unsigned short xsubi_i[3])

{



	/* variables */

	FILE *fp;



	int i,j;		/*pdl*/

	double f_tmp;	/*pdl*/





	char pc_filename[20];

	time_t start_time, stop_time, delta_time;

	My_Real mse_lrn, mse_val;

	

	Build_Cas_Poly *b_pc;

	Cascade_Poly *pc;



	int num_lrn_ex, num_val_ex;

	int curr_cross_val, dim_in, dim_out, appr_cnt;

	

	/* function prototypes */

	void Save_Poly_Cascade(Cascade_Poly *pc,

		FILE *fp);

	

	void Delete_Poly_Cascade(Cascade_Poly *pc);

	

	void Initialize_Data(int *num_lrn_ex, int *num_val_ex, 

		int *dim_i, int *dim_o);

	

	void Set_Data_Dim_Output(int curr_d_o);



	void Set_Current_Approx(int curr_ap);

	

	void Delete_Data(void);

	

	void Get_Lrn_Ex_Input(int ex_num, 

		int var, 

		double *in);

	

	void Get_Lrn_Ex_Output(int ex_num, 

		double *out);



	void Get_Val_Ex_Input(int ex_num, 

		int var, 

		double *in);

	

	void Get_Val_Ex_Output(int ex_num, 

		double *out);

	

	void Build_Poly_Cascade(Build_Cas_Poly *b_pc,

		void (*Get_Lrn_Ex_Input)(int ex_num, 

		int var, double *in),

		void (*Get_Lrn_Ex_Output)(int ex_num, 

		double *out),

		void (*Get_Val_Ex_Input)(int ex_num, 

		int var, double *in),

		void (*Get_Val_Ex_Output)(int ex_num, 

		double *out),

		My_Real *mse_lrn, My_Real *mse_val

		);

	

	void Split_Up_Data(int num_orig_ex, int *num_lrn_ex, 

		int *num_val_ex);

	

	

	/* Start the building program */

	start_time = time(0);

	

	/* load the data from DataTrain */

	printf("Loading Data...\n");

	Initialize_Data(&num_lrn_ex, &num_val_ex, &dim_in, &dim_out);

	fprintf(fp_RES_OUTPUT,"Total Num of Examples = %d\n",num_lrn_ex);

	printf("Total Num of Examples = %d\n",num_lrn_ex);



	/* split up the data in DataTrain into MAX_APPROX sets of learning and validation

	data */

	printf("Splitting up data...\n");

	Split_Up_Data(num_lrn_ex, &num_lrn_ex, &num_val_ex);



	fprintf(fp_RES_OUTPUT,"Input Dim = %d\n",dim_in);

	fprintf(fp_RES_OUTPUT,"Output Dim = %d\n",dim_out);

	fprintf(fp_RES_OUTPUT,"Number of Approximations = %d\n",MAX_APPROX);

	fprintf(fp_RES_OUTPUT,"Num of Lrn Examples in Each Approx = %d\n",num_lrn_ex);

	fprintf(fp_RES_OUTPUT,"Num of Val Examples in Each Approx = %d\n",num_val_ex);

	

	fprintf(fp_RES_OUTPUT,"\n\nApproximation Type: POLY_DIM = %d, POLY_TERMS = %d\n\n",

		POLY_DIM, POLY_TERMS);

	

	printf("Input Dim = %d\n",dim_in);

	printf("Output Dim = %d\n",dim_out);

	printf("Number of Approximations = %d\n",MAX_APPROX);

	printf("Num of Lrn Examples in Each Approx = %d\n",num_lrn_ex);

	printf("Num of Val Examples in Each Approx = %d\n",num_val_ex);

	

	printf("\n\nApproximation Type: POLY_DIM = %d, POLY_TERMS = %d\n\n",

		POLY_DIM, POLY_TERMS);



	

	/*pdl:  If no cross-validation, write out the Training Data into DataTrainSplit. This

	is to examine the samples chosen, for program testing purposes only*/



	if ((SPLIT_OUTPUT == TRUE) && (MAX_APPROX == 1))

	{

		Set_Current_Approx(0);



		for (i = 0; i<num_lrn_ex; i++)

		{

			for (j = 0; j < dim_in; j++)

			{

				Get_Lrn_Ex_Input(i,j,&f_tmp);



				fprintf(fp_TRAIN_OUTPUT,"%f ",f_tmp);

			}



			for (j=0; j< dim_out; j++)

			{

				Set_Data_Dim_Output(j);



				Get_Lrn_Ex_Output(i,&f_tmp);



				fprintf(fp_TRAIN_OUTPUT,"%f ",f_tmp);

			}



			fprintf(fp_TRAIN_OUTPUT,"\n");





		} 





		/*pdl: Write out the Validation Data into DataValSplit*/





		for (i = 0; i<num_val_ex; i++)

		{

			for (j = 0; j < dim_in; j++)

			{

				Get_Val_Ex_Input(i,j,&f_tmp);



				fprintf(fp_VAL_OUTPUT,"%f ",f_tmp);

			}



			for (j=0; j< dim_out; j++)

			{

				Set_Data_Dim_Output(j);



				Get_Val_Ex_Output(i,&f_tmp);



				fprintf(fp_VAL_OUTPUT,"%f ",f_tmp);

			}



			fprintf(fp_VAL_OUTPUT,"\n");

		} 

	}

	



	stop_time = time(0);

	delta_time = stop_time - start_time;

	fprintf(fp_RES_OUTPUT,"\n\nData Initialization time = %ld sec\n",delta_time);

	printf("\n\nData Initialization time = %ld sec\n",delta_time);

	fflush(stdout);

	

	start_time = time(0);



	/* cycle through the MAX_APPROX approximation cross-validation routine */

	for (curr_cross_val = 0; curr_cross_val < MAX_APPROX; curr_cross_val++) {

	

		/* set a local variable in data_vt */

		Set_Current_Approx(curr_cross_val);



		/* initialize pc */

		pc = (Cascade_Poly *)

			malloc((unsigned)dim_out * sizeof(Cascade_Poly));

		if (!(pc)) {

			My_Error("Cannot allocate Cascade_Poly structure!!\n");

		}

	
		/* clear the pcX.s file (X is curr_cross_val) */
		sprintf(pc_filename,"pc%d.s",curr_cross_val);

		if ((fp = fopen(pc_filename,"w")) == NULL) {
			fprintf(fp_RES_OUTPUT,"Couldn't open \"%s\"\n",pc_filename);
			printf("Couldn't open \"%s\"\n",pc_filename);
		}
		fclose(fp);
	
		/* cycle through the ouput variables x, y, theta */
		for ( appr_cnt = 0; appr_cnt < dim_out; appr_cnt++ )
		{
			fprintf(fp_RES_OUTPUT,"\n#####################\n    For Cross-Validation Set %d\n    Building approx %d\n",curr_cross_val, appr_cnt);
			printf("\n#####################\n    For Cross-Validation Set %d\n    Building approx %d\n",curr_cross_val, appr_cnt);

			

			/* set local variable in data_vt */

			Set_Data_Dim_Output(appr_cnt);
			
			pc[appr_cnt].dim = dim_in;
			
			/* initialize b_pc */
			b_pc = (Build_Cas_Poly *)
				malloc((unsigned)sizeof(Build_Cas_Poly));
			if (!(b_pc)) {
				My_Error("Cannot allocate Build_Cas_Poly struct!!\n");
			}
			
			/* setup b_pc structure */

			b_pc->pc = &(pc[appr_cnt]);
			b_pc->num_lrn_ex = num_lrn_ex;
			b_pc->num_val_ex = num_val_ex;
			b_pc->xsubi[0] = xsubi_i[0];
			b_pc->xsubi[1] = xsubi_i[1];
			b_pc->xsubi[2] = xsubi_i[2];


			/* actually build the poly cascade */

			Build_Poly_Cascade(b_pc, Get_Lrn_Ex_Input, 
				Get_Lrn_Ex_Output,
				Get_Val_Ex_Input, Get_Val_Ex_Output,
				&mse_lrn, &mse_val);


			/* print out final mean squared error */

			fprintf(fp_RES_OUTPUT,"\n\n########################################\n");
			fprintf(fp_RES_OUTPUT,"  After Leaning appr_cnt %d: mse_lrn = %g, mse_val = %g\n",
				appr_cnt, mse_lrn, mse_val); 
			fprintf(fp_RES_OUTPUT,"########################################\n\n");
			
			printf("\n\n########################################\n");
			printf("  After Leaning appr_cnt %d: mse_lrn = %g, mse_val = %g\n",
				appr_cnt, mse_lrn, mse_val); 
			printf("########################################\n\n");
		
		
			/* initialise random seeds based on last random number */

			xsubi_i[0] = b_pc->xsubi[0];
			xsubi_i[1] = b_pc->xsubi[1];
			xsubi_i[2] = b_pc->xsubi[2];
		
			/* free memory allocated to b_pc */

			free(b_pc);
		
			/* open pcX.s to save the approximation */

			sprintf(pc_filename,"pc%d.s",curr_cross_val);

			if ((fp = fopen(pc_filename,"ab")) == NULL)
			{
				fprintf(fp_RES_OUTPUT,"Couldn't open \"%s\"\n",pc_filename);
				printf("Couldn't open \"%s\"\n",pc_filename);
			}
		
			/* save it */

			Save_Poly_Cascade(&(pc[appr_cnt]),fp);
		
#ifdef ERASE_APPROX_RIGHT_AWAY
/* this ifdef is a memory management issue */

			Delete_Poly_Cascade(&(pc[appr_cnt]));
#endif


			/* close the file */
			fclose(fp);
		}


#ifdef ERASE_APPROX_RIGHT_AWAY
/* this ifdef is a memory management issue */

		/* free the memory allocated to pc */

		free(pc);
#endif
	
#ifndef ERASE_APPROX_RIGHT_AWAY 
/* this ifdef is a memory management issue */

		/* now delete the approximations */
		for ( appr_cnt = 0; appr_cnt < dim_out; appr_cnt++ ) 

		{
			Delete_Poly_Cascade(&(pc[appr_cnt]));
		}
		/* free the memory allocated to pc */

		free(pc);
		/************************************/
#endif


	}



	/* calculate the total learning time */

	stop_time = time(0);

	delta_time = stop_time - start_time;

	fprintf(fp_RES_OUTPUT,"\n\nLearning time = %ld sec\n",delta_time);

	printf("\n\nLearning time = %ld sec\n",delta_time);

	fflush(stdout);



	/* free the memory used by the data in orig_inputs_lrn etc... */

	Delete_Data();



}







void Test_Approximation(void)
{
	/* variables */

	Cascade_Poly *pc;

	int curr_cross_val;

	char pc_filename[20];

	FILE *fp;

	time_t start_time, stop_time, delta_time;

	My_Real *x, des, act;

	int i, j;



	/*pdl added Est[3], MaxAbsErr[3], and Loc[3] below*/

	int num_lrn_ex, num_val_ex, dim_in, dim_out, appr_cnt, Loc[3];

	float Robin_Error[5], True[3], Err[3], Est[3], MaxAbsErr[3];



	/* function prototypes */

	void Load_Poly_Cascade(Cascade_Poly *pc,

		FILE *fp);



	void Delete_Poly_Cascade(Cascade_Poly *pc);

	

	void Set_Current_Approx(int curr_ap);



	void Initialize_Data_Test_Val(int *num_lrn_ex, int *num_val_ex, 
		int *dim_i, int *dim_o);
	
	void Set_Data_Dim_Output(int curr_d_o);
	
	void Delete_Data(void);



	void Delete_Data2(void); /*pdl added*/
	
	void Get_Lrn_Ex_Input(int ex_num, 
		int var, 
		double *in);
	

	void Get_Lrn_Ex_Input2(int ex_num, /*pdl added*/

		int var, 

		double *in);


	void Get_Lrn_Ex_Output(int ex_num, 

		double *out);



	void Get_Lrn_Ex_Output2(int ex_num, /*pdl added*/

		double *out);


	
	void Get_Val_Ex_Input(int ex_num, 
		int var, 
		double *in);


	
	void Get_Val_Ex_Output(int ex_num, 
		double *out);





	void Split_Up_Data(int num_orig_ex, int *num_lrn_ex, 

		int *num_val_ex);

	
	My_Real Evaluate_Poly_Cascade(Cascade_Poly *pc,
		My_Real *x_in);
	
	

	/* Start the Testing Program */

	start_time = time(0);

	

	printf("\n\nTesting the Saved Approximation:\n");

	fprintf(fp_RES_OUTPUT,"\n\nTesting the Saved Approximation:\n");

	

	/* load the data from DataTest and (arbitrarily) read it into the learning data array */

	printf("Loading Data...\n");



	Initialize_Data_Test_Val(&num_lrn_ex, &num_val_ex, &dim_in, &dim_out);



	fprintf(fp_RES_OUTPUT,"Total Num of Test Examples = %d\n",num_lrn_ex);

	printf("Total Num of Test Examples = %d\n",num_lrn_ex);



	fprintf(fp_RES_OUTPUT,"Input Dim = %d\n",dim_in);

	fprintf(fp_RES_OUTPUT,"Output Dim = %d\n",dim_out);

	fprintf(fp_RES_OUTPUT,"Number of Approximations = %d\n",MAX_APPROX);



	printf("Input Dim = %d\n",dim_in);
	printf("Output Dim = %d\n",dim_out);
	
	/* initialise Robin_Error and maximum absolute error to 0 */

	for ( appr_cnt = 0; appr_cnt < dim_out; appr_cnt++ ) {

		

		Robin_Error[appr_cnt] = 0;

		MaxAbsErr[appr_cnt] = 0;

		Loc[appr_cnt] = 0;  

	}





/*pdl: For each test example, calculate mean value of all MAX_APPROX approximations */









	/* cycle through all the test examples */

	for ( i = 0; i < num_lrn_ex; i++ )

	{









/*pdl: Initialize estimations of outputs*/



		for ( j = 0; j < dim_out; j++) Est[j] = 0.0;









		/* cycle through the MAX_APPROX approximation cross-validation sets */

		for (curr_cross_val = 0; curr_cross_val < MAX_APPROX; curr_cross_val++) 

		{

		

			/* set some local variables in data_vt */

			Set_Current_Approx(curr_cross_val);



			/* initialise polynomial cascade pc*/

			pc = (Cascade_Poly *)

				malloc((unsigned)dim_out * sizeof(Cascade_Poly));

			if (!(pc)) 

			{

				My_Error("Cannot allocate Cascade_Poly structure!!\n");

			}

			

			/* load the current polynomial cascade pc */

			sprintf(pc_filename,"pc%d.s",curr_cross_val);



			if ((fp = fopen(pc_filename,"rb")) == NULL) 

			{

				fprintf(fp_RES_OUTPUT,"Couldn't open \"%s\"\n",pc_filename);

				printf("Couldn't open \"%s\"\n",pc_filename);

			}

			

			for ( appr_cnt = 0; appr_cnt < dim_out; appr_cnt++ ) 

			{

				Load_Poly_Cascade(&(pc[appr_cnt]),fp);

			}

			fclose(fp);



			/* initialise the input data array x */

			x = (My_Real *)

				malloc((unsigned)pc->dim * (sizeof(My_Real)));

			if (!(x)) 

			{

				My_Error("Cannot allocate x!!\n");

			}









			/* cycle through the output variables*/

			for ( appr_cnt = 0; appr_cnt < dim_out; appr_cnt++ ) 

			{
		
				/* set the local variable in data_vt */

				Set_Data_Dim_Output(appr_cnt);
			
		
				/* get the inputs */			

				for ( j = 0; j < (int)pc->dim; j++ ) 

				{
					Get_Lrn_Ex_Input2(i,j,&(x[j]));     /*pdl change*/
				}
			
				/* get the actual output */

				Get_Lrn_Ex_Output2(i,&des);   /*pdl change*/

				True[appr_cnt] = (float)des;


			
				/* get the best guess of the output */

				act = Evaluate_Poly_Cascade(&(pc[appr_cnt]),x);



				/* pdl Calculate contribution to the estimation of outputs*/

				Est[appr_cnt] = Est[appr_cnt] + (float)act;

				
				

				/* increment Robin's error counter */

				/*Robin_Error[appr_cnt] = Robin_Error[appr_cnt] + (float)fabs(des-act);*/



				/*Calc. error for pdl Testing below*/

				Err[appr_cnt] = (float)fabs(des-act);



		

			}



            /*pdl Testing*/

			printf("Set %d Example %d: True XYA: %6.2f %6.2f %6.2f Err XYA: %6.2f %6.2f %6.2f\n", curr_cross_val+1, i+1, True[0],True[1],True[2],Err[0],Err[1],Err[2]);

			fprintf(fp_RES_OUTPUT,"Set %d Example %d: True XYA: %6.2f %6.2f %6.2f Err XYA: %6.2f %6.2f %6.2f\n", curr_cross_val+1, i+1, True[0],True[1],True[2],Err[0],Err[1],Err[2]);







			/* free the memory used by the input array */

			free(x);



			/* delete the approximations */

			for ( appr_cnt = 0; appr_cnt < dim_out; appr_cnt++ ) 

			{

				Delete_Poly_Cascade(&(pc[appr_cnt]));

			}

			free(pc);



			/* pdl removed: print a dot every cycle to let the user know we're still going */

			/*fprintf(stderr,".");*/






		}
			

		

/* pdl: Get average estimated value and error for each output variable*/



		for ( j = 0; j < dim_out; j++) 

		{

			/* Calculate the estimation average over MAX_APPROX estimates*/



			Est[j] = Est[j] / MAX_APPROX;

			Err[j] = (float)fabs(True[j] - Est[j]);

			Robin_Error[j] = Robin_Error[j] + Err[j];



			/* If the estimate at this testpoint is in more error than worst so far, store error*/

			if ( MaxAbsErr[j] < Err[j]) {

				MaxAbsErr[j] = Err[j];

				Loc[j] = i+1;

			}





		}



		



		printf("Example %d: Est. Error in X,Y,A: %6.2f %6.2f %6.2f\n", i+1, Err[0],Err[1],Err[2]);

		fprintf(fp_RES_OUTPUT,"Example %d: Est. Error in X,Y,A: %6.2f %6.2f %6.2f\n", i+1, Err[0],Err[1],Err[2]);

	

			



	}	



	/*pdl: Display the Maximum Absolute Error for each output variable over all test points*/



	printf("\nWorst case errors: Maximum absolute error over all test points\n");

	fprintf(fp_RES_OUTPUT,"\nWorst case errors: Maximum absolute error over all test points\n");

	

	for ( appr_cnt = 0; appr_cnt < dim_out; appr_cnt++ ) 

	{

	printf("Output Variable %d:  %6.2f, at test point %d.\n", appr_cnt, MaxAbsErr[appr_cnt], Loc[appr_cnt]);

	fprintf(fp_RES_OUTPUT,"Output Variable %d:  %6.2f, at test point %d.\n", appr_cnt, MaxAbsErr[appr_cnt], Loc[appr_cnt]);

	}

	


	/* Calculate and display average Robin_Error */

	printf("\nRobin Errors: Mean absolute error over all test points\n");

	fprintf(fp_RES_OUTPUT,"\nRobin Errors: Mean absolute error over all test points\n");

	

	for ( appr_cnt = 0; appr_cnt < dim_out; appr_cnt++ ) 

	{



	Robin_Error[appr_cnt] = Robin_Error[appr_cnt] / num_lrn_ex;





	printf("Output Variable %d:  %6.2f\n", appr_cnt, Robin_Error[appr_cnt]);

	fprintf(fp_RES_OUTPUT,"Output Variable %d: %6.2f\n", appr_cnt, Robin_Error[appr_cnt]);

	}



	/* free the memory used by the data in orig_inputs_lrn etc... */



	Delete_Data2();



	/* display the total testing time */

	stop_time = time(0);

	delta_time = stop_time - start_time;

	fprintf(fp_RES_OUTPUT,"\n\nValidation time = %ld sec\n",delta_time);

	printf("\n\nValidation time = %ld sec\n",delta_time);

	fflush(stdout);
}
