Java – unexpected results using repast Simphony

I need to use repast Simphony as a simulator to develop the Java version of the iterative prisoner's dilemma

The idea is that each player is an agent and we have an n x n player grid that can't be moved Each player must play with 4 neighbors (North, South, West and East) to find the best strategy according to the results of 4 different games in each round

Since there is no built-in system to exchange messages between agents in repast Simphony, I have to implement some solution to deal with agent synchronization (a vs B and B vs a should be counted as the same round, which is why they need to synchronize)

This is done by treating each round as:

>Player I select the next action for each of the 4 enemies > player I send the correct action to each of the 4 enemies > player I wait for each of the 4 enemies to reply

According to my understanding of repast Simphony, the scheduled method is sequential (there is no agent level parallelism), which means that I am forced to wait in a different way from the sending method (arranged with a lower priority to ensure that all transmissions are completed) before starting the waiting)

The problem here is that although all four expected messages are received (at least this is the printed content), once the waiting method starts, it reports fewer than four receiving elements

This is the code obtained from the player class:

// 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,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 ...
}

This is console output, so you can see that everything seems to be sent and received without problems (using a 3 x 3 grid):

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,2]
Player[2,2] receives (0) from Player[2,0] sent (0) to Player[0,0]
Player[0,0] receives (0) from Player[2,0] sent (0) to Player[1,0]
Player[1,2] started playing
Player[1,2] sent (1) to Player[2,2] receives (1) from Player[1,2]
Player[1,2] sent (1) to Player[0,2]
Player[0,2] sent (1) to Player[1,0] receives (1) from Player[1,1]
Player[1,1] receives (1) from Player[1,2] started playing
Player[0,2] receives (1) from Player[0,0] receives (1) from Player[0,1]
Player[0,1] receives (1) from Player[0,1] started playing
Player[0,1] sent (1) to Player[2,1] sent (1) to Player[0,1] sent (1) to Player[1,0] started playing
Player[1,0] receives (0) from Player[1,1] receives (0) from Player[1,2] receives (0) from Player[1,1] started playing
Player[1,1] sent (0) to Player[2,1] sent (0) to Player[0,1] sent (0) to Player[1,2] started playing
Player[2,2] sent (0) to Player[2,2] sent (0) to Player[0,2] sent (0) to Player[1,0] started playing
Player[0,0] sent (1) to Player[2,0] sent (1) to Player[0,0] sent (1) to Player[1,1] started playing
Player[2,0] receives (1) from Player[2,2] receives (1) from Player[2,1] receives (1) from Player[2,2] waits for results [1]

As you can see in the last line, playsharedqueue Size () is 1. I really don't understand why

If the method call is sequential, then the waitResults () method is called after 9play () 'execution, and assuming that each of the 4 messages is sent correctly, I can not find the reason that the size is still 1.

Of course, all sequences mean no synchronization problems, even if I use linkedblockingqueue instead of HashSet

Do you have any hints?

Solution

After a while, I opened the code again and found that I made a simple and serious error:

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

playSharedQueue. clear(); The execution is done to clear the previous result, but since the call is continuous, the second game player will call the game player after he sends his game to him, so as to abandon the game.

Moving the row at the end of waitresults resolves it

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>