51 return static_cast< size_t >(
std::rand() % n);
59 return static_cast<size_t>((i + 1) % n);
65 return i == 0? n - 1: i -1;
72 template <
typename MATRIX >
75 pgassert(std::fabs(tourCost(current_tour) - current_cost) < epsilon);
76 pgassert(std::fabs(tourCost(best_tour) - bestCost) < epsilon);
82 template <
typename MATRIX >
88 if (current_cost < bestCost) {
90 best_tour = current_tour;
91 bestCost = current_cost;
99 template <
typename MATRIX >
103 const std::set<size_t> inserted)
const {
106 auto distance_row(get_row(current_city));
110 std::ostringstream err;
111 for (
const auto &d : distance_row) {
116 size_t best_city = 0;
117 auto best_distance = (std::numeric_limits<double>::max)();
122 for (
size_t i = 0; i < distance_row.size(); ++i) {
123 if (i == current_city)
continue;
124 if (inserted.find(i) != inserted.end())
continue;
125 if (distance_row[i] < best_distance) {
127 best_distance = distance_row[i];
141 template <
typename MATRIX >
146 std::set<size_t> pending(best_tour.cities.begin(), best_tour.cities.end());
147 std::set<size_t> inserted;
148 std::vector<size_t> tour_to_be;
150 auto current_city = idx_start;
153 std::ostringstream err;
154 auto ps(pending.size());
157 pending.erase(idx_start);
160 pgassert(pending.size() == (ps - 1));
163 tour_to_be.push_back(current_city);
164 inserted.insert(current_city);
166 while (!pending.empty()) {
167 auto next_city = find_closest_city(current_city, inserted);
168 tour_to_be.push_back(next_city);
169 inserted.insert(next_city);
172 auto ps(pending.size());
174 for (
const auto p : pending) {
179 pending.erase(next_city);
182 err <<
"\nafter deleting" << next_city <<
":\t";
183 for (
const auto p : pending) {
186 pgassertwm(pending.size() == (ps - 1), err.str());
189 current_city = next_city;
193 current_tour =
Tour(tour_to_be);
194 current_cost = tourCost(current_tour);
222 template <
typename MATRIX >
227 std::ostringstream err;
228 err <<
"\tplace" << place
229 <<
"\tfirst" << first
234 pgassertwm(place < first || place > last, err.str());
260 auto cityP = current_tour.cities[place];
261 auto cityF = current_tour.cities[first];
262 auto cityL = current_tour.cities[last];
263 auto cityP1 = current_tour.cities[
succ(place, n)];
264 auto cityF1 = current_tour.cities[
succ(first, n)];
265 auto cityL1 = current_tour.cities[
succ(last, n)];
268 distance(cityF, cityL1)
269 + distance(cityP, cityF1)
270 + distance(cityL, cityP1)
271 - distance(cityF, cityF1)
272 - distance(cityL, cityL1)
273 - distance(cityP, cityP1));
276 Tour new_tour(current_tour);
277 new_tour.
slide(place, first, last);
279 err <<
"\ncurrent_tour:";
280 for (
const auto id : current_tour.cities) {
284 err <<
"\nnew_tour:";
285 for (
const auto id : new_tour.
cities) {
289 auto exactDelta = tourCost(new_tour) - tourCost(current_tour);
294 << exactDelta - delta
296 << std::fabs(exactDelta - delta);
297 pgassertwm(std::fabs((exactDelta - delta)) < epsilon, err.str());
314 template <
typename MATRIX >
319 if (
succ(posE, n ) == posA) std::swap(posA, posE);
320 if (
succ(posA, n) == posE) {
321 auto b = current_tour.cities[
pred(posA, n)];
322 auto a = current_tour.cities[posA];
324 auto e = current_tour.cities[posE];
325 auto f = current_tour.cities[
succ(posE, n)];
326 return distance(b, e) + distance(e, a) + distance(a, f)
327 - distance(b, a) - distance(a, e) - distance(e, f);
330 auto b = current_tour.cities[
pred(posA, n)];
331 auto a = current_tour.cities[posA];
332 auto c = current_tour.cities[
succ(posA, n)];
334 auto d = current_tour.cities[
pred(posE, n)];
335 auto e = current_tour.cities[posE];
336 auto f = current_tour.cities[
succ(posE, n)];
339 auto delta = distance(b, e)
340 + distance(e, c) + distance(d, a) + distance(a, f)
341 - distance(b, a) - distance(a, c) - distance(d, e) - distance(e, f);
342 auto new_tour(current_tour);
343 new_tour.swap(posA, posE);
344 auto exactDelta = tourCost(new_tour) - tourCost(current_tour);
345 std::ostringstream log;
349 << exactDelta - delta
351 << std::fabs(exactDelta - delta);
353 pgassertwm(std::fabs((exactDelta - delta)) < epsilon, log.str());
357 return distance(b, e) + distance(e, c) + distance(d, a) + distance(a, f)
358 - distance(b, a) - distance(a, c) - distance(d, e) - distance(e, f);
367 template <
typename MATRIX >
372 if (posA == (posC - 1))
return 0;
373 auto a = current_tour.cities[posA];
374 auto b = current_tour.cities[
succ(posA, n)];
376 auto c = current_tour.cities[posC];
377 auto d = current_tour.cities[
succ(posC, n)];
382 distance(a, c) + distance(b, d) - distance(a, b) - distance(c, d);
383 auto new_tour(current_tour);
384 new_tour.reverse(posA, posC);
385 auto exactDelta = tourCost(new_tour) - tourCost(current_tour);
387 std::ostringstream log;
388 log <<
"exactDelta(" << exactDelta
389 <<
") - delta(" << delta
391 << exactDelta - delta
393 << (exactDelta - delta)
394 <<
" epsilon = " << epsilon;
395 pgassertwm(std::fabs((exactDelta - delta)) < epsilon, log.str());
399 return distance(a, c) + distance(b, d) - distance(a, b) - distance(c, d);
402 template <
typename MATRIX >
410 for (
size_t first = 0; first < n; first++) {
411 for (
size_t last = first + 1; last < n; last++) {
414 auto energyChange = getDeltaSwap(first, last);
416 if (energyChange < 0 && epsilon < std::fabs(energyChange)) {
418 current_cost += energyChange;
419 current_tour.swap(first, last);
427 template <
typename MATRIX >
431 double final_temperature,
432 double cooling_factor,
433 int64_t tries_per_temperature,
434 int64_t max_changes_per_temperature,
435 int64_t max_consecutive_non_changes,
439 clock_t start_time(clock());
442 std::srand(
static_cast<unsigned int>(time(NULL)));
451 for (; final_temperature < temperature; temperature *= cooling_factor) {
454 log <<
"\nCycle(" << temperature <<
") ";
461 int64_t non_change = 0;
462 for (int64_t j = 0; j < tries_per_temperature; j++) {
465 auto which =
rand(2);
475 if (c1 == c2) c2 =
succ(c2, n);
476 if (c1 == (c2 - 1)) c2 =
succ(c2, n);
477 if (c1 > c2) std::swap(c1, c2);
483 auto energyChange = getDeltaReverse(c1, c2);
485 if ( (energyChange < 0
486 && epsilon < std::fabs(energyChange))
490 static_cast<double>(RAND_MAX))
491 < exp(-energyChange / temperature))) {
492 if (energyChange < 0) ++enchg;
496 current_cost += energyChange;
497 current_tour.reverse(c1, c2);
513 if (first == last) last =
succ(last, n);
514 if (first > last) std::swap(first, last);
515 if (first == 0 && last == (n - 1)) {
516 first =
succ(first, n);
519 pgassert((n - (last - first) - 1) > 0);
520 auto place =
std::rand() % (n - (last - first) - 1);
521 place = place < first? place :
522 last + (place - first) + 1;
529 auto energyChange = getDeltaSlide(
532 if ((energyChange < 0
533 && epsilon < std::fabs(energyChange))
536 /
static_cast<double>(RAND_MAX))
537 < exp(-energyChange / temperature))) {
538 if (energyChange < 0) ++enchg;
542 current_cost += energyChange;
543 current_tour.slide(place, first, last);
551 if (max_changes_per_temperature < pathchg
552 && max_consecutive_non_changes < non_change ) {
558 clock_t current_time(clock());
559 double elapsed_time =
static_cast<double>(
560 current_time - start_time) / CLOCKS_PER_SEC;
561 if (time_limit < elapsed_time) {
564 log <<
"\ttotal changes =" << pathchg
565 <<
"\t" << enchg <<
" were because delta energy < 0";
566 if (pathchg == 0)
break;