• contact@spgoo.org

\(\textrm{Explication des tournois d’Axelrod}\)

La théorie des jeux est apparue à la fin de la seconde guerre mondiale dans l’effort hors du commun de John von Neuman et Oscar Morgenstern pour développer une théorie des interactions entre agents. Une mauvaise appellation au départ a créé une certaine confusion. La théorie des jeux s’intéresse essentiellement aux conflits sociaux, et les jeux sont effectivement des conflits sociaux.

Avec l’introduction du dilemme du prisonnier, il a semblé qu’il n’était jamais rationnel de coopérer (en 1950, Melvin Dresher et Merill Flood présentèrent ce jeu sous une forme mathématique qui fut, par la suite, enveloppée dans une formulation littéraire par Albert W. Tucker, le directeur de thèse de John Nash). On obtient un équilibre dit de Cournot-Nash quand les deux joueurs trahissent. Bien sûr, ils pourraient améliorer tous les deux leur situation (on parle d’équilibre de Pareto) s’ils coopéraient, mais la menace de la trahison les en empêche.

Malgré les réflexions profondes de David Hume qui, dès le XVIIIeme siècle, justifiait la coopération dans les interactions répétitives et l’observation dans la Nature de la coopération entre individus de même espèce mais sans lien de parenté (la chauve-souris vampire d’Amazonie)ou d’espèces opposées comme le requin et le labre néttoyeur comme le pluvian et le crocodile, entre les fleurs polinisées par les abeilles, entre les bactéries qui peuplent notre microbiote intestinal (dans lequel nous pouvons modifier les interactions en fonction de notre alimentation), il a fallu attendre longtemps pour que l’on s’intéresse aux interactions intertemporelles.

Pourtant dès 1964, William Hamilton apporte une solution à la question de l’existence de comportements altruistes dans la Nature : ils sont favorisés par la sélection naturelle si les coûts opératifs de ces comportements sont inférieurs aux avantages escomptés. Hamilton découvre avec d’autres comme John Maynard Smith et Georges Price en 1973 que le théorie des jeux est aussi un langage de la Nature.

Cependant la coopération demeure partiellement une énigme parce que ce qui est intéressant c’est de comprendre pourquoi des individus fondamentalement égoïstes vont être amenés à coopérer. En effet depuis les « Discours sur les origines et les fondements des inégalités entre les hommes » de J.-J. Rousseau en 1755, on sait que des individus rationnels et égoïstes abandonneront le gain important collectif pour un gain plus petit mais individuel.

En 1981, Robert Axelrod et William Hamilton publièrent un article qui allait se transformer en un livre après que le premier, un spécialiste de science politique, eut demandé dans un grand nombre de revues en Sciences Humaines, qu’on lui transmette des stratégies qu’il pourrait opposer les unes aux autres dans un tournoi bati sur un dilemme du prisonnier répété. L’idée était de vérifier quelle serait la stratégie qui dans un nombre fini d’interactions l’emporterait dans un tournoi de type Round-Robin (toutes les stratégies sont confrontées les unes aux autres et la vainqueure est celle qui accumule le plus grand nombre de victoires).

Le résultat fut l’émergence de la stratégie bienveillante la plus simple : Donnant-Donnant (ou en anglais Tit-for-Tat) qui trahit si elle a été trahie dans le tour précédent mais revient à à la coopération immédiatement après. L’avantage d’une telle stratégie est qu’elle incite à la coopération peut être pour une mauvaise raison (la peur d’être trahie si on trahit).

Cette page reconstruit les deux tournois d’Axelrod, mais elle permet aussi de s’interroger sur la forme du tournoi. De plus, elle permet de se poser une autre question : si l’association entre une stratégie et une entité vivante est logique en biologie, l’est-elle quand il s’agit d’individus ?

Liste des méthodes

Premier Tournois (1980)

Key

Intitulé

Signature


Explications de l’implémentation

Les signatures des fonctions ont été harmonisées. Les arguments passés à la fonction sont définis de la manière suivante

  • choixAdv : valeur de l’adversaire au coup précédent C ou T
  • choixMe : valeur du candidat au coup précédent C ou T
  • histoAdv : historique des choix de l’adversaire [‘C’,’T’]
  • histoMe : historique des choix du candidat [‘C’,’T’]

Lors de l’exécution des fonctions il nous suffit de remplacer les arguments par les variables en cours Choix1, Choix2, Histo1 ou Histo2 ce qui permet de fournir le contexte d’exécution à la fonction et de retourner la réponse

        // ---------------------------------------------------
        // gestion des parties: 
        // ---------------------------------------------------
        async function game_start(fighter1,fighter2) {
	    pas_score=1/nb_duels;
            game_init();
	    pas=0;
            fct1=fighter1.strategie.signature;
            fct1=fct1.replace("choixAdv","choix2").replace("HistoAdv","histo2").replace("HistoMe","histo1");
            fct2=fighter2.strategie.signature;
            fct2=fct2.replace("choixAdv","choix1").replace("HistoAdv","histo1").replace("HistoMe","histo2");
            return await execute(fighter1,fighter2);
        }
        async function execute(fighter1,fighter2) { 
	    let res1=0,res2=0;
            while (pas<nb_duels) {
                eval("choix1="+fct1);
                histo1.push(choix1);
                eval("choix2="+fct2);
                histo2.push(choix2);
                // calcul des scores score1 et score2 
                [score1,score2]=resultat[choix1+"-"+choix2];
                // calcul des cumuls Cscore1 et Cscore2
                res1+=score1;res2+=score2;
                if (choix1=="C")  {CptC1++;pc10_Glider.setGliderPosition(-0.25+CptC1*pas_score);}
                else   {CptT1++;pc11_Glider.setGliderPosition(-0.25+CptT1*pas_score);}
                if (choix2=="C")  {CptC2++;pc20_Glider.setGliderPosition(-0.25+CptC2*pas_score);}
                else   {CptT2++;pc21_Glider.setGliderPosition(-0.25+CptT2*pas_score);}
                pas++;
                await new Promise(resolve => setTimeout(resolve, 200));
            } 
	    fighter1.score+=res1;
	    fighter2.score+=res2;
	    return res1>res2?1:res2<res1?2:0;
        }