2016-01-20 10 views
7

Ich brauche eine Java Version des iterierten Gefangenendilemma mit Repast Simphony als Simulator zu entwickeln.Unerwartete Ergebnisse mit Repast Simphony

Die Ideen ist, dass jeder Player ist ein Mittel, und wir haben ein n x n Raster von Player, die nicht verschoben werden können. Jede Player muss mit 4 Nachbarn (Norden, Süden, Westen und Osten) spielen, um die beste Strategie zu finden, basierend auf dem Ausgang der 4 verschiedenen Spiele in jeder Runde.

Da gibt es keine eingebauten System-Nachrichten zwischen Agenten auszutauschen in Repast Simphony, ich hatte eine Art der Problemumgehung implementieren mit Agenten sync (A gegen B und B vs A behandeln sollte als das gleiches zählt Runde, deshalb müssen sie synchronisiert werden).

Dies wird durch Sehen in jeder Runde als getan:

  • Playeri für jeden der 4 Gegner den nächsten Schritt wählt
  • Playeri sendet den richtigen Zug zu jedem der 4 Gegner
  • Playeri wartet für jeden der 4 Gegner antworten

Von meinem Verständnis von Repast Simphony, geplante Methoden sind sequentiell (keine Agenten-Ebene Parallelität), was bedeutet, dass ich gezwungen bin, das Warten auf eine andere Methode als die senden (mit geringerer Pritorität geplant zu gewährleisten dass alle Sendungen abgeschlossen sind, bevor die Wartezeiten beginnen).

Das Problem hier ist, dass, obwohl alle 4 erwarteten Nachrichten empfangen (zumindest das ist, was gedruckt wird), sobald die Wartungsmethode startet es weniger als 4 empfangene Elemente berichtet.

Hier ist die von Player Klasse genommen Code:

// myPoint is the location inside the grid (unique, agents can't move and only one per cell is allowed) 
public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    result = prime * result + ((myPoint == null) ? 0 : myPoint.hashCode()); 
    return result; 
} 

// Returns enemy's choice in the previous round 
private byte getLastPlay(Player enemy) { 
    return (neighbors.get(enemy)[1]) ? COOPERATE : DEFECT; 
} 

// Elements are saved as (player, choice) 
private void receivePlay(Player enemy, byte play) { 
    System.out.println(this + " receives (" + play + ") from " + enemy); 
    while (!playSharedQueue.add(new Object[] { enemy, play })){ 
     // This doesn't get printed, meaning that the insertion is successful! 
     System.out.println(this + " failed inserting"); 
    } 
} 

@ScheduledMethod(start = 1, interval = 1, priority = 10) 
public void play() { 
    System.out.println(this + " started playing"); 
    // Clear previous plays 
    playSharedQueue.clear(); 
    for (Player enemy : neighbors.keySet()) { 
     // properties[0] = true if we already played together 
     // properties[1] = true if enemy choose to cooperate on the previous round 
     Boolean[] properties = neighbors.get(enemy); 
     // Choose which side we take this time 
     byte myPlay; 
     if (properties[0]) { 
      // First time that we play, use memory-less strategy 
      myPlay = (Math.random() <= strategy[0]) ? COOPERATE : DEFECT; 
      // Report that we played 
      properties[0] = false; 
      neighbors.put(enemy, properties); 
     } else { 
      // We already had a round, use strategy with memory 
      byte enemyLastPlay = enemy.getLastPlay(this); 
      // Choose which side to take based on enemy's previous decision 
      myPlay = (Math.random() <= strategy[(enemyLastPlay) == COOPERATE ? 1 : 2]) ? COOPERATE : DEFECT; 
     } 
     // Send my choice to the enemy 
     System.out.println(this + " sent (" + myPlay + ") to " + enemy); 
     enemy.receivePlay(this, myPlay); 
    } 
} 

// Waits for the results and processes them 
@ScheduledMethod(start = 1, interval = 1, priority = 5) 
public void waitResults() { 
    // Clear previous score 
    lastPayoff = 0; 
    System.out.println(this + " waits for results [" + playSharedQueue.size() + "]"); 
    if (playSharedQueue.size() != 4) { 
     // Well, this happens on the first agent :(
     System.exit(1); 
    } 
    // ... process ... 
} 

Hier ist die Ausgabe der Konsole, so dass Sie, dass alles, was gesendet werden sehen scheint und erhalten ohne Probleme (ein 3 x 3 Raster verwendet):

Player[2, 0] started playing 
Player[2, 0] sent (0) to Player[2, 1] 
Player[2, 1] receives (0) from Player[2, 0] 
Player[2, 0] sent (0) to Player[2, 2] 
Player[2, 2] receives (0) from Player[2, 0] 
Player[2, 0] sent (0) to Player[0, 0] 
Player[0, 0] receives (0) from Player[2, 0] 
Player[2, 0] sent (0) to Player[1, 0] 
Player[1, 0] receives (0) from Player[2, 0] 
Player[1, 2] started playing 
Player[1, 2] sent (1) to Player[2, 2] 
Player[2, 2] receives (1) from Player[1, 2] 
Player[1, 2] sent (1) to Player[0, 2] 
Player[0, 2] receives (1) from Player[1, 2] 
Player[1, 2] sent (1) to Player[1, 0] 
Player[1, 0] receives (1) from Player[1, 2] 
Player[1, 2] sent (1) to Player[1, 1] 
Player[1, 1] receives (1) from Player[1, 2] 
Player[0, 2] started playing 
Player[0, 2] sent (1) to Player[2, 2] 
Player[2, 2] receives (1) from Player[0, 2] 
Player[0, 2] sent (1) to Player[0, 0] 
Player[0, 0] receives (1) from Player[0, 2] 
Player[0, 2] sent (1) to Player[0, 1] 
Player[0, 1] receives (1) from Player[0, 2] 
Player[0, 2] sent (1) to Player[1, 2] 
Player[1, 2] receives (1) from Player[0, 2] 
Player[0, 1] started playing 
Player[0, 1] sent (1) to Player[2, 1] 
Player[2, 1] receives (1) from Player[0, 1] 
Player[0, 1] sent (1) to Player[0, 0] 
Player[0, 0] receives (1) from Player[0, 1] 
Player[0, 1] sent (1) to Player[0, 2] 
Player[0, 2] receives (1) from Player[0, 1] 
Player[0, 1] sent (1) to Player[1, 1] 
Player[1, 1] receives (1) from Player[0, 1] 
Player[1, 0] started playing 
Player[1, 0] sent (0) to Player[2, 0] 
Player[2, 0] receives (0) from Player[1, 0] 
Player[1, 0] sent (0) to Player[0, 0] 
Player[0, 0] receives (0) from Player[1, 0] 
Player[1, 0] sent (0) to Player[1, 1] 
Player[1, 1] receives (0) from Player[1, 0] 
Player[1, 0] sent (0) to Player[1, 2] 
Player[1, 2] receives (0) from Player[1, 0] 
Player[1, 1] started playing 
Player[1, 1] sent (0) to Player[2, 1] 
Player[2, 1] receives (0) from Player[1, 1] 
Player[1, 1] sent (0) to Player[0, 1] 
Player[0, 1] receives (0) from Player[1, 1] 
Player[1, 1] sent (0) to Player[1, 0] 
Player[1, 0] receives (0) from Player[1, 1] 
Player[1, 1] sent (0) to Player[1, 2] 
Player[1, 2] receives (0) from Player[1, 1] 
Player[2, 2] started playing 
Player[2, 2] sent (0) to Player[2, 0] 
Player[2, 0] receives (0) from Player[2, 2] 
Player[2, 2] sent (0) to Player[2, 1] 
Player[2, 1] receives (0) from Player[2, 2] 
Player[2, 2] sent (0) to Player[0, 2] 
Player[0, 2] receives (0) from Player[2, 2] 
Player[2, 2] sent (0) to Player[1, 2] 
Player[1, 2] receives (0) from Player[2, 2] 
Player[0, 0] started playing 
Player[0, 0] sent (1) to Player[2, 0] 
Player[2, 0] receives (1) from Player[0, 0] 
Player[0, 0] sent (1) to Player[0, 1] 
Player[0, 1] receives (1) from Player[0, 0] 
Player[0, 0] sent (1) to Player[0, 2] 
Player[0, 2] receives (1) from Player[0, 0] 
Player[0, 0] sent (1) to Player[1, 0] 
Player[1, 0] receives (1) from Player[0, 0] 
Player[2, 1] started playing 
Player[2, 1] sent (1) to Player[2, 0] 
Player[2, 0] receives (1) from Player[2, 1] 
Player[2, 1] sent (1) to Player[2, 2] 
Player[2, 2] receives (1) from Player[2, 1] 
Player[2, 1] sent (1) to Player[0, 1] 
Player[0, 1] receives (1) from Player[2, 1] 
Player[2, 1] sent (1) to Player[1, 1] 
Player[1, 1] receives (1) from Player[2, 1] 
Player[2, 2] waits for results [1] 

Wie Sie in der letzten Zeile sehen können, ist playSharedQueue.size()1 und ich verstehe wirklich nicht warum.

Wenn Methoden Aufruf sind sequenzielle die waitResults() methos is invoked after the 9 play() `Hinrichtungen, und da jede der richtig sendet 4-Nachrichten, kann ich keinen Grund finden, warum diese Größe noch ist 1.

Of Natürlich ist alles sequentiell bedeutet, dass es keine synchronization Probleme gibt, auch wenn ich das gleiche Problem mit LinkedBlockingQueue anstelle von HashSet hatte.

Haben Sie einen Hinweis darauf?

+0

Wenn playSharedQueue lokal für Player 'feind.receivePlay (this, myPlay) ist;' hat nur ein Objekt [] in playSharedQueue und es wird immer 1 sein. Können Sie die gesamte Player-Klasse veröffentlichen. –

Antwort

2

Nach einiger Zeit habe ich den Code wieder geöffnet und ich fand heraus, dass ich einen einfachen, aber schweren Fehler machen:

@ScheduledMethod(start = 1, interval = 1, priority = 10) 
public void play() { 
    System.out.println(this + " started playing"); 
    // Clear previous plays 
    playSharedQueue.clear(); 

Die playSharedQueue.clear(); ausgeführt wird, um die vorherigen Ergebnisse zu räumen, aber da Anrufungen sind sequenzielle der zweite Spieler wird es rufen, nachdem der erste Spieler ihm sein Spiel geschickt hat, so dass das Spiel verworfen wird.

Das Verschieben dieser Zeile am Ende von waitResults löste es.

Verwandte Themen