예제 #1
0
파일: inverover.cpp 프로젝트: esa/pagmo
/**
 * 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::base_tsp* prob;
	//check if problem is of type pagmo::problem::base_tsp
	try {
		const problem::base_tsp& tsp_prob = dynamic_cast<const problem::base_tsp &>(pop.problem());
		prob = &tsp_prob;
	}
	catch (const std::bad_cast& e) {
		pagmo_throw(value_error,"Problem not of type pagmo::problem::base_tsp");
	}

	// Let's store some useful variables.
	const population::size_type NP = pop.size();
	const problem::base::size_type Nv = prob->get_n_cities();

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

	//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::base_tsp::FULL:
					my_pop[i] = prob->full2cities(pop.get_individual(i).cur_x);
					break;
				case problem::base_tsp::RANDOMKEYS:
					my_pop[i] = prob->randomkeys2cities(pop.get_individual(i).cur_x);
					break;
				case problem::base_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
		std::vector<int> starting_notes(std::max(Nv,not_feasible.size()));
			for (size_t j = 0; j < starting_notes.size(); j++) {
					starting_notes[j] = j;
			}
			//std::shuffle(starting_notes.begin(), starting_notes.end(), m_urng);
			for (size_t ii = 0; ii < not_feasible.size(); ii++) {
				i = not_feasible[ii];
				pagmo::population one_ind_pop(pop.problem(), 1);
				std::cout << starting_notes[i] << ' ';
				pagmo::algorithm::nn_tsp algo(starting_notes[i] % Nv);
				algo.evolve(one_ind_pop);
				switch( prob->get_encoding() ) {
					case problem::base_tsp::FULL:
						my_pop[i] = prob->full2cities(one_ind_pop.get_individual(0).cur_x);
						break;
					case problem::base_tsp::RANDOMKEYS:
						my_pop[i] = prob->randomkeys2cities(one_ind_pop.get_individual(0).cur_x);
						break;
					case problem::base_tsp::CITIES:
						my_pop[i] = one_ind_pop.get_individual(0).cur_x;
						break;
				}
				std::cout << i << ' ' << one_ind_pop.get_individual(0).cur_f << std::endl;
			}
			break;
		}
		default:
			pagmo_throw(value_error,"Invalid initialization type");
	}

	std::vector<fitness_vector>  fitness(NP, fitness_vector(1));
	for(size_t i=0; i < NP; i++){
		switch( prob->get_encoding() ) {
			case problem::base_tsp::FULL:
				fitness[i] = prob->objfun(prob->full2cities(my_pop[i]));
				break;
			case problem::base_tsp::RANDOMKEYS:
				fitness[i] = prob->objfun(prob->cities2randomkeys(my_pop[i], pop.get_individual(i).cur_x));
				break;
			case problem::base_tsp::CITIES:
				fitness[i] = prob->objfun(my_pop[i]);
				break;
		}
	}


	decision_vector tmp_tour(Nv);
	bool stop, changed;
	size_t rnd_num, i2, pos1_c1, pos1_c2, pos2_c1, pos2_c2; //pos2_c1 denotes the position of city1 in parent2
	fitness_vector fitness_tmp;

	//InverOver main loop
	for(int iter = 0; iter < m_gen; iter++) {
		for(size_t i1 = 0; i1 < NP; i1++) {
			tmp_tour = my_pop[i1];
			pos1_c1 = unif_Nv();
			stop = false;
			changed = 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 || static_cast<problem::base::size_type>(abs(pos1_c1-pos1_c2))==Nv-1);
				if(!stop) {
					changed = true;
					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]);
						}
						pos1_c1 = pos1_c2;
					} else {
						//inverts the section from c1 to c2 (see documentation Note3)
						for(size_t l=0; l < (double (pos1_c1-pos1_c2-1)/2); l++) {
							std::swap(tmp_tour[pos1_c2+l],tmp_tour[pos1_c1-l-1]);
						}
						pos1_c1 = (pos1_c2 == 0? Nv-1:pos1_c2-1);
					}
					
				}
			} //end of while loop (looping over a single indvidual)
			if(changed) {
				switch(prob->get_encoding()) {
					case problem::base_tsp::FULL:
						fitness_tmp = prob->objfun(prob->full2cities(tmp_tour));
						break;
					case problem::base_tsp::RANDOMKEYS: //using "randomly" index 0 as a temporary template
						fitness_tmp = prob->objfun(prob->cities2randomkeys(tmp_tour, pop.get_individual(0).cur_x));
						break;
					case problem::base_tsp::CITIES:
						fitness_tmp = prob->objfun(tmp_tour);
						break;
				}
				if(prob->compare_fitness(fitness_tmp,fitness[i1])) { //replace individual?
					my_pop[i1] = tmp_tour;
					fitness[i1][0] = fitness_tmp[0];
				}
			}
		} // 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::base_tsp::FULL:
				pop.set_x(ii,prob->cities2full(my_pop[ii]));
				break;
			case problem::base_tsp::RANDOMKEYS:
				pop.set_x(ii,prob->cities2randomkeys(my_pop[ii],pop.get_individual(ii).cur_x));
				break;
			case problem::base_tsp::CITIES:
				pop.set_x(ii,my_pop[ii]);
				break;
		}
	}
} // end of evolve
예제 #2
0
/**
 * Run the co-evolution algorithm
 *
 * @param[in,out] pop input/output pagmo::population to be evolved.
 */
void cstrs_co_evolution::evolve(population &pop) const
{	
	// Let's store some useful variables.
	const problem::base &prob = pop.problem();
	const population::size_type pop_size = pop.size();
	const problem::base::size_type prob_dimension = prob.get_dimension();

	// get the constraints dimension
	problem::base::c_size_type prob_c_dimension = prob.get_c_dimension();

	//We perform some checks to determine wether the problem/population are suitable for co-evolution
	if(prob_c_dimension < 1) {
		pagmo_throw(value_error,"The problem is not constrained and co-evolution is not suitable to solve it");
	}
	if(prob.get_f_dimension() != 1) {
		pagmo_throw(value_error,"The problem is multiobjective and co-evolution is not suitable to solve it");
	}

	// Get out if there is nothing to do.
	if(pop_size == 0) {
		return;
	}

	//get the dimension of the chromosome of P2
	unsigned int pop_2_dim = 0;
	switch(m_method)
	{
	case algorithm::cstrs_co_evolution::SIMPLE:
	{
		pop_2_dim = 2;
		break;
	}
	case algorithm::cstrs_co_evolution::SPLIT_NEQ_EQ:
	{
		pop_2_dim = 4;
		break;
	}
	case algorithm::cstrs_co_evolution::SPLIT_CONSTRAINTS:
		pop_2_dim = 2*prob.get_c_dimension();
		break;
	default: 
		pagmo_throw(value_error,"The constraints co-evolutionary method is not valid.");
		break;
	}

	// split the population into two populations
	// the population P1 associated to the modified problem with penalized fitness
	// and population P2 encoding the penalty weights
	
	// Populations size
	population::size_type pop_1_size = pop_size;
	population::size_type pop_2_size = m_pop_penalties_size;

	//Creates problem associated to P2
	problem::cstrs_co_evolution_penalty prob_2(prob,pop_2_dim,pop_2_size);
	prob_2.set_bounds(m_pen_lower_bound,m_pen_upper_bound);

	//random initialization of the P2 chromosome (needed for the fist generation)
	std::vector<decision_vector> pop_2_x(pop_2_size);
	std::vector<fitness_vector> pop_2_f(pop_2_size);

	for(population::size_type j=0; j<pop_2_size; j++) {
		pop_2_x[j] = decision_vector(pop_2_dim,0.);
		// choose random coefficients between lower bound and upper bound
		for(population::size_type i=0; i<pop_2_dim;i++) {
			pop_2_x[j][i] = boost::uniform_real<double>(m_pen_lower_bound,m_pen_upper_bound)(m_drng);
		}
	}

	//vector of the population P1. Initialized with clones of the original population
	std::vector<population> pop_1_vector;
	for(population::size_type i=0; i<pop_2_size; i++){
		pop_1_vector.push_back(population(pop));
	}

	// Main Co-Evolution loop
	for(int k=0; k<m_gen; k++) {
		// for each individuals of pop 2, evolve the current population,
		// and store the position of the feasible idx
		for(population::size_type j=0; j<pop_2_size; j++) {

			problem::cstrs_co_evolution prob_1(prob, pop_1_vector.at(j), m_method);

			// modify the problem by setting decision vector encoding penalty
			// coefficients w1 and w2 in prob 1
			prob_1.set_penalty_coeff(pop_2_x.at(j));

			// creating the POPULATION 1 instance based on the
			// updated prob 1

			// prob_1 is a BASE_META???? THE CLONE OF prob_1 IN POP_1 IS AT THE LEVEL OF
			// THE BASE CLASS AND NOT AT THE LEVEL OF THE BASE_META, NO?!?
			population pop_1(prob_1,0);

			// initialize P1 chromosomes. The fitnesses related to problem 1 are computed
			for(population::size_type i=0; i<pop_1_size; i++) {
				pop_1.push_back(pop_1_vector.at(j).get_individual(i).cur_x);
			}

			// evolve the P1 instance
			m_original_algo->evolve(pop_1);

			//updating the original problem population (computation of fitness and constraints)
			pop_1_vector.at(j).clear();
			for(population::size_type i=0; i<pop_1_size; i++){
				pop_1_vector.at(j).push_back(pop_1.get_individual(i).cur_x);
			}

			// set up penalization variables needs for the population 2
			// the constraints has not been evaluated yet.
			prob_2.update_penalty_coeff(j,pop_2_x.at(j),pop_1_vector.at(j));

		}
		// creating the POPULATION 2 instance based on the
		// updated prob 2
		population pop_2(prob_2,0);

		// compute the fitness values of the second population
		for(population::size_type i=0; i<pop_2_size; i++) {
			pop_2.push_back(pop_2_x[i]);
		}

		m_original_algo_penalties->evolve(pop_2);

		// store the new chromosomes
		for(population::size_type i=0; i<pop_2_size; i++) {
			pop_2_x[i] = pop_2.get_individual(i).cur_x;
			pop_2_f[i] = pop_2.get_individual(i).cur_f;
		}

		// Check the exit conditions (every 40 generations, just as DE)
		if(k % 40 == 0) {
			// finds the best population
			population::size_type best_idx = 0;
			for(population::size_type j=1; j<pop_2_size; j++) {
				if(pop_2_f[j][0] < pop_2_f[best_idx][0]) {
					best_idx = j;
				}
			}

			const population &current_population = pop_1_vector.at(best_idx);

			decision_vector tmp(prob_dimension);

			double dx = 0;
			for(decision_vector::size_type i=0; i<prob_dimension; i++) {
				tmp[i] = current_population.get_individual(current_population.get_worst_idx()).best_x[i] -
						current_population.get_individual(current_population.get_best_idx()).best_x[i];
				dx += std::fabs(tmp[i]);
			}

			if(dx < m_xtol ) {
				if (m_screen_output) {
					std::cout << "Exit condition -- xtol < " << m_xtol << std::endl;
				}
				break;
			}

			double mah = std::fabs(current_population.get_individual(current_population.get_worst_idx()).best_f[0] -
					current_population.get_individual(current_population.get_best_idx()).best_f[0]);

			if(mah < m_ftol) {
				if(m_screen_output) {
					std::cout << "Exit condition -- ftol < " << m_ftol << std::endl;
				}
				break;
			}

			// outputs current values
			if(m_screen_output) {
				std::cout << "Generation " << k << " ***" << std::endl;
				std::cout << "    Best global fitness: " << current_population.champion().f << std::endl;
				std::cout << "    xtol: " << dx << ", ftol: " << mah << std::endl;
				std::cout << "    xtol: " << dx << ", ftol: " << mah << std::endl;
			}
		}
	}

	// find the best fitness population in the final pop
	population::size_type best_idx = 0;
	for(population::size_type j=1; j<pop_2_size; j++) {
		if(pop_2_f[j][0] < pop_2_f[best_idx][0]) { 
			best_idx = j;
		}
	}

	// store the final population in the main population
	// can't avoid to recompute the vectors here, otherwise we
	// clone the problem stored in the population with the
	// pop = operator!
	pop.clear();
	for(population::size_type i=0; i<pop_1_size; i++) {
		pop.push_back(pop_1_vector.at(best_idx).get_individual(i).cur_x);
	}
}
예제 #3
0
    /**
     * 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