[英]Factoring a minizinc model into a user defined function
For my larger minizinc model, I need a function which basically answers: "is there a subset of this array in which the sum of it is within $tolerance of $target" (and returns a boolean). 对于更大的minizinc模型,我需要一个基本回答以下问题的函数:“此数组的子集是否存在,其总和在$ target的$ tolerance之内”(并返回一个布尔值)。
By itself this is pretty easy to write in minizinc. 就其本身而言,这很容易用minizinc编写。 eg
例如
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)];
But how could I make this a user-defined function (that returns a boolean "solvable") so I can use it from my real model? 但是,如何使它成为用户定义的函数(返回布尔“可解”),以便可以在实际模型中使用它?
You can introduce a user-defined predicate that returns the value of solvable
in your model: 您可以引入一个用户定义的谓词,该谓词返回模型中
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
;
Predicates are like functions, just that they return Boolean values. 谓词就像函数一样,只是它们返回布尔值。 In the predicate I introduce the local variable
subsetAmount
and constrain it the same way you did in your initial model. 在谓词中,我介绍了局部变量
subsetAmount
并以与初始模型相同的方式subsetAmount
进行约束。 Then I post the expression that needs to hold for the predicate to return true: abs(subsetAmount - target) < tolerance
. 然后,我发布需要使谓词返回true的表达式:
abs(subsetAmount - target) < tolerance
。
You can then use this predicate in your model, for instance in the solve
statement, in the following way: 然后,您可以通过以下方式在模型中(例如在
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
EDIT : 编辑 :
You can also add your variable includeAmount
as a parameter to the prediate: 您还可以将变量
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
;
then you can call your predicate with different variables, such as includeAmount1
and includeAmount2
: 那么您可以使用不同的变量来调用谓词,例如
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));
You can also add target
and tolerance
as parameters to the predicate, in case they also depend on the different includeAmount
variables. 您还可以添加
target
和tolerance
作为参数谓词,在情况下,他们还取决于不同的includeAmount
变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.