Prolog 逻辑测试示例



我在Prolog上有一个测试,但我无法真正掌握它的基本思想。我有点理解我所经历的一些例子,但我不能坐下来知道如何解决一个特定的问题。

我们的教授给了我们一些例子,我想知道是否有人可以引导我如何做到这一点,所以我有某种想法如何处理这样的事情。

这个例子来自我们的书:

Donna, Danny, David, and Doreen were seated at a table. 
The men sat across from each other, as did the women. 
They each ordered a different drink and main course.
Facts:
Doreen sat beside the person that ordered steak
The chicken came with a coke
The person with lasagna sat across from the person with milk
David never drinks coffee
Donna only drinks water
Danny could not afford to order steak

我尝试了一些东西,每个人都有一个与他们相关的列表,你会填充事实,但我认为这不是正确的方法。有人可以带我完成这个吗?谢谢!

编辑:

这是我最终得到的代码,它完成了大部分难题,它留下了一个主菜和一个饮料,但这应该是可以修复的:

  sat_across([X,_,Y,_], X, Y).
  sat_across([_,X,_,Y], X, Y).
  sat_beside(T, X, Y) :-  % this is tricky
      nth1(N,T,X), nth1(M,T,Y),
      (N =:= M+1 ; N =:= M-1 ; N == 1, M == 4 ; N == 4, M == 1).
      not_connected(T, Place) :- + member(Place, T).
  connected(T, Place) :- member(Place, T).
  solve(T) :- T = [_,_,_,_],
      sat_across(T, (danny,_,_), (david,_,_)),
      sat_across(T, (donna,_,_), (doreen,_,_)),
      sat_beside(T, (doreen,_,_), (_,_,steak)),
      connected(T, (_,coke,chicken)),
      sat_across(T, (_,_,lasagna), (_,milk,_)),
      not_connected(T, (david,coffee,_)),
      connected(T, (donna,water,_)),
      not_connected(T, (danny,_,steak)).

使用模式匹配,每个位置都带有一个属性三重:名称,饮料,食物。

然后我们有一个 [N,S,W,E] 表(滥用合同桥约定),我们必须应用所有可用的约束:我认为可以这样做......

sat_across([X,_,Y,_], X, Y).
sat_across([_,X,_,Y], X, Y).
sat_across([X,_,Y,_], Y, X).
sat_across([_,X,_,Y], Y, X).
sat_beside(T, X, Y) :-  % this is tricky
    nth1(N,T,X), nth1(M,T,Y),
    (N =:= M+1 ; N =:= M-1 ; N == 1, M == 4 ; N == 4, M == 1).
cant_afford(T, Place) :- + member(Place, T).
solve(T) :- T = [N,S,W,E],
      sat_across(T, (danny,_,_), (david,_,_)),
      sat_across(T, (donna,_,_), (doreen,_,_)),
      sat_beside(T, (doreen,_,_), (_,_,steak)),
      ....
      cant_afford(T, (danny,_,steak)),
      ....

你应该认识到这个问题有八个变量:每个人的饮料和主菜,所以DonnaDrinkDannyFood等。

你的程序应该根据给出的事实,用==来反对这八个变量,也许使用额外的谓词,如gender

(这实际上是斑马拼图的简单变体,但没有所有的排序。

抱歉,

如果我正在死灵这个线程,但我对答案并不满意(它们似乎不优雅/不完整)。

这是斑马问题的一个变体。唯一真正的问题是"X处于什么位置",X可以是一个人,主菜或饮料。因此,您的域是 { 1, 2, 3, 4 },其中每个数字代表一个席位。

然后添加你的约束,确保每个项目相对于其类型的其他项目处于唯一位置(即一个人只能坐在 1 个座位上,等等),并设置松散 prolog。

哦,别忘了把你的负面约束放在最后。这是我最终得到的:

%  Organize the seating, so:
%  1  2
%  3  4
%  This means that "across" is always (n+2)%4
%  and "beside" is (n+1)%2
pos(1). pos(2). pos(3). pos(4).
beside(A,B) :- pos(A), B is (A+1) mod 2.
across(A,B) :- pos(A), B is (A+2) mod 4.
zebra(Donna,Danny,David,Doreen,
     Steak,Lasagna,Pizza,Chicken,
     Coke,Milk,Coffee,Water) :-
  % Our 4 given positive constraints
  beside(Doreen,Steak),
  Chicken=Coke,
  across(Lasagna,Milk),
  Donna=Water,
  % The men and women sat across from each other
  across(David,Danny),
  across(Doreen,Donna),
  % Ensure that each item is only in 1 position
  uniq_pos(Steak,Lasagna,Pizza,Chicken),
  uniq_pos(Coke,Milk,Coffee,Water),
  uniq_pos(Donna,Danny,David,Doreen),
  % The remaining two negative constraints.
  + David=Coffee,
  + Danny=Steak.
% Ensures that all 4 items are in unique positions.
uniq_pos(A,B,C,D) :-
  pos(A), pos(B), pos(C), pos(D),
  + A=B, + A=C, + A=D,
          + B=C, + B=D,
                  + C=D.

似乎有效。Prolog告诉我:
坐在1号座位上的大卫得到了牛排和牛奶,
坐在2号座位上的多琳拿了鸡肉和可乐,
坐在3号座位上的丹尼得到了千层面和咖啡,
坐在4号座位上的唐娜得到了披萨和水。

希望这有助于其他试图理解这个问题的人。

相关内容

  • 没有找到相关文章

最新更新