In dieser Herausforderung spielst du das Dilemma des lauten iterierten Gefangenen.
Das Gefangenendilemma ist ein Szenario in der Spieltheorie, in dem es zwei Spieler gibt, die jeweils zwei Optionen haben: Kooperation oder Defekt. Jeder Spieler macht es besser für sich, wenn er defekt ist, als wenn er kooperiert, aber beide Spieler würden das Ergebnis, bei dem beide Spieler kooperieren, dem vorziehen, bei dem beide Spieler defekt sind.
Das iterierte Gefangenendilemma ist dasselbe Spiel, außer dass Sie wiederholt gegen denselben Gegner spielen und wissen, was Ihr Gegner in der Vergangenheit gespielt hat. Ihr Ziel ist es immer, die höchste Punktzahl für sich selbst zu erzielen, unabhängig davon, wie Ihr Gegner vorgeht.
Das laute Dilemma der iterierten Gefangenen bringt ein wenig Lärm in die Kommunikation. Wenn du weißt, was dein Gegner in der Vergangenheit gespielt hat, werden Geräusche eingeführt. Sie werden auch wissen, welche Bewegungen Sie in der Vergangenheit gemacht haben. Die Geräuschrate ist während einer Runde gegen denselben Gegner konstant, aber zwischen verschiedenen Runden unterschiedlich.
Herausforderung
In dieser Herausforderung werden Sie ein Python 3-Programm schreiben, um das Dilemma eines lauten iterierten Gefangenen zu spielen.
Ihr Programm erhält drei Eingaben:
Deine eigenen Züge, ohne zufällige Flips.
Die Züge deines Gegners mit zufälligen Flips.
Eine Statusvariable, die in jeder Runde als leere Liste beginnt und die Sie bei Bedarf ändern können. Sie können dies ignorieren, wenn Sie es nicht verwenden möchten.
Ihr Programm sollte ausgegeben werden, 'c'
um zusammenzuarbeiten oder 'd'
zu defekten.
Hier ist zum Beispiel ein Programm, das kooperiert, wenn der Gegner in der Vergangenheit mindestens 60% der Zeit kooperiert hat, nachdem zufällige Flips angewendet wurden, und für die ersten 10 Flips:
def threshold(my_plays, their_flipped_plays, state):
if len(their_flipped_plays) < 10:
return 'c'
opp_c_freq = their_flipped_plays.count('c')/len(their_flipped_plays)
if opp_c_freq > 0.6:
return 'c'
else:
return 'd'
Wenn Sie Python nicht kennen, schreiben Sie Ihren Beitrag in Pseudocode, und jemand (ich oder ein anderes Mitglied der Site) kann das entsprechende Python-Programm erstellen.
Gameplay
Der Turnierläufer ist hier zu finden: noisy-game . Laufen noisy-game.py
, um das Turnier zu starten. Ich werde dieses Repository mit neuen Einreichungen auf dem Laufenden halten. Beispielprogramme finden Sie in basic.py
.
Die Gesamtpunktzahl eines Programms ergibt sich aus der Gesamtpunktzahl von über 100 Spielen des Spiels.
Ein Spiel besteht aus Round-Robin-Matches jedes Spielers gegen jeden Spieler, einschließlich sich selbst. Ein Matchup besteht aus 100 Runden. Eine Runde besteht aus 300 Zügen, bei denen jeweils 'c'
oder ausgegeben werden 'd'
.
Ihre Einsendung wird gegen jede Einsendung, einschließlich Ihrer eigenen, ein Matchup spielen. Jedes Matchup besteht aus 100 Runden. Während jeder Runde wird eine Schlagwahrscheinlichkeit einheitlich zufällig aus gewählt [0, 0.5]
.
Jede Runde besteht aus 300 Zügen. Bei jedem Zug erhalten beide Programme alle vorherigen Spiele, die sie versucht haben, und alle vorherigen Spiele, die das andere Programm nach dem Anwenden von Flips gemacht hat, sowie eine Statusvariable, eine veränderbare Liste, die das Programm ändern kann, wenn es möchte. Die Programme geben ihre Züge aus.
Züge werden wie folgt gewertet: Wenn ein Programm a spielt 'c'
, erhält das gegnerische Programm 2 Punkte. Wenn ein Programm einen 'd'
abspielt, erhält dieses Programm 1 Punkt.
Dann wird jeder Zug unabhängig mit einer Wahrscheinlichkeit gespiegelt, die gleich der Spiegelwahrscheinlichkeit ist, und zum Zeigen für den Gegner gespeichert.
Nachdem alle Runden gespielt wurden, addieren wir die Anzahl der Punkte, die jeder Spieler in jedem Matchup erhalten hat. Anschließend verwenden wir das folgende Bewertungssystem, um die Punktzahl jedes Spielers für das Spiel zu berechnen. Diese Wertung wird durchgeführt, nachdem alle Matchups abgeschlossen sind.
Wertung
Wir werden die Evolutionsbewertung verwenden. Jedes Programm beginnt mit gleichem Gewicht. Anschließend werden die Gewichte für 100 Iterationen unter Verwendung der Punktsummen aus dem Spiel wie folgt aktualisiert:
Das neue Gewicht jedes Programms ist proportional zum Produkt seines vorherigen Gewichts und seiner durchschnittlichen Punktzahl, gewichtet mit den Gewichten seiner Gegner.
100 solcher Aktualisierungen werden angewendet, und die endgültigen Gewichte sind die Punktzahlen der einzelnen Programme für diesen Lauf des Spiels.
Die Gesamtpunktzahl ergibt sich aus der Summe der über 100 Durchläufe des Spiels.
Die Spieler werden alle gültige Antworten auf diese Herausforderung sein, plus sechs Basisprogramme , um uns zum Start zu bringen.
Vorbehalte
Verändern Sie die Eingänge nicht. Versuchen Sie nicht, die Ausführung eines anderen Programms zu beeinträchtigen, außer durch Zusammenarbeit oder Fehler. Machen Sie keine Opfergabe, bei der versucht wird, eine andere Aufgabe zu erkennen, und nutzen Sie diesen Gegner auf eigene Kosten. Standardlücken sind verboten.
BEARBEITEN: Einreichungen dürfen keines der Basisprogramme oder frühere Einreichungen exakt duplizieren .
Wenn Sie Fragen haben, können Sie diese gerne stellen.
Aktuelle Ergebnisse
nicht_genug: 40.6311
stealer: 37.1416
enough: 14.4443
wait_for_50: 6.947
threshold: 0.406784
buckets: 0.202875
change_of_heart: 0.0996783
exploit_threshold: 0.0670485
kickback: 0.0313357
tit_for_stat: 0.0141368
decaying_memory: 0.00907645
tit_for_whoops: 0.00211803
slider: 0.00167053
trickster: 0.000654875
sounder: 0.000427348
tit_for_tat: 9.12471e-05
stubborn_stumbler: 6.92879e-05
tit_for_time: 2.82541e-05
jedi2sith: 2.0768e-05
cooperate: 1.86291e-05
everyThree: 1.04843e-05
somewhat_naive: 4.46701e-06
just_noise: 1.41564e-06
growing_distrust: 5.32521e-08
goldfish: 4.28982e-09
vengeful: 2.74267e-09
defect: 3.71295e-10
alternate: 2.09372e-20
random_player: 6.74361e-21
Ergebnisse mit nur Antworten auf diese Frage und Basisprogrammen, die das Spiel des Gegners ignorieren:
nicht_genug: 39.3907
stealer: 33.7864
enough: 20.9032
wait_for_50: 5.60007
buckets: 0.174457
kickback: 0.0686975
change_of_heart: 0.027396
tit_for_stat: 0.024522
decaying_memory: 0.0193272
tit_for_whoops: 0.00284842
slider: 0.00153227
sounder: 0.000472289
trickster: 0.000297515
stubborn_stumbler: 3.76073e-05
cooperate: 3.46865e-05
tit_for_time: 2.42263e-05
everyThree: 2.06095e-05
jedi2sith: 1.62591e-05
somewhat_naive: 4.20785e-06
just_noise: 1.18372e-06
growing_distrust: 6.17619e-08
vengeful: 3.61213e-09
goldfish: 3.5746e-09
defect: 4.92581e-10
alternate: 6.96497e-20
random_player: 1.49879e-20
Gewinnen
Der Wettbewerb bleibt auf unbestimmte Zeit geöffnet, da neue Beiträge veröffentlicht werden. Ich erkläre jedoch einen Monat nach dem Absenden dieser Frage einen Gewinner (akzeptiere eine Antwort) auf der Grundlage der Ergebnisse.
exploit_threshold()
mehrmals versucht, als exploit_threshold1()
usw. zu kopieren und sie zur players
Liste hinzugefügt . Warum erhalte ich bei identischen Strategien sehr unterschiedliche Ergebnisse?