Prolog 寻路
Posted
技术标签:
【中文标题】Prolog 寻路【英文标题】:Prolog Path Finding 【发布时间】:2010-10-15 08:32:00 【问题描述】:如果我有以下谓词door,它声明两个房间之间有一扇门:
door(office, hall).
door(kitchen, office).
door(hall, "dining room").
door(kitchen, cellar).
door("dining room", kitchen).
以及声明门状态的谓词doorstate:
doorstate(hall, office, closed).
doorstate(hall, "dining room", opened).
doorstate("dining room", kitchen, opened).
doorstate(kitchen, office, opened).
doorstate(kitchen, cellar, opened).
如果两个房间之间的所有门都打开,则它们之间有一条通道。
如何编写规则来发现两个房间之间是否存在这样的通道?
【问题讨论】:
如果我有编辑能力,我会在“饭厅”周围加上单引号。否则是语法错误。另外,我会在每个逗号后加一个空格,否则会不一致且不可读。 修正了语法。也克服了热情并调整了语言。 @Matthew:“饭厅”是一个(序列化的)列表,“饭厅”是一个原子。所以,我会把“饭厅”改成“饭厅”,因为例如厨房在类型上等同于“厨房”。 ;) 【参考方案1】:prolog 的悲惨恐怖来得太快了。
wayopen(Room1,Room2) :- doorstate(Room1, Room2, opened).
wayopen(Room1,Room2) :- doorstate(Room1, RoomX, opened), wayopen(RoomX,Room2).
所以我不只是为你做作业,这里是如何理解它:
如果两个房间由一扇门连接并且门是打开的,则它们之间的路是开放的。 如果第一条路有一扇通往另一个房间的门,并且有一条从另一个房间到第二个房间的路,那么这条路在两个房间之间是开放的。请注意,这些规则只能通过一个方向的门。 你的功课是让它双向工作。
从大厅到哪里去?
?- wayopen(hall, X).
X = diningroom ;
X = kitchen ;
X = office ;
X = cellar ;
false.
以下是您可以往返的所有房间:
?- wayopen(Room1,Room2).
Room1 = hall,
Room2 = diningroom ;
Room1 = diningroom,
Room2 = kitchen ;
Room1 = kitchen,
Room2 = office ;
Room1 = kitchen,
Room2 = cellar ;
Room1 = hall,
Room2 = kitchen ;
Room1 = hall,
Room2 = office ;
Room1 = hall,
Room2 = cellar ;
Room1 = diningroom,
Room2 = office ;
Room1 = diningroom,
Room2 = cellar ;
false.
【讨论】:
我正在玩一些游戏 - 首先,您可能想占用“餐厅”之外的空间。另一件事是我写的代码只允许你单向通过一扇门。 是的,它现在可以工作,但是当我问 wayopen(hall,Room2) 时,答案应该是大厅和餐厅,但它显示了 4 个答案(餐厅、办公室、地窖),为什么?我怎样才能让它只打印餐厅。 我删除了第二条规则! :-) 使用这两个规则,您应该期待 4 个答案。原因是从餐厅可以到厨房,从厨房可以到地窖。 您的门似乎只有单向。你应该记住你去过哪里以避免循环(和堆栈溢出:-)。【参考方案2】:您需要描述一个对称且可传递的关系 (exists_way/2
)。
% Base cases
exists_way_(hall, 'dining room').
exists_way_('dining room', kitchen).
exists_way_(kitchen, office).
exists_way_(kitchen, cellar).
% Symmetric
exists_way(R1, R2) :- exists_way_(R1, R2) ; exists_way_(R2, R1).
% Transitive
exists_way(R1, R2) :-
exists_way_(R1, R3),
exists_way(R3, R2).
不过,此代码会过度生成解决方案。因此,您需要稍后过滤掉重复项。
【讨论】:
【参考方案3】:您需要描述一个对称且可传递的关系 (exists_way/2
)。
在支持制表的 Prolog(例如XSB)中,您可以以非常自然的方式表达这些关系,即就像它们在数学书中表达的那样。
:- table exists_way/2.
% Open doors
exists_way(hall, 'dining room').
exists_way('dining room', kitchen).
exists_way(kitchen, office).
exists_way(kitchen, cellar).
% Symmetry
exists_way(R1, R2) :-
exists_way(R2, R1).
% Transitivity
exists_way(R1, R2) :-
exists_way(R1, R3),
exists_way(R3, R2).
在这种情况下,查询 exists_way(R1, R2)
恰好提供了 25 个独特的解决方案。
【讨论】:
【参考方案4】:本着学习的精神:这与您在序言课程的第一周可能遇到的祖父母问题相同。
事实证明,你将在 prolog 中做的很多事情在结构上都非常相似。因此,请确保您掌握有关递归谓词的概念,以及子句的顺序,以便更正和执行。
例如,您应该尽可能避免非尾递归。
【讨论】:
以上是关于Prolog 寻路的主要内容,如果未能解决你的问题,请参考以下文章