import copy import random import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.animation as animation ###################### ### Variables Globales # taille de la grille TailleGrilleX = 15 TailleGrilleY = 15 # Grille Grille = np.ndarray((TailleGrilleX, TailleGrilleY)) # historique des grilles aux itérations précédentes # utilisé durant l'affichage dynamique HistoriqueGrilles = list() # chaque StratsResultats[i] est un triplet [nb_utilisations, total_ans_prisons, utilisation_detail] avec: # i = index de la stratégie en question # nb_utilisations = nombre total d'utilisations de la stratégie # total_ans_prisons = total d'années de prisons subies par les utilisateurs de la stratégie # utilisation_detail[i] = une liste de trilets [utilisateurs, utilisations, prisons] # représentant, à la fin de l'itération i, le nombre d'utilisateurs, le nombre d'utilisations # ainsi quel le nombre d'années de prisons qu'ils ont accumulés # attention, le nombre d'utilisateurs stockés est StratsResultats = list() # liste des stratégies (fonctions Joueur^2 -> {0, 1} décidant si un joueur nie ou non en fonction de son adversaire) ListeStrategies = list() # liste des fonctions génératrices de grille ListeGenGrille = list() # génératrice de grille à utiliser TypeGrilleInitiale = 3 # itération actuelle Iteration = 0 # nombre max d'itérations MaxIterations = 4 # stratégie par défaut StratParDefaut = 0 # affichage dynamique AffichageDynamique = True # nécessaire pour matrice_init_pourcents_choisis() ListePourcents = list() #Couleurs des Stratégies CouleursStrat=['b','r','black','g','purple'] """ Types: Coord = tuple(x, y) Joueur = dict("etat", "historique_etats", "strategie", "annees_de_prison", "historique_strategies") GrilleJoueurs = matrice2d(Joueur) """ ##################################### ### Génération de la matrice initiale def gen_matrice_initiale(): """ NoneType -> GrilleJoueurs """ fonction_gen = ListeGenGrille[TypeGrilleInitiale] return fonction_gen() ############################## ### Execution des tours / jeux def partie1v1(joueur, adversaire): """ Joueur^2 -> int Effectue une partie à deux joueurs Renvoie: paire (prison_joueur, prison_adversaire) """ stratj = ListeStrategies[joueur["strategie"]] strata = ListeStrategies[adversaire["strategie"]] etatj = stratj(joueur, adversaire) etata = strata(adversaire, joueur) # 1 = avouer # 0 = nier if etatj == 0: if etata == 0: # nie-nie ans_prison = (2, 2) else: # nie-avoue ans_prison = (10, 0) else: if etata == 0: # avoue-nie ans_prison = (0, 10) else: # avoue-avoue ans_prison = (5, 5) StratsResultats[joueur["strategie"]][0] += 1 StratsResultats[joueur["strategie"]][1] += ans_prison[0] StratsResultats[adversaire["strategie"]][0] += 1 StratsResultats[adversaire["strategie"]][1] += ans_prison[1] StratsResultats[joueur["strategie"]][2][Iteration][1] += 1 StratsResultats[joueur["strategie"]][2][Iteration][2] += ans_prison[0] StratsResultats[adversaire["strategie"]][2][Iteration][1] += 1 StratsResultats[adversaire["strategie"]][2][Iteration][2] += ans_prison[0] joueur["etat"] = etatj adversaire["etat"] = etata joueur["annees_de_prison"] += ans_prison[0] adversaire["annees_de_prison"] += ans_prison[1] return ans_prison def partie8tours(x,y): """ Coord -> NoneType Effectue huit parties 1v1 entre le joueur et chacun de ses voisins l'un après l'autre """ for i in range (-1,2): for j in range (-1,2): #(i,j) sont les coordonnées de l'adversaire if (0 <= x+i and x+i < len(Grille)) and (0 <= y+j and y+j < len(Grille[0])) and i != 0 and j != 0: partie1v1(Grille[x][y], Grille[x+i][y+j]) def partie_globale(): """ Effectue une partie de huit par joueur """ global Grille for i in range(len(Grille)): for j in range(len(Grille[0])): partie8tours(i,j) # Changement des stratégies # On parcourt une copie de la grille pour avoir accès aux anciennes stratégies et non pas aux nouvelles adoptées copie_grille = np.copy(Grille) for x in range(len(copie_grille)): for y in range(len(copie_grille[0])): #(x,y) : joueur dont on va modifier la stratégie, si besoin min_prison = copie_grille[x][y]["annees_de_prison"] new_strat = copie_grille[x][y]["strategie"] for i in range (-1,2): for j in range (-1,2): #(x+i,y+j) : adversaires autour de (x,y) if (0 <= x+i and x+i < len(Grille)) and (0 <= y+j and y+j < len(Grille[0])) and i != 0 and j != 0: if min_prison > copie_grille[x+i][y+j]["annees_de_prison"]: new_strat = copie_grille[x+i][y+j]["strategie"] Grille[x][y]["strategie"] = new_strat # on modifie la stratégie du joueur dans la Grille et pas dans la copie # Réinitialisation du nb d'années de prison for j in range(len(Grille[0])): Grille[i][j]['annees_de_prison'] = 0 return Grille ##################################### ### Fonction génératrices de matrices def matrice_init_vide(): """ Crée une matrice contenant des dicts vides {} """ return [[dict() for x in range(TailleGrilleX)] for y in range(TailleGrilleY)] def matrice_init_meme_strat(): """ int -> array Index: 0 Crée la matrice des joueurs où chacun a la même stratégie mais commence avec des statuts différents, générés aléatoirement """ histo_strat = [StratParDefaut] matrice = matrice_init_vide() for i in range(TailleGrilleY): for j in range(TailleGrilleX): etat = random.randint(0, 1) matrice[i][j] = {'etat' : etat, 'strategie' : StratParDefaut, 'annees_de_prison' : 0,\ 'historique_strategies' : histo_strat, 'historique_etats' : [etat]} return matrice def matrice_init_nie_sauf_un(): """ int -> array Index: 1 Crée la matrice des joueurs tel que chaque joueurs nie, sauf un qui avoue. Chaque joueur à la même stratégie """ histo_strat = [StratParDefaut] matrice = matrice_init_vide() for i in range(TailleGrilleY): for j in range(TailleGrilleX): matrice[i][j] = {'etat' : 1, 'strategie' : StratParDefaut, 'annees_de_prison' : 0,\ 'historique_strategies' : histo_strat, 'historique_etats' : [1]} index_aleatoirex = random.randint(0,TailleGrilleX-1) index_aleatoirey = random.randint(0,TailleGrilleY-1) (matrice[index_aleatoirex][index_aleatoirey])['etat'] = 0 return matrice def matrice_init_avoue_sauf_un(): """ int -> array Index: 2 Créer la matrice des joueurs tel que chaque joueur avoue, sauf un qui nie. Tous les joueurs ont la même strategie """ histo_strat = [StratParDefaut] matrice = matrice_init_vide() for i in range(TailleGrilleY): for j in range(TailleGrilleX): matrice[i][j] = {'etat' : 0, 'strategie' : StratParDefaut, 'annees_de_prison' : 0,\ 'historique_strategies' : histo_strat, 'historique_etats' : [0]} index_aleatoirex = random.randint(0,TailleGrilleX-1) index_aleatoirey = random.randint(0,TailleGrilleY-1) (matrice[index_aleatoirex][index_aleatoirey])['etat'] = 1 return matrice def matrice_init_equitable(): """ Crée la matrice des joueurs tel que le probabilité d'apparition de chaque stratégie est équitable. Les états initiaux de chaque joueur sont aléatoires. Index: 3 """ matrice_strat = np.full((TailleGrilleX, TailleGrilleY), -1, dtype=int) nb_de_joueurs_de_chaque = int((TailleGrilleX*TailleGrilleY)/len(ListeStrategies)) places_vides = TailleGrilleX*TailleGrilleY for e in range(len(ListeStrategies)): count_joueurs = 0 while count_joueurs <= nb_de_joueurs_de_chaque: index_aleatoirex = random.randint(0,TailleGrilleX-1) index_aleatoirey = random.randint(0,TailleGrilleY-1) if matrice_strat[index_aleatoirex][index_aleatoirey] != -1: if places_vides < 1: break continue matrice_strat[index_aleatoirex][index_aleatoirey] = e count_joueurs += 1 places_vides -= 1 for i in range(TailleGrilleY): #on vérifie qu'il n'y a pas d'index vides for j in range(TailleGrilleX): #si oui, on le rempli avec une strat aléatoire if matrice_strat[i][j] == -1: matrice_strat[i][j] = random.randint(0, len(ListeStrategies)) matrice = matrice_init_vide() for i in range(TailleGrilleY): for j in range(TailleGrilleX): etat = random.randint(0, 1) matrice[i][j] = {'etat' : etat, 'strategie' : matrice_strat[i][j], 'annees_de_prison' : 0,\ 'historique_strategies' : [matrice_strat[i][j]], 'historique_etats' : [etat]} return matrice def matrice_init_pourcents_choisis(): """ list[float] -> array Index: 4 ListePourcents contient des float de 0.0 à 1.0. Crée la matrice des joueurs tel que le pourcentage de chaque stratégie est choisi. Les états initiaux sont choisis aléatoirement. """ if (len(ListePourcents) != len(ListeStrategies)): print("Erreur: matrice_init_pourcents_choisis: liste_pourcent est de taille incorrecte!") matrice_strat = np.full((TailleGrilleX, TailleGrilleY), -1, dtype=int) list_nb_joueurs_de_chaque = list() for i in range(len(ListePourcents)): list_nb_joueurs_de_chaque.append((TailleGrilleX*TailleGrilleY)*ListePourcents[i]) places_vides = TailleGrilleX*TailleGrilleY for e in range(len(ListePourcents)): count_joueurs = 0 while count_joueurs <= list_nb_joueurs_de_chaque[e]: index_aleatoirex = random.randint(0,TailleGrilleX-1) index_aleatoirey = random.randint(0,TailleGrilleY-1) if matrice_strat[index_aleatoirex][index_aleatoirey] != -1: if places_vides < 1: break continue matrice_strat[index_aleatoirex][index_aleatoirey] = e count_joueurs += 1 places_vides -= 1 for i in range(TailleGrilleY): #on vérifie qu'il n'y a pas d'index vides for j in range(TailleGrilleX): #si oui, on le rempli avec une strat aléatoire if matrice_strat[i][j] == 0: matrice_strat[i][j] = random.randint(0, len(ListePourcents)) matrice = matrice_init_vide() for i in range(TailleGrilleY): for j in range(TailleGrilleX): etat = random.randint(0, 1) matrice[i][j] = {'etat' : etat, 'strategie' : matrice_strat[i][j], 'annees_de_prison' : 0,\ 'historique_strategies' : [matrice_strat[i][j]], 'historique_etats' : [etat]} return matrice ####################### ### Fonction stratégies def strat_toujours_nier(joueur, adversaire): """ Joueur^2 -> int Index: 0 Toujours nier (coopération) """ return 0 # 0 : coop def strat_toujours_avouer(joueur, adversaire): """ Joueur^2 -> int Index: 1 Toujours avouer (trahir) """ return 1 #1 : traître def strat_meilleur_gain (joueur, adversaire): """ Joueur^2 -> int Index : 5 Le joueur adopte l'état de l'adversaire ayant obtenu le meilleur gain (= le moins d'années de prison) """ max_gain = joueur['annees_de_prison'] nveau_etat = joueur['etat'] for i in range (-1,2): for j in range (-1,2): #(i,j) sont les coordonnées de l'adversaire if (0 <= x+i and x+i < len(Grille)) and (0 <= y+j and y+j < len(Grille[0])) and i != 0 and j != 0: if Grille[i][j]['annees_de_prison'] < max_gain : max_gain = Grille[i][j]['annees_de_prison'] nveau_etat = Grille[i][j]['etat'] return nveau_etat def strat_precedent_adversaire(joueur, adversaire): """ Joueur^2 -> int Index: 3 Le joueur avoue/nie si durant la partie locale précédente, son adversaire avait avoué/nié (on utilise l'hisorique des états) """ return adversaire['historique_etats'][len(adversaire['historique_etats'])-1] == 0 def strat_principal_adversaire(joueur, adversaire): """ Joueur^2 -> int Index: 4 Le joueur avoue/nie si l’adversaire avait majoritairement avoué/nié durant ses parties précédentes (on utilise l'hisorique des états) Si aucun état n’est majoritaire, la coopération l’emporte (le joueur nie) """ s = 0 # somme des entiers représentant les états for i in adversaire['historique_etats']: s += i if len(adversaire['historique_etats']) == 0: return 0 elif (s/len(adversaire['historique_etats'])) > 0.5: return 1 else: return 0 ############################################################################### ############## ### Simulation def init_complete(): """ Rajoute à ListeStrategies toutes les fonctions stratégies Rajoute à ListeGenGrille toutes les fonctions de génération de grille """ ListeGenGrille.append(matrice_init_meme_strat) # 0 ListeGenGrille.append(matrice_init_nie_sauf_un) # 1 ListeGenGrille.append(matrice_init_avoue_sauf_un) # 2 ListeGenGrille.append(matrice_init_equitable) # 3 ListeGenGrille.append(matrice_init_pourcents_choisis) # 4 ListeStrategies.append(strat_toujours_nier) # 0 ListeStrategies.append(strat_toujours_avouer) # 1 ListeStrategies.append(strat_altern) # 2 ListeStrategies.append(strat_precedent_adversaire) # 3 ListeStrategies.append(strat_principal_adversaire) # 4 global Grille global StratsResultats Grille = gen_matrice_initiale() for i in range(len(ListeStrategies)): StratsResultats.append([0, 0, [ [0, 0, 0] ]]) for x in range(TailleGrilleX): for y in range(TailleGrilleY): if Grille[x][y]["strategie"] == i: StratsResultats[i][2][0][0] += 1 return Grille def simulation(): global Iteration global HistoriqueGrilles Iteration = 0 while Iteration <= MaxIterations: HistoriqueGrilles.append(copy.deepcopy(Grille)) Iteration += 1 for i in range(len(StratsResultats)): StratsResultats[i][2].append([0, 0, 0]) partie_globale() for i in range(len(StratsResultats)): for x in range(TailleGrilleX): for y in range(TailleGrilleY): if Grille[x][y]["strategie"] == i: StratsResultats[i][2][Iteration][0] += 1 return Grille ############################################################################### ### Affichage dynamique et graphiques def matRecup(i, param): """array*str-> array Récupère la matrice avec seulement le paramètre stratégie pour chaque joueur , à litération i voulue""" matR = np.random.randint(0,1,(TailleGrilleX,TailleGrilleY)) matrice = HistoriqueGrilles[i] for ligne in range (0,TailleGrilleX): #int ligne for colonne in range (0, TailleGrilleY): #int colonne matR[ligne][colonne]=matrice[ligne][colonne][param] return matR def afficher_strat_dynamique(): fig=plt.figure() fig.suptitle('Animation des stratégies') cmap = mpl.colors.ListedColormap(["b","r" ,"black" ,"g" ,"purple"]) bounds=[0,1,2,3,4,5] norm=mpl.colors.BoundaryNorm(bounds, cmap.N) img=plt.imshow(matRecup(0, 'strategie'), interpolation = "nearest", cmap = cmap , norm = norm) cb=plt.colorbar(img , cmap=cmap , norm=norm , boundaries = bounds , ticks=bounds) labels = np.arange(0, 5, 1) cb.set_ticklabels(labels) def update(next_iteration,*args): img.set_array(matRecup(next_iteration , 'strategie')) return [img] anim = animation.FuncAnimation(fig, update, frames=range(MaxIterations), interval=500, repeat = False) plt.show(block = True) def afficher_etat_dynamique(): fig=plt.figure() fig.suptitle('Animation des états') cmap = mpl.colors.ListedColormap(["black","white"]) bounds=[0,1,2] norm=mpl.colors.BoundaryNorm(bounds, cmap.N) img=plt.imshow(matRecup(0, 'etat'), interpolation = "nearest", cmap = cmap , norm = norm) cb=plt.colorbar(img , cmap=cmap , norm=norm , boundaries = bounds , ticks=bounds) labels = np.arange(0, 2, 1) cb.set_ticklabels(labels) def update(next_iteration,*args): img.set_array(matRecup(next_iteration , 'etat')) return [img] anim = animation.FuncAnimation(fig, update, frames=range(MaxIterations), interval=500, repeat = False) plt.show(block = True) def affichage_strats_resultats_totaux(): """array->graph Retourne les diagrammes en baton qui mettent en évidence le nombre moyen d'années de prison en fonction de la stratégie et le nombre d'utilisation de chaque stratégies """ #initialisation des paramètres #list gain gain=[] #list strat stratUtili=[] #nb_utilisations utilisateurs=list() #uti[strat][iter] = nb #iteration iteration=[] for i in range(5): gain.append(0) stratUtili.append(0) for i in range(0,len(ListeStrategies)): stratUtili[i]=StratsResultats[i][0] if StratsResultats[i][0]==0: gain[i] else: gain[i]=StratsResultats[i][1]/StratsResultats[i][0] utilisateurs.append([]) for i in range(0,MaxIterations+1): for j in range(0,len(ListeStrategies)): utilisateurs[j].append(StratsResultats[j][2][i][0]) iteration.append(i) Strat=('0','1', '2','3' ,'4') x_pos = np.arange(len(Strat)) plt.subplot(221) plt.title("Nombre d'adoptions de chaque stratégie") plt.bar(x_pos, stratUtili, align='center' , color=CouleursStrat) plt.xlabel("Stratégies") plt.ylabel("Nombre individus ayant adopté stratégie") plt.xticks(x_pos,Strat) plt.subplot(222) plt.title("Nombre moyen d'années de prison de chaque stratégie") plt.bar(x_pos, gain, align='center', color=CouleursStrat ) plt.xlabel("Stratégies") plt.ylabel("Nombre moyen d'années de prison ") plt.xticks(x_pos,Strat) plt.subplot(223) plt.title("Evolution du nombre d'utilisateurs de chaque stratégie au cours des itérations") plt.xlabel('Iterations') plt.ylabel("Nombre utilisateurs") for i in range(len(ListeStrategies)): plt.plot(iteration,utilisateurs[i], CouleursStrat[i] ,linewidth=5 ,label="Stratégie" + str(i)) plt.show() plt.legend()