int SRGAntColony(SRGGraph& g, std::vector<bool>& relays, std::size_t genSize, std::size_t iterations) { PheromoneMatrix p(relays.size()); p.setEvaporationRate(0.3); p.setQ(relays.size()*0.3); std::vector<bool> best(relays.size(),true), oldBest(relays.size(),true); int opt = relays.size(); //put a proper hating criterion in bool halt = false; std::vector<RanGen*> generators(NUM_THREADS); for(int i=0; i<NUM_THREADS; ++i) generators[i] = new RanGen(rand()); for(int i=0; !halt || i<iterations; ++i) { std:copy(best.begin(), best.end(), oldBest.begin()); std::vector<std::vector<std::size_t> > tours(genSize, std::vector<std::size_t>(0)); std::vector<size_t> result(genSize); for(int j=0; j<genSize/NUM_THREADS; ++j) { //some parallel code? pthread_t threads[NUM_THREADS]; ACOInfo * infos[NUM_THREADS]; std::vector<std::vector<bool> > relayArray(NUM_THREADS, std::vector<bool>(relays.size(),true)); for(int k=0; k<NUM_THREADS; ++k) { tours[j*NUM_THREADS+k].reserve(relays.size()); infos[k] = new ACOInfo(g,&relayArray[k],&tours[j*NUM_THREADS+k],&p, generators[k], &result[j*NUM_THREADS+k]); int rc = pthread_create(&threads[k], NULL, DropThread, (void *) infos[k]); } for(int k=0; k<NUM_THREADS; ++k) pthread_join(threads[k],NULL); for(int k=0; k<NUM_THREADS; ++k) { if(result[j*NUM_THREADS+k] < opt) { std::copy(relayArray[k].begin(), relayArray[k].end(), best.begin()); opt = result[j*NUM_THREADS+k]; } delete infos[k]; } } for(int j=0; j<genSize; ++j) { p.update(tours[j],(float) result[j]); } halt = true; for(int j=0; j<best.size(); ++j) if(best[j]!=oldBest[j]) halt = false; } std::copy(best.begin(), best.end(), relays.begin()); return opt; }
/** * Implementation of the Clarke and Wright savings algorithm * This function modifies an existing solution by merging tours from the same depot if this results in a net * cost reduction. The tours are merged in order of net reduction from highest to lowest. This is primarily * used to initiate the solver with a sensible first guess. */ SolutionPtr cw_savings(SolutionPtr prevsol) { set<TourPtr> newsol; for (auto depot : prevsol->get_problem()->get_depots()) { vector<TourPtr> tours_vec = prevsol->tours_from_depot(depot); set<TourPtr> tours(tours_vec.begin(), tours_vec.end()); while (true) { double reduction = -1; TourPtr left, right; for (auto t1 : tours) for (auto t2 : tours) { if (t1 == t2) continue; double test_reduction = triangle(*t1->last(), *depot, *t2->first()); // Only accept this merge if it doesn't break the daily cap condition if ( test_reduction > reduction && t1->duration() + t2->duration() - test_reduction <= prevsol->get_problem()->get_daily_cap()) { reduction = test_reduction; left = t1; right = t2; } } if (reduction >= 0) { tours.erase(left); tours.erase(right); tours.insert(TourPtr(new Tour(*left, *right))); } else break; } newsol.insert(tours.begin(), tours.end()); } return SolutionPtr(new Solution(prevsol->get_problem(), newsol)); }