1

This is a subproblem of a constraint satisfaction problem I'm currently working on and thus, I've omitted extra constraints that I apply to my variables.

Suppose we have a list of 5 variables and said vars can take values from 1 to 3. Symmetry is defined as such: Suppose we were to take 2 full assignments of all variables. Let's also suppose that for each one of those full assignments, we calculate the sets of the variables that have the same value. If we could find a way so that each set of the first assignment could have an equal/identical set in the second assignment, the two said assignments would be symmetrical.

Here is a small example to make things a bit clearer: Let's take the following two assignments:

L1 = [ 1, 2, 1, 1, 3 ]
L2 = [ 2, 1, 2, 2, 3 ]

Those two are symmetrical. Let's also take the following one:

L3 = [3, 1, 3, 3, 2]

This is also symmetrical with L1 and L2.

I am trying to prune all symmetrical assignments. How can I express this in constraints?

So far I've tried using constraints to find the first variable with no assigned value and basically locking its value with the #=/2; this happens once for each possible domain value. My code gets an instantiation error but I'm not really sure that my endeavour is actually a valid way to go about solving this problem.

:-lib(ic).

getNth(0, [ H | T], H, T).
getNth(Count, [ _ | T], Target, Others):-
    NewCount is Count - 1,
    getNth(NewCount, T, Target, Others).

assigned(_, [], TruthVal, TruthVal).
assigned(Var, [Val | OtherVals], CurTruthVal, TruthVal):-
    UpdatedTruthVal #= (CurTruthVal and (Var #\= Val)),
    assigned(Var, OtherVals, UpdatedTruthVal, TruthVal).

firstUnassigned(_, [], _, _, _, _).
firstUnassigned( CurP, [Var | OtherVars], PrevVals, Found, CurCount, Index):-
    assigned(Var, PrevVals, 1, TruthVal),
    (TruthVal and (Found #\= 1)) => ((Index #= CurCount) and (Var #= CurP) and (NewFound #= 1)),
    Found => (NewFound #= Found),
    NewCount is CurCount + 1,
    firstUnassigned(CurP, OtherVars, PrevVals, NewFound, NewCount, Index).

symmetryConstraints(CurP, NP, _, _):-
    CurP > NP.

symmetryConstraints(CurP, NP, L, PrevVals):-
    CurP =< NP,
    firstUnassigned(CurP, L, PrevVals, 0, 0, Index),
    getNth(Index, L, _, NextL),
    NewP is CurP + 1,
    symmetryConstraints(NewP, NP, NextL, [CurP | PrevVals]).

start(L):-
    L = [ Var1, Var2, Var3 ],
    L #:: 1..2,
    length(L, N),
    symmetryConstraints(1, N, L, []),
    search(L, 0, most_constrained, indomain, complete, []).
  • What libraries are you using and how L1 and L2 are symmetrical? IN L1 you have 3 1's and L2 you have 1 1's? In eclipse you can use loops instead of recursion which provides a clean code. – Luai Ghunim Jun 06 '19 at 15:44
  • @LuaiGhunim I am using ic and ic_global. As this is part of my course assignment, I am not allowed to use for loops and if/else statements. As for the symmetry, let's think of it like this: The list of vars are jobs that must be assigned and the values are personal IDs that indicate to whom a job has been assigned. L1 and L2 are symmetrical in the sense that whether person 1 gets jobs 1, 3 and 4 (by order) and person 2 gets job 2 OR the reverse happens, it's the same thing. What really matters is not which person gets which set of assignments, but the set of assignments itself. – Imperator Romanorum Jun 06 '19 at 16:24
  • Here is a related answer that might help with some ideas https://stackoverflow.com/a/55869661/2353967 – jschimpf Jun 06 '19 at 22:36

0 Answers0