logic-programminganswer-set-programmingclingo

Shorthand for multiple choice predicates in clingo


Right now I have a single choice predicate that defines my search space.

#const nRounds = 3.
#const nPlayers = 17.
#const nSeats = nRounds * nPlayers.
#const nRooms = 3.
#const nDecks = 6.

nSeats { seat(1..nPlayers, 1..nRooms, 1..nDecks) } nSeats.

I would like to restrict this search space as I'm starting to run into performance problems. In my set up each each player can only appear in 4 "seat" predicates so I would like something along the lines of:

#for i in 1..nPlayers
nRounds { seat(i, 1..nRooms, 1..nDecks) } nRounds.
#endfor

which would basically turn into something like this internally:

nRounds { seat(1, 1..nRooms, 1..nDecks) } nRounds.
nRounds { seat(2, 1..nRooms, 1..nDecks) } nRounds.
nRounds { seat(3, 1..nRooms, 1..nDecks) } nRounds.
...

I could, of course, "spell this out myself" i.e. use another language to generate these lines but I don't see why this wouldn't exist in clingo.

The reason I am looking for a way to do this in the first place is because I expect that (nRooms*nDecks choose nRounds) * nPlayers is going to be much smaller than (nRooms*nDecks*nPlayers) choose nRounds*nPlayers which is in turn much better than {seat(P, R, D)} with its 2^(nRooms*nDecks*nPlayers) which is what I started with.

Even with constraints in my code that restrict the actual possible sets I can end up with so that all three of these representations are equivalent, there are still performance benefits to gain from such manual search space pruning right?


Solution

  • The "for loop" you are looking for is a straight forward rule:

    nRounds { seat(S, 1..nRooms, 1..nDecks) } nRounds :- S = 1..nPlayers.
    

    Check the difference to your code with clingo --text

    I would also advise you to seperate the seat(P,R,D) predicate into several smaller ones (depending on your problem. Like each player is assigned a room p2r(P,R) and every room is assigned to a deck r2d(R,D). This way you save a lot of unecessary combinations in your constraints later on. Of course my two predicate may not make sense for your problem but I'm sure you will find a combination to split your seat predicate.