简体   繁体   English

将微型锌模型分解为用户定义的函数

[英]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 : 那么您可以使用不同的变量来调用谓词,例如includeAmount1includeAmount2

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. 您还可以添加targettolerance作为参数谓词,在情况下,他们还取决于不同的includeAmount变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM