MiniZinc语法错误求助:赛事赛程约束建模问题排查
体育赛事赛程规划MiniZinc语法错误排查与修复
问题背景
规划20支队伍的体育赛事赛程:
- 每轮14支队伍参赛、6支轮休
- 每队总计14场比赛
- 同一项目参赛次数不超过2次
- 尽量均衡各队休息间隔
使用MiniZinc构建约束模型时,遇到语法错误:MiniZinc: syntax error: syntax error, unexpected [, expecting end of file,转无BOM UTF-8格式后问题仍存在。
错误原因分析
数组声明语法错误:
原代码中var 1..N_ROUNDS: RoundOfMatch [m in 1..N_MATCHES];不符合MiniZinc数组声明规范,正确的数组变量声明格式应为array[索引范围] of var 类型: 变量名;。count函数用法错误:
MiniZinc的count函数用于统计数组中某个值的出现次数,而非遍历集合统计条件满足的次数。原代码中count(m in 1..N_MATCHES)(...)的写法不合法,需替换为sum + bool2int的组合来统计满足条件的元素数量。
修正后的完整代码
int: N_MATCHES = 140; int: N_TEAMS = 20; int: N_ROUNDS = 20; int: N_SPORTS = 7; % 需补充具体的SportOf和TeamsOf输入数据 array[1..N_MATCHES] of int: SportOf; array[1..N_MATCHES] of set of int: TeamsOf; % 修正数组变量声明语法 array[1..N_MATCHES] of var 1..N_ROUNDS: RoundOfMatch; % A. 足球(SportOf=1)仅在第1-10轮,接力赛(SportOf=3)仅在第11-20轮 constraint sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 1 /\ RoundOfMatch[m] > 10)) = 0 /\ sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 3 /\ RoundOfMatch[m] < 11)) = 0; % B1. 第1-10轮:每场包含2场足球(1),1场篮球(4)、排球(2)、标签赛(6)、目标球(7)、夺旗赛(5) constraint forall(r in 1..10) ( sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 1 /\ RoundOfMatch[m] == r)) = 2 /\ sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 4 /\ RoundOfMatch[m] == r)) = 1 /\ sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 2 /\ RoundOfMatch[m] == r)) = 1 /\ sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 6 /\ RoundOfMatch[m] == r)) = 1 /\ sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 7 /\ RoundOfMatch[m] == r)) = 1 /\ sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 5 /\ RoundOfMatch[m] == r)) = 1 ); % B2. 第11-20轮:每场包含2场接力赛(3),1场篮球(4)、排球(2)、标签赛(6)、目标球(7)、夺旗赛(5) constraint forall(r in 11..20) ( sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 3 /\ RoundOfMatch[m] == r)) = 2 /\ sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 4 /\ RoundOfMatch[m] == r)) = 1 /\ sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 2 /\ RoundOfMatch[m] == r)) = 1 /\ sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 6 /\ RoundOfMatch[m] == r)) = 1 /\ sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 7 /\ RoundOfMatch[m] == r)) = 1 /\ sum(m in 1..N_MATCHES) (bool2int(SportOf[m] == 5 /\ RoundOfMatch[m] == r)) = 1 ); % 同一队伍在同一轮中最多参加1场比赛 constraint forall(r in 1..N_ROUNDS, t in 1..N_TEAMS) ( sum(m in 1..N_MATCHES) (bool2int(t in TeamsOf[m] /\ RoundOfMatch[m] == r)) <= 1 ); % 休息间隔优化:最小化连续参赛次数 array[1..N_TEAMS, 1..N_ROUNDS] of var bool: Play; constraint forall(t in 1..N_TEAMS, r in 1..N_ROUNDS) ( Play[t,r] <-> exists(m in 1..N_MATCHES)( t in TeamsOf[m] /\ RoundOfMatch[m] == r ) ); array[1..N_TEAMS, 1..(N_ROUNDS-1)] of var 0..1: consecutive; constraint forall(t in 1..N_TEAMS, r in 1..(N_ROUNDS-1)) ( consecutive[t,r] = bool2int( Play[t,r] /\ Play[t,r+1] ) ); % 补充每队总计14场比赛的约束 constraint forall(t in 1..N_TEAMS) ( sum(r in 1..N_ROUNDS) (bool2int(Play[t,r])) = 14 ); % 补充同一项目参赛次数不超过2次的约束 constraint forall(t in 1..N_TEAMS, s in 1..N_SPORTS) ( sum(m in 1..N_MATCHES) (bool2int(t in TeamsOf[m] /\ SportOf[m] == s)) <= 2 ); solve minimize sum(t in 1..N_TEAMS, r in 1..(N_ROUNDS-1))( consecutive[t,r] ); output [ "Success: RoundOfMatch = [", concat([ show(RoundOfMatch[m]) ++ if m < N_MATCHES then ", " else "" endif | m in 1..N_MATCHES ]), "]\n" ];
额外注意事项
- 需为
SportOf和TeamsOf数组补充具体输入数据,例如每一场比赛对应的项目和参赛队伍集合,否则模型无法运行。 - 原模型未覆盖每队14场比赛和同一项目参赛不超过2次的需求,上述修正代码已补充对应的约束条件。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

