GENTILLON Loris, SURIER GAROFALO Aurelien
Dans ce DM, on s’intéresse au jeu de Pierre Papier Ciseaux et on cherche à savoir quelle est la bonne stratégie à avoir. Dans la première partie on s’intéressera à l’estimation de l’espérance de gain dans des cas de jeux biaisés ou non, et dans la seconde partie comment donner un minimum d’intelligence à la machine pour augmenter son espérance de gain contre l’Humain.
# sémantique :
# p_pierre : probabilité de jouer pierre
# p_feuille: probabilité de jouer feuille
# p_ciseaux : probabilité de jouer ciseaux
# Probabilités pour le Joueur A (uniforme : non biaisé)
p_pierre_a = 0.33;
p_feuille_a = 0.33;
p_ciseaux_a = 0.33;
# Probabilités pour le Joueur B (uniforme : non biaisé)
p_pierre_b = 0.33;
p_feuille_b = 0.33;
p_ciseaux_b = 0.33;
# Nombre de coup de simulation
n = 100; # Le nombre de fois ou on fait pierre papier ciseaux
n2 = 50; # Le nombre de moyennes que l'on veut calculer -> n2 moyenne pour lisser
# Joue un coup
tirerUniqueCoup = function(ppa, pfa, pca){
s1 = ppa;
s2 = ppa + pfa;
s3 = ppa + pfa + pca;
temp = runif(1, min= 0 , max = s3);
if(temp < s1){
X = 'p';
}
else if (temp < s2){
X = 'f';
}
else{
X = 'c';
}
return(X);
}
# créer un vecteur de taille n en répartissant les valeurs p, f et c selon leurs probabilités associées = c'est une simulation de jeu
tirerVecteurCoups = function(ppa, pfa, pca, n){
s1 = ppa;
s2 = ppa + pfa;
s3 = ppa + pfa + pca;
temp = runif(n, min= 0 , max = s3);
X = vector(mode="character", length = n);
for(i in 1:n){
if(temp[i] < s1){
X[i] = 'p';
}
else if (temp[i] < s2){
X[i] = 'f';
}
else{
X[i] = 'c';
}
}
return(X);
}
# retourne un vecteur de comparaison (+1 , 0 , -1) entre deux vecteurs coupA, coupB. Tous les vecteurs sont de taille n.
comparaison = function(coupA, coupB, n){
X = integer(length = n)
for(i in 1:n){
if(coupA[i] == 'p' & coupB[i] == 'p' ){
X[i] = 0;
}
else if(coupA[i] == 'p' & coupB[i] == 'f' ){
X[i] = -1;
}
else if(coupA[i] == 'p' & coupB[i] == 'c' ){
X[i] = 1;
}
else if(coupA[i] == 'f' & coupB[i] == 'p' ){
X[i] = 1;
}
else if(coupA[i] == 'f' & coupB[i] == 'f' ){
X[i] = 0;
}
else if(coupA[i] == 'f' & coupB[i] == 'c' ){
X[i] = -1;
}
else if(coupA[i] == 'c' & coupB[i] == 'p' ){
X[i] = -1;
}
else if(coupA[i] == 'c' & coupB[i] == 'f' ){
X[i] = 1;
}
else if(coupA[i] == 'c' & coupB[i] == 'c' ){
X[i] = 0;
}
}
return(X)
}
# retourne la somme des éléments du vecteur X de taille n.
resultat = function(X,n){
return(sum(X[1:n]));
}
# créer deux vecteurs, puis retourne la comparaison entre les deux (du point de vue de B)
comparer_jeu = function(ppa,pfa,pca,ppb,pfb,pcb,n){
coupsA = tirerVecteurCoups(ppa,pfa,pca,n);
coupsB = tirerVecteurCoups(ppb,pfb,pcb,n);
#We compare B to A, so B is first in our func
compared = comparaison(coupsB,coupsA,n)
return(resultat(compared,n))
}
# créer un vecteur de coups, puis le compare avec le vecteur vecA en paramètre (du point de vue de B)
comparer_jeu_a_fixe = function(vecA,ppb,pfb,pcb,n){
coupsA = vecA;
coupsB = tirerVecteurCoups(ppb,pfb,pcb,n);
#We compare B to A, so B is first in our func
compared = comparaison(coupsB,coupsA,n);
return(resultat(compared,n));
}
# Créer un vecteur de taille n2, appelant n2 fois les fonctions précédentes.
createFinalVector = function(ppa, pfa, pca, ppb, pfb, pcb, n, n2){
X = integer(length = n2);
for(i in 1:n2){
X[i] = comparer_jeu(ppa, pfa, pca, ppb, pfb, pcb, n);
}
return(X);
}
# Créer un vecteur de taille n2, appelant n2 fois les fonctions précédentes.
createFinalVector2 = function(vecA, ppb, pfb, pcb, n, n2){
X = integer(length = n2);
for(i in 1:n2){
X[i] = comparer_jeu_a_fixe(vecA, ppb, pfb, pcb, n);
}
return(X);
}
# Fonction plus utilisée (bogue)
analyze = function(ppa,pfa,pca,ppb,pfb,pcb,n){
X = createFinalVector(ppa,pfa,pca,ppb,pfb,pcb,n);
median(X);
mean(X);
plot(X);
}
Quand le joueur A est biaisé
# le joueur A est biaisé, avec plus de chance de jouer ciseaux
p_pierre_a = 0.25;
p_feuille_a = 0.25;
p_ciseaux_a = 0.5;
# coups joués par A
vecRefA = tirerVecteurCoups(p_pierre_a, p_feuille_a, p_ciseaux_a, n);
# le joueur B est également biaisé, avec plus de chance de jouer ciseaux
p_pierre_b = 0.25;
p_feuille_b = 0.25;
p_ciseaux_b = 0.5;
X = createFinalVector2(vecRefA, p_pierre_b, p_feuille_b, p_ciseaux_b, n, n2);
print("La médiane vaut : "); median(X);
## [1] "La médiane vaut : "
## [1] 2
print("La moyenne vaut : "); mean(X);
## [1] "La moyenne vaut : "
## [1] 2.44
#plot(X);
Arbre de probabilité
Si on fait la somme des probabilités, on obtient :
Ainsi, jouer contre un joueur biaisé en ayant le même biais que lui semble donner une espérance de 0.
# Joueur A : on garde le même vecteur que précédemment, afin d'avoir une base de comparaison commune.
# Joueur B
p_pierre_b = 0.33;
p_feuille_b = 0.33;
p_ciseaux_b = 0.33;
X = createFinalVector2(vecRefA, p_pierre_b, p_feuille_b, p_ciseaux_b, n, n2);
print("La médiane vaut : "); median(X);
## [1] "La médiane vaut : "
## [1] -3
print("La moyenne vaut : "); mean(X);
## [1] "La moyenne vaut : "
## [1] -2.84
#plot(X);
Lorsque l’on somme les probabilités, on obtient :
Ainsi, jouer contre un joueur biaisé en n’ayant pas de biais laisse dans ce cas encore espérer d’un gain de 0 (espérance = 0).
# retourne une liste Li composée de 64 vecteurs, chacun avec des valeurs différentes de X, Y et Z.
createAllVector = function (vecRefA,n,n2){
Li = list();
indiceLi = 1;
X = 0;
Y = 0;
Z = 1 - X - Y;
for(i in 1:10){
for (j in 1:10){
if (X + Y > 1){
break;
}
temp = createFinalVector2(vecRefA,X,Y,Z,n,n2);
Li[[indiceLi]] = temp;
indiceLi = indiceLi + 1;
Y = Y + 0.1;
}
Y = 0;
X = X + 0.1;
}
return(Li);
}
# idem mais créer une liste de moyenne
createAllVectorAndMedian = function (vecRefA,n,n2){
Li = list();
indiceLi = 1;
X = 0;
Y = 0;
Z = 1 - X - Y;
for(i in 1:10){
for (j in 1:10){
if (X + Y > 1){
break;
}
temp = mean(createFinalVector2(vecRefA,X,Y,Z,n,n2));
Li[[indiceLi]] = temp;
indiceLi = indiceLi + 1;
Y = Y + 0.1;
}
Y = 0;
X = X + 0.1;
}
return(Li);
}
# Return a lsit with the X Y Z of the optimal solution for a particular verRefA
getXandYandZ = function (vecRefA,n,n2){
Li = integer();
LX = list();
LY = list();
indiceLi = 1;
X = 0;
Y = 0;
Z = 1 - X - Y;
for(i in 1:10){
for (j in 1:10){
if (X + Y > 1){
break;
}
temp = mean(createFinalVector2(vecRefA,X,Y,Z,n,n2));
Li[[indiceLi]] = temp;
LX[[indiceLi]] = X;
LY[[indiceLi]] = Y;
indiceLi = indiceLi + 1;
Y = Y + 0.1;
}
Y = 0;
X = X + 0.1;
}
#print(max(Li));
#this line from https://stat.ethz.ch/pipermail/r-help/2007-January/123788.html
#to sort the maximal value
#print(which(Li == max(Li)));
last = which(Li == max(Li));
lereturn = list();
lereturn[[1]] = LX[[last]];
lereturn[[2]] = LY[[last]];
lereturn[[3]] = 1 - lereturn[[1]] - lereturn[[2]]
return(lereturn);
}
optimalValues = getXandYandZ(vecRefA,n,n2);
print("optimalValues :");
## [1] "optimalValues :"
print("X :");
## [1] "X :"
print(optimalValues[1]);
## [[1]]
## [1] 0.9
print("Y :");
## [1] "Y :"
print(optimalValues[2]);
## [[1]]
## [1] 0
print("Z :");
## [1] "Z :"
print(optimalValues[3]);
## [[1]]
## [1] 0.1
Après plusieurs exécutions de la fonction écrite ci-dessus, on trouve, pour le vecteur A de valeurs ( 0.25 , 0.25 , 0.5), des valeurs pour B optimales : (0.9, 0 , 0.1), avec cependants quelques variations (comme (0.8, 0, 0.2) par exemple).