Comprensione di un algoritmo per il problema della stazione di servizio


11

Nel problema del distributore di benzina ci vengono date città e strade tra di loro. Ogni strada ha lunghezza e ogni città definisce il prezzo del carburante. Un'unità di strada costa un'unità di carburante. Il nostro obiettivo è di passare da una fonte a una destinazione nel modo più economico possibile. Il nostro serbatoio è limitato da un certo valore.{ 0 , , n - 1 }n{0,,n1}

Cerco di capire l'algoritmo , quindi ho scritto manualmente i passaggi per calcolare la soluzione. Purtroppo mi sono bloccato - a un certo punto non ci sono spigoli da considerare, non so perché, forse mi manca qualcosa.

Esempio:
strada:
0 ----------- 1 ------------ 2 -------------- 3
(non funziona deve essere così semplice, potrebbe essere qualsiasi grafico, cioè potrebbero esserci strade tra 0-> 2, 0-> 3, 1-> 3 ecc.)

Fonte: 0, Destinazione: 3, Serbatoio: 10 unità
Prezzi del carburante: 0 : 10 unità, 1 : 10 unità, 2 : 20 unità, 3 : 12 unità
Lunghezze: 0-> 1 : 9 unità, 1-> 2 : 1 unità, 2-> 3 : 7 unità
Soluzione ottimale: riempire 9 unità a 0 e 8 unità a 1. Il costo totale è quindi di 170 unità (9 * 10 + 8 * 10).

Quindi ho provato a calcolarlo come mostrato qui (paragrafo 2.2)

GV[u] is defined as:
GV[u] = { TankCapacity - length[w][u] | w in Cities and fuelPrice[w] < fuelPrice[v] and length[w][u] <= TankCapacity } U {0}

so in my case:
GV[0] = {0}
GV[1] = {0}
GV[2] = {0, 3, 9}
GV[3] = {0}

D(u,g) - minimum cost to get from u to t starting with g units of fuel in tank:
D(t,0) = 0, otherwise:
D(u,g) = min (foreach length[u][v] <= TankCapacity)
         { 
           D(v,0) + (length[u][v] - g) * fuelPrice[u]                             : if  fuelPrice[v] <= fuelPrice[u] and g <= length[u][v]
           D(v, TankCapacity - length[u][v]) + (TankCapacity - g) * fuelPrice[u]  : if  fuelPrice[v] > fuelPrice[u]
         }

so in my case:
D(0,0) = min { D(1,0) + 9*10 }  - D(0,0) should contain minimum cost from 0->3
D(1,0) = min { D(2,9) + 10*10 } - in OPT we should tank here only 8 units :(
D(2,9) = min { ??? - no edges which follows the condition from the reccurence 

Nevertheless D(0,0) = 90 + 100 + smth, so it's already too much.

To achieve the optimal solution algorithm should calculate D(2,7) because the optimal route is:   
(0,0) -> (1,0) -> (2, 7) -> (3, 0) [(v, g): v - city, g - fuel in tank]. 
If we look at G[2] there is no "7", so algorithm doesn't even assume to calculate D(2,7), 
so how can it return optimal solutions?

La ricorrenza dal documento non sembra funzionare o, cosa più probabile, faccio qualcosa di sbagliato.

Qualcuno potrebbe aiutarmi con questo?

Risposte:


7

Il problema è nella condizione per il primo argomento di min()in Equazione (4) a pag. 7. È attualmente

c(v) <= c(u) and g < d[u][v]

ma dovrebbe essere

(c(v) <= c(u) or v = t) and g < d[u][v]

per forzare l'arrivo a t per non avere più gas. (Proprio come con la mia spiegazione di seguito per il bug in Fill-Row (u, q), non siamo mai interessati al costo del gas at. E come con lì, un altro modo per risolvere il problema sarebbe quello di sovrascrivere c (t ) con 0 all'inizio dell'algoritmo.)

Correggere questo errore (nell'algoritmo pubblicato), combinato con l'aggiunta dei bordi mancanti come descrivo di seguito (il tuo errore :-P), dovrebbe essere sufficiente per far funzionare tutto.


Una cosa che ti manca è che il grafico G deve essere completo (prima frase della sezione 2, p. 4) - e se non è completo, è necessario aggiungere eventuali bordi mancanti, con i pesi rilevati prendendo le lunghezze minime del percorso in il grafo. Quindi, ad esempio nel tuo grafico di esempio, dovrebbe esserci (tra gli altri) un bordo da 1 a 3 con peso 8 (corrispondente al percorso via 2), in modo che in realtà GV [3] = {0, 2}.

Non sono sicuro se questo risolverà completamente il problema per te, ma dovrebbe aiutare.

Separatamente, penso che ci sia un bug nell'algoritmo Fill-Row (u, q) a pag. 6: questo algoritmo dovrebbe trattare il caso q = 1 appositamente, ma non lo fa. Credo che potrebbe essere risolto cambiando

if c(v) <= c(u)

sulla linea 3 a

if c(v) <= c(u) or q = 1

per forzare qualsiasi tappa finale per arrivare a destinazione vuota. (Intuitivamente, dovremmo sempre ignorare il prezzo del gas alla destinazione finale, t.) Un altro modo per aggirare questo sarebbe sovrascrivere c (t) con 0 all'inizio.


Oltre ad essere attento a ciò che accade per , devi anche fare attenzione a compilare la tabella con valori significativi quando il ciclo interno esaurisce gli elementi. Inoltre, se lo sto leggendo correttamente, l'algoritmo sembra ignorare completamente il caso (cfr. Questa domanda di CS SE ), quindi è necessario fare qualcosa anche lì. c ( v ) > c ( u )q=1c(v)>c(u)
Fuglede,

2

Usando la soluzione @j_random_hacker dobbiamo trasformare il nostro grafico in un grafico completo e cambiare la condizione dall'equazione (4) in:

(c(v) <= c(u) or v = t) and g < d[u][v]     

Il grafico completo dovrebbe apparire così:

inserisci qui la descrizione dell'immagine

e calcoli finali:

GV[0] = {0}, GV[1] = {0}, GV[2] = {0, 3, 9}, GV[3] = {0, 2}

D(0,0) = min { D(1,0) + 9 * 10 }
D(1,0) = min { D(2,9) + 10 * 10, D(3,0) + 8*10 }
D(3,0) = 0
... etc

so D(0,0) = 170

Percorso attraverso 0 -> 1 -> 3 [costo totale 170 $] è la soluzione. Questo è quello che ci aspettavamo :-). Se abbiamo bisogno di un percorso, allora dovremmo essere in grado di trasformare quei bordi extra dalla soluzione ai bordi dati all'inizio (non dovrebbe essere molto difficile).

Mi chiedo solo come dovremmo evitare deadloops in questa ricorrenza. Ad esempio, può esserci deadloop tra 0 <-> 1, perché c (0) <= c (1) ec (1) <= c (0).


Per riferimento futuro, vedi questo meta post :-)
Juho,

1

L'idea è quella di ottenere il carburante come richiesto nella tariffa più economica ovunque tu sia (paradigma di algoritmo avido)

Prendi alcuni esempi. nel tuo esempio

Fonte: 0, Destinazione: 3, Serbatoio: 10 unità Prezzi del carburante: 0: 10 unità, 1: 10 unità, 2: 20 unità, 3: 12 unità Lunghezze: 0-> 1: 9 unità, 1-> 2: 1 unità, 2-> 3: 7 unità

Devo viaggiare inizialmente 9 unità, quindi devo riempire il mio serbatoio a 0 con> = 9 unità (capacità> = 9). Ora, posso vedere a 1,2,3 la tariffa del carburante è> = tariffa del carburante a 0. Come, voglio comprare il mio carburante necessario alla tariffa più economica proverò a riempire 9 + 1 + 7 = 17 unità a solo città 0. Ma la capacità del serbatoio potrebbe essere <17, diciamo 10. Quindi, riempirò fino a 10. Quindi a 1 mi restano 1 unità di carburante e devo attraversare altre 8 unità, quindi a 1 riempirò 7 unità di più. Non riesco a riempire a 2 perché il tasso sarebbe più alto. Mio, costo totale = 10 * 10 + 7 * 10 = 170.

L'algoritmo avido segue l'idea di cui sopra. costo del carburante in città i. distanza tra due città e . "pieno" è l'unità di carburante con cui viene riempito il serbatoio. "capacità" è la capacità massima del serbatoio.d i j i jCidijij

i) pieno = 0

ii) per a , lasciate sia la prima città dopo tale che (se tale esiste quindi ). = more_distance_need_to_travel_till_city_ = . Acquista { pieno, capacità} carburante unità nella città . full = { full, capacity}. Impostare .i=0n1liCi>Clll=n1dllk=i+1ldk,k+1mindlimindli=l


La ringrazio per la risposta! Sfortunatamente non mi sono specificato abbastanza chiaramente. Hai assunto che quel grafico sarà semplice come il mio esempio, ma può essere qualsiasi grafico, ad esempio ci possono essere anche strade 0-> 2, 1-> 3 ecc.
Wojciech Kulik

Sì, come non hai detto prima che immaginavo che tutte le città fossero collegate in modo lineare (il grafico è un percorso semplice).
Sayan Bandyapadhyay,
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.