void annealing(TSP *tsp) { Path p; int i, j, pathchg; int numOnPath, numNotOnPath; DTYPE pathlen; int n = tsp->n; double energyChange, T; pathlen = pathLength (tsp); for (T = T_INIT; T > FINAL_T; T *= COOLING) /* annealing schedule */ { pathchg = 0; for (j = 0; j < TRIES_PER_T; j++) { do { p[0] = unifRand (n); p[1] = unifRand (n); /* non-empty path */ if (p[0] == p[1]) p[1] = MOD(p[0]+1,n); numOnPath = MOD(p[1]-p[0],n) + 1; numNotOnPath = n - numOnPath; } while (numOnPath < 2 || numNotOnPath < 2); /* non-empty path */ if (RANDOM() % 2) /* threeWay */ { do { p[2] = MOD(unifRand (numNotOnPath)+p[1]+1,n); } while (p[0] == MOD(p[2]+1,n)); /* avoids a non-change */ energyChange = getThreeWayCost (tsp, p); if (energyChange < 0 || RREAL < exp(-energyChange/T) ) { pathchg++; pathlen += energyChange; doThreeWay (tsp, p); } } else /* path Reverse */ { energyChange = getReverseCost (tsp, p); if (energyChange < 0 || RREAL < exp(-energyChange/T)) { pathchg++; pathlen += energyChange; doReverse(tsp, p); } } // if the new length is better than best then save it as best if (pathlen < tsp->bestlen) { tsp->bestlen = pathlen; for (i=0; i<tsp->n; i++) tsp->border[i] = tsp->iorder[i]; } if (pathchg > IMPROVED_PATH_PER_T) break; /* finish early */ } DBG("T:%f L:%f B:%f C:%d", T, pathlen, tsp->bestlen, pathchg); if (pathchg == 0) break; /* if no change then quit */ } }
void TSP::annealing() { Path p; size_t numOnPath, numNotOnPath; double pathCost(dist.pathCost(iorder)); const double T_INIT = 100.0; const double FINAL_T = 0.1; const double COOLING = 0.9; /* to lower down T (< 1) */ const size_t TRIES_PER_T(500 * n); const size_t IMPROVED_PATH_PER_T = 60 * n; /* annealing schedule */ for (double T = T_INIT; FINAL_T < T; T *= COOLING) { size_t pathchg = 0; for (size_t j = 0; j < TRIES_PER_T; j++) { do { p[0] = rand(n); p[1] = rand(n); /* non-empty path */ if (p[0] == p[1]) p[1] = MOD(p[0] + 1, n); numOnPath = MOD(p[1] - p[0], n) + 1; numNotOnPath = n - numOnPath; } while (numOnPath < 2 || numNotOnPath < 2); /* non-empty path */ if (rand(2)) { /* threeWay */ do { p[2] = MOD(rand(numNotOnPath) + p[1] + 1, n); } while (p[0] == MOD(p[2] + 1, n)); /* avoids a non-change */ auto energyChange = getThreeWayCost(p); // if (energyChange < 0 || RREAL < exp(-energyChange / T) ) if (energyChange < 0 || std::rand() < exp(-energyChange / static_cast<double>(T)) ) { pathchg++; pathCost += energyChange; doThreeWay(p); } } else { /* path Reverse */ auto energyChange = getReverseCost(p); if (energyChange < 0 || std::rand() < exp(-energyChange / static_cast<double>(T)) ) { pathchg++; pathCost += energyChange; doReverse(p); } } // if the new length is better than best then save it as best update(iorder); #if 0 if (pathlen < tsp->bestlen) { tsp->bestlen = pathlen; for (i=0; i<tsp->n; i++) tsp->border[i] = tsp->iorder[i]; } #endif if (pathchg > IMPROVED_PATH_PER_T) break; /* finish early */ } // PGR_DBG("T:%f L:%f B:%f C:%d", T, pathlen, tsp->bestlen, pathchg); if (pathchg == 0) break; /* if no change then quit */ } }