Marchandage et partage d'objetspar Bastien Ibanez - Lucas Bugeaud Université Paris Dauphine - Master 1 - Mathématiques appliquées 2021 |
2.3 Exemple d'application réelle de cette théoriePour conclure cette partie théorique voici un exemple de jeu de marchandage faisant intervenir les concepts développés jusqu'à maintenant et qui puisse s'appliquer à une situation réelle, tout en mettant en évidence certaines limites. Prenons le cadre de l'Union Européenne. Supposons que la commission européenne ait pour mission de répartir des vaccins aux États membres dans le cadre de la crise du COVID-19. Elle se doit d'avoir un jugement impartial entre les pays, elle joue donc le rôle du juge. Les pays sont les joueurs qui veulent maximiser les vaccins reçus, et donc maximiser leur utilité. Cette utilité liée aux vaccins est d'autant plus grande que l'état du système de santé du pays en question est sous-développé et que le nombre de cas positifs au COVID-19 y résidant est grand. Si les pays ne se mettent pas d'accord, personne n'aura de vaccin car ceux-ci ont entre temps été achetés aux laboratoires par d'autres pays hors Union Européenne. La solution de Nash appliquée à ce problème permettrait d'avoir une répartition des vaccins juste et la plus efficace possible. 10 Cette utilisation de la solution de Nash est imaginable, il faut néanmoins en énoncer certaines limites. Il se peut en effet que dans la réalité elle soit politiquement inapplicable. Par exemple si la France et l'Allemagne ne reçoivent que très peu de vaccins en raison de leurs bons systèmes de santé, ils seront davantage à même de bloquer cette décision car ils font partie des pays ayant le plus d'influence au sein de l'Union Européenne. Malgré tout, la solution de Nash pourrait servir d'indicateur sur la voie à suivre. Par ailleurs, on peut aussi imaginer que des pays choisissent de mentir à la commission sur l'état de leur système de santé ainsi que le nombre de cas de COVID dans leur pays. Ce mensonge influerait sur la solution de Nash et augmenterait le nombre de doses reçues par le pays. On peut imaginer encore une fois que pour dissuader cette éventualité, la commission enverrait des inspecteurs européens dans les différents pays pour vérifier l'utilité annoncée et en cas de duperie la pays se verrait infliger une amende. Cette exemple met en lumière la grande applicabilité de cette théorie, bien qu'à première vue elle paraisse plutôt théorique. 2.4 Conclusion sur la partie théorique de la solution de NashCette partie a été l'occasion de présenter la démarche axiomatique entreprise par J.F Nash pour trouver une solution au problème de marchandage ainsi qu'à démontrer l'existence de la solution qu'induit ce choix des axiomes. On remarque que le choix des axiomes relève avant tout d'un choix arbitraire destiné à faire émerger une solution, il n'est pas exclu que certains de ces axiomes fassent l'objet de remises en question. De plus, le dernier exemple évoqué donne un premier aperçu des difficultés que peut rencontrer l'application de cette théorie à des cas pratiques. L'enjeu de notre mémoire consiste désormais à numériser une telle solution pour pouvoir l'appliquer à des cas concrets, en valider certains aspects et en montrer ses limites. 11 3 Développement numérique du jeu de marchandage Remarque : Toute cette partie numérique fait référence au fichier "Nash_solver" Il est aussi possible de se référer aux sections 8.2.1 et 8.2.2 mises en annexe. 3.1 De la théorie au numérique Nous avons montré comment il était possible de trouver la solution de Nash pour un jeu (A,d). Afin de pouvoir implémenter et développer l'exemple décrit en introduction, il est nécessaire de construire l'algorithme permettant la résolution d'un jeu de marchandage. On a vu que tout jeu était décrit à l'aide du couple (A,d), où A est un ensemble convexe et d est le point de désutilité. Dans un jeu à deux joueurs, l'ensemble A est l'enveloppe convexe des couples d'utilités des joueurs. L'ensemble A sera donc du type list (voire même list de list où cette dernière comporte les utilités de chacun des joueurs). Le point de désutilité d sera quant à lui du type array qui permet des manipulations plus faciles, notamment quant il s'agit de translater les points d'un ensemble selon le vecteur d afin de centrer l'ensemble A en [0,0]. Nous allons dans un premier temps présenter les étapes clés qui ont permis la construction de l'algorithme de résolution du jeu de Nash. Nous illustrerons ces parties grâce aux données suivantes, tirées au hasard : L = [[444, 968], [261, 220], [646, 985], [815, 878], [929, 122],
d = [1,28] Voici premier plot de nos points, le point de désaccord est mis en évidence en rouge. FIGURE 1 - Ensemble des points choisis pour l'illustration 3.2 Exhibition de la frontière de Pareto En premier lieu, la solution de Nash se trouve nécessairement sur la frontière de Pareto qui constitue l'ensemble des meilleures alternatives possibles pour les joueurs. Il convient donc de 12 FIGURE 2 - Premier tri de la liste (de droite à gauche et bas en haut) trier la liste des couples d'utilité pour garder uniquement ceux constituant cette frontière. 1. Première étape: trier la liste Il est tout d'abord nécessaire de faire un premier tri afin de pouvoir facilement manipuler la liste de points. La figure montre bien le choix de tri qui a été fait. On remarque que tous les points désignés par une flèche orientée vers le bas ne seront pas retenus car strictement Pareto-dominés par ceux qui l'entourent (ce ne sont pas les seuls, nous le verrons par la suite) Voici les fonctions utiles à ce premier tri : 1 2 def first_component(a): # renvoie l'abscisse d'un point de R2 3 return a[0] 4 def second_component(a): # renvoie l'ordonnee d'un point de R2 5 return a[1] 6 7 def double_sort(L): 8 S = sorted(L, key = second_component, reverse = True) 9 S.sort(key = first_component, reverse = True) # la
méthode "sort" 10 return S 11 # prend en entree une liste de points de R2 renvoie 12 # la liste triee par ordre decroissant par rapport a la premiere ãÑ composante 13 # les points de premiere composante egale sont tries par rapport a la ãÑ seconde Voici l'état de la liste qui en résulte : L = [[958, 304], [929, 122], [815, 878], [670, 198], [646, 985], [638, 136], [608, 674], [569, 491], [536, 550], [444, 968], [435, 992], [372, 283], [346, 161], [261, 220], [255, 962]] 2. Seconde étape : Frontière de Pareto Après avoir trié intelligemment la liste, il nous faut exclure les points Pareto-dominés de notre liste. Dans un premier temps, la fonction first_selection élimine les points désignés 13 par les flèches orientées vers le bas, qui sont comme évoqué précédemment, Pareto-dominés par leurs voisins. Cela ne suffit pas, car parmi les points restants, certains peuvent se situer en-dessous de la droite reliant ses deux voisins, auquel cas, il est dominé par toutes combinaisons linéaires de ces derniers. Les fonctions above et second_selection permettent de terminer d'exhiber de la frontière de Pareto. 14 def first_selection(L): 15 S = [L[0]] # L etant triee par
"double_sort", L[0] sera forcement
le 16 n = len(L) 17 i = 1 18 j = 0 19 while i < n: 20 if L[i][0] < S[j][0] and L[i][1] > S[j][1]: 21 S.append(L[i]) 22 j+=1 23 i+=1 24 return S 25 # prend en entree une liste triee par la fonction "double_sort" 26 # renvoie une sous-liste strictement décroissante pour la premiere 27 # composante et strictement croissante pour la seconde 28 29 def above(a,b,c): 30 return b[1] >
(a[1]*(b[0]-c[0])/(a[0]-c[0])) + 31 # prend en entree trois points strictement decroissants/croissants 32 # pour la premiere/seconde composante renvoie "True" ssi le point du ãÑ milieu 33 # est strictement au-dessus de la droite passant par les deux autres 34 35 def second_selection(L): 36 if len(L) == 1: return L 37 S = [L[0],L[1]] 38 n = len(L) 39 i = 2 40 j = 0 41 while i < n: 42 if above(S[j],S[j+1],L[i]): 43 S.append(L[i]) 44 j+=1 45 i+=1 46 else: 47 S.pop() 48 if j == 0: 49 S.append(L[i]) 50 i+=1 51 else: 52 j-=1 53 return(S) 14 54 # prend en entree une liste strictement decroissante/croissante pour la ãÑ premiere/ 55 # seconde composante renvoie la sous-liste privee des points ãÑ Pareto-domines 56 # par une combinaison d'autres points Notre exemple de liste n'étant pas assez exhaustif, il ne met pas en avant la différence apportée par la fonction second_selection, voici donc deux print tirés d'une liste plus exhaustive, et qui illustre bien le passage de la première à la seconde sélection. On exhibe par ailleurs la frontière de Pareto de notre liste initiale sur la figure. Voici la liste finale : L = [[958,304], [815,878], [646,985], [435,992]] 3.3 Solution du jeu de Nash Après avoir réussi à réduire la liste en incluant uniquement les points appartenant à la frontière de Pareto, il nous est désormais possible de trouver la solution du problème selon Nash. On rappelle pour cela que la solution de Nash maximise la fonction produit de la frontière de Pareto. Autrement dit, il faut trouver la combinaison linéaire de deux points appartenant à la frontière (ou un point appartenant directement à la frontière s'il s'agit du maximiseur) qui maximise l'aire du rectangle dont une des diagonales rejoint le point de désaccord et le maximiseur en question. Pour cela, les fonctions x_max et y_max sont utilisées afin de trouver l'abscisse et l'ordonnée respectives du point qui maximise la fonction produit sur une droite passant par deux points. Le maximum ne se situe pas nécessairement entre les deux points. 57 def y_max(a,b): # a est sous la forme [x1,y1] 58 a_1, a_2, b_1, b_2 = a[0], a[1] ,b[0] ,b[1] 59 p_cut = b_1/(b_1-a_1) 60 return (p_cut*a_2 + (1-p_cut)*b_2)/2 61 62 def x_max(a,b): 63 a_1, a_2 ,b_1 ,b_2 = a[0], a[1] ,b[0] ,b[1] 64 p_cut = b_2/(b_2-a_2) 65 return (p_cut*a_1 + (1-p_cut)*b_1)/2 Il est à présent possible de trouver la solution de Nash par dichotomie. Brièvement, nous comparons deux points de l'enveloppe : 1. Soit le maximum de la fonction produit se trouve entre les deux points, dans ce cas le point représente la solution de Nash 2. Soit le maximum de la fonction produit se trouve à gauche du segment reliant les deux points, deux possibilités s'ouvrent à nous:
3. Le raisonnement est similaire pour le cas où le maximum de la fonction produit se trouve à droite du segment reliant les deux points FIGURE 3 - Ensemble L après first_selection FIGURE 4 - Ensemble L après second_selection FIGURE 5 - Frontière de Pareto de notre liste initiale 15 16 Voici les fonctions qui nous permettent de trouver la solution finale : (à noter que la fonction solution_rec renvoie un array avec: la solution, les deux points issus de la combinaison amenant au résultat ainsi que les coefficients de la combinaison ([1,0] si le point appartient à l'enveloppe)) 66 def y_max(a,b): # a est sous la forme [x1,y1] 67 a_1, a_2, b_1, b_2 = a[0], a[1] ,b[0] ,b[1] 68 p_cut = b_1/(b_1-a_1) 69 return (p_cut*a_2 + (1-p_cut)*b_2)/2 70 # prend en entree deux points strictement decroissants/croissants pour la ãÑ premiere 71 # /seconde composante renvoie l'ordonnee du maximiseur de la "fonction produit"
72 # la droite passant par ces deux points 73 74 def x_max(a,b): 75 a_1, a_2 ,b_1 ,b_2 = a[0], a[1] ,b[0] ,b[1] 76 p_cut = b_2/(b_2-a_2) 77 return (p_cut*a_1 + (1-p_cut)*b_1)/2 78 79 # prend en entrée une liste traitee par "frontier_points" 80 # renvoie le point de l'enveloppe convexe de la liste qui maximise la "fonction ãÑ produit" 81 def solution_rec(L): 82 n = len(L) 83 if n == 0: 84 print("Echec de la recurrence") 85 if n == 1: 86 return np.array([[L[0][0],L[0][1]],[0,0],[0,0],[1,0]]) 87 else: 88 m = n//2 89 a, b = L[m-1], L[m] 90 y = y_max(a,b) 91 if y < a[1]: 92 if n > 2: 93 return solution_rec(L[:m]) 94 else: 95 s = np.array([a[0],a[1]]) 96 a = np.array([a[0],a[1]]) 97 b = np.array([b[0],b[1]]) 98 c = np.array([1,0]) 99 return np.array([s,a,b,c]) 100 if y > b[1]: 101 if n > 2: 102 return solution_rec(L[m:]) 103 else: 104 s = np.array([b[0],b[1]]) 105 a = np.array([a[0],a[1]]) 106 b = np.array([b[0],b[1]]) 107 c = np.array([0,1]) 108 return np.array([s,a,b,c]) 109 else: 110 x = x_max(a,b) 111 p = (x - b[0]) / (a[0]-b[0]) 112 s = np.array([x,y]) 113 a = np.array([a[0],a[1]]) 114 b = np.array([b[0],b[1]]) 115 c = np.array([p,1-p]) 116 return np.array([s,a,b,c]) 117 Important : Dans ce dernier paragraphe, la solution de Nash était avant tout le maximum de la fonction produit de la frontière de Pareto dans un ensemble centré en [0,0], c'est à dire que le point de désaccord est nécessairement [0,0]. Pour trouver la solution de Nash d'un problème quelconque, il est nécessaire d'introduire une fonction shift qui permet de centrer l'ensemble, d'en exhiber le maximum de la fonction produit, et de l'incrémenter à nouveau de la valeur du point de désaccord. Voici les fonctions en question : 118 def shift(L,v): 119 L_shifted = [] 120 for i in range(len(L)): 121 P = np.array([ L[i][0] + v[0], L[i][1] + v[1] ]) 17 122 L_shifted.append(P) 123 return L_shifted 124 125 def true_solution(A,d): 126 L = shift(A+[d], (-1)*d) 127 F = frontier_points(L) 128 s = solution_rec(F) 129 s_list =[] 130 for i in range (3): 131 s_list.append(shift(to_list(s[i]),d)) #
la fonction shift prends en 132 # le point solution, le point a et le point b sont incrémentés du point d L=[] 133 134 for i in range (len(s_list)): # on remet les valeurs de la solution ãÑ incrémentées par le point d 135 p = [s_list[i][0][0], s_list[i][0][1]] 136 L.append(p) 137 L.append([s[3][0],s[3][1]]) 138 return L Nous avons désormais les outils nécessaires permettant de trouver la solution de Nash à notre exemple de départ : la solution est le point de la liste initiale : [815, 878] Voici un autre résultat d'un exemple quelconque où la solution est une combinaison de deux points : La solution est une combinaison linéaire du point [955.0, 779.0] chargé du poids 0.29 et du point [819.0, 913.0] chargé du poids 0.71 La solution est le point [859.1, 873.49] 18 On peut maintenant écrire une fonction qui permet d'afficher un plot de notre solution, voici le résultat de notre exemple : FIGURE 6 - Plot final de la solution de Nash 19 4 Étude numérique : voiture partagée "uberisée" 4.1 Rappel introductif Dans un premier temps, remettons en contexte l'exemple décrit en introduction. Le jeu s'articule autour de deux joueurs se trouvant chacun à un endroit et souhaitant se rendre à un endroit différent. Une voiture reçoit les requêtes des joueurs, à peu près simultanément par soucis de simplification et neuf possibilités s'offrent à elle, parmi lesquelles notamment : -- la voiture vient chercher J1 puis J2, dépose J1 puis J2 -- la voiture va chercher J1, le dépose, elle va ensuite chercher J2 pour le déposer -- la voiture va chercher J1 et J2 doit se rendre à pied à destination -- chacun des joueurs se rend à pied à sa destination. Cet exemple ne correspond pas exactement à ce à quoi on pourrait s'attendre intuitivement d'un jeu de marchandage. Le schéma de pensée s'orienterait davantage autour d'une discussion entre deux joueurs au sujet du partage de biens disponibles, le partage serait tranché par un arbitre désintéressé en suivant les 4 axiomes décrits pas J.F Nash. Le partage d'un héritage entre plusieurs membres d'une famille se prête bien à cette description. Ces exemples ont été évoqués dans la partie 1.2 Remettons donc en place les différents paramètres constituant un jeu de marchandage qui se prêtent ici à notre modèle. L'utilité des joueurs est sûrement le point le plus contestable. En effet, dans un jeu de marchandage classique, deux options sont imaginables : les acteurs ont soit, chacun quelque chose à partager (exemple: un agriculteur partage avec le supermarché local une partie de sa récolte contre de l'argent), soit un ensemble de biens qui leur ait collectivement légué et qu'ils se répartissent entre eux (l'exemple déjà cité précédemment d'un héritage). Ici, les biens partageables ne sont pas matériels mais plutôt immatériels voire idéologiques. En effet, la première ressource que les acteurs se partagent est le temps. Aller chercher un joueur puis prendre le suivant dans la foulée est, dans la plupart du temps, une perte de temps pour le premier. On peut alors imaginer que l'utilité d'un joueur soit maximale à condition qu'il soit le seul client du chauffeur. Dans un cas pareil, le jeu de marchandage n'a pas de raison d'être car un joueur ne rentre dans un jeu de marchandage que s'il y trouve un intérêt. Il est donc nécessaire de conceptualiser cet intérêt par un facteur supplémentaire qui incite le joueur à participer au jeu. Le facteur imaginé ici, est idéologique, il se matérialise sous la forme d'un marqueur de bonne volonté pour lequel les joueurs consentiraient à contribuer au principe de partage de l'utilisation d'une même voiture. Les raisons seraient par exemple, soit écologiques ou soit de l'ordre d'une solidarité exprimée vis-à-vis d'une petite entreprise ne possédant pas encore beaucoup de véhicules. Ce postulat ne constitue pas un frein majeur à la transposition de notre exemple dans la réalité étant donné que des principes de covoiturages et autres façons diverses de partager des voitures sont déjà implantés dans notre société. On s'autorise à modéliser l'utilité des joueurs en fonction uniquement du temps qu'ils mettent à se rendre à l'endroit désiré. Le facteur de bonne volonté est implicitement suggéré dans l'existence même du jeu par le fait que chacun des joueurs accepte de concéder un peu de leur temps pour en faire gagner à l'autre. Des fonctions d'utilité concaves en la variable de temporalité permettent le bon fonctionnement de l'exemple. En effet, les joueurs souhaitent malgré tout minimiser leurs temps de trajet, ainsi la composition d'une fonction concave avec le temps de trajet permet d'obtenir un ensemble convexe. 20 A présent loti de notre ensemble convexe, il convient de fixer le point de désaccord indispensable au jeu de marchandage. Il parait naturel que l'une des alternatives suggérant le fait que les deux joueurs soient obligés de se rendre à pied à leur destination constitue le point de désaccord évident de notre jeu. On complète la théorie en attribuant à la voiture (ou indifféremment au chauffeur) le rôle d'arbitre désintéressé du jeu dont le rôle est de prendre la meilleure décision en connaissance des utilités des joueurs, de leurs positions et leur endroit d'arrivée. 4.2 Notations Les notations en dimension 1 sont les suivantes : -- x1 = la position de départ du joueur 1 -- x2 = la position de départ du joueur 2 -- y1 = l'endroit d'arrivée du joueur 1 -- y2 = l'endroit d'arrivée du joueur 2 -- v = la position de départ de la voiture. Nous allons étudier un cas simplifié de notre exemple en nous concentrant sur le segment [0,1]. L'utilité attribuée à chaque joueur est une fonction concave qui va dépendre du temps. On choisit arbitrairement la fonction uipt1, t2q « 't2 i . On distingue également le temps parcouru en voiture tv et le temps parcouru à pied tm :
Ce choix simplifie légèrement le calcul des distances mais a pour défaut de recourir souvent aux mêmes alternatives. Il faut par exemple que deux points x1 et x2 soient complètement opposés pour que la voiture choisissent d'en prendre un et de le déposer avant de prendre le second. Exemple : dans cette configuration, mise à part un changement majeur, la solution sera quasi- systématiquement : La voiture ira chercher J2 puis J1, déposera J1 puis J2 Un choix de dimension 2 sur une grille aurait sûrement permis à d'autres alternatives de ressortir plus régulièrement. 4.4 Perspectives d'études Ce jeu nous offre plusieurs possibilités. Dans un premier temps, il nous faut coder les solutions du jeu en fonction des paramètres initiaux. Nous allons laisser apparaître les résultats de la console ainsi que les graphiques qui permettent d'illustrer le fonctionnement de certaines fonctions. Le code dans son intégralité est laissé disponible en annexe. Rendre possible le calcul numérique de ces solutions nous permet également d'en tester les limites. En effet, nous avons laissé entendre en introduction qu'un joueur (ou les deux) pouvait choisir de mentir sur la position d'arrivée qu'il indiquait à la voiture, cela induit inévitablement le calcul d'une solution différente lui permettant dans certains cas d'obtenir davantage d'utilité, au détriment parfois de l'utilité de l'autre joueur. Le recours à des concepts de théorie des jeux vont nous permettre d'étudier les effets ainsi que la récurrence de cet aspect du modèle. Il est également intéressant de se mettre à la place de la compagnie. En effet, sa problématique consiste à traiter au mieux la gestion de ses voitures afin d'en utiliser le moins possible, en prenant 21 en charge plusieurs utilisateurs à la fois. Cette dernière envisage de considérer la solution de Nash pour résoudre cette problématique. L'étude des comportements tel que le mensonge peut lui permettre de juger la pertinence de l'application d'un jeu de marchandage à son business (qui consiste dans la mesure de ses capacités à satisfaire ses clients). On a vu également que la solution théorique n'aboutissait pas systématiquement sur un point appartenant à l'ensemble des alternatives. Cela implique le recours au hasard lorsque la solution est issue de la combinaison de deux possibilités. On peut imaginer que la compagnie souhaiterait savoir si avec une probabilité raisonnable elle peut espérer obtenir des solutions pures. 4.5 Application de l'algorithme à un cas simple Remarque: Cette partie numérique fait référence aux fichiers "Etude_probleme_voiture_partagee" et "Applications_theorie_des_jeux" Il est aussi possible de se référer aux sections 8.2.3 et 8.2.4 mises en annexe.. Dans un premier temps, nous allons étudier un cas fixé nous permettant d'imager les résultats renvoyés par notre code. Pour cela, imaginons la situation suivante pour laquelle les deux joueurs se situent dans des quartiers différents délimités par les sous-segments [0,0.2] et [0.3,0.35] et souhaitent tous deux se rendre sur leur lieu de travail se situant dans une zone industrielle située dans [0.7,1.0]. Les joueurs sont positionnés arbitrairement en x1 = 0.02 et x2 = 0.34. Ils souhaitent se rendre en y1 = 0.84 et en y2 = 0.71. La voiture est placée en v = 0.5. Rappelons également que la fonction d'utilité est la même pour les deux joueurs à savoir: ui(t1, t2) = 10--t2 i et que le temps de marche est défini comme tm,i(x, y) = Ktv,i(x, y) où on choisira K = 5. La marche est donc un facteur pénalisant dans le calcul de l'utilité du joueur même si elle n'intervient pas encore car les deux joueurs annonce ici l'endroit où ils souhaitent véritablement se rendre en voiture. Voici le message affiché par la console ainsi que le plot de la résolution : 139 140 Solution du jeu classique 141 142 La voiture est placée en 0.5 sur [0,1] 143 144 Le joueur 1 est placée en 0.02 sur [0,1] et souhaite se rendre en 0.84 à 145 146 Le joueur 2 est placée en 0.34 sur [0,1] et souhaite se rendre en 0.71 147 148 Le point de désaccord correspondant au fait que les deux joueurs se rendent ãÑ pied 149 est [-6.81 6.578] 150 Avec une réalisation classique du jeu, l'action suivante sera choisie : 151 La voiture ira chercher J2, le déposera, puis ira chercher J1 et le déposera 152 153 J1 en retire une utilité de 5.838 154 155 J2 en retire une utilité de 9.719 156 22 FIGURE 7 - Plot de notre solution simple On remarque qu'une autre configuration peut également nous donner une solution mixte. On imagine que dans un tel cas, l'entreprise serait obligée de tirer une des deux solutions au hasard. D'un point de vue pratique, ce n'est pas une configuration souhaitable pour l'entreprise qui préfère obtenir une solution simple parmi les alternatives proposées. 157 Solution du jeu classique 158 159 La voiture est placée en 0.2 sur [0,1] 160 161 Le joueur 1 est placée en 0.05 sur [0,1] et souhaite se rendre en 0.89 162 163 Le joueur 2 est placée en 0.6 sur [0,1] et souhaite se rendre en 0.91 164 165 Le point de désaccord correspondant au fait que les deux joueurs se rendent à ãÑ pied est [-7.64 7.6 ] 166 Avec une réalisation classique du jeu, l'action suivante sera choisie : 167 0.6 fois du temps, on aura l'action : La voiture ira chercher .31 puis .32, ãÑ déposera .31 puis .32 168 169 0.4 fois du temps, on aura l'action : La voiture ira chercher .32, le déposera, ãÑ puis ira chercher .31 et le déposera 170 171 .31 en retire une utilité de 7.1 172 173 .32 en retire une utilité de 9.19 23 4.6 La problématique du mensonge 4.6.1 Jeu à information parfaite Continuons l'analyse en donnant la possibilité au joueur de mentir sur sa position d'arrivée. S'il décide de mentir, le joueur est déposé à l'endroit qu'il a annoncé et doit donc parcourir la distance restante à pied. Le joueur cherche donc d'abord à connaître le point d'arrivée le plus favorable qui lui permette de maximiser son utilité. Pour implémenter la recherche de ce y et limiter le nombre et le temps de calcul, nous avons opté pour une méthode de dichotomie à trois variables permettant de trouver une bonne approximation de l'utilité maximum en fonction du point d'arrivée du joueur sur le segment. On choisit d'ajouter une variable à la méthode de dichotomie à deux variables car cette dernière n'est pas adaptée en tant que tel pour trouver un extrema. La méthode consiste ici à évaluer l'utilité (recherche sollicitant beaucoup de calculs) en 3 points : a < p < m < q < b Ainsi, chercher le maximum a sur l'intervalle [a,b] se réduit aux 3 possibilités suivantes :
Nous allons maintenant montrer que u est une solution au problème de marchandage à 2 joueurs et qu'elle satisfait l'axiome de monotonicité.
La monotonicité va se prouver géométriquement. Soit Lá est une droite de pente a avec 0 ï a ï 2 passant par d. Si po1paq, o2paqq est le point d'intersection de Lá avec la frontière de tx P R2 : Dy P A, x ì 0 et x ï yu, alors si /3 a, o2p/3q ì o2paq et si po12'paq,o22'paqq est le point correspondant pour pA2,dq, on a que o1 páq ì op1' p2' 1 . On rappelle que dans le cadre de cet axiome gA1 ï gA2.
Prouvons finalement que u est l'unique solution qui satisfait la condition de monotonicité. Soit pA, 0q un jeu normalisé et f une solution monotonique. p1, 0q, upA', 0qu un Soit A' « tx P R2 : Dy P A tel que x ì 0 et x ï yu. pA', 0q est bien un jeu normalisé avec A A' tel qu'il n'existe pas de point y tel que y ì fpA', 0q et y %o fpA', 0q. Donc fpA, 0q « fpA', 0q. Les points p0,1q et p1,0q sont dans A'. Soit A'' « tp0,1q, convexe. Alors pA'', 0q est un jeu normalisé symétrique pour les 2 joueurs avec A'' A'. Nous avons donc fpA'', 0q « upA', 0q. On remarque aussi que A' ne contient aucun point y tel que y ì fpA'', 0q et y %o fpA'', 0q. Donc fpA, 0q « upA', 0q « upA, 0q. Revenons à notre exemple des étudiants. Ceux-ci doivent se mettre d'accord pour de l'entraide concernant 2 examens à passer. Dans ce problème notre point de désaccord était d « p0, 0q et on avait à notre disposition deux ensembles d'alternatives : A1 « tp20, 0q, p0, 20q, p15, 15qu et A2 « tp20, 0q, p0, 20q, p20, 14qu. Les solutions de Nash avec A1 et A2 étaient respectivement p15, 15q et p20, 14q. D'après Kalai et Smorodinsky, la solution du Joueur 2 devrait être supérieure avec A2 car la moyenne maximum atteignable par le joueur 2 peut obtenir si le joueur 1 obtient au moins la moyenne x est supérieure avec A2. Calculons les solutions monotoniques de ce problème et voyons si cela résout notre problème concernant la solution de Nash. Tout d'abord pour A1 nous devons donc résoudre le problème suivant : " « M1pA1q ' d1 ' p 1q ' u2 d2 M2 A d2 max pu1, u2q P ]I82 + | u1 ' d1 En remplaçant on obtient : " max px, y, zq P ]I83 120x ` 15z « 20 } 20y ` 15z 20 40 sachant que x + y + z = 1 et que x, y, z 0 On obtient donc : max { (x, y, z) E 1183 | x = y} sachant que x + y + z = 1 et que x, y, z 0 De façon similaire pour A2 nous obtenons : "max (u1,u2) E 118+ | 2 1 u1 -- d1 M1(A2) -- d1 = u2 -- d2 M2(A2) -- d2 En remplaçant on obtient : " 3 20x + 20z 20 max (x, y, z) E 118 I = 20y + 14z 20 sachant que x + y + z = 1 et que x, y, z 0 On obtient ainsi : max { (x, y, z) E 1183 | 20x + 6z = 20y} sachant que x + y + z = 1 et que x, y, z 0 Pour A1 nous obtenons encore une fois (15, 15) mais pour A2 nous trouvons ici (15.38, 15.38). Nous constatons bien que l'utilité du Joueur 2 est supérieure pour A2 avec son utilité obtenue via la solution de Nash pour le même ensemble d'alternatives. Cela résout en effet la problématique soulevée par Ehud Kalai et Meir Smorodinsky, le joueur 2 ayant une meilleure utilité dans le cas où il a plus de choix possibles. 41 FIGURE 15 - Solutions de Nash et Kalai avec A1 et A2 Dans ce problème en question la solution de Kalai paraît beaucoup plus logique que la solution de Nash. En effet dans l'ensemble des alternatives A2, l'étudiant 1 peut se permettre d'aider l'étudiant 2 à avoir 14 de moyenne tout en gardant 20 de moyenne. Avec l'ensemble des alternatives A1, il lui est impossible d'atteindre 20 de moyenne tout en aidant l'étudiant 2 à avoir 14. Avec A2, l'étudiant peut "gratuitement" avoir 14 de moyenne, le joueur 1 étant indifférent entre l'aider où non vu qu'il a 20 de toute façon. Cela devrait donc se traduire par un avantage pour le joueur 2 au moment des négociations, ce que la solution de Nash manque de prendre en compte. Après cette partie il est légitime de se demander laquelle de ces 2 solutions est la plus juste. Cela va dépendre de notre préférence pour l'un des axiomes interchangeables. Si nous considérons que l'ajout d'une alternative qui ne sera jamais choisie ne va pas modifier l'accord trouvé entre les 2 joueurs, alors la solution de Nash est pertinente via l'axiome d'indépendance des alternatives non pertinentes. Si au contraire nous acceptons le fait que bien que cette alternative ne soit pas choisie, elle modifie le pouvoir de négociation des joueurs, il sera intéressant de choisir la solution de Kalai avec l'axiome de monotonicité. Dans ce cas là, si l'utilité maximum d'un joueur augmente, et cela pour toute utilité que l'autre joueur puisse demander, alors son utilité augmentera. Nous pouvons faire l'interprétation qu'un juge, dont le rôle est de trouver l'accord entre les deux joueurs, va être impartial entre les deux joueurs mais partial sur le choix des axiomes utilisés et donc sur la solution choisie. Cela pourrait représenter sa propre notion de ce qui est juste. Ces préférences peuvent être apparenté au type de société dans lequel l'échange prend place, celle-ci ayant des caractéristiques sociales et morales spécifiques. 42 6 Conclusion Nous avons vu avec ce mémoire que le principe de marchandage est un cadre créé par J.F Nash pour pouvoir rigoureusement développer une théorie permettant d'encadrer l'échange entre 2 agents. Il a essayé de décrire le comportement de ces agents au travers d'axiomes mathématiques, lesquels ont été soigneusement choisis pour qu'ils puissent permettre, ensemble, l'acquisition de certaines propriétés essentielles concernant l'arrangement trouvé entre les deux individus. Incorporés au modèle développé par J.F Nash, ces axiomes rendent l'existence d'un accord systématique et unique, deux caractéristiques indispensables à l'application concrète du principe de marchandage. Ces axiomes procurent à la solution des propriétés géométriques avantageant sa construction algorithmique et permettant ainsi une étude approfondie de ses applications à des exemples concrets. L'étude du concept de voiture partagée géré par une entreprise était un exemple, original, de l'application concrète qu'il était possible de faire avec la solution obtenue par J.F Nash. Néanmoins, elle n'est pas une solution "miracle" car elle comporte certains défauts à une application dans la réalité. La possible malhonnêteté d'un ou des agents en est un premier. En effet, de la véracité des informations qu'il soumet à l'arbitre (ici l'entreprise) dépend la solution obtenue. On a vu que lorsque l'agent choisit de modifier légèrement des paramètres sur lesquels il a un pouvoir de décision, à savoir sa destination dans notre cas, le résultat pouvait changer radicalement, au point que mentir formait souvent une stratégie dominante. Le deuxième défaut étudié a été le fait que la solution n'appartenait pas forcément à un élément du cadre initial mais pouvait être le mixte entre deux d'entre eux. Le cadre théorique ne se soucie pas de cette éventualité, par contre elle peut rendre difficile une application concrète du principe de marchandage. C'est la raison pour laquelle on a étudié le fait que l'entreprise devait prendre en compte cette éventualité avant de décider si elle devait ou non appliquer le principe de marchandage à sa problématique initiale. Il est nécessaire malgré tout de préciser que le fait de ne pas appliquer cette solution ne signifie pas que dans le cadre imaginé, il en existe une meilleure. On a vu par la suite que la solution de Nash pouvait être confrontée à celle de Kalai, mais parfois (et c'est le cas nous le pensons ici) il vaut mieux changer le cadre plutôt que d'essayer de trouver une meilleure solution (positionnement plus stratégique des voitures par l'entreprise par exemple). Nous avons pu mettre en lumière la différence entre la solution de Nash et la solution de Ka-lai pour un jeu de marchandages à 2 joueurs. Ceci est fort intéressant car nous constatons que contrairement à d'autres champs comme les mathématiques, les sciences économiques tel que celle des jeux de marchandages sont relativement récentes (1950 pour Nash et 1975 pour Kalai). Nous avons constaté que le choix des axiomes dépendait non pas d'une vérité universelle mais de la vision de son créateur et de certaines propriétés à appliquer à leur solution. En effet, au cours de l'étude de leurs travaux, nous avons constaté que ces économistes étaient autant préoccupés par les caractéristiques mathématiques avantageuses de leur solution, comme l'unicité, que par la vraisemblance de cette solution à la réalité. Les axiomes choisis servent à décrire la manière de réfléchir des agents, mais surtout à créer un modèle mathématique qui a du sens. Nous avons vu via l'exemple de la distribution de vaccins dans l'Union Européenne qu'en réalité il y a beaucoup plus de paramètres à prendre en compte et que la solution de Nash ou de Kalai sont difficiles à appliquer. Néanmoins, ces 2 solutions restent pertinentes et peuvent servir de repères pour prendre une décision. Il serait intéressant pour des décideurs de prendre en compte plusieurs solutions différentes comme les solutions de Nash et Kalai pour ensuite prendre une décision concernant un jeu de marchandage. Bien qu'ils soient différents, les axiomes mis en place par les différents économistes ont tous du sens et peuvent mettre en lumière certains comportements. 43 Avis personnels : Lucas : Ayant eu la matière Théorie des Jeux durant ma Licence de Mathématiques puis Théorie des Contrats au premier semestre de cette année, j'étais d'avis à choisir un sujet de mémoire dans ce domaine ayant aimé ces matières. Le sujet Marchandage et partage d'objets a donc été le choix évident pour moi. Ce mémoire nous a appris à nous organiser à plusieurs autour d'un projet. Chercher par soi-même des concepts théoriques sans avoir un cours à l'Université sur lequel on peut se baser n'est pas chose évidente, et avoir appris à lire et comprendre des papiers de chercheurs est, je pense, un outil pertinent à avoir pour la suite de mes études et surtout pour ma future carrière professionnelle. Les concepts étant parfois compliqué à saisir, j'ai compris l'importance des exemples de de la "vulgarisation scientifique" des notions avancées. En effet ce mémoire ne s'adresse pas forcément aux personnes déjà compétentes dans ce domaine d'étude et donc, comme nous au départ, vont avoir besoin de de contexte pour bien saisir toutes les nuances du modèle créé par Nash. C'est cela qui, à mon avis, rend le sujet intéressant. Bastien : Ce mémoire a été enrichissant à bien des égards. Il m'a permis de comprendre la démarche que pouvait entreprendre un scientifique lorsqu'il souhaitait trouver une solution à un problème posé. J'ai donc éprouvé un réel intérêt envers ce procédé axiomatique qui relève parfois d'une logique personnelle pouvant être remise en question sans pour autant être fausse. Ce mémoire a aussi été l'occasion pour moi de beaucoup coder avec certaines problématiques en tête, la première étant le fait d'essayer de rendre un code le plus intelligible possible, tâche ô combien ardue. Une deuxième consistait à découper un gros problème en plusieurs plus petits et plus facilement réalisables. Enfin, une dernière problématique concernait l'application d'algorithmes sur des cas pratiques à des fins théoriques. Face à toutes les idées d'applications qu'on pouvait imaginer, il a fallu à chaque fois penser des façons de procéder et choisir celle qui nous semblait être la meilleure. On a malheureusement dû se séparer de beaucoup d'idées intéressantes mais également très chronophages. 7 Bibliographie Nash, J. (1950). The Bargaining Problem. Consulté sur https :// www.semanticscholar.org/paper/The-Bargaining-Problem-Nash/c38e70179b9c33a19824fd157adb8291cfbef1c2 Nash, J. (1953). Two-Person Cooperative Games. Consulté sur https :// www.jstor.org/stable/1906951 ?seq=1 Kalai, E., & Smorodinsky, M. (1975). Other Solutions to Nash's Bargaining Problem. Consulté sur https :// www.semanticscholar.org/paper/OTHER-SOLUTIONS-TO-NASH%27S-BARGAINING-PROBLEM-Kalai-Smorodinsky/ea620f7be68a48d3bcc9b260fecdfd6e54f14270 ?p2df Ozdaglar, A. (2010). Game Theory with Engineering Applications Lecture 14 : Nash Bargaining Solution. Consulté sur https :// ocw.mit.edu/courses/electrical-engineering-and-computer- science/6-254-game-theory-with-engineering-applications-spring-2010/lecture-notes/MIT6_254S10_lec14.pdf 44 8 Appendice 8.1 Codes et résultats consoles annexe de la partie 4 1. Fonction de dichotomie pour la recherche d'extrema 3 Lien pour retourner sur la page contenant la référence 23 227 def joueur_ment_y_maximum_dichotomie ãÑ (joueur,a,b,x1,x2,y1,y2,v,decimale,tolerance) : 228 u_et_y = [[],[]] 229 if joueur == 1 : # le while suivant trouve le max quand J2 ment, ãÑ on inverse donc si c'est J1 qui ment 230 c = x1 231 x1 = x2 232 x2 = c 233 d = y1 234 y1 = y2 235 y2 = d 236 i = 0 237 while (b-a) > 10**(-tolerance) and (i < 50): 238 p = a + (b-a)/4 239 m = a + (b-a)/2 240 q = a + 3*(b-a)/4 241 242 u_p =
solution_rapide(x1,x2,y1,p,v,decimale)[0][1] - 243 u_q =
solution_rapide(x1,x2,y1,q,v,decimale)[0][1] - 244 u_m =
solution_rapide(x1,x2,y1,m,v,decimale)[0][1] - 245 246 u_et_y[0].append(u_p),
u_et_y[0].append(u_q), 247 u_et_y[1].append(p), u_et_y[1].append(q), u_et_y[1].append(m) 248 249 if u_p > u_m: 250 b = m 251 elif u_m < u_q: 252 a = m 253 else: 254 a = p 255 b = q 256 i+=1 257 y_sol = (a+b)/2 258 u_sol = solution_rapide (x1,x2,y1,y_sol,v,decimale)[0][1] - ãÑ abs(utilite_marche(y_sol, y2, decimale)) 259 260 u_et_y[0].append(u_sol) 261 u_et_y[1].append(y_sol) 262 return [y_sol,u_sol,u_et_y] # u_et_y sert au plot 45 2. Fonction print_jeu_decouvert Lien pour retourner sur la page contenant la référence 24 263 def print_jeu_decouvert (x1,x2,y1,y2,v,decimale): 264 B=[] 265 B.append(str("\nQuand .31 est le premier à jouer, .31 décidera de ãÑ mentir et .32 également")) 266 B.append(str("\nQuand .31 est le premier
à jouer, .31 décidera de 267 B.append(str("\nQuand .31 est le premier
à jouer, .31 décidera de
dire 268 B.append(str("\nQuand .31 est le premier
à jouer, .31 décidera de
dire 269 270 B.append(str("\nQuand .32 est le premier
à jouer, .32 décidera de 271 B.append(str("\nQuand .32 est le premier
à jouer, .32 décidera de 272 B.append(str("\nQuand .32 est le premier
à jouer, .32 décidera de
dire 273 B.append(str("\nQuand .32 est le premier
à jouer, .32 décidera de
dire 274 print(" \n Solution de Nash du jeu à découvert
275 liste_1 = creation_4_couples_utilites ãÑ (1,x1,x2,y1,y2,v,decimale,tolerance) 276 s_1,i_1 = nash_joueur_i_premier_joueur(1, liste_1)[:2] 277 print(B[i_1]) 278 liste_2 = creation_4_couples_utilites ãÑ (1,x1,x2,y1,y2,v,decimale,tolerance) 279 s_2,i_2 = nash_joueur_i_premier_joueur(2, liste_2)[:2] 280 print(B[i_2+4]) 3. Cliquer pour revenir à la page correspondante 281 def nash_info_parfaite (premier_joueur,S): # prend en argument le ãÑ return de creation_4_couples_utilites 282 s_mm,s_vm,s_mv,s_vv = S[0], S[1], S[2], S[3] 283 if premier_joueur == 1 : 284 joueur = 2 285 s_1 = comparaison(joueur,s_mv,s_vv) 286 s_2 = comparaison(joueur,s_mm,s_vm) 287 s = comparaison(premier_joueur, s_1, s_2) 288 else : 289 joueur = 1 290 s_1 = comparaison(joueur,s_mv,s_vv) 291 s_2 = comparaison(joueur,s_mm,s_vm) 292 s = comparaison(premier_joueur, s_1, s_2) 293 return s 4. Cliquer pour revenir à la page correspondante 46 FIGURE 16 - Graphique : recherche par dichotomie quand aucun des joueurs ment FIGURE 17 - Graphique: recherche par dichotomie quand un joueur sait que l'autre ment 47 294 def occurrence_type_solution_jeu_decouvert (taille_echantillon = 100, ãÑ decimale = 2, tolerance = 100, joueur = 1): # joueur ==> premier à
295 occurrence_J1 = [] 296 for i in range (taille_echantillon): 297 x1, x2, y1, y2, v =
random_5_points(decimale) #
random_5_points 298 liste = creation_4_couples_utilites ãÑ (joueur,x1,x2,y1,y2,v,decimale,tolerance) # -> créer les 4 ãÑ couples d'utilité 299 ãÑ occurrence_J1.append(nash_joueur_i_premier_joueur(joueur,liste)[1]) 300 return occurrence_J1 48 8.2 Code réalisé tout au long de ce mémoire Le code a été écrit sur spyder, certaines syntaxe sont donc propres à cet IDE. 8.2.1 Fichier "Nash_solver.py" 301 # Le programme suivant vise a calculer la solution de Nash d'un jeu de ãÑ marchandage a deux joueurs dont l'ensemble d'alternatives est l'enveloppe ãÑ convexe d'un nombre fini de points. 302 303 from numpy import array 304 from matplotlib.pyplot import plot, figure, title, grid, legend, show 305 from matplotlib.patches import Rectangle 306 307 308 # renvoie l'abscisse d'un point de R2 309 def first_component(a): 310 return a[0] 311 312 # renvoie l'ordonnee d'un point de R2 313 def second_component(a): 314 return a[1] 315 316 # prend en entree une liste de points de R2 renvoie 317 # la liste triee par ordre decroissant par rapport a la premiere composante 318 # les points de premiere composante egale sont tries par rapport a la seconde 319 def double_sort(L): 320 S = sorted(L, key = second_component, reverse = True) 321 S.sort(key = first_component, reverse = True) # la méthode "sort" ãÑ conserve 322 # l'ordre lorque la cle est ãÑ la meme 323 return S #O(len(L)) 324 325 # prend en entree une liste triee par la fonction "double_sort" 326 # renvoie une sous-liste strictement décroissante pour la premiere 327 # composante et strictement croissante pour la seconde 328 def first_selection(L): 329 S = [L[0]] # L etant triee par "double_sort", L[0] sera forcement 330 # le premier element de la sous-liste 331 n = len(L) 332 i = 1 333 j = 0 334 while i < n: 335 if L[i][0] < S[j][0] and L[i][1] > S[j][1]: 336 S.append(L[i]) 337 j+=1 338 i+=1 339 return S #O(len(L)) 340 49 341 # prend en entree trois points strictement decroissants/croissants 342 # pour la premiere/seconde composante renvoie "True" ssi le point du milieu 343 # est strictement au-dessus de la droite passant par les deux autres 344 def above(a,b,c): 345 return b[1] > (a[1]*(b[0]-c[0])/(a[0]-c[0]))
+ 346 347 # prend en entree une liste strictement decroissante/croissante pour la ãÑ premiere/ 348 # seconde composante renvoie la sous-liste privee des points Pareto-domines 349 # par une combinaison d'autres points 350 def second_selection(L): 351 if len(L) == 1: return L 352 S = [L[0],L[1]] 353 n = len(L) 354 i = 2 355 j = 0 356 while i < n: 357 if above(S[j],S[j+1],L[i]): 358 S.append(L[i]) 359 j+=1 360 i+=1 361 else: 362 S.pop() 363 if j == 0: 364 S.append(L[i]) 365 i+=1 366 else: 367 j-=1 368 return(S) # O(len(L)) 369 370 # prend en entree une liste de points de R2 371 # renvoie la liste triee des points constituant la frontiere de Pareto de ãÑ l'enveloppe convexe de l'ensemble des points 372 def frontier_points(L): 373 S_0 = double_sort(L) 374 S_1 = first_selection(S_0) 375 S_2 = second_selection(S_1) 376 return S_2 # O(len(L)) 377 378 # prend en entree deux points strictement decroissants/croissants pour la ãÑ premiere 379 # /seconde composante renvoie l'ordonnee du maximiseur de la "fonction produit"
380 # la droite passant par ces deux points 381 382 def y_max(a,b): # a est sous la forme [x1,y1] 383 a_1, a_2, b_1, b_2 = a[0], a[1] ,b[0] ,b[1] 384 p_cut = b_1/(b_1-a_1) 50 385 return (p_cut*a_2 + (1-p_cut)*b_2)/2 386 387 # idem "y_max"; renvoie l'abscisse 388 def x_max(a,b): 389 a_1, a_2 ,b_1 ,b_2 = a[0], a[1] ,b[0] ,b[1] 390 p_cut = b_2/(b_2-a_2) 391 return (p_cut*a_1 + (1-p_cut)*b_1)/2 392 393 # prend en entrée une liste traitee par "frontier_points" 394 # renvoie le point de l'enveloppe convexe de la liste qui maximise la "fonction ãÑ produit" 395 def solution_rec(L): 396 n = len(L) 397 if n == 0: 398 print("Echec de la recurrence") 399 if n == 1: 400 return array([[L[0][0],L[0][1]],[0,0],[0,0],[1,0]]) 401 else: 402 m = n//2 403 a, b = L[m-1], L[m] 404 y = y_max(a,b) 405 if y < a[1]: 406 if n > 2: 407 return solution_rec(L[:m]) 408 else: 409 s = array([a[0],a[1]]) 410 a = array([a[0],a[1]]) 411 b = array([b[0],b[1]]) 412 c = array([1,0]) 413 return array([s,a,b,c]) 414 if y > b[1]: 415 if n > 2: 416 return solution_rec(L[m:]) 417 else: 418 s = array([b[0],b[1]]) 419 a = array([a[0],a[1]]) 421 c = array([0,1]) 422 return array([s,a,b,c]) 423 else: 424 x = x_max(a,b) 425 420 b = array([b[0],b[1]]) p = (x - b[0]) / (a[0]-b[0]) 426 s = array([x,y]) 427 a = array([a[0],a[1]]) 428 b = array([b[0],b[1]]) 429 c = array([p,1-p]) 430 return array([s,a,b,c]) # O(len(L)) 431 432 # prend en entree une liste de points et un vecteur de R2 51 433 # renvoie la liste decalee par le vecteur 434 def shift(L,v): 435 L_shifted = [] 436 for i in range(len(L)): 437 P = array([ L[i][0] + v[0], L[i][1] + v[1] ]) 438 L_shifted.append(P) 439 return L_shifted # O(len(L)) 440 441 # prend en entree une liste de points de R2 442 # renvoie deux listes constituees respectivement de ses abscisses et ordonnees 443 def get_lists(L): 444 X = [] 445 Y = [] 446 for i in range(len(L)): 447 tmp = L[i] 448 X.append(tmp[0]) 449 Y.append(tmp[1]) 450 return [X,Y] # O(len(L)) 451 452 # prend en entree une liste d'alternatives et un point de desaccord 453 # affiche la representation du jeu sur le plan ainsi que sa solution de Nash 454 def plot_solution(A,d): 455 L = shift(A+[d], (-1)*d) 456 F = frontier_points(L) 457 s = solution_rec(F)[0] 458 A_lists = get_lists(A) 459 F_lists = get_lists(shift(F,d)) 460 fig = figure() 461 ax = fig.add_subplot(111) 462 plot(A_lists[0], A_lists[1], '.k') 463 plot(d[0], d[1], '+b', label="point de désaccord") 464 plot(F_lists[0], F_lists[1], '--y', c = "deepskyblue", label="frontière de ãÑ Pareto") 465 plot(s[0]+d[0], s[1]+d[1], '*r', label="solution de Nash") 466 ax.add_patch(Rectangle(d,s[0], s[1], linewidth = 0.5, edgecolor = 'black', ãÑ fill = False,hatch='/')) 467 grid() 468 title("Représentation graphique du jeu") 469 legend() 470 show() 471 472 def to_list (s): 473 n = len(s) 474 if n%2 != 0: 475 print('Raté') 476 return 0 477 m = int(n/2) 478 L = [] 479 for i in range (m): 52 480 x = [s[2*i],s[2*i+1]] 481 L.append(x) 482 return L # O(len(L)) 483 484 def true_solution(A,d): 485 L = shift(A+[d], (-1)*d) 486 F = frontier_points(L) 487 s = solution_rec(F) 488 s_list =[] 489 for i in range (3): 490 s_list.append(shift(to_list(s[i]),d)) 491 492 L=[] 493 for i in range (len(s_list)): 494 p = [s_list[i][0][0], s_list[i][0][1]] 495 L.append(p) 496 L.append([s[3][0],s[3][1]]) 497 return L # O(len(L)) 498 499 500 def print_solution(s): # prend en entrée le résultat de true_solution 501 sol = [round(s[0][0],2),round(s[0][1],2)] 502 a = [round(s[1][0],2),round(s[1][1],2)] 503 b = [round(s[2][0],2),round(s[2][1],2)] 504 p = round(s[3][0],2) 505 q = round(1 - p,2) 506 507 if p == 1: 508 print ("La solution est le point de la liste initiale : ", sol) 509 elif p == 0: 510 print ("La solution est le point de la liste initiale : ", sol) 511 else : 512 print("La solution est une combinaison linéaire du point " + str(a)\ 513 + " chargé du poids " + str(p) + " et du point " + str(b) + \ 514 " chargé du poids " + str(q)) 515 print("La solution est le point ", sol) 516
517 518 519 520 521 522 523 524 525 #%%
526 527 L_list = get_lists (L) 528 53 529 figure() 530 plot(L_list[0],L_list[1],'o', c = 'b') 531 plot(d[0],d[1],'o', c = 'r') 532 533 L_double_sort = double_sort(L) 534 L_double_sort_list = get_lists(L_double_sort) 535 figure() 536 plot(L_double_sort_list[0],L_double_sort_list[1],'o', c = 'b') 537 plot(d[0],d[1],'o', c = 'r') 538 title('Points restants après le triage par "double sort"') 539 540 L_frontier = frontier_points(L_double_sort) 541 L_frontier_list = get_lists(L_frontier) 542 figure() 543 plot(L_frontier_list[0],L_frontier_list[1],'o', c = 'b') 544 plot(d[0],d[1],'o', c = 'r') 545 title('Points restants après le triage par "frontier point"') 546 547 d = array([d[0],d[1]]) 548 S = true_solution(L,d) 549 print_solution(S) 550 plot_solution(L, d) #''' 54 8.2.2 Fichier "Fonctions_distances.py" 551 from numpy import array 552 553 def marche(x): 554 return 5*x 555 556 def dist(x,y): # simple calcul de la distance euclidienne 557 return abs(y-x) 558 559 def cp3 (x,z,y): # calcul de la distance entre deux points en imposant un ãÑ checkpoint 560 return dist(x,z) + dist(z,y) 561 562 def cp4 (x,v,w,y): 563 return cp3(x,v,w)+dist(w,y) 564 565 def cp5 (x,u,v,w,y): 566 return cp4(x,u,v,w)+dist(w,y) 567 568 def dist_v(x,y): # calcul de la distance parcourue en voiture en faisant ãÑ x -> y 569 return dist(x,y) 570 571 def cp3_v (x,z,y): # calcul de la distance parcourue en voiture 572 return cp3(x,z,y) 573 574 def cp4_v (x,v,w,y): 575 return cp4(x,v,w,y) 576 577 def cp5_v (x,u,v,w,y): 578 return cp5(x,u,v,w,y) 579 580 def dist_m(x,y): # calcul de la distance parcourue en
marchant, en 581 return marche(dist_v(x,y)) 582 583 def cp3_m (x,z,y): # calcul de la distance parcourue en marchant en ãÑ faisant x -> z -> y 584 return marche(cp3_v(x,z,y)) 585 586 def cp4_m (x,v,w,y): # calcul de la distance parcourue en marchant en ãÑ faisant x -> v -> w -> y 587 return marche(cp4_v(x,v,w,y)) 588 589 def cp5_m (x,u,v,w,y): 590 return marche(cp5_v(x,u,v,w,y)) 591 592 #%% 55 593 # renvoie un vecteur de dimension 2x9 des distances négatives 594 # quand on est dans le cas à 9 solutions sur un segment [0,1] 595 # le premier vecteur est celui des 9 distances du joueur 1 596 # le second vecteur est celui des 9 distances du joueur 2 597 598 def vect_temps (v,x1,x2,y1,y2): 599 600 d11 = cp4_v (v,x1,x2,y1) 601 d12 = d11 + dist_v (y1,y2) 602 603 d22 = cp4_v (v,x1,x2,y2) 604 d21 = d22 + dist_v (y2,y1) 605 606 d31 = cp4_v (v,x2,x1,y1) 607 d32 = d31 + dist_v (y1,y2) 608 609 d41 = cp4_v (v,x2,x1,y2) 610 d42 = d41 + dist_v (y2,y1) 611 612 d52 = cp3_v (v,x2,y2) 613 d51 = d52 + cp3_v(y2,x1,y1) 614 615 d61 = cp3_v (v,x1,y1) 616 d62 = d61 + cp3_v(y1,x2,y2) 617 618 d71 = dist_m (x1,y1) # le joueur 1 y va à pied 619 d72 = cp3_v (v,x2,y2) 620 621 d81 = cp3_v (v,x1,y1) # le joueur 2 y va à pied 622 d82 = dist_m (x2,y2) 623 624 d91 = dist_m(x1, y1) # les deux joueurs y vont à pied 625 d92 = dist_m(x2, y2) 626 627 D = ãÑ array([[d11,d21,d31,d41,d51,d61,d71,d81,d91],[d12,d22,d32,d42,d52,d62,d72,d82,d92]]) 628 629 return D 56 8.2.3 Fichier "Etude_probleme_voiture_partagee" 630 from numpy import array 631 from matplotlib import pyplot as plt 632 from random import randint 633 from sympy import symbols, solve 634 635 import Nash_solver as ns 636 import Fonctions_distances as fd 637 #%% 638 639 ''' Jeu classique ''' 640 v = 0.21 641 x1 = 0.2 642 x2 = 0.1 643 y1 = 0.98 644 y2 = 0.66 645 decimale = 2 646 a = 0 647 b = 1 648 tolerance = 100 649 650 n = 4 651 m = 1000 652 joueur = 1 653 i = 0 654 655 #%% 656 ''' Fonctions "utilitaires" ''' 657 658 # fonctions pour transformer un array de coordonnées de points en liste 659 # on entre neuf points (correspondands aux alternatives) sous forme d'array de ãÑ dimension 2 660 # dimension 1 : abcisses des 9 alternatives 661 # dimension 2 : ordonnées des 9 alternatives 662 def array_to_list_simple (D): 663 C = [] 664 for i in range (9): # on remplit la liste 665 C.append([D[0][i],D[1][i]]) 666 return C 667 668 # même fonction ou on entre plusieurs combinaisons de 9 points 669 # exemple : si on veut entrer 1000 combinaisons différentes on aura un array 670 # de dimension 2000 671 def array_to_list (D): 672 lengthD = int(len(D)/2) # on prend la
partie entière divisée par deux,
les 673 C = [] 674 for i in range(lengthD): # création de la liste sour le format qui 675 57 C.append([]) # nous intéresse pour le calcul de la solution ãÑ de Nash 676 for j in range (9): 677 C[i].append([]) 678 for i in range (lengthD): # on remplit la liste 679 for j in range (9): C[i][j] = [D[2*i][j],D[2*i+1][j]] 680 681 return C 682 683 684 def round_list_coordonnees_nx2 (D,decimale = 2): # D = ãÑ ((2.1223,3.3314],(2.44141,4.43134],...] 685 for i in range (len(D)): 686 D[i][0] = round(D[i][0],decimale) 687 D[i][1] = round(D[i][1],decimale) 688 return D # D = ãÑ ((2.12,3.33],(2.44,4.43],...] 689 690 def get_coordonnees (L): # L = ((x1,x2,x3,...],(y1,y2,y3,...]] 691 M = [] 692 for i in range (len(L[0])): M.append([L[0][i],L[1][i]]) 693 694 return M # M = ((x1,y1],(x2,y2],(x3,y3],...] 695 696 #%% 697 ''' Fonctions servant à
l'affichage de la solution de Nash ãÑ 698 699 def print_donnees (x1,x2,y1,y2,v = 0.5): 700 print("v = ",v) 701 print("x1 = ",x1) 702 print("x2 = ",x2) 703 print("y1 = ",y1) 704 print("y2 = ",y2) 705 706 def utilite (x): 707 return 5-x*x 708 709 def utilite_list_couple (L): 710 D = [] 711 for i in range (len(L)): 712 A1 = utilite(L[i][0]) 713 A2 = utilite(L[i][1]) 714 A = [A1,A2] 715 D.append(A) 716 return D # O(len(L)) 717 718 def coordonnees_utilites (x1,x2,y1,y2,v = 0.5,decimale = 2): 719 D = fd.vect_temps(v,x1,x2,y1,y2) # sans mensonges 58 720 D1 = array_to_list_simple(D) # rappel : liste de coordonnées de 9 points 721 D2 = utilite_list_couple(D1) # application de la fonction d'utilité 722 D_f = round_list_coordonnees_nx2(D2,decimale) # on essaye de garder n ãÑ décimales 723 return D_f # D_f = [[u_x_1,u_y_1],[u_x_2,u_y_2],[u_x_3,u_y_3],...] 724 725 def desaccord (D): # prend en argument la solution de coordonnees_utilites 726 return array([D[8][0],D[8][1]]) # point de désaccord 727 728 def solution (D, d): 729 return ns.true_solution(D,d) 730 # array([[x_sol,y_sol],[x_a,y_a],[x_b,y_b], [p,1-p]]) 731 # x_sol = utilité joueur 1, y_sol = utilité joueur 2 732 733 def solution_rounded (s, decimale = 2): # prend en argument la solution de la ãÑ fonction "solution" 734 for i in range (4): # s = array(solution = [3.2313,3.234], a ãÑ =[2.2313,4.1414], b =[.,.], p=[.,.]) 735 s[i][0] = round(s[i][0],decimale) 736 s[i][1] = round(s[i][1],decimale) 737 return s # s = array(solution = [3.23,3.23], a
=[2.23,4.14], b =[.,.], 738 739 ''' Fonction "résumé" du cas d'étude de la voiture partagée ''' ãÑ 740 741 def solution_rapide (x1,x2,y1,y2,v = 0.5,decimale = 2): 742 D = coordonnees_utilites (x1,x2,y1,y2,v,decimale) 743 d = desaccord (D) 744 s = solution (D, d) 745 s = solution_rounded (s) # s = array(solution = [3.23,3.23], a ãÑ =[2.23,4.14], b =[.,.], p=[.,.]) 746 return s 747 748 def print_solution_voiture(s,D): # prend en entrée le résultat de true_solution ãÑ et la liste des 9 coordonnées d'utilité 749 sol = [s[0][0],s[0][1]] 750 a = [s[1][0],s[1][1]] 751 b = [s[2][0],s[2][1]] 752 p = round(s[3][0],2) 753 q = round(1 - p,2) 754 B=[] 755 B.append(str("La voiture ira chercher J1 puis J2, déposera J1 puis J2")) 756 B.append(str("La voiture ira chercher J1 puis J2, déposera J2 puis J1")) 757 B.append(str("La voiture ira chercher J2 puis J1, déposera J1 puis J2")) 758 B.append(str("La voiture ira chercher J2 puis J1, déposera J2 puis J1") ) 759 B.append(str("La voiture ira chercher J2, le déposera, puis ira chercher J1 ãÑ et le déposera")) 760 B.append(str("La voiture ira chercher .31, le déposera, puis ira chercher .32 59 ãÑ et le déposera")) 761 B.append(str("La voiture ira chercher .32 et le déposera, .31 se rendra à ãÑ pied")) 762 B.append(str("La voiture ira chercher .31 et le déposera, .32 se rendra à ãÑ pied")) 763 B.append(str("La voiture n'ira chercher personne, les deux joueurs se ãÑ rendront à pied à leur destination")) 764 765 if sol in D: 766 i = 0 767 while sol != D[i]: 768 i+= 1 769 if i>=9 : 770 print("Soucis 1") 771 break 772 print(B[i]) 773 else : 774 i = 0 775 j = 0 776 while a != D[i]: 777 i+= 1 778 if i>=9 : 779 print("Soucis 2") 780 break 781 while b != D[j]: 782 j+= 1 783 if j>=9 : 784 print("Soucis 3") 785 break 786 print(str(p) + " fois du temps, on aura l'action : " + B[i] + "\n \n" + 787 str(q) + " fois du temps, on aura l'action : " + B[j]) 788 789 790 def print_solution_jeu_classique (x1,x2,y1,y2,v = 0.5,decimale = 2): 791 792 print_donnees (x1,x2,y1,y2,v) 793 print("\n Solution du jeu
classique 794 795 print("La voiture est placée en " + str(v) + " sur [0,1] \n") 796 797 print("Le joueur 1 est placée en " + str(x1) + \ 798 " sur [0,1] et souhaite se rendre en " + str(y1) + " \n") 799 print("Le joueur 2 est placée en " + str(x2) + \ 800 " sur [0,1] et souhaite se rendre en " + str(y2) + " \n") 801 802 D = coordonnees_utilites (x1,x2,y1,y2,v,decimale) 803 d = desaccord(D) 60 804 s = solution(D,d) 805 s = solution_rounded(s) 806 u1 = s[0][0] 807 u2 = s[0][1] 808 809 print("Le point de désaccord
correspondant au fait que les deux joueurs
se 810 d) 811 print("Avec une réalisation classique
du jeu, l'action suivante sera 812 print_solution_voiture(s,D) 813 print("\nJ1 en retire une utilité de ", u1) 814 print("\nJ2 en retire une utilité de ", u2) 815 ns.plot_solution(D,d) 816 817 818 ''' Jeu mensonge ''' 819 820 def desutilite_marche (x,y,decimale = 2): 821 return round(-(fd.dist_m(x,y))**(2),decimale) 822 823 def y_max_joueur_quand_il_ment (joueur,a,b,x1,x2,y1,y2,v = 0.5,decimale = ãÑ 2,tolerance = 100) : 824 u_et_y = [[],[]] 825 if joueur == 1 : # le while suivant trouve le max quand J2 ment, on ãÑ inverse donc si c'est J1 qui ment 826 c = x1 827 x1 = x2 828 x2 = c 829 d = y1 830 y1 = y2 831 y2 = d 832 i = 0 833 while (b-a) > 10**(-tolerance) and (i < 50): 834 p = a + (b-a)/4 835 m = a + (b-a)/2 836 q = a + 3*(b-a)/4 837 838 u_p =
solution_rapide(x1,x2,y1,p,v,decimale)[0][1] + 839 u_q =
solution_rapide(x1,x2,y1,q,v,decimale)[0][1] + 840 u_m =
solution_rapide(x1,x2,y1,m,v,decimale)[0][1] + 841 842 u_et_y[0].append(u_p), u_et_y[0].append(u_q), u_et_y[0].append(u_m) 843 u_et_y[1].append(p), u_et_y[1].append(q), u_et_y[1].append(m) 844 845 if u_p > u_m: 61 846 b = m 847 elif u_m < u_q: 848 a = m 849 else: 850 a = p 851 b = q 852 i+=1 853 y_sol = (a+b)/2 854 u_sol = solution_rapide (x1,x2,y1,y_sol,v,decimale)[0][1] + ãÑ desutilite_marche(y_sol, y2, decimale) 855 856 u_et_y[0].append(u_sol) 857 u_et_y[1].append(y_sol) 858 return [y_sol,u_sol,u_et_y] # u_et_y sert au plot 859 860 861 def plot_recherche_max_joueur1et2 (x1,x2,y1,y2,v = 0.5,decimale = 2,tolerance = ãÑ 100,titre = "Utilité des joueurs en fonction de leur point ãÑ d'arrivée",a=0,b=1): 862 s1 = y_max_joueur_quand_il_ment (1,a,b,x1,x2,y1,y2,v,decimale,tolerance) 863 s2 = y_max_joueur_quand_il_ment (2,a,b,x1,x2,y1,y2,v,decimale,tolerance) 864 865 u_verite = solution_rapide (x1,x2,y1,y2,v,decimale)[0] 866 867 plt.figure(0) 868 plt.plot(s1[2][1],s1[2][0], '.k',color = "deeppink", label = "Utilité J1") 869 plt.plot(s2[2][1],s2[2][0], '.k',color = "deepskyblue", label = "Utilité ãÑ J2") 870 plt.scatter(s1[0], s1[1], c = 'red', label = 'Max de J1 : ' + ãÑ str(round(s1[1],decimale))) 871 plt.scatter(s2[0], s2[1], c = 'blue', label
= 'Max de J2 : ' + 872 plt.plot([a, b], [u_verite[0], u_verite[0]], '--', label = 'Utilité J1 sans ãÑ mentir', c = 'deeppink', lw=1) 873 plt.plot([a, b], [u_verite[1], u_verite[1]], '--', label = 'Utilité J2 sans ãÑ mentir', c = 'deepskyblue', lw=1) 874 plt.xlabel ('Starting point') 875 plt.ylabel ('Utility') 876 plt.title (titre) 877 plt.legend(loc = 'best', shadow=True, borderpad=1) 878 plt.grid() 879 plt.show() 880 881 # similaire a la fonction précédente mais concerne seulement 1 joueur 882 def plot_recherche_max_joueur1 (x1,x2,y1,y2,v = 0.5,decimale = 2,tolerance = ãÑ 100,titre = "Utilité du joueur en fonction de son point ãÑ d'arrivée",a=0,b=1): 883 s1 = y_max_joueur_quand_il_ment (1,a,b,x1,x2,y1,y2,v,decimale,tolerance) 884 62 885 u_verite = solution_rapide (x1,x2,y1,y2,v,decimale)[0] 886 887 plt.figure(1) 888 plt.plot(s1[2][1],s1[2][0], '.k',color = "deeppink", label = "Utilité J1") 889 plt.scatter(s1[0], s1[1], c = 'red', label = 'Max de J1 : ' + ãÑ str(round(s1[1],decimale))) 890 plt.plot([a, b], [u_verite[0], u_verite[0]],
'--', label = 'Utilité J1 sans 891 plt.xlabel ('Starting point') 892 plt.ylabel ('Utility') 893 plt.title (titre) 894 plt.legend(loc = 'best', shadow=True, borderpad=1) 895 896 897 def plot_recherche_max_joueur2 (x1,x2,y1,y2,v = 0.5,decimale = 2,tolerance = ãÑ 100,titre = "Utilité du joueur en fonction de son point ãÑ d'arrivée",a=0,b=1): 898 s2 = y_max_joueur_quand_il_ment (2,a,b,x1,x2,y1,y2,v,decimale,tolerance) 899 900 u_verite = solution_rapide (x1,x2,y1,y2,v,decimale)[0] 901 902 plt.figure(1) 903 plt.plot(s2[2][1],s2[2][0], '.k',color = "deepskyblue", label = "Utilité ãÑ J") 904 plt.scatter(s2[0], s2[1], c = 'blue', label = 'Max de J2 : ' + ãÑ str(round(s2[1],decimale))) 905 plt.plot([a, b], [u_verite[1], u_verite[1]], '--', label = 'Utilité J2 sans ãÑ mentir', c = 'deepskyblue', lw=1) 906 plt.xlabel ('Starting point') 907 plt.ylabel ('Utility') 908 plt.title (titre) 909 plt.legend(loc = 'best', shadow=True, borderpad=1) 910 plt.grid() 911 912 def J1_et_J2_verite (x1,x2,y1,y2,v = 0.5,decimale = 2): 913 u_verite = solution_rapide (x1,x2,y1,y2,v,decimale) 914 return u_verite # array([[x_sol,y_sol],[x_a,y_a],[x_b,y_b], [p,1-p]]) 915 916 def J1_ment (x1,x2,y1,y2,v = 0.5,decimale = 2,tolerance = 100): 917 s_J1_ment =
y_max_joueur_quand_il_ment 918 y_J1_ment = s_J1_ment[0] 919 s_J1_ment_bis = solution_rapide (x1,x2,s_J1_ment[0],y2,v,decimale) 920 u1_J1_menteur = s_J1_ment[1] # utilité de J1 quand il ment 921 u2_J1_ment = s_J1_ment_bis[0][1] # utilité de J2 quand J1 ment et que J2 ne ãÑ ment pas 922 return [u1_J1_menteur, u2_J1_ment, y_J1_ment] 923 924 def J2_ment (x1,x2,y1,y2,v,decimale,tolerance): 63 925 s_J2_ment = y_max_joueur_quand_il_ment ãÑ (2,a,b,x1,x2,y1,y2,v,decimale,tolerance) 926 y_J2_ment = s_J2_ment[0] 927 s_J2_ment_bis = solution_rapide (x1,x2,y1,s_J2_ment[0],v,decimale) 928 u1_J2_ment = s_J2_ment_bis[0][0] # utilité de J1 quand J2 ment et que J1 ne ãÑ ment pas 929 u2_J2_menteur = s_J2_ment[1] # utilité de J2 quand il ment 930 return [u1_J2_ment, u2_J2_menteur, y_J2_ment] 931 932 def J1_et_J2_mentent_ingenument (J1_ment_obj,J2_ment_obj): 933 y_J1_ment = J1_ment_obj [2] 934 y_J2_ment = J2_ment_obj [2] 935 solution = solution_rapide(x1, x2, y_J1_ment, y_J2_ment, v, decimale) 936 u1 = solution[0][0] 937 u2 = solution[0][1] 938 return [u1,u2,y_J1_ment,y_J2_ment] 939 940 def J1_et_J2_mentent_decouvert (x1,x2,y1,y2,v = 0.5,decimale = 2,tolerance = ãÑ 100,a=0,b=1): 941 s_J1_ment = y_max_joueur_quand_il_ment ãÑ (1,a,b,x1,x2,y1,y2,v,decimale,tolerance) 942 s_J2_ment =
y_max_joueur_quand_il_ment 943 y_J1_ment = s_J1_ment[0] # choix du point d'arrivée de J1 quand il ment 944 y_J2_ment = s_J2_ment[0] # choix du point d'arrivée de J2 quand il ment 945 946 s_J2_ment_sachant_J1_ment =
y_max_joueur_quand_il_ment 947 y2_J2_ment_sachant_J1_ment = s_J2_ment_sachant_J1_ment[0] 948 s_J2_ment_sachant_J1_ment_bis = solution_rapide ãÑ (x1,x2,y_J1_ment,y2_J2_ment_sachant_J1_ment,v,decimale) 949 u1_J2_ment_sachant_J1_ment = s_J2_ment_sachant_J1_ment_bis[0][0] 950 u2_J2_ment_sachant_J1_ment = s_J2_ment_sachant_J1_ment[1] 951 952 s_J1_ment_sachant_J2_ment =
y_max_joueur_quand_il_ment 953 y1_J1_ment_sachant_J2_ment = s_J1_ment_sachant_J2_ment[0] 954 s_J1_ment_sachant_J2_ment_bis = solution_rapide ãÑ (x1,x2,y1_J1_ment_sachant_J2_ment,y_J2_ment,v,decimale) 955 u1_J1_ment_sachant_J2_ment = s_J1_ment_sachant_J2_ment[1] 956 u2_J1_ment_sachant_J2_ment = s_J1_ment_sachant_J2_ment_bis[0][1] 957 958 ãÑ #plot_recherche_max_joueur1(x1,x2,y1,y_J2_ment,v,decimale,tolerance,"Utilité ãÑ du joueur en fonction de son point d'arrivée sachant que l'autre ment") 959 #plot_recherche_max_joueur2(x1,x2,y_J1_ment,y2,v,decimale,tolerance) 960 64 961 return ãÑ [[u1_J2_ment_sachant_J1_ment,u2_J2_ment_sachant_J1_ment],[u1_J1_ment_sachant_J2_ment,u2_ ãÑ [y_J1_ment,y2_J2_ment_sachant_J1_ment],[y1_J1_ment_sachant_J2_ment,y_J2_ment]] 962 963 def print_utilites_jeu_info_parfaite (x1,x2,y1,y2,v = 0.5,decimale = 2): 964 J1_et_J2_verite_var = J1_et_J2_verite (x1,x2,y1,y2,v,decimale) 965 J1_ment_var = J1_ment (x1,x2,y1,y2,v,decimale,tolerance) 966 J2_ment_var = J2_ment (x1,x2,y1,y2,v,decimale,tolerance) 967 J1_et_J2_mentent_ingenument_var = J1_et_J2_mentent_ingenument(J1_ment_var, ãÑ J2_ment_var) 968 J1_et_J2_mentent_decouvert_var =
J1_et_J2_mentent_decouvert 969 970 u1 = J1_et_J2_verite_var [0][0] 971 u2 = J1_et_J2_verite_var [0][1] 972 u1_J1_ment = J1_ment_var [0] 973 u2_J1_ment = J1_ment_var [1] 974 u1_J2_ment = J2_ment_var [0] 975 u2_J2_ment = J2_ment_var [1] 976 u1_J1_ment_J2_ment = J1_et_J2_mentent_ingenument_var [0] 977 u2_J1_ment_J2_ment = J1_et_J2_mentent_ingenument_var [1] 978 u1_J1_ment_sachant_J2_ment = J1_et_J2_mentent_decouvert_var [1][0] 979 u2_J1_ment_sachant_J2_ment = J1_et_J2_mentent_decouvert_var [1][1] 980 u1_J2_ment_sachant_J1_ment = J1_et_J2_mentent_decouvert_var [0][0] 981 u2_J2_ment_sachant_J1_ment = J1_et_J2_mentent_decouvert_var [0][1] 982 983 y1_J1_ment = round(J1_ment_var [2],decimale) 984 y2_J2_ment = round(J2_ment_var [2],decimale) 985 y1_J1_ment_J2_ment = round(J1_et_J2_mentent_ingenument_var [2],decimale) 986 y2_J1_ment_J2_ment = round(J1_et_J2_mentent_ingenument_var [3],decimale) 987 y1_J1_ment_sachant_J2_ment = round(J1_et_J2_mentent_decouvert_var ãÑ [2][0],decimale) 988 y2_J1_ment_sachant_J2_ment =
round(J1_et_J2_mentent_decouvert_var 989 y1_J2_ment_sachant_J1_ment =
round(J1_et_J2_mentent_decouvert_var 990 y2_J2_ment_sachant_J1_ment =
round(J1_et_J2_mentent_decouvert_var 991 992 993 print("\n Valeurs du jeu à information parfaite ãÑ \n") 994 995 print("\nQuand les deux joueurs disent la vérité : ") 996 print("Utilité de J1 : ", u1) 997 print("Utilité de J2 : ", u2) 998 999 print("\nQuand J1 ment et que J2 dit la vérité : ") 1000 print("Utilité de J1 : ", u1_J1_ment) 65 1001 print("Utilité de J2 : ", u2_J1_ment) 1002 print("J1 annonce vouloir aller en " + str(y1_J1_ment) + " au lieu de " + ãÑ str(y1)) 1003 print("La différence d'utilité de J1
équivaut à : " , round(u1_J1_ment
- 1004 print("La différence d'utilité de J2
équivaut à : " , round(u2_J1_ment
- 1005 1006 print("\nQuand J2 ment et que J1 dit la vérité : ") 1007 print("Utilité de J1 : ", u1_J2_ment) 1008 print("Utilité de J2 : ", u2_J2_ment) 1009 print("J2 annonce vouloir aller en " + str(y2_J2_ment) + " au lieu de " + ãÑ str(y2)) 1010 print("La différence d'utilité de J1 équivaut à : " , round(u1_J2_ment - ãÑ u1, decimale)) 1011 print("La différence d'utilité de J2 équivaut à : " , round(u2_J2_ment - ãÑ u2, decimale)) 1012 1013 print("\nQuand les deux joueurs mentent de manière
ingénue (ils se 1014 print("Utilité de J1 : ", u1_J1_ment_J2_ment) 1015 print("Utilité de J2 : ", u2_J1_ment_J2_ment) 1016 print("J1 annonce vouloir aller en " + str(y1_J1_ment_J2_ment) + " au lieu ãÑ de " + str(y1)) 1017 print("J2 annonce vouloir aller en " + str(y2_J1_ment_J2_ment) + " au lieu ãÑ de " + str(y2)) 1018 print("La différence d'utilité de J1 équivaut à : " , ãÑ round(u1_J1_ment_J2_ment - u1, decimale)) 1019 print("La différence d'utilité de J2 équivaut à : " , ãÑ round(u2_J1_ment_J2_ment - u2, decimale)) 1020 1021 1022 print("\nQuand le joueur 2 a décidé de mentir
alors qu'il savait que le 1023 print("Utilité de J1 : ", u1_J2_ment_sachant_J1_ment) 1024 print("Utilité de J2 : ", u2_J2_ment_sachant_J1_ment) 1025 print("J1 annonce vouloir aller en " + str(y1_J2_ment_sachant_J1_ment) + " ãÑ au lieu de " + str(y1)) 1026 print("J2 annonce vouloir aller en " + str(y2_J2_ment_sachant_J1_ment) + " ãÑ au lieu de " + str(y2)) 1027 print("La différence d'utilité de J1 équivaut à : " , ãÑ round(u1_J2_ment_sachant_J1_ment - u1, decimale)) 1028 print("La différence d'utilité de J2 équivaut à : " , ãÑ round(u2_J2_ment_sachant_J1_ment - u2, decimale)) 1029 1030 1031 print("\nQuand le joueur 1 a décidé de mentir
alors qu'il savait que le 66 1032 print("Utilité de J1 : ", u1_J1_ment_sachant_J2_ment) 1033 print("Utilité de J2 : ", u2_J1_ment_sachant_J2_ment) 1034 print("J1 annonce vouloir aller en " + str(y1_J1_ment_sachant_J2_ment) + " ãÑ au lieu de " + str(y1)) 1035 print("J2 annonce vouloir aller en " + str(y2_J1_ment_sachant_J2_ment) + " ãÑ au lieu de " + str(y2)) 1036 print("La différence d'utilité de J1 équivaut à : " , ãÑ round(u1_J1_ment_sachant_J2_ment - u1, decimale)) 1037 print("La différence d'utilité de J2 équivaut à : " , ãÑ round(u2_J1_ment_sachant_J2_ment - u2, decimale)) 1038 1039 1040 ''' Fonctions permettant de trouver la solution de Nash au ãÑ jeu à info parfaite ''' 1041 1042 def comparaison (joueur,s1,s2): 1043 if s1[joueur-1] <= s2[joueur-1] : 1044 return s2 1045 elif s1[joueur-1] > s2[joueur-1] : # pourquoi le -1 : indice de J1 = 0, ãÑ indice de J2 = 1 1046 return s1 1047 # on compare deux couples d'utilité pour le joueur 1 ou 2 1048 # on prend en argument 1 ou 2 correspondant au joueur 1049 # ainsi que les deux couples (u11, u12) et (u21, u22) d'utilité qu'on souhaite ãÑ comparer 1050 1051 def nash_info_parfaite
(premier_joueur,S): # prend en argument le return
de 1052 s_mm,s_vm,s_mv,s_vv = S[0], S[1], S[2], S[3] 1053 if premier_joueur == 1 : 1054 joueur = 2 1055 s_1 = comparaison(joueur,s_mv,s_vv) 1056 s_2 = comparaison(joueur,s_mm,s_vm) 1057 s = comparaison(premier_joueur, s_1, s_2) 1058 else : 1059 joueur = 1 1060 s_1 = comparaison(joueur,s_mv,s_vv) 1061 s_2 = comparaison(joueur,s_mm,s_vm) 1062 s = comparaison(premier_joueur, s_1, s_2) 1063 return s 1064 # Pour trouver toutes les solutions de Nash il faut faire tourner la fonction ãÑ quand J1 joue en premier 1065 # et quand J2 joue en premier, si on trouve la meme elle est unique, sinon il y ãÑ a en a deux. 1066 1067 def indice (s,L): 1068 i = 0 1069 while (s != L[i]): 1070 if i >= len(L): 67 1071 break 1072 i+=1 1073 return i 1074 1075 # Fonction très utile permettant de calculer directement les 4 couples ãÑ d'utilité du problème 1076 # en fonction des paramètres de base 1077 def creation_4_couples_utilites (joueur,x1,x2,y1,y2,v = 0.5,decimale = ãÑ 2,tolerance = 100) : 1078 if joueur == 1: 1079 s_mm = J1_et_J2_mentent_decouvert(x1,x2,y1,y2,v,decimale,tolerance)[0] 1080 s_vm = J1_ment(x1,x2,y1,y2,v,decimale,tolerance)[:2] 1081 s_mv = J2_ment(x1,x2,y1,y2,v,decimale,tolerance)[:2] 1082 s_vv = J1_et_J2_verite(x1,x2,y1,y2,v,decimale)[0] 1083 list_sol = [s_mm,s_vm,s_mv,s_vv] 1084 else : 1085 s_mm = J1_et_J2_mentent_decouvert(x1,x2,y1,y2,v,decimale,tolerance)[1] 1086 s_vm = J2_ment(x1,x2,y1,y2,v,decimale,tolerance) 1087 s_mv = J1_ment(x1,x2,y1,y2,v,decimale,tolerance) 1088 s_vv = J1_et_J2_verite(x1,x2,y1,y2,v,decimale)[0] 1089 list_sol = [s_mm,s_vm,s_mv,s_vv] 1090 return list_sol 1091 1092 ''' Jeu info parfaite, solution de Nash en fonction du ãÑ joueur qui joue en premier ''' 1093 1094 def nash_joueur_i_premier_joueur (joueur,liste): 1095 sol = nash_info_parfaite(joueur,liste) 1096 i = indice(sol,liste) # on prend un indice pour la fonction print ãÑ suivante 1097 return [sol,i] 1098 # sol = couple d'utilité solution 1099 # i = indice de la réponse (0 3) : 1100 # 0 : mensonge puis mensonge 1101 # 1 : verité puis mensonge 1102 # 2 : mensonge puis verite 1103 # 3 : verite puis verite 1104 1105 # Un utilise le principe d'indifference quand une solution mixte existe 1106 # la fonction n'a pas été utilisée durant le mémoire malheureusement 1107 def solution_mixte_nash (S): 1108 s1 = nash_info_parfaite(1, S) 1109 s2 = nash_info_parfaite(2, S) 1110 if s1 == s2: 1111 return s1 1112 elif s1!=s2 and (abs(indice(s1,S) - indice(s2,S))%2 != 0): 1113 x = symbols('x') 1114 eq1 = x*S[0][1] + (1-x)*S[1][1] - (x*S[2][1] + (1-x)*S[3][1]) 1115 p = solve(eq1) 68 1116 1117 y = symbols('y') 1118 eq2 = y*S[0][0] + (1-y)*S[2][0] - (y*S[1][0] + (1-y)*S[3][0]) 1119 q = solve(eq2) 1120 return p,q 1121 ''' 1122 S = [[3,2],[2,3],[2,3],[3,2]] 1123 #S = [[5,3],[2,2],[1,1],[4,6]] 1124 print(solution_mixte_nash(S)) #''' 1125 1126 # fonction "print" affichant la solution de Nash lorsqu'on a le choix entre 4 ãÑ couples d'utilité 1127 def print_jeu_decouvert (x1,x2,y1,y2,v = 0.5,decimale = 2): 1128 B=[] 1129 B.append(str("\nQuand J1 est le premier à jouer, J1 décidera de mentir et ãÑ J2 également")) 1130 B.append(str("\nQuand J1 est le premier à jouer, J1 décidera de mentir mais ãÑ J2 préfèrera dire la vérité")) 1131 B.append(str("\nQuand J1 est le premier à jouer, J1 décidera de dire la ãÑ vérité mais J2 préfèrera mentir")) 1132 B.append(str("\nQuand J1 est le premier
à jouer, J1 décidera de dire
la 1133 1134 B.append(str("\nQuand J2 est le premier
à jouer, J2 décidera de mentir
et 1135 B.append(str("\nQuand J2 est le premier
à jouer, J2 décidera de mentir
mais 1136 B.append(str("\nQuand J2 est le premier
à jouer, J2 décidera de dire
la 1137 B.append(str("\nQuand J2 est le premier
à jouer, J2 décidera de dire
la 1138 1139 print(" \n Solution de Nash du jeu à découvert ãÑ ") 1140 liste_1 = creation_4_couples_utilites (1,x1,x2,y1,y2,v,decimale,tolerance) 1141 s_1,i_1 = nash_joueur_i_premier_joueur(1, liste_1)[:2] 1142 print(B[i_1]) 1143 liste_2 = creation_4_couples_utilites (1,x1,x2,y1,y2,v,decimale,tolerance) 1144 s_2,i_2 = nash_joueur_i_premier_joueur(2, liste_2)[:2] 1145 print(B[i_2+4]) 1146 1147 # fonction pour définir 5 points aléatoires, on veut éviter d'avoir x1 = y1 et ãÑ x2 = y2, car 1148 # ils n'ont pas d'interêt dans le problème et le font planter. 1149 def random_5_points(decimale = 2): 1150 x1 = randint(0,10**decimale)/10**decimale 1151 x2 = randint(0,10**decimale)/10**decimale 1152 y1 = x1 1153 y2 = x2 69 1154 v = x1 1155 while (y1 == x1) or (y2 == x2) or (v == x1): 1156 y1 = randint(0,10**decimale)/10**decimale 1157 y2 = randint(0,10**decimale)/10**decimale 1158 v = randint(0,10**decimale)/10**decimale #''' 1159 return x1, x2, y1, y2, v 1160 1161 # fonction servant la partie théorie des jeux
pour compter le nombre de fois 1162 def occurrence_type_solution_jeu_decouvert (taille_echantillon = 100, decimale ãÑ = 2, tolerance = 100, joueur = 1): 1163 occurrence_J1 = [] 1164 for i in range (taille_echantillon): 1165 x1, x2, y1, y2, v = random_5_points(decimale) 1166 liste = creation_4_couples_utilites ãÑ (joueur,x1,x2,y1,y2,v,decimale,tolerance) 1167 occurrence_J1.append(nash_joueur_i_premier_joueur(joueur,liste)[1]) 1168 return occurrence_J1 1169 1170 # fonction servant la partie statistique du
mémoire, on ne s'intéressera
que 1171 # qui n'est autre qu'une liste de 0 et 1 suivant le fait que la solution est ãÑ pure ou mixte 1172 def echantillon_test_stat_solution_pure (m): # taille de l'échantillon 1173 liste, s_list, s_pure, s_mixte, x1_pure, x2_pure, y1_pure, y2_pure, v_pure, ãÑ \ 1174 x1_mixte, x2_mixte, y1_mixte, y2_mixte, v_mixte = ãÑ [],[],[],[],[],[],[],\ 1175 [],[],[],[],[],[],[] 1176 for i in range (m): 1177 x1, x2, y1, y2, v = random_5_points(decimale) 1178 s = solution_rapide(x1,x2,y1,y2,v,decimale) 1179 s_list.append(s) 1180 if (s[3][0] == 0.0) or (s[3][0] == 1.0) : 1181 liste.append(1), s_pure.append(s), x1_pure.append(x1), \ 1182 x2_pure.append(x2), y1_pure.append(y1), y2_pure.append(y2), ãÑ v_pure.append(v) 1183 else: 1184 liste.append(0), s_mixte.append(s), x1_mixte.append(x1), \ 1185 x2_mixte.append(x2), y1_mixte.append(y1), y2_mixte.append(y2), ãÑ v_mixte.append(v) 1186 return liste,s_list, s_pure, x1_pure, x2_pure, y1_pure, y2_pure, v_pure, \ 1187 s_mixte, x1_mixte, x2_mixte, y1_mixte, y2_mixte, v_mixte 1188 # 0 : liste de 0 et de 1 correspondant des solutions mixtes ou pures 1189 # 1 : liste de toutes les solutions : [point solution, point A, point B, le ãÑ facteur p] 1190 # 2 : liste des solutions uniquement pures 1191 # 3 - 7 : valeurs des coordonnées quand la solution est pure 1192 # 8 : liste des solutions uniquement mixtes 70 1193 # 9 - 13 : valeurs des coordonnées quand la solution est mixte 1194 1195 def n_echantillon (m,n): 1196 L_liste_pure_mixte = [J 1197 L_s_list = [J 1198 L_s_pure = [J 1199 L_x1_pure = [J 1200 L_x2_pure = [J 1201 L_y1_pure = [J 1202 L_y2_pure = [J 1203 L_v_pure = [J 1204 L_s_mixte = [J 1205 L_x1_mixte = [J 1206 L_x2_mixte = [J 1207 L_y1_mixte = [J 1208 L_y2_mixte = [J 1209 L_v_mixte = [J 1210 1211 for i in range (n): 1212 liste_pure_mixte, s_list, s_pure, x1_pure, x2_pure, y1_pure,
y2_pure, 1213 1214 L_liste_pure_mixte.append(liste_pure_mixte) 1215 L_s_list.append(s_list) 1216 L_s_pure.append(s_pure) 1217 L_x1_pure.append(x1_pure) 1218 L_x2_pure.append(x2_pure) 1219 L_y1_pure.append(y1_pure) 1220 L_y2_pure.append(y2_pure) 1221 L_v_pure.append(v_pure) 1222 L_s_mixte.append(s_mixte) 1223 L_x1_mixte.append(x1_mixte) 1224 L_x2_mixte.append(x2_mixte) 1225 L_y1_mixte.append(y1_mixte) 1226 L_y2_mixte.append(y2_mixte) 1227 L_v_mixte.append(v_mixte) 1228 1229 return L_liste_pure_mixte,L_s_list, L_s_pure, L_x1_pure, L_x2_pure, \ 1230 L_y1_pure, L_y2_pure, L_v_pure, L_s_mixte, L_x1_mixte,
L_x2_mixte, 1231 L_y2_mixte, L_v_mixte 1232 # Nous renvoie 14 listes contenant chacunes les n sous-listes suivantes : 1233 1234 # 0 : liste de 0 et de 1 correspondant à des solutions mixtes ou pures 1235 # 1 : liste de toutes les solutions : [point solution, point A, point B, le ãÑ facteur p] 1236 # 2 : liste des solutions uniquement pures 1237 # 3 - 7 : valeurs des coordonnées quand la solution est pure 71 1238
72 8.2.4 Fichier "Applications_theorie_des_jeux.py" 1240 from random import uniform 1241 from numpy import mean 1242 1243 import Etude_probleme_voiture_partagee as ev 1244 1245 #%% 1246 ''' Partie 4.5 - Cas simple n°1 ''' ãÑ 1247 1248 x1, x2, y1, y2, v = 0.02, 0.34, 0.84, 0.71, 0.5 1249 tolerance = 100 1250 1251 1252 s = ev.solution_rapide (x1,x2,y1,y2,v) 1253 1254 D = ev.coordonnees_utilites(x1, x2, y1, y2, v) 1255 ev.print_solution_voiture(s, D) 1256 ev.print_solution_jeu_classique (x1,x2,y1,y2,v) 1257 1258 #%% 1259 ''' Partie 4.5 - Cas simple n°2 ''' ãÑ 1260 1261 x1, x2, y1, y2, v = 0.05, 0.60, 0.89, 0.91, 0.2 1262 tolerance = 100 1263 1264 #''' 1265 s = ev.solution_rapide (x1,x2,y1,y2,v) 1266 1267 D = ev.coordonnees_utilites(x1, x2, y1, y2, v) 1268 ev.print_solution_voiture(s, D) 1269 ev.print_solution_jeu_classique (x1,x2,y1,y2,v) 1270 1271 #%% 1272 ''' Partie 4.6.1 - infos parfaites ''' ãÑ 1273 #''' 1274 x1, x2, y1, y2, v = 0.02, 0.34, 0.84, 0.71, 0.5 1275 decimale, tolerance = 2, 100 1276 a, b = 0, 1 1277 1278 1279 #s = ãÑ ev.joueur_ment_y_maximum_dichotomie(1,a,b,x1,x2,y1,y2,v,decimale,tolerance) 1280 #print(s) 1281 #ev.plot_solution_menteur(a,b,x1,x2,y1,y2,v,decimale,tolerance) 1282 73 1283 s = ev.solution_rapide (x1,x2,y1,y2,v,decimale) 1284 1285 D = ev.coordonnees_utilites(x1, x2, y1, y2, v, decimale) 1286 1287 ev.print_solution_voiture(s, D) 1288 ev.print_solution_jeu_classique (x1,x2,y1,y2,v,decimale) 1289 ev.print_jeu_decouvert(x1,x2,y1,y2,v,decimale) 1290 ev.plot_recherche_max_joueur1et2 (x1,x2,y1,y2,v,decimale,tolerance,"Utilité des ãÑ joueurs en fonction de leur point d'arrivée",a,b) 1291 ev.print_utilites_jeu_info_parfaite(x1,x2,y1,y2,v,decimale) #''' 1292 1293 1294 #%% 1295 ''' Partie 4.6.2 - occurrence des mensonges ''' ãÑ 1296 #''' 1297 L = ev.occurrence_type_solution_jeu_decouvert(taille_echantillon = 200, joueur ãÑ = 1) 1298 1299 print(" Quand le joueur 1 joue en premier ") 1300 zero1 = L.count(0) 1301 print("Nombre de fois oil les deux individus mentent : ", zero1) 1302 un1 = L.count(1) 1303 print("Nombre de fois oil le premier ment et que le second ne ment pas : ", un1) 1304 deux1 = L.count(2) 1305 print("Nombre de fois oil le premier ne ment pas et que le second ment : ", ãÑ deux1) 1306 trois1 = L.count(3) 1307 print("Nombre de fois oil les deux disent la vérité : ", trois1) 1308 1309 L = ev.occurrence_type_solution_jeu_decouvert(taille_echantillon = 200, joueur ãÑ = 2) 1310 1311 print(" Quand le joueur 2 joue en premier ") 1312 zero2 = L.count(0) 1313 print("Nombre de fois oil les deux individus mentent : ", zero2) 1314 un2 = L.count(1) 1315 print("Nombre de fois oil le premier ment et que le second ne ment pas : ", un2) 1316 deux2 = L.count(2) 1317 print("Nombre de fois oil le premier ne ment pas et que le second ment : ", ãÑ deux2) 1318 trois2 = L.count(3) 1319 print("Nombre de fois oil les deux disent la vérité : ", trois2) #''' 1320 1321 #%% 1322 ''' Partie 4.6.3 - infos imparfaites ''' ãÑ 1323 #''' 1324 m = 300 74 1325 i = 0 1326 decimale, tolerance = 3, 100 1327 a, b = 0, 1 1328 1329 y1_les_deux_mentent = [] 1330 y2_les_deux_mentent = [] 1331 y1_J1_ment_sachant_J2_ment_List = [] 1332 y2_J2_ment_sachant_J1_ment_List = [] 1333 1334 for i in range (m): 1335 x1_u, x2_u = uniform(0,0.2), uniform(0.3,0.35) 1336 x1_v, x2_v = 0.02, 0.34 # correspond l'endroit où se trouve vraiment le ãÑ joueur 1337 1338 y1_u, y2_u = uniform(0.7,1.0), uniform(0.7,1.0) 1339 y1_v, y2_v = 0.84, 0.71 # correspond la vraie destination du joueur 1340 v = 0.5 1342 # Calcul de
l'approximation de y1 # 1344 J1_et_J2_verite = ev.J1_et_J2_verite
(x1_v,x2_u,y1_v,y2_u,v,decimale)
# 1345 J1_ment = ev.J1_ment (x1_v,x2_u,y1_v,y2_u,v,decimale,tolerance) 1346 J2_ment = ev.J2_ment (x1_v,x2_u,y1_v,y2_u,v,decimale,tolerance) 1347 J1_et_J2_mentent_ingenument = ev.J1_et_J2_mentent_ingenument(J1_ment, ãÑ J2_ment) 1348 J1_et_J2_mentent_decouvert =
ev.J1_et_J2_mentent_decouvert 1349 1350 y1_J1_ment_J2_ment = round(J1_et_J2_mentent_ingenument [2],decimale) 1351 y1_J1_ment_sachant_J2_ment = round(J1_et_J2_mentent_decouvert ãÑ [3][0],decimale) 1352 1353 y1_les_deux_mentent.append(y1_J1_ment_J2_ment) 1354 y1_J1_ment_sachant_J2_ment_List.append(y1_J1_ment_sachant_J2_ment) 1355 1356 # Calcul de
l'approximation de y2 # 1358 J1_et_J2_verite = ev.J1_et_J2_verite
(x1_u,x2_v,y1_u,y2_v,v,decimale)
# 1359 J1_ment = ev.J1_ment (x1_u,x2_v,y1_u,y2_v,v,decimale,tolerance) 1360 J2_ment = ev.J2_ment (x1_u,x2_v,y1_u,y2_v,v,decimale,tolerance) 1361 J1_et_J2_mentent_ingenument = ev.J1_et_J2_mentent_ingenument(J1_ment, ãÑ J2_ment) 1362 J1_et_J2_mentent_decouvert =
ev.J1_et_J2_mentent_decouvert 1363 1364 y2_J1_ment_J2_ment = round(J1_et_J2_mentent_ingenument [3],decimale) 1365 y2_J2_ment_sachant_J1_ment = round(J1_et_J2_mentent_decouvert 75 ãÑ [2][1],decimale) 1366 1367 y2_les_deux_mentent.append(y2_J1_ment_J2_ment) 1368 y2_J2_ment_sachant_J1_ment_List.append(y2_J2_ment_sachant_J1_ment) #''' 1369 #''' 1370 MOYENNE_y1_les_deux_mentent = mean(y1_les_deux_mentent) 1371 MOYENNE_y2_les_deux_mentent = mean(y2_les_deux_mentent) 1372 MOYENNE_y1_J1_ment_sachant_J2_ment_List = mean(y1_J1_ment_sachant_J2_ment_List) 1373 MOYENNE_y2_J2_ment_sachant_J1_ment_List = mean(y2_J2_ment_sachant_J1_ment_List) 1374 1375 print("Moyenne des y1 quand J1 ment et que J2 dit la vérité = ", ãÑ round(MOYENNE_y1_les_deux_mentent,3)) 1376 print("Moyenne des y2 quand J2 ment et que J1 dit la vérité = ", ãÑ round(MOYENNE_y2_les_deux_mentent,3)) 1377 print("Moyenne des y1 quand J1 ment et qu'il sait que J2 ment = ", ãÑ round(MOYENNE_y1_J1_ment_sachant_J2_ment_List,3)) 1378 print("Moyenne des y2 quand J2 ment et qu'il sait que J1 ment = ", ãÑ round(MOYENNE_y2_J2_ment_sachant_J1_ment_List,3)) #''' 1379 #%% 1380 #''' 1381 1382 y_1_app = (1/2)*(MOYENNE_y1_les_deux_mentent + ãÑ MOYENNE_y1_J1_ment_sachant_J2_ment_List) 1383 y_2_app = (1/2)*(MOYENNE_y2_les_deux_mentent + ãÑ MOYENNE_y2_J2_ment_sachant_J1_ment_List) 1384 v = 0.5 1385 1386 y1, y2 = 0.84, 0.71 1387 print("On prend donc comme valeur de y1 : ", y_1_app) 1388 print("On prend donc comme valeur de y2 : ", y_2_app) #''' 1389 1390 1391 #%% 1392 #''' 1393 y_1_app = 0.7323850000000001 1394 y_2_app = 0.671815 1395 v = 0.5 #''' 1396 1397 x1, x2 = 0.02, 0.34 # correspond l'endroit où se trouve vraiment le joueur 1398 y1, y2 = 0.84, 0.71 # correspond la vraie destination du joueur 1399 1400 # Solution du jeu info imparfaite # 1401 1402 VV = ev.solution_rapide(x1,x2,y1,y2,v = 0.5,decimale = 2) 1403 VM = ev.solution_rapide(x1,x2,y1,y_2_app,v = 0.5,decimale = 2) 1404 MV = ev.solution_rapide(x1,x2,y_1_app,y2,v = 0.5,decimale = 2) 1405 MM = ev.solution_rapide(x2,x2,y_1_app,y_2_app,v = 0.5,decimale = 2) 1406 76 1407 1408 print("\n Solution du jeu à info imparfaite ãÑ \n") 1409 1410 print("\n Quand les deux joueurs disent la vérité : \n") 1411 print("J1 obtient une utilité de :", VV[0][0]) 1412 print("J2 obtient une utilité de :", VV[0][1]) 1413 1414 print("\n Quand J1 dit la vérité et que J2 ment : \n") 1415 print("J1 obtient une utilité de :", VM[0][0]) 1416 print("J2 obtient une utilité de :", VM[0][1]) 1417 1418 print("\n Quand J2 dit la vérité et que J1 ment : \n") 1419 print("J1 obtient une utilité de :", MV[0][0]) 1420 print("J2 obtient une utilité de :", MV[0][1]) 1421 1422 print("\n Quand les deux joueurs mentent : \n") 1423 print("J1 obtient une utilité de :", MM[0][0]) 1424 print("J2 obtient une utilité de :", MM[0][1]) 1425 1426 #print(ev.solution_mixte_nash ([VV[0],VM[0],MV[0],MM[0]])) #''' 1427 1428 #%% 1429 a = 0 1430 b = 1 1431 v = 0.5 1432 zonehab11 = 0 1433 zonehab12 = 0.1 1434 zonehab21 = 0.9 1435 zonehab22 = 1 1436 zone1 = [zonehab11,zonehab12] 1437 zone2 = [zonehab21,zonehab22] 1438 1439 p_zone1 = 0.3 1440 p_zone2 = 1-p_zone1 1441 1442 zoneind1 = 0.5 1443 zoneind2 = 0.6 1444 zoneindustielle = [zoneind1,zoneind2] 1445 1446 x_zone1_moyen, x_zone2_moyen = mean(zone1), mean(zone2) 1447 y_moyen = mean(zoneindustielle) 1448 1449 1450 ''' Première étude ''' 1451 1452 ''' Un a ici 16 couples d'utilités à trouver, il faut distinguer les cas en ãÑ fonction 77 1453 de la zone où se trouve le joueur, il faut également penser que les endroits où ãÑ ils 1454 décident de mentir dépend de là où ils se trouvent (ex: si J1 est dans la zone ãÑ 1, l'endroit 1455 de son mensonge sera choisi en considérant que J2 est dans la zone opposée, ie. ãÑ la zone 2 ''' 1456 1457 y1,y2 = y_moyen, y_moyen 1458 1459 ''' ''' 1460 ''' J1 zone 1 - J2 zone 1 = K1 ''' 1461 ''' ''' 1462 x1 = x_zone1_moyen 1463 x2 = x_zone1_moyen 1464 ''' Aucun joueur ne ment ''' 1465 1466 solution_verite_K1 = ev.solution_rapide (x1,x2,y1,y2,v) 1467 u1_verite_K1 = solution_verite_K1[0][0] 1468 u2_verite_K1 = solution_verite_K1[0][1] 1469 1470 ''' J1 ment, J2 vérité
''' ãÑ (1,a,b,x1,x_zone2_moyen,y1,y2,v)[0] 1472 1473 solution_J1ment_J2verite_K1 = ev.solution_rapide (x1,x2,y1_J1ment_J2zone2,y2,v) 1474 u1_J1ment_J2verite_K1 = solution_J1ment_J2verite_K1[0][0] 1475 u2_J1ment_J2verite_K1 = solution_J1ment_J2verite_K1[0][1] 1476 1477 ''' J1 vérité, J2 ment
''' 1479 1480 solution_J2ment_J1verite_K1 = ev.solution_rapide (x1,x2,y1,y2_J2ment_J1zone2,v) 1481 u1_J2ment_J1verite_K1 = solution_J2ment_J1verite_K1[0][0] 1482 u2_J2ment_J1verite_K1 = solution_J2ment_J1verite_K1[0][1] 1483 1484 ''' J1 ment, J2 ment ''' 1485 1486 solution_J1ment_J2ment_K1 = ev.solution_rapide ãÑ (x1,x2,y1_J1ment_J2zone2,y2_J2ment_J1zone2,v) 1487 u1_J1ment_J2ment_K1 = solution_J1ment_J2ment_K1[0][0] 1488 u2_J1ment_J2ment_K1 = solution_J1ment_J2ment_K1[0][1] 1489 print ("\n ") 1491 print (" ") 78 1496 print ("J1 aura une utilité de :", u1_J1ment_J2verite_K1) 1497 print ("J2 aura une utilité de :", u2_J1ment_J2verite_K1) 1498 print ("\nSi J1 décide de dire la vérité et J2 mentir") 1499 print ("J1 aura une utilité de :", u1_J2ment_J1verite_K1) 1500 print ("J2 aura une utilité de :", u2_J2ment_J1verite_K1) 1501 print ("\nSi les deux joueurs décident de mentir") 1502 print ("J1 aura une utilité de :", u1_J1ment_J2ment_K1) 1503 print ("J2 aura une utilité de :", u2_J1ment_J2ment_K1) 1504 1505 ''' ''' 1506 ''' J1 zone 1 - J2 zone 2 = K2 ''' 1507 ''' ''' 1508 x1 = x_zone1_moyen 1509 x2 = x_zone2_moyen 1510 ''' Aucun joueur ne ment ''' 1511 1512 solution_verite_K2 = ev.solution_rapide (x1,x2,y1,y2,v) 1513 u1_verite_K2 = solution_verite_K2[0][0] 1514 u2_verite_K2 = solution_verite_K2[0][1] 1515 1516 ''' J1 ment, J2 vérité
''' ãÑ (1,a,b,x1,x_zone2_moyen,y1,y2,v)[0] 1518 1519 solution_J1ment_J2verite_K2 = ev.solution_rapide (x1,x2,y1_J1ment_J2zone2,y2,v) 1520 u1_J1ment_J2verite_K2 = solution_J1ment_J2verite_K2[0][0] 1521 u2_J1ment_J2verite_K2 = solution_J1ment_J2verite_K2[0][1] 1522 1523 ''' J1 vérité,
J2 ment ''' 1525 1526 solution_J2ment_J1verite_K2 = ev.solution_rapide (x1,x2,y1,y2_J2ment_J1zone1,v) 1527 u1_J2ment_J1verite_K2 = solution_J2ment_J1verite_K2[0][0] 1528 u2_J2ment_J1verite_K2 = solution_J2ment_J1verite_K2[0][1] 1529 1530 ''' J1 ment, J2 ment ''' 1531 1532 solution_J1ment_J2ment_K2 = ev.solution_rapide ãÑ (x1,x2,y1_J1ment_J2zone2,y2_J2ment_J1zone1,v) 1533 u1_J1ment_J2ment_K2 = solution_J1ment_J2ment_K2[0][0] 1534 u2_J1ment_J2ment_K2 = solution_J1ment_J2ment_K2[0][1] 1535 1536 print ("\n ") 1537 print ("Quand le joueur 1 se trouve dans la zone 1 et le joueur 2 dans la zone ãÑ 2") 1538 print (" ") 1539 print ("\nSi les deux joueurs décident de dire la vérité") 1540 print ("J1 aura une utilité de :", u1_verite_K2) 79 1541 print ("J2 aura une utilité de :", u2_verite_K2) 1542 print ("\nSi J1 décide de mentir et J2 dire la vérité") 1543 print ("J1 aura une utilité de :", u1_J1ment_J2verite_K2) 1544 print ("J2 aura une utilité de :", u2_J1ment_J2verite_K2) 1545 print ("\nSi J1 décide de dire la vérité et J2 mentir") 1546 print ("J1 aura une utilité de :", u1_J2ment_J1verite_K2) 1547 print ("J2 aura une utilité de :", u2_J2ment_J1verite_K2) 1548 print ("\nSi les deux joueurs décident de mentir") 1549 print ("J1 aura une utilité de :", u1_J1ment_J2ment_K2) 1550 print ("J2 aura une utilité de :", u2_J1ment_J2ment_K2) 1551 1552 ''' ''' 1553 ''' J1 zone 2 - J2 zone 1 = K3 ''' 1554 ''' ''' 1555 x1 = x_zone2_moyen 1556 x2 = x_zone1_moyen 1557 ''' Aucun joueur ne ment ''' 1558 1559 solution_verite_K3 = ev.solution_rapide (x1,x2,y1,y2,v) 1560 u1_verite_K3 = solution_verite_K3[0][0] 1561 u2_verite_K3 = solution_verite_K3[0][1] 1562 1563 ''' J1 ment, J2 vérité
''' ãÑ (1,a,b,x1,x_zone1_moyen,y1,y2,v)[0] 1565 1566 solution_J1ment_J2verite_K3 = ev.solution_rapide (x1,x2,y1_J1ment_J2zone1,y2,v) 1567 u1_J1ment_J2verite_K3 = solution_J1ment_J2verite_K3[0][0] 1568 u2_J1ment_J2verite_K3 = solution_J1ment_J2verite_K3[0][1] 1569 1570 ''' J1 vérité,
J2 ment ''' 1572 1573 solution_J2ment_J1verite_K3 = ev.solution_rapide (x1,x2,y1,y2_J2ment_J1zone2,v) 1574 u1_J2ment_J1verite_K3 = solution_J2ment_J1verite_K3[0][0] 1575 u2_J2ment_J1verite_K3 = solution_J2ment_J1verite_K3[0][1] 1576 1577 ''' J1 ment, J2 ment ''' 1578 1579 solution_J1ment_J2ment_K3 = ev.solution_rapide ãÑ (x1,x2,y1_J1ment_J2zone1,y2_J2ment_J1zone2,v) 1580 u1_J1ment_J2ment_K3 = solution_J1ment_J2ment_K3[0][0] 1581 u2_J1ment_J2ment_K3 = solution_J1ment_J2ment_K3[0][1] 1582 1583 print ("\n ") 1584 print ("Quand le joueur 1 se trouve dans la zone 2 et le joueur 2 dans la zone ãÑ 1") 1585 print (" ") 80 1586 print ("\nSi les deux joueurs décident de dire la vérité") 1587 print ("J1 aura une utilité de :", u1_verite_K3) 1588 print ("J2 aura une utilité de :", u2_verite_K3) 1589 print ("\nSi J1 décide de mentir et J2 dire la vérité") 1590 print ("J1 aura une utilité de :", u1_J1ment_J2verite_K3) 1591 print ("J2 aura une utilité de :", u2_J1ment_J2verite_K3) 1592 print ("\nSi J1 décide de dire la vérité et J2 mentir") 1593 print ("J1 aura une utilité de :", u1_J2ment_J1verite_K3) 1594 print ("J2 aura une utilité de :", u2_J2ment_J1verite_K3) 1595 print ("\nSi les deux joueurs décident de mentir") 1596 print ("J1 aura une utilité de :", u1_J1ment_J2ment_K3) 1597 print ("J2 aura une utilité de :", u2_J1ment_J2ment_K3) 1598 1599 ''' ''' 1600 ''' J1 zone 2 - J2 zone 2 = K4 ''' 1601 ''' ''' 1602 x1 = x_zone2_moyen 1603 x2 = x_zone2_moyen 1604 ''' Aucun joueur ne ment ''' 1605 1606 solution_verite_K4 = ev.solution_rapide (x1,x2,y1,y2,v) 1607 u1_verite_K4 = solution_verite_K4[0][0] 1608 u2_verite_K4 = solution_verite_K4[0][1] 1609 1610 ''' J1 ment, J2 vérité
''' ãÑ (1,a,b,x1,x_zone1_moyen,y1,y2,v)[0] 1612 1613 solution_J1ment_J2verite_K4 = ev.solution_rapide (x1,x2,y1_J1ment_J2zone1,y2,v) 1614 u1_J1ment_J2verite_K4 = solution_J1ment_J2verite_K4[0][0] 1615 u2_J1ment_J2verite_K4 = solution_J1ment_J2verite_K4[0][1] 1616 1617 ''' J1 vérité,
J2 ment ''' 1619 1620 solution_J2ment_J1verite_K4 = ev.solution_rapide (x1,x2,y1,y2_J2ment_J1zone1,v) 1621 u1_J2ment_J1verite_K4 = solution_J2ment_J1verite_K4[0][0] 1622 u2_J2ment_J1verite_K4 = solution_J2ment_J1verite_K4[0][1] 1623 1624 ''' J1 ment, J2 ment ''' 1625 1626 solution_J1ment_J2ment_K4 = ev.solution_rapide ãÑ (x1,x2,y1_J1ment_J2zone1,y2_J2ment_J1zone1,v) 1627 u1_J1ment_J2ment_K4 = solution_J1ment_J2ment_K4[0][0] 1628 u2_J1ment_J2ment_K4 = solution_J1ment_J2ment_K4[0][1] 1629 1630 print ("\n ") 1631 print ("Quand les joueurs se situe dans la même zone 2") 81 1632 1633 1634 1635
82 8.2.5 Fichier "Applications_statistiques.py" 1645 from numpy import zeros 1646 from matplotlib import pyplot as plt 1647 from scipy.stats import binom, t 1648 from math import sqrt 1649 1650 import Etude_probleme_voiture_partagee as ev 1651 1652 #%% 1653 n = 100 1654 1655 def list_to_array(L): 1656 n = len(L) 1657 X = zeros(n) 1658 for i in range (n): X[i]=L[i] 1659 1660 return X 1661 1662 liste = ev.echantillon_test_stat_solution_pure (n)[0] 1663 1664 X_sample = list_to_array(liste) 1665 #%% 1666 p=1/2 1667 1668 stat_test_mediane = sum(X_sample) 1669 1670 moyenne_empirique = (1/n)*sum(X_sample) 1671 1672 variance_empirique = (1/(n-1))*sum((X_sample-moyenne_empirique)**2) 1673 1674 quantile_p_valeur = (sqrt(n)/variance_empirique)*(moyenne_empirique-0.90) 1675 1676 p_valeur_mediane = binom.cdf(stat_test_mediane,n,p) 1677 p_valeur_student = t.cdf(quantile_p_valeur,n-1) 1678 1679 print("stat_test_mediane = ",stat_test_mediane) 1680 print("stat_test_mediane = ",moyenne_empirique) 1681 1682 print("p_valeur_mediane = ",p_valeur_mediane) 1683 print("p_valeur_student = ",p_valeur_student) 1684 1685 #%% 1686 1687 def m_p_valeur (n,m): 1688 p_mediane = [] # on rentre les p-valeurs du test 1 de la médiane 1689 p_student = [] # on rentre les p-valeurs du test 2 de Student 1690 moyenne = [] # on rentre les valeurs des moyennes 1691 save_nb_solutions_mixtes = [] # sert
étudier les moyennes quand
les 83 1692 1693 for i in range (m): 1694 liste = ev.echantillon_test_stat_solution_pure (n)[0] 1695 1696 X_sample = list_to_array(liste) 1697 stat_test_mediane = sum(X_sample) 1698 1699 moyenne_empirique = (1/n)*stat_test_mediane 1700 moyenne.append(moyenne_empirique) 1701 1702 variance_empirique = (1/(n-1))*sum((X_sample-moyenne_empirique)**2) 1703 1704 quantile_p_valeur = ãÑ (sqrt(n)/variance_empirique)*(moyenne_empirique-0.90) 1705 p = 1/2 1706 p_valeur_mediane = binom.cdf(stat_test_mediane,n,p) 1707 p_valeur_student = t.cdf(quantile_p_valeur,n-1) 1708 if p_valeur_student < 0.8: 1709 ãÑ save_nb_solutions_mixtes.append([p_valeur_student,moyenne_empirique]) 1710 p_mediane.append(p_valeur_mediane) 1711 p_student.append(p_valeur_student) 1712 1713 return p_mediane, p_student, moyenne, save_nb_solutions_mixtes 1714 n, m = 100, 100 1715 p_mediane, p_student, moyenne, etude_p_valeur = m_p_valeur(n,m) 1716 1717 1718 plt.figure() 1719 plt.hist(p_mediane, edgecolor = "black", color = "white") 1720 plt.title("Histogramme de " + str(n) + " p-valeurs correspondant au test de la ãÑ médiane") 1721 1722 plt.figure() 1723 plt.hist(p_student, edgecolor = "magenta", color = "white") 1724 plt.title("Histogramme de " + str(n) + " p-valeurs correspondant au test de ãÑ Student") 1725 1726 plt.figure() 1727 plt.hist(moyenne, edgecolor = "darkred", color = "white") 1728 plt.title("Histogramme de " + str(n) + " moyennes") |
|