Result *TSPSimulatedAnnealing::solve() { /** * 1). losujesz rozwiazanie * 2). losujesz sąsiada żeby do niego przejść * 3). przechodzisz jak jest lepszy a jak nie to sprawdzasz prawdopodobieństwo przejścia * 4). koniec algorytmu, gdy: * - osiągnie daną liczbę kroków * - jeżeli nie ma poprawy po określonej liczbie kroków * - przy przejśiu sprawdzamy czy temperatuda nie opadła poniżej minimum */ Result *cur; Result *next; Result *best = NULL; u_int32_t bestDistance = 0, noBadMovesCounter = 0; u_int32_t loopCounter = 0; u_int32_t neighorsVisited = 0, betterSolutionsCount = 0; u_int32_t nextDistance, curDistance, worseSolutions = 0; //printf("%f %f %f %d\n", _startTemperature, _endTemperature, _alpha, _maxBadMoves); _temperature = _startTemperature; cur = generateRandomResult(); // TSPGreedySolver2 *greedySolver2; // greedySolver2 = new TSPGreedySolver2(_instance, ""); // cur = greedySolver2->solve(); // delete greedySolver2; best = new Result(*cur); bestDistance = calculateDistance(cur); while ((_temperature > _endTemperature) && (loopCounter < getNumberOfSteps()) && (noBadMovesCounter < _maxBadMoves)) { next = new Result(*cur); next->swapRandomly(); nextDistance = calculateDistance(next); next->setCalculatedDistance(nextDistance); neighorsVisited++; float lotery = ((float) (rand() % RAND_MAX) / (float) RAND_MAX); float accProb = acceptanceProbability(curDistance, nextDistance); //kiedy przechodzimy do nowego rozwiazania if ((nextDistance < curDistance) || (lotery > accProb)) { delete cur; cur = next; noBadMovesCounter = 0; if (nextDistance >= curDistance) { //printf("worse %f %f %f\n", lotery, accProb, _temperature); worseSolutions++; } if (nextDistance < bestDistance) { if (best != NULL) delete best; betterSolutionsCount++; best = new Result(*next); bestDistance = nextDistance; best->setCalculatedDistance(bestDistance); } curDistance = calculateDistance(cur); cur->setCalculatedDistance(curDistance); } else { noBadMovesCounter++; delete next; } loopCounter++; _temperature *= _alpha; } // printf("worse: %d\n", worseSolutions); // printf("temperature: %f\n", _temperature); // printf("loopCounter: %d\n", loopCounter); // printf("bad moves: %d\n", noBadMovesCounter); best->setNeighborsVisited(neighorsVisited); best->setStepsCount(loopCounter); best->setBetterSolutionsCount(betterSolutionsCount); return best; }
Data MatrixGraph::simulatedAnnealing(uint temperature) { clock_t overallTime = clock(); initRand(); stringstream results; vector<uint> route, bestRoute; route.reserve(vertexNumber); bestRoute.reserve(vertexNumber); uint prevCost = greedyAlg(route), bestCost; route.pop_back(); bestRoute = route; bestCost = prevCost; if (!temperature) temperature = vertexNumber << 10; default_random_engine gen(uint(time(nullptr))); uniform_real_distribution<double> doubleRnd(0.0, 1.0); uint i = 0; for (; temperature; --temperature, ++i) { i %= route.size(); uint firstIndex = rand() % (route.size()); uint secondIndex = rand() % (route.size() - 1); if (secondIndex >= firstIndex) ++secondIndex; vector<uint> tmpVector(route); uint tmp = tmpVector[firstIndex]; tmpVector[firstIndex] = tmpVector[secondIndex]; tmpVector[secondIndex] = tmp; uint tmpCost = calculateCost(tmpVector); if (tmpCost < prevCost) { route = tmpVector; prevCost = tmpCost; } else { if (acceptanceProbability(prevCost, tmpCost, temperature) >= doubleRnd(gen)) { route = tmpVector; prevCost = tmpCost; } } // Śledzenie najlepszego rozwiązania if (prevCost < bestCost) { bestRoute = route; bestCost = prevCost; } } double duration = (clock() - overallTime) / (double)CLOCKS_PER_SEC; results << "Koszt drogi: " << bestCost << "\nCalkowity czas trwania: " << duration << " sekund\n"; return Data(bestRoute, bestCost, results.str(), duration); }