Java 使用Repast Simphony的意外结果
我需要使用Repast Simphony作为模拟器开发迭代囚徒困境的Java版本 其思想是每个Java 使用Repast Simphony的意外结果,java,repast-simphony,Java,Repast Simphony,我需要使用Repast Simphony作为模拟器开发迭代囚徒困境的Java版本 其思想是每个玩家都是一个代理,我们有一个nxn的玩家网格,无法移动。每个玩家必须与4个邻居(北部、南部、西部和东部)进行游戏,根据每轮4场不同游戏的结果找到最佳策略 由于在Repast Simphony中没有一个内置的系统来在代理之间交换消息,所以我不得不实施一些解决方案来处理代理的同步(a对B和B对a应该算作同一轮,这就是为什么它们需要同步) 通过将每一轮视为: 玩家我为4个敌人中的每一个选择下一步 玩家我向4
玩家
都是一个代理,我们有一个nxn
的玩家
网格,无法移动。每个玩家
必须与4个邻居(北部、南部、西部和东部)进行游戏,根据每轮4场不同游戏的结果找到最佳策略
由于在Repast Simphony中没有一个内置的系统来在代理之间交换消息,所以我不得不实施一些解决方案来处理代理的同步(a对B和B对a应该算作同一轮,这就是为什么它们需要同步)
通过将每一轮视为:
我为4个敌人中的每一个选择下一步玩家
我向4个敌人中的每一个发送正确的移动玩家
我等待4个敌人中的每一个回复Player
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 ...
}
正如您在最后一行中看到的,playSharedQueue.size()
是1
,我真的不明白为什么
如果方法调用是连续的,那么waitResults()Methodos将在9次执行之后调用,并且假设每个方法都正确地发送了4条消息,那么我找不到该大小仍然为1的原因
当然,所有内容都是连续的意味着没有同步问题
,即使我使用LinkedBlockingQueue
而不是HashSet
时遇到同样的问题
你们对此有什么提示吗?过了一段时间,我再次打开代码,发现我犯了一个简单但严重的错误:
@ScheduledMethod(start = 1, interval = 1, priority = 10)
public void play() {
System.out.println(this + " started playing");
// Clear previous plays
playSharedQueue.clear();
playSharedQueue.clear()代码>被执行以清除先前的结果,但是由于调用是连续的,第二个玩家将在第一个玩家向他发送游戏后调用它,因此游戏被丢弃
移动waitResults
末尾的那条线解决了问题。如果playSharedQueue是玩家敌人的本地玩家。receivePlay(这是我的游戏)代码>将只有一个对象[]进入playSharedQueue,并且始终为1。你能发布整个玩家类吗。
@ScheduledMethod(start = 1, interval = 1, priority = 10)
public void play() {
System.out.println(this + " started playing");
// Clear previous plays
playSharedQueue.clear();