我需要使用Prolog来解决Ship Puzzle问题。 以下是事实。
共有5艘船。
- 希腊船只在六点起飞,带着咖啡。
- 中间的船有一个黑色的烟囱。
- 英国船只在9点离开。
- 带有蓝色烟囱的法国船只位于运载咖啡的船的左侧。
- 载着可可的船的右边是一艘前往马赛的船。
- 这艘巴西船正前往马尼拉。
- 在运载大米的船旁边是一艘带有绿色烟囱的船。
- 一艘前往热那亚的船只在五点离开。
- 西班牙船在七点离开,在船的右边,前往马赛。
- 带红色烟囱的船前往汉堡。
- 在七号船离开的旁边是一艘带有白色烟囱的船。
- 边境的船上有玉米。
- 带有黑色烟囱的船只在八点落下。
- 运载玉米的船停泊在运载大米的船旁。
- 前往汉堡的船只在六点离开。
醇>哪艘船去了赛义德港?哪艘船载茶?
我在网上搜索答案,但我找不到任何答案。所以我引用了“斑马拼图”#39;因此我安排了这个问题的代码。所以这是我的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).
但是当我运行该程序时,它会说“假”'。那么我该如何解决这个问题?
谢谢
答案 0 :(得分:6)
你问:
那我怎么解决这个问题呢?
以下是一般方法,总是适用于像您这样的纯粹,单调的Prolog程序。您的实际问题是特定目标应该成功,但它失败了。所以你遇到了意外失败。为了本地化您的程序的负责部分,我们现在将系统地推广您的程序。一步步。直到我们有一个小小的程序片段。此技术有时称为程序切片,有时称为程序修改。
首先,在代码中添加以下内容:
:- op(950, fy, *).
*_.
:- initialization(solution(_Port, _Carrier)).
现在,我们将在其中删除一个目标,在其前面添加 *
,然后重新运行您的程序。所以要做好准备,重新运行你的程序几次。要加载程序,请输入toplevel:
?- [shipes].
这几乎适用于所有地方,例如SICStus,GNU,SWI,YAP。您现在将收到关于"失败指令的警告"或类似的。所以 - 快乐 - 因为你现在可以轻松地重现问题!
开始在最后一个目标添加 *
。你可以一次尝试几个。
要在修改后重新加载,您可以重新进入该目标,或
在SICStus中,更好的状态ensure_loaded(shipes).
这将检查文件是否已被修改,只有在重新加载后才重新运行
,输入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]
这是常见的列表符号。
答案 1 :(得分:1)
第二行中的术语ship(...)
的参数数量(在解决方案谓词之后)是错误的。它是:
middleShip(ship(_,_,_,_,'Black',_),Shipes),
虽然它应该是:
middleShip(ship(_,_,_,'Black',_),Shipes),
我还没有检查过这是否有效,但这会导致你的求解器失败。