我需要使用 Repast Simphony 作为模拟器来开发 Java 版本的 Iterated Prisoner Dilemma 。
我们的想法是每个Player
都是代理商,我们的n x n
网格Player
无法移动。每个Player
必须与4个邻居(北部,南部,西部和东部)进行比赛,根据每轮4场不同比赛的结果找到最佳策略。
由于 Repast Simphony 中的代理商之间没有内置系统来交换消息,因此我必须实施某种解决方法来处理代理商问题。同步(A对B和B对A应该算作同一轮,这就是他们需要同步的原因)。
这是通过将每一轮视为:
来完成的Player
我为4个敌人中的每一个选择下一步行动Player
我向4个敌人中的每一个发送正确的动作Player
我等待4个敌人中的每一个回复根据我对 Repast Simphony 的理解,预定的方法是顺序的(没有代理级并行),这意味着我被迫以与发送方法不同的方法进行等待(以较低的优先级安排,以确保在开始等待之前完成所有发送。)
这里的问题是,尽管收到了所有4条预期的消息(至少这是打印的消息),一旦等待方法开始,它报告的接收元素少于4个。
以下是Player
类:
// 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 ...
}
这是控制台输出,因此您可以看到所有内容似乎都没有问题地发送和接收(使用3 x 3
网格):
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]
正如您在最后一行中所看到的,playSharedQueue.size()
是1
,我真的不明白为什么。
如果方法调用是顺序的waitResults()methos is invoked after the 9
play()`执行,并且假设每个正确发送4条消息,我找不到该大小仍为1的原因。
当然,所有顺序意味着没有synchronization
问题,即使我使用LinkedBlockingQueue
而不是HashSet
遇到同样的问题。
你们对此有任何暗示吗?
答案 0 :(得分:2)
一段时间后,我再次打开代码,发现我做了一个简单而严重的错误:
@ScheduledMethod(start = 1, interval = 1, priority = 10)
public void play() {
System.out.println(this + " started playing");
// Clear previous plays
playSharedQueue.clear();
执行playSharedQueue.clear();
以清除之前的结果,但由于调用是连续的,第二个玩家将在第一个玩家向他发送他的游戏后调用它,以便该游戏被丢弃。
在waitResults
的末尾移动该行解决了它。