You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Otree中运行两个不同组规模并行应用时的组矩阵分配错误

如何解决Otree中运行两个不同组规模并行应用时的组矩阵分配错误

嘿,我来帮你拆解问题、搞定这个报错!

问题根源

你遇到的The matrix of integers either has duplicate or missing elements错误,核心原因其实很简单:在并行运行的App里,每个App的subsession默认包含整个Session的所有玩家——哪怕你用is_displayed()把非目标玩家的页面隐藏了,subsession依然认定这些玩家属于自己。而set_group_matrix()有个硬要求:传入的矩阵必须覆盖当前subsession的所有玩家,不能只塞你需要的那部分。你之前只把目标玩家放进矩阵,漏掉了其他玩家,自然会触发“缺失元素”的报错。

另外你不用纠结“传玩家对象还是ID”的问题,Otree两种都支持,问题本质是矩阵没覆盖全所有玩家。

解决方案

解决思路就一个:把当前subsession的所有玩家都纳入组矩阵。对于那些不属于当前App的玩家,我们把他们单独分到1人小组里就行——反正他们看不到当前App的页面,完全不影响正常流程。

步骤1:修改并行App的creating_session函数

以你需要6人组的quiz App为例,修改后的代码如下:

def creating_session(subsession):
    if subsession.round_number == 1:  # 只在第一轮分配组,避免重复操作
        # 筛选当前App的目标玩家
        target_players = [
            p for p in subsession.get_players()
            if p.participant.group_assignment == 'quiz'
        ]
        # 筛选不属于当前App的非目标玩家
        non_target_players = [
            p for p in subsession.get_players()
            if p.participant.group_assignment != 'quiz'
        ]
        
        # 目标玩家按6人一组分组
        target_groups = [target_players[i:i+6] for i in range(0, len(target_players), 6)]
        # 非目标玩家单独分到1人组(不参与当前App流程)
        non_target_groups = [[p] for p in non_target_players]
        
        # 合并成覆盖所有玩家的完整矩阵
        full_group_matrix = target_groups + non_target_groups
        
        subsession.set_group_matrix(full_group_matrix)

对应的,需要4人组的quiz_CP App代码改成这样:

def creating_session(subsession):
    if subsession.round_number == 1:
        target_players = [
            p for p in subsession.get_players()
            if p.participant.group_assignment == 'quiz_CP'
        ]
        non_target_players = [
            p for p in subsession.get_players()
            if p.participant.group_assignment != 'quiz_CP'
        ]
        
        # 目标玩家按4人一组分组
        target_groups = [target_players[i:i+4] for i in range(0, len(target_players), 4)]
        non_target_groups = [[p] for p in non_target_players]
        
        full_group_matrix = target_groups + non_target_groups
        subsession.set_group_matrix(full_group_matrix)

步骤2:(可选)优化初始分组的满员适配

如果你希望每组都是满员的(避免出现5人或3人的不满小组),可以调整初始分配玩家数量的逻辑,让分到quiz的玩家数是6的倍数,分到quiz_CP的是4的倍数:

import random

def creating_session(subsession):
    if subsession.round_number == 1:
        players = subsession.get_players()
        total_players = len(players)
        
        # 优先匹配60%比例,同时确保两组人数分别是6和4的倍数
        target_quiz = int(total_players * 0.6)
        # 调整到最近的6的倍数
        target_quiz = round(target_quiz / 6) * 6
        # 微调确保剩余人数能被4整除
        while (total_players - target_quiz) % 4 != 0 and target_quiz > 0:
            target_quiz -=6
        # 兜底:如果调整到0,重新找符合条件的最大值
        if target_quiz ==0:
            target_quiz = max([x for x in range(0, total_players,6) if (total_players -x) %4 ==0])
        
        split_indices = {
            'quiz': target_quiz,
            'quiz_CP': total_players - target_quiz,
        }
        
        group_assignment = (
            ['quiz'] * split_indices['quiz'] +
            ['quiz_CP'] * split_indices['quiz_CP']
        )
        random.shuffle(group_assignment)
        for player, group in zip(players, group_assignment):
            player.participant.group_assignment = group
            print(f"Assigned {player.participant.code} to {group}")

如果你对满员没有硬性要求,这步可以跳过,直接用你原来的随机分配逻辑就行。

修改后效果验证

调整完之后:

  • 目标玩家会按你需要的6/4人组成正常小组,参与App流程;
  • 非目标玩家被分到1人小组,他们的is_displayed()返回False,完全看不到当前App的页面,不会干扰任何流程;
  • 组矩阵覆盖了当前subsession的所有玩家,没有缺失或重复元素,Otree就不会再抛出报错了。

备注:内容来源于stack exchange,提问作者Zahra Hajbaraty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 12:49:31