void get_tiles_radius(gamemap const &map, std::vector<map_location> const &locs, size_t radius, std::set<map_location> &res, xy_pred *pred) { typedef std::set<map_location> location_set; location_set not_visited(locs.begin(), locs.end()), must_visit, filtered_out; ++radius; for(;;) { location_set::const_iterator it = not_visited.begin(), it_end = not_visited.end(); std::copy(it,it_end,std::inserter(res,res.end())); for(; it != it_end; ++it) { map_location adj[6]; get_adjacent_tiles(*it, adj); for(size_t i = 0; i != 6; ++i) { map_location const &loc = adj[i]; if(map.on_board(loc) && !res.count(loc) && !filtered_out.count(loc)) { if(!pred || (*pred)(loc)) { must_visit.insert(loc); } else { filtered_out.insert(loc); } } } } if(--radius == 0 || must_visit.empty()) { break; } not_visited.swap(must_visit); must_visit.clear(); } }
/** * Function that will add to @a result all elements of @a locs, plus all * on-board locations matching @a pred that are connected to elements of * locs by a chain of at most @a radius tiles, each of which matches @a pred. * @a result must be a std::set of locations. */ void get_tiles_radius(gamemap const &map, std::vector<map_location> const &locs, size_t radius, std::set<map_location> &result, bool with_border, xy_pred const &pred) { typedef std::set<map_location> location_set; location_set must_visit, filtered_out; location_set not_visited(locs.begin(), locs.end()); for ( ; radius != 0 && !not_visited.empty(); --radius ) { location_set::const_iterator it = not_visited.begin(); location_set::const_iterator it_end = not_visited.end(); result.insert(it, it_end); for(; it != it_end; ++it) { map_location adj[6]; get_adjacent_tiles(*it, adj); for(size_t i = 0; i != 6; ++i) { map_location const &loc = adj[i]; if ( with_border ? map.on_board_with_border(loc) : map.on_board(loc) ) { if ( !result.count(loc) && !filtered_out.count(loc) ) { if ( pred(loc) ) must_visit.insert(loc); else filtered_out.insert(loc); } } } } not_visited.swap(must_visit); must_visit.clear(); } result.insert(not_visited.begin(), not_visited.end()); }
/** * Runs the NN_TSP algorithm. * * @param[in,out] pop input/output pagmo::population to be evolved. */ void nn_tsp::evolve(population &pop) const { const problem::base_tsp* prob; //check if problem is of type pagmo::problem::base_tsp try { prob = &dynamic_cast<const problem::base_tsp &>(pop.problem()); } catch (const std::bad_cast& e) { pagmo_throw(value_error,"Problem not of type pagmo::problem::tsp, nn_tsp can only be called on problem::tsp problems"); } // Let's store some useful variables. const problem::base::size_type Nv = prob->get_n_cities(); //create individuals decision_vector best_tour(Nv); decision_vector new_tour(Nv); //check input parameter if (m_start_city < -1 || m_start_city > static_cast<int>(Nv-1)) { pagmo_throw(value_error,"invalid value for the first vertex"); } size_t first_city, Nt; if(m_start_city == -1){ first_city = 0; Nt = Nv; } else{ first_city = m_start_city; Nt = m_start_city+1; } int length_best_tour, length_new_tour; size_t nxt_city, min_idx; std::vector<int> not_visited(Nv); length_best_tour = 0; //main loop for (size_t i = first_city; i < Nt; i++) { length_new_tour = 0; for (size_t j = 0; j < Nv; j++) { not_visited[j] = j; } new_tour[0] = i; std::swap(not_visited[new_tour[0]],not_visited[Nv-1]); for (size_t j = 1; j < Nv-1; j++) { min_idx = 0; nxt_city = not_visited[0]; for (size_t l = 1; l < Nv-j; l++) { if(prob->distance(new_tour[j-1], not_visited[l]) < prob->distance(new_tour[j-1], nxt_city) ) { min_idx = l; nxt_city = not_visited[l];} } new_tour[j] = nxt_city; length_new_tour += prob->distance(new_tour[j-1], nxt_city); std::swap(not_visited[min_idx],not_visited[Nv-j-1]); } new_tour[Nv-1] = not_visited[0]; length_new_tour += prob->distance(new_tour[Nv-2], new_tour[Nv-1]); length_new_tour += prob->distance(new_tour[Nv-1], new_tour[0]); if(i == first_city || length_new_tour < length_best_tour){ best_tour = new_tour; length_best_tour = length_new_tour; } } //change representation of tour population::size_type best_idx = pop.get_best_idx(); switch( prob->get_encoding() ) { case problem::base_tsp::FULL: pop.set_x(best_idx,prob->cities2full(best_tour)); break; case problem::base_tsp::RANDOMKEYS: pop.set_x(best_idx,prob->cities2randomkeys(best_tour,pop.get_individual(best_idx).cur_x)); break; case problem::base_tsp::CITIES: pop.set_x(best_idx,best_tour); break; } } // end of evolve
__kernel void findRoute(__global double *graph, __global double* next_moves, __global double *output, __global int* constK, __global double* messages, __global double* rands ) { int k = constK[0]; //next_moves has size k*2*k // graph has size edges*4 // output has size k*k int num_edges = k*(k-1)/2; double alpha = 2.0; double beta = 2.0; int idx = get_global_id(0); int idy = get_global_id(1); int current_position = idx; add_to_array(output, k, current_position, idx, messages); bool possible_to_move = true; int count = 0; while(possible_to_move){ possible_to_move = false; double sum = 0.0; for (int i = 0; i < num_edges; i++){ int edge_start = i*4; int possible_goal; bool fits = false; if (graph[edge_start]==current_position){ possible_goal = edge_start+1; fits = true; } else if(graph[edge_start+1]==current_position) { possible_goal = edge_start; fits = true; } if (fits && not_visited(output, graph, possible_goal, k, idx)){ possible_to_move = true; double cost = graph[edge_start + 2]; double pheromones = graph[edge_start + 3]; double thao = pow(pheromones, alpha); double attr = pow(cost, -beta); double nomin = thao * attr; sum = sum + nomin; add_nominative(next_moves, nomin, edge_start, k, idx, messages); } } if (possible_to_move){ for (int i = idx*k*2; i < idx*k*2+k*2; i=i+2){ next_moves[i] = next_moves[i] / sum; } double random = get_random(rands, k, idx, count); int edge_choice_index = get_next_move(next_moves, random, k, idx); // in that edge, one value is our current position and the other value // is the next node double next_node = -1.0; if (current_position == graph[edge_choice_index]){ // e.g. edge 1-2 and we are in 1. Put 2 in output and into current pos next_node = graph[edge_choice_index + 1]; } else { // e.g. edge 2-1 and we are in 1. Put 2 in output and into current pos next_node = graph[edge_choice_index]; } add_to_array(output, k, next_node, idx, messages); current_position = next_node; } else { return; } clear_next_moves(next_moves, k, idx); count = count + 1; } }
/** * Runs the Inverover algorithm for the number of generations specified in the constructor. * * @param[in,out] pop input/output pagmo::population to be evolved. */ void inverover::evolve(population &pop) const { const problem::tsp* prob; //check if problem is of type pagmo::problem::tsp try { const problem::tsp& tsp_prob = dynamic_cast<const problem::tsp &>(pop.problem()); prob = &tsp_prob; } catch (const std::bad_cast& e) { pagmo_throw(value_error,"Problem not of type pagmo::problem::tsp"); } // Let's store some useful variables. const population::size_type NP = pop.size(); const std::vector<std::vector<double> >& weights = prob->get_weights(); const problem::base::size_type Nv = prob->get_n_cities(); // Get out if there is nothing to do. if (m_gen == 0) { return; } // Initializing the random number generators boost::uniform_real<double> uniform(0.0,1.0); boost::variate_generator<boost::lagged_fibonacci607 &, boost::uniform_real<double> > unif_01(m_drng,uniform); boost::uniform_int<int> NPless1(0, NP - 2); boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > unif_NPless1(m_urng,NPless1); boost::uniform_int<int> Nv_(0, Nv - 1); boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > unif_Nv(m_urng,Nv_); boost::uniform_int<int> Nvless1(0, Nv - 2); boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > unif_Nvless1(m_urng,Nvless1); //check if we have a symmetric problem (symmetric weight matrix) bool is_sym = true; for(size_t i = 0; i < Nv; i++) { for(size_t j = i+1; j < Nv; j++) { if(weights[i][j] != weights[j][i]) { is_sym = false; goto end_loop; } } } end_loop: //create own local population std::vector<decision_vector> my_pop(NP, decision_vector(Nv)); //check if some individuals in the population that is passed as a function input are feasible. bool feasible; std::vector<int> not_feasible; for (size_t i = 0; i < NP; i++) { feasible = prob->feasibility_x(pop.get_individual(i).cur_x); if(feasible){ //if feasible store it in my_pop switch( prob->get_encoding() ) { case problem::tsp::FULL: my_pop[i] = prob->full2cities(pop.get_individual(i).cur_x); break; case problem::tsp::RANDOMKEYS: my_pop[i] = prob->randomkeys2cities(pop.get_individual(i).cur_x); break; case problem::tsp::CITIES: my_pop[i] = pop.get_individual(i).cur_x; break; } } else { not_feasible.push_back(i); } } //replace the not feasible individuals by feasible ones int i; switch (m_ini_type){ case 0: { //random initialization (produces feasible individuals) for (size_t ii = 0; ii < not_feasible.size(); ii++) { i = not_feasible[ii]; for (size_t j = 0; j < Nv; j++) { my_pop[i][j] = j; } } int tmp; size_t rnd_idx; for (size_t j = 1; j < Nv-1; j++) { boost::uniform_int<int> dist_(j, Nv - 1); boost::variate_generator<boost::mt19937 &, boost::uniform_int<int> > dist(m_urng,dist_); for (size_t ii = 0; ii < not_feasible.size(); ii++) { i = not_feasible[ii]; rnd_idx = dist(); tmp = my_pop[i][j]; my_pop[i][j] = my_pop[i][rnd_idx]; my_pop[i][rnd_idx] = tmp; } } break; } case 1: { //initialize with nearest neighbor algorithm int nxt_city; size_t min_idx; std::vector<int> not_visited(Nv); for (size_t ii = 0; ii < not_feasible.size(); ii++) { i = not_feasible[ii]; for (size_t j = 0; j < Nv; j++) { not_visited[j] = j; } my_pop[i][0] = unif_Nv(); std::swap(not_visited[my_pop[i][0]],not_visited[Nv-1]); for (size_t j = 1; j < Nv-1; j++) { min_idx = 0; nxt_city = not_visited[0]; for (size_t l = 1; l < Nv-j; l++) { if(weights[my_pop[i][j-1]][not_visited[l]] < weights[my_pop[i][j-1]][nxt_city]){ min_idx = l; nxt_city = not_visited[l];} } my_pop[i][j] = nxt_city; std::swap(not_visited[min_idx],not_visited[Nv-j-1]); } my_pop[i][Nv-1] = not_visited[0]; } break; } default: pagmo_throw(value_error,"Invalid initialization type"); } //compute fitness of individuals (necessary if weight matrix is not symmetric) std::vector<double> fitness(NP, 0); if(!is_sym){ for(size_t i=0; i < NP; i++){ fitness[i] = weights[my_pop[i][Nv-1]][my_pop[i][0]]; for(size_t k=1; k < Nv; k++){ fitness[i] += weights[my_pop[i][k-1]][my_pop[i][k]]; } } } decision_vector tmp_tour(Nv); bool stop; size_t rnd_num, i2, pos1_c1, pos1_c2, pos2_c1, pos2_c2; //pos2_c1 denotes the position of city1 in parent2 double fitness_change, fitness_tmp = 0; //InverOver main loop for(int iter = 0; iter < m_gen; iter++){ for(size_t i1 = 0; i1 < NP; i1++){ fitness_change = 0; tmp_tour = my_pop[i1]; pos1_c1 = unif_Nv(); stop = false; while(!stop){ if(unif_01() < m_ri){ rnd_num = unif_Nvless1(); pos1_c2 = (rnd_num == pos1_c1? Nv-1:rnd_num); } else{ i2 = unif_NPless1(); i2 = (i2 == i1? NP-1:i2); pos2_c1 = std::find(my_pop[i2].begin(),my_pop[i2].end(),tmp_tour[pos1_c1])-my_pop[i2].begin(); pos2_c2 = (pos2_c1 == Nv-1? 0:pos2_c1+1); pos1_c2 = std::find(tmp_tour.begin(),tmp_tour.end(),my_pop[i2][pos2_c2])-tmp_tour.begin(); } stop = (abs(pos1_c1-pos1_c2)==1 || abs(pos1_c1-pos1_c2)==Nv-1); if(!stop){ if(pos1_c1<pos1_c2){ for(size_t l=0; l < (double (pos1_c2-pos1_c1-1)/2); l++){ std::swap(tmp_tour[pos1_c1+1+l],tmp_tour[pos1_c2-l]);} if(is_sym){ fitness_change -= weights[tmp_tour[pos1_c1]][tmp_tour[pos1_c2]] + weights[tmp_tour[pos1_c1+1]][tmp_tour[pos1_c2+1 - (pos1_c2+1 > Nv-1? Nv:0)]]; fitness_change += weights[tmp_tour[pos1_c1]][tmp_tour[pos1_c1+1]] + weights[tmp_tour[pos1_c2]][tmp_tour[pos1_c2+1 - (pos1_c2+1 > Nv-1? Nv:0)]]; } } else{ //inverts the section from c1 to c2 (see documentation Note3) for(size_t l=0; l < (double (Nv-(pos1_c1-pos1_c2)-1)/2); l++){ std::swap(tmp_tour[pos1_c1+1+l - (pos1_c1+1+l>Nv-1? Nv:0)],tmp_tour[pos1_c2-l + (pos1_c2<l? Nv:0)]);} if(is_sym){ fitness_change -= weights[tmp_tour[pos1_c1]][tmp_tour[pos1_c2]] + weights[tmp_tour[pos1_c1+1 - (pos1_c1+1 > Nv-1? Nv:0)]][tmp_tour[pos1_c2+1]]; fitness_change += weights[tmp_tour[pos1_c1]][tmp_tour[pos1_c1+1 - (pos1_c1+1 > Nv-1? Nv:0)]] + weights[tmp_tour[pos1_c2]][tmp_tour[pos1_c2+1]]; } } pos1_c1 = pos1_c2; //better performance than original Inver-Over (shorter tour in less time) } } //end of while loop (looping over a single indvidual) if(!is_sym){ //compute fitness of the temporary tour fitness_tmp = weights[tmp_tour[Nv-1]][tmp_tour[0]]; for(size_t k=1; k < Nv; k++){ fitness_tmp += weights[tmp_tour[k-1]][tmp_tour[k]]; } fitness_change = fitness_tmp - fitness[i1]; } if(fitness_change < 0){ //replace individual? my_pop[i1] = tmp_tour; if(!is_sym){ fitness[i1] = fitness_tmp; } } } //end of loop over population } //end of loop over generations //change representation of tour for (size_t ii = 0; ii < NP; ii++) { switch( prob->get_encoding() ) { case problem::tsp::FULL: pop.set_x(ii,prob->cities2full(my_pop[ii])); break; case problem::tsp::RANDOMKEYS: pop.set_x(ii,prob->cities2randomkeys(my_pop[ii],pop.get_individual(ii).cur_x)); break; case problem::tsp::CITIES: pop.set_x(ii,my_pop[ii]); break; } } } // end of evolve