Contenu | Rechercher | Menus

Annonce

Ubuntu 16.04 LTS
Commandez vos DVD et clés USB Ubuntu-fr !

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

#1 Le 22/11/2016, à 08:47

chris_wafer

Script pour optimiser une tournée

Bonjour,

J'ai une liste d'adresse dans un fichier, et je voudrais faire un script qui me permettent de me réorganiser la liste afin que je parcoure toutes les adresses dans le moins de temps possible.
C'est en fait pour optimiser une tournée.

Quelqu'un aurait une idée?

Merci.

Hors ligne

#2 Le 22/11/2016, à 09:04

pingouinux

Re : Script pour optimiser une tournée

Bonjour,
C'est le fameux problème du voyageur de commerce. Pour chaque couple d'adresses, il faut connaître le temps pour aller de l'une à l'autre. Une recherche exhaustive ne peut se faire que pour un petit nombre d'adresses, car le temps de calcul augmente très vite avec ce nombre.
Il existe peut-être des algorithmes donnant une solution approchée.

Édité : Quel est le nombre d'adresses ?

Dernière modification par pingouinux (Le 22/11/2016, à 09:10)

En ligne

#3 Le 22/11/2016, à 09:17

chris_wafer

Re : Script pour optimiser une tournée

Il y a environ une centaine d'adresse.
Où trouver un algorithme et comment faire?
Ça me serait vraiment très utile.

Hors ligne

#4 Le 22/11/2016, à 09:22

pingouinux

Re : Script pour optimiser une tournée

Voici un article qui peut t'aiguiller, mais je ne sais pas faire : Le problème du voyageur de commerce : introduction
Tu trouveras de nombreux articles à ce sujet sur internet.

En ligne

#5 Le 22/11/2016, à 09:55

chris_wafer

Re : Script pour optimiser une tournée

Il n'y aurait pas des scripts existant sur quoi ce baser?

Hors ligne

#6 Le 22/11/2016, à 09:59

chris_wafer

Re : Script pour optimiser une tournée

En fait, c'est surtout comment lister la distance entre chaque adresse automatiquement?

Hors ligne

#7 Le 22/11/2016, à 11:42

jean bono

Re : Script pour optimiser une tournée

Salut,
Si tu comprends l'anglais, ceci peut t'aider
http://analystcave.com/excel-calculate- … addresses/

Hors ligne

#8 Le 22/11/2016, à 12:23

chris_wafer

Re : Script pour optimiser une tournée

Merci.
Et comment on pourrait appeler ça dans un un script? L'API de google où on lui donne deux adresses?

Merci.

Hors ligne

#9 Le 22/11/2016, à 12:54

Hizoka

Re : Script pour optimiser une tournée

Salut, petite contribution smile

function CalculDistance
{
depart="${1}"
arrive="${2}"
distance=""
temps=""

while read ligne
do
  if [[ ${ligne} =~ '"text" :' ]]
  then
    if [[ -z ${distance} ]]
    then
      distance="${ligne##*: ?}"
      distance="${distance/%?,}"
    else
      temps="${ligne##*: ?}"
      temps="${temps/%?,}"
    fi
  fi
done < <(curl https://maps.googleapis.com/maps/api/distancematrix/json?origins=${depart}\&destinations=${arrive}\&language=fr)
echo "la distance entre ${depart} et ${arrive} est de ${distance} et il faut compter ${temps} pour la parcourir en voiture"
}

exemple :

CalculDistance Rouen Paris
=> la distance entre Rouen et Paris est de 136 km et il faut compter 1 heure 45 min pour la parcourir en voiture

Pour la suite, il est imaginable de boucler sur un fichier avec les adresses, de comparer toutes les adresses une à une.
Pour la suite faut reflechir un peu plus tongue

Perso je me dis qu'il vaudrait mieux faire ça en python mais bon...
genre un dico par adresse qu'il faut classer par ordre,
le trajet le plus court est utilisé,
on charge à ce moment là le dico de nouvelle destination en y supprimant les adresses déjà visitées
et ainsi de suite...

Une idée comme une autre je pense...

Dernière modification par Hizoka (Le 22/11/2016, à 13:09)

Hors ligne

#10 Le 22/11/2016, à 14:11

chris_wafer

Re : Script pour optimiser une tournée

Merci beaucoup, c'est super!!!

Et pour l'implémentation de l'Algorithme génétique? Car après faudra faire ça?

Merci d'"avance pour votre aide.

Hors ligne

#11 Le 22/11/2016, à 19:44

Hizoka

Re : Script pour optimiser une tournée

En fait je n'ai pas lu les pages tongue

je suis parti sur un truc un peu perso du genre en python3:

from urllib.request import urlopen

# Fonction qui regarde la ville la plus proche en temps
def Tri(Depart, VillesVisitees):
    x = []
    for Ville, Values in BigDico[Depart].items():
        if Ville not in VillesVisitees:
            x.append((int(Values[1]), Values[0], Ville))
    x.sort()
    return(x[0][2])


# Villes à visiter
Villes = ["Rouen", "Paris", "Rennes", "Lyon", "Strasbourg"] # Liste des villes
VillesVisitees = ["Rouen"] # Ville de départ

# Dictionnaire qui contiendra les infos
BigDico = {}

# 1ere boucle travaillant sur les villes
for Depart in Villes:
    # Ajoute la ville à la liste
    BigDico[Depart] = {}
    # 2e boucle traitant les villes
    for Arrive in Villes:
        # Si les 2 villes sont les mêmes, on saute ce calcul
        if Depart == Arrive:
            continue
        # On ajoute la nouvelle destination à la ville de départ
        BigDico[Depart][Arrive] = []
        # On ajoute les infos sur le trajet
        for Ligne in urlopen("https://maps.googleapis.com/maps/api/distancematrix/json?origins={}&destinations={}&language=fr".format(Depart, Arrive)).read().decode('UTF-8').split("\n"):
            if '"value" :' in Ligne:
                BigDico[Depart][Arrive].append(Ligne.split(' : ')[1])

# Tri les temps d'acces par ordre
Trajet = [Villes[0]]
VillesVisitees.append(Villes[0])

NextVille = Tri(Villes[0], VillesVisitees)
Trajet.append(NextVille)

while len(Villes) != len(VillesVisitees):
    VillesVisitees.append(NextVille)
    NextVille = Tri(NextVille, VillesVisitees)
    Trajet.append(NextVille)

ça donne ça :

['Rouen', 'Paris', 'Rennes', 'Lyon', 'Strasbourg']

et ça semble en effet être à chaque fois le trajet le plus rapide...

Après il y a surement une meilleur logique...

Pour travailler sur la distance au lieu du temps, il suffit de changer ça :

def Tri(Depart, VillesVisitees):
    x = []
    for Ville, Values in BigDico[Depart].items():
        if Ville not in VillesVisitees:
            x.append((int(Values[1]), Values[0], Ville))
    x.sort()
    return(x[0][2])

en

def Tri(Depart, VillesVisitees):
    x = []
    for Ville, Values in BigDico[Depart].items():
        if Ville not in VillesVisitees:
            x.append((int(Values[0]), Values[1], Ville))
    x.sort()
    return(x[0][2])

Hors ligne

#12 Le 22/11/2016, à 19:52

chris_wafer

Re : Script pour optimiser une tournée

Merci beaucoup.

Mais l’algorithme risque d'être long pour 120 villes, non?

Hors ligne

#13 Le 22/11/2016, à 20:00

Hizoka

Re : Script pour optimiser une tournée

Je regarde pour éviter les récupérations doublons des infos, mais oui ça va prendre un peu de temps enfin bon, il suffit d'attendre...

EDIT, version un chouille plus rapide :

from urllib.request import urlopen

# Fonction qui regarde la ville la plus proche en temps
def Tri(Depart, VillesVisitees):
    x = []
    
    for Ville, Values in BigDico[Depart].items():
        if Ville not in VillesVisitees:
            x.append((int(Values[1]), Values[0], Ville))
            
    x.sort()
    
    return(x[0][2])


# Villes à visiter
Villes = ["Rouen", "Paris", "Rennes", "Lyon", "Strasbourg", "Le Havre", "Sotteville les Rouen", "Quimper", "Londres", "Brest", "Berlin"] # Liste des villes
VillesVisitees = ["Rouen"] # Ville de départ

# Dictionnaire qui contiendra les infos
BigDico = {}

# 1ere boucle travaillant sur les villes
for Depart in Villes:
    # Ajoute la ville à la liste
    if Depart not in BigDico.keys():
        BigDico[Depart] = {}
    
    # 2e boucle traitant les villes
    for Arrive in Villes:
        # Si les 2 villes sont les mêmes, on saute ce calcul
        if Depart == Arrive:
            continue
            
        # Pour eviter de calculer plusieurs fois les mêmes trajets
        if Arrive not in BigDico.keys():
            BigDico[Arrive] = {}
            
        # On ajoute la nouvelle destination à la ville de départ
        if Arrive not in BigDico[Depart].keys():
            BigDico[Depart][Arrive] = []
            BigDico[Arrive][Depart] = []
        
            # On ajoute les infos sur le trajet
            for Ligne in urlopen("https://maps.googleapis.com/maps/api/distancematrix/json?origins={}&destinations={}&language=fr".format(Depart.replace(" ", "+"), Arrive.replace(" ", "+"))).read().decode('UTF-8').split("\n"):
                if '"value" :' in Ligne:
                    BigDico[Depart][Arrive].append(Ligne.split(' : ')[1])
                    BigDico[Arrive][Depart].append(Ligne.split(' : ')[1])

                
# Tri les temps d'acces par ordre
Trajet = [Villes[0]]

NextVille = Tri(Villes[0], VillesVisitees)
Trajet.append(NextVille)
VillesVisitees.append(NextVille)

while len(Villes) != len(VillesVisitees):
    print("ville de depart", NextVille)
    NextVille = Tri(NextVille, VillesVisitees)
    Trajet.append(NextVille)
    VillesVisitees.append(NextVille)

print("Les trajets les plus rapides seraient :", " => ".join(Trajet))

Il est évident qu'on peut améliorer le code et que ça doit être un chouille long (le temps de réponse du serveur) mais l'avantage c'est que c'est automatique...
Il est possible dans l'idée de faire du multi thread sur la récup des infos, ça ferait une très grosse différence si tu as plusieurs core.
EDIT : code modifié pour prendre en compte les espaces

Dernière modification par Hizoka (Le 22/11/2016, à 21:51)

Hors ligne

#14 Le 23/11/2016, à 05:45

chris_wafer

Re : Script pour optimiser une tournée

Bonjour,

Merci merci c'est trop sympa.
L'idéal serait maintenant de lire un fichier où chaque ligne contient une adresse; et ensuite de gérer un fichier qui contient les adresses dans l'ordre de la tournée.
Et aussi, écrire à la fin de la génération le temps ou la distance parcouru.

Merci d'avance.

Hors ligne

#15 Le 23/11/2016, à 18:39

Hizoka

Re : Script pour optimiser une tournée

V'la un code un peu cracra mais qui va bien plus vite si tu as plusieurs coeurs :

#!/bin/python3

from urllib.request import urlopen
from concurrent.futures import ThreadPoolExecutor # Permet de le multi calcul
from psutil import cpu_count # Indique le nombre de cpu


def Internet(Arrive):
    global Depart

    # On ajoute les infos sur le trajet
    for Ligne in urlopen("https://maps.googleapis.com/maps/api/distancematrix/json?origins={}&destinations={}&language=fr".format(Depart.replace(" ", "+"), Arrive.replace(" ", "+"))).read().decode('UTF-8').split("\n"):
        if '"value" :' in Ligne:
            BigDico[Depart][Arrive].append(Ligne.split(' : ')[1])
            BigDico[Arrive][Depart].append(Ligne.split(' : ')[1])



# Fonction qui regarde la ville la plus proche en temps
def Tri(Depart, VillesVisitees):
    x = []

    for Ville, Values in BigDico[Depart].items():
        if Ville not in VillesVisitees:
            x.append((int(Values[1]), int(Values[0]), Ville))

    x.sort()

    global TotalDistance
    TotalDistance += x[0][1]
    global TotalTemps
    TotalTemps += x[0][0]

    return(x[0][2])


# Villes à visiter
TotalDistance = 0
TotalTemps = 0
Villes = []
Fichier = "ListeVilles.txt" # La 1ere ville est celle de départ
Sortie = "VillesTriees.txt"

with open(Fichier, "r") as ListeVilles:
    for Ville in ListeVilles:
        Villes.append(Ville.replace('\n', ''))

VillesVisitees = [Villes[0]] # Ville de départ

# Dictionnaire qui contiendra les infos
BigDico = {}


# 1ere boucle travaillant sur les villes
for Depart in Villes:
    # Ajoute la ville à la liste
    if Depart not in BigDico.keys():
        BigDico[Depart] = {}

    Caca = []

    # 2e boucle traitant les villes
    for Arrive in Villes:
        # Si les 2 villes sont les mêmes, on saute ce calcul
        if Depart == Arrive:
            continue

        # Pour eviter de calculer plusieurs fois les mêmes trajets
        if Arrive not in BigDico.keys():
            BigDico[Arrive] = {}

        # On ajoute la nouvelle destination à la ville de départ
        if Arrive not in BigDico[Depart].keys():
            BigDico[Depart][Arrive] = []
            BigDico[Arrive][Depart] = []

            Caca.append(Arrive)

    with ThreadPoolExecutor(max_workers=cpu_count()) as executor:
        print("Traitement des distances en partant de", Depart)
        for City in Caca:
            executor.submit(Internet, City)



# Tri les temps d'acces par ordre
Trajet = [Villes[0]]

NextVille = Tri(Villes[0], VillesVisitees)
Trajet.append(NextVille)
VillesVisitees.append(NextVille)

while len(Villes) != len(VillesVisitees):
    NextVille = Tri(NextVille, VillesVisitees)
    Trajet.append(NextVille)
    VillesVisitees.append(NextVille)

with open(Sortie, "w") as VillesTriees:
    for Ville in Trajet:
        VillesTriees.write(Ville + '\n')


print("Les trajets les plus rapides seraient :", " => ".join(Trajet))
print("Cela fait un total de {}km et {} heures de trajet".format(int(TotalDistance/1000), int(TotalTemps/3600)))

ex :

Traitement des distances en partant de Rouen
Traitement des distances en partant de Caen
Traitement des distances en partant de Amiens
Traitement des distances en partant de Paris
Traitement des distances en partant de Brest
Traitement des distances en partant de Marseille
Traitement des distances en partant de Grenoble
Traitement des distances en partant de Berlin
Traitement des distances en partant de Moscou
Traitement des distances en partant de Londres
Traitement des distances en partant de Rome
Traitement des distances en partant de Venise
Les trajets les plus rapides seraient : Rouen => Amiens => Paris => Caen => Brest => Londres => Grenoble => Marseille => Venise => Rome => Berlin => Moscou
Cela fait un total de 7723km et 77 heures de trajet

Pour le fichier d'entré :

Fichier = "ListeVilles.txt" # La 1ere ville est celle de départ

Pour le fichier de sortie :

Sortie = "VillesTriees.txt"

Dernière modification par Hizoka (Le 23/11/2016, à 18:42)

Hors ligne

#16 Le 23/11/2016, à 19:28

chris_wafer

Re : Script pour optimiser une tournée

ça me marque :

Traceback (most recent call last):
  File "/home/chris/bin/CDCalulDistance.py", line 5, in <module>
    from psutil import cpu_count # Indique le nombre de cpu
ImportError: cannot import name 'cpu_count'

Hors ligne

#17 Le 23/11/2016, à 19:37

Hizoka

Re : Script pour optimiser une tournée

vla une version ou tu indiques le nombre de core à utiliser :

#!/bin/python3

from urllib.request import urlopen
from concurrent.futures import ThreadPoolExecutor # Permet de le multi calcul


def Internet(Arrive):
    global Depart

    # On ajoute les infos sur le trajet
    for Ligne in urlopen("https://maps.googleapis.com/maps/api/distancematrix/json?origins={}&destinations={}&language=fr".format(Depart.replace(" ", "+"), Arrive.replace(" ", "+"))).read().decode('UTF-8').split("\n"):
        if '"value" :' in Ligne:
            BigDico[Depart][Arrive].append(Ligne.split(' : ')[1])
            BigDico[Arrive][Depart].append(Ligne.split(' : ')[1])



# Fonction qui regarde la ville la plus proche en temps
def Tri(Depart, VillesVisitees):
    x = []

    for Ville, Values in BigDico[Depart].items():
        if Ville not in VillesVisitees:
            x.append((int(Values[1]), int(Values[0]), Ville))

    x.sort()

    global TotalDistance
    TotalDistance += x[0][1]
    global TotalTemps
    TotalTemps += x[0][0]

    return(x[0][2])


NombreDeCoeur = 4
TotalDistance = 0
TotalTemps = 0
Villes = []
Fichier = "ListeVilles.txt" # La 1ere ville est celle de départ
Sortie = "VillesTriees.txt"

with open(Fichier, "r") as ListeVilles:
    for Ville in ListeVilles:
        Villes.append(Ville.replace('\n', ''))

VillesVisitees = [Villes[0]] # Ville de départ

# Dictionnaire qui contiendra les infos
BigDico = {}


# 1ere boucle travaillant sur les villes
for Depart in Villes:
    # Ajoute la ville à la liste
    if Depart not in BigDico.keys():
        BigDico[Depart] = {}

    Caca = []

    # 2e boucle traitant les villes
    for Arrive in Villes:
        # Si les 2 villes sont les mêmes, on saute ce calcul
        if Depart == Arrive:
            continue

        # Pour eviter de calculer plusieurs fois les mêmes trajets
        if Arrive not in BigDico.keys():
            BigDico[Arrive] = {}

        # On ajoute la nouvelle destination à la ville de départ
        if Arrive not in BigDico[Depart].keys():
            BigDico[Depart][Arrive] = []
            BigDico[Arrive][Depart] = []

            Caca.append(Arrive)

    with ThreadPoolExecutor(max_workers=NombreDeCoeur) as executor:
        print("Traitement des distances en partant de", Depart)
        for City in Caca:
            executor.submit(Internet, City)



# Tri les temps d'acces par ordre
Trajet = [Villes[0]]

NextVille = Tri(Villes[0], VillesVisitees)
Trajet.append(NextVille)
VillesVisitees.append(NextVille)

while len(Villes) != len(VillesVisitees):
    NextVille = Tri(NextVille, VillesVisitees)
    Trajet.append(NextVille)
    VillesVisitees.append(NextVille)

with open(Sortie, "w") as VillesTriees:
    for Ville in Trajet:
        VillesTriees.write(Ville + '\n')


print("Les trajets les plus rapides seraient :", " => ".join(Trajet))
print("Cela fait un total de {}km et {} heures de trajet".format(int(TotalDistance/1000), int(TotalTemps/3600)))

tu modifies

NombreDeCoeur = 4

tu lances bien le logiciel en utilisant python3 ?

Hors ligne

#18 Le 23/11/2016, à 20:06

chris_wafer

Re : Script pour optimiser une tournée

Je tape :

 python3 <MonScript>
 

Une idée?
Je pensais aussi que tu pourrais rajouter un message d'erreur lorsque les villes sont erronées (qu'on ne trouve pas)?

Merci encore pour ton superbe travail!

Hors ligne

#19 Le 23/11/2016, à 20:19

chris_wafer

Re : Script pour optimiser une tournée

J'ai remplacé par ça et ça marche :

from multiprocessing import cpu_count

Hors ligne

#20 Le 23/11/2016, à 20:27

chris_wafer

Re : Script pour optimiser une tournée

Une version pour afficher une erreur et ignorer lorsque l'adresse est pas valide?

Hors ligne

#21 Le 24/11/2016, à 15:24

Hizoka

Re : Script pour optimiser une tournée

Une version un peu crados :

#!/bin/python3
from urllib.request import urlopen
from concurrent.futures import ThreadPoolExecutor # Permet de le multi calcul
from multiprocessing import cpu_count # Indique le nombre de cpu


def Internet(Arrive):
    global Depart

    if Depart in VillesInconnues or Arrive in VillesInconnues:
        return

    # On ajoute les infos sur le trajet
    for Ligne in urlopen("https://maps.googleapis.com/maps/api/distancematrix/json?origins={}&destinations={}&language=fr".format(Depart.replace(" ", "+"), Arrive.replace(" ", "+"))).read().decode('UTF-8').split("\n"):
        if '"value" :' in Ligne:
            BigDico[Depart][Arrive].append(Ligne.split(' : ')[1])
            BigDico[Arrive][Depart].append(Ligne.split(' : ')[1])

        elif '"destination_addresses" : [ "" ],' in Ligne:
            VillesInconnues.add(Arrive)

        elif '"origin_addresses" : [ "" ],' in Ligne:
            VillesInconnues.add(Depart)


# Fonction qui regarde la ville la plus proche en temps
def Tri(Depart, VillesVisitees):
    try:
        x = []

        for Ville, Values in BigDico[Depart].items():
            if Ville not in VillesVisitees:
                x.append((int(Values[1]), int(Values[0]), Ville))

        x.sort()

        global TotalDistance
        TotalDistance += x[0][1]
        global TotalTemps
        TotalTemps += x[0][0]

        return(x[0][2])

    except:
        pass

# Villes à visiter
TotalDistance = 0
TotalTemps = 0
Villes = []
VillesInconnues = set()
Fichier = "ListeVilles.txt" # La 1ere ville est celle de départ
Sortie = "VillesTriees.txt"

with open(Fichier, "r") as ListeVilles:
    for Ville in ListeVilles:
        Villes.append(Ville.strip())

VillesVisitees = [Villes[0]] # Ville de départ

# Dictionnaire qui contiendra les infos
BigDico = {}


# 1ere boucle travaillant sur les villes
for Depart in Villes:
    # Ajoute la ville à la liste
    if Depart not in BigDico.keys():
        BigDico[Depart] = {}

    Caca = []

    # 2e boucle traitant les villes
    for Arrive in Villes:
        # Si les 2 villes sont les mêmes, on saute ce calcul
        if Depart == Arrive:
            continue

        # Pour eviter de calculer plusieurs fois les mêmes trajets
        if Arrive not in BigDico.keys():
            BigDico[Arrive] = {}

        # On ajoute la nouvelle destination à la ville de départ
        if Arrive not in BigDico[Depart].keys():
            BigDico[Depart][Arrive] = []
            BigDico[Arrive][Depart] = []

            Caca.append(Arrive)

    with ThreadPoolExecutor(max_workers=cpu_count()) as executor:
        for City in Caca:
            executor.submit(Internet, City)


# Supprime les villes iconnues
for Ville in VillesInconnues:
    print("Impossible de trouver la ville", Ville)

    try:
        del(BigDico[Ville])
    except:
        pass

    popo = dict(BigDico)

    for MiniDict in popo:
        try:
            del(BigDico[MiniDict][Ville])
        except:
            pass


# Tri les temps d'acces par ordre
Trajet = [Villes[0]]

NextVille = Tri(Villes[0], VillesVisitees)
Trajet.append(NextVille)
VillesVisitees.append(NextVille)

# Boucle traitant toutes les villes
while len(Villes) != len(VillesVisitees) + len(VillesInconnues):
    NextVille = Tri(NextVille, VillesVisitees)
    Trajet.append(NextVille)
    VillesVisitees.append(NextVille)


# Écriture dans le fichier de sortie
with open(Sortie, "w") as VillesTriees:
    for Ville in Trajet:
        if Ville:
            VillesTriees.write(Ville + '\n')


# informations
print("Les trajets les plus rapides seraient :", " => ".join(Trajet))
print("Cela fait un total de {}km et {} heures de trajet".format(int(TotalDistance/1000), int(TotalTemps/3600)))

ex :

Impossible de trouver la ville Kakakokikokukp
Impossible de trouver la ville Salololollope
Les trajets les plus rapides seraient : Rouen => Le Havre => Paris => Berlin
Cela fait un total de 1340km et 13 heures de trajet

Hors ligne

#22 Le 24/11/2016, à 18:44

chris_wafer

Re : Script pour optimiser une tournée

Si j'ai un fichier avec ça :

Bordeaux
Paris
Lille
Toulouse
Narbonne
Marseille
Léognan

Ca me met cette erreur :

Traceback (most recent call last):
  File "/home/chris/bin/CDCalulDistance.py", line 135, in <module>
    print("Les trajets les plus rapides seraient :", " => ".join(Trajet))
TypeError: sequence item 1: expected str instance, NoneType found

Hors ligne

#23 Le 24/11/2016, à 19:00

Hizoka

Re : Script pour optimiser une tournée

les accents semblent poser probleme...
sans, ça fonctionne...

Hors ligne

#24 Le 24/11/2016, à 19:27

chris_wafer

Re : Script pour optimiser une tournée

Une idée pour gérer les accents?

Hors ligne

#25 Le 24/11/2016, à 19:57

Hizoka

Re : Script pour optimiser une tournée

#!/bin/python3
from urllib.request import urlopen
from urllib.parse import quote
from concurrent.futures import ThreadPoolExecutor # Permet de le multi calcul
from multiprocessing import cpu_count # Indique le nombre de cpu



# Variables
TotalDistance = 0
TotalTemps = 0
Villes = []
VillesInconnues = set()
Stop=False
StopMessage=""
Cle="AIzaSyD5UNZCB4zhybm0f8Kf1vxOhsprKCFVIyE"
#Cle="AIzaSyB3mt5IkwuxFVS2H7pcdy4aqrkDGhsi_ao"
Fichier = "ListeVilles.txt" # La 1ere ville est celle de départ
Sortie = "VillesTriees.txt"


def Internet(Arrive):
    global Depart
    global Stop

    if Depart in VillesInconnues or Arrive in VillesInconnues or Stop:
        return

    # On ajoute les infos sur le trajet
    print(Depart, "<=>", Arrive)
    for Ligne in urlopen("https://maps.googleapis.com/maps/api/distancematrix/json?origins={}&destinations={}&language=fr&key={}".format(quote(Depart.replace(" ", "+")), quote(Arrive.replace(" ", "+")), Cle)).read().decode('UTF-8').split("\n"):
        if '"value" :' in Ligne:
            BigDico[Depart][Arrive].append(Ligne.split(' : ')[1])
            BigDico[Arrive][Depart].append(Ligne.split(' : ')[1])

        elif '"destination_addresses" : [ "" ],' in Ligne:
            VillesInconnues.add(Arrive)

        elif '"origin_addresses" : [ "" ],' in Ligne:
            VillesInconnues.add(Depart)

        elif '"error_message" :' in Ligne:
            Stop=True

            global StopMessage
            StopMessage = ":".join(Ligne.split(":")[1:])



# Fonction qui regarde la ville la plus proche en temps
def Tri(Depart, VillesVisitees):
    try:
        x = []

        for Ville, Values in BigDico[Depart].items():
            if Ville not in VillesVisitees:
                x.append((int(Values[1]), int(Values[0]), Ville))

        x.sort()

        global TotalDistance
        TotalDistance += x[0][1]
        global TotalTemps
        TotalTemps += x[0][0]

        return(x[0][2])
    except:
        print("La fonction tri n'a pas bien fonctionnée avec", Depart, VillesVisitees)
        print(BigDico[Depart])



with open(Fichier, "r") as ListeVilles:
    for Ville in ListeVilles:
        Villes.append(Ville.strip())

VillesVisitees = [Villes[0]] # Ville de départ

# Dictionnaire qui contiendra les infos
BigDico = {}


# 1ere boucle travaillant sur les villes
for Depart in Villes:
    # Ajoute la ville à la liste
    if Depart not in BigDico.keys():
        BigDico[Depart] = {}

    Caca = []

    # 2e boucle traitant les villes
    for Arrive in Villes:
        # Si les 2 villes sont les mêmes, on saute ce calcul
        if Depart == Arrive:
            continue

        # Pour eviter de calculer plusieurs fois les mêmes trajets
        if Arrive not in BigDico.keys():
            BigDico[Arrive] = {}

        # On ajoute la nouvelle destination à la ville de départ
        if Arrive not in BigDico[Depart].keys():
            BigDico[Depart][Arrive] = []
            BigDico[Arrive][Depart] = []

            Caca.append(Arrive)

    with ThreadPoolExecutor(max_workers=cpu_count()) as executor:
        for City in Caca:
            executor.submit(Internet, City)


# Supprime les villes iconnues
for Ville in VillesInconnues:
    print("Impossible de trouver la ville", Ville)

    try:
        del(BigDico[Ville])
    except:
        pass

    popo = dict(BigDico)

    for MiniDict in popo:
        try:
            del(BigDico[MiniDict][Ville])
        except:
            pass


if Stop:
    print("Une erreur est survenue :", StopMessage)
    exit()


for Ville, Values in BigDico[Depart].items():
    print(Ville, Values)

# Tri les temps d'acces par ordre
Trajet = [Villes[0]]

NextVille = Tri(Villes[0], VillesVisitees)
Trajet.append(NextVille)
VillesVisitees.append(NextVille)

# Boucle traitant toutes les villes
while len(Villes) != len(VillesVisitees) + len(VillesInconnues):
    NextVille = Tri(NextVille, VillesVisitees)
    Trajet.append(NextVille)
    VillesVisitees.append(NextVille)


# Écriture dans le fichier de sortie
with open(Sortie, "w") as VillesTriees:
    for Ville in Trajet:
        if Ville:
            VillesTriees.write(Ville + '\n')


# informations
print("Les trajets les plus rapides seraient :", " => ".join(Trajet))
print("Cela fait un total de {}km et {} heures de trajet".format(int(TotalDistance/1000), int(TotalTemps/3600)))
Les trajets les plus rapides seraient : Bordeaux => Léognan => Toulouse => Narbonne => Marseille => Paris => Lille
Cela fait un total de 1668km et 16 heures de trajet

Va te falloir te mettre à python smile

Dernière modification par Hizoka (Le 26/11/2016, à 14:57)

Hors ligne