当前位置: 首页 > 知识库问答 >
问题:

使用Repast Simphony的意外结果

燕和裕
2023-03-14

我需要使用Repast Simphony作为模拟器开发迭代囚徒困境的Java版本。

其思想是,每个玩家都是一个代理,我们有一个nxn网格,由玩家组成,无法移动。每个玩家必须与4个邻居(北部、南部、西部和东部)比赛,根据每轮4场不同比赛的结果找到最佳策略。

由于在Repast Simphony中没有一个内置的系统来在代理之间交换消息,所以我不得不实施某种解决方案来处理代理的同步(a对B和B对a应该算作同一轮,这就是为什么它们需要同步)。

通过将每一轮视为:

  • 玩家我为4个敌人中的每一个选择下一步
  • 玩家我向四个敌人中的每一个发送正确的移动
  • Player我等待4个敌人中的每一个回复

根据我对Repast Simphony的理解,计划的方法是顺序的(没有代理级别的并行性),这意味着我不得不使用与发送不同的方法进行等待(计划的优先级较低,以确保在开始等待之前完成所有发送)。

这里的问题是,尽管收到了所有4条预期消息(至少这是打印出来的消息),但一旦waiting方法启动,它报告的接收元素就少于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,我真的不明白为什么。

如果方法调用是顺序的,则在9play()执行之后调用wait结果()方法,并且考虑到每个方法都正确发送了4条消息,我找不到该大小仍然为1的原因。

当然,一切都是顺序的意味着没有同步问题,即使我使用LinkedBlockingQueue而不是HashSet遇到了同样的问题。

你们对此有什么提示吗?


共有1个答案

郑俊美
2023-03-14

过了一段时间,我再次打开代码,发现我犯了一个简单但严重的错误:

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

playSharedQueue。清除() 被执行以清除之前的结果,但由于调用是连续的,第二个玩家将在第一个玩家向他发送游戏后调用它,因此游戏被丢弃。

wait结果末尾移动该行解决了这个问题。

 类似资料:
  • 在我看来,我的缓冲区包含关于最后一个数据包步骤(路由器->my home)的信息,这些信息解释了为什么TTL值是254以及为什么我用Traceroute找到了相同的两个IP: $>traceroute qwant.com traceroute to qwant.com(194.187.168.99),30跳最大,60字节数据包 172.17.0.1(172.17.0.1)0.026 ms 0.01

  • 问题内容: 我有一个名为“单词”的列表,其中包含字符串。在这里Log.i可以很好地处理“ word”标签,但不会执行“step”语句。似乎如果条件不能很好地工作。尽管“单词”列表包含类似的字符串,但这种方法永远不会进入它。怎么了 请帮助 问题答案: 您需要使用,不。检查两个Object引用是否引用相同的内容Object: 从部分15.21.3引用相等运算符==和=!在的Java语言规范3.0: 虽

  • 我正在尝试解析从Movie DB返回的JSON数据。我收到一个错误,告诉我我收到以下错误: MovieReq.Open('get','https://api.themoviedb.org/3/movie/299537?api_key=',false); 我还有其他XMLHttpRequests可以很好地返回JSON数据。这些请求使用API的discover函数。 这是产生问题的函数 {“成人”:f

  • 问题内容: 我正在使用python 3.8.2和bs4 BeautifulSoup。我试图找到一个标记的所有实例,并在结果集中列出每个实例,每行一个。但是,返回的结果集包含的行数多于网站的原始内容。这是因为结果集的第一行包含标记的所有实例。接下来的行包含除第一个实例以外的所有实例,第三行包含除第一个和第二个实例以外的所有实例,依此类推,以此类推,并包含结果集的其余部分。 这是代码: 我如何获得它,

  • 问题内容: 给定一个变量,该变量包含巴黎时区的日期时间2000-01-01 00:01(冬季afaik中为UTC + 2): 我希望转换为UTC会导致日期时间为1999-12-31 22:01,但是却得到了: 我想念什么? 谢谢 问题答案: 不幸的是 ,在许多时区使用标准构造函数的参数“不起作用” 。 但是对于没有夏令时转换的时区来说是安全的,例如UTC: 您会注意到: “ LMT + 0:09:

  • 我有以下代码: 为什么它会打印Java流?