Examen final, Janvier 2015đź”—
Consignes:
Vous avez accès à tout l’internet « statique » (hors mail, tchat, forum, etc.), y compris donc au cours en ligne.
Ne soumettez pas de codes non-fonctionnels (i.e. provoquant une exception à l’interprétation, avant même l’exécution): les erreurs de syntaxe seront lourdement sanctionnées.
Respectez scrupuleusement les directives de l’énoncé (nom des variables, des méthodes, des fichiers, etc.), en particulier concernant le nom des fichiers à renvoyer aux correcteurs.
Exerciceđź”—
Un appareil de vélocimétrie a mesuré une vitesse à intervalle de temps
régulier puis à sorti le fichier texte velocimetrie.dat
(attention à l’entête). Vous écrirez un script python
« exo_nom_prénom.py
 » (sans accent) utilisant matplotlib
qui
générera, affichera et sauvegardera sous le nom « exo_nom_prénom.pdf
 »
une figure composée de trois sous-figures, l’une au dessus de l’autre:
la vitesse en mm/s mesurée en fonction du temps,
le déplacement en mètres en fonction du temps. On utilisera volontairement une intégration naïve à partir de zéro via la fonction
numpy.cumsum()
,l’accélération en m/s² en fonction du temps. On utilisera volontairement une dérivation naïve à deux points:
\[f'(x) \approx \frac{f(x+h)-f(x-h)}{2h}\]via la fonction
numpy.diff()
. Attention, si l’entrée de cette fonction est un tableau de taille N, sa sortie est un tableau de taille N-1.
Le script doit lire le fichier velocimetrie.dat
stocké dans le
répertoire courant. On prendra soin des noms des axes et des unités
physiques. Si les trois axes des abscisses sont identiques, seul
celui de la troisième sous-figure peut être nommé.
Le problème du voyageur de commerce🔗
Introductionđź”—
Le problème du voyageur de commerce est un problème d’optimisation consistant à déterminer le plus court chemin reliant un ensemble de destinations. Il n’existe pas d’algorithme donnant la solution optimale en un temps raisonnable (problème NP-complet), mais l’on peut chercher à déterminer des solutions approchées.
On va se placer ici dans le cas d’un livreur devant desservir une seule fois chacune des n destinations d’une ville américaine où les rues sont agencées en réseau carré (Figure). On utilise la « distance de Manhattan » (norme L1) entre deux points \(A(x_A, y_A)\) et \(B (x_B, y_B)\):
En outre, on se place dans le cas où les coordonnées des destinations
sont entières, comprises entre 0
(inclus) et TAILLE = 50
(exclus). Deux destinations peuvent Ă©ventuellement avoir les mĂŞmes
coordonnées.
Les instructions suivantes doivent permettre de définir les classes
nécessaires (Ville
et Trajet
) et de développer deux algorithmes
approchés (heuristiques): l’algorithme du plus proche voisin, et
l’optimisation 2-opt. Seules la librairie standard et la librairie
numpy
sont utilisables si nécessaire.
Un squelette du code, définissant l’interface de programmation et
incluant des tests unitaires (Ă utiliser avec py.test
), vous est
fourni: exam_1501.py
. Après l’avoir renommé
« pb_nom_prénom.py
 » (sans accent), l’objectif est donc de
compléter ce code progressivement, en suivant les instructions
suivantes.
Une ville-test de 20 destinations est fournie: ville.dat
(Fig.), sur laquelle des tests de lecture et d’optimisation seront
réalisés.
Classe Ville
đź”—
Les n coordonnées des destinations sont stockées dans l’attribut
destinations
, un tableau numpy
d’entiers de format (n, 2)
.
__init__()
: initialisation d’une ville sans destination (déjà implémenté, ne pas modifier).aleatoire(n)
: création de n destinations aléatoires (utilisernumpy.random.randint()
).lecture(nomfichier)
: lecture d’un fichier ASCII donnant les coordonnées des destinations.ecriture(nomfichier)
: écriture d’un fichier ASCII avec les coordonnées des destinations.nb_trajet()
: retourne le nombre total (entier) de trajets: \((n-1)!/2\) (utilisermath.factorial()
).distance(i, j)
: retourne la distance (Manhattan-L1) entre les deux destinations de numéro i et j.
Classe Trajet
đź”—
L’ordre des destinations suivi au cours du trajet est stocké dans
l’attribut etapes
, un tableau numpy
d’entiers de format (n,)
.
__init__(ville, etapes=None)
: initialisation sur uneville
. Si la listeetapes
n’est pas spécifiée, le trajet par défaut est celui suivant les destinations deville
.longueur()
: retourne la longueur totale du trajet bouclé (i.e. revenant à son point de départ).
Heuristique Plus proche voisinđź”—
Ville.plus_proche(i, exclus=[])
: retourne la destination la plus proche de la destination i (au sens deVille.distance()
), hors les destinations de la listeexclus
.Ville.trajet_voisins(depart=0)
: retourne unTrajet
déterminé selon l’heuristique des plus proches voisins (i.e. l’étape suivante est la destination la plus proche hors les destinations déjà visitées) en partant de l’étape initialedepart
.
Heuristique Opt-2đź”—
Trajet.interversion(i, j)
: retourne un nouveauTrajet
résultant de l’interversion des 2 étapes i et j.Ville.optimisation_trajet(trajet)
: retourne leTrajet
le plus court de tous les trajets « voisins » Ătrajet
(i.e. résultant d’une simple interversion de 2 étapes), outrajet
lui-même s’il est le plus court.Ville.trajet_opt2(trajet=None, maxiter=100)
: à partir d’untrajet
initial (par défaut le trajet des plus proches voisins), retourne unTrajet
optimisé de façon itérative par interversion successive de 2 étapes. Le nombre maximum d’itération estmaxiter
.
Questions hors-barĂŞmeđź”—
À l’aide de la librairie matplotlib
:
Ville.figure()
: trace la figure représentant les destinations de la ville (similaire à la Figure).Ville.figure(trajet=None)
: compléter la méthode précédente pour ajouter un trajet au plan de la ville (utilisermatplotlib.step()
pour des trajets de type « Manhattan »).