/// Local search method: heuristic to locally improve a solution; usually this is not /// part of the base version of the algorithms, but it is used to improve the algorithms /// as hibridize them. Note that during local search we might decide to add some non-dominated /// solutions to the external non-dominated set. // Note that it might be useful to specify /// the number of solutions examined in the local search, otherwise we might end up spending /// too much time in the local search function. The k neighbour solutions to be examined are /// randomly chosen. We used the local search as described in Murata's paper. /// In case a linear scalarizing function is used, the direction of the local search is given /// by the weights of the function. /// TODO: set max number of moves that I want to perform durin local search void TDSESolution::LocalSearch(TPoint & ReferencePoint, TNondominatedSet & NondominatedSet){ /// I do not want to spend too much time in local search, otherwise I /// loose the effectiveness of the rest of the algorithm; /// lets say that for each parameter I try to move forward or backward /// with respect to the current position; for each intermediate solution found /// I also check if it is non-dominated and, in case, I add it to the non-dominated set double currentOptimalValue = TSolution::ScalarizingFunction(ReferencePoint); boost::uniform_int<> degen_dist(0, 1); boost::variate_generator<boost::minstd_rand&, boost::uniform_int<> > deg(Problem.generator, degen_dist); std::map<std::string, std::string>::iterator solIter, solEnd; for(solIter = this->param2Value.begin(), solEnd = this->param2Value.end(); solIter != solEnd; solIter++){ // First I save the old solution std::map<std::string, std::string> oldSolution = this->param2Value; SaveObjectiveValues(); // I now randomly choose whether to take the value from the first or the second parent if(deg() == 0) solIter->second = TDSESolution::findPrevious(solIter->first, solIter->second); else solIter->second = TDSESolution::findSuccessive(solIter->first, solIter->second); if(this->param2Value[solIter->first] != this->oldSolution[solIter->first]) this->updateObjectives(); double newObjValue = TSolution::ScalarizingFunction(ReferencePoint); // Now I check to see if the current solution is a non dominated one this->addToNonDominated(NondominatedSet); if(newObjValue < currentOptimalValue) break; else{ this->param2Value = oldSolution; RestoreObjectiveValues(); } } }
//Simple systemc thread which keeps on generating interrupts; //the number of the interrupt is printed to the screen before sending it to //the processor void generateIrq() { while(true) { //An interrupt transaction is composed of a data pointer (containing //0 if the interrupt has to be lowered, different if raised) and an //address, corrisponding to the ID of the interrupt if(this->lastIrq == -1) { unsigned char data = 1; tlm::tlm_generic_payload trans; boost::uniform_int<> degen_dist(0x1, 0xe); boost::variate_generator<boost::minstd_rand&, boost::uniform_int<> > deg(this->generator, degen_dist); this->lastIrq = deg(); std::cerr << "Sending out IRQ id=" << std::hex << std::showbase << this->lastIrq << std::endl; trans.set_address(this->lastIrq); trans.set_data_ptr(&data); trans.set_data_length(0); trans.set_byte_enable_ptr(0); trans.set_dmi_allowed(false); trans.set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); sc_time delay; this->init_socket->b_transport(trans, delay); if(trans.is_response_error()) { std::string errorStr("Error in generateIrq, response status = " + trans.get_response_string()); SC_REPORT_ERROR("TLM-2", errorStr.c_str()); } } wait(this->latency); } }
void TDSESolution::createRandom(TDSESolution &solution){ std::map<std::string, std::vector<std::string> >::iterator paramsIter, paramsEnd; for(paramsIter = Problem.parameters.begin(), paramsEnd = Problem.parameters.end(); paramsIter != paramsEnd; paramsIter++){ boost::uniform_int<> degen_dist(0, paramsIter->second.size() - 1); boost::variate_generator<boost::minstd_rand&, boost::uniform_int<> > deg(Problem.generator, degen_dist); solution.param2Value[paramsIter->first] = paramsIter->second[deg()]; } }
Int Primes::GenPrime(Int size, boost::mt19937 *randNumGen) { Int beg = 1; boost::uniform_int<> degen_dist(1 << (size-1), 1 << size); boost::variate_generator<boost::mt19937&, boost::uniform_int<> > sampler(*randNumGen, degen_dist); beg = sampler(); beg = NextPrime(beg); return beg; }
/// Mutates the solution; this method is used by the NSGA and SPEA algorithms. The mutation /// consists in a random change of a random parameter of the solution. Note that mutation is not /// necessary; we might configure the probability of performing it. /// TODO: set probability of mutation void TDSESolution::Mutate(){ /// I randomly choose one parameter and randomly choose the value for this parameter; /// then I change the value boost::uniform_int<> params_dist(0, this->param2Value.size() - 1); boost::variate_generator<boost::minstd_rand&, boost::uniform_int<> > params_generator(Problem.generator, params_dist); std::map<std::string, std::string>::iterator solIter = this->param2Value.begin(); unsigned int randomParam = params_generator(); for(unsigned int i = 0; i < randomParam; solIter++, i++); // I now randomly choose whether to take the value from the first or the second parent boost::uniform_int<> degen_dist(0, Problem.parameters[solIter->first].size() - 1); boost::variate_generator<boost::minstd_rand&, boost::uniform_int<> > deg(Problem.generator, degen_dist); solIter->second = Problem.parameters[solIter->first][deg()]; this->updateObjectives(); }
/// Given two parents it composed them into solution void TDSESolution::crossSolution(TDSESolution & solution, TDSESolution & Parent1, TDSESolution & Parent2){ // I simply take a random element among the two solutions and create the new solution // which is a combination of the two boost::uniform_int<> degen_dist(0, 1); boost::variate_generator<boost::minstd_rand&, boost::uniform_int<> > deg(Problem.generator, degen_dist); std::map<std::string, std::string>::iterator solIter, solEnd; for(solIter = Parent1.param2Value.begin(), solEnd = Parent1.param2Value.end(); solIter != solEnd; solIter++){ //I now randomly choose whether to take the value from the first or the second parent if(deg() == 0) solution.param2Value[solIter->first] = solIter->second; else solution.param2Value[solIter->first] = Parent2.param2Value[solIter->first]; } }
/// We perform a single random local move; method used by PSA, SMOSA, MOSA. /// This method actually performs the move; in case the move has to be undone, /// the RejectLocalMove method is called. void TDSESolution::FindLocalMove(){ /// I simply choose randomly one parameter and the direction (whether to /// increment or decrement the value) boost::uniform_int<> params_dist(0, this->param2Value.size() - 1); boost::variate_generator<boost::minstd_rand&, boost::uniform_int<> > params_generator(Problem.generator, params_dist); std::map<std::string, std::string>::iterator solIter = this->param2Value.begin(); unsigned int randomParam = params_generator(); for(unsigned int i = 0; i < randomParam; solIter++, i++); // First I save the old solution this->oldSolution = this->param2Value; SaveObjectiveValues(); // I now randomly choose whether to take the value from the first or the second parent boost::uniform_int<> degen_dist(0, 1); boost::variate_generator<boost::minstd_rand&, boost::uniform_int<> > deg(Problem.generator, degen_dist); if(deg() == 0) solIter->second = TDSESolution::findPrevious(solIter->first, solIter->second); else solIter->second = TDSESolution::findSuccessive(solIter->first, solIter->second); if(this->param2Value[solIter->first] != this->oldSolution[solIter->first]) this->updateObjectives(); }
int main() { // Define a random number generator and initialize it with a reproducible // seed. base_generator_type generator(42); std::cout << "10 samples of a uniform distribution in [0..1):\n"; // Define a uniform random number distribution which produces "double" // values between 0 and 1 (0 inclusive, 1 exclusive). boost::uniform_real<> uni_dist(0,1); boost::variate_generator<base_generator_type&, boost::uniform_real<> > uni(generator, uni_dist); std::cout.setf(std::ios::fixed); // You can now retrieve random numbers from that distribution by means // of a STL Generator interface, i.e. calling the generator as a zero- // argument function. for(int i = 0; i < 10; i++) std::cout << uni() << '\n'; /* * Change seed to something else. * * Caveat: std::time(0) is not a very good truly-random seed. When * called in rapid succession, it could return the same values, and * thus the same random number sequences could ensue. If not the same * values are returned, the values differ only slightly in the * lowest bits. A linear congruential generator with a small factor * wrapped in a uniform_smallint (see experiment) will produce the same * values for the first few iterations. This is because uniform_smallint * takes only the highest bits of the generator, and the generator itself * needs a few iterations to spread the initial entropy from the lowest bits * to the whole state. */ generator.seed(static_cast<unsigned int>(std::time(0))); std::cout << "\nexperiment: roll a die 10 times:\n"; // You can save a generator's state by copy construction. base_generator_type saved_generator = generator; // When calling other functions which take a generator or distribution // as a parameter, make sure to always call by reference (or pointer). // Calling by value invokes the copy constructor, which means that the // sequence of random numbers at the caller is disconnected from the // sequence at the callee. experiment(generator); std::cout << "redo the experiment to verify it:\n"; experiment(saved_generator); // After that, both generators are equivalent assert(generator == saved_generator); // as a degenerate case, you can set min = max for uniform_int boost::uniform_int<> degen_dist(4,4); boost::variate_generator<base_generator_type&, boost::uniform_int<> > deg(generator, degen_dist); std::cout << deg() << " " << deg() << " " << deg() << std::endl; { // You can save the generator state for future use. You can read the // state back in at any later time using operator>>. std::ofstream file("rng.saved", std::ofstream::trunc); file << generator; } return 0; }