为什么我无法用 Prolog 得到 Ship Puzzle 的答案?
Why I can't get an answer for the Ship Puzzle with Prolog?
我需要使用 Prolog 解决 Ship Puzzle 问题。
这是事实。
There are 5 ships.
- The Greek ship leaves at six and carries coffee.
- The Ship in the middle has a black chimney.
- The English ship leaves at nine.
- The French ship with blue chimney is to the left of a ship that carries coffee.
- To the right of the ship carrying cocoa is a ship going to Marseille.
- The Brazilian ship is heading for Manila.
- Next to the ship carrying rice is a ship with a green chimney.
- A ship going to Genoa leaves at five.
- The Spanish ship leaves at seven and is to the right of the ship going to Marseille.
- The ship with a red chimney goes to Hamburg.
- Next to the ship leaving at seven is a ship with a white chimney.
- The ship on the border carries corn.
- The ship with a black chimney leaves at eight.
- The ship carrying corn is anchored next to the ship carrying rice.
- The ship to Hamburg leaves at six.
Which ship goes to Port Said? Which ship carries tea?
我在网上搜索答案,但找不到任何答案。所以我引用 'The Zebra Puzzle' 并相应地为这个问题安排了代码。所以这是我的 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).
但是当我运行程序时它会说'false'。
那么我该如何解决这个问题呢?
谢谢
第二行(在解决谓词之后)中术语 ship(...)
的参数数量是错误的。它是:
middleShip(ship(_,_,_,_,'Black',_),Shipes),
虽然应该是:
middleShip(ship(_,_,_,'Black',_),Shipes),
我还没有检查这是否有效,但这肯定会导致您的求解器失败。
您问的是:
So how can I solve this?
以下是一种通用方法,它始终适用于像您这样的纯单调 Prolog 程序。你的实际问题是一个特定的目标应该成功,但它失败了。所以你遇到了 意外故障 。为了本地化您程序的负责部分,我们现在将系统地概括您的程序。一步步。直到我们有一个很小的程序片段。这种技术有时称为程序切片,有时称为程序修改。
首先,将以下内容添加到您的代码中:
:- op(950, fy, *).
*_.
:- initialization(solution(_Port, _Carrier)).
现在我们将通过在目标前面添加 *
一个接一个地删除目标,然后重新运行您的程序。因此请做好准备,您将重新运行您的程序几次。要加载程序,请在顶层输入:
?- [shipes].
这几乎适用于任何地方,例如 SICStus、GNU、SWI、YAP。您现在将收到有关 "failed directive" 或类似内容的警告。所以 - 高兴 - 因为您现在可以轻松重现问题!
开始在最后一个目标添加 *
。你可以一次尝试几个。
要在修改后重新加载,您可以重新输入该目标,或者
在 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)
,这是常见的列表表示法。
我需要使用 Prolog 解决 Ship Puzzle 问题。 这是事实。
There are 5 ships.
- The Greek ship leaves at six and carries coffee.
- The Ship in the middle has a black chimney.
- The English ship leaves at nine.
- The French ship with blue chimney is to the left of a ship that carries coffee.
- To the right of the ship carrying cocoa is a ship going to Marseille.
- The Brazilian ship is heading for Manila.
- Next to the ship carrying rice is a ship with a green chimney.
- A ship going to Genoa leaves at five.
- The Spanish ship leaves at seven and is to the right of the ship going to Marseille.
- The ship with a red chimney goes to Hamburg.
- Next to the ship leaving at seven is a ship with a white chimney.
- The ship on the border carries corn.
- The ship with a black chimney leaves at eight.
- The ship carrying corn is anchored next to the ship carrying rice.
- The ship to Hamburg leaves at six.
Which ship goes to Port Said? Which ship carries tea?
我在网上搜索答案,但找不到任何答案。所以我引用 'The Zebra Puzzle' 并相应地为这个问题安排了代码。所以这是我的 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).
但是当我运行程序时它会说'false'。
那么我该如何解决这个问题呢?
谢谢
第二行(在解决谓词之后)中术语 ship(...)
的参数数量是错误的。它是:
middleShip(ship(_,_,_,_,'Black',_),Shipes),
虽然应该是:
middleShip(ship(_,_,_,'Black',_),Shipes),
我还没有检查这是否有效,但这肯定会导致您的求解器失败。
您问的是:
So how can I solve this?
以下是一种通用方法,它始终适用于像您这样的纯单调 Prolog 程序。你的实际问题是一个特定的目标应该成功,但它失败了。所以你遇到了 意外故障 。为了本地化您程序的负责部分,我们现在将系统地概括您的程序。一步步。直到我们有一个很小的程序片段。这种技术有时称为程序切片,有时称为程序修改。
首先,将以下内容添加到您的代码中:
:- op(950, fy, *).
*_.
:- initialization(solution(_Port, _Carrier)).
现在我们将通过在目标前面添加 *
一个接一个地删除目标,然后重新运行您的程序。因此请做好准备,您将重新运行您的程序几次。要加载程序,请在顶层输入:
?- [shipes].
这几乎适用于任何地方,例如 SICStus、GNU、SWI、YAP。您现在将收到有关 "failed directive" 或类似内容的警告。所以 - 高兴 - 因为您现在可以轻松重现问题!
开始在最后一个目标添加 *
。你可以一次尝试几个。
要在修改后重新加载,您可以重新输入该目标,或者
在 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)
,这是常见的列表表示法。