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

MiniZinc中简化含大量零的LB参数数组的方法问询

时间表模型中简化LB参数定义的实现方法

问题背景

开发时间表模型时,需定义4行66列的参数数组LB,但绝大多数元素为0,手动输入效率极低。改用硬编码的等效约束虽能实现需求,但数据与模型耦合,不利于泛化和复用。希望采用如下简洁形式定义LB,询问可行性及调整方法:

subjclass = [{ITA, ING}, {CHI, SCI, DIS, DIR}, {ITA, ING, MAT}, {ITA, ING, LELE}];
LB = [       {2,   1},   {0,   0,   1,   0},   {2,   1,   2},   {2,   1,   1}];

可行性说明

完全可以实现这种简洁定义方式,核心思路是利用subjclass中科目集合的顺序与LB数值列表的顺序一一对应,通过关联映射生成完整的LB数组,同时保留原约束逻辑的通用性。

具体调整步骤

1. 替换LB的定义形式

将原二维数组改为与subjclass结构匹配的列表集合(用列表而非集合,保证顺序对应):

array[class] of list of int: LB_simple = [
    [2, 1],     % 对应subjclass[1]的{ITA, ING}
    [0, 0, 1, 0], % 对应subjclass[2]的{CHI, SCI, DIS, DIR}
    [2, 1, 2],  % 对应subjclass[3]的{ITA, ING, MAT}
    [2, 1, 1]   % 对应subjclass[4]的{ITA, ING, LELE}
];

2. 生成完整LB数组

通过循环遍历,根据subjclass和LB_simple的映射关系自动填充LB,非目标科目默认设为0:

array[class, allsubjects] of 0..3: LB = array2d(class, allsubjects, [
    let {
        set of allsubjects: subjs = subjclass[i],
        list of int: lbs = LB_simple[i],
        array[subjs] of int: subj_to_lb = array1d(subjs, lbs)
    } in
    if k in subjs then subj_to_lb[k] else 0 endif
    | i in class, k in allsubjects
]);

3. 保留原约束逻辑

原约束无需修改,生成的LB数组与手动定义的结构完全一致:

constraint forall (i in class, k in subjclass[i]) (
    sum([tbl[i,j] | j in weektime where subjects[i,j] == k]) >= LB[i,k]
);

4. 处理特殊等式约束

如果需要像原替代约束中第4类LELE的等式约束(=1而非>=1),可单独补充:

constraint sum([tbl[4,j] | j in weektime where subjects[4,j] == LELE]) == 1;

若需更通用的约束类型区分,可扩展定义结构:

array[class] of list of tuple(allsubjects, int, string): LB_constraints = [
    [(ITA, 2, ">="), (ING, 1, ">=")],
    [(DIS, 1, ">=")],
    [(ITA, 2, ">="), (ING, 1, ">="), (MAT, 2, ">=")],
    [(ITA, 2, ">="), (ING, 1, ">="), (LELE, 1, "==")]
];

constraint forall (i in class, c in LB_constraints[i]) (
    let {
        allsubjects: k = c.1,
        int: val = c.2,
        string: op = c.3
    } in
    if op == ">=" then
        sum([tbl[i,j] | j in weektime where subjects[i,j] == k]) >= val
    elseif op == "==" then
        sum([tbl[i,j] | j in weektime where subjects[i,j] == k]) == val
    endif
);

这种方式彻底解耦数据与模型,无需维护大数组LB。

完整调整后代码示例

include "globals.mzn";

enum weektime = {M1,M2,M3,M4,M5,M6,T1,T2,T3,T4,T5,T6,W1,W2,W3,W4,W5,W6,TH1,TH2,TH3,TH4,TH5,TH6,F1,F2,F3,F4,F5,F6,S1,S2,S3,S4};

enum allsubjects = {BIO, CHA, CHI, CHO, CMAT, DES, DIR, DIS, EFI, ELE, EMM, FIS, GCA, GEE, GEO, GEP, IGI, INF, ING, IPM, ITA, LBIO, LCHA, LCHI, LCHO, LDES, LDIS, LELE, LFIS, LGCA, LGEE, LGEP, LIGI, LINF, LIPM, LLTE, LPCI, LSA, LSIS, LSTA, LTCH, LTE, LTEL, LTLC, LTMA, LTMM, LTOP, LTPS, LTTI, MAT, PCI, REL, ROB, SCI, SIS, STA, STO, TCH, TEL, TLC, TMA, TMM, TOP, TPS, TTI, n};

int: nc = 4;
set of int: class = 1..nc;

array[class, weektime] of allsubjects: subjects;
subjects = 
[| EFI, EFI, LIGI, LBIO, LBIO, n, MAT, MAT, BIO, ITA, IGI, n, ING, REL, ITA, LCHO, LCHO, IGI, LCHA, LCHA, CHO, IGI, MAT, ING, ING, BIO, ITA, ITA, CHA, MAT, ITA, ITA, LIGI, LIGI
| DIS, DIS, LCHI, MAT, SCI, ITA, MAT, ITA, ITA, SCI, DIR, n, ITA, LDIS, MAT, CHI, LSTA, LSTA, CHI, ING, DIR, LFIS, EFI, EFI, STA, ITA, ING, FIS, MAT, n, REL, ING, ITA, FIS
| REL, MAT, SIS, ITA, TPS, ING, ITA, ITA, INF, MAT, ING, n, ROB, ROB, ING, MAT, ITA, n, ITA, INF, LTPS, LTPS, MAT, TEL, LSIS, LSIS, ITA, LINF, LINF, LINF, LTEL, LTEL, EFI, EFI
| TMA, LTE, REL, MAT, LTTI, LTTI, MAT, TTI, TTI, ITA, LELE, n, ITA, MAT, LTTI, ING, LELE, LELE, ITA, EFI, EFI, LTMA, TTI, n, LTMA, LTMA, ITA, ITA, LLTE, LLTE, ITA, ING, LTE, LTE
|];

array[class] of set of allsubjects: subjclass = [
    {ITA, ING}, 
    {CHI, SCI, DIS, DIR}, 
    {ITA, ING, MAT}, 
    {ITA, ING, LELE}
];

% 简化的LB定义:与subjclass科目顺序一一对应
array[class] of list of int: LB_simple = [
    [2, 1],     
    [0, 0, 1, 0], 
    [2, 1, 2],  
    [2, 1, 1]   
];

array[class, allsubjects] of 0..3: LB = array2d(class, allsubjects, [
    let {
        set of allsubjects: subjs = subjclass[i],
        list of int: lbs = LB_simple[i],
        array[subjs] of int: subj_to_lb = array1d(subjs, lbs)
    } in
    if k in subjs then subj_to_lb[k] else 0 endif
    | i in class, k in allsubjects
]);

array[class, weektime] of var 0..1: tbl;

% 原约束逻辑不变
constraint forall (i in class, k in subjclass[i]) (
    sum([tbl[i,j] | j in weektime where subjects[i,j] == k]) >= LB[i,k]
);

% 补充第4类LELE的等式约束
constraint sum([tbl[4,j] | j in weektime where subjects[4,j] == LELE]) == 1;

内容的提问来源于stack exchange,提问作者cnzo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:30:55