/********************************************************************************************
gainLossOptimizer
*********************************************************************************************/
gainLossOptimizer::gainLossOptimizer(tree& tr, stochasticProcess* sp, const sequenceContainer &sc,
									 const MDOUBLE epsilonOptimization, const int numIterations,
									 const MDOUBLE epsilonOptimizationModel, const int numIterationsModel,
									 const MDOUBLE epsilonOptimizationBBL, const int numIterationsBBL,
									 Vdouble*  weights,
									 unObservableData* unObservableData_p, bool performOptimizationsBBL, bool isbblLSWhenbblEMdontImprove):
_tr(tr),_sp(sp),_sc(sc),
_epsilonOptimization(epsilonOptimization),_maxNumOfIterations(numIterations),
_epsilonOptimizationModel(epsilonOptimizationModel),_maxNumOfIterationsModel(numIterationsModel),
_epsilonOptimizationBBL(epsilonOptimizationBBL),_maxNumOfIterationsBBL(numIterationsBBL),
_weightsUniqPatterns(weights),
_unObservableData_p(unObservableData_p),_performOptimizationsBBL(performOptimizationsBBL),
_isbblLSWhenbblEMdontImprove(isbblLSWhenbblEMdontImprove)
{
	//gainLossOptions::distributionType rateDistributionType = getRateDistributionType(sp->distr());
	//_weights = gainLossOptions::_weights;			// since - no weights are used over positions
	_isReversible = !dynamic_cast<gainLossModelNonReversible*>(_sp->getPijAccelerator()->getReplacementModel());
	_isSkipBblEM = false; // will change to T if like is not improved by BBL-EM
	_freq.resize(_sc.alphabetSize());
	optimizations();
}
Example #2
0
int main(int argc, char* argv[]) {
	if(argc != 2) {
		std::cout << "Usage: " << argv[0] << " /path/to/lua/script.lua" << std::endl;
		exit(1);
	}

	std::cout.unsetf(std::ios::floatfield);
	std::cout.precision(5);
	std::cout << std::fixed;

	std::cout << "==================== SETUP ====================" << std::endl;

	// TODO: detect unusual currency bases for accurate profit calculation

	auto config = std::make_shared<LuaScript>(argv[1]);

	std::cout << "Simulating a maximum of " << config->steps() << " steps" << std::endl;
	std::cout << config->optimizations() << " optimizations per in sample" << std::endl;

	auto charts = Chart::load_from_string(config->charts());
	auto ts = std::make_unique<TickSource>(config->csv_path());
	auto vars = Variable::load_from_string(config->variables());
	auto optimizer = std::make_unique<Optimizer>(vars);

	ts->fill_charts(charts);
	ts->advance_charts_to_next_sunday(charts);

	int step_number = 1;
	int weeks_in_sample = std::stoi(config->in_sample_time());
	int weeks_out_of_sample = std::stoi(config->out_of_sample_time());

	std::vector<float> optimization_scores;
	std::vector<float> execution_scores;

	// ----- MAIN LOOP -------------------------------------------------------------------------

	for(;;) {
		// ----- FIND IN AND OUT OF SAMPLE START AND END POINTS ----------------------------

		// in_sample_record_end is just out_of_sample_record_start - 1
		unsigned long in_sample_record_start = ts->next_record_id();
		unsigned long out_of_sample_record_start = 0;
		unsigned long out_of_sample_record_end = 0;

		bool tick_is_sunday = true;
		bool on_sunday = true;
		int sundays_seen = 0;

		for(auto tick = ts->next(); tick; tick = ts->next()) {
			tick_is_sunday = tick->is_sunday();

			if(!on_sunday && tick_is_sunday) {
				on_sunday = true;
				sundays_seen++;
			} else if(on_sunday && !tick_is_sunday) {
				on_sunday = false;
			}

			if(sundays_seen == weeks_in_sample) {
				out_of_sample_record_start = ts->next_record_id() - 1;
				break;
			}
		}

		if(!out_of_sample_record_start) {
			bail("ran out of tick source when searching for out of sample start");
		}

		sundays_seen = 0;
		on_sunday = true;

		for(auto tick = ts->next(); tick; tick = ts->next()) {
			tick_is_sunday = tick->is_sunday();

			if(!on_sunday && tick_is_sunday) {
				on_sunday = true;
				sundays_seen++;
			} else if(on_sunday && !tick_is_sunday) {
				on_sunday = false;
			}

			if(sundays_seen == weeks_out_of_sample) {
				// stop on the tick before the current tick
				out_of_sample_record_end = ts->next_record_id() - 2;
				break;
			}
		}

		if(!out_of_sample_record_end) {
			bail("ran out of tick source when searching for out of sample end");
		}

		std::cout << "In sample: " << ts->peek_at(in_sample_record_start)->show()
			<< " through " << ts->peek_at(out_of_sample_record_start - 1)->show()
			<< std::endl;

		std::cout << "Out of sample: " << ts->peek_at(out_of_sample_record_start)->show()
			<< " through " << ts->peek_at(out_of_sample_record_end)->show()
			<< std::endl;

		// ----- OPTIMIZE ON IN SAMPLE PERIOD ----------------------------------------------

		auto subset = ts->subset(in_sample_record_start, out_of_sample_record_start - 1);

		auto winner = optimizer->optimize_variables_on(config, charts, subset);
		// optimizer->print_scores();

		// ----- IF OPTIMIZATION SUCCEEDED, EXECUTE ON OUT OF SAMPLE PERIOD ----------------

		if(winner->get_score() < config->minimum_optimization_score()) {
			bail("Failed to find a variables above the cutoff");
		}

		optimization_scores.push_back(winner->get_score());

		std::cout << "==================== EXECUTING ON ====================" << std::endl;
		std::cout << "Winning variables!" << std::endl;
		std::cout << "Score: " << winner->get_score() << std::endl;
		for(auto var: winner->get_variables()) {
			std::cout << "\t" << var->get_name() << " -> " << var->show() << std::endl;
		}

		auto new_vars = winner->get_variables();
		auto new_config = config;
		auto new_charts = charts;

		auto oos = ts->subset(out_of_sample_record_start, out_of_sample_record_end);

		Simulation sim(new_config, new_charts, new_vars);
		sim.run(oos);

		std::cout << "Execution score: " << sim.get_score() << std::endl;
		std::cout << "% profitable: " << sim.percentage_of_profitable_trades()
			<< "%" << std::endl;
		std::cout << "Average trade duration: " << sim.average_trade_duration() << std::endl;
		std::cout << "Worst DD: " << sim.get_worst_drawdown() << "%" << std::endl;
		std::cout << "Equity high: " << sim.get_equity_high() << std::endl;
		std::cout << "Equity low: " << sim.get_equity_low() << std::endl;
		std::cout << "Trades: " << sim.get_trade_count() << std::endl;
		std::cout << "Winners: " << sim.get_winning_trade_count() << std::endl;
		std::cout << "Losers: " << sim.get_losing_trade_count() << std::endl;
		std::cout << "Best: " << sim.best_winning_trade()->profit() << std::endl;
		std::cout << "Worst: " << sim.worst_losing_trade()->profit() << std::endl;

		// ----- IF EXECUTION SUCCEEDED, RECORD RESULTS ------------------------------------

		if(sim.get_score() < config->minimum_execution_score()) {
			bail("Failed at optimization step");
		}

		execution_scores.push_back(sim.get_score());

		// ----- EXIT IF WE'RE AT MAX STEPS ------------------------------------------------

		step_number++;

		if(step_number > config->steps()) {
			std::cout << "Reached max steps, breaking" << std::endl;
			break;
		}

		// ----- ADVANCE CHARTS TO NEXT IN SAMPLE START ------------------------------------

		ts->seek_to_record(in_sample_record_start);
		ts->advance_charts_to_next_sunday(charts);
	}

	std::cout << "==================== RESULTS ====================" << std::endl;

	// ----- SHOW PROFIT FOR EACH PERIOD -------------------------------------------------------

	std::cout << "Scores:" << std::endl;

	for(unsigned long i = 0; i < optimization_scores.size(); i++) {
		std::cout << i + 1 << " - ";
		std::cout << "Opti: " << optimization_scores[i];
		std::cout << " - ";
		std::cout << "Exec: " << execution_scores[i];
		std::cout << std::endl;
	}

	// ----- SHOW WALK FORWARD EFFICIENCY ------------------------------------------------------

	float optimization_total = sum_vector(optimization_scores);
	float execution_total = sum_vector(execution_scores);
	float efficiency = execution_total / optimization_total;

	std::cout << "Optimization total: " << optimization_total << " - ";
	std::cout << "Execution total: " << execution_total << " - ";
	std::cout << "WFA efficiency: " << efficiency << "% - Verdict: ";

	if(efficiency < 0.5) {
		std::cout << "FAIL";
	} else if(efficiency >= 0.5 && efficiency < 1.0) {
		std::cout << "ACCEPTABLE";
	} else if(efficiency >= 1.0 && efficiency <= 1.5) {
		std::cout << "GREAT";
	} else {
		std::cout << "TOO GOOD - SUSPICIOUS";
	}

	std::cout << std::endl;

	// ----- SHOW PROFIT FACTOR ----------------------------------------------------------------

	float gross_profit = 0.0;
	float gross_loss   = 0.0;

	for(auto score: execution_scores) {
		if(score >= 0.0)
			gross_profit += score;
		else
			gross_loss += score;
	}

	gross_loss = std::abs(gross_loss);

	float profit_factor = gross_profit / gross_loss;

	std::cout << "Gross profit: " << gross_profit << " - ";
	std::cout << "Gross loss: " << gross_loss << " - ";
	std::cout << "Profit factor: " << profit_factor << " - Verdict: ";

	if(profit_factor < 1.5) {
		std::cout << "FAIL";
	} else if(profit_factor >= 1.5 && profit_factor < 2.0) {
		std::cout << "ACCEPTABLE";
	} else if(profit_factor >= 2.0 && profit_factor <= 3.0) {
		std::cout << "GREAT";
	} else {
		std::cout << "TOO GOOD - SUSPICIOUS";
	}

	std::cout << std::endl;

	// ----- SHOW FINAL SCORE ------------------------------------------------------------------

	// TODO: final score should be some function of two or more of the following:
	//       execution_total, WFA efficiency, max drawdown, profit factor, % profitable

	std::cout << "Final score: " << execution_total << " - Minimum score: "
		<< config->minimum_overall_score() << " - Verdict: ";

	std::cout << (execution_total >= config->minimum_overall_score() ? "PASS" : "FAIL") << std::endl;

	std::cout << "==================== SHUTDOWN ====================" << std::endl;

	return 0;
}
Example #3
0
void compile(boost::program_options::variables_map vm,
			 string out_file_name,
			 string routine_name,
			 map<string,type*>& inputs,
			 map<string,type*>& inouts,
			 map<string,type*>& outputs,
			 vector<stmt*> const& prog)
{
    // set up signal to end search after certain amount of time
    int sMinutes = vm["limit"].as<int>();
    if (sMinutes > 0) {
        int sSeconds = sMinutes * 60;
        signal(SIGALRM, sig_alarm_handler);
        alarm(sSeconds);
    }
    
	// search strategy
	enum search_strategy {exhaustive, orthogonal, random, 
		hybrid_orthogonal, ga, debug, thread};

	search_strategy strat = ga;
	if (vm["search"].as<std::string>().compare("ex") == 0) {
		strat = exhaustive;
	} 
    else if (vm["search"].as<std::string>().compare("debug") == 0) {
		strat = debug;
	}
	else if (vm["search"].as<std::string>().compare("orthogonal") == 0) {
		strat = orthogonal;
	}
	else if (vm["search"].as<std::string>().compare("random") == 0) {
		strat = random;
	}
	else if (vm["search"].as<std::string>().compare("hybrid_orthogonal") == 0) {
		strat = hybrid_orthogonal;
	}
	else if (vm["search"].as<std::string>().compare("ga") == 0) {
		strat = ga;
	}
    else if (vm["search"].as<std::string>().compare("thread") == 0) {
        strat = thread;
    }
	else {
		std::cout << "Error: unknown search strategy (--search):" << vm["search"].as<std::string>() << "\n\n";
		exit(0);
	}
	
	// which backend
	bool noptr;
	if (vm["backend"].as<std::string>().compare("noptr") == 0) {
		noptr = true;
	} else {
		noptr = false;
	}
	std::cout << noptr << std::endl;
	
	// partitiong FIXME can't turn off anymore?
	/*
	bool partitionSet = true;
	if (vm.count("partition_off")) {
		partitionSet = false;
	}
	*/

	bool mpi = false;
	if (vm.count("distributed")) {
		mpi = true;
	}
	
	string pathToTop = getcwd(NULL,0);	
	pathToTop += "/";
	// std::cout << pathToTop << std::endl;
	
	// set up temporary workspace
	string tmpPath, fileName, path;
	if (setUpWorkSpace(out_file_name, fileName, path, tmpPath, pathToTop,
                       vm.count("delete_tmp"))) {
		std::cout << "Failed to set up temporary directory for unique implementations\n";
		return;
	}
	
	// set all work to be performed in temporary work directory
	out_file_name = tmpPath + fileName;
	
	
	// {{{ COST MODELS
	std::list<versionData*> orderedVersions;
	string testParam = vm["test_param"].as<std::string>();
	string start, stop, step;
	
	string::size_type pos = testParam.find_first_of(":");
	if (pos != string::npos)
		start = testParam.substr(0, pos);
	string::size_type last = pos+1;
	pos = testParam.find_first_of(":",last);
	if (pos != string::npos)
		stop = testParam.substr(last, pos-last);
	step = testParam.substr(pos+1,string::npos);
	
	if (boost::lexical_cast<int>(start) > boost::lexical_cast<int>(stop)) {
		std::cout << "Test parameters are illegal (start > stop)\n";
		std::cout << "\tstart: " << start << "\n";
		std::cout << "\tstop:  " << stop << "\n";
		return;
	}
	
	modelMsg msg(boost::lexical_cast<int>(start),
				 boost::lexical_cast<int>(stop),
				 boost::lexical_cast<int>(step));
	msg.pathToTop = pathToTop;
	// build_machine 0 -> parallel, 1 -> serial
	// msg.parallelArch = build_machine((char*)(pathToTop.c_str()),0);
	if (msg.parallelArch == NULL) {
		std:: cout << "Error attempting to get cost with parallel analytic model\n";
		//return;
	}
	// msg.serialArch = build_machine((char*)(pathToTop.c_str()),1);
	// if (msg.serialArch == NULL) {
		// std:: cout << "Error attempting to get cost with parallel analytic model\n";
		//return;
	// }
	
	// analyticSerial, tempCount, analyticParallel, symbolic, noModel			
	vector<model_typ> models;
	models.clear();
	// the model we want to rank with should go first in this list
	//models.push_back(noModel);
	models.push_back(analyticParallel);
	//models.push_back(analyticSerial);
	//models.push_back(tempCount);
	// }}}
	
	
	precision_type = vm["precision"].as<std::string>();
	
#ifdef MODEL_TIME
	// time spent in memmodel routines
	boost::timer memmodelTimer;
	double memmodelTotal = 0.0;
#endif
	
	
	/* Model deprecated
	double threshold;
	if (vm.count("use_model")) {
		std::cout << "\nAnalytic model enabled\n";
		threshold = vm["threshold"].as<double>();
	}
	*/
	
	std::vector<std::pair<int, double> >::iterator itr;
    
	graph g;
	
	std::vector<algo> algos;
	//std::cerr << "finished parsing" << std::endl;
	program2graph(prog, inputs, inouts, outputs, g);  
	//std::cerr << "graph created" << std::endl;
    //std::ofstream out44("lower0.dot");
    //print_graph(out44, g);
	//out44.close();
	//use yices to compute types externally
//#define TYPES
#ifdef TYPES
    std::ofstream out("lower0.dot");
    print_graph(out, g); 
	out.close();
    generate_constraints(g);
#endif
	compute_types(g);
#ifdef TYPES
    std::ofstream out("lower1.dot");
    print_graph(out, g);
	out.close();
    exit(0);
#endif
    
	update_sizes(g);
	update_dim_info(g);
    
	init_algos(algos);
		
	assign_algorithms(algos, g);
	//std::cerr << "algorithms assigned" << std::endl;
	
	assign_work(algos, g);
	//std::cerr << "work assigned" << std::endl;
	
	rewrite_fun rewriters[] =
    {	flip_transpose,                 //0
		flip_transpose_stride,          //1
		merge_tmp_output,               //2
		merge_tmp_cast_output,          //3
		remove_intermediate_temporary,  //4
		merge_gets,                     //5
		merge_sumto_store,              //6
		move_temporary,                 //7
		remove_cast_to_output,          //8
		remove_input_to_cast,           //9
		remove_cast_to_cast,            //10
		merge_same_cast,                //11
        straighten_top_level_scalar_ops,//12
        reduce_reductions               //13
    };
	
	optim_fun optimizers[] =
    {	fuse_loops,			//0
		fuse_loops_nested,	//1
		merge_scalars,		//2
		pipeline,			//3
        fuse_loops_n        //4
    };

	optim_fun_chk checkers[] =
    {	check_fuse_loops, 
		check_fuse_loops_nested,
		check_merge_scalars,
		check_pipeline,
        check_fuse_loops_n
    };
	
	partition_fun partition[] = {
		part_mult_left_result,	//0
		part_mult_right_result,	//1
		part_mult_left_right, 	//2
		part_mult_scl_row,		//3
		part_mult_scl_col,		//4
		partition_add_col,		//5
		partition_add_row,		//6
		part_mult_scl,			//7
		partition_add			//8
	};
	rewrite_fun part_checkers[] = {
		check_part_mult_left_result,
		check_part_mult_right_result,
		check_part_mult_left_right,
		check_part_mult_scl_row,
		check_part_mult_scl_col,
		check_partition_add_col,
		check_partition_add_row,
		check_part_mult_scl,
		check_partition_add
	};
	
	vector<rewrite_fun> rewrites(rewriters, rewriters + 
								 sizeof(rewriters) / sizeof(rewrite_fun));
	
	vector<optim_fun> optimizations(optimizers, optimizers + 
									sizeof(optimizers) / sizeof(optim_fun));
	vector<optim_fun_chk> checks(checkers, checkers + 
								 sizeof(checkers) / sizeof(optim_fun_chk));
	vector<rewrite_fun> part_checks(part_checkers, part_checkers + 
									sizeof(part_checkers)/sizeof(rewrite_fun));
	vector<partition_fun> partitioners(partition, partition +
									 sizeof(partition) / sizeof(partition_fun));
	
	//std::cerr << "about to start lowering and optimizine" << std::endl;
	
	std::stack<work_item> s;
	string history = "";
	
#ifdef DUMP_DOT_FILES
  	std::ofstream out("lower1.dot");
	print_graph(out, g);
	out.close();
#endif
	
#ifdef DUMP_GRAPHS
	graphToQuery(g,out_file_name,0,0);
#endif
	
	if (vm.count("correctness")) {
		createCorrectnessTest(g, routine_name, out_file_name, inputs, 
                              outputs,msg,noptr);
	}
	
	// keep copy of base graph around
	graph *baseGraph = new graph(g);

	// {{{ Partition Space
	code_generation codetype = threadtile;
	string spec = vm["level1"].as<std::string>();
	if (!spec.empty()) {
		string::size_type pos = spec.find_first_of(" ");
		if (pos == string::npos) {
			std::cout << "Bad format for level1 arg:" << spec << endl;
			exit(0);
		} else {
			string codetype_str = spec.substr(0, pos);
			if (codetype_str == "thread") {
				codetype = threadtile;
			} else if (codetype_str == "cache") {
				codetype = cachetile;
			} else {
				std::cout << "Bad format for level1 arg:" << spec << endl;
				std::cout << "needs to be thread or cache" << endl;
				exit(0);
			}
		}
		int err = parse_range(&partition_bounds[0][0], 
				&partition_bounds[0][1],
				&partition_bounds[0][2],
				spec.substr(pos+1));
		if (err) {
			std::cout << "Couldn't parse range for level1: " << spec << endl;
			exit(0);
		}
		if (partition_bounds[0][0] > partition_bounds[0][1]) {
			std::cout << "Test parameters are illegal (start > stop)\n";
			std::cout << "\tstart: " << partition_bounds[0][0] << "\n";
			std::cout << "\tstop:  " << partition_bounds[0][1] << "\n";
			exit(0);
		}

		// Now level 2
		string spec = vm["level2"].as<std::string>();
		std::cout << "spec:" << spec << endl;
		if (!spec.empty()) {
			MAX_PARTS = 2;
			string::size_type pos = spec.find_first_of(" ");
			cout << "pos = " << pos << endl;
			if (pos == string::npos) {
				std::cout << "Bad format for level2 arg:" << spec << endl;
				exit(0);
			} else {
				string codetype_str = spec.substr(0, pos);
				cout << "codetype_str: '" << codetype_str << "'" << endl;
				if (codetype_str == "thread" && codetype==cachetile) {
					std::cout << "ERROR: threads inside tile loops not supported" << endl;
					std::cout << "consider swapping level1 and level2 args" << endl;
					exit(0);
				} else if (codetype_str == "cache" && codetype==threadtile) {
					codetype = bothtile;
				} else {
					std::cout << "Bad format for level2 arg:" << spec << endl;
					std::cout << "needs to be thread or cache" << endl;
					exit(0);
				}
			}
			int err = parse_range(&partition_bounds[1][0], 
					&partition_bounds[1][1],
					&partition_bounds[1][2],
					spec.substr(pos+1));
			if (err) {
				std::cout << "Couldn't parse range for level2: " << spec.substr(pos) << endl;
				exit(0);
			}
			if (partition_bounds[1][0] > partition_bounds[1][1]) {
				std::cout << "Test parameters are illegal (start > stop)\n";
				std::cout << "\tstart: " << partition_bounds[1][0] << "\n";
				std::cout << "\tstop:  " << partition_bounds[1][1] << "\n";
				exit(0);
			}
		} else {
			// Only 1 level specified
			MAX_PARTS = 1;
		}
	} else {
		// no idea what this will do!
		// Maybe we should just throw an error here?  Or at least a warning?
		std::cout << "WARNING: No threading or cache tiling specified" << endl;
		std::cout << "Performing Loop fusion only, search may get confused" << endl;
		MAX_PARTS = 0;
	}

	// }}}

	// initializing the partition type forest
	// cout << "initializing partition forest..." << endl;
	vector< partitionTree_t* > partitionForest;
    buildForest(partitionForest, g, MAX_PARTS);
	// cout << "success" << endl;

	/*
	for (int i = 0; i < partitionForest.size(); ++i) {
		partitionTree_t *t = partitionForest[i];
		if (t != NULL) {
			stringstream o;
			o << "tree" << i << ".dot";
			ofstream treefile(o.str().c_str());
			printTree(treefile, t);
		}
	}
	*/

	initial_lower(g, algos, rewrites);
	//std::cout << "finished lowering and rewriting" << std::endl;
	
#ifdef DUMP_DOT_FILES
  	std::ofstream out2("lower2.dot");
	print_graph(out2, g);
	out2.close();
#endif
	
#if 0
    for (int i = 0; i < g.num_vertices(); ++i)
        if (g.info(i).op & OP_ANY_ARITHMATIC)
            cout << i << "\t";
    cout << "\n";
#endif
    
	int reps = vm["empirical_reps"].as<int>();
	if (vm.count("distributed")) {
		createMPIEmpiricalTest(g, routine_name, out_file_name, inputs,
                               outputs, noptr, reps);
	} else if (!vm.count("empirical_off")) {
		createEmpiricalTest(g, routine_name, out_file_name, inputs,
                            outputs, noptr, reps);
	}
	
    compile_details_t cDetails(routine_name,tmpPath,fileName,
                               vm.count("correctness"), 
                               vm.count("use_model"),
                               !vm.count("empirical_off"),
                               noptr, mpi, codetype,
                               &inputs, &inouts, &outputs);
    
    build_details_t bDetails(&part_checks, &partitioners,
                             &checks, &optimizations,
                             &algos, &rewrites,
                             &models, &msg);

	// int maxT = max(0,msg.parallelArch->threads);
	// std::cout << "Testing with " << maxT << " threads, step = " << min(4,maxT) << std::endl;
	// int stride = 2;
    
	// {{{ Strategy cases
	switch (strat) {
		case exhaustive:
		{
			std::cout << "entering exhaustive search" << endl;
			//int numVersions = 5;
			int bestVersion = smart_exhaustive(g, *baseGraph, 
                                               cDetails, bDetails);
			// One way or another we have selected a version we are calling the best
			// or we failed
			if (bestVersion < 0) {
				std::cout << "All versions failed to generate or compile\n";
				return;
			}
			else {
				std::cout << "\n----------------------------------\n";
				std::cout << "Best Version: " << fileName + "__" << bestVersion << ".c\n";
			}
			
			// copy best version to same directory as input .m file
			// and report location
			handleBestVersion(fileName,path,tmpPath,bestVersion);
			break;
		}
		case orthogonal:
		{
			std::cout << "entering orthogonal search" << endl;
			//int numVersions = 5;
			int bestVersion = orthogonal_search(g, *baseGraph, 
                                                cDetails, bDetails);
			// One way or another we have selected a version we are calling the best
            
			// or we failed
			if (bestVersion < 0) {
				std::cout << "All versions failed to generate or compile\n";
				return;
			}
			else {
				std::cout << "\n----------------------------------\n";
				std::cout << "Best Version: " << fileName + "__" << bestVersion << ".c\n";
			}
			
			// copy best version to same directory as input .m file
			// and report location
			handleBestVersion(fileName,path,tmpPath,bestVersion);
			break;
		}
		case random:
		{
			std::cout << "entering random search" << endl;
			int seconds = vm["random_count"].as<int>();
			int bestVersion = genetic_algorithm_search(g, *baseGraph,
				partitionForest, 
				seconds, 1, false, cDetails, bDetails).best_version; // pop = 1
			// One way or another we have selected a version we are calling the best
			// or we failed
			if (bestVersion < 0) {
				std::cout << "All versions failed to generate or compile\n";
				return;
			}
			else {
				std::cout << "\n----------------------------------\n";
				std::cout << "Best Version: " << fileName + "__" << bestVersion << ".c\n";
			}
			
			// copy best version to same directory as input .m file
			// and report location
			handleBestVersion(fileName,path,tmpPath,bestVersion);
			break;
		}
		case hybrid_orthogonal:
		{
			std::cout << "entering hybrid orthogonal search " << endl;
			int bestVersion = smart_hybrid_search(g, *baseGraph, 
                                                  cDetails, bDetails);
			// One way or another we have selected a version we are calling the best
			// or we failed
			if (bestVersion < 0) {
				std::cout << "All versions failed to generate or compile\n";
				return;
			}
			else {
				std::cout << "\n----------------------------------\n";
				std::cout << "Best Version: " << fileName + "__" << bestVersion << ".c\n";
			}
			
			// copy best version to same directory as input .m file
			// and report location
			handleBestVersion(fileName,path,tmpPath,bestVersion);
			break;
		}
		case debug:
		{
			std::cout << "entering debug search " << endl;
			int bestVersion = debug_search(g, *baseGraph, partitionForest,
											cDetails, bDetails);
			// One way or another we have selected a version we are calling the best
			// or we failed
			if (bestVersion < 0) {
				std::cout << "All versions failed to generate or compile\n";
				return;
			}
			else {
				std::cout << "\n----------------------------------\n";
				std::cout << "Best Version: " << fileName + "__" << bestVersion << ".c\n";
			}
			
			// copy best version to same directory as input .m file
			// and report location
			handleBestVersion(fileName,path,tmpPath,bestVersion);
			break;
		}
		case ga:
		{
			std::cout << "entering genetic algorithm search " << endl;
			bool gamaxfuse = true;
			if (vm.count("ga_nomaxfuse")) {
				gamaxfuse = false;
			}
			int seconds = vm["ga_timelimit"].as<int>();
			int popsize = vm["ga_popsize"].as<int>();
			int bestVersion = -1;
			if (vm.count("ga_noglobalthread")) {
				bestVersion = genetic_algorithm_search(g, *baseGraph,
					partitionForest, seconds, popsize, gamaxfuse, 
					cDetails, bDetails).best_version;
			} else if (vm.count("ga_exthread")) {
				bestVersion = ga_exthread(g, *baseGraph,
						 partitionForest, seconds, gamaxfuse, popsize, cDetails,
						 bDetails);
			} else { // global thread
				bestVersion = ga_thread(g, *baseGraph,
						 partitionForest, seconds, gamaxfuse, popsize, cDetails,
						 bDetails);
			}
			// One way or another we have selected 
			// a version we are calling the best
			// or we failed
			if (bestVersion < 0) {
				std::cout << "All versions failed to generate or compile\n";
				return;
			}
			else {
				std::cout << "\n----------------------------------\n";
				std::cout << "Best Version: " << fileName + "__" << bestVersion << ".c\n";
			}
			
			// copy best version to same directory as input .m file
			// and report location
			handleBestVersion(fileName,path,tmpPath,bestVersion);
			break;
		}
            
        case thread:
		{
            int thread_search(graph &g, graph &baseGraph, 
                              vector<partitionTree_t*> part_forest,
                              compile_details_t &cDet,
                              build_details_t &bDet);
			std::cout << "entering thread search " << endl;
			thread_search(g, *baseGraph, partitionForest,
                                           cDetails, bDetails);

			break;
		}
	}
	// }}}
    
    deleteForest(partitionForest);
}