1

I have an array of sets that means that the items inside the set must finish before the actual one starts. For example:

before = [ {},
      {1},
      {},
      {},
      {2}];

I'm looking to make each line include the ones who go before recursively. So in this case, it should end up like this:

abans = [ {},
      {1},
      {},
      {},
      {1,2}];

I've tried generating a variable and creating the sets from blank, but I didn't manage to do it. Any ideas how I could do this?

duplode
  • 31,361
  • 7
  • 69
  • 130
Stasky
  • 11
  • 1

1 Answers1

1

CASE 1: before is a variable.

Let's take the following list of tasks:

enum TASKS = { A, B, C, D, E };

We declare an array before to hold the set of blocking tasks for each task:

array [TASKS] of var set of TASKS: before;

A task should never block on itself:

constraint forall(i in index_set(before))
    (
        not (i in before[i])
    );

A task i inherits the block-set of each task j blocking task i:

constraint forall(taskset in before)
    (
        forall(task in taskset)
        (
            before[task] subset taskset
        )
    );

You can append:

 solve satisfy;

And find all possible solutions:

~$ minizinc test.mzn --all-solutions
before = array1d(TASKS, [{}, {A}, {A, B}, {A, B, C}, {A, B, C, D}]);
----------
before = array1d(TASKS, [{B}, {}, {A, B}, {A, B, C}, {A, B, C, D}]);
----------
before = array1d(TASKS, [{}, {}, {A, B}, {A, B, C}, {A, B, C, D}]);
----------
before = array1d(TASKS, [{}, {A, C}, {A}, {A, B, C}, {A, B, C, D}]);
----------
before = array1d(TASKS, [{}, {A}, {A}, {A, B, C}, {A, B, C, D}]);
----------
before = array1d(TASKS, [{}, {}, {A}, {A, B, C}, {A, B, C, D}]);
----------
before = array1d(TASKS, [{B, C}, {}, {B}, {A, B, C}, {A, B, C, D}]);
----------
before = array1d(TASKS, [{B}, {}, {B}, {A, B, C}, {A, B, C, D}]);
----------
before = array1d(TASKS, [{}, {}, {B}, {A, B, C}, {A, B, C, D}]);
----------
before = array1d(TASKS, [{C}, {A, C}, {}, {A, B, C}, {A, B, C, D}]);
----------
before = array1d(TASKS, [{}, {A, C}, {}, {A, B, C}, {A, B, C, D}]);
----------
before = array1d(TASKS, [{}, {A}, {}, {A, B, C}, {A, B, C, D}]);
...

CASE 2: before is an input parameter.

A task i belongs to abans[j] if it is contained in before[j], or there exists a task k in abans[j] such that i is in before[j].

Encoding:

enum TASKS = { A, B, C, D, E };

array [TASKS] of set of TASKS: before = 
    [{C}, {A}, {D}, {}, {B}];

array [TASKS] of var set of TASKS: abans;

constraint forall(i, j in TASKS)
    (
        i in abans[j] <->
        (
            i in before[j]
            \/
            exists(k in abans[j])
            (
                i in before[k]
            )
        )
        % circular dependencies are not allowed!
        /\ not(j in abans[j])
    );

solve satisfy;

Output:

~$ minizinc test.mzn --all-solutions
abans = array1d(TASKS, [{C, D}, {A, C, D}, {D}, {}, {A, B, C, D}]);
----------
==========
Patrick Trentin
  • 6,721
  • 3
  • 20
  • 38
  • It's actually an input, sorry for not specifying it. Would it change much? – Stasky Jan 25 '20 at 21:07
  • @Stasky not much, actually.. can you derive the correct constraints from this answer? Otherwise I'll edit the answer for you – Patrick Trentin Jan 25 '20 at 22:19
  • I think that's not exactly what I was asking for. I'm given as input an array with n sets of ints inside. What I want to do is, for example, if the set in position array[5]={3}, then array[5] should contain the union of array[5] U array[3]. So: [{3},{},{2},{1}] would become [{3,2},{},{2},{1,2,3}] – Stasky Jan 25 '20 at 22:42
  • @Stasky that's exactly what happens with the `before` array in my own answer. Since you find it confusing i'll edit the answer. Give me some minutes. – Patrick Trentin Jan 25 '20 at 22:45
  • okay, thank you very much. I've been trying to mess with your current answer but I get "WARNING: model inconsistency detected" – Stasky Jan 25 '20 at 23:44
  • @Stasky Edited. Notice that the provided solution assumes that there is no circular dependency. (That should probably be a forbidden input). – Patrick Trentin Jan 26 '20 at 00:44
  • That works great! Thank you very much! I'm still learning this and was of great help! – Stasky Jan 26 '20 at 17:13