#Pour lancer le programme, appuyer sur CTRL + Enter #importation des modules from tkinter import * import tkinter as Tkinter import random as rd import matplotlib.pyplot as pl import numpy as np #paramètres de la fenêtre fenetre=Tk() fenetre.geometry('500x630') fenetre.title("Modélisation de l'organisation spatiale d'un troupeau") #paramètres des curseurs w = Label(fenetre, text="Bonjour et bienvenue dans ce simulateur de l'évolution de la segrégation d'un troupeau de gnous et de zèbres lors d'une grande migration africaine.",width = 145,wraplength=450,height=3) w.pack() f = Label(fenetre, text="Ci-dessous, vous pouvez choisir les paramètres de la simulation : ", width = 145,wraplength=450,height=2) f.pack() curseur1 = Scale(fenetre, orient='horizontal', from_=0, to=1000000,resolution=1, tickinterval=250000, length=430,label="Quantité de gnous", fg = 'saddlebrown') curseur1.pack() curseur2 = Scale(fenetre, orient='horizontal', from_=0, to=200000,resolution=1, tickinterval=50000, length=430,label="Quantité de zèbres", fg = 'dimgrey') curseur2.pack() curseur = Scale(fenetre, orient='horizontal', from_=0, to=1,resolution=0.1, tickinterval=0.2, length= 430,label="seuil de similarité (%)", fg = 'black') curseur.pack() # Modélisation de la savane (matrice) prenant en arguments le quantité de gnous x1 et de zèbres x2 du troupeau et la taille de la matrice n def savaneground(x1,x2,n):#x1 valeur du curseur du nombre de gnous x2 de zèbres g=x1/1200000#pourcentage de gnous z=x2/1200000#pourcentage de zèbres nvg = int(g*n*n) nvz = int(z*n*n) nv0 = n*n - nvg - nvz L = nvg*[1] + nvz*[2] + nv0*[0]#nombre de 0, 1 et 2 dans la matrice rd.shuffle(L)#on mélange la liste return np.reshape(np.array(L, dtype=int), (n,n)), nvg, nvz#retranscription de la liste en matrice # Création d'un compteur de voisins: pour une case (x,y) dans la savane M de taille n (arguments) elle renvoie une liste de 3 valeurs (le nombre de cases voisines, le nombre de voisins de type 1 puis 2) def voisins(M, x, y,n): V = [0, 0, 0] # compteur en tout, type 1, type 2 for Dx in (-1, 0, 1):# déplacement de x for Dy in (-1, 0, 1):# déplacement de y if (Dx, Dy) != (0,0): xx = x + Dx yy = y + Dy if (xx >= 0) and (xx < n) and (yy >= 0) and (yy < n):# on ne tient pas compte des bords et des angles V[0] = V[0] + 1 a = M[xx,yy] if a != 0 : V[a] = V[a] + 1 return V # On géneralise le compteur du nombre de voisins à la matrice M de taille n def NbVoisins(M,n): R = np.zeros((n,n,3), dtype=int) for x in range(n): for y in range(n): for tp in (0,1, 2): R[x, y, tp] = voisins(M, x, y, n)[tp] return R# rend une matrice de listes avec 3 élements le nombre total de voisins, le nombre de type 1 et de type 2 # Fonction qui renvoie la valeur du taux de similarité d'un individu dans son environnement proche prenant en arguments la matrice M de taille n def TauxSimilaires(M,n): R = np.zeros((n,n)) NbV = NbVoisins(M,n) for x in range(n): for y in range(n): if M[x,y]!=0: tp = M[x,y] # ici, % d'animaux de même type if (NbV[x,y,1]+NbV[x,y,2])!=0: R[x,y] = NbV[x,y,tp]/(NbV[x,y,1]+NbV[x,y,2]) else: R[x,y]=0 else: R[x,y]=0 return R # Mise en couleur de la matrice initiale M de taille n def CouleursIni(M,n): sol=(1,0.8,0.3) gnous=(0.8,0.4,0) zèbres=(0.5, 0.5, 0.5) Aff = np.zeros((n,n),dtype=int) for x in range(n): for y in range(n): if M[x,y] == 0: # rien Aff[x,y,:] = sol if M[x,y] == 1: Aff[x,y,:] = zèbres if M[x,y] == 2: Aff[x,y,:] = gnous return Aff # Mise en couleur des insatisfaits prenant en arguments la matrice M de taille n la valeur du seuil de similarité et TS le taux de similarité def Couleurs(M, TS,n,seuil): Aff = np.zeros((n,n,3),dtype=np.uint8) # Attention le type dans une matrice image est float/int8 mais pas int for x in range(n): for y in range(n): if M[x,y] == 0: # si absence d'individu Aff[x,y,:] = (220,215,80)#couleur de la savanne else: if TS[x,y]>seuil:#individus satisfaits de leur environnement if M[x,y]==1: Aff[x,y,:] = (167,110,20)#couleur des gnous satisfaits: marron foncé elif M[x,y]==2: Aff[x,y,:] = (200,200,200)#couleur des zèbres satisfaits: gris clair else: Aff[x,y,:] = (128,128,128)#couleurs des gnous instaisfaits: gris foncé return Aff # Modélisation d'un mouvement aléatoire selon deux hypothéses : # L'évolution se fait sur l'ensemble de la matrice la fonction prend en arguments la matrice M de taille n et la valeur du seuil def Evolution1(M,seuil,n): TS = TauxSimilaires(M,n) for x in range(n): for y in range(n): a = M[x,y] if a != 0 and TS[x,y] < seuil: # chercher parmi d'autres cases choisies au hasard une case plus confortable # et qui est encore vide Nx = rd.randint(0,n-1) Ny = rd.randint(0,n-1) if M[Nx, Ny] == 0 & (Nx!=x or Ny!=y): lv = voisins(M, Nx, Ny,n) if (lv[1]+lv[2])!=0: pv = lv[a]/(lv[1]+lv[2]) if pv>seuil : M[x,y] = 0 M[Nx,Ny] = a else: pv=0 M[x,y] = 0 M[Nx,Ny] = a return M # L'évolution se fait selon un mouvement de proche en proche: # Donne la position (x,y) correspondant à la valeur max dans L=[[v,x,y]] def PosMax(L): p = len(L) mx = L[0] for k in range(1,p): PC = L[k] if PC[0] > mx[0]: mx = PC return mx[1], mx[2]#rend la position de la première valeur maximale rencontrée def Evolution2(M,seuil,n): TS = TauxSimilaires(M,n) for x in range(n): for y in range(n): a = M[x,y] if a != 0 and TS[x,y] < seuil: # chercher parmi les voisins la case la plus confortable # non encore vide LPP = [] for Dx in (-1, 0, 1): for Dy in (-1, 0, 1): Nx = x + Dx Ny = y + Dy if (Nx >= 0) and (Nx < n) and (Ny >= 0) and (Ny < n): if M[Nx, Ny] == 0: lv = voisins(M, Nx, Ny,n) if (lv[1]+lv[2])!=0: pv = lv[a]/(lv[1]+lv[2]) LPP.append((pv, Nx, Ny)) else: pv=0 LPP.append((pv, Nx, Ny)) if len(LPP) > 0: xF, yF = PosMax(LPP) M[x,y] = 0 M[xF, yF] = a return M # Fonctions qui compilent toutes les fonctions et qui modélisent les mouvements au cours du temps sur l'ensemble de la savane prenant en arguments x1 x2 les quantités d'animaux, la valeur du seuil de similarité, le nombre d'itérations ite et n la taille de la savane def compilation1(n,x1,x2,seuil,ite): # modif ici M=savaneground(x1,x2,n)[0] TS=TauxSimilaires(M,n) pl.ion() pl.figure(1) image = pl.imshow(Couleurs(M,TS,n,seuil)) pl.show() pl.pause(0.01) i=0#permet de compter le nombre d'itération donner en argument par ite while pl.fignum_exists(1) and i