Skip to content

Instantly share code, notes, and snippets.

@drusepth
Created July 6, 2013 06:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drusepth/5938924 to your computer and use it in GitHub Desktop.
Save drusepth/5938924 to your computer and use it in GitHub Desktop.
Non-iterative prisoner's dilemma simulated with a basic genetic algorithm
Generation 1
Alice: 0.5
Bob: 0.5
Generation 2
Alice: 0.9136221749087309
Bob: 0.9048452243325479
Generation 3
Alice: 0.7525407199758025
Bob: 0.7001147600768378
Generation 4
Alice: 0.6023520588331079
Bob: 0.6319019029736853
Generation 5
Alice: 0.37688867843857393
Bob: 0.5681285046340958
Generation 6
Alice: 0.3239342915239891
Bob: 0.014626085061660354
Generation 7
Alice: 0
Bob: 0
Generation 8
Alice: 0
Bob: 0
[...snip...]
Generation 997
Alice: 0
Bob: 0
Generation 998
Alice: 0
Bob: 0
Generation 999
Alice: 0
Bob: 0
Generation 1000
Alice: 0
Bob: 0
So... world peace?
---
First encountered optimal solution at generation 2
Stopped evolving at generation 7
Final genes:
Alice decided to cooperate 0% of the time.
Bob decided to cooperate 0% of the time.
And faith in humanity is lost!
// Simulates the prisoner's dilemma with aa genetic algorithm powering the prisoner
// decision making, with the intent of evolving harmony and world peace.
// PRISONER'S DILEMMA:
//
// Create a prisoner who can make a decision based on a genetic trait.
var prisoner = function () {
var _public = {}, _protected = {};
_public.genes = {
cooperation_likeliness: 0.50 // %
};
_public.fitness = function (years_in_jail) {
return (1 / years_in_jail); // Less years in jail the better, of course
};
// Make a decision on whether to cooperate (true) or defect (false)
_public.decision = function () {
return Math.random() <= _public.genes.cooperation_likeliness;
};
// Breed with another prisoner (assuming the guards allow that kind of thing)
// and produce a new one
_public.breed_with = function(other_prisoner) {
var breed_type = Math.floor(Math.random() * 7);
// Sum and difference of parent cooperation likelinesses
var sum = _public.genes.cooperation_likeliness + other_prisoner.genes.cooperation_likeliness;
var delta = Math.abs(_public.genes.cooperation_likeliness - other_prisoner.genes.cooperation_likeliness);
var new_likeliness = 0.5; // Default value
switch (breed_type) {
case 0: // Average cooperation likeliness
new_likeliness = sum / 2;
break;
case 1: // Increase dad likeliness by delta
new_likeliness = _public.genes.cooperation_likeliness + delta;
break;
case 2: // Increase mom likeliness by delta
new_likeliness = other_prisoner.genes.cooperation_likeliness + delta;
break;
case 3: // Increase average likeliness by delta
new_likeliness = sum + delta;
break;
case 4: // Decrease dad likeliness by delta
new_likeliness = _public.genes.cooperation_likeliness - delta;
break;
case 5: // Decrease mom likeliness by delta
new_likeliness = other_prisoner.genes.cooperation_likeliness - delta;
break;
case 6: // Decrease average likeliness by delta
new_likeliness = sum - delta;
break;
default: // Disregard parents, go purely random
new_likeliness = Math.random();
break;
}
// Go ahead and throw in some random fuzzing for funsies
new_likeliness += (Math.random(2) - 1) / 5; // [-0.2, 0.2)
// And lastly, bound on [0, 1]
new_likeliness = Math.min(new_likeliness, 1);
new_likeliness = Math.max(new_likeliness, 0);
var child = prisoner();
child.genes.cooperation_likeliness = new_likeliness;
return child; // lol
};
return _public;
};
// Create a 0-player representation of the game that can be set up and played out
// without any further interaction.
var prisoners_dilemma = function(alice, bob) {
var _public = {}, _protected = {};
_protected.alice = alice;
_protected.bob = bob;
_protected.game_result = function () {
return {
alice_cooperates: _protected.alice.decision(),
bob_cooperates: _protected.bob.decision()
};
};
_public.total_years_served = function () {
var years_served = { alice: 0, bob: 0 };
var result = _protected.game_result();
if (result.alice_cooperates) {
years_served.alice = (result.bob_cooperates ? 1 : 3);
years_served.bob = (result.bob_cooperates ? 1 : 0);
} else {
years_served.alice = (result.bob_cooperates ? 0 : 2);
years_served.bob = (result.bob_cooperates ? 3 : 2);
}
return years_served;
};
return _public;
};
var num_generations = 1000;
// Create some initial prisoners
var alice = prisoner();
var bob = prisoner();
var best_alice = alice;
var best_bob = bob;
// We're optimizing for *least* amount of years in prison here, so lets just
// assume we can do better than ten thousand years of incarceration.
var best_alice_score = 10000; // years
var best_bob_score = 10000; // years
// What generation we reached the peak of evolution
var generation_down_the_drain = -1;
// What generation we first hit the optimal solution
var generation_in_the_sky = -1;
for (var g = 0; g < num_generations; g++) {
print("Generation " + (g + 1));
print("Alice: " + alice.genes.cooperation_likeliness);
print("Bob: " + bob.genes.cooperation_likeliness);
// Lets interrogate the prisoners 10 times (in different dimensions,
// of course), because while the genes guide their decisions, there is still
// some randomness in what they will actually say (because they're only human,
// after all!)
for (var i = 0; i < 10; i++) {
var interrogation = prisoners_dilemma(alice, bob);
var alice_score = alice.fitness(interrogation.total_years_served().alice);
var bob_score = bob.fitness(interrogation.total_years_served().bob);
// If Alice did her best this time...
if (alice_score < best_alice_score) {
best_alice_score = alice_score;
best_alice = alice;
}
// If Bob did his best this time...
if (bob_score < best_bob_score) {
best_bob_score = bob_score;
best_bob = bob;
}
// If we're at the optimal solution, make a note
if (alice_score == 1 && bob_score == 1 && generation_in_the_sky == -1) {
generation_in_the_sky = g + 1;
}
// Mark what generation it took to get to the "worst" situation (best for each party)
if (alice.genes.cooperation_likeliness == 0 && bob.genes.cooperation_likeliness == 0 && generation_down_the_drain == -1) {
generation_down_the_drain = g + 1;
}
}
// Otherwise, lets breed some new prisoners from the best dimension and spawn
// a new generation from them.
var child_alice = alice.breed_with(bob);
var child_bob = bob.breed_with(alice);
// Look at them, all grow'd up!
alice = child_alice;
bob = child_bob;
}
print("So... world peace?");
print("---");
print("First encountered optimal solution at " + (generation_in_the_sky == -1 ? "NEVER!" : "generation " + generation_in_the_sky));
print("Stopped evolving at generation " + generation_down_the_drain);
print("Final genes:");
print("Alice decided to cooperate " + (alice.genes.cooperation_likeliness * 100) + "% of the time.");
print("Bob decided to cooperate " + (bob.genes.cooperation_likeliness * 100) + "% of the time.");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment