From 9d198f4dd75037577ab035d6a1826ba780b06109 Mon Sep 17 00:00:00 2001 From: khouadjia Date: Wed, 11 Mar 2009 15:07:01 +0000 Subject: [PATCH] New approach for Dynamic Vehicle Routing Problem based on Particle Swarm Optimization git-svn-id: svn://scm.gforge.inria.fr/svnroot/paradiseo@1507 331e1502-861f-0410-8da2-ba01fb791d7f --- .../branches/PSO-DVRP/eoPsoDVRPutils.cpp | 1789 ----------------- 1 file changed, 1789 deletions(-) delete mode 100644 contribution/branches/PSO-DVRP/eoPsoDVRPutils.cpp diff --git a/contribution/branches/PSO-DVRP/eoPsoDVRPutils.cpp b/contribution/branches/PSO-DVRP/eoPsoDVRPutils.cpp deleted file mode 100644 index 4960da805..000000000 --- a/contribution/branches/PSO-DVRP/eoPsoDVRPutils.cpp +++ /dev/null @@ -1,1789 +0,0 @@ -/* - * Copyright (C) DOLPHIN Project-Team, INRIA Lille Nord-Europe, 2007-2008 - * (C) OPAC Team, LIFL, 2002-2008 - * - * (c) Mostepha Redouane Khouadjia , 2008 - * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/ or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. - * - * ParadisEO WebSite : http://paradiseo.gforge.inria.fr - * Contact: paradiseo-help@lists.gforge.inria.fr - * - */ - - -#include "eoPsoDVRPutils.h" - - - // The computed distances will be stored in dist. - -setCustumers clients; - -std::vector newCustomers; - -lengthMatrix dist; - - -template - -std::string to_string( const T & Value ) -{ - // utiliser un flux de sortie pour créer la chaîne - - std::ostringstream oss; - - // écrire la valeur dans le flux - - oss << Value; - - // renvoyer une string - return oss.str(); -} - - - - - - -void computeDistances() { - - - dist.resize (clients.size ()) ; - - for (unsigned i = 0; i < dist.size (); i ++) - - dist [i].resize (clients.size ()); - - // Distances computation - for (unsigned i = 0; i < dist.size (); i ++) - - for (unsigned j = i ; j < dist.size (); j ++) - - { - - double distX = clients [i].x - clients [j].x; - - double distY = clients [i].y - clients [j].y; - - dist [i][j] = dist [j][i] = sqrt (distX * distX + distY * distY); - - } -} - -/** - * \brief Returns the time window information of a given client. - * \param _client The client whose information we want to know. - * \param _availTime Return value. The time xhen client will be available in system. - * \param _durationService Return value. The client's service time. - */ - -void getInformation (unsigned _custumer, double& _availTime, double& _durationService) { - - assert (_custumer >= 0 && _custumer < clients.size ()); - - _availTime = clients [_custumer].availTime; - - _durationService = clients [_custumer].durationService; - -} - - - -/** - * \brief A function to get the distance between two clients. - * \param _from The first client. - * \param _to The second client. - * \return The distance between _from and _to. - */ - -void PrintCustumersMatrix (){ - - for (int i =0 ; i < clients.size(); ++i) - - cout<< clients[i].id<<'\t'<= 0 && _from < clients.size ()); - - assert (_to >= 0 && _to < clients.size ()); - - return _dist [_from][_to]; - -} - - -const lengthMatrix distanceMatrix() {return dist;} - - -/** - * \brief Loads the problem data from a given file. - * \param _fileName The file to load data from. - * \warning No error check is performed! - */ - - -double computTourLength(Route _route) - - { - double RouteLength =0.0; - for (unsigned i = 0, size = _route.size()-1; i < size; ++i ) - RouteLength+=distance(dist,_route[i], _route[i+1]); - - RouteLength+= distance(dist, _route.back(),0); - return RouteLength; - - } - - - -double computTourLength( Routes _mRoute) - - { - double MatrixLength =0.0; - - for(unsigned tr = 0, tsize = _mRoute.size(); tr < tsize; ++tr ) - - MatrixLength += computTourLength(_mRoute[tr]); - - return MatrixLength; - } - - - - -bool findClient (unsigned id) // Look for one customers in the table Clients - -{ - for ( size_t i = 0, size = clients.size(); i < size; ++i ) - { - if (id == (clients.at(i)).id) - return true; - } - - return false; -} - - -void loadNewCustomers(double _timeStep, double _timeSlice){ - - unsigned id_customer; - - newCustomers.clear(); - - unsigned i = 1; - - while (i < clients.size()) - { - if(clients[i].availTime > (_timeStep - _timeSlice) && clients[i].availTime <=_timeStep) - - newCustomers.push_back(clients[i].id); - - i++; - - } - -} - - -void loadMatrixCustomers (const string _fileName) { - - string line; - - istringstream iss; - - std::ifstream file (_fileName.c_str()); - - ClientDataT depot, custumer; - - unsigned int id; - - - if (file) { - - depot.id= 0; - - depot.availTime = depot.demand=depot.durationService = 0.0; - - clients.push_back (depot); - - - do - getline(file,line); - - while (line.find("DEMAND_SECTION")== string::npos); - - getline(file,line); - - do{ - - iss.str(line); - - iss>> custumer.id>>custumer.demand; - - clients.push_back (custumer); - - iss.clear(); - - getline(file,line); - - }while(line.find("LOCATION_COORD_SECTION")== string::npos); - - - getline(file,line); - do{ - - iss.str(line); - - iss>>id; - - iss>>clients[id].x; - - iss>>clients[id].y; - - iss.clear(); - - getline(file,line); - - } while(line.find("DEPOT_LOCATION_SECTION")== string::npos); - - - do - getline(file,line); - - - while (line.find("DURATION_SECTION")== string::npos); - - - getline(file,line); - - - do{ iss.str(line); - - iss>>id; - - iss>>clients[id].durationService; - - iss.clear(); - - getline(file,line); - - } while(line.find("DEPOT_TIME_WINDOW_SECTION")== string::npos); - - - getline(file,line); - - iss.str(line); - - iss>>id; - - iss>>clients[id].availTime>>clients[id].durationService; - - iss.clear(); - - do - getline(file,line); - - - - while(line.find("TIME_AVAIL_SECTION")== string::npos); - - - getline(file,line); - - - do{ - iss.str(line); - - iss>>id; - - iss>>clients[id].availTime; - - iss.clear(); - - getline(file,line); - - } while(line.find("EOF")== string::npos); - - - - file.close (); - - computeDistances(); - - } - else { - - std::cerr << "Error: the file: " << _fileName << " doesn't exist !!!" << std::endl ; - - abort(); - - } - -} - - -/** - * \brief Prints a route to the standard output. - * \param _route The route to print. - */ - -void printRoute (const Route& _route, std::ostream &_os) { - - _os<< "["; - - for (unsigned i = 0; i < _route.size (); i++) { - - _os << _route [i]; - - if (i != _route.size () -1) - - _os << ", "; - - } - - _os << "]"< _dispoTime) - - - return _nextTimeStep ; - - - - else - - return _dispoTime; - -} - - - - -double getCapacityUsed (Route _route) - - { - - double charge =0.0; - - unsigned id_custumer; - - for (size_t i=1, size = _route.size(); i uGen(0,maxTour); - - return uGen(); - } - - -int randVelocity(int sizetr) - { - - - - eoUniformGenerator uGen(-sizetr,sizetr); - - return uGen(); - - - } - - - -unsigned randPosition (unsigned _lastPosition, unsigned _sizeTour) - -{ - - eoUniformGenerator uGen(_lastPosition ,_sizeTour); - - return uGen(); - - -} - - -void checkDistances(const Routes _matrix) - -{ - - double longeurTotal = 0.0 ; - - for(size_t tr = 0, tsize =_matrix.size(); tr < tsize; ++tr ) - { - double longeur = 0.0 ; - - for (size_t i = 0, size = _matrix[tr].size()-1; i < size; ++i ) - - longeur +=distance(dist,_matrix[tr][i], _matrix[tr][i+1]); - - cout << endl<<"distance route "<< tr+1 << " "<< longeur < i) - - - positionTour = i; - - else - - positionTour = i + 1; - - - double dueTime = getTimeOfService(_route, _startTime, customer_id, positionTour) - - + distance (dist,_route.back(),0) ; - - - double demandTour = getCapacityUsed(_route) + clients[customer_id].demand; - - - if( dueTime <= depotTimeWindow && demandTour <= VEHICULE_CAPACITY ) - - - { - nearestCostInsertion = costInsertion ; - - nearestPosition = positionTour; - - feasibleInsertion = true; - - } - - } - } - } - - - - - - if(!commitCustomer && feasibleInsertion) - { - - commitCustomer = true; - - nearestTourCost = nearestCostInsertion; - - positionNearestTour = nearestPosition; - - nearestTour = indexTour; - - } - - else - { - - if(feasibleInsertion) - - if( nearestTourCost < nearestCostInsertion ) - - { - nearestTourCost = nearestCostInsertion; - - positionNearestTour = nearestPosition; - - nearestTour = indexTour; - - - } - - - } - - } - - - - -void nearestInsertionAlgorithm (Route _route, unsigned indexTour, - - unsigned lastServedCustomer_id, unsigned lastServedCustomerPosition, - - double serviceTime, unsigned customer_id, unsigned & nearestTour, - - double & nearestTourCost, unsigned & positionNearestTour, bool & commitCustomer) -{ - - double costInsertion, nearestCostInsertion, nearestCheapCostInsertion , costLeftInsertion , costRightInsertion; - - unsigned leftCustomer_id, rightCustomer_id, nearestPosition, positionTour; - - bool feasibleInsertion = false ; - - double depotTimeWindow = clients[0].durationService; - - for( size_t i = lastServedCustomerPosition, sizetr = _route.size() ; i < sizetr ; i ++) - { - - unsigned nearestCustomer_id = _route [i]; - - costInsertion = distance (dist, nearestCustomer_id, customer_id); - - if (((!feasibleInsertion) ) || ( costInsertion < nearestCostInsertion)) - { - - if( nearestCustomer_id != lastServedCustomer_id ) - { - - leftCustomer_id = _route[i-1]; - - if(i == _route.size()-1) - - rightCustomer_id = 0; - else - - rightCustomer_id = _route[i+1]; - - - - costLeftInsertion = distance (dist , leftCustomer_id , customer_id) + - - distance (dist, customer_id, nearestCustomer_id ) - - - distance (dist, leftCustomer_id, nearestCustomer_id ) ; - - costRightInsertion = distance(dist, nearestCustomer_id, customer_id) + - - distance(dist, customer_id , rightCustomer_id) - - - distance (dist , nearestCustomer_id , rightCustomer_id); - - - if (costLeftInsertion < costRightInsertion) - - positionTour = i ; - - else - - positionTour = i + 1 ; - - } - else - - positionTour = i + 1 ; - - - double dueTime = getTimeOfService(_route, lastServedCustomer_id, serviceTime, customer_id, positionTour) - - + distance (dist, _route.back(),0); - - double demandTour = getCapacityUsed(_route) + clients[customer_id].demand; - - - - if( dueTime <= depotTimeWindow && demandTour <= VEHICULE_CAPACITY ) - - - { - nearestCostInsertion =costInsertion ; - - nearestPosition = positionTour; - - feasibleInsertion = true; - - } - else - - if( nearestCustomer_id !=lastServedCustomer_id) - - { - - - if( positionTour > i) - - - positionTour = i; - - else - - positionTour = i + 1; - - - double dueTime = getTimeOfService(_route, lastServedCustomer_id, serviceTime, customer_id, positionTour) - - + distance (dist, _route.back(),0); - - double demandTour = getCapacityUsed(_route) + clients[customer_id].demand; - - - if( dueTime <= depotTimeWindow && demandTour <= VEHICULE_CAPACITY ) - - - { - nearestCostInsertion = costInsertion ; - - nearestPosition = positionTour; - - feasibleInsertion = true; - - } - - } - } - } - - - if(!commitCustomer && feasibleInsertion) - { - - commitCustomer = true; - - nearestTourCost = nearestCostInsertion; - - positionNearestTour = nearestPosition; - - nearestTour = indexTour; - - } - - else - { - - if(feasibleInsertion) - - if(nearestTourCost < nearestCostInsertion ) - - { - nearestTourCost = nearestCostInsertion; - - positionNearestTour = nearestPosition; - - nearestTour = indexTour; - - - } - - } - - } - - - - -void generalizedInsertionTypeOneAlgorithm (Route _route, Route & _GenRoute, unsigned indexTour, double _startTime, unsigned customer_id, unsigned & generalizedTour, - - unsigned & positionGeneralizedTour, double & generalizedTourCost, bool & commitCustomer) -{ - - double costInsertion, lowCostInsertion; - - unsigned positionTour, lowPosition; - - std::vector tempNodes; - - bool feasibleInsertion = false ; - - double depotTimeWindow = clients[0].durationService; - - Route _tempRoute, _GenTempRoute ; - - if(_route.size() >= 3) - - { - - for( size_t i = 1, sizetri = _route.size()-1; i < sizetri; i ++) - { - - for( size_t j = i, sizetrj = _route.size()-1 ; j < sizetrj; j ++) - - - for( size_t k = j+1, sizetrk = _route.size(); k < sizetrk ; k++) - - { - - costInsertion = distance(dist,_route[i] , customer_id) + distance (dist, customer_id, _route[j]) + distance (dist, _route[i+1],_route[k]) + distance(dist,_route[j+1],_route[k+1]) - - - - - distance (dist, _route[i],_route[i+1]) + distance (dist, _route[j], _route[j+1]) + distance(dist,_route[k],_route[k+1]); - - - positionTour = i+1; - - - _tempRoute = _route ; - - - tempNodes.clear() ; - - - tempNodes.push_back(j); tempNodes.push_back(k); - - - InsertionTypeOne(_tempRoute,positionTour,customer_id,tempNodes); - - - double dueTime = getTimeOfService(_tempRoute, 0, _startTime ) + distance (dist,_tempRoute.back() , 0); - - - double demandTour = getCapacityUsed(_tempRoute); - - - if (dueTime <= depotTimeWindow && demandTour <= VEHICULE_CAPACITY ) - { - - if ((!feasibleInsertion) || (costInsertion < lowCostInsertion)) - - { - - lowCostInsertion= costInsertion; - - lowPosition = positionTour; - - _GenTempRoute = _tempRoute; - - feasibleInsertion = true; - - } - - } - - } - } - } -else - { - _tempRoute = _route ; - - positionTour = _tempRoute.size(); - - _tempRoute.push_back(customer_id); - - costInsertion = distance(dist,_tempRoute.back(), customer_id) + distance(dist,customer_id, 0) - distance(dist,_tempRoute.back(),0) ; - - double dueTime = getTimeOfService(_tempRoute, 0, _startTime ) + distance (dist,_tempRoute.back() , 0); - - double demandTour = getCapacityUsed(_tempRoute) + clients[customer_id].demand; - - if (dueTime <= depotTimeWindow && demandTour <= VEHICULE_CAPACITY ) - - { - - if ((!feasibleInsertion) || (costInsertion < lowCostInsertion)) - - { - - lowCostInsertion= costInsertion; - - lowPosition = positionTour; - - _GenTempRoute = _tempRoute; - - feasibleInsertion = true; - - } - - } - - } - - -if(feasibleInsertion) - - if( !commitCustomer || lowCostInsertion < generalizedTourCost ) - - { - generalizedTourCost = lowCostInsertion; - - positionGeneralizedTour = lowPosition; - - _GenRoute = _GenTempRoute; - - generalizedTour = indexTour; - - commitCustomer = true; - - - } - - -} - - - - - -void generalizedInsertionTypeOneAlgorithm (Route _route, Route& _Genroute, unsigned indexTour, unsigned lastServedCustomer_id, - - unsigned lastServedCustomerPosition, double serviceTime, unsigned customer_id, unsigned & generalizedTour, - - unsigned & positionGeneralizedTour, double & generalizedTourCost, bool & commitCustomer) -{ - - double costInsertion, lowCostInsertion; - - unsigned positionTour, lowPosition; - - std::vector tempNodes; - - bool feasibleInsertion = false ; - - double depotTimeWindow = clients[0].durationService; - - Route _tempRoute, _GenTempRoute; - - - if(_route.size() >= 3) - { - - for( size_t i = lastServedCustomer_id + 1, sizetri = _route.size() -1; i < sizetri; i ++) - { - - for( size_t j = i, sizetrj = _route.size() -1 ; j < sizetrj; j ++) - - - for( size_t k = j+1, sizetrk = _route.size(); k < sizetrk ; k++) - - - { - - - costInsertion = distance(dist,_route[i] , customer_id) + distance (dist, customer_id, _route[j]) + distance (dist, _route[i+1],_route[k]) + distance(dist,_route[j+1],_route[k+1]) - - - - - distance (dist, _route[i],_route[i+1]) + distance (dist, _route[j], _route[j+1]) + distance(dist,_route[k],_route[k+1]); - - - positionTour = i+1; - - - _tempRoute = _route ; - - - tempNodes.clear() ; - - - tempNodes.push_back(j); - - - tempNodes.push_back(k); - - - InsertionTypeOne(_tempRoute,positionTour,customer_id,tempNodes); - - - double dueTime = getTimeOfService(_tempRoute, lastServedCustomer_id, serviceTime) + distance (dist,_tempRoute.back() , 0); - - - double demandTour = getCapacityUsed(_tempRoute); - - - if (dueTime <= depotTimeWindow && demandTour <= VEHICULE_CAPACITY ) - { - - if ((!feasibleInsertion) || (costInsertion < lowCostInsertion)) - - { - - lowCostInsertion= costInsertion; - - lowPosition = positionTour; - - _GenTempRoute = _tempRoute; - - feasibleInsertion = true; - - } - } - } - } - }else - { - - _tempRoute = _route ; - - positionTour = _tempRoute.size(); - - _tempRoute.push_back(customer_id); - - costInsertion = distance(dist,_tempRoute.back(), customer_id) + distance(dist,customer_id, 0) - distance(dist,_tempRoute.back(),0) ; - - double dueTime = getTimeOfService(_tempRoute, lastServedCustomer_id, serviceTime) + distance (dist,_tempRoute.back() , 0); - - double demandTour = getCapacityUsed(_tempRoute) + clients[customer_id].demand; - - if (dueTime <= depotTimeWindow && demandTour <= VEHICULE_CAPACITY ) - - { - - if ((!feasibleInsertion) || (costInsertion < lowCostInsertion)) - - { - - lowCostInsertion= costInsertion; - - lowPosition = positionTour; - - _GenTempRoute = _tempRoute; - - feasibleInsertion = true; - - } - } - - } - - - if(feasibleInsertion) - - if( !commitCustomer || lowCostInsertion < generalizedTourCost ) - - { - generalizedTourCost = lowCostInsertion; - - positionGeneralizedTour = lowPosition; - - generalizedTour = indexTour; - - _Genroute = _GenTempRoute; - - commitCustomer = true; - - - } -} - -/* -double computTourLength(const Routes _routes) - { - - double Length = 0.0 ; - - - for(size_t tr = 0, tsize = _routes.size(); tr < tsize; ++tr ) - - { - - for (size_t i = 0, size = _routes[tr].size()-1; i < size; ++i ) - - Length+= distance(dist,_routes[tr][i], _routes[tr][i+1]); - - - - Length+= distance(dist,_routes[tr].back(),0); - - } - - return Length ; - - } - -*/ - - -unsigned bestNeighborhoodRoutes ( const std::vector _neighborhoodRoutes, unsigned _bestNeighborIndex, double _bestNeighbor_fitness) - -{ - double minFitness, fitnessRoute ; - - unsigned minRoute ; - - - minFitness = computTourLength(_neighborhoodRoutes[0]); - - minRoute = 0; - - - for (size_t i =1, size = _neighborhoodRoutes.size(); i < size ; i++ ) - - { fitnessRoute = computTourLength(_neighborhoodRoutes[i]) ; - - - if(fitnessRoute < minFitness) - - - { minFitness = fitnessRoute; - - minRoute = i ; - - } - - } - - _bestNeighborIndex = minRoute; - - _bestNeighbor_fitness = minFitness ; -} - - - -void swapCustomers(Route &_route, unsigned _lastCustomerPosition) -{ - - - unsigned customer1 = randPosition(_lastCustomerPosition + 1 , _route.size()); - - - unsigned customer2 = randPosition(_lastCustomerPosition +1 , _route.size()); - - - swap(_route[customer1],_route[customer2]); - -} - - - - -bool twoOptOnRoute( Route & _route , unsigned _lastServedCustomerPosition) - -{ - bool twoOptFeasible = false ; - - for (unsigned from = _lastServedCustomerPosition , size1 = _route.size() ; from < size1 -1 ; from ++) - - for(unsigned to = from +1 , size2 = _route.size(); to < size2 ; to ++) - - if( GainCost(_route,from,to) > 0 ) - - { - int idx =(to-from)/2; - - for(unsigned k = 1; k <= idx ;k++) - - std::swap(_route[from+k],_route[to-k]); - - - - twoOptFeasible = true; - - } - - return twoOptFeasible; -} - - - -void InsertionTypeOne(Route & _route, unsigned positionGeneralizedTour, unsigned customer_id, std::vector vertices) -{ - - _route.insert(_route.begin() + positionGeneralizedTour, customer_id ); - - unsigned j = vertices[0]; - - unsigned k = vertices[1]; - - _route.insert(_route.begin() + positionGeneralizedTour + 1, _route[j+1]); - - _route.erase(_route.begin() + j + 2); - - unsigned to = k + 1; - - unsigned from = positionGeneralizedTour + 2; - - int idx =( to - from )/2; - - for(unsigned q = 1; q <= idx ;q++) - - std::swap(_route[from+q],_route[to-q]); - - -} - -void threeMoveRoute(Route & _route, unsigned _from, unsigned _to, unsigned _end) -{ - - Route tempRoute; - - for(size_t i=0; i<= _from; i++) - - tempRoute.push_back(_route[i]); - - tempRoute.push_back( _route[_to + 1]); - - tempRoute.push_back(_route[_end]); - - for(size_t i=_from +1; i<= _to; i++) - - tempRoute.push_back(_route[i]); - - tempRoute.push_back(_route[_end+1]); - - for(size_t i=_to +2; i<_end; i++) - - tempRoute.push_back(_route[i]); - - for(size_t i=_end + 2; i<_route.size(); i++) - - tempRoute.push_back(_route[i]); - - _route = tempRoute; - - -} - -bool threeOptOnRoute( Route & _route , unsigned _lastServedCustomerPosition) - -{ - bool threeOptFeasible = false ; - - for (unsigned from = _lastServedCustomerPosition , size1 = _route.size()-3 ; from < size1 ; from ++) - - for(unsigned to = from +1 , size2 = _route.size()-2; to < size2; to ++) - - for(unsigned end= to + 1, size3 = _route.size()-1 ; end < size3; end++) - - if( GainCost(_route,from,to,end) > 0 ) - - { - - //threeMoveRoute(_route,from,to,end); - - if (!threeOptFeasible) threeOptFeasible = true; - - - } - - return threeOptFeasible; -} - - - - - -double GainCost(Route _route, unsigned _from, unsigned _to) -{ - - double Gain ; - - Gain= (distance (dist, _route[_from], _route[(_from +1) % _route.size()]) + distance(dist, _route[_to - 1], _route[_to % _route.size()])) - - - - - (distance (dist, _route[_from],_route[_to - 1]) + distance(dist, _route[(_from+1)%_route.size()],_route[_to% _route.size()])); - - return Gain; -} - - -double GainCost(Route _route, unsigned _from, unsigned _to, unsigned _end) -{ - - double Gain; - - Gain = distance (dist, _route[_from],_route[(_from +1) % _route.size()]) + - - distance(dist, _route[_to], _route[(_to + 1) % _route.size()]) + - - distance (dist,_route[_end],_route[(_end + 1) % _route.size()]) - - - - - distance (dist, _route[_from],_route[(_to + 1) % _route.size()]) + - - distance(dist, _route[_to], _route[(_end + 1) % _route.size()]) + - - distance (dist,_route[_end],_route[(_from + 1) % _route.size()]); - - - - return Gain; - -} - - -