为什么我无法通过Prolog获得Ship Puzzle的答案?

Pun*_*uth 3 prolog zebra-puzzle

我需要使用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).
Run Code Online (Sandbox Code Playgroud)

但是当我运行该程序时,它会说"假".
那我怎么解决这个问题呢?
谢谢

fal*_*lse 6

您询问:

那我怎么解决这个问题呢?

以下是一般方法,总是适用于像你这样纯粹,单调的Prolog程序.您的实际问题是特定目标应该成功,但它失败了.所以你意外失败了.为了本地化您的程序的负责部分,我们现在将系统地推广您的程序.一步步.直到我们有一个小小的程序片段.这种技术有时被称为程序切片,有时也称为程序修改.

首先,在代码中添加以下内容:

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

:- initialization(solution(_Port, _Carrier)).
Run Code Online (Sandbox Code Playgroud)

现在我们将在一个目标之后添加一个目标*,然后重新运行您的程序.所以要做好准备,重新运行你的程序几次.要加载程序,请在顶层输入:

?- [shipes].
Run Code Online (Sandbox Code Playgroud)

这几乎无处不在,如SICStus,GNU,SWI,YAP.您现在将收到有关"失败的指令"或类似内容的警告.所以 - 快乐 - 因为你现在可以轻松地重现问题!

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

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

  • 在SWI中,输入 make.

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

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

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).

因此,您需要了解四行代码才能理解您的问题!

正如其他人已经指出的那样,问题是一旦你使用ship/6和其他情况ship/5.

另一句话:代替(_,_,_,A,B)更好的写[_,_,_,A,B],这是常见的列表符号.