HI Ofer,
First of all, the code you supplied would not work anyway, since you
are constructing a matrix of size order * order from just
order*(order-1)/2. However, if you use the full definition instead for
the comprehension (o1, o2 in orders) it works. Now, disregarding the
fact that we are creating a very large output array, given this code
(I've added some trivial data
int: n_orders = 50;
set of int: orders = 1..n_orders;
int: n_parts = 50;
set of int: parts = 1..n_parts;
array[parts] of int: p_code = [1, 1, 2, 2, 3, 3, 4, 4, 1, 1, 5, 5, 6,
6, 7, 7, 8, 8, 9, 9, 1, 1, 2, 2, 3, 3, 4, 4, 1, 1, 5, 5, 6, 6, 7, 7,
8, 8, 9, 9, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9];
array[orders] of int: o_part = [2, 2, 3, 3, 4, 4, 1, 1, 5, 5, 6, 6, 7,
7, 8, 8, 9, 9, 1, 11, 1, 2, 2, 3, 3, 4, 4, 1, 1, 5, 5, 6, 6, 7, 7, 8,
8, 9, 9, 0, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9];
array[parts] of int: p_machine = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 4, 5,
6, 7, 8, 9, 10, 11, 12, 13, 1, 1, 2, 2, 3, 3, 4, 4, 1, 1, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9];
array[orders,orders] of bool: orders_with_intersecting_machine_sets =
array2d(orders,orders, [
exists(p1 in parts, p2 in parts) (
p_code[p1] = o_part[o1] /\
p_code[p2] = o_part[o2] /\
p_machine[p1] = p_machine[p2]
)
| o1, o2 in orders
]
);
solve satisfy;
output [show2d(orders_with_intersecting_machine_sets)];
The above takes 1.6 s flattening time on my machine. One very simple
way to improve the code, is to make two exist calls instead, and hoist the
checks for the code into the enumerations. Like this
array[orders,orders] of bool: orders_with_intersecting_machine_sets =
array2d(orders,orders, [
exists(p1 in parts where p_code[p1] = o_part[o1]) (
exists(p2 in parts where p_code[p2] = o_part[o2]) (
p_machine[p1] = p_machine[p2]
)
)
| o1, o2 in orders
]
);
This takes the flattening time down to 0.2 seconds on my computer. The
reason is that the inner loop body is not executed once for each
order*order*part*part as is done for the first variant.
A better solution is probably to change the representation, and
instead generate an array of sets
array[orders[ of set of orders: orders_with_intersecting_machine_sets;
The idea is to have each orders_with_intersecting_machine_sets[o] be
the set of other orders for which your original definition would have
been true. This can be constructed as follows
array[orders] of set of orders: orders_with_intersecting_machine_sets = [
{ o2
| o2 in orders where
exists(p1 in parts where p_code[p1] = o_part[o1]) (
exists(p2 in parts where p_code[p2] = o_part[o2]) (
p_machine[p1] = p_machine[p2]
)
)
}
| o1 in orders
];
This takes the same amount of time as the matrix version for this
small example, but might be more efficient for other parts of your
model.
Cheers,
Mikael
> --
> You received this message because you are subscribed to the Google Groups "MiniZinc" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to
minizinc+u...@googlegroups.com.
> To view this discussion on the web visit
https://groups.google.com/d/msgid/minizinc/df47aca7-d7e8-4c28-9ce8-00d8498c90c7n%40googlegroups.com.
--
Mikael Zayenz Lagerkvist