Boireau Benoît Rakhodai Nima Maitrise d’informatique Groupe 2 UM3 : Assignation de longueurs d’onde dans un réseau à fibres optiques Année 2002/200 Introduction Ce projet a pour objectif d’optimiser les chemins et les longueurs d’onde utilisés dans le cadre d’un réseau à fibres optiques. Pour cela nous modélisons le réseau sous forme de graphes et nous utiliserons différents algorithmes de parcours de graphes pour déterminer les méthodes adaptées selon la configuration du réseau et les requêtes qui vont être effectuées. Ainsi après avoir défini les types et structures de données nécessaires pour représenter les éléments composant le réseau, nous allons implémenter les algorithmes « gloutons » et « suivant charge ». Nous analyserons ensuite ces algorithmes pour définir les méthodes les plus efficaces en fonction du nombre d’arêtes et de requêtes et leur positionnement sur le réseau. I) Implémentation : entrées/sorties, structure de données et algorithmes a. Vue d’ensemble du programme Types et structures de données utilisés : Le graphe est représenté sous forme de matrice d’adjacence dans laquelle les éléments ne sont pas de type booléen mais entier : ils représentent la charge des arêtes. Une intersection dans la matrice contient -1 si l’arête n’existe pas dans le graphe ; un entier positif si l’arête existe. La création de propriétés et méthodes abstraites dans la classe graphe a pour objectif de permettre l’utilisation d’une structure de données différente par la simple création d’une classe implémentant ses propriétés et méthodes, mais dans le cadre de ce projet nous nous sommes limités à l’implémentation par matrice. Nous utilisons aussi une classe chemin qui hérite de la classe vector à laquelle on ajoute une variable int longueurOnde et des méthodes, notamment la méthode comparer, qui permet la comparaison de deux chemins pour déterminer si ils ont au moins un arête en commun. De la même manière nous utilisons souvent la classe vector pour représenter différents types de données en raison de sa souplesse d’utilisation pour représenter différentes structures, les réutiliser et les afficher. Entrées/Sorties et interface : La représentation des données en entrée est celle donnée dans le sujet, soit deux suites d’entiers permettant de représenter le graphe et les requêtes. Les entrées sont données au choix par l’ouverture de fichiers ou en les écrivant directement dans l’interface. Le graphe est automatiquement chargé, il est ensuite possible de l’afficher à l’écran après avoir positionné tous les sommets à la souris dans la zone dédiée de l’interface. De même le choix des algorithmes à utiliser pour définir les chemins et longueurs d’onde est effectué dans l’interface, les résultats sont affichés dans la « comboBox ». Ces résultats sont de la forme x [s0, s1,…,sn] où x est la longueur d’onde et les sommets entre crochets représentent le chemin correspondant à une requête (dans l’ordre de traitement des requêtes, donc en fonction de l’algorithme utilisé). Lorsque le choix de l’algorithme a été fait, les arêtes correspondant au chemin sélectionné changent de couleur ; les charges sont elles aussi affichées sur le graphe. 2 b. Implémentation des algorithmes Recherche des chemins gloutonne : La procédure Requetes.construireCheminsGlouton lit le vecteur contenant l’ensemble des requêtes et les extrait une par une. Elle appelle la procédure reseau.RechercheGloutonne qui va renvoyer un chemin existant entre les deux sommets. S’il existe un chemin, il est ajouté au vecteur chemins qui contiendra l’ensemble des chemins. C’est donc cette dernière procédure qui va rechercher un chemin entre 2 sommets x et y passés en paramètres. Elle traite d’abord plusieurs cas particuliers : - x et y désignent le même sommet - (x,y) est une arête du graphe - il n’existe pas de chemin entre x et y On effectue ensuite un parcours des sommets voisins de x et on crée à chaque fois un vecteur temp qui contient les éléments x et vi. Chaque vecteur temp créé est ensuite ajouté au vecteur chemins (variable locale). On parcourt ensuite les éléments de chemins et pour chaque vecteur qu’il contient on parcourt l’ensemble de ses voisins : si un voisin est y alors le vecteur est retourné comme résultat ; sinon il est ajouté dans un nouveau vecteur temporaire (newChemin), lui-même ajouté dans chemins. Exemple : Vecteur chemins créé : 1 2 3 4 5 1 1 1 1 1 1 2 3 2 3 3 2 4 4 5 4 5 On s’arrête ainsi lorsque le premier chemin reliant x et y est trouvé. Recherche des chemins avec seuil de charge : Cette recherche est effectuée par la procédure Requetes.construireChaminSeuil, on y effectue un parcours de l’ensemble des requêtes et pour chacune on appelle la procédure reseau.rechercheSeuil avec en paramètres les deux postes concernés par la requête et le seuil (initialisé à 1). Tant que l’on ne trouve pas de chemins satisfaisant la condition (les charges des arêtes doivent être inférieures au seuil), on recommence l’opération en incrémentant le seuil. Lorsque l’on trouve un chemin acceptable on l’insère dans le vecteur chemins (retourné en fin de procédure). Attribution gloutonne des longueurs d’onde : Cet algorithme est implémenté dans la procédure requetes.attributionGloutonne. On va parcourir le vecteur contenant tous les chemins (vecteur chemins) ; le chemin lu est stocké dans la variable courant. On refait ensuite un parcours sur le vecteur chemin (variable courant2) et on va utiliser la procédure comparer pour déterminer si les chemins courant et courant2 ont au moins une arête en commun. Ceci nous permet pour chaque chemin de construire un ensemble des longueurs d’onde (vecteur longueursOndes) qu’il ne peut pas 3 prendre. Il suffit ensuite de parcourir ce vecteur pour déterminer la longueur d’onde minimum disponible pour chaque chemin et de lui attribuer. Attribution des longueurs d’onde suivant charge : La procédure correspondant à cet algorithme est requetes.attributionSeuil. L’objectif de cet algorithme est de faire une attribution des longueurs d’onde dans un ordre définit : on attribue une longueur d’onde aux chemins passant par l’arête de plus grande charge et on recommence jusqu'à avoir attribué une longueur d’onde à tous les chemins. La méthode que nous avons retenue pour cet algorithme est de commencer par ordonner le vecteur chemins (contenant l’ensemble des chemins), puis appliquer l’algorithme d’attribution gloutonne des longueurs d’onde sur ce vecteur. Pour ordonner le vecteur chemins nous créons un vecteur contenant les arêtes de charge non nulle par ordre de charge ; pour chacune de ces arêtes nous parcourons le vecteur chemins pour rechercher tous les chemins concernés. Chacun de ces chemins est ajouté dans l’ordre au vecteur cheminsOrdonnes. II)Analyse et discussion a. Algorithme 1 : recherche gloutonne + attribution gloutonne La méthode de recherche gloutonne des chemins ne tient pas compte de la charge des arêtes utilisées pour chaque chemin. Cela peut avoir pour conséquence l’obtention d’arêtes avec une charge très élevée. De même l’attribution gloutonne des longueurs d’onde ne tient pas compte de la charge des arêtes, on prend donc les chemins dans l’ordre dans lequel ils ont été recherchés et on leur attribue la plus petite longueur d’onde disponible. Le nombre de longueurs d’onde obtenues étant directement dépendant de la charge maximale des arêtes, cet algorithme n’utilisera par le nombre minimum de longueurs d’onde dans tous les cas où on pourrait définir les chemins de manière à obtenir une charge maximale inférieure. Exemple pour lequel cet algorithme n’utilise pas le nombre minimum de longueurs d’onde : G=412133424 R=1214 L’ensemble des chemins obtenu est : (12,124), la charge max est 2. Si on considère l’ensemble de chemins (12,134), la charge max est 1. Quelle que soit la méthode utilisée pour attribuer les longueurs d’onde on obtiendra dans le premier cas 2 longueurs d’onde différentes contre une seule dans le deuxième cas. Exemple de couple (G, R) pour lequel cet algorithme fonctionne mieux que les trois autres : G = 12 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 7 10 10 11 11 12 1 7 12 9 R=T Cet algorithme utilise 23 longueurs d’onde dans ce cas, les autres en utilisent 24. b. Algorithme 2 : recherche gloutonne + attribution suivant charge 4 Cet algorithme utilisant la recherche gloutonne, on retrouve le problème de l’algorithme 1, c’est-à-dire que si la recherche des chemins abouti à des charges plus élevées que celles que l’on pourrait avoir. Mais on observe aussi des différences entre ces deux algorithmes sur certains graphes. En effet le fait de trier les chemins en prenant comme critère la charge des arêtes permet d’optimiser la distribution des longueurs d’onde lorsqu’un grand nombre de requêtes sont effectuées sur le réseau, en particulier quand on passe T en requête (toutes les requêtes possibles sont effectuées). Ainsi le plus grand nombre de chemins est créé dont certains ont plusieurs arêtes en commun. Exemple de couple (G,R) pour lequel cet algorithme n’utilise pas le nombre minimum de longueurs d’onde : G=5122334455124 R=T On obtient un seuil de charge égal à 4 alors qu’il est possible de conserver tous les seuils de charge inférieurs à 3. Exemple de couple (G, R) pour lequel cet algorithme fonctionne mieux que les trois autres : G = 12 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 7 10 10 11 11 12 1 7 R=T c. Algorithme 3 : seuil de charge + attribution gloutonne L’algorithme de recherche des chemins avec seuil de charge a pour objectif d’obtenir des charges moins élevées, notamment la charge maximale du réseau. L’attribution gloutonne des longueurs d’onde n’est pas toujours efficace et dépend de la « superposition » des requêtes. Exemple de couple (G, R) pour lequel cet algorithme n’utilise pas le nombre minimum de longueurs d’onde : G=71223255664674741 R=T On obtient 9 longueurs d’onde dans ce cas alors qu’il est possible d’en avoir seulement 7 différentes. Exemple de couple (G, R) pour lequel cet algorithme fonctionne mieux que les trois autres : G=812244331264556677885 R=T C’est ici le seul algorithme qui permet d’obtenir 9 longueurs d’onde (contre 10 dans les autres cas). d. Algorithme 4 : seuil de charge + attribution suivant charge Cet algorithme permet à la fois de réduire la charge maximale du réseau et d’optimiser la distribution des longueurs d’onde. Il est adapté aux graphes contenant un nombre important 5 d’arêtes et de requêtes : il permet d’obtenir des charges plus régulières sur l’ensemble du graphe et de traiter en priorité les arêtes de charge élevée. Exemple de couple (G, R) pour lequel cet algorithme n’utilise pas le nombre minimum de longueurs d’onde : G=51223344551 R=T La charge maximale obtenue est 4, alors qu’avec une recherche gloutonne des chemins elle est égale à 3. Exemple de couple (G, R) pour lequel cet algorithme fonctionne mieux que les trois autres : G = 12 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 7 10 10 11 11 12 1 7 5 7 12 4 R=T Cet algorithme utilise 20 longueurs d’onde différentes, les autres en utilisent 21. e. Exemple pour lequel aucun de ces algorithmes ne donne pas le nombre minimum de longueurs d’onde G=51223344551 R=132423 L’objectif est de trouver une solution avec 2 longueurs d’onde. Avec les algorithmes 1 et 2 la recherche gloutonne donne une charge max égale à 3, cet algorithme ne permet donc pas de trouver le nombre minimum de longueurs d’onde. En utilisant les algorithmes 3 et 4 (recherche par seuil de charge), les chemins sont : 123, 234, 21543 Le chemin 21543 a une arête en commun avec chacune des 2 autres arêtes, les 3 chemins doivent donc avoir 3 longueurs d’onde différentes alors que la charge max est 2 (Schéma 1). 3 1 2 5 2 4 Schéma 1 3 1 5 4 Schéma 2 Si on considère les chemins 123, 2154, 23 : la charge max est 2, et on peut leur attribuer respectivement les longueurs d’onde 1, 2, 2 (Schéma 2). Conclusion Jeux d’essai 6 Listing 7