#include<stdlib.h>
#include<stdio.h>
#include<stdbool.h>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<math.h>
#include<sys/time.h>
#include<functional>
#include<string>
#include<fstream>
#include<sstream>
#include<vector>
#include<dirent.h>
#include<stdint.h>
#include<omp.h>
#include<unistd.h>
#include<random>
#include <stdexcept>
#include <unordered_map>
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
#define XXH_IMPLEMENTATION      /* access definitions */
#include"json.hpp"
#include"xxhash.h"


using namespace std;


#include"cvt.h"
#include"top.h"

//电路的parameter	Circuit_parameter
int			circuit_index	 		= 9999;		//电路编号
extern const int			parameter_max_orders		= 2;



//算法的parameter 	Algorithm_parameter
extern const int 	parameter_num_threads		= 64;		//线程数
extern const int	parameter_multi_output_index	= 0; 		//BSD从第几层开始化简，前面若干层展开序确定
extern const int	parameter_max_BDD_width		= 320000;	//BSD每一层最多多少个节点
int	parameter_early_stop_depth	= parameter_input_bit_width;		//BSD到第几层终止，输出此时的不准确BSD
int	parameter_early_stop_split_nodes= 1000000;	//BSD每一层最多多少个节点

//全局变量
int	GLOBAL_which_demo_function;
int	GLOBAL_BDD_id_number; 
int	GLOBAL_BDD_nodes; 
int	GLOBAL_BDD_split_nodes; 
int	GLOBAL_train_time; 
int	GLOBAL_program_time; 

//待优化变量
int**	variable_order ;
int	variable_order_number;

int	BSD_execute(int variable_order_number,int** variable_order, int partition_depth, int partition_parts,int order_num, bool* output_partition_set);
//bool	truth_table [1024*1024];

#include"BSD.h"
#include"next_layer_bit.h"
#include"tool_function.h"
#include"print_circuit.h"





class BSD_features{
public:
	int	BSD_depth;
	int	BSD_area;
	double	accuracy;
	
	int*	BSD_area_layers;
	int*	accuracy_layers;
	int*	BDD_width_each_layer;


	int	feature_area;
	BSD_features(){
		BSD_area_layers		=	new int [parameter_input_bit_width];
		accuracy_layers		=	new int [parameter_input_bit_width];
		BDD_width_each_layer		=	new int [parameter_input_bit_width];
	}
	//int	nodes_for_each_start_nodparameter_max_BDD_width];
};

	BSD_features BSD_features_0;
//double	variable_features[parameter_input_bit_width];
int	search_order(int search_iterations,bool*  partition_set,int start_order_depth, int* start_order);
int	search_reward(BSD_features BSD_features_0);
int	search_partition(int start_order_depth, int* start_order);

bool*	default_partition_set;
int*	default_start_order;

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

	omp_set_num_threads(parameter_num_threads);
	GLOBAL_BDD_id_number 	= 0;
	GLOBAL_BDD_nodes 	= 0;
	GLOBAL_BDD_split_nodes 	= 0;
	default_start_order 	= new int  [parameter_input_bit_width];	
	default_partition_set 	= new bool [parameter_output_bit_width];	
	for(int i=0;i<parameter_output_bit_width;i++)
		default_partition_set[i] = 1;
	//for(int i=0;i<parameter_output_bit_width;i++)
		default_partition_set[0] = 1;
	

	//io generator来自真值表，不来自写好的文件
 	//char*  truth_table_name = new char [100];
	//int    truth_table_input_width;
	//	if(argc >= 2){
	//		truth_table_input_width= atoi(argv[1]);
	//	}
	//	if(argc>=3){
	//		truth_table_name = argv[2];
	//	}
	//
	//        ifstream truth_table_file(truth_table_name);
	//	string line_data;
	//	for(int i=0;i<pow(2,20);i++){
	//			truth_table[i] = 0;
	//	}
	//	for(int i=0;i<pow(2,20);i++){
	//		getline(truth_table_file,line_data);
	//		//cout<<line_data[truth_table_input_width+1]<<endl;
	//		if(line_data[truth_table_input_width+1]=='0')
	//			truth_table[i] = 0;
	//		else
	//			truth_table[i] = 1;
	//	}
	//search_order();
	//int* start_order_a = new int [parameter_input_bit_width];	
	//int area_a =	search_order(10,output_partition_set_a,0,start_order_a);
	
	
	int* start_order 	= new int  [parameter_input_bit_width];
	
	int area_a =	search_order(10,default_partition_set,0,start_order);
	//search_partition(parameter_input_bit_width,start_order);
};
int search_partition(int start_order_depth, int* start_order){
	random_device rd;	
	mt19937 gen(rd());
	int   best_area = 999999;
	int   best_area_a = 999999;
	int   best_area_b = 999999;
	bool* best_output_partition_set_a = new bool [parameter_output_bit_width];	
	bool* best_output_partition_set_b = new bool [parameter_output_bit_width];	
	int*  best_start_order_a = new int [parameter_input_bit_width];	
	int*  best_start_order_b = new int [parameter_input_bit_width];	
	for (int i=0;i<parameter_output_bit_width;i++){
		best_output_partition_set_a[i]=0;
		best_output_partition_set_b[i]=0;
	}
	best_area =	search_order(1,default_partition_set,parameter_input_bit_width,start_order);
		cout<<"###########################################################################"<<endl;
		cout<<"Best Design Area:	"<<best_area<<"	"<<best_area_a<<"	+ "<<best_area_b<<endl;
		cout<<"###########################################################################"<<endl;
	for (int j=0;j<2;j++){
		bool* output_partition_set_a = new bool [parameter_output_bit_width];	
		bool* output_partition_set_b = new bool [parameter_output_bit_width];	
		for (int i=0;i<parameter_output_bit_width;i++){
			output_partition_set_a[i]=(gen()%2==0);
			output_partition_set_b[i]=1-output_partition_set_a[i];
		}
		
		int area=0;;
	//	int* start_order_a = new int [parameter_input_bit_width];	
	//	int* start_order_b = new int [parameter_input_bit_width];	
	//	for(int i=0;i<parameter_input_bit_width;i++){
	//		start_order_a[i] = 0;
	//		start_order_b[i] = 0;
	//	}
		int area_a =	search_order(10,output_partition_set_a,start_order_depth,start_order);
		int area_b =	search_order(10,output_partition_set_b,start_order_depth,start_order);
		area = area_a + area_b;
		if(area<best_area){
			best_area = area;
			best_area_a = area_a;
			best_area_b = area_b;
			for (int i=0;i<parameter_output_bit_width;i++){
				best_output_partition_set_a[i]=output_partition_set_a[i];
				best_output_partition_set_b[i]=output_partition_set_b[i];
			}
			for (int i=0;i<parameter_input_bit_width;i++){
				best_start_order_a[i]=start_order[i];
				best_start_order_b[i]=start_order[i];
			}
		}
		cout<<"###########################################################################"<<endl;
		cout<<"Design Area:		"<<area<<"	"<<area_a<<"	+ "<<area_b<<endl;
		cout<<"Best Design Area:	"<<best_area<<"	"<<best_area_a<<"	+ "<<best_area_b<<endl;
		cout<<"###########################################################################"<<endl;
		delete [] output_partition_set_a;
		delete [] output_partition_set_b;
	//	delete [] start_order_a;
	//	delete [] start_order_b;
	}
		//parameter_max_orders		*= 2;
		int area=0;	
		int area_a =	search_order(40,best_output_partition_set_a,parameter_input_bit_width,best_start_order_a);
		int area_b =	search_order(40,best_output_partition_set_b,parameter_input_bit_width,best_start_order_b);
		area = area_a + area_b;
		
		cout<<"###########################################################################"<<endl;
		cout<<"Final Design Area:		"<<area<<"	"<<area_a<<"	+ "<<area_b<<endl;
		cout<<"Best Design Area:		"<<best_area<<"	"<<best_area_a<<"	+ "<<best_area_b<<endl;
		cout<<"###########################################################################"<<endl;
	delete []  best_output_partition_set_a;	
	delete []  best_output_partition_set_b;	
	delete []  best_start_order_a;	
	delete []  best_start_order_b;	


};
int BSD_execute(int variable_order_number,int** variable_order, int partition_depth, int partition_parts,int order_num,bool*  output_partition_set){

	cout<<"BSD execute start"<<endl;	
	BDD_class BDD_class_main;
	cout<<"This variable order: "<<variable_order_number<<endl;
	for (int j=0;j<parameter_max_orders;j++){
		//cout<<"j"<<j<<endl;
		BDD_class_main.BSD_variable_order[j]     = new int [parameter_input_bit_width];
	}
	BDD_class_main.output_partition_set 	= output_partition_set;
	BDD_class_main.which_demo_function 	= GLOBAL_which_demo_function;
	//for (int vi=0;vi<partition_parts;vi++){
	//	BDD_class_main.BSD_variable_order_number = variable_order_number;
	//	for(int i=0;i<variable_order_number;i++){
	//		BDD_class_main.BSD_variable_order[vi][i] = variable_order[vi][i];
	//		cout<<BDD_class_main.BSD_variable_order[vi][i]<<" ";
	//	}
	//	cout<<endl;
	//}
	//cout<<endl;
	BDD_class_main.order_num = order_num;
	for(int vi=0;vi<parameter_max_orders;vi++){
		BDD_class_main.BSD_variable_order_number = variable_order_number;
		for(int i=0;i<variable_order_number;i++){
			BDD_class_main.BSD_variable_order[vi][i] = variable_order[vi][i];
			cout<<BDD_class_main.BSD_variable_order[vi][i]<<" ";
		}
		cout<<endl;
	}
	cout<<endl;


	BDD_class_main.start_depth 	= 0;	
	BDD_class_main.BDD_id 	= 0;
	BDD_class_main.how_many_start_nodes = parameter_output_bit_width;
	BDD_class_main.start_nodes = new BDD_node [BDD_class_main.how_many_start_nodes];
	for(int zi=0;zi<BDD_class_main.how_many_start_nodes;zi++){
		BDD_class_main.start_nodes[zi].which_bit_output 	= zi;
		BDD_class_main.start_nodes[zi].which_root_node  	= zi;
		BDD_class_main.start_nodes[zi].which_root_node_all[BDD_class_main.start_nodes[zi].which_root_node] = 1;
	}
	for(int zi=0;zi<parameter_input_bit_width+1;zi++){
		BDD_class_main.has_been_unfold[zi] = 0;
		BDD_class_main.most_influence[zi] = 0;
		BDD_class_main.BDD_width_each_layer[zi] = 0;
	}

	BDD_class_main.partition_depth = partition_depth;
	BDD_class_main.partition_parts = partition_parts;

	BDD_class_main.BDD_FULL_PROCESS();

	for(int zi=0;zi<parameter_input_bit_width;zi++){
		BSD_features_0.BSD_area_layers [zi] =  BDD_class_main.split_nodes_each_layer[zi];
		BSD_features_0.accuracy_layers [zi] =  BDD_class_main.accuracy_each_layer[zi];
		BSD_features_0.BDD_width_each_layer[zi] = BDD_class_main.BDD_width_each_layer[zi];
	}
	if(partition_depth > parameter_input_bit_width){
		for(int zj = 0; zj<parameter_max_orders;zj++){
			for(int zi=0;zi<parameter_input_bit_width;zi++){
				variable_order [zj][zi] = BDD_class_main.most_influence[zi];
			}
		}
	}
	else{
		for(int zj =0; zj<parameter_max_orders;zj++){
			for(int zi=0;zi<parameter_input_bit_width;zi++){
				variable_order [zj][zi] = BDD_class_main.BSD_variable_order[0][zi];
			}
		}
	}

	BSD_features_0.BSD_depth = BDD_class_main.total_BDD_depth+1;
	BSD_features_0.BSD_area  = BDD_class_main.total_split_nodes_recursive;
	BSD_features_0.accuracy  = BDD_class_main.circuit_accuracy;
	BSD_features_0.feature_area  = BDD_class_main.feature_area;

	int reward = search_reward(BSD_features_0);

	return reward;	

};

int search_reward(BSD_features BSD_features_0){
	int	reward = (1000000*double(1-BSD_features_0.accuracy));
	reward += BSD_features_0.BSD_area;
	if(BSD_features_0.accuracy <1)
		reward = int(1.2*reward);
	cout<<"BSD accuracy:	"<< BSD_features_0.accuracy <<endl;
	cout<<"BSD area:	"<< BSD_features_0.BSD_area <<endl;
	//reward += int(BSD_features_0.feature_area/100) ;

	return reward;	

};

int search_order(int search_iterations,bool* output_partition_set,int start_order_depth, int* start_order){
        ofstream result_0("result_0_20bit",ios::app);
        ofstream result_10("result_10_20bit",ios::app);
        ofstream result_100("result_100_20bit",ios::app);
        ofstream result_1000("result_1000_20bit",ios::app);

	variable_order = new int* [parameter_max_orders];
	for (int vi=0;vi<parameter_max_orders;vi++){
		variable_order[vi] = new int [parameter_input_bit_width];
		for (int vj=0;vj<parameter_input_bit_width;vj++)
			variable_order[vi][vj]=0;
	}

	int	best_area=9999999; 
	int	best_reward=9999999; 
	int	best_area_depth = 2;
	int**	best_variable_order;

	int*	best_BDD_split_nodes = new int [parameter_input_bit_width];
	int*	best_areas	= new int [parameter_max_orders];
	int*	best_rewards	= new int [parameter_max_orders];
	int*	best_area_depths= new int [parameter_max_orders];
	for (int vi=0;vi<parameter_max_orders;vi++){
		best_areas[vi] = 0;
		best_rewards[vi] = 0;
		best_area_depths[vi] = 0;
	}
	int best_reward_max = 0;
	int best_order_num=0;

	best_variable_order = new int* [parameter_max_orders];
	for (int vi=0;vi<parameter_max_orders;vi++){
		best_variable_order[vi] = new int [parameter_input_bit_width];
		for (int vj=0;vj<parameter_input_bit_width;vj++)
			best_variable_order[vi][vj]=0;
	}

	int area =0;
	int reward =0;
	int	mutation_depth =0;
	random_device rd;	
	mt19937 gen(rd());

	double*	feature_variable = new double [parameter_input_bit_width];
		for (int vj=0;vj<parameter_input_bit_width;vj++)
			feature_variable[vj]=0;

	int best_area_0;
	int best_area_10;
	int best_area_100;
	int best_area_1000;

	int	best_iteration = 0;
	int	partition_depth = 1000000;
	int	partition_parts = 2;	
	int	best_partition_depth = 1000000;
	int	best_partition_parts = 2;	
	int learning_rate;
	for (int i=0;i<=search_iterations;i++){

				GLOBAL_BDD_id_number += 1;

		if(i==1){
			result_0 << best_area << endl;
			best_area_0 = best_area; 
		}
		else if(i==11){
			result_10 << best_area << endl;
			best_area_10 = best_area; 
			
		}
		else if(i==101){
			result_100 << best_area << endl;
			best_area_100 = best_area; 
			
		}
		else if(i==999){
			result_1000 << best_area << endl;
		}

		int parameter_learning_rate = 2;
		if(best_area > 10000){
			parameter_learning_rate =6;
		}
		else if(best_area > 6000)
			parameter_learning_rate =5;
		else if(i-best_iteration > 2000)	
			parameter_learning_rate =4;
		else if(i-best_iteration > 800)	
			parameter_learning_rate =3;
		learning_rate = 1+gen()%parameter_learning_rate;
		//learning_rate = 1;
		mutation_depth =  int(best_area_depth/2);
		if(mutation_depth > best_area_depth)
			mutation_depth = best_area_depth;

		int	min_feature = 9999999;
		cout<<"Current best variable order: "<<endl;
		for(int vj=0;vj<parameter_max_orders;vj++){
			if(i==0){
				for(int vi=0;vi<parameter_input_bit_width;vi++){
					variable_order[vj][vi] = start_order[vi];
					cout<<variable_order[vj][vi]<<" ";
				}
			}
			else{
				for(int vi=0;vi<best_area_depth;vi++){
					variable_order[vj][vi] = best_variable_order[vj][vi];
					cout<<variable_order[vj][vi]<<" ";
				}
			}
			cout<<endl;
		}
		cout<<endl;
			
			int order_num = gen()%parameter_max_orders;
			if(i<parameter_max_orders)
				order_num = 0;
			//else if (i==search_iterations){
			//	int best_reward_tmp = 999999;
			//	int min_best_order = 0;
			//	for(int zi=0;zi<parameter_max_orders;zi++){
			//		if(best_rewards[zi] < best_reward_tmp){
			//			best_reward_tmp = best_rewards[zi];
			//			min_best_order = zi;
			//		}
			//	}
			//	order_num = min_best_order;
			//	cout<<"Best order num	"<<order_num<<endl;
			//}
			

			//if(gen()%4==0){
			//	order_num = max_best_order;
			//}
		//if(i<100)
		// 	learning_rate= int((100-i)/10);
		//else
		// 	learning_rate= 2;
		learning_rate=1;
		for (int zi=0;zi<learning_rate;zi++){	
			//for(int vv = 0;vv<parameter_max_orders;vv++){	
				int vv = order_num;
			if(i<parameter_max_orders){
					vv=0;
			}else if (i==search_iterations){
			}
			else{
				best_area_depth = best_area_depths[vv];
			      //for(int vi=1;vi<best_area_depth;vi++){
			      //	if( (gen()%int(1+best_area_depth)==0)){
			      //		int vii = vi-1;
			      //		int x = variable_order[vv][vi];
			      //		variable_order[vv][vi] = variable_order[vv][vii];
			      //		variable_order[vv][vii] = x;
			      //		//double y = variable_features[vi];
			      //		//variable_features[vi] = variable_features[vii];
			      //		//variable_features[vii] = y;
			      //		break;
			      //	}
			      //}
			      int num_a = gen()%int(best_area_depth-1);
			      //int num_b = gen()%int(1+best_area_depth/4);
			      int num_c = gen()%int(1+best_area_depth/2);
			      int num_b =  gen()%int(1+best_area_depth/2);
			      cout<<"order number	"<<order_num<<endl;
			      cout<<"num_a:	"<<num_a<<"	num_b:	"<<num_b<<"	num_c:	"<<num_c<<endl;
			      for(int vc=0;vc<num_c;vc++){
			      	int x = variable_order[vv][num_a];
			        	for (int vj=0;vj<num_b+num_c;vj++){
			        		if( (vj==(num_b+num_c-1))){
			            			variable_order[vv][(num_a + vj)%int(best_area_depth)] =x;
			        		}
			        		else
			        			variable_order[vv][(num_a + vj)%int(best_area_depth)] = variable_order[vv][(num_a + vj+1)%int(best_area_depth)];
			        	}
			      }
	
			      //for(int vi=0;vi<best_area_depth;vi++){
			      //	for(int vj=0;vj<vi;vj++){
			      //		if(variable_order[vv][vi] == variable_order[vv][vj]){
			      //			for(int vk=0;vk<best_area_depth-vi-1;vk++)
			      //				variable_order[vv][vi+vk] = variable_order[vv][vi+vk+1];
			      //		}
			      //	}
			      //}
			      
				//int num_d = gen()%int(1+best_area_depth);
				//int num_e = gen()%int(1+best_area_depth);
			      	//int x = variable_order[vv][num_d];
			      	//variable_order[vv][num_d] = variable_order[vv][num_e];
			      	//variable_order[vv][num_e] = x;
			}
			//}
			  	
		}     			
		

					//for (int vj=0;vj<parameter_max_orders;vj++){
					//	for(int vi=0;vi<parameter_input_bit_width;vi++){
					//		cout<<variable_order[vj][vi]<<" ";
					//		//variable_features[vi] = double(BSD_features_0.BDD_width_each_layer[vi+1]) / double(BSD_features_0.BDD_width_each_layer[vi]);
					//		//cout<<variable_features[vi]<<"	";
					//	}
					//	cout<<endl;
					//}

		//for(int j=mutation_depth;j<parameter_input_bit_width;j++){
		//	for (int vi=0;vi<parameter_input_bit_width;vi++){
		//		if(feature_variable[vi]<min_feature){
		//			min_feature = feature_variable[vi];
		//			variable_order[j] = vi;
		//		}
		//	}
		//	min_feature = 9999999;
		//	feature_variable[variable_order[j]] = 9999999;

		//}
		if (i<parameter_max_orders){
			//parameter_max_samples 		= int(parameter_max_samples/10);		//BSD每一个节点最多进行多少次采样
			reward = 	BSD_execute(start_order_depth,variable_order,partition_depth,partition_parts,0,output_partition_set);
			//parameter_max_samples 		*= 10;		//BSD每一个节点最多进行多少次采样
		}
		//else if (i<parameter_max_orders){
		//	reward = 	BSD_execute(0,variable_order,partition_depth,partition_parts,0,output_partition_set);
		//}
		else if (i==search_iterations){
			parameter_early_stop_split_nodes = 9999999;
			//  area = 	BSD_execute(best_area_depth,variable_order,partition_depth,partition_parts,order_num,output_partition_set);
			reward = 	BSD_execute(best_area_depth,variable_order,partition_depth,partition_parts,order_num,output_partition_set);
			//area = 	BSD_execute(parameter_input_bit_width,best_variable_order,10000,best_partition_parts,best_order_num,output_partition_set);
			break;
		}
		else{
			reward = 	BSD_execute(best_area_depth,variable_order,partition_depth,partition_parts,order_num,output_partition_set);
		}


		bool accept=0;
			//accept = (reward <= best_reward);
			double accept_ratio = double(reward) / double(best_reward_max);
			if(i<parameter_max_orders)
				accept = 1;
			else if(accept_ratio < 1)
				accept = 1;
			else if (accept_ratio == 1){
				if(gen()%2 == 0)
					accept = 1;
				else 
					accept = 0;
			}
			else if (accept_ratio > 1.1)
				accept = 0;
			else {
				int k = (1.1-accept_ratio)*100;
				if(gen()%40<k)
					accept = 1;
				else
					accept = 0;	
			}
			if(accept){
				int replace_order;
					replace_order = order_num;
					int best_reward_tmp = 0;
					if(i>=parameter_max_orders){
						for(int zi=0;zi<parameter_max_orders;zi++){
							if(best_rewards[zi] > best_reward_tmp){
								best_reward_tmp = best_rewards[zi];
								replace_order = zi;
							}
						}
					}
					else{
						replace_order = i;
					}
					
				if(i==0){
					for (int zi=0;zi<1;zi++){
						replace_order = zi;
						best_iteration = i;
						if(reward<best_reward){
							best_reward = reward;
							best_area = BSD_features_0.BSD_area;
							best_area_depth = BSD_features_0.BSD_depth;
						}
						best_rewards[replace_order] = reward;
						best_areas[replace_order] = BSD_features_0.BSD_area;
						best_area_depths[replace_order] = BSD_features_0.BSD_depth;
						best_partition_depth = partition_depth;
						best_partition_parts = partition_parts;
								for(int vi=0;vi<parameter_input_bit_width;vi++){
									best_variable_order[replace_order][vi] = variable_order[0][vi];
									cout<<best_variable_order[replace_order][vi]<<" ";
									best_BDD_split_nodes[vi] = BSD_features_0.BSD_area_layers[vi];
								}
								cout<<endl;
						}
						best_reward_max = 0;	
						best_order_num = 0;	
						for(int zi=0;zi<parameter_max_orders;zi++){
							if(best_rewards[zi] > best_reward_max)
								best_reward_max = best_rewards[zi];
							if(best_rewards[zi] == best_reward)
								best_order_num = zi;	
						}
							if(best_reward_max<1000)
								parameter_early_stop_split_nodes = 4000;
							else
								parameter_early_stop_split_nodes = int(best_reward_max*4);

				}else{
					best_iteration = i;
					if(reward<best_reward){
						best_reward = reward;
						best_area = BSD_features_0.BSD_area;
						best_area_depth = BSD_features_0.BSD_depth;
					}
					best_rewards[replace_order] = reward;
					best_areas[replace_order] = BSD_features_0.BSD_area;
					best_area_depths[replace_order] = BSD_features_0.BSD_depth;
					best_partition_depth = partition_depth;
					best_partition_parts = partition_parts;
							for(int vi=0;vi<parameter_input_bit_width;vi++){
								best_variable_order[replace_order][vi] = variable_order[0][vi];
								cout<<best_variable_order[replace_order][vi]<<" ";
								best_BDD_split_nodes[vi] = BSD_features_0.BSD_area_layers[vi];
							}
							cout<<endl;
					best_reward_max = 0;	
					best_order_num = 0;	
					for(int zi=0;zi<parameter_max_orders;zi++){
						if(best_rewards[zi] > best_reward_max)
							best_reward_max = best_rewards[zi];
						if(best_rewards[zi] == best_reward)
							best_order_num = zi;	
					}
					if(i>=parameter_max_orders)
						if(best_reward_max<1000)
							parameter_early_stop_split_nodes = 4000;
						else
								parameter_early_stop_split_nodes = int(best_reward_max*4);


					if((i>=10) && (best_reward_max < 1.005*best_reward))
						break;

				}

				cout<<"#############################"<<endl;
				cout<<"#    This order accept      #"<<endl;
				cout<<"#############################"<<endl;
			}
			if(parameter_early_stop_split_nodes<4*best_reward_max)
				parameter_early_stop_split_nodes += 100;
							cout<<endl;
			cout<<"Best Iteration:	"<<best_iteration<<endl;
			cout<<"This Iteration:	"<<i<<endl;
			cout<<"Reward:		"<<reward<<endl;
			cout<<"Best Reward:	"<<best_reward<<endl;
			cout<<"Area:		"<<BSD_features_0.BSD_area<<endl;
			cout<<"Best Area:	"<<best_area<<endl;


			cout<<endl;
			cout<<"Best Reward Max:	"<<best_reward_max<<endl;
			for(int zi=0;zi<parameter_max_orders;zi++){
				cout<<"Reward["<<zi<<"]	"<<best_rewards[zi]<<endl;
			}
			cout<<"Best Order:	";
			for (int vj=0;vj<parameter_input_bit_width;vj++){
				start_order[vj]=best_variable_order[best_order_num][vj];
				cout<<start_order[vj]<<" ";
			}
			cout<<endl;
			//cout<<"Best Design Area:	"<<BSD_features_0.BSD_area<<endl;
			cout<<endl;
		}
				
	//area = 	BSD_execute(parameter_input_bit_width,best_variable_order,10000,best_partition_parts,best_order_num,output_partition_set);

//	delete [] best_BDD_split_nodes ;
//	delete [] best_areas	;
//	delete [] best_rewards	;
//	delete [] best_area_depths;
//	for (int vi=0;vi<parameter_max_orders;vi++){
//		delete [] variable_order[vi];
//		delete [] best_variable_order[vi];
//	}
//	delete [] variable_order;
//	delete [] best_variable_order;
	return reward;
};

