3

I am trying to assign a component to each node of a graph in such a way that all nodes that are assigned the same component are connected. By connected I mean that any two nodes in the same component should be reachable through some undirected path (possibly involving more than one edge). However my MiniZinc model turns out to be unsatisfiable. I tried analyzing it with findMUS but just got the following output:

FznSubProblem:  Solve: 2(U:U) ncons:        0   took: 0.01353 seconds
Background is not satisfiable, exiting. Try using --soft-defines.

   Done (overall time 0.21 s)

Here is my code with a small graph inlined:

include "globals.mzn";

% Figure showing the input graph:
%
%        1       2       3       4
%   (1) <-> (2) <-> (3) <-> (4) <-> (5)
%

int: nodes = 5;
set of int: nodeIndices = 1..nodes;

int: edges = 4;
set of int: edgeIndices = 1..edges;

array[edgeIndices] of nodeIndices: from = [1, 2, 3, 4];
array[edgeIndices] of nodeIndices: to   = [2, 3, 4, 5];

set of int: partitionIndices = nodeIndices;
array[nodeIndices] of var partitionIndices: solution;

constraint forall(i in partitionIndices) (
  connected(
    from,
    to,
    [solution[j] == i | j in nodeIndices],
    [true | j in edgeIndices]
  )
);

solve satisfy;

output [show(solution)];

I'd expect solutions like:

[1, 1, 1, 1, 1]
[1, 1, 2, 2, 2]
[1, 2, 3, 4, 5]
...

Regarding the constraint, I am using connected in such a way that I filter for nodes in a given component. I allow all edges to be used.

What am I doing wrong here? Did I misunderstand how connected works?

Edit: Through debugging I found out that the following constraint (not literally contained in the above program) is unsat:

constraint connected(
  from,
  to,
  [false | j in nodeIndices],
  [false | j in edgeIndices]
);

This is bad, because this means that my program will be unsat as soon as there is one empty/unused partition. If I try to relax the constraint like so:

constraint forall(i in partitionIndices) (
  exists(j in nodeIndices)(solution[j] == i) -> connected(...)
)

I get:

Abort: Reified connected is not supported.

Additionally, I found out that the selection of edges cannot be "all edges" like I tried, but must be more specific. I tried to select edges per partition, like so:

constraint forall(i in partitionIndices) (
  connected(
    from, 
    to,
    [solution[j] == i | j in nodeIndices],
    [
      solution[from[j]] == solution[to[j]] /\
      solution[from[j]] == i
      | j in edgeIndices
    ]
  )
);

... and got one solution:

[5, 2, 4, 1, 3]

I then tried to decrease the maximum number of partitions and constrained the solution mapping for two nodes to be equal and got a solution where one partition contains two nodes and all others one.

Lorenz Leutgeb
  • 474
  • 6
  • 12

0 Answers0