TP Ro GM

Vous aimerez peut-être aussi

Vous êtes sur la page 1sur 16

COMPTE RENDU TP RECHERCHE OPERATIONNELLE

1ere année CI : GSMI

20/01/2023

Réalisé par :

Elmarzouki abdessamad

Achi salah - eddine

Boutayeb youness

Encadré par :

Pr. Abdessamad KAMOUSS


TABLE DES MATIERES

REMERCIEMENT............................................................................................................................. 3

INTRODUCTION GÉNÉRALE............................................................................................................ 4

I. MANIPULATION DES GRAPHES EN UTILISANT LE LANGAGE PYTHON :........................................................5


1. Exemple d’un graphe :...........................................................................................................5
2. Détermination des degrés des sommets d’un graphe en utilisant le module NymPy :..........6
3. Calculer les degrés des sommets d’un graphe :.....................................................................7
4. Déterminer le type d’un graphe (eulérien, semi-eulérien ou non eulérien) :..........................8
5. Implémentation de Dijkstra :................................................................................................9
6. Arborescence de graphes G :...............................................................................................10
7. Algorithme de Floyd-Warshall :...........................................................................................12
1) Présentation :.................................................................................................................................12
2) Implémenter la fonction FloydWarshall :.......................................................................................12
II. IMPLÉMENTATION D’UN PROGRAMME PERMETTEZ DE DÉTERMINER LE PLUS LONG CHEMIN :......................13

1
LISTE DES FIGURES

Figure 1: graphe symétrique G................................................................................................5


Figure 2:code return la matrice d'adjasence...........................................................................6
Figure 3:Resultat obtenu de matrice d'adjacence...................................................................6
Figure 4:code des degrés des sommets..................................................................................7
Figure 5:les degrés des sommets............................................................................................7
Figure 6: code qui détermine les types de graphe..................................................................8
Figure 7: Résultat de fonction eulérien...................................................................................9
Figure 8: Code fonction de Dijkstra.........................................................................................9
Figure 9: Résultat de fonction Dijkstra..................................................................................10
Figure 10 : code Arborescence de graphes G........................................................................10
Figure 11: Arborescence de graphes G depuis le sommet 0.................................................11
Figure 12: code la fonction FloydWarshall............................................................................12
Figure 13: résultat de Floyd Warshall sur le graph G.............................................................13
Figure 14: code permet de calculer le plus long chemin.......................................................13
Figure 15: exemple d'graphe.................................................................................................14
Figure 16: résultat de programme........................................................................................15

2
REMERCIEMENT

A l'attention de notre professeur Mr Kamouss

Permettez-nous, notre professeur respecté, de vous exprimer nos


profonds remerciements pour vos efforts inlassables visant à nous doter des outils
scientifiques nécessaires capables de nous guider pour la bonne maîtrise de cette
matière constituant la boussole de notre future carrière.

Nous nous trouvons aujourd'hui incapables de trouver les mots adequats


pouvant vous décrire notre reconnaissance, l’appréciation et le respect que vous
méritez pour les efforts que vous developper, étant conscients de l'énorme travail
qu'exigent cette vocation, de sacrifices et de dévouement pour nous soutenir et
nous guider avec détermination.

Aussi, souhaitons-nous être à la hauteur de votre enseignement de


manière à être capable de traduire avec vigueur et réussite, en concrétisant les
résultats de votre éducation et pouvoir être votre fierté.

3
Introduction générale

La recherche opérationnelle (RO) est une discipline interdisciplinaire qui


s’intéresse à la résolution de problèmes complexes à l’aide de méthodes mathématiques
et informatiques. Elle est utilisée dans de nombreux domaines tels que la gestion de la
production, la logistique, la planification des ressources humaines, la finance et la gestion
de projet.

Python est un langage de programmation open-source, multi-paradigme,


populaire pour son utilisation facile et sa syntaxe lisible. Il peut être utilisé pour de
nombreux types de développement de logiciels, y compris la science des données,
l'apprentissage automatique, la création de scripts et l'application de scripts. Il possède
une grande communauté active et de nombreuses bibliothèques et Framework, tels que
NumPy, pandas, et TensorFlow, qui facilitent la résolution de tâches spécifiques. Il est
également utilisé par de grandes entreprises telles que Google, NASA, et Facebook. En
résumé, Python est un langage de programmation puissant et polyvalent, facile à
apprendre et à utiliser, avec une communauté active et de nombreuses ressources
disponibles.

Dans ce TP, nous allons utiliser langage python pour étudier la théorie des
graphes, par exemple calculer le plus court chemin et le plus long chemin….

4
I. Manipulation des graphes en utilisant le langage Python :
1. Exemple d’un graphe :

Pour calculer la matrice d’adjacence on a utilisé le graphe symétrique G suivant :

Figure 1: graphe symétrique G

La matrice d’adjacence du graphe ci-dessus :

( )
0 5 3 2 + ∞ +∞ + ∞ +∞
5 0 1 +∞ 2 2 + ∞ +∞
3 1 0 1 + ∞ +∞ + ∞ +∞
2 +∞ 1 0 3 +∞ 2 +∞
+∞ 2 +∞ 3 0 4 4 +∞
+ ∞ 2 + ∞ +∞ 4 0 1 7
+ ∞ +∞ + ∞ 2 4 1 0 6
+ ∞ +∞ + ∞ +∞ + ∞ 7 6 0

5
2. Détermination des degrés des sommets d’un graphe en utilisant le module
NymPy :

Figure 2:code return la matrice d'adjasence

Ce code crée une matrice appelée ADJ en utilisant la fonction "matrix" de la bibliothèque
numpy. La matrice est initialisée avec des valeurs spécifiques sous la forme d'un tableau à deux
dimensions, qui représente une matrice d'adjacence. Une matrice d'adjacence est une matrice
carrée utilisée pour représenter un graphe fini, avec des dimensions égales au nombre de
sommets dans le graphe.

Figure 3:Resultat obtenu de matrice d'adjacence

6
3. Calculer les degrés des sommets d’un graphe :

Figure 4:code des degrés des sommets

Ce code définit une fonction appelée "degrés" qui prend en paramètre une matrice
d'adjacence représentée par "ADJ".

La fonction commence par créer une liste vide appelée "Deg" qui stockera le degré de
chaque sommet.

Ensuite, il parcourt les lignes (i) de la matrice, en commençant à 0 et en allant jusqu'à la


longueur de la matrice. Pour chaque ligne, la fonction initialise une variable appelée "deg" à 0, qui
va suivre le degré du sommet actuel.

Ensuite, il parcourt les colonnes (j) de la matrice, en commençant à 0 et en allant jusqu'à la


longueur de la matrice. Pour chaque colonne, il vérifie si la valeur dans la ième ligne et la jème
colonne est supérieure à 0 et différente de l'infini (inf est une variable qui représente l'infini positif).
Si cette condition est vraie, il incrémente la variable "deg" de 1.

Ceci est fait pour chaque sommet, ce qui donne le degré de chaque sommet.

Enfin, la fonction ajoute le degré de chaque sommet à la liste "Deg" et la renvoie.

En résumé, cette fonction prend en entrée une matrice d'adjacence "ADJ" et renvoie une
liste des degrés de chaque sommet dans le graphe représenté par la matrice d'adjacence.

Figure 5:les degrés des sommets

7
4. Déterminer le type d’un graphe (eulérien, semi-eulérien ou non eulérien) :

Figure 6: code qui détermine les types de graphe

Ce code définit une fonction appelée "eulerien" qui prend en paramètre "M", qui est une
matrice d'adjacence. Le but de la fonction est de déterminer si un graphe représenté par la matrice
d'adjacence "M" est Eulérien, semi-Eulérien ou non-Eulérien.

La fonction appelle d'abord une autre fonction appelée "degrés" qui prend en entrée une
matrice d'adjacence et renvoie une liste des degrés de chaque sommet dans le graphe représenté
par la matrice d'adjacence. La fonction utilise ensuite cette liste pour compter le nombre de
sommets ayant un degré impair.

La fonction crée ensuite une variable "n" avec la longueur de la liste des degrés. Il crée une
variable appelée "nb_degre_impair" et l'initialise à 0, cette variable va suivre le nombre de
sommets ayant un degré impair.

Il parcourt la liste des degrés et pour chaque élément, il vérifie s'il est impair en utilisant
l'opérateur modulo (%), s'il est impair, il incrémente "nb_degre_impair" de 1.

Après la boucle, il vérifie la valeur de "nb_degre_impair":

si elle est égale à 0, la fonction renvoie "eulerien", indiquant que le graphe est Eulérien.

si elle est égale à 2, la fonction renvoie "semi-eulerien", indiquant que le graphe est semi-
Eulérien.

sinon, la fonction renvoie "non eulerien", indiquant que le graphe n'est ni Eulérien ni semi-
Eulérien.

En résumé, cette fonction prend en entrée une matrice d'adjacence "M" et renvoie une
chaîne indiquant si le graphe représenté par la matrice est Eulérien, semi-Eulérien ou non-Eulérien
en comptant le nombre de sommets ayant un degré impair

8
Figure 7: Résultat de fonction eulérien

5. Implémentation de Dijkstra :

Figure 8: Code fonction de Dijkstra.

Il parcourt alors à nouveau tous les sommets dans le graphe et pour chaque sommet, il
vérifie si la distance stockée dans la liste "result" est supérieure à la somme de la distance du
dernier sommet visité et le poids de l'arête entre le dernier sommet visité et le sommet courant. Si
c'est vrai, il met à jour la liste "result"

Ce code définit une fonction appelée "Dijkstras" qui prend en paramètre deux variables, "S"
et "M".

La fonction commence par créer une liste appelée "result" et définit tous ses éléments
comme l'infini positif. Ensuite, il définit l'élément à l'index "S" à 0.

La fonction crée également deux listes vides, "visited" et "path", avec la même longueur
que la matrice "M".

Il entre ensuite dans une boucle while qui continue tant que la longueur de "visited" est
égale au nombre de sommets dans le graphe.

9
Dans la boucle, il initialise deux variables "min_dist" et "min_idx" à l'infini positif et à
"None" respectivement.

Il parcourt alors tous les sommets dans le graphe et pour chaque sommet qui n'a pas été
visité, il vérifie si sa distance stockée dans la liste "result" est inférieure à "min_dist". Si c'est vrai, il
met à jour "min_dist" avec la distance et "min_idx" avec l'index du sommet.

Une fois la boucle terminée, il ajoute le sommet avec la distance minimale à la liste
"visited".

Figure 9: Résultat de fonction Dijkstra.

6. Arborescence de graphes G :

Figure 10 : code Arborescence de graphes G


10
Ce code définit une fonction appelée "arbo" qui prend en entrée deux paramètres, "S" et
"M". Il crée un objet graphe vide en utilisant la bibliothèque NetworkX, et ajoute des nœuds au
graphe à partir de la plage de 0 au nombre de lignes de M.

Il initialise ensuite une liste appelée "result" avec le même nombre d'éléments que le
nombre de lignes de "M" et met la valeur à l'index "S" à 0, et tous les autres éléments à l'infini. Il
initialise également une liste vide appelée "visited" et une liste appelée "path" avec le même
nombre d'éléments que le nombre de lignes de "M" et met la valeur à l'index "S" à "S".

Il entre dans une boucle while qui se poursuit tant que le nombre d'éléments dans "visited"
est inférieur au nombre de lignes de "M". Dans la boucle while, il initialise deux variables appelées
"min_dist" et "min_idx" avec l'infini et None respectivement. Il utilise ensuite une boucle for pour
parcourir les lignes de "M" et si la ligne actuelle n'est pas dans "visited" et la valeur correspondante
dans "result" est inférieure à "min_dist", il met à jour "min_dist" et "min_idx" avec la valeur
actuelle et l'index respectivement.

Si "min_idx" est None, il sort de la boucle while.

La prochaine étape, il ajoute l'index "min_idx" courant à la liste "visited" et une autre
boucle for pour parcourir les lignes de "M" et vérifie si la valeur dans "result" à l'index "i" est
supérieure à la valeur dans "result" à "min_idx" plus la valeur dans "M" aux indices "min_idx" et "i".
Si c'est le cas, il met à jour "result" à l'index "i" avec cette nouvelle valeur et met à jour "path" à
l'index "i" en "min_idx".

Enfin, il utilise une boucle for pour parcourir les éléments dans "path" et si l'index n'est pas
égal à la valeur à cet index, il ajoute une arête avec un poids égal à la valeur correspondante dans
"result" de l'index à la valeur à cet index dans "path".

Il crée ensuite un sous-graphe et utilise la fonction de dessin de NetworkX pour dessiner le


graphe avec des étiquettes, et montre le graphe. Il retourne la liste "result" et "path".

Figure 11: Arborescence de graphes G depuis le sommet 0

11
7. Algorithme de Floyd-Warshall :

1) Présentation :

L'algorithme de Floyd-Warshall est un algorithme de programmation dynamique utilisé


pour trouver les plus courts chemins entre tous les sommets dans un graphe pondéré. Il est
similaire à l'algorithme de Dijkstra, mais contrairement à Dijkstra qui ne peut être utilisé que pour
les graphes non négatifs, Floyd-Warshall peut être utilisé pour les graphes avec des poids positifs et
négatifs.

L'algorithme utilise une matrice de distance pour stocker les distances les plus courtes
entre les sommets, commençant par initialiser toutes les distances entre les sommets à l'infini sauf
pour les arêtes directes où la distance est égale au poids de l'arête. Il utilise ensuite une boucle de
trois niveaux pour mettre à jour cette matrice de distance en utilisant la règle de Bellman-Ford pour
trouver les chemins les plus courts en passant par un sommet intermédiaire.

L'algorithme a une complexité de O(n^3), où n est le nombre de sommets dans le graphe,


ce qui le rend inefficace pour les graphes très grands. Cependant, il est utile pour les petits graphes
et peut également être utilisé pour détecter des cycles négatifs dans un graphe.

2) Implémenter la fonction FloydWarshall :

Figure 12: code la fonction FloydWarshall.

Ce code définit une fonction appelée "floyd" qui prend en entrée une matrice "M". Il crée
d'abord une liste à deux dimensions appelée "dist" ayant le même nombre de lignes et de colonnes
que le nombre de lignes dans "M" et initialise tous les éléments avec l'infini positif.

Il utilise ensuite deux boucles imbriquées pour parcourir les lignes et les colonnes de "M"
pour mettre à jour l'élément correspondant dans "dist" avec la valeur de "M" si les indices de ligne
et de colonne ne sont pas égaux, sinon il met la valeur à 0.

12
Ensuite, des boucles imbriquées pour k, i, j sont utilisées pour parcourir les lignes et les
colonnes de "M" et vérifier si la valeur dans "dist" aux indices "i", "j" est supérieure à la somme des
valeurs dans "dist" aux indices "i", "k" et "k", "j". Si c'est le cas, il met à jour "dist" aux indices "i", "j"
avec cette nouvelle valeur.

Finalement, il retourne un tableau numpy de la liste "dist".

Ce code semble implémenter l'algorithme de Floyd-Warshall, qui est utilisé pour trouver le
plus court chemin entre tous les sommets d'un graphe pondéré représenté par la matrice "M". Il
initialise d'abord la matrice de distance avec l'infini sauf les arêtes directes où la distance est le
poids de cette arête. Il utilise des boucles imbriquées pour trouver le plus court chemin entre tous
les sommets en relâchant les arêtes à plusieurs reprises.

Figure 13: résultat de Floyd Warshall sur le graph G.

II. Implémentation d’un programme permettez de déterminer le plus long


chemin :

Figure 14: code permet de calculer le plus long


chemin
13
Ce programme définit une fonction "Best_scr" qui prend en entrée une matrice "M" et
retourne une liste "parcour" contenant les numéros de colonnes des éléments maximaux de
chaque ligne de la matrice.

La fonction commence par initialiser la variable "max" avec la valeur du premier élément de
la première ligne de la matrice (M[0][0]). Elle initialise également la variable "d" à 1, qui sera
utilisée pour stocker le numéro de la colonne de l'élément maximal courant, et la variable "b" à 0,
qui sera utilisée pour parcourir les lignes de la matrice. La liste "parcour" est également initialisée
avec la valeur de "d" pour stocker les numéros de colonnes des éléments maximaux de chaque
ligne.

La fonction utilise ensuite une boucle while pour parcourir chaque ligne de la matrice "M".
Pour chaque ligne, la variable "max" est réinitialisée avec la valeur de la première colonne de cette
ligne (M[b][0]). Il utilise une boucle "for" pour parcourir chaque colonne de la ligne courante, et si
l'élément courant est plus grand que "max", la variable "max" est mise à jour avec cette valeur et la
variable "d" est mise à jour pour stocker le numéro de colonne de cet élément (i+1).

Une fois que toutes les colonnes de la ligne courante ont été parcourues, la variable "b" est
incrémentée de 1 pour passer à la ligne suivante. Le numéro de colonne de l'élément maximal pour
la ligne courante est ajouté à la liste "parcour"

Enfin, une fois que toutes les lignes ont été parcourues, la fonction retourne la liste
"parcour" qui contient les numéros de colonnes des éléments maximaux pour chaque ligne de la
matrice d'entrée.

Pour vérifier le programme on a utilisé le graphe suivant :

Figure 15: exemple d'graphe

14
Figure 16: résultat de programme

15

Vous aimerez peut-être aussi