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


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



//算法的parameter 	Algorithm_parameter
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= 10000000;	//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; 

bool**	file_inputs;
//待优化变量
int**	multi_variable_order ;
int	variable_order_number;

//bool	truth_table [1024*1024];


int output_bit_index [PO_WIDTH] = {120};
bool* io_generator_function(bool* input_data, bool* output_data) {

	
	int i,j;
	bool* output_data_temp = new bool [PO_WIDTH];
	
		
	io_generator_outer(input_data,output_data_temp);
	for(i=0;i<parameter_output_bit_width;i++){
		if(parameter_output_bit_width == PO_WIDTH)
			output_data[i] = output_data_temp[i];
		else
			output_data[i] = output_data_temp[output_bit_index[i]];
	}
	arr_delete (output_data_temp);
			
	return	output_data;
}

#ifdef INPUT_AIG
uint64_t* io_generator_function_vec(uint64_t* input_data, uint64_t* output_data) {

	
	int i,j;
	uint64_t* output_data_temp = new uint64_t [PO_WIDTH];
	
	io_generator_outer_vec(input_data,output_data_temp);
	for(i=0;i<parameter_output_bit_width;i++){
		if(parameter_output_bit_width == PO_WIDTH)
			output_data[i] = output_data_temp[i];
		else
			output_data[i] = output_data_temp[output_bit_index[i]];
	}
	arr_delete (output_data_temp);
		
	return	output_data;
}
#endif
class	node_index {
public:	
	int	node_depth;
	int	root_node_index;
	int*	expand_input_bit_index;
	bool*	expand_input_bit_data;
	
	node_index(){
		expand_input_bit_index = new int  [parameter_input_bit_width];
		expand_input_bit_data  = new bool [parameter_input_bit_width];
	}
	~node_index(){
		//arr_delete (expand_input_bit_index);
		//arr_delete (expand_input_bit_data);
	}
};

int default_start_node_number = parameter_output_bit_width;
node_index*	default_start_node_index;


int BSD_execute(int start_node_number, node_index* start_node_index,int variable_order_number, int* variable_order);






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

	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];
		variable_order		= 	new int [parameter_input_bit_width];
	}
	//int	nodes_for_each_start_nodparameter_max_BDD_width];
};
BSD_features BSD_features_0;

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

bool*	default_partition_set;
int*	default_start_order;


void	set_default(){
	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];
	default_start_node_index= new node_index [parameter_output_bit_width];
	for(int i=0;i<parameter_output_bit_width;i++){
		default_partition_set[i] = 1;
	}
	default_start_node_number = parameter_output_bit_width;
	for(int i=0;i<default_start_node_number;i++){
		default_start_node_index[i].node_depth = 0;
		default_start_node_index[i].root_node_index = i;
		for (int j=0;j<parameter_input_bit_width;j++){
			default_start_node_index[i].expand_input_bit_index[j] = 0;
			default_start_node_index[i].expand_input_bit_data[j]  = 0;
		}
	}
	//for(int i=0;i<parameter_output_bit_width;i++)
		default_partition_set[0] = 1;
	
	ifstream sampling_input_file("sample_input.set");
	file_inputs = new bool* [parameter_io_file_lines];
	for (int i=0;i<parameter_io_file_lines;i++){
		file_inputs[i] = new bool [parameter_input_bit_width];
		for(int j=0;j<parameter_input_bit_width;j++){
			file_inputs[i][j] = 0;
		}
	}
	std::string line;
	int lineCount = 0;
	while ((lineCount < parameter_io_file_lines) && std::getline(sampling_input_file, line)){
		if (line.length() >= parameter_input_bit_width){
			for (int i = 0; i < parameter_input_bit_width; i++) {
				if(line[i] == '1'){
					file_inputs[lineCount][i] = 1;
				}
				else if (line[i] == '0'){
					file_inputs[lineCount][i] = 0;
				}else{
					std::cerr << "第 " << lineCount + 1 << " 行第 " << i + 1 << " 个字符无效，应为'0'或'1'" << std::endl;
					file_inputs[lineCount][i] = 0;  // 默认值
				}
			}
			lineCount ++;
		}
	}	
	//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];
	//	}
	//
	

	//	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);
	
	


}
//double	variable_features[parameter_input_bit_width];
double search_order(int start_node_number , int start_node_depth, node_index* start_node_index,int search_iterations, int* start_order);
double	search_reward(BSD_features BSD_features_0);
int search_partition(int start_node_number,int start_node_depth , node_index* start_node_index , int* start_order);

int search_partition(int start_node_number=default_start_node_number,int start_node_depth = 0, node_index* start_node_index = default_start_node_index, int* start_order = default_start_order){
	
	int search_order_times = 5;
	int min_partition_parts ;
	#ifdef ACCURACY_FIRST							
		min_partition_parts = start_node_number;
	#else
		min_partition_parts = 0;
	#endif

	random_device rd;	
	mt19937 gen(rd());
	int   max_partition_parts = start_node_number;
	int   best_partition_parts = max_partition_parts;
	double   best_area = 999999;
	
	bool** partition_sets = new bool* [max_partition_parts];
	bool** best_partition_sets = new bool* [max_partition_parts];
	for (int i=0;i<max_partition_parts;i++){
		partition_sets[i] = new bool [max_partition_parts];
		best_partition_sets[i] = new bool [max_partition_parts];
		for(int j=0;j<max_partition_parts;j++){
			partition_sets[i][j] = 0;
			best_partition_sets[i][j] = 0;
		}
		partition_sets[i][i] = 1;
		best_partition_sets[i][i] = 1;
	}
	double* area_parts 	= new double [max_partition_parts];
	double* best_area_parts 	= new double [max_partition_parts];
	
	double area=0;
	for (int i=0;i<max_partition_parts;i++){
		cout<<"Partition_set	["<<i<<"]	";
		int start_node_partition = 0;
		for(int j=0;j<max_partition_parts;j++){
			cout<<partition_sets[i][j];
			if(partition_sets[i][j]){
				start_node_partition ++;
			}
		}
		cout<<endl;
		int zi =0;
		node_index* start_node_index_partition = new node_index [max_partition_parts];
		for(int j=0;j<max_partition_parts;j++){
			if(partition_sets[i][j]){
				start_node_index_partition[zi].node_depth = start_node_index[j].node_depth;
				start_node_index_partition[zi].root_node_index = start_node_index[j].root_node_index;
				for(int zj=0;zj<parameter_input_bit_width;zj++){
					start_node_index_partition[zi].expand_input_bit_index[zj] = start_node_index[j].expand_input_bit_index[zj];
					start_node_index_partition[zi].expand_input_bit_data[zj] = start_node_index[j].expand_input_bit_data[zj];
				}
				zi++;
			}
		}
		area_parts[i] =  search_order(start_node_partition , start_node_depth, start_node_index_partition, search_order_times, start_order);
		area += area_parts[i];
		arr_delete  (start_node_index_partition);
	}
	if(area<best_area){
		best_area = area;
		best_partition_parts = max_partition_parts;
		for (int i=0;i<max_partition_parts;i++){
			for(int j=0;j<max_partition_parts;j++){
				best_partition_sets[i][j] = partition_sets[i][j];
			}
			best_area_parts[i] = area_parts[i];
		}
	}
	cout<<"###########################################################################"<<endl;
	cout<<"Design Area:		"<<area<<endl;
	for (int i=0;i<max_partition_parts;i++){
		cout<<"partition "<<i<<"	"<<area_parts[i]<<endl;
	}	
	char* 	    start_node_index_string = new char [parameter_output_bit_width+1];
	
	ofstream function_top_file("rtl/function_top.v");
	for (int i = 0 ;i < best_partition_parts;i++){
		for (int j=0;j<parameter_output_bit_width;j++){
			if(best_partition_sets[i][j]){
				start_node_index_string[j] = '1';
			}
			else{
				start_node_index_string[j] = '0';
			}
			
		}
		start_node_index_string[parameter_output_bit_width] = '\0';
 		function_top_file << "`include \"function_layer_"<<start_node_depth<<"_nodes_"<<start_node_index_string<<".v\" "<<endl;
 	}
	function_top_file << endl;
	function_top_file << "module function_top (i,o);"<<endl<<endl;
 	function_top_file << "input 	["<<PI_WIDTH-1<<":0] i;"<<endl; 
 	function_top_file << "output	["<<parameter_output_bit_width-1<<":0]  o;"<<endl<<endl;
	for (int i = 0 ;i < best_partition_parts;i++){
 		function_top_file << "wire	["<<parameter_output_bit_width-1<<":0]  o_"<<i<<";"<<endl;
 	}
	function_top_file << endl;
	for (int i = 0 ;i < best_partition_parts;i++){
		for (int j=0;j<parameter_output_bit_width;j++){
			if(best_partition_sets[i][j]){
				start_node_index_string[j] = '1';
			}
			else{
				start_node_index_string[j] = '0';
			}
			
		}
		start_node_index_string[parameter_output_bit_width] = '\0';
 		function_top_file << "function_layer_"<<start_node_depth<<"_nodes_"<<start_node_index_string<<"	part"<<i<<"	(.i(i),.o_index(o_"<<i<<"));"<<endl;
 	}
	function_top_file <<endl;
	for (int i = 0 ;i < parameter_output_bit_width;i++){
		int position_a = 0;
		for (int j=0;j<best_partition_parts;j++){
				if(best_partition_sets[j][i] == 1){
					position_a = j;
					break;
				}
		}
 		function_top_file << "assign	o["<<i<<"]	=	o_"<<position_a<<"["<<i<<"];"<<endl;
 	}
	function_top_file << "endmodule"<<endl;
	function_top_file.close();

	cout<<"Best Design Area:	"<<best_area<<endl;
	cout<<"###########################################################################"<<endl;

	for (int partition_parts=max_partition_parts-1;partition_parts>min_partition_parts;partition_parts--){
		int use_part;
		for (use_part=0;use_part<partition_parts;use_part++){
			bool merge_success = 0;
			for(int merge_part=use_part+1;merge_part<partition_parts;merge_part++){
				
				//改变Partition Set

				for (int i=0;i<partition_parts;i++){
					if(i<merge_part){
						for(int j=0;j<max_partition_parts;j++){
							partition_sets[i][j] = best_partition_sets[i][j];
						}
					}else if(i<partition_parts){
						for(int j=0;j<max_partition_parts;j++){
							partition_sets[i][j] = best_partition_sets[i+1][j];
						}
					}else{
						for(int j=0;j<max_partition_parts;j++){
							partition_sets[i][j] = 0;
						}
					}
				}		
				for(int j=0;j<max_partition_parts;j++){
					if(!partition_sets[use_part][j])
						partition_sets[use_part][j] = best_partition_sets[merge_part][j];
				}


				//执行对比
				double area=0;
				for (int i=0;i<partition_parts;i++){
					if(i>=merge_part){

						area_parts[i] =  best_area_parts[i+1];
						area += area_parts[i];
					}
					else{
			
						cout<<"Partition_set	["<<i<<"]	";
						int start_node_partition = 0;
						for(int j=0;j<max_partition_parts;j++){
							cout<<partition_sets[i][j];
							if(partition_sets[i][j]){
								start_node_partition ++;
							}
						}
						cout<<endl;
						node_index* start_node_index_partition = new node_index [max_partition_parts];
						int zi =0;
						for(int j=0;j<partition_parts;j++){
							if(partition_sets[i][j]){
								//start_node_index_partition[zi] = start_node_index[j];
								start_node_index_partition[zi].node_depth 		= start_node_index[j].node_depth;
								start_node_index_partition[zi].root_node_index 		= start_node_index[j].root_node_index;
								for(int zj=0;zj<parameter_input_bit_width;zj++){
									start_node_index_partition[zi].expand_input_bit_index[zj] = start_node_index[j].expand_input_bit_index[zj];
									start_node_index_partition[zi].expand_input_bit_data[zj]  = start_node_index[j].expand_input_bit_data[zj];
								}

								zi ++;
							}
						}
						area_parts[i] =  search_order(start_node_partition , start_node_depth, start_node_index_partition, search_order_times, start_order);
						area += area_parts[i];
						arr_delete ( start_node_index_partition);
					}
					
				}
				if(area<best_area){
					best_area = area;
					best_partition_parts = partition_parts;
					for (int i=0;i<max_partition_parts;i++){
						for(int j=0;j<max_partition_parts;j++){
							best_partition_sets[i][j] = partition_sets[i][j];
						}
						best_area_parts[i] = area_parts[i];
					}
					merge_success = 1;
				}
				cout<<"###########################################################################"<<endl;
				cout<<"Design Area:		"<<area<<endl;
				for (int i=0;i<partition_parts;i++){
					cout<<"partition "<<i<<"	";
					for (int j = 0;j<max_partition_parts;j++){
						cout<<partition_sets[i][j];
					}
					cout<<"	"<<area_parts[i]<<endl;
				}
				cout<<"Best Design Area:	"<<best_area<<endl;
			
				char* 	    start_node_index_string = new char [parameter_output_bit_width+1];
				ofstream function_top_file("rtl/function_top.v");
				for (int i = 0 ;i < best_partition_parts;i++){
					for (int j=0;j<parameter_output_bit_width;j++){
						if(best_partition_sets[i][j]){
							start_node_index_string[j] = '1';
						}
						else{
							start_node_index_string[j] = '0';
						}
						
					}
					start_node_index_string[parameter_output_bit_width] = '\0';
 					function_top_file << "`include \"function_layer_"<<start_node_depth<<"_nodes_"<<start_node_index_string<<".v\" "<<endl;
 				}
				function_top_file << endl;
				function_top_file << "module function_top (i,o);"<<endl<<endl;
 				function_top_file << "input 	["<<PI_WIDTH-1<<":0] i;"<<endl; 
 				function_top_file << "output	["<<parameter_output_bit_width-1<<":0]  o;"<<endl<<endl;
				for (int i = 0 ;i < best_partition_parts;i++){
 					function_top_file << "wire	["<<parameter_output_bit_width-1<<":0]  o_"<<i<<";"<<endl;
 				}
				function_top_file << endl;
				for (int i = 0 ;i < best_partition_parts;i++){
					for (int j=0;j<parameter_output_bit_width;j++){
						if(best_partition_sets[i][j]){
							start_node_index_string[j] = '1';
						}
						else{
							start_node_index_string[j] = '0';
						}
						
					}
					start_node_index_string[parameter_output_bit_width] = '\0';
 					function_top_file << "function_layer_"<<start_node_depth<<"_nodes_"<<start_node_index_string<<"	part"<<i<<"	(.i(i),.o_index(o_"<<i<<"));"<<endl;
 				}
				function_top_file <<endl;
				for (int i = 0 ;i < parameter_output_bit_width;i++){
					int position_a = 0;
					for (int j=0;j<best_partition_parts;j++){
							if(best_partition_sets[j][i] == 1){
								position_a = j;
								break;
							}
					}
 					function_top_file << "assign	o["<<i<<"]	=	o_"<<position_a<<"["<<i<<"];"<<endl;
 				}
				function_top_file << "endmodule"<<endl;
				function_top_file.close();

				cout<<"###########################################################################"<<endl;
				if(merge_success)
					break;
			}
			if(merge_success)
				break;
		}
		if(use_part==(partition_parts-1))
			break;
	}
				
	cout<<"###########################################################################"<<endl;
	cout<<"Best Design Area:		"<<best_area<<endl;
				for (int i=0;i<best_partition_parts;i++){
					cout<<best_area_parts[i]<<endl;
				}

	cout<<"###########################################################################"<<endl;
	arr2d_delete(partition_sets,max_partition_parts);
	arr2d_delete(best_partition_sets,max_partition_parts);

	arr_delete( area_parts 	);
	arr_delete( best_area_parts 	);

	return 0;
};
int BSD_execute(int start_node_number, node_index* start_node_index,int variable_order_depth, int* variable_order){

	cout<<"BSD execute start"<<endl;	
	BDD_class BDD_class_main;
	cout<<"This variable order: "<<variable_order_depth<<endl;
	//BDD_class_main.output_partition_set 	= output_partition_set;
	BDD_class_main.which_demo_function 	= GLOBAL_which_demo_function;
	BDD_class_main.BSD_variable_order_depth = variable_order_depth;
	//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;
		for(int i=0;i<variable_order_depth;i++){
			BDD_class_main.BSD_variable_order[i] = variable_order[i];
			cout<<BDD_class_main.BSD_variable_order[i]<<" ";
		}
		cout<<endl;
	cout<<endl;


	BDD_class_main.start_depth 	= 0;	
	BDD_class_main.BDD_id 	= 0;
	BDD_class_main.how_many_start_nodes = start_node_number;
	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_node_index[zi].node_depth 		= start_node_index[zi].node_depth;
		BDD_class_main.start_node_index[zi].root_node_index 	= start_node_index[zi].root_node_index;
		for(int zj=0;zj<parameter_input_bit_width;zj++){
			BDD_class_main.start_node_index[zi].expand_input_bit_index[zj] = start_node_index[zi].expand_input_bit_index[zj];
			BDD_class_main.start_node_index[zi].expand_input_bit_data[zj]  = start_node_index[zi].expand_input_bit_data[zj];
		}
		BDD_class_main.start_nodes[zi].which_bit_output 	= start_node_index[zi].root_node_index;
		BDD_class_main.start_nodes[zi].which_root_node  	= start_node_index[zi].root_node_index;
		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 = 1000000;
	BDD_class_main.partition_parts = 1;

	BDD_class_main.BDD_FULL_PROCESS();

	for(int zi=0;zi<parameter_input_bit_width;zi++){
		variable_order[zi] = BSD_features_0.variable_order [zi] ;
	}
	double reward = search_reward(BSD_features_0);

	arr_delete(BDD_class_main.start_nodes) ;
	return reward;	

};

double search_reward(BSD_features BSD_features_0){
	double	reward = 0;//(1000000*double(1-BSD_features_0.accuracy));
	reward += BSD_features_0.BSD_area;
	if(BSD_features_0.accuracy <parameter_early_stop_accuracy)
		reward = int(1.2*reward) +int(1000000*double(1-BSD_features_0.accuracy)) + BSD_features_0.accuracy;
	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;	

};

double search_order(int start_node_number = default_start_node_number, int start_node_depth = 0, node_index* start_node_index = default_start_node_index,int search_iterations = parameter_search_iterations, int* start_order = default_start_order){
        
	arr2d_new(multi_variable_order,parameter_max_orders);
	//multi_variable_order = new int* [parameter_max_orders];
	for (int vi=0;vi<parameter_max_orders;vi++){
		multi_variable_order[vi] = new int [parameter_input_bit_width+1];
		for (int vj=0;vj<parameter_input_bit_width;vj++)
			multi_variable_order[vi][vj]=0;
	}

	double	best_area=9999999; 
	int	best_reward=9999999; 
	int	best_area_depth = 0;
	int**	best_variable_order;

	int*	best_BDD_split_nodes = new int [parameter_input_bit_width];
	double*	best_areas	= new double [parameter_max_orders];
	int*	best_rewards	= new int [parameter_max_orders];
	double*	best_area_depths= new double [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];
	arr2d_new(best_variable_order,parameter_max_orders);
	for (int vi=0;vi<parameter_max_orders;vi++){
		best_variable_order[vi] = new int [parameter_input_bit_width+1];
		for (int vj=0;vj<parameter_input_bit_width;vj++)
			best_variable_order[vi][vj]=0;
	}

	double 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;

	double best_area_0;
	double best_area_10;
	double best_area_100;
	double 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;
	cout<<"Start search order"<<endl;
	for (int i=0;i<search_iterations;i++){

				GLOBAL_BDD_id_number += 1;

	
		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<best_area_depth;vi++){
					multi_variable_order[vj][vi] = start_order[vi];
					cout<<multi_variable_order[vj][vi]<<" ";
				}
			}
			else{
				for(int vi=0;vi<max(best_area_depth,parameter_input_bit_width);vi++){
					multi_variable_order[vj][vi] = best_variable_order[vj][vi];
					cout<<multi_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 = multi_variable_order[vv][num_a];
			        	for (int vj=0;vj<num_b+num_c;vj++){
			        		if( (vj==(num_b+num_c-1))){
			            			multi_variable_order[vv][(num_a + vj)%int(best_area_depth)] =x;
			        		}
			        		else
			        			multi_variable_order[vv][(num_a + vj)%int(best_area_depth)] = multi_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;

		//}
		node_index* start_node_index_copy = new node_index [start_node_number];
		for(int zi=0;zi<start_node_number;zi++){
				start_node_index_copy[zi].node_depth 		= start_node_index[zi].node_depth;
				start_node_index_copy[zi].root_node_index 	= start_node_index[zi].root_node_index;
				for(int zj=0;zj<parameter_input_bit_width;zj++){
					start_node_index_copy[zi].expand_input_bit_index[zj] = start_node_index[zi].expand_input_bit_index[zj];
					start_node_index_copy[zi].expand_input_bit_data[zj]  = start_node_index[zi].expand_input_bit_data[zj];
				}

		}
		if (i<parameter_max_orders){
			//parameter_max_samples 		= int(parameter_max_samples/10);		//BSD每一个节点最多进行多少次采样
			reward = 	BSD_execute(start_node_number,start_node_index_copy,start_node_depth,multi_variable_order[order_num]);
			//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-1){
			parameter_early_stop_split_nodes = 9999999;
			reward = 	BSD_execute(start_node_number,start_node_index_copy,best_area_depth,best_variable_order[order_num]);
			break;
		}
		else{
			reward = 	BSD_execute(start_node_number,start_node_index_copy,best_area_depth,multi_variable_order[order_num]);
		}
		arr_delete(start_node_index_copy);
		#ifdef SEARCH_PARTITION
		#else
			char* start_node_index_string = new char [parameter_output_bit_width+1];
			ofstream function_top_file("rtl/function_top.v");
			for (int j=0;j<parameter_output_bit_width;j++){
					start_node_index_string[j] = '1';
			}
			start_node_index_string[parameter_output_bit_width] = '\0';
	 		function_top_file << "`include \"function_layer_"<<start_node_depth<<"_nodes_"<<start_node_index_string<<".v\" "<<endl;
			function_top_file << endl;
			function_top_file << "module function_top (i,o);"<<endl<<endl;
	 		function_top_file << "input 	["<<PI_WIDTH-1<<":0] i;"<<endl; 
	 		function_top_file << "output	["<<parameter_output_bit_width-1<<":0]  o;"<<endl<<endl;
			for (int i = 0 ;i < 1;i++){
	 			function_top_file << "wire	["<<parameter_output_bit_width-1<<":0]  o_"<<i<<";"<<endl;
	 		}
			function_top_file << endl;
				
	 		function_top_file << "function_layer_"<<start_node_depth<<"_nodes_"<<start_node_index_string<<"	part1	(.i(i),.o_index(o_1));"<<endl;
			function_top_file <<endl;
			for (int i = 0 ;i < parameter_output_bit_width;i++){
	 			function_top_file << "assign	o["<<i<<"]	=	o_1["<<i<<"];"<<endl;
	 		}
			function_top_file << "endmodule"<<endl;
			function_top_file.close();
			arr_delete(start_node_index_string);
		#endif

		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] = multi_variable_order[order_num][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] = multi_variable_order[order_num][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++){
				cout<<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);

	arr_delete( best_BDD_split_nodes );
	arr_delete( best_areas	);
	arr_delete( best_rewards)	;
	arr_delete( best_area_depths);
	arr2d_delete (multi_variable_order,parameter_max_orders);
	arr2d_delete(best_variable_order,parameter_max_orders);
	//arr2d_delete (best_variable_order,1);
	//delete [] best_variable_order[0];
	//for(int i=0;i<parameter_input_bit_width;i++)
	//	cout<<best_variable_order[0][i];
	//delete [] best_variable_order[0];
	//delete [] best_variable_order;
	
	return reward;
};

