Complessità temporale dell'algoritmo Held-Karp per TSP


9

Quando ho esaminato " Un approccio di programmazione dinamica ai problemi di sequenziamento " di Michael Held e Richard M. Karp, ho trovato la seguente domanda: perché la complessità del loro algoritmo per TSP è (k=2n1k(k1)(n1k))+(n1) (p. 199), intendo dove prendono il fattore k ? Se ho capito bene k1 significa il numero di aggiunte per ciascun sottoinsieme di città. Allora perché ogni operazione di aggiunta è accoppiata con operazioni sconosciute a me k ? Suppongo che sia collegato in qualche modo al minimo, ma il minimo di calcolo non sembra richiedere così tante operazioni.

L'algoritmo di programmazione dinamica di Held e Karp e indipendentemente Bellman funziona come segue: per ogni coppia (S,ci) , che significa un percorso che attraversa c1 , tutti gli elementi di S e termina al calcolo ci

OPT[S,ci]=min{OPT[S{ci},cj]+d(cj,ci):cjS{ci}},

dove d(cj,ci) indica la distanza tra le città cj e ci . Poi nella formula dalla carta k indica la dimensione di S .

Risposte:


5

Appendice al seguito, che chiarisce i termini k(k1) :

Quindi, se si esaminano i termini nell'espressione, si può immaginare (come analogia) il termine è un'enumerazione di tutte le stringhe binarie contenenti 1 che hanno un 1 in prima posizione. In altre parole, lasciamo che ogni posizione nella stringa binaria rappresenti la scelta se una data delle città del problema si trova nel sottoinsieme esatto che stiamo considerando al momento. Pertanto, per 5 città, 10101 corrisponde al sottoinsieme {1,3,5}. kn(n1k)kn

Pertanto, per calcolare tutti i sottoinsiemi di {1, ..., }, contiamo semplicemente attraverso ogni sottoinsieme binario (ovvero contiamo attraverso stringhe binarie) di dimensione = 2 (ovvero stringhe binarie di dimensione che contengono due 1), quindi size = 3, quindi size = 4, ... quindi size = n. (Notare che la dimensione = 1 sottoinsieme deve contenere solo la prima città, quindi è irrilevante calcolare la sua distanza parziale, poiché la distanza da 1 -> tutte le altre città nel sottoinsieme -> 1 è esattamente 0.)nnn

In ogni sottoinsieme con città, dobbiamo considerare fino a percorsi parziali ottimali per i candidati. In particolare, il percorso ottimale e totale potrebbe concepibilmente attraversare il sottoinsieme dato e finire su una qualsiasi delle città , esclusa la prima città. Quindi, per ciascuno di questi sotto-percorsi candidati, calcoliamo il tour ottimale fino a quel punto come il minimo di uno dei precedenti sotto-percorsi size = più la distanza dalla città terminale per quel sotto-percorso verso il città terminale per l'attuale sotto-percorso candidato. Questo dà a paragoni che dobbiamo fare. La discrepanza tra il mio termine e il terminek - 1 k - 1 k - 1 ( k - 1 ) ( k - 2 ) ( k - 1 ) ( k - 2 ) k ( k - 1 )kk1k1k1(k1)(k2)(k1)(k2)k(k1)il termine nell'analisi collegata è una differenza notazionale (vorrei sommare su un intervallo diverso, data la mia definizione di rispetto a loro). Per lo meno, tuttavia, dovrebbe illustrare la complessità dell'ordine di secondo grado di quel termine.k


È interessante - ho appena finito di codificare questo esatto algoritmo in C ++ pochi minuti fa. (Quindi perdona la tangente della pura teoria in una piccola discussione pratica. :))

Costa tempo e spazio - almeno sotto la mia implementazione. In pratica, tuttavia, quando i requisiti di spazio crescono così velocemente, diventano molto più dolorosi dei requisiti di tempo. Ad esempio, sul mio PC (con 4 GB di RAM), posso risolvere istanze con un massimo di 24 città, non più di così, e ho esaurito la memoria.O ( 2 n n )O(2nn2)O(2nn)

Certo, potrei solo essere un cattivo programmatore e potresti essere in grado di fare meglio di me in pratica. :)

Modifica: un po 'più specifici su un dettaglio della tua domanda: il termine deriva dal fatto che devi, nel peggiore dei casi, calcolare la distanza parziale, ottimale dai sottoinsiemi precedenti (ci sono al massimo di essi; nota che è sommato su nell'analisi che hai collegato) a quello corrente. Ciò richiede, sempre nel peggiore dei casi, confronti con sottoinsiemi di dimensione per un totale di .n k n O ( k ) k - 1 O ( k 2 )k(k1)nknO(k)k1O(k2)

Inoltre, se la mia spiegazione non fosse abbastanza chiara, ecco alcune belle note di lezione di Vazirani ( PDF ). Scorri verso il basso fino a P. 188 per una discussione su TSP, inclusa un'analisi di Held-Karp.


Oh, certo! Mi sento sciocco a pensarci adesso; Aggiornerò la mia risposta. In realtà avevo già sentito quel commento esatto prima e l'avevo trasmesso senza pensarci. E sì: scrivere su un file / leggere da un file ti consentirà di andare effettivamente in alto arbitrariamente su un numero di città. ... è anche un dolore di cui non vale la pena preoccuparsi se non stai cercando di risolvere istanze TSP per uno scopo reale. Il mio non era decisamente per uno scopo pratico. ;)
Daniel Apon il

2
È ora di implementare l'algoritmo di Bjorklund :)
Suresh Venkat il

@Suresh: buona idea!
Daniel Apon,

@Daniel Apon Potresti, per favore, precisare perché abbiamo bisogno di confronti nel calcolo della "distanza parziale, ottimale"?
Oleksandr Bondarenko il

@Oleksandr: Certo, lo aggiungerò all'inizio della mia risposta.
Daniel Apon,

0

Nota principale

È importante notare che calcoliamo e memorizziamo non
"distanza del percorso ottimale per combination of k cities"
ma
"distanza del percorso ottimale per combination of k cities AND per end-point city from this combination".
Comprenderlo aiuterà con il significato dei primi due moltiplicatori nella seguente formula.

Prima fase

Il numero di operazioni nella prima fase è:

k>=2(n1k1)choose city combinationof size = k1(k1)choose city to be the lastfrom k1 citiesin chosen combination((n1)(k1))choose citythat is not in chosen combinationto add to path

L'apice mancante in somma significa for all k>=2 that is valid for binomial coefficient. Quindi l'ultimo termine valido non nullo della somma sarà per Significa che la nostra somma non acquisisce le ultime scelte della città per connettersi alla prima città. Ci sono città per connettersi alla prima città. Quindi alla fine aggiungeremo questo termine alla somma.k=n1

(n1n2)(n2)1
n1

Consenti di trasformare la formula nel modulo che fornisci che si trova anche sulla pagina di Held-Karp Wikipedia .

k>=2(n1k1)(k1)((n1)(k1))=k>=2(n1)!(k1)!(nk)!(k1)(nk)=k>=2(n1)!k!(n1k)!k(k1)=k>=2(n1k)k(k1)
manipolazione dei coefficienti binomiali porta a: Quindi il numero di operazioni nella prima phase is
k>=2(n1k)k(k1)=k>=2(n1)!k!(n1k)!k(k1)=k>=2(n3)!(k2)!(n3(k2))!(n1)(n2)=(n1)(n2)k>=2(n3k2)=(n1)(n2)2n3
(n1)(n2)2n3+(n1)

Seconda fase

La seconda fase sta ripristinando il percorso ottimale con i segni che abbiamo fatto nella prima fase contemporaneamente alle distanze di calcolo.

Per ogni percorso ottimale "per combination of k cities AND per end-point city from this combination" abbiamo salvato la penultima città.

Per tornare indietro nel percorso ottimale, dobbiamo chiedere ad alcune strutture di dati di restituire la penultima città "per combination of k cities AND per end-point city from this combination". Quindi questa struttura di dati deve essere qualcosa di simile
Map<combination of k cities, Map<last city, second-to-last city>>. Come indice di combination of k citiespossiamo usare, per esempio binary_string[city id]=1 if city id is in combination,. Quindi dobbiamo esaminare tutti gli elementi combination of k citiesper identificare la combinazione e indicizzare la nostra struttura di dati. Questo ci dà il numero di operazioni per la seconda fase:

k>=2n1k=(n)(n1)21

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.