예제 #1
0
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 */
    }
}
예제 #2
0
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 */
    }
}