为什么我无法通过 Prolog 获得 Ship Puzzle 的答案? [英] Why I can't get an answer for the Ship Puzzle with Prolog?

查看:11
本文介绍了为什么我无法通过 Prolog 获得 Ship Puzzle 的答案?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<块引用>

有 5 艘船.

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

哪艘船开往塞得港?哪艘船运茶?

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

存在(A,(A,_,_,_,_)).存在(A,(_,A,_,_,_)).存在(A,(_,_,A,_,_)).存在(A,(_,_,_,A,_)).存在(A,(_,_,_,_,A)).正确的(A,B,(B,A,_,_,_)).正确的(A,B,(_,B,A,_,_)).正确的(A,B,(_,_,B,A,_)).正确的(A,B,(_,_,_,B,A)).中间船(A,(_,_,A,_,_)).最后一船(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)).解决方案(PortSaidShip,TeaCarrier):-船舶 = (船舶(_,_,_,_,_),船舶(_,_,_,_,_),船舶(_,_,_,_,_),船舶(_,_,_,_,_),船(_,_,_,_,_)),存在(船('希腊',6,'咖啡',_,_),船舶),middleShip(ship(_,_,_,_,'Black',_),Shipes),存在(船('英语',9,_,_,_),船舶),rightOf(ship(_,_,'Coffee',_,_),ship('French',_,_,'Blue',_),Shipes),rightOf(船(_,_,_,_,'Marseille'),船(_,_,'Cocoa',_,_),Shipes),存在(船舶('巴西',_,_,_,'马尼拉'),船舶),nextTo(ship(_,_,_,'Green',_),ship(_,_,'Rice',_,_),Shipes),存在(船(_,5,_,_,'热那亚'),船舶),rightOf(船('西班牙语',7,_,_,_),船(_,_,_,_,'马赛'),Shipes),存在(船(_,_,_,'红色','汉堡'),船舶),nextTo(船(_,_,_,'白',_),船(_,7,_,_,_),Shipes),lastShip(船(_,_,'Corn',_,_),Shipes),存在(船(_,8,_,'黑色',_),船舶),nextTo(ship(_,_,'Corn',_,_),ship(_,_,'Rice',_,_),Shipes),存在(船(_,6,_,_,'汉堡'),船舶),存在(船(PortSaidShip,_,_,_,'Port Said'),Shipes),存在(船(TeaCarrier,_,'茶',_,_),Shipes).

但是当我运行程序时它会说'false'.
那么我该如何解决这个问题呢?
谢谢

解决方案

你问:

<块引用>

那我该如何解决呢?

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

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

:- op(950, fy, *).*_.:- 初始化(解决方案(_Port,_Carrier)).

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

?- [shipes].

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

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

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

  • 在 SWI 中,输入 make.

最后得到如下程序片段:

<上一页>中间船(A,(_,_,A,_,_)).解决方案(PortSaidShip,TeaCarrier):-船舶 = (船舶(_,_,_,_,_),船舶(_,_,_,_,_),船舶(_,_,_,_,_),船舶(_,_,_,_,_),船(_,_,_,_,_)),* 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),* 存在(ship('Brazilian',_,_,_,'Manila'),Shipes),* nextTo(ship(_,_,_,'Green',_),ship(_,_,'Rice',_,_),Shipes),* 存在(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),* 存在(ship(_,8,_,'Black',_),Shipes),* nextTo(ship(_,_,'Corn',_,_),ship(_,_,'Rice',_,_),Shipes),* exists(ship(_,6,_,_,'Hamburg'),Shipes),* exists(ship(PortSaidShip,_,_,_,'Port Said'),Shipes),* 存在(ship(TeaCarrier,_,'Tea',_,_),Shipes).

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

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

另外说明:(_,_,_,A,B) 最好写成 [_,_,_,A,B] 代替 (_,_,_,A,B)常用列表表示法.

I need to solve the Ship Puzzle problem with using Prolog. Here are the facts.

There are 5 ships.

  1. The Greek ship leaves at six and carries coffee.
  2. The Ship in the middle has a black chimney.
  3. The English ship leaves at nine.
  4. The French ship with blue chimney is to the left of a ship that carries coffee.
  5. To the right of the ship carrying cocoa is a ship going to Marseille.
  6. The Brazilian ship is heading for Manila.
  7. Next to the ship carrying rice is a ship with a green chimney.
  8. A ship going to Genoa leaves at five.
  9. The Spanish ship leaves at seven and is to the right of the ship going to Marseille.
  10. The ship with a red chimney goes to Hamburg.
  11. Next to the ship leaving at seven is a ship with a white chimney.
  12. The ship on the border carries corn.
  13. The ship with a black chimney leaves at eight.
  14. The ship carrying corn is anchored next to the ship carrying rice.
  15. The ship to Hamburg leaves at six.

Which ship goes to Port Said? Which ship carries tea?

I search internet for answers, but I could not find any. So I refer 'The Zebra Puzzle' and accordingly I arranged the code for this problem. So this is my Prolog code the problem.

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

But when I run the program it will say 'false'.
So how can I solve this?
thank you

解决方案

You asked:

So how can I solve this?

The following is a general methodology, that always works for pure, monotonic Prolog programs like yours. Your actual problem is that a specific goal should succeed, but it fails. So you got an unexpected failure. To localize the responsible part of your program, we will now systematically generalize your program. Step by step. Until we have a tiny little program fragment. This technique is called sometimes program slicing and sometimes program modification.

First of all, add the following to your code:

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

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

Now we will remove one goal after the other by adding a * in front of it and then rerun your program. So be prepared that you will rerun your program for a couple of times. To load the program enter at the toplevel:

?- [shipes].

This works virtually everywhere, like in SICStus, GNU, SWI, YAP. You will get now a warning about a "failed directive" or similar. So - be happy - for you can now reproduce the problem with ease!

Start adding a * at the last goal. You might try several at once. To reload after modification you might reenter that goal, or

  • in SICStus, better state ensure_loaded(shipes). This checks if the file has been modified and only reruns it if it has been reloaded

  • in SWI, enter make.

Finally, I got the following program fragment:

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

So you need to understand four lines of code to understand your problem!

As others have already indicated, the problem is that once you use ship/6 and in other situations ship/5.

Another remark: In stead of (_,_,_,A,B) better write [_,_,_,A,B] which is the common list notation.

这篇关于为什么我无法通过 Prolog 获得 Ship Puzzle 的答案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆