简体   繁体   English

MiniZinc:获得一组超级数组

[英]MiniZinc: Obtain a super set of array of sets

I am working on a constraint programming problem but stuck at a specific step and need suggestions. 我正在研究约束编程问题,但停留在特定步骤,需要建议。

My data has a bunch of orders with each order having some SKUs. 我的数据有很多订单,每个订单都有一些SKU。 I want to group these orders in different batches and then count unique SKUs in a batch/group. 我想将这些订单分为不同的批次,然后在一个批次/组中​​计算唯一的SKU。 For eg 例如

Order 1 - SKUs 1, 2, 3 
Order 2 - SKUs 2, 5 
Order 3 - SKUs 1, 3, 7
Order 4 - SKUs 3, 4, 6

Now, if I group Orders 1 & 4 in Batch 1 while Orders 2 & 3 in Batch 2 then following will be unique SKU count in each batch: 现在,如果我将批次1中的订单1和4分组,而批次2中的订单2和3,则每个批次中的唯一SKU计数如下:

Batch 1 - SKUs 1, 2, 3, 4, 6 = 5 SKUs
Batch 2 - SKUs 1, 2, 3, 5, 7 = 5 SKUs

My code is as below 我的代码如下

include "globals.mzn"; 

int: N_Orders = 14; % Number of orders
set of int: ORDERS = 1..N_Orders;
set of int: skuids = {1,2,3,4,5}; % Distinct sku ids across all orders
array[ORDERS] of set of skuids: oskuids = [{1,2,3},{1,3},{4},{4,5},{1},{1,4},{3,4},{5},{1,4,5},{1,2,3},{1,3},{4,5},{1},{1,4}]; % Distinct SKU ids in each order

% Orders per batch
ORDERS: x = 2; 

% Batches needed
int: N_Batches = 7;


% Define array that contains batch for each order
array[ORDERS] of var 1..N_Batches: obatch;
constraint global_cardinality(obatch, [i | i in (1..N_Batches-1)], [x | i in 1..(N_Batches-1)]); % Total orders in batch set to 'x'

% Distinct skus in each batch
array[1..N_Batches] of var int: skus_in_batch;
constraint forall(i in 1..N_Batches)(
             skus_in_batch[i] = card(array_union(o in ORDERS where obatch[o] = i)(oskuids[o]))
           );

solve satisfy;

On running this code, I get following error: 在运行此代码时,出现以下错误:

MiniZinc: type error: no function or predicate with this signature found: `array_union(array[int] of var opt set of int)'

How can I modify code to give me the required result? 如何修改代码以提供所需的结果?

If I understand it correctly, you can simply use sum instead: 如果我理解正确,则可以简单地使用sum代替:

constraint forall(i in 1..N_Batches)(
   skus_in_batch[i] = sum([obatch[o] = i | o in ORDERS])
);

The first solution is then 然后第一个解决方案是

obatch = array1d(1..14 ,[7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1]);
skus_in_batch = array1d(1..7 ,[2, 2, 2, 2, 2, 2, 2]);

Here is the answer I received from the architects of MiniZinc on another forum and realized that this method can be used at many other similar situations where we receive error due to unsupported option types - 这是我在另一个论坛上从MiniZinc的架构师处获得的答案,并意识到该方法可以在许多其他类似情况下使用,这些情况由于不支持的选项类型而导致出现错误-

The expression 表达方式

 skus_in_batch[i] = card(array_union(o in ORDERS where obatch[o] = i)(oskuids[o])); 

Is effectively equivalent to 有效相当于

 skus_in_batch[i] = card(array_union([ if obatch[o] = i then oskuids[o] else top endif | o in ORDERS]]); 

and hence fails since array_union is not able to handle the array of optional sets that are created. 因此失败,因为array_union无法处理所创建的可选集的数组。 You can simple rewrite it to below to avoid option types. 您可以将其简单地重写为以下内容,以避免使用选项类型。

 skus_in_batch[i] = card(array_union([ if obatch[o] = i then oskuids[o] else {} endif | o in ORDERS]]); or equivalently skus_in_batch[i] = card(array_union(o in ORDERS) (if obatch[o] = i then oskuids[o] else {} endif)); 

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

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