簡體   English   中英

MiniZinc:獲得一組超級數組

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

我正在研究約束編程問題,但停留在特定步驟,需要建議。

我的數據有很多訂單,每個訂單都有一些SKU。 我想將這些訂單分為不同的批次,然后在一個批次/組中​​計算唯一的SKU。 例如

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

現在,如果我將批次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

我的代碼如下

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;

在運行此代碼時,出現以下錯誤:

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

如何修改代碼以提供所需的結果?

如果我理解正確,則可以簡單地使用sum代替:

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

然后第一個解決方案是

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]);

這是我在另一個論壇上從MiniZinc的架構師處獲得的答案,並意識到該方法可以在許多其他類似情況下使用,這些情況由於不支持的選項類型而導致出現錯誤-

表達方式

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

有效相當於

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

因此失敗,因為array_union無法處理所創建的可選集的數組。 您可以將其簡單地重寫為以下內容,以避免使用選項類型。

 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