对于我的更大的minizinc模型,我需要一个基本回答以下问题的函数:“此数组的子集内,其总和是否在$ target的$ tolerance之内”(并返回一个布尔值)。
这本身就很容易用minizinc编写。例如
int: tolerance = 3;
int: target = 200;
int: amountsCount = 7;
array[1..amountsCount] of int: amounts = [23, 345, 230, 100, 25, 28, 25];
array[1..amountsCount] of var bool: includeAmount;
var int: subsetAmount = sum([(if includeAmount[i] then amounts[i] else 0 endif) | i in 1..amountsCount]);
var bool: solvable = abs(subsetAmount - target) < tolerance;
solve maximize bool2int(solvable);
output ["solvable=", show(solvable), " included: ", show(includeAmount), " subset amount:", show(subsetAmount)];
但是如何使它成为用户定义的函数(返回布尔值“可解决”),以便可以在实际模型中使用它?
答案 0 :(得分:2)
您可以引入一个用户定义的谓词,该谓词在模型中返回solvable
的值:
predicate has_subset_within_tolerance(array[1..amountsCount] of int: amounts_array) =
let {
var int: subsetAmount = sum([(if includeAmount[i] then amounts[i] else 0 endif) | i in 1..amountsCount]);
} in
abs(subsetAmount - target) < tolerance
;
谓词就像函数一样,只是它们返回布尔值。在谓词中,我引入了局部变量subsetAmount
并以与初始模型相同的方式对其进行约束。然后,我发布需要保留以使谓词返回true的表达式:abs(subsetAmount - target) < tolerance
。
然后您可以通过以下方式在模型中使用该谓词,例如在solve
语句中:
int: tolerance = 3;
int: target = 200;
int: amountsCount = 7;
array[1..amountsCount] of int: amounts = [23, 345, 230, 100, 25, 28, 25];
array[1..amountsCount] of var bool: includeAmount;
solve maximize bool2int(has_subset_within_tolerance(amounts));
% don't forget to insert the predicate here as well
编辑:
您还可以将变量includeAmount
作为参数添加到谓词中:
predicate has_subset_within_tolerance(array[1..amountsCount] of int: amounts_array,
array[1..amountsCount] of var bool: includeAmount)=
let {
var int: subsetAmount = sum([(if includeAmount[i] then amounts_array[i] else 0 endif) | i in 1..amountsCount]);
} in
abs(subsetAmount - target) < tolerance
;
然后,您可以使用不同的变量来调用谓词,例如includeAmount1
和includeAmount2
:
int: tolerance = 3;
int: target = 200;
int: amountsCount = 7;
array[1..amountsCount] of int: amounts1 = [23, 345, 230, 100, 25, 28, 25];
array[1..amountsCount] of int: amounts2 = [20, 35, 10, 400, 65, 19, 69];
array[1..amountsCount] of var bool: includeAmount1;
array[1..amountsCount] of var bool: includeAmount2;
solve maximize
bool2int(has_subset_within_tolerance(amounts1, includeAmount1))
+ bool2int(has_subset_within_tolerance(amounts2, includeAmount2));
如果它们还依赖于不同的target
变量,还可以将tolerance
和includeAmount
作为谓词的参数添加。