如何在MiniZinc中实现类似np.any的布尔数组存在True判断函数?
问题
我原本在MiniZinc模型中用以下代码最小化线性成本函数:
set of int: foos = 1..8; set of int: bars = 1..5; array[foos] of float: cost; array[foos, bars] of var bool: assignment; solve minimize sum(foo in foos) ( sum(bar in bars) (cost[foo] * assignment[foo, bar]) );
现在想要定义一个类似np.any(x)的非线性/离散函数any_fun,实现对assignment[foo, :]每行判断:只要存在至少一个True元素就返回True,否则返回False。比如对矩阵[[False, False], [True, False], [True, True]]应用该函数后,每行结果是False、True、True。
我已经实现了一维数组的判断:
set of int: foos = 1..10; array[foos] of int: assignment; var bool: any_fun = sum(i in foos) (assignment[i]) > 0; solve minimize any_fun; output [show(any_fun)];
但不清楚如何应用到二维数组,同时希望能像sum那样用内置函数式的方式实现。
解决方案
在MiniZinc中,可以通过定义可复用函数或直接内嵌逻辑来实现类似np.any的功能,以下是两种实用方式:
1. 定义可复用的any_fun函数
自定义一个接受一维数组的函数,判断数组中是否存在至少一个true值,之后在二维数组的每行调用这个函数:
set of int: foos = 1..8; set of int: bars = 1..5; array[foos] of float: cost; array[foos, bars] of var bool: assignment; % 定义类似np.any的函数:判断一维数组是否存在至少一个true function bool any_fun(array[int] of var bool: arr) = sum(arr) > 0; % 目标函数:对每行应用any_fun后求和 solve minimize sum(foo in foos) ( any_fun(assignment[foo, bars]) );
2. 直接内嵌逻辑(无需显式定义函数)
如果不需要复用函数,可以直接在求和表达式中内嵌行级判断逻辑,效果完全一致:
set of int: foos = 1..8; set of int: bars = 1..5; array[foos] of float: cost; array[foos, bars] of var bool: assignment; solve minimize sum(foo in foos) ( sum(bar in bars) (assignment[foo, bar]) > 0 );
补充说明
MiniZinc中bool类型会自动转换为数值:true对应1,false对应0,所以sum(assignment[foo, bars])的结果就是该行中true的数量,只要大于0就说明存在至少一个true,完全符合你需要的判断逻辑。
内容的提问来源于stack exchange,提问作者fibonacciguy
相关产品推荐
相关产品推荐

