Clingo: assert partial constraints

一曲冷凌霜 提交于 2019-12-12 01:23:52

问题


I am trying to implement a program in clingo that solves one of those classic riddles where you have a series of assertions of facts and constraints and you have to deduce other facts. Here goes the problem:

Five men of different nationalities live in five side-by-side houses, each of a different color; they all have different jobs, a different favourite animal and favourite beverages. We know that:

  1. The English man lives in the red house.
  2. The Spanish man's favourite animal is the dog.
  3. The Japanese man is a painter.
  4. The Italian man drinks tea.
  5. The Norwegian man lives in the first house from the left. (number_norw = 1)
  6. The person living in the green house drinks coffee.
  7. The green house is immediately right of the white one. (number_green = number_white + 1)
  8. The clerk loves cats.
  9. The salesman lives in the yellow house.
  10. Milk is the favourite drink in the center house. (number_milk = 3)
  11. The Norwegian's house is adjacent to the blue one. (number_norw = number_blue ± 1)
  12. The cook likes juice.
  13. The man living in the house next to the doctor's loves foxes.
  14. The man who loves horses lives next door to the salesman.

The assignment is to find out who likes zebras. So I set forth asserting:

% Number (the number of the house, 1 being the leftmost of the block, 5 the rightmost)
number(1..5).

% Color
color(red;green;white;yellow;blue).

% Nationality
nationality(english;spanish;japanese;italian;norwegian).

% Animal
animal(dog;cat;fox;horse;zebra).

% Job
job(painter;clerk;salesman;cook;doctor).

% Beverage
beverage(tea;coffee;milk;juice;coke).

% House
house(X, C, N, A, J, B) :-
    number(X),
    color(C),
    nationality(N),
    animal(A),
    job(J),
    beverage(B).

Now I'm stuck on asserting the constraints; how do I go about coding assertions 1. through 14.? I just need to understand the proper syntax, so if someone could please set me on the right track with one or two examples I can figure out the rest. Thanks.

N.B. Notice I could have inferred, from 5. and 11., that the second house is the blue one because 11. number_blue = number_norw ± 1, 5. number_norw = 1, and 0 is not in the range of possible numbers, but I don't want to manually add it to the constraints because I expect clingo to figure it out itself.


回答1:


One way to add the constraint for the first assertation:

% 1. The English man lives in the red house.
%     S: english --> red house <==> red house OR not english
% not S: not (red house OR not english) <==> not red house AND english
% ie. it is not so, that the english man doesn't live in the red house
:- not 1 { house(X, red, english, A, J, B) :
           number(X) : animal(A) : job(J) : beverage(B) }.

and as another example the seventh assertation:

% 7. The green house is immediately right of the white one.
% (number_green = number_white + 1)
:- house(NG, green, _, _, _, _), house(NW, white, _, _, _, _), NG!=NW+1.

This will however lead to long solving times and large memory requirements (gigabytes), because the grounded program (output of gringo) is massive. You can see this with gringo -t yourcode.asp. This is because the "do not care" variables _ (and X, A, J, B in the constraint for the first assertation above). Each rule will be written in at least 5*5*5*5 ways.

M. Gebser adviced me that the predicates (relations) should be kept short. The problem with this encoding of the instance is that house/6 is so long. One way to combat this would be to encode it in the following style:

house(1..5).
elem(color, red;green;white;yellow;blue).
elem(nationality, english;spanish;japanese;italian;norwegian).
...

and start from there. Now the arity of elem is only 2. When the instance is defined this way, the program becomes simpler eg. the constraints for the assertations do not need aggregates (the 1{ ... }N syntax).

:- not chosen(H, nationality, english), chosen(H, color, red).

M. Gebser also suggested that the solver (clasp) might benefit form the rule being written in the other way too:

:- not chosen(H, nationality, english), chosen(H, color, red).
:- chosen(H, nationality, english), not chosen(H, color, red).

You also need some additional restrictions, like that two different elements of the same type shouldn't be mapped to one house.

For nicer output, you can make a relation that gives the output like house/6 did.

Note that I used gringo3 and clasp2, which are not the newest versions. If you have the new clingo, there might be modifications that are needed.



来源:https://stackoverflow.com/questions/23482224/clingo-assert-partial-constraints

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!