Problémy a algoritmy
Řešení problému obchodního cestujícího metodou simulovaného ochlazování
(5. úloha)


Zadání

Je dáno m měst. Některá města jsou propojena silnicemi, délka silnic je známa. Úkolem obchodního cestujícího je navštívit všechna města (právě jednou, aspoň jednou, uvažujte oba případy). Nalezněte takovou túru (permutaci měst), aby délka ujeté cesty byla co nejmenší. Navrhněte a implementujte algoritmus řešící problém obchodního cestujícího (TSP). Funkčnost algoritmu ověřte na sadě dodaných testovacích příkladů.

Poznámka
K řešení jsem zvolil metodu simulovaného ochlazování, která řeší problém pro navštívení všech měst právě jednou, druhá varianta není uvažována


Simulované ochlazování

Metoda simulovaného ochlazování je jednou ze základních iterativních metod pro řešení NPO problémů. Její podstata spočívá v postupném "snižování teploty", přičemž teplota ovlivňuje pravděpodobnost přijmutí nového stavu zhoršujícího optimalizační kritérium současného řešení. Tedy pokud je teplota vysoká, pravděpodobnost akceptace stavu, který má horší optimalizační kritérium než současný stav je vyšší, než pokud je teplota nízká. Základní schéma algoritmu simulovaného ochlazování je následující:

//hlavní cyklus
state = initial_state;	//pocatecni stav
t = t0;			//pocatecni teplota
do {
  do {
    state = try(state, t);
  } while (! equilibrium(state, t, ...) );
  t = cool(t);
} while (! frozen(t, ...) );
//nalezení dalšího stavu
try(state, t) {
  new = random_neighbourhood(state);
  delta = cost(new) - cost(old);
  //zlepseni ci pripustne zhorseni
  if ( (delta < 0) || (random() < exp(-delta/t)) )
    return new;
  return state;
}

Ze schématu je jasné, že metoda je rozsáhle parametrizovaná, a to jak použitými algoritmy, tak počátečními podmínkami. V následujících odstavcích naleznete mojí implementaci pro řešení TSP.


Nalezení počátečního stavu

Metoda simulovaného ochlazování vychází z předpokladu, že počáteční stav je řešením daného problému, a proto není sestavení počátečního řešení zcela triviální - je to problém nalezení libovolné Hamiltonovské kružnice (kružnice procházející všemi městy právě jednou) v zadaném grafu. Výsledné řešení je také na volbě počátečního stavu závislé, ale špatná volba počáteční řešení lze "dohnat" zvýšením počáteční teploty, což nám umožní dostat s z lokálního minima, které počáteční řešení může představovat. Proto bylo mou snahou nalézt libovolné počáteční řešení, nikoliv jeho optimalizace.

Algoritmus pro nalezení Hamiltonovské kružnice je všem (alespoň těm kteří řeší tuto úlohu) relativně známý, proto jen stručně (mou konkrétní implementaci naleznete v přiloženém zdrojáku). Základem algoritmu jsou následující funkce:

Tyto funkce jsou používány ve třech fázích algoritmu:

Daný popis by měl stačit k pochopení principu algoritmu. Je z něj též patrná případná "parametrizace" algoritmu - volba počátečního měst a algoritmus výběru měst pro prodložení a modifikaci. Já jsem volil cestu nejjednodušší - počátečním městem je město 0 a algoritmus výběru je jednoduchý cyklus procházející postupně všechna města (0..count-1)


Vylepšování řešení simulovaným ochlazováním

Již z popisu algoritmu simulovaného ochlazování je zřejmé, že i zde je výrazná možnost "parametrizace" řešení, a to jak volbou parametrů, tak samotnou implementací metod. Proto se postupně zaměřím na všechny části algoritmu

Volba nového stavu (random_neigbourhood)
Nový je z existujícího stavu tvořen tzv. dvojzáměnou (překřížením), kdy jsou náhodně vybrána města i a j, u kterých existují spojení i->j a i+1->j+1 a platí i<j-1. Pokud je taková dvojice nalezena, provedene se překřížení, tedy spojení i->i+1 nahradí i->j, poté je cesta vedena proti původnímu směru do města i+1, kde je přidána cesta i+1->j+1, čímž zaniká cesta j->j+1. Pro pochopení ještě schéma obou cest
    stará cesta:   a ->...-> i -> i+1 ->...-> j -> j+1 ->...-> a
    nová cesta:   a ->...-> i -> j ->...-> i+1 -> j+1 ->...-> a

Rovnováha vniřního cyklu (equilibrium)
rovnováhy je dosaženo, pokud počet iterací uvnitř cyklu překročí zadanou mez
return iterCount > maxIter;

Rozvrh ochlazování (cool)
teplota je snižována exponenciálně násobením koeficientem alfa
return t * alfa;

Bod zamrznutí (frozen)
teplota klesne pod zadanou hranici
return t < tMin;

Ze zadaného popisu vyplývá, že jsem zvolil nejjednodušší implementaci algoritmu simulovaného ochlazování, ale i ta má možnost nastavení čtyřech parametrů, což je pro testování více než dostatečné. Vstupní parametry mého algoritmu tedy jsou:

Výstupem je délka výsledné cesty a počet iterací potředný k dosažení výsledku.

Implementaci algoritmu naleznete ve zdrojáku. Je umožněno i opakované spouštění s různým nastavení parametrů a výstupem do "tabulky" - výstupního souboru.


Výsledky testů na zkušebních instancích

Nejlepší dosažená řešení

Název instance Počet měst Délka poč. řešení t0 alfa tMin maxIter délka řešení počet iterací
A 2187 21253 3 0.8 0.5 100 20531 909
B 625 3886 5 0.96 0.001 500 2010 104709
D 200 600 3 0.97 0.001 200 581 52863
E 256 325 3 0.96 0.001 200 286 39597
J 2048 21416 3 0.96 0.001 200 21091 39597
Testik 81 616 5 0.96 0.001 1000 131 209209
C, F, G, H, I, K

Nenalezena Hamiltonovská kružnice


Testik - test parametrů

První část testu zachycuje závislost kvality řešení na počtu iterací (při snižování bodu mrazu, ale i mírné změně ostatních parametrů). Část druhá se naopak snaží zachytit závislost kvality řešení na nastavení parametrů při "konstantním" počtu iterací. Výsledky shrnuje následující tabulka, délka řešení představuje průměr z 5-ti pokusů.
Instance Testik byla zvolena pro její malou velikost a tím vyšší rychlost řešení, která umožnila provést více testů.

t0 alfa tMin maxIter počet iterací délka řešení
5 0.98 1.0 100 8080 211
5 0.98 0.5 100 11514 182
5 0.98 0.1 100 19594 159
5 0.98 0.05 100 23028 153
5 0.98 0.01 100 31108 146
5 0.98 0.001 100 42622 146
5 0.98 0.0001 100 54136 143
5 0.99 0.01 100 62519 143
5 0.99 0.001 100 85648 140
5 0.96 0.001 1000 209209 135
           
1000 0.97 0.01 100 38172 156
100 0.975 0.01 100 36764 158
10 0.98 0.01 100 34542 150
5 0.982 0.01 100 34542 150
1 0.986 0.01 100 33027 147
0.5 0.989 0.01 100 35754 147
0.1 0.993 0.01 100 33128 147
0.05 0.995 0.01 100 32522 146

První část potvrzuje relativně velkou (a samozřejmě očekávanou) závislost kvality řešení na počtu iterací. Je jasné, že při přibližování se optimálnímu řešení se rozdíly ve kvalitě snižují, ale snižuje se též rozptyl hodnot jednotlivých měření - zvyšuje se zaručení přesnosti řešení.

Druhá část prokazuje, že počáteční teplota by neměla být volena příliš vysoká - umožňuje to vzdálit se optimálnímu řešení výrazným zhoršením, které pak již není možno při nižších teplotách překonat zpět. Mnohem výhodnější se ukazuje volba v podstatě konstantní teploty - stačí relativně nízká počáteční hodnota a její jen mírné snižování.
Je zřejmé, že na kvalitě řešení se nejvýrazněji projevuje celkový počet iterací (ne však lineárně, jak již bylo uvedeno), pokud ovšem neuvažujeme extremní nastavení parametrů metody.
Je však nutno upozornit, že tento závěr je velmi závislý na konkrétní instanci a též na počátečním řešení.

Obecně by se dalo shrnout, že mnohem výhodnější než zvyšování počtu iterací se jeví vícenásobné spuštění řešení a posléze výběr nejlepšího řešení. Ani vysoký počet iterací totiž kvalitní řešení nemusí zajistit.

A - test parametrů

Jako zajímavou pro testování jsem uznal i instanci A, která svojí velkou velikostí neumožňuje zvyšovat počet iterací - pro velký počet je řešení velmi časově náročné. Následující tabulka shrnuje výsledky mých měření

t0 alfa tMin maxIter počet iterací délka řešení
3 0.5 2.0 100 101 20761
3 0.8 2.0 100 202 20678
3 0.8 1.6 100 303 20660
3 0.8 1.3 100 404 20666
3 0.8 1.0 100 505 20577
3 0.8 0.5 100 909 20531
10 0.2 0.05 100 404 20604
10 0.2 0.01 100 505 20564
3 0.9 1.8 100 505 20584

Z výsledků je patrné, že pro tuto instanci se při nízkém počtu iterací jako nejvýhodnější jeví rychlé ochlazení počáteční relativně vysoké teploty. Závislost kvality na počtu iterací se samozřejmě projevuje také.
Je ale nutné upozornit, že testy nebyly prováděny opakovaně a proto je možný znatelný projev náhodnosti v jednotlivých výsledcích.


Závěr

Má implementace simulovaného ochlazování řeší problém obchodního cestujícího s navštívením všech měst právě jednou. Výsledky jsou samozřejmě závislé na zadaných vstupních parametrech, výsledky testů naleznete v předchozí části.

Zdrojový soubor (v C++) naleznete zde