bool reduceRoute(solution &sol, const problem& input){ if(sol.routes.size() <= 1) return false; unsigned int before = sol.routes.size(); // find route with highest (distance / # of customers). list<route>::iterator minR; double dis = 0; for(list<route>::iterator it = sol.routes.begin(); it != sol.routes.end(); it++){ double p = it->distance / it->visits.size(); if(p > dis){ minR = it; dis = p; } } // remove this shortest route route shortest = (*minR); sol.routes.erase(minR); for(list<int>::iterator cus = shortest.visits.begin(); cus != shortest.visits.end();){ solution min = sol; for(int tryCount = 0; tryCount < input.getNumCusto(); tryCount++){ solution temp = min; list<route>::iterator r = temp.routes.begin(); advance(r, rand() % temp.routes.size() ); list<int>::iterator ins = r->visits.begin(); advance(ins, r->visits.size()); r->visits.insert(ins, *cus); r->modified = true; temp.fitness(input); if(temp.totalDistance < min.totalDistance){ min = temp; } } if(min.totalDistance < sol.totalDistance){ cus = shortest.visits.erase(cus); shortest.modified = true; sol = min; }else{ cus++; } } // append a new route with customers can't be inserted. if( !shortest.visits.empty() ){ sol.routes.push_front(shortest); } return (sol.routes.size() < before); }
void mutation(solution &sol, const problem& input){ int tryCount = 0; while(tryCount < input.getNumCusto() ){ solution test = sol; // randomly select two routes list<route>::iterator routeA = test.routes.begin(); advance(routeA, rand() % test.routes.size() ); list<route>::iterator routeB = test.routes.begin(); advance(routeB, rand() % test.routes.size() ); // # of feasible route BEFORE the reinsertion int beforeFeasibleCount = 0; if(routeA->feasible) beforeFeasibleCount++; if(routeB->feasible) beforeFeasibleCount++; // randomly select two positions list<int>::iterator cusA = routeA->visits.begin(); advance(cusA, rand() % routeA->visits.size() ); list<int>::iterator cusB = routeB->visits.begin(); advance(cusB, rand() % routeB->visits.size() ); routeB->visits.insert(cusB, *cusA); routeB->modified = true; routeA->visits.erase(cusA); routeA->modified = true; bool reduce = false; if( routeA->visits.empty() ){ test.routes.erase(routeA); reduce = true; } test.fitness(input); // # of feasible route AFTER the reinsertion int afterFeasibleCount = 0; if(reduce || routeA->feasible) afterFeasibleCount++; if(routeB->feasible) afterFeasibleCount++; if(afterFeasibleCount >= beforeFeasibleCount) sol = test; tryCount++; } }
void solution::random(int maxRoutes, const problem& input){ clear(); vector< vector<int> > newRoutes; newRoutes.resize(maxRoutes); for(int id = 1; id <= input.getNumCusto(); ++id){ newRoutes[ rand() % maxRoutes ].push_back(id); } for(int i = 0; i < maxRoutes; ++i){ if(newRoutes[i].size() > 0){ // insert customers according to time windows' position vector<int> sorted; sorted.reserve(newRoutes[i].size()); for(unsigned int j = 0; j < sorted.capacity(); ++j){ int minStart = input[0].end, minEnd = input[0].end, id; for(unsigned int k = 0; k < newRoutes[i].size(); ++k){ if(input[ newRoutes[i][k] ].end < minEnd){ minEnd = input[ newRoutes[i][k] ].end; minStart = input[ newRoutes[i][k] ].start; id = k; }else if(input[ newRoutes[i][k] ].end == minEnd && input[ newRoutes[i][k] ].start < minStart ){ minStart = input[ newRoutes[i][k] ].start; id = k; } } sorted.push_back(newRoutes[i][id]); newRoutes[i].erase(newRoutes[i].begin() + id); } route newRoute; newRoute.visits = list<int>(sorted.begin(), sorted.end()); routes.push_back(newRoute); } } fitness(input); }