Comprendre un algorithme pour le problème de la station-service

11

Dans le problème des stations-service, on nous donne villes et des routes entre elles. Chaque route a une longueur et chaque ville définit le prix du carburant. Une unité de route coûte une unité de carburant. Notre objectif est de passer d'une source à une destination de la manière la moins chère possible. Notre réservoir est limité par une certaine valeur.{ 0 , , n - 1 }n{0,,n1}

J'essaie de comprendre l'algorithme , j'ai donc noté manuellement les étapes pour calculer la solution. Malheureusement, je suis resté coincé - à un moment donné, il n'y a pas d'arête à considérer, je ne sais pas pourquoi, peut-être que je manque quelque chose.

Exemple:
route:
0 ----------- 1 ------------ 2 -------------- 3
(il ne doit être aussi simple que cela, il peut s'agir de n'importe quel graphique, c'est-à-dire qu'il peut y avoir des routes entre 0-> 2, 0-> 3, 1-> 3, etc.)

Source: 0, Destination: 3, Réservoir: 10 unités
Prix ​​du carburant: 0 : 10 unités, 1 : 10 unités, 2 : 20 unités, 3 : 12 unités
Longueurs: 0-> 1 : 9 unités, 1-> 2 : 1 unité, 2-> 3 : 7 unités
Solution optimale: remplissez 9 unités à 0 et 8 unités à 1. Le coût total est alors de 170 unités (9 * 10 + 8 * 10).

J'ai donc essayé de le calculer comme indiqué ici (paragraphe 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 récurrence du document ne semble pas fonctionner ou, plus probablement, je fais quelque chose de mal.

Quelqu'un pourrait-il m'aider avec ça?

Wojciech Kulik
la source

Réponses:

7

Le problème est dans la condition du premier argument de l' min()équation (4) à la p. 7. C'est actuellement

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

mais ça devrait être

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

pour forcer l'arrivée à t pour qu'il n'y ait plus de gaz. (Tout comme avec mon explication ci-dessous pour le bogue dans Fill-Row (u, q), nous ne sommes jamais intéressés par le coût du gaz à t. Et comme avec là-bas, une autre façon de résoudre le problème serait d'écraser c (t ) avec 0 au début de l'algorithme.)

La correction de cette erreur (dans l'algorithme publié), combinée à l'ajout des bords manquants comme je le décris ci-dessous (votre erreur :-P), devrait suffire pour que tout fonctionne.


Une chose qui vous manque est que le graphique G doit être complet (première phrase de la section 2, p. 4) - et s'il n'est pas complet, tous les bords manquants doivent être ajoutés, avec les poids trouvés en prenant des longueurs de chemin minimales dans le graphique. Ainsi, par exemple, dans votre exemple de graphique, il devrait y avoir (entre autres) une arête de 1 à 3 avec un poids 8 (correspondant au chemin via 2), de sorte qu'en fait GV [3] = {0, 2}.

Je ne sais pas si cela résoudra complètement le problème pour vous, mais cela devrait aider.

Séparément, je pense qu'il y a un bug dans l'algorithme Fill-Row (u, q) sur p. 6: cet algorithme devrait traiter le cas q = 1 spécialement, mais ce n'est pas le cas. Je pense que cela pourrait être corrigé en changeant

if c(v) <= c(u)

sur la ligne 3 à

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

pour forcer toute étape finale à arriver à destination vide. (Intuitivement, nous devons toujours ignorer le prix du gaz à la destination finale, t.) Une autre solution consiste à remplacer c (t) par 0 au départ.

j_random_hacker
la source
En plus de faire attention à ce qui se passe pour , vous devez également prendre soin de remplir le tableau avec des valeurs significatives lorsque la boucle interne manque d'éléments. De plus, si je le lis correctement, l'algorithme semble ignorer complètement le cas (cf. cette question CS SE ), donc quelque chose doit être fait là aussi. c ( v ) > c ( u )q=1c(v)>c(u)
fuglede
2

En utilisant la solution @j_random_hacker, nous devons transformer notre graphique en un graphique complet et changer la condition de l'équation (4) en:

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

Le graphique complet devrait ressembler à ceci:

entrez la description de l'image ici

et calculs finaux:

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

Traverser 0 -> 1 -> 3 [coût total 170 $] est la solution. C'est ce que nous attendions :-). Si nous avons besoin d'un itinéraire, alors nous devrions être en mesure de transformer ces bords supplémentaires de la solution aux bords donnés au début (cela ne devrait pas être très difficile).

Je me demande seulement comment éviter les impasses dans cette récurrence. Par exemple, il peut y avoir une boucle morte entre 0 <-> 1, car c (0) <= c (1) et c (1) <= c (0).

Wojciech Kulik
la source
Pour référence future, voir ce méta post :-)
Juho
1

L'idée est d'obtenir le carburant nécessaire au tarif le moins cher où que vous soyez (paradigme d'algorithme gourmand)

Prenons quelques exemples. dans votre exemple

Source: 0, Destination: 3, Réservoir: 10 unités Prix du carburant: 0: 10 unités, 1: 10 unités, 2: 20 unités, 3: 12 unités Longueurs: 0-> 1: 9 unités, 1-> 2: 1 unité, 2-> 3: 7 unités

Je dois d'abord voyager 9 unités, donc je dois remplir mon réservoir à 0 avec> = 9 unités (capacité> = 9). Maintenant, je peux voir à 1,2,3 le taux de carburant est> = taux de carburant à 0. Comme, je veux acheter mon carburant nécessaire au taux le moins cher, j'essaierai de remplir 9 + 1 + 7 = 17 unités à ville 0 uniquement. Mais, la capacité du réservoir pourrait être <17, disons 10. Donc, je remplirai jusqu'à 10. Ensuite, à 1, il me reste 1 unité de carburant et je dois parcourir 8 unités de plus, donc à 1, je remplirai 7 unités plus. Je ne peux pas faire le plein à 2 car le tarif serait plus élevé. Mon, coût total = 10 * 10 + 7 * 10 = 170.

L'algorithme gourmand suit l'idée mentionnée ci-dessus. Coût du carburant à la ville i. distance entre deux villes et . "plein" est l'unité de carburant avec laquelle le réservoir est rempli. "capacité" est la capacité maximale du réservoir.d i j i jCidijij

i) plein = 0

ii) pour à , soit la première ville après telle que (si aucun n'existe, alors ). = more_distance_need_to_travel_till_city_ = . Achetez { plein, capacité} unité de carburant à la ville . full = { full, capacité}. Réglez .i=0n1liCi>Clll=n1dllk=i+1ldk,k+1mindlimindli=l

Sayan Bandyapadhyay
la source
Merci pour votre réponse! Malheureusement, je ne me suis pas suffisamment précisé. Vous avez supposé que ce graphique sera aussi simple que mon exemple, mais il peut s'agir de n'importe quel graphique, c'est-à-dire qu'il peut également y avoir des routes 0-> 2, 1-> 3, etc.
Wojciech Kulik
Oui, comme vous ne l'avez pas mentionné avant de supposer que toutes les villes sont connectées de manière linéaire (le graphique est un chemin simple).
Sayan Bandyapadhyay