I’m new to clingo (answer set programming) and I’m stuck with a very simple problem.
I want to simulate a very simple behaviour: A game board with two rows and three columns, and three tokens, placed on the first row. As if they were chess pawns, the three tokens can only make one kind of move: one step ahead.
Only one token can move each time, and has to. To simplify, I want to represent the game after just one move. So, the initial moment will look like this:
And the next moment should look like one of this three situations:
My goal is to get exactly that three answer sets.
So I made my code like this:
next(zero, one).
% The three tokens at initial positions. Parameters are (Row, Column, Moment).
token(zero, zero, zero).
token(zero, one, zero).
token(zero, two, zero).
% The position of the tokens in time, that may result from moving one step ahead
{ token(Row, Column, Moment) } :-
token(InitialRow, Column, InitialMoment),
next(InitialRow, Row),
next(InitialMoment, Moment).
And it subsequently generates the eight possible ways the game may look like at second moment, attending to the current code:
Answer: 1 → token(zero,zero,zero) token(zero,one,zero) token(zero,two,zero)
Answer: 2 -> token(zero,zero,zero) token(zero,one,zero) token(zero,two,zero) token(one,one,one)
Answer: 3 -> token(zero,zero,zero) token(zero,one,zero) token(zero,two,zero) token(one,zero,one)
Answer: 4 -> token(zero,zero,zero) token(zero,one,zero) token(zero,two,zero) token(one,one,one) token(one,zero,one)
Answer: 5 -> token(zero,zero,zero) token(zero,one,zero) token(zero,two,zero) token(one,two,one)
Answer: 6 -> token(zero,zero,zero) token(zero,one,zero) token(zero,two,zero) token(one,two,one) token(one,zero,one)
Answer: 7 -> token(zero,zero,zero) token(zero,one,zero) token(zero,two,zero) token(one,two,one) token(one,one,one)
Answer: 8 -> token(zero,zero,zero) token(zero,one,zero) token(zero,two,zero) token(one,two,one) token(one,one,one) token(one,zero,one)
The only task left to do is eliminate all the answer sets that have been generated moving more or less than one token at a time. It’s mandatory for the game that only one token moves each turn… so must contain only the three desired sets exposed above.
So I add to the code this negation rules:
% Eliminate if
:- token(Row, Column, Moment), % all of its tokens didn't move
next(Moment, NextMoment),
token(Row, Column, NextMoment).
% Eliminate if
:- token(Row, Column, Moment), % all of its tokens moved
next(Moment, NextMoment),
not token(Row, Column, NextMoment).
And it negates the first and the last of the 8 answer sets, still leaving 6 sets.
Then, how on earth should I express “if one and only one of them moved” in clingo?
Note: I also tried creating an Id for tokens, but since clingo applies negation rules to all facts of a set indistinctly, I dont think works for a solution. I tried the code:
next(zero, one).
% The three tokens at initial positions. Parameters are (Row, Column, Moment, Id).
token(zero, zero, zero, zero).
token(zero, one, zero, one).
token(zero, two, zero, two).
% The position of the tokens in time, that may result from moving one step ahead
{ token(Row, Column, Moment, _) } :-
token(InitialRow, Column, InitialMoment, _),
next(InitialRow, Row),
next(InitialMoment, Moment).
% Eliminate if
:- token(Row, Column, Moment, Id), % all of it's tokens moved while the rest of tokens stay still (nonesense)
next(Moment, NextMoment),
not token(Row, Column, NextMoment, Id),
token(Row2, Column2, Moment2, Id2),
not Id = Id2, % (intended to get only the rest of the tokens. Does this make sense?)
next(Moment2, NextMoment2),
token(Row2, Column2, NextMoment2).
But is wrong, as well...