Vous êtes sur la page 1sur 27

RECHERCHE OPÉRATIONNELLE

RAPPORT
DE PROJET
LA RÉSOLUTION DU PROBLÈME DE
VOYAGEUR DE COMMERCE PAR UN
ALGORITHME DE COLONIES DE FOURMIS
CALIBRÉ ET OPTIMISÉ PAR UN
ALGORITHME GÉNÉTIQUE

DATE

30 MARS 2018

ELABORÉ PAR :

SLIMANE RABII
BELLAHIRECH FAROUK
SUPERVISÉ PAR :
HACHAICHI YASSINE
TABLE DES MATIERES

1. INTRODUCTION :………………………………………………………………………………………………………..2

2. POURQUOI LES FOURMIS :………………………………………………………………………………..…………2

3. PROBLEME DU PLUS COURT CHEMIN ENTRE DEUX POINTS :………………………………..……..2

4. PROBLEME DE VOYAGEUR DE COMMERCE :……………………………………………………..…………3

5. MODELISATION DU COMPORTEMENT DES FOURMIS :……………………………………….………..4

5.1. REGLE DE TRANSITION :………………………………………………………………………..………4

5.2. QUANTITES DE PHEROMONES……………………………………………..……..………..………..5

6. IMPLEMENTATION DE L’ALGORITHME ET TEST AVEC PYTHON 3 :…………………………..….6

6.1. IMPLEMENTATION DE L’ALGORITHME :…………………………………………..…..….…….6

6.2. TEST DE L’ALGORITHME :………………………………………………………..……..……….....….6

7. CHOIX DES PARAMETRES : PERFORMANCE ET OPTIMISATION : ……………..……………..……6

7.1. INFLUENCE DU NBR_FOURMI SUR LE TEMPS DE CALCUL : …………...…………...…. 7

7.2. INFLUENCE DE Q SUR LE TEMPS DE CALCUL : ………………………………...…………..…8

7.3. INFLUENCE DE C SUR LE TEMPS DE CALCUL :…………………………………..…......……..9

7.4. INFLUENCE DE ALPHA SUR LE TEMPS DE CALCUL :……………………………………..10

7.5. INFLUENCE DE BETA SUR LE TEMPS DE CALCUL :………………………………………..11

7.6. INFLUENCE DE STAGNATION_MAX SUR LE TEMPS DE CALCUL :……………..…….11

7.7. INFLUENCE DE CYCLE_MAX SUR LE TEMPS DE CALCUL :………………………….…..12

7.8. INFLUENCE DE ROU SUR LE TEMPS DE CALCUL :…………………………………………13

8. CALIBRATION ET L’OPTIMISATION PAR UN ALGORITHME GENETIQUE :…………..………13

8.1. INTRODUCTION :………………………………………………..………………………………………..13

8.2. IMPLEMENTATION :………………………………………………………………….…………….…..14

8.3. RESUME DES RESULTATS :……………………………………………………………...……….…..14

9. CONCLUSION :…………………………………………………………………………………………………….…….15
1
1. INTRODUCTION :

Calibration et optimisation de l'algorithme de colonie de fourmis


Ce projet de recherche opérationnelle porte sur la résolution du problème de
voyageur de commerce par l’algorithme de colonies de fourmis calibré et optimisé par un
algorithme génétique.

Pour commencer, le problème de voyageur de commerce est un problème


d'optimisation qui, étant donné une liste de ville et des distances entre toutes les paires de
villes, détermine un plus court chemin qui visite chaque ville une et une seule fois et qui
termine dans la ville de départ. Malgré la simplicité de son énoncé, il s'agit d'un
problème NP-complet et du fait de sa NP-complétude, de nombreuses métaheuristique ont
été proposées.

Alors une métaheuristique est un algorithme d’optimisation visant à résoudre des


problèmes d’optimisation difficile (pour lequel on ne connaît pas de méthode classique
plus efficace) comme par exemple l’algorithme de colonies de fourmis qui est
un algorithme inspiré du comportement des fourmis.

2. POURQUOI LES FOURMIS :


Les fourmis ont un comportement collectif qui les aide à résoudre des problèmes
complexes tels que celui de la recherche du plus court chemin. Et pour la résolution de ces
problèmes, les fourmis communiquent entre eux en déposant au passage sur le sol une
substance odorante appelée phéromone et en la suivant pour se déplacer.

3. PROBLEME DU PLUS COURT CHEMIN ENTRE DEUX POINTS:

Figure 1 : recherche du plus court chemin entre deux points.

2
Au départ le déplacement des fourmis est assez aléatoire mais les premières
fourmis qui reviennent au nid avec de la nourriture (en rouge sur la figure 1) sont celles qui
ont emprunté un chemin plus court et donc leur chemin sera plus marqué par les
phéromones (plus attirant). Et grâce à l’aspect aléatoire dans le déplacement des fourmis le
choix du chemin plus court s’améliora au fur du temps et attirera au final toutes les
fourmis.

Il faut noter que la phéromone est une substance volatile ce qui joue un rôle très
important, en effet cela favorise la découverte de nouveaux chemins, qui malgré leur
concentration faible en phéromone ont quand même une chance d’être choisi.

4. PROBLEME DE VOYAGEUR DE COMMERCE :


A partir d’un ensemble de nœuds, et des distances dij entre toutes les paires de
nœuds (i,j), le problème de voyageur de commerce consiste à déterminer un plus court
chemin qui visite chaque nœud une et une seule fois et qui termine dans le nœud de départ.
C’est-à-dire à partir d’un graphe complet d’ordre n (nombre des nœuds) on va déterminer
le cycle hamiltonien minimal en terme de longueur.

Pour cela on va utiliser la méthode de colonie de fourmis qui est basé


principalement sur les étapes suivantes :

1-Distribuer f fourmis sur les n nœuds.

2-remplir les arrêtes avec une quantité de phéromone initiale.

3-Répéter :

3-1-Chaqu'une des f fourmi effectue un cycle hamiltonien en respectant quelques


règles de transition. (Le traitement de cette étape est similaire au traitement du
« Problème du plus court chemin entre deux points » sauf que cette fois chaque
fourmi, pour effectuer un cycle hamiltonien, elle doit mémoriser les nœuds déjà
visité).

3-2-Calculer la longueur du cycle effectué par chaque fourmi.

3-3-Mettre à jour le meilleur cycle trouvé.

3-4-Mettre à jour les quantités de phéromones des arrêtes (déposer de nouvelle


quantité et tenir compte de l’évaporation).

3-5-Vider les mémoires des fourmis pour recommencer à partir du nœud initial.

Jusqu’à (stagnation) ou (nitération> nitération_max)

3
5. MODELISATION DU COMPORTEMENT DES FOURMIS :

5.1. REGLE DE TRANSITION :


Soit une fourmi k placée sur un nœud i. Pour effectuer un seul cycle hamiltonien
cette fourmi va visiter tout les nœuds en passant par chaque nœud une seule fois. C’est-à-
dire elle est amenée à se déplacer d’un nœud à un autre n fois (elle doit prendre n
décision).

Figure 2 : Règle de transition.

Pour chaque décision la fourmi choisit une arrête non encore visité tout en
préférant les arrêtes courtes et les arrêtes qui contiennent plus de phéromones. La
probabilité du passage de la fourmi k placée sur le nœud i vers un nœud j se calcule par la
formule suivante.

𝟏
𝒕𝒊𝒋𝜶 . ( )𝜷
𝒅𝒊𝒋
𝒌
𝒑𝒊𝒋 = , 𝒔𝒊 𝒋𝝐𝑵𝒌𝒊 (𝟏)
𝜶 𝟏 𝜷
∑𝒍𝝐𝑵𝒌 𝒕𝒊𝒍 . ( )
𝒊 𝒅𝒊𝒍
{ 𝟎, 𝒔𝒊𝒏𝒐𝒏
Avec :

-𝒕𝒊𝒋 : Variable qui indique la quantité des phéromones entre le nœud i et le nœud j.

𝟏
- : Variable qui caractérise la visibilité du nœud j à partir du nœud i (𝒅𝒊𝒋 est la distance qui
𝒅𝒊𝒋

sépare le nœud i du nœud j)

4
-𝜶 : Paramètre qui caractérise l’importance de la quantité de phéromones.

-𝜷 : Paramètre qui caractérise l’importance du facteur visibilité.

-𝑵𝒌𝒊 : L’ensemble des nœuds que la fourmi k, placée sur la ville i, n’a pas encore visité dans
le cycle courant.

5.2. QUANTITES DE PHEROMONES


Soit Q la quantité de phéromone distribué par une seule fourmi lors d’un seul cycle.
Et soit 𝑳 𝒌 la distance parcourue par une fourmi k lors d’un cycle bien déterminé.

Lors de son passage entre le nœud i et le nœud j la fourmi k va déposer une quantité
𝑸⁄ de phéromone sur l’arrête ij. Par conséquence, pour calculer la quantité de
𝑳𝒌
phéromone déposée sur cette arrête par toute les fourmis ∆𝒕𝒊𝒋 , on utilise la formule
suivante :

𝑸
∆𝒕𝒊𝒋 = ∑ (𝟐)
𝑳𝒌
𝒌𝝐𝑬

Avec :

-E : l’ensemble des fourmis qui ont passé par l’arrête ij.

Une fois les ∆𝒕𝒊𝒋 sont calculés, on passe au calcul des 𝒕𝒊𝒋 au biais de la formule suivante :

𝒕𝒊𝒋 ← 𝝆. 𝒕𝒊𝒋 + ∆𝒕𝒊𝒋 (𝟑)

Avec :

𝝆 : Coefficient qui définie la vitesse d’évaporation des phéromones sur les arrêtes.

5
6. IMPLEMENTATION DE L’ALGORITHME ET TEST AVEC PYTHON 3 :

(Voir annexe 1)

6.1. IMPLEMENTATION :

6.2. Test:
from numpy.core.multiarray import array
from main import voy_comm_colo_fourmi
from random import *
from matplotlib import pyplot as PLT

#entrer les données du graphe


tab_distance=array([[0,5,7,4,11,2,5],
[5,0,9,8,14,1,6],
[7,9,0,4,7,12,7],
[4,8,4,0,7,17,7],
[11,14,7,7,0,4,1],
[2,1,12,17,4,0,3],
[5,6,7,7,1,3,0]])

voy_comm_colo_fourmi(tab_distance=tab_distance, nbr_fourmi=7, c=0.5, alpha=1, beta=1,


q=100, rou=0.01, cycle_max=100, stagnation_max=2,nbr_noeud=7);

Résultat de l’exécution :

C:\Users\firas\AppData\Local\Programs\Python\Python36-32\python.exe "D:/Rabii/2
année/PRO/test3.py"
nbr cycle: 42
nbr stagnation: 2
meilleur circuit trouvé: [1, 5, 6, 4, 2, 3, 0, 1]
distance: 25
*******************************************

Process finished with exit code 0

7. Etude de l’influence des paramètres sur la PERFORMANCE ET la


convergence de l’algorithme :
Après avoir effectué plusieurs tests, ce qu’on a pu constater c’est que le temps de
calcul et la convergence même de l’algorithme dépendent fortement du choix des 8
paramètres suivantes (nbr_fourmi, c, alpha, beta, q, rou, cycle_max, stagnation_max).
Dans cette partie notre objectif est de visualiser l’influence de chaque paramètre sur le
temps de calcul et la convergence de l’algorithme et cela pour 5 graphes de tailles
différentes.

6
Remarques :

1-Pour la visualisation on va considérer les variables non étudiées comme


constantes selon le tableau ci dessous, en effet D’après « Optimisation par colonies de fourmis-
COSTANZO Andrea -LUONG Thé Van -MARILL Guillaume -19 mai 2006 » les résultats suivants
donnent en pratique les meilleurs résultats pour un problème à 30 villes :

nbr_fourmi c Alpha beta q rou cycle_max stagnation_max


nbr_noeud 0.5 1 1 100 0.5 5000 1

2-En ce qui concerne le temps de calcul, les calculs ont été effectués avec un Pc
Portable Asus K555LD i5-4210U 4é Génération Up To 2.7 GHz, Mémoire 8 Go DDR3 1600
MHz.

7.1. INFLUENCE DU NBR_FOURMI SUR LE TEMPS DE CALCUL :

Figure 3 : étude de l’influence du nombre de fourmis sur le temps de calcul et la convergence de l’algorithme

𝑐𝑜𝑒𝑓𝑓𝑐𝑜𝑟𝑟 (𝑞, 𝑡𝑒𝑚𝑝𝑠𝑐𝑎𝑙𝑐𝑢𝑙 ) = 0.79296

7
La figure 3 représente l’influence du nombre de fourmis sur le temps de calcul et la
convergence de l’algorithme et ceci pour 5 graphe de différent nombre de nœud. En effet
chaque figure englobe 1000 point et Chaque point de cette figure indique le temps de calcul
en (ms) et la longueur du meilleur resultat trouvé en exécutant l’algorithme pour un
nombre de nœud entre 6 et 10 et pour un nombre aléatoire de fourmis entre 1 et 20.

Comme le coefficient de corrélation le confirme, le temps de calcul est proportionnel


au nombre de fourmis utilisé et proportionnel au carré du nombre de nœud (on pourra
démontrer par une étude de complexité que le nombre d’itération et un O(cycle_max ·
nbr_noeud2 · nbr_fourmi)).

7.2. INFLUENCE DE Q SUR LE TEMPS DE CALCUL :

Figure 4 : étude de l’influence du facteur q sur le temps de calcul et la convergence de l’algorithme

Remarque :
𝑛𝑜𝑚𝑏𝑟𝑒 𝑑𝑒 𝑝𝑜𝑖𝑛𝑡 𝑝𝑎𝑟 𝑡𝑦𝑝𝑒 𝑑𝑒 𝑔𝑟𝑎𝑝ℎ𝑒 = 1000

𝑐𝑜𝑒𝑓𝑓𝑐𝑜𝑟𝑟 (𝑞, 𝑡𝑒𝑚𝑝𝑠𝑐𝑎𝑙𝑐𝑢𝑙 ) = 0.00297

D’après la figure ci dessus les deux variables q et temps de calcul sont du moins
linéairement indépendantes, d’ailleurs le coefficient de corrélation est assez faible.

8
7.3. INFLUENCE DE C SUR LE TEMPS DE CALCUL :

Figure 5 : étude de l’influence du facteur c sur le temps de calcul et la convergence de l’algorithme

Remarque :

𝑛𝑜𝑚𝑏𝑟𝑒 𝑑𝑒 𝑝𝑜𝑖𝑛𝑡 𝑝𝑎𝑟 𝑡𝑦𝑝𝑒 𝑑𝑒 𝑔𝑟𝑎𝑝ℎ𝑒 = 250

𝑐𝑜𝑒𝑓𝑓𝑐𝑜𝑟𝑟 (𝑐, 𝑡𝑒𝑚𝑝𝑠𝑐𝑎𝑙𝑐𝑢𝑙 ) = −0.88878

La figure 5 et le coefficient de corrélation confirment la présence d’une relation


(fonction constante par palier) entre le temps de calcul et le facteur c dans l’intervalle
[0,2]. Au-delà de cet intervalle le coefficient de corrélation est de l’ordre de 0.00128 c’est-à-
dire pas de relation.

Vu que quand on augmente c le temps de calcul diminue, on pense directement à


prendre max(c) mais malheureusement quand c augmente, le risque de divergence de
l’algorithme augmente aussi.

9
7.4. Influence d’alpha sur le temps de calcul :

Figure 6 : étude de l’influence du facteur rou sur le temps de calcul et la convergence de l’algorithme

Remarque :

𝑛𝑜𝑚𝑏𝑟𝑒 𝑑𝑒 𝑝𝑜𝑖𝑛𝑡 𝑝𝑎𝑟 𝑡𝑦𝑝𝑒 𝑑𝑒 𝑔𝑟𝑎𝑝ℎ𝑒 = 500

𝑐𝑜𝑒𝑓𝑓𝑐𝑜𝑟𝑟 (𝑎𝑙𝑝ℎ𝑎, 𝑡𝑒𝑚𝑝𝑠𝑐𝑎𝑙𝑐𝑢𝑙 ) = −0.86137

La figure 6 et le coefficient de corrélation confirment la présence d’une relation


(fonction constante par palier) entre le temps de calcul et le facteur alpha dans
l’intervalle [0,2]. Au-delà de cet intervalle le coefficient de corrélation est de l’ordre de
0.00302 c’est-à-dire pas de relation.

Vu que quand on augmente alpha le temps de calcul diminue, on pense


directement à prendre max (alpha) mais malheureusement quand alpha augmente, le
risque de divergence de l’algorithme augmente aussi.

10
7.5. INFLUENCE DE BETA SUR LE TEMPS DE CALCUL :

Figure 7 : étude de l’influence du facteur beta sur le temps de calcul et la convergence de l’algorithme

Remarque :

𝑛𝑜𝑚𝑏𝑟𝑒 𝑑𝑒 𝑝𝑜𝑖𝑛𝑡 𝑝𝑎𝑟 𝑡𝑦𝑝𝑒 𝑑𝑒 𝑔𝑟𝑎𝑝ℎ𝑒 = 500

𝑐𝑜𝑒𝑓𝑓𝑐𝑜𝑟𝑟 (𝑏𝑒𝑡𝑎, 𝑡𝑒𝑚𝑝𝑠𝑐𝑎𝑙𝑐𝑢𝑙 ) = 0.06491

D’après la figure ci dessus les deux variables beta et temps de calcul sont du moins
linéairement indépendantes, d’ailleurs le coefficient de corrélation est assez faible.

7.6. INFLUENCE DE STAGNATION_MAX SUR LE TEMPS DE CALCUL :

Figure 8 : étude de l’influence de stagnation_max sur le temps de calcul et la convergence de l’algorithme

11
Remarque :

𝑛𝑜𝑚𝑏𝑟𝑒 𝑑𝑒 𝑝𝑜𝑖𝑛𝑡 𝑝𝑎𝑟 𝑡𝑦𝑝𝑒 𝑑𝑒 𝑔𝑟𝑎𝑝ℎ𝑒 = 1000

𝑐𝑜𝑒𝑓𝑓𝑐𝑜𝑟𝑟 (𝑎𝑙𝑝ℎ𝑎, 𝑡𝑒𝑚𝑝𝑠𝑐𝑎𝑙𝑐𝑢𝑙 ) = 0.46906

D’après la figure ci dessus et le coefficient de corrélation les deux variables


stagnation_max et temps de calcul présentent une faible dépendance linaire.

7.7. INFLUENCE DE CYCLE_MAX SUR LE TEMPS DE CALCUL :

Figure 9 : étude de l’influence du facteur cycle_max sur le temps de calcul et la convergence de l’algorithme

Remarque :

𝑛𝑜𝑚𝑏𝑟𝑒 𝑑𝑒 𝑝𝑜𝑖𝑛𝑡 𝑝𝑎𝑟 𝑡𝑦𝑝𝑒 𝑑𝑒 𝑔𝑟𝑎𝑝ℎ𝑒 = 250

𝑐𝑜𝑒𝑓𝑓𝑐𝑜𝑟𝑟 (𝑎𝑙𝑝ℎ𝑎, 𝑡𝑒𝑚𝑝𝑠𝑐𝑎𝑙𝑐𝑢𝑙 ) = 0.94697

Comme le coefficient de corrélation le confirme, le temps de calcul est proportionnel


au facteur cycle_max (nombre d’itération et un O(cycle_max · nbr_noeud2 · nbr_fourmi)).

12
7.8. INFLUENCE DE ROU SUR LE TEMPS DE CALCUL :

Figure 10 : étude de l’influence du facteur rou sur le temps de calcul et la convergence de l’algorithme

Remarque :

𝑛𝑜𝑚𝑏𝑟𝑒 𝑑𝑒 𝑝𝑜𝑖𝑛𝑡 𝑝𝑎𝑟 𝑡𝑦𝑝𝑒 𝑑𝑒 𝑔𝑟𝑎𝑝ℎ𝑒 = 500

𝑐𝑜𝑒𝑓𝑓𝑐𝑜𝑟𝑟 (𝑟𝑜𝑢, 𝑡𝑒𝑚𝑝𝑠𝑐𝑎𝑙𝑐𝑢𝑙 ) = 0.06491

D’après la figure précédente les deux variables rou et temps de calcul sont du
moins linéairement indépendantes, d’ailleurs le coefficient de corrélation est assez faible.

8. CALIBRATION ET L’OPTIMISATION PAR UN ALGORITHME GENETIQUE :

8.1. INTRODUCTION :

Les algorithmes génétiques appartiennent à la famille des algorithmes évolutionnistes.


Leur but est d'obtenir une solution approchée à un problème d'optimisation, lorsqu'il
n'existe pas de méthode exacte (ou que la solution est inconnue) pour le résoudre en un
temps raisonnable. Les algorithmes génétiques utilisent la notion de sélection naturelle et
l'appliquent à une population de solutions potentielles au problème donné.

13
Le déroulement d'un algorithme génétique peut être découpé en cinq parties :

1. La création de la population initiale


2. L'évaluation des individus
3. La création de nouveaux individus
4. L'insertion des nouveaux individus dans la population
5. Réitération du processus

Figure 11: déroulement d'un algorithme génétique


8.2. IMPLEMENTATION :

(Voir annexe 2)

8.3. RESUME DES RESULTATS :

La figure ci dessous représente les meilleurs résultats trouvés par l’algorithme


génétique. La distribution des points de cette figure nous montre que plus on minimise
l’erreur plus le temps de calcul augmente et vice vers ça et ceci est tout à fait attendue. Pour
plus de détails des points trouvés voir annexe 3.

14
Figure 12 : représentation des meilleurs résultats trouvés par l’algorithme génétique.

9. CONCLUSION :

Le problème du voyageur de commerce se prête très bien à l'utilisation de la méta-


heuristiques colonies de fourmis. Cette méthode a ses points forts et ses inconvénients.
Grâce au partage des données entre les fourmis cette méthode fourni des très bons
résultats. Le choix des paramètres reste le point le plus délicat de cette méthode.

15
ANNEXE 1
from random import *
from numpy import *
import copy
#Def la class fourmi
class Fourmi():
id=0
trajet=[]
def __init__(self,id,nbr_noeud):
self.id=id
self.trajet=[randint(0, nbr_noeud-1)]
def deplacer (self,x):
self.trajet.append(x)

def __repr__(self):
return (str(self.id)+str(self.trajet))

#passage: retourne le noeud suivant de f en utilisant la formule (1)


def passage(f,tab_distance,nbr_noeud,tab_pheromone,alpha,beta):
noeud_act=f.trajet[-1]
liste=copy.copy(tab_distance[noeud_act])
#effacer les noeud deja visités
for i in f.trajet:
liste[i]=0
#calculer les probabilité
s=0
for i in range(0,nbr_noeud):
liste = liste.astype(float32)
if liste[i]!=0:
liste[i]=(tab_pheromone[noeud_act,i]**alpha)*\
((1/tab_distance[noeud_act,i])**beta)
s+=liste[i]
for i in range(0,nbr_noeud):
if s!=.0:
liste[i]=(liste[i])/s
liste1=[]
#eliminer les proba null
for i in range(0,nbr_noeud):
if liste[i]!=.0:
liste1.append([i,liste[i]])
#linst1:intervalle
for i in range(1,len(liste1)):
liste1[i][1]+=liste1[i-1][1]
#selection du noeud suivant
r=uniform(0, 0.99)
for i in range(0,len(liste1)):
if r<=liste1[i][1]:
return (liste1[i][0])

#distance: determine la longueur du trajet


def distance(trajet,tab_distance):
dist=0
for i in range(0, len(trajet) - 1):
dist+=tab_distance[trajet[i], trajet[i + 1]]
return dist

1
#ajout: calcule les quantités de phéromone deposées par tout
# les fourmis en utilisant la formule (2)
def ajout(tab_distance,nbr_noeud,tab_fourmi,q):
a = zeros((nbr_noeud, nbr_noeud))
for f in tab_fourmi:
for i in range(0,nbr_noeud):
a[f.trajet[i],f.trajet[i+1]]+=q/distance(f.trajet,tab_distance)
return a

#mise_a_jour_pheromone: met à jour les quantités de phéromone en utilisant la


formule (3)
def mise_a_jour_pheromone(a,nbr_noeud,tab_pheromone,rou):
for i in range(0,nbr_noeud):
for j in range(0,nbr_noeud):
tab_pheromone[i,j]=tab_pheromone[i,j]*rou+a[i,j]

#test_permutation: test si deux liste t1 et t2 sont equivalentes


def test_permutation(t1, t2):
count=len(t1);
if t1[0] not in t2:
return False
pos=t2.index(t1[0])
permut_directe=True
permut_indirecte=True
for i in range(0,count):
if(pos+i == count):
pos=-i
if t1[i]!=t2[pos+i]:
permut_directe=False

pos = t2.index(t1[0])
for i in range(0, count):
if (t1[i]!=t2[pos-i]):
permut_indirecte=False
return permut_indirecte or permut_directe

#test_stagnation: test si les fourmis sont en etat de stagnation


def test_stagnation(tab_fourmi,nbr_noeud):
for f in tab_fourmi:
if not test_permutation(t1=f.trajet[0:nbr_noeud],
t2=tab_fourmi[0].trajet[0:nbr_noeud]):
return(False)
return(True)

def voy_comm_colo_fourmi(tab_distance, nbr_fourmi, c, alpha, beta, q, rou,


cycle_max, stagnation_max,nbr_noeud):
#nbr_noeud=len(tab_distance)
tab_fourmi=[]
meilleur=array([])
cycle=0
stag=0
#creation des fourmis reparties aléatoirement sur les noeuds
for i in range(0, nbr_fourmi):
tab_fourmi.append(Fourmi(i,nbr_noeud))

#initialisation des densités de pheromone

2
tab_pheromone=zeros((nbr_noeud,nbr_noeud))
for i in range(0,nbr_noeud):
for j in range(0,nbr_noeud):
if tab_distance[i,j]!=0:
tab_pheromone[i,j] = c

####Boucle principale####
while True:
#Chaque fourmi effectue un cycle
for i in range(0,nbr_noeud-1):
for f in tab_fourmi:

f.deplacer(passage(f,tab_distance,nbr_noeud,tab_pheromone,alpha,beta))
#verifier la stagnation et mise à jour du nbr de stagnation et nbr de
cycle
if test_stagnation(tab_fourmi,nbr_noeud):
stag+=1
cycle += 1
#Fermer le cycle par le noeud initial
for f in tab_fourmi:
f.deplacer(f.trajet[0])

#Calcul des quantités de phéromone deposé sur chaque arrête pendant


ce cycle

tab_ajout=ajout(tab_distance,nbr_noeud,tab_fourmi,q)

#mise à jour des quantité de pheromone de chaque arrête


mise_a_jour_pheromone(tab_ajout,nbr_noeud,tab_pheromone,rou)

#mise a jour du meilleur circuit jamais trouvé


for f in tab_fourmi:
if (len(meilleur)==0):
meilleur=copy.copy(f.trajet)
elif
distance(meilleur,tab_distance)>distance(f.trajet,tab_distance):
meilleur=copy.copy(f.trajet)
#Remise à zero des mémoires des fourmis
for f in tab_fourmi:
f.trajet=[f.trajet[0]]

#verifier le condition d'arret


if cycle>=cycle_max or stag>=stagnation_max:
break
#affichage des resultats
print('nbr cycle:',cycle)
print('nbr stagnation:',stag)
print('meilleur circuit trouvé:',meilleur)
print('distance:',distance(meilleur,tab_distance))
print('*******************************************')
return()

3
ANNEXE 2
from main import voy_comm_colo_fourmi
from random import *
import operator
from numpy.core.multiarray import array
from math import inf
def fitness (indiv):
tab_distance = array([[0, 5, 7, 4, 11, 2, 5, 6, 3, 2],
[5, 0, 9, 8, 13, 1, 6, 2, 7, 6],
[7, 9, 0, 4, 7, 12, 7, 4, 2, 1],
[4, 8, 4, 0, 7, 17, 7, 8, 4, 1],
[11, 14, 7, 7, 0, 4, 1, 5, 10, 8],
[2, 1, 12, 17, 4, 0, 3, 5, 3, 5],
[5, 6, 7, 7, 1, 3, 0, 3, 4, 6],
[6, 2, 4, 8, 5, 5, 3, 0, 8, 1],
[3, 7, 2, 4, 10, 3, 4, 8, 0, 2],
[2, 6, 1, 1, 8, 5, 6, 1, 2, 0]])
meilleur_sol=23
nbr_fourmi=indiv[0]
c=indiv[1]
alpha=indiv[2]
beta=indiv[3]
q=indiv[4]
rou=indiv[5]
cycle_max=indiv[6]
stag_max=indiv[7]
nbr_noeud = len(tab_distance)
res=voy_comm_colo_fourmi(tab_distance=tab_distance,
nbr_fourmi=nbr_fourmi, c=c, alpha=alpha, beta=beta, q=q,rou=rou,
cycle_max=cycle_max, stagnation_max=stag_max, nbr_noeud=nbr_noeud)
if res[1]>meilleur_sol:
return 0.0000001
else:
return (1/(res[0]+0.0000001))
def generate_indiv ():
# ( nbr_fourmi, c, alpha, beta,
q, rou, cycle_max, stagnation_max )

indiv=[randint(10,20),uniform(0.1,2.0),uniform(0.1,2.0),uniform(0.1,2.0),rand
int(0,100),uniform(0.1,2.0),randint(1,50),randint(1,10)]
return indiv
def generateFirstPopulation(sizePopulation):
population = []
for i in range(0,sizePopulation):
population.append(generate_indiv())
return population
def computePerfPopulation(population):
populationPerf = {}
for i in range(0,len(population)):
populationPerf[i] = fitness(population[i])
# for j in range(0,len(populationPerf)):
# print(str(populationPerf[j])+":"+str(population[j]))
# print(populationPerf)
return sorted(populationPerf.items(), key = operator.itemgetter(1),
reverse=True)

4
def selectFromPopulation(populationSorted,population, best_sample,
lucky_few):
nextGeneration = []
for i in range(best_sample):
nextGeneration.append(population[populationSorted[i][0]])
for i in range(lucky_few):
nextGeneration.append(population[choice(populationSorted)[0]])
shuffle(nextGeneration)
return nextGeneration
def createChild(individual1, individual2):
child = []
for i in range(len(individual1)):
if (randint(0,100) < 50):
child.append(individual1[i])
else:
child.append(individual2[i])
return child
def createChildren(breeders, number_of_child):
nextPopulation = []
for i in range(int(len(breeders)/2)+1):
for j in range(number_of_child):
nextPopulation.append(createChild(breeders[i],
breeders[len(breeders) -1 -i]))
return nextPopulation
def mutation (population,mutationRate):
for indiv in population:
for j in range(0,len(indiv)):
if uniform(0,1)<mutationRate:
zombie=generate_indiv()
indiv[j]=zombie[j]
return population
def
newGeneration(populationSorted,childrenSorted,population,children,nbrNew):
newPopulation=[]
nbrAncient=len(population)-nbrNew
for i in range(0,nbrNew):
newPopulation.append(children[childrenSorted[i][0]])
for i in range(0,nbrAncient):
newPopulation.append(population[populationSorted[i][0]])
return newPopulation

nbGeneration=5
best=[[],10]
population=generateFirstPopulation(10)
for generation in range(0,nbGeneration):
save=population
try:
print('********* ',generation,' *********')
populationSorted=(computePerfPopulation(population))
if 1 / populationSorted[0][1]<best[1]:
best[1]=1 / populationSorted[0][1]
best[0]=population[populationSorted[0][0]]
print(best[1])

breeders=selectFromPopulation(populationSorted,population,best_sample=8,lucky
_few=2)

5
children=createChildren(breeders,number_of_child=100)
childrenSorted=(computePerfPopulation(children))

population=newGeneration(populationSorted,childrenSorted,population,children,
nbrNew=3)
print(population)
population=mutation(population,mutationRate=0.3)
except:
print('erreur')
population=save
pass
print('La solution est:',best[0])

6
ANNEXE 3
Meilleur resultat=[nbr_fourmi,c,alpha,beta,q,rou,cycle_max, stagnation_max]
Pourcentage d’erreur
Temps de calcul en (s)
*********
[17, 0.2443693125538206, 0.9924280903400223, 1.998168770394875, 36,
1.341642086767427, 50, 1]
0.0
0.9417201538085938
*********
[12, 1.1229766494519244, 1.5937505441923254, 1.5444586329661063, 28,
1.84214820666453, 30, 8]
0.1
0.5153367328643799
*********
[10, 1.2712693718169472, 1.649378548222074, 1.6235544654747267, 19,
0.867351501697566, 12, 4]
8.5
0.17183248615264893
*********
[20, 0.17201724975299973, 1.0869197870394898, 0.6501627465068914, 74,
1.0740380350510816, 48, 1]
0.1
1.2985054161548615
*********
[20, 1.8558252892697331, 1.9002271594054663, 1.5820395932931186, 50,
1.0758798939036422, 13, 3]
1.5
0.38942874884605405
*********
[19, 1.552379413021, 1.1369338652601726, 1.733155591652135, 93,
0.5982142712928494, 22, 7]
0.3
0.6039646081924438
*********
[10, 1.3175235708073774, 0.7317492636488722, 1.5777291588683222, 44,
0.8070346206190222, 12, 3]
3.9
0.18110764050483705
*********
[19, 0.3465562657451963, 0.2802974635042992, 1.348760633823064, 42,
0.46572856513500416, 23, 1]
1.7
0.6794796109199523
**********
[11, 1.6722615596908075, 0.9414898214736025, 1.163036727299893, 64,
0.8503810626762516, 37, 4]
0.2
0.751004506111145
**********
[18, 1.5623135394402237, 1.1044801495917558, 1.9600565382327897, 98,
1.27442547730125, 13, 2]
0.2
0.4102074246406555
**********

7
[18, 0.6325102093858508, 1.477081279851728, 1.9320769083640734, 73,
1.1005709921640958, 12, 2]
0.5
0.38414630222320556
*********
[11, 0.6930787442620084, 1.2000277622743736, 0.9212855869243388, 23,
1.6392940282236723, 28, 5]
9.9
0.5777804048061371
*********
[17, 1.979528533996157, 1.802629111199852, 1.7203582091841385, 72,
0.6778766069615064, 7, 2]
6.9
0.23427860522270202
*********
[14, 1.2191170164060352, 1.954642511172922, 1.41958629906768, 42,
1.152432395273703, 13, 4]
5.9
0.4036863133907318
*********
[13, 0.3721557860612301, 0.26804721711952106, 1.5478274833122032, 80,
1.2673094580574225, 12, 6]
15.5
0.30396376132965086
*********
[18, 1.54186584632649, 1.6753526367124894, 1.2783283106592112, 92,
1.9410385537398898, 10, 1]
3.3
0.34682101202011106
*********
[17, 1.3806716265584642, 0.6664998825763278, 1.6692109533220685, 90,
0.9197111038175976, 34, 2]
0.0
1.0153991210460662
*********
[16, 0.8705077664551016, 1.4729350539192925, 1.9894238803433675, 61,
0.15170618250547355, 10, 3]
10.4
0.294479368686676
*********
[12, 1.8509721510060066, 0.5995204712964222, 1.969356806446231, 91,
1.0210491352969269, 20, 8]
0.0
0.47343212366104126
*********
[18, 0.6843066216717102, 0.5400462743815595, 1.713428271017493, 30,
0.2857350828217829, 20, 10]
0.0
0.6844536347389221
*********
[13, 1.5213579014486291, 0.30605000150059025, 1.3971746378205754, 75,
1.0244012038947743, 16, 3]
14.1
0.379948650598526
*********
[10, 0.8226511089320764, 1.018252016630586, 1.6894156379535963, 6,
1.7618931012983965, 12, 9]

8
19.3
0.23950820755958557
*********
[10, 1.4838749895188754, 0.4295203698108515, 1.2058147921359368, 16,
1.535255530044854, 39, 5]
17.0
0.8306101479530335
*********
[18, 0.7509363268853435, 1.5485207685262032, 1.8750629835347192, 4,
1.2760669461282421, 6, 2]
6.4
0.19340564799308776
*********
[13, 1.0307984738661018, 1.081296169375582, 1.2069444433148082, 98,
0.40736279736477454, 15, 8]
8.0
0.34341290140151975
*********
[20, 0.39205998373594664, 1.1113510784407297, 1.8625411526449152, 73,
1.369354089491065, 13, 8]
0.1
0.5255045499801636
*********
[11, 1.7405480664645254, 0.6340366945264527, 1.5932105060878214, 18,
0.34183078453773585, 37, 2]
0.1
0.7799423980712891
*********
[11, 0.9662254048019777, 0.8337755387110909, 1.3658061530277732, 37,
1.2018417585945111, 15, 3]
4.1
0.2867293493747711
*********
[10, 1.605932699502046, 0.5392479389310566, 1.6172297940137204, 5,
1.8161700274037862, 28, 6]
10.2
0.5543758010864258
*********
[11, 0.53540478184028, 0.45325141243730394, 1.9183438344472852, 10,
0.1481150254284247, 17, 9]
1.0
0.4296486091613769
*********
[14, 0.7341563608432642, 1.3208050203555346, 1.4707314059398717, 23,
0.511604400363516, 16, 7]
5.6
0.39553445458412173
*********
[14, 0.20522515893029242, 0.24720174369641063, 1.839820614795412, 81,
0.29015347346438214, 10, 8]
6.8
0.24479062294960022
*********
[13, 1.0680918414221765, 0.8493733594811014, 1.4970479925070768, 87,
0.5225269182237003, 17, 2]
0.8
0.31479517436027527

9
*********
[17, 1.7549487702201194, 0.7108481076586947, 1.8681629564537765, 83,
0.5342151215585703, 7, 1]
2.7
0.16425596046447755
*********
[19, 0.194847415843598, 0.9545910098737831, 0.7437348287738343, 83,
1.8511063085503738, 14, 2]
22.4
0.3797992353439331
*********
[14, 1.1415669423002754, 0.7681374415271441, 1.694844469298878, 51,
1.0713380551821392, 11, 3]
1.6
0.21824168848991393
*********
[20, 0.5685223893709509, 1.4524460190276487, 1.7235523942711253, 65,
0.30031432164258876, 43, 6]
3.6
1.192927778482437
*********
[19, 0.13983426738917198, 1.6830936399499736, 1.442663531629513, 24,
0.9416497328756358, 6, 7]
8.5
0.16472658109664917
*********
[19, 1.6928440806473648, 0.7193357087577548, 1.7934356322560174, 9,
0.6978261239239884, 7, 10]
3.8
0.2064707443714142
*********
[18, 1.7119570890238436, 1.7680593915340561, 1.8975851762806735, 47,
0.718153988769933, 14, 9]
4.9
0.4344768481254578
*********
[16, 0.35819223523688193, 1.5259845646914272, 1.8152382891921277, 44,
0.1287622095389266, 6, 10]
13.1
0.16368883800506592
*********
[20, 1.0422091936501605, 0.5235325102387436, 1.745678803953794, 34,
1.8474481023904599, 17, 2]
0.0
0.4642293403148651
*********
[14, 1.1955303424040116, 0.9730735105811512, 0.8975112857084352, 84,
1.6494828937782269, 17, 4]
18.5
0.3463819789886475
*********
[14, 0.5517299016553531, 1.1897278277890184, 1.5147456439979365, 83,
1.1282015779374903, 19, 1]
0.5
0.3788981487751007
*********

10
[13, 1.8016002664461261, 1.795399704690363, 1.3408500375475945, 41,
0.9285307803777088, 8, 9]
13.3
0.14626645016670228
*********
[14, 1.7497474324042417, 1.6172747558372338, 1.1617385859298717, 70,
1.8927280796489243, 9, 5]
15.0
0.18056275486946105
*********
[14, 0.12487098349137499, 0.8813066982932798, 1.8270670879269353, 75,
1.7705280342509062, 14, 7]
0.4
0.27772400236129763
*********
[16, 1.606496051294973, 1.9225299979927495, 1.4388885446874462, 8,
0.9392257458219606, 16, 1]
0.8
0.39164734196662904
*********
[11, 1.771382057763233, 1.7736522039227747, 1.4940096132677618, 5,
0.9518916937166947, 12, 10]
3.5
0.20900227808952332
*********
[16, 1.128012870071321, 0.5872612236280811, 1.8000894650280976, 5,
0.8756131879420824, 19, 4]
0.1
0.46301876854896545
***** 1 ****
[19, 1.3839031672639919, 0.7985428295245918, 1.3644015199252741, 78,
1.4757515061276447, 13, 10]
1.1
0.2858739595413208

11