std::vector<Candidate> buildRCL(std::vector<City>& citiesToGo, Solution s, CitiesData cd) { std::vector<Candidate> RCL; std::vector<Candidate> allCandidates; // evaluate (myopic) incremental cost based on the last element of solution for (int i = 0; i < citiesToGo.size(); i++) { Candidate c; c.c = citiesToGo.at(i); if(s.num_routes == 0 || s.routes[s.num_routes-1].num_cities == cd.k + 2){ // will be the first city on the route -> incremental cost == route length // TODO: sporbowac wsadzic kazde miasto do kazdej trasy gdzie jest miejsce // ( i na roznych pozycjach) ( tez tych pustych) policzyc ile tras optymalnie //c.incrementalCost = distanceBetween(cd.warehouse,c.c) * 2.0; c.incrementalCost = fastRandomInRange(0,1000); }else{ // will not be the first-> in that case calculate incremental cost // which is the difference between route length before adding city and after Route tmp; copyRoute(tmp,s.routes[s.num_routes-1]); double costBefore = getSingleRouteLength(tmp); tmp.cities = (City*)realloc(tmp.cities,(tmp.num_cities + 1) * sizeof(City)); tmp.cities[tmp.num_cities - 1] = c.c; tmp.cities[tmp.num_cities - 0] = cd.warehouse; tmp.num_cities++; //double costAfter = getSingleRouteLength(tmp); double costAfter = getSingleRouteLength(twoOpt(tmp)); // to daje super mega du¿o lepsze wyniki (ale mocno zwalnia) free(tmp.cities); c.incrementalCost = costAfter - costBefore; } allCandidates.push_back(c); } std::sort(allCandidates.begin(), allCandidates.end(),Candidate_compareByCost); float threshold = allCandidates.back().incrementalCost - allCandidates.front().incrementalCost; threshold *= GRASP_ALPHA; threshold += allCandidates.front().incrementalCost; for (int j = 0; j < allCandidates.size(); j++) { if(allCandidates.at(j).incrementalCost < threshold || RCL.size() == 0) RCL.push_back(allCandidates.at(j)); else break; // list is sorted so we can break } return RCL; }
Solution Tabu_findPath(const CitiesData& cities) { int numberOfCycles = cities.count / TABU_CYCLE_INTERVAL; Solution bestSolution; TABU_DURATION_TIME = 2*cities.k; NEIGHBOURHOOD_SIZE = 4*cities.k; for (int cycle = 0; cycle<numberOfCycles; cycle++) { int i = 0; std::vector<TabuItem> tabuList; std::vector<SolutionCandidate> neighbourhood; SolutionCandidate baseSolutionCandidate; Solution baseSolution = getNearestNeighbourSolution(cities, cycle*TABU_CYCLE_INTERVAL + 1); /////DEBUG printf("%d before %f \n", cycle, getRoutesLength(baseSolution)); if (!cycle) bestSolution = baseSolution; else bestSolution = getBetterSolution(bestSolution, baseSolution); float bestCost = getRoutesLength(bestSolution); while(!shouldStop(i)) { generateNeighbourhood(baseSolution, neighbourhood, cities, tabuList); baseSolutionCandidate = getBestSolution(neighbourhood, tabuList); updateTabu(tabuList, baseSolutionCandidate); bestSolution = getBetterSolution(baseSolutionCandidate.solution, bestSolution); Solution tmp = baseSolution; baseSolution = baseSolutionCandidate.solution; if (tmp.routes != bestSolution.routes) { destroySolution(tmp); } i++; } //destroySolution() ////DEBUG printf("%d after %f \n", cycle, getRoutesLength(bestSolution)); } bestSolution = twoOpt(bestSolution); ////DEBUG sortAndPrintAllCities(cities, bestSolution); return bestSolution; }
Solution addRandomCandidateToSolution(std::vector<Candidate>& RCL,std::vector<City>& citiesToGo, Solution s, CitiesData cd) { if(RCL.size() < 1) return s; // choose and remove from RCL and citiesToGo int ind = uniformRandomInRange(0,RCL.size()-1); int i; Candidate chosen = take(RCL,ind); for (i = 0; i < citiesToGo.size(); i++) { if(citiesToGo.at(i).id == chosen.c.id){ ind = i; break; } } take(citiesToGo,ind); Solution r = s; i = r.num_routes - 1; if(i >= 0 && r.routes[i].num_cities < cd.k + 2){ // dodajemy do ostatniej, niepe³nej trasy r.routes[i].num_cities++; r.routes[i].cities = (City*)realloc((void*)r.routes[i].cities,r.routes[i].num_cities*sizeof(City)); r.routes[i].cities[r.routes[i].num_cities-2] = chosen.c; r.routes[i].cities[r.routes[i].num_cities-1] = cd.warehouse; r.routes[i] = twoOpt(r.routes[i]); return r; }else{ // ostatnia trasa jest pe³na, wiêc tworzymy now¹ z jednym elementem i++; r.num_routes++; if(i > 0){ r.routes = (Route*)realloc(r.routes,r.num_routes*sizeof(Route)); }else{ r.routes = (Route*)malloc(r.num_routes*sizeof(Route)); } r.routes[i].num_cities = 3; r.routes[i].cities = (City*)malloc(3*sizeof(City)); r.routes[i].cities[0] = cd.warehouse; r.routes[i].cities[1] = chosen.c; r.routes[i].cities[2] = cd.warehouse; } return r; }
vector<Solution> TwoObjectivesInstance::GenerateVoisinage(Solution s) { /* A partir de l'itinéraire d'une solution, va former tous les itinéraires possibles en inversant 2 villes */ vector<Solution> voisinage; for(unsigned int i = 0; i < s.GetItineraire().size()-1; ++i) { for(unsigned int j = i+1; j < s.GetItineraire().size(); ++j) { Solution p; p.SetItineraire(twoOpt(s.GetItineraire(), i, j)); sumVilles(p); //Pour obtenir la distance et le coût de la solution p voisinage.push_back(p); } } return voisinage; }
Solution localSearch(Solution solution) { return twoOpt(solution); }