Search code examples
arraysmatrixminizinc

How to make operations on index in matrix


I use MiniZinc to create matrix and I would like to create the same matrix as "assignment" but the value at a certain point is should be greater than one. For example:

assignment = 
[|        Allegro: eBay: 
 | Node1:       1,    2
 | Node2:       2,    1
 | Node3:       1,    2
 | Node4:       1,    3
 | Node5:       1,    1
 |];
assignment_add_container = 
[|        Allegro: eBay: 
 | Node1:       1,    2
 | Node2:       2,    2
 | Node3:       1,    2
 | Node4:       1,    3
 | Node5:       1,    1
 |];

So my question is, how can I refer to an element in a matrix?

this is my code:

enum Servers = {Node1, Node2, Node3, Node4, Node5};
enum Services = {Allegro, eBay};

array[Servers, Services] of var 0..5: assignment;
array[Servers, Services] of var 0..5: assignment_add_container;

constraint forall(server in Servers, service in Services)
  (assignment_add_container[server, service] = assignment[server, service])
;

constraint assignment_add_container[Node2, eBay] = assignment_add_container[Node2, eBay] + 1
;

but I got error: MiniZinc: type error: undefined identifier `Node2'

I also tried sth like this

constraint assignment_add_container[2, 2] = assignment_add_container[2, 2] + 1

But I got MiniZinc: type error: array index 1 must be 'Servers', but is `int'


Solution

  • As for Axel, I don't get any Node2 errors message in MiniZinc 2.6.4 (Linux).

    Here's is a way of increasing one of the values by 1 (for server=Node2 and service=eBay). The main point is that you must exclude the Node2/eBay from the plain copying, which is here done using if/then/endif. The model assumes that the matrix assignment contains fixed values.

    enum Servers = {Node1, Node2, Node3, Node4, Node5};
    enum Services = {Allegro, eBay};
    
    array[Servers, Services] of 0..5: assignment;
    array[Servers, Services] of var 0..5: assignment_add_container;
    
    constraint forall(server in Servers, service in Services )
      (
         if server = Node2 /\ service = eBay then
            assignment_add_container[Node2, eBay] = assignment[Node2, eBay] + 1
         else
           assignment_add_container[server, service] = assignment[server, service]
         endif
       )
    ;
    
    assignment = 
    [|        Allegro: eBay: 
     | Node1:       1,    2
     | Node2:       2,    1
     | Node3:       1,    2
     | Node4:       1,    3
     | Node5:       1,    1
     |];
    

    This results in this solution:

    assignment_add_container = 
    [|        Allegro: eBay: 
     | Node1:       1,    2
     | Node2:       2,    2
     | Node3:       1,    2
     | Node4:       1,    3
     | Node5:       1,    1
     |];
    ----------
    ==========
    

    One other way would be to use where in the forall loop to exclude the special assignment, and have a separate constraint for incrementing the value:

    % ...
    forall(server in Servers, service in Services where not (server = Node2 /\ service = eBay) )  (
            assignment_add_container[Node2, eBay] = assignment[Node2, eBay] + 1
       )
    ;
    
    constraint assignment_add_container[Node2, eBay] = assignment[Node2, eBay] + 1 ;