#1 Sat 24 June 2017 19:54
- bruhnild
- Participant actif
- Lieu: Lyon
- Date d'inscription: 7 Jun 2014
- Messages: 130
Pgrouting - itinéraire en deux temps
Bonjour,
Je travaille actuellement sur une problématique d'optimisation de tournée de facteurs.
J'ai réussi à générer une série d'itinéraires partant d'un seul point (la poste) vers tous les points relais connus avec la fonction pgr_kdijkstraPat (voir : http://docs.pgrouting.org/2.0/fr/src/kd … kdijkstra)
Aujourd'hui je cherche à générer un itinéraire unique qui partirait de la poste pour aller desservir un à un tous les points relais en prenant en compte la notion de cout distance entre chacun d'eux.
Mon problème se décompose en deux temps :
1) Trouver un algorythme avec Pg Routing permettant de faire du calcul d'itinéraire en plusieurs temps (comme le fait Google Maps par exemple);
2) Trouver l'ordre de desserte entre les différents points relais.
Pourriez vous m'aider?
Hors ligne
#2 Sat 24 June 2017 21:47
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: Pgrouting - itinéraire en deux temps
Bonsoir,
C'est pas TSP l'algo qu'il vous faut ? http://pgrouting.org/docs/1.x/tsp.html
Nicolas
Hors ligne
#3 Sun 25 June 2017 21:15
- tumasgiu
- Membre
- Lieu: Ajaccio
- Date d'inscription: 5 Jul 2010
- Messages: 1160
Re: Pgrouting - itinéraire en deux temps
C'est ce que je me disais aussi,
mais j'ai peur de ne pas vraiment comprendre le besoin.
Hors ligne
#4 Mon 26 June 2017 12:18
- tqhien
- Participant actif
- Lieu: Clamart
- Date d'inscription: 22 Apr 2011
- Messages: 78
Re: Pgrouting - itinéraire en deux temps
Bonjour,
J'avais été une fois confronté au même type de problématique : optimiser une tournée avec contrainte de charge/d'emport. J'avais trouvé le logiciel OpenSource Optaplanner (https://www.optaplanner.org/) qui permet avec un peu de codage, de définir les points à desservir, leur besoin, la capacité max du véhicule transporteur, etc. En sortie, on peut avoir 1,2, ou plus tournées repassant par le point de départ par exemple.
Remarque : il semble que dans ce type d'algo, la distance à vol d'oiseau est tout aussi efficace mais bien plus rapide en calculs que de faire un véritable routage sur le réseau.
Hien.
Hors ligne
#5 Tue 27 June 2017 07:18
- bruhnild
- Participant actif
- Lieu: Lyon
- Date d'inscription: 7 Jun 2014
- Messages: 130
Re: Pgrouting - itinéraire en deux temps
Bonjour,
Merci pour vos réponses.
Nicolas Ribot, je ne vois pas comment utiliser TSP pour parvenir au résultat souhaité.
J'ai joins une pièce jointe qui permet de mieux comprendre mon besoin.
Le calcul d'itinéraire a été réalisé sur ce site : https://gebweb.net/optimap/
On y rentre une série de coordonnées en longitude et latitude et on choisit le "Fastest Round Trip".
Cela nous permet d'obtenir une proposition d'itinéraire en partant du point 1 (la poste) et qui va desservir les points relais tout autour.
A partir le 15 points, le tracé n'est pas garanti optimal..
Cette méthode n'est pas satisfaisante selon moi car je ne sais pas encore comment exploiter les résultats en sortie.
C'est pour cela que j'aimerais réussir à trouver une solution sous Pg routing.
Bonne journée.
Hors ligne
#6 Tue 27 June 2017 17:06
- tqhien
- Participant actif
- Lieu: Clamart
- Date d'inscription: 22 Apr 2011
- Messages: 78
Re: Pgrouting - itinéraire en deux temps
Pour utiliser l'algo TSP de pgrouting : il faut procéder en deux temps.
Construire la requête des noeuds (variable sql dans la doc) : elle renvoit 3 colonnes : source_id, x et y. Il faut donc traduire tes champs en ces trois noms.
Par exemple :
Code:
SELECT mon_noeud_id as source_id, mon_noeud_x as x, mon_noeud_y as y from mon_reseau ;
ou autre exemple :
Code:
SELECT mon_noeud_id as source_id, ST_X(mon_noeud_geom) as x, ST_Y(mon_noeud_geom) as y from mon_reseau ;
Les noeuds à desservir sont à mettre dans une liste 'n1,n2,n3,n4'. Tu peux la générer selon la requête suivante par exemple:
Code:
SELECT string_agg(CAST(mon_noeud_id as varchar), ',') FROM mes_cibles
Si le noeud de départ a pour identifiant mon_noeud_id = xxx, la requête a faire est la suivante :
Code:
SELECT * from tsp ('SELECT mon_noeud_id as source_id, ST_X(mon_noeud_geom) as x, ST_Y(mon_noeud_geom) as y from mes_noeuds_a_desservir' , <- ici c'est la requete du réseau de noeud 'SELECT string_agg(CAST(mon_noeud_id as varchar), ',') FROM mes_cibles' , <- ici la liste des noeuds, soit par requete, soit en dur xxx) <- ici le noeud de départ
En sortie, le numéro de la ligne correspond à l'ordre de passage du vertex_id (qui vaut source_id = mon_noeud_id) donc pour l'intégrer dans la requête, il suffit d'un :
Code:
SELECT a.*, row_number() OVER () as rnum FROM tsp (<les deux requêtes et le noeud de départ>) as a
Bon, il y a peut-être des fautes de frappe dans ce que j'ai écrit, n'ayant pas de réseau à tester sous la main, mais dans le principe, c'est ça.
Hien.
Hors ligne
#7 Wed 28 June 2017 12:12
- bruhnild
- Participant actif
- Lieu: Lyon
- Date d'inscription: 7 Jun 2014
- Messages: 130
Re: Pgrouting - itinéraire en deux temps
Bonjour,
Tout d'abord, merci pour votre aide et exemples de requetes.
Cette requête fonctionne bien (avec un temps de calcul anormalement long - 22 minutes) mais juste d'un point (6) à l'autre (5)
Code:
SELECT seq, id1, id2, round(cost::numeric, 2) AS cost FROM pgr_tsp('SELECT node_id as id, longitude as x,latitude as y FROM noeuds_a_desservir ORDER BY id', 6, 5);
Tandis que cette requete, reprise de celle que vous m'indiquez dans votre dernier message ne fonctionne pas avec mes données :
Code:
SELECT * from pgr_tsp ('SELECT node_id as source_id, longitude as x, latitude as y from noeuds_a_desservir' , 'SELECT string_agg(CAST(node_id as varchar), ',') FROM mes_cibles' , 6987)
Sauriez vous me dire d'où vient le problème?
Marine.
Hors ligne
#8 Wed 28 June 2017 12:43
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: Pgrouting - itinéraire en deux temps
Tandis que cette requete, reprise de celle que vous m'indiquez dans votre dernier message ne fonctionne pas avec mes données :
Code:
SELECT * from pgr_tsp ('SELECT node_id as source_id, longitude as x, latitude as y from noeuds_a_desservir' , 'SELECT string_agg(CAST(node_id as varchar), ',') FROM mes_cibles' , 6987)Sauriez vous me dire d'où vient le problème?
Marine.
Bonjour,
Pensez à mettre le message d'erreur, et éventuellement un petit jeu de données permettant de reproduire le problème.
Une requête seule ne permet pas de voir ou se situe le pb (à moins d'une erreur de syntaxe évidente).
Nicolas
Hors ligne
#9 Wed 28 June 2017 13:30
- bruhnild
- Participant actif
- Lieu: Lyon
- Date d'inscription: 7 Jun 2014
- Messages: 130
Re: Pgrouting - itinéraire en deux temps
Voici le message d'erreur pour cette requete :
Code:
SELECT * from pgr_tsp ('SELECT node_id as source_id, longitude as x, latitude as y from noeuds_a_desservir' , 'SELECT string_agg(CAST(node_id as varchar), ',') FROM mes_cibles' , 6987)
ERREUR: syntaxe en entrée invalide pour l'entier : « SELECT string_agg(CAST(node_id as varchar), »
LINE 3: 'SELECT string_agg(CAST(node_id as varchar), ',') FROM mes_c...
^
********** Erreur **********
ERREUR: syntaxe en entrée invalide pour l'entier : « SELECT string_agg(CAST(node_id as varchar), »
État SQL :22P02
Caractère : 113
J'ai également joins en PJ mon jeu de données pour des tests éventuels.
Merci d'avance.
Marine.
Hors ligne
#10 Wed 28 June 2017 15:07
- atilio
- Participant actif
- Lieu: Brest
- Date d'inscription: 17 Jan 2006
- Messages: 80
Re: Pgrouting - itinéraire en deux temps
est-ce qu'il ne serait pas plus approprié d'utiliser un array_agg au lieu du string_agg? Je pense que c'est une liste d'entiers et non de strings qui est utilisée par pgr_tsp
Hors ligne
#11 Thu 29 June 2017 09:51
- tqhien
- Participant actif
- Lieu: Clamart
- Date d'inscription: 22 Apr 2011
- Messages: 78
Re: Pgrouting - itinéraire en deux temps
Je viens de voir qu'il y a une grosse modif des paramètres selon la version de pgrouting. Mes explications étaient valables pour la version 1.x.
Pour la version 2.x, c'est légèrement modifié : la première requête intègre tous les noeuds à desservir (idem qu'avant sauf que les champs sont id, x et y comme tu l'as indiqué Marine) Par contre, il suffit d'ajouter le noeud de départ (et éventuellement celui d'arrivée), donc la requête que tu trouves anormalement longue est pourtant la bonne, si tu souhaites passer par tous les noeuds du réseau. Or, ce sont plustôt tes cibles !
La requête serait plutôt celle-ci :
Code:
SELECT seq, id1, id2, round(cost::numeric, 2) AS cost FROM pgr_tsp('SELECT node_id as id, longitude as x,latitude as y FROM mes_cibles ORDER BY id', 6, 5);
Pour une tournée de 100 noeuds à desservir, le calcul se fait en 0.4s.
Hors ligne
#12 Thu 29 June 2017 10:03
- tqhien
- Participant actif
- Lieu: Clamart
- Date d'inscription: 22 Apr 2011
- Messages: 78
Re: Pgrouting - itinéraire en deux temps
Autre précision : mon tableau résultat m'indique seulement l'ordre des noeuds à atteindre, les deux colonnes id1 (matrice de distance interne) et id2 (identifiant du noeud à atteindre) sont identiques -ici départ du noeud 50)
Code:
seq id1 id2 cost 0 50 50 1466.10343482386 1 60 60 192.610186749464 2 59 59 774.945012095801 3 58 58 472.514839841867 4 16 16 735.235782257773 5 14 14 568.802381746603 6 17 17 261.616502798908 7 15 15 736.156584914652 8 3 3 512.742947608021 9 2 2 983.630360151605 10 4 4 690.105171508342
Pour avoir sur la même ligne l'id2 de la ligne précédente, il y a la fonction window de postgresql :
Code:
select seq, id1, id2, cost, lag(id2) OVER (ORDER by seq) as id_prec from pgr_tsp (...)
ce qui donne
Code:
seq id1 id2 cost id_prec 0 50 50 1466.10343482386 1 60 60 192.610186749464 50 2 59 59 774.945012095801 60 3 58 58 472.514839841867 59 4 16 16 735.235782257773 58 5 14 14 568.802381746603 16 6 17 17 261.616502798908 14 7 15 15 736.156584914652 17 8 3 3 512.742947608021 15 9 2 2 983.630360151605 3 10 4 4 690.105171508342 2
Hors ligne