3

我需要使用 Prolog 来解决 Ship Puzzle 问题。以下是事实。

有5艘船。

  1. 希腊船六点出发,载着咖啡。
  2. 中间的船有一个黑色的烟囱。
  3. 英国船九点出发。
  4. 带有蓝色烟囱的法国船在运送咖啡的船的左侧。
  5. 载可可的船的右边是一艘前往马赛的船。
  6. 这艘巴西船正驶向马尼拉。
  7. 载米的船旁边是一艘带有绿色烟囱的船。
  8. 一艘去热那亚的船五点出发。
  9. 西班牙船七点出发,在前往马赛的船的右侧。
  10. 带有红色烟囱的船前往汉堡。
  11. 七点出发的船旁边是一艘带白色烟囱的船。
  12. 边境的船载着玉米。
  13. 黑烟囱的船八点出发。
  14. 运送玉米的船停泊在运送大米的船旁边。
  15. 六点开往汉堡的船。

哪艘船去塞得港?哪艘船运茶?

我在互联网上搜索答案,但我找不到任何答案。所以我参考了“斑马拼图”,因此我为这个问题安排了代码。所以这是我的Prolog代码的问题。

exists(A,(A,_,_,_,_)).
exists(A,(_,A,_,_,_)).
exists(A,(_,_,A,_,_)).
exists(A,(_,_,_,A,_)).
exists(A,(_,_,_,_,A)).

rightOf(A,B,(B,A,_,_,_)).
rightOf(A,B,(_,B,A,_,_)).
rightOf(A,B,(_,_,B,A,_)).
rightOf(A,B,(_,_,_,B,A)).

middleShip(A,(_,_,A,_,_)).

lastShip(A,(_,_,_,_,A)).

nextTo(A,B,(B,A,_,_,_)).
nextTo(A,B,(_,B,A,_,_)).
nextTo(A,B,(_,_,B,A,_)).
nextTo(A,B,(_,_,_,B,A)).
nextTo(A,B,(A,B,_,_,_)).
nextTo(A,B,(_,A,B,_,_)).
nextTo(A,B,(_,_,A,B,_)).
nextTo(A,B,(_,_,_,A,B)).

solution(PortSaidShip, TeaCarrier) :-
   Shipes = (ship(_,_,_,_,_),ship(_,_,_,_,_),ship(_,_,_,_,_),ship(_,_,_,_,_),ship(_,_,_,_,_)),
   exists(ship('Greek',6,'Coffee',_,_),Shipes),
   middleShip(ship(_,_,_,_,'Black',_),Shipes),
   exists(ship('English',9,_,_,_),Shipes),
   rightOf(ship(_,_,'Coffee',_,_),ship('French',_,_,'Blue',_),Shipes),
   rightOf(ship(_,_,_,_,'Marseille'),ship(_,_,'Cocoa',_,_),Shipes),
   exists(ship('Brazilian',_,_,_,'Manila'),Shipes),
   nextTo(ship(_,_,_,'Green',_),ship(_,_,'Rice',_,_),Shipes),
   exists(ship(_,5,_,_,'Genoa'),Shipes),
   rightOf(ship('Spanish',7,_,_,_),ship(_,_,_,_,'Marseille'),Shipes),
   exists(ship(_,_,_,'Red','Hamburg'),Shipes),
   nextTo(ship(_,_,_,'White',_),ship(_,7,_,_,_),Shipes),
   lastShip(ship(_,_,'Corn',_,_),Shipes),
   exists(ship(_,8,_,'Black',_),Shipes),
   nextTo(ship(_,_,'Corn',_,_),ship(_,_,'Rice',_,_),Shipes),
   exists(ship(_,6,_,_,'Hamburg'),Shipes),
   exists(ship(PortSaidShip,_,_,_,'Port Said'),Shipes),
   exists(ship(TeaCarrier,_,'Tea',_,_),Shipes).

但是当我运行程序时,它会说“假”。
那么我该如何解决呢?
谢谢你

4

2 回答 2

6

您问:

那么我该如何解决呢?

以下是一种通用方法,它始终适用于像您这样的纯单调 Prolog 程序。您的实际问题是特定目标应该成功,但它失败了。所以你遇到了意想不到的失败。为了本地化您程序的负责部分,我们现在将系统地概括您的程序。一步步。直到我们有一个很小的程序片段。这种技术有时称为程序切片,有时称为程序修改

首先,将以下内容添加到您的代码中:

:- op(950, fy, *).
*_.

:- initialization(solution(_Port, _Carrier)).

现在,我们将通过*在其前面添加一个来删除一个又一个目标,然后重新运行您的程序。所以准备好你将重新运行你的程序几次。要加载程序,请在顶层输入:

?- [shipes].

这几乎适用于任何地方,例如 SICStus、GNU、SWI、YAP。您现在将收到有关“失败指令”或类似内容的警告。所以 - 开心点 - 因为您现在可以轻松地重现问题!

开始*在最后一个目标处添加一个。你可以一次尝试几个。要在修改后重新加载,您可以重新输入该目标,或者

  • 在 SICStus 中,更好的状态ensure_loaded(shipes).这将检查文件是否已被修改,并且仅在已重新加载时才重新运行它

  • 在 SWI 中,输入make.

最后,我得到了以下程序片段:

中间船(A,(_,_,A,_,_))。

解决方案(PortSaidShip,TeaCarrier):-
   船舶 = (船舶(_,_,_,_,_),船舶(_,_,_,_,_),船舶(_,_,_,_,_),船舶(_,_,_, _,_),船(_,_,_,_,_)),
   * 存在(船('希腊',6,'咖啡',_,_),船舶),
   middleShip(ship(_,_,_,_,'Black',_),Shipes),
   *  exists(ship('English',9,_,_,_),Shipes) ,
    *  rightOf(ship(_,_,'Coffee',_,_),ship('French',_,_,'蓝色',_),Shipes) ,
    *  rightOf(ship(_,_,_,_,'Marseille'),ship(_,_,'Cocoa',_,_),Shipes) ,
    *  exists(ship( '巴西',_,_,_,'马尼拉'),Shipes) ,
    *  nextTo(ship(_,_,_,'Green',_),ship(_,_,'Rice',_,_) ,Shipes) ,
    * 存在(ship(_,5,_,_,'Genoa'),Shipes) ,
    *  rightOf(ship('Spanish',7,_,_,_),ship(_,_,_ ,_,'Marseille'),Shipes) ,
    * 存在(ship(_,_,_,'Red','Hamburg'),Shipes) ,
   *  nextTo(ship(_,_,_,'White',_),ship(_,7,_,_,_),Shipes),
    *  lastShip(ship(_,_,'Corn',_,_),Shipes) ,
    *  exists(ship(_,8,_,'Black',_),Shipes) ,
    *  nextTo(ship(_, _,'Corn',_,_),ship(_,_,'Rice',_,_),Shipes) ,
    * 存在(ship(_,6,_,_,'Hamburg'),Shipes) ,
    *  exists(ship(PortSaidShip,_,_,_,'Port Said'),Shipes) ,
    *  exists(ship(TeaCarrier,_,'Tea',_,_),Shipes)

所以你需要看懂四行代码才能理解你的问题!

正如其他人已经指出的那样,问题在于,一旦您ship/6在其他情况下使用ship/5.

另一句话:而不是(_,_,_,A,B)更好的写[_,_,_,A,B],这是常见的列表表示法。

于 2015-06-10T11:19:56.540 回答
1

ship(...)第二行(在解决方案谓词之后)中术语的参数数量是错误的。这是:

middleShip(ship(_,_,_,_,'Black',_),Shipes),

虽然它应该是:

middleShip(ship(_,_,_,'Black',_),Shipes),

我还没有检查这是否有效,但这肯定会导致您的求解器失败。

于 2015-06-09T19:14:45.980 回答