- 序言教程
- 序言 - 主页
- Prolog - 简介
- Prolog - 环境设置
- Prolog - 你好世界
- Prolog - 基础知识
- Prolog - 关系
- Prolog - 数据对象
- Prolog - 运算符
- 循环与决策
- 连接词和析取词
- Prolog - 列表
- 递归和结构
- Prolog - 回溯
- Prolog - 不同与不同
- Prolog - 输入和输出
- Prolog - 内置谓词
- 树数据结构(案例研究)
- Prolog - 示例
- Prolog - 基本程序
- Prolog - 剪切示例
- 河内塔问题
- Prolog - 链接列表
- 猴子和香蕉问题
- Prolog 有用资源
- Prolog - 快速指南
- Prolog - 有用的资源
- Prolog - 讨论
Prolog - 猴子和香蕉问题
在这个序言示例中,我们将看到一个非常有趣且著名的问题,猴子和香蕉问题。
问题陈述
假设问题如下 -
房间里有一只饥饿的猴子,它靠近门。
猴子在地板上。
房间天花板中央挂着香蕉。
房间里靠近窗户的地方有一个木块(或椅子)。
猴子想要香蕉,但够不到。
那么猴子怎样才能得到香蕉呢?
因此,如果猴子足够聪明,他可以来到积木面前,将积木拖到中心,爬上积木,然后得到香蕉。以下是这种情况下的一些观察结果 -
如果猴子和猴子在同一水平线上,猴子就能到达方块。从上图中,我们可以看到猴子和木块都在地板上。
如果方块位置不在中心,那么猴子可以将其拖动到中心。
如果猴子和木块都在地板上,并且木块位于中心,那么猴子可以爬上木块。这样猴子的垂直位置就会改变。
当猴子在方块上,并且方块在中心时,猴子就可以得到香蕉。
现在,让我们看看如何使用 Prolog 解决这个问题。我们将创建一些谓词如下 -
我们有一些谓词通过执行操作从一种状态转移到另一种状态。
当方块在中间,而猴子在方块上方,而猴子没有香蕉(即没有状态)时,那么使用抓取动作,它会从没有状态变为有状态。
通过执行爬升动作,它可以从地板移动到方块的顶部(即顶部状态)。
推或拖操作将块从一个位置移动到另一个位置。
猴子可以使用walk或move子句从一个地方移动到另一个地方。
另一个谓词是 canget()。这里我们传递一个状态,因此这将使用不同的操作执行从一个状态到另一个状态的移动谓词,然后在状态 2 上执行 canget()。当我们到达状态“has>”时,这表示“有香蕉”。我们将停止执行。
程序
move(state(middle,onbox,middle,hasnot), grasp, state(middle,onbox,middle,has)). move(state(P,onfloor,P,H), climb, state(P,onbox,P,H)). move(state(P1,onfloor,P1,H), drag(P1,P2), state(P2,onfloor,P2,H)). move(state(P1,onfloor,B,H), walk(P1,P2), state(P2,onfloor,B,H)). canget(state(_,_,_,has)). canget(State1) :- move(State1,_,State2), canget(State2).
输出
| ?- [monkey_banana]. compiling D:/TP Prolog/Sample_Codes/monkey_banana.pl for byte code... D:/TP Prolog/Sample_Codes/monkey_banana.pl compiled, 17 lines read - 2167 bytes written, 19 ms (31 ms) yes | ?- canget(state(atdoor, onfloor, atwindow, hasnot)). true ? yes | ?- trace . The debugger will first creep -- showing everything (trace) yes {trace} | ?- canget(state(atdoor, onfloor, atwindow, hasnot)). 1 1 Call: canget(state(atdoor,onfloor,atwindow,hasnot)) ? 2 2 Call: move(state(atdoor,onfloor,atwindow,hasnot),_52,_92) ? 2 2 Exit:move(state(atdoor,onfloor,atwindow,hasnot),walk(atdoor,_80),state(_80,onfloor,atwindow,hasnot)) ? 3 2 Call: canget(state(_80,onfloor,atwindow,hasnot)) ? 4 3 Call: move(state(_80,onfloor,atwindow,hasnot),_110,_150) ? 4 3 Exit: move(state(atwindow,onfloor,atwindow,hasnot),climb,state(atwindow,onbox,atwindow,hasnot)) ? 5 3 Call: canget(state(atwindow,onbox,atwindow,hasnot)) ? 6 4 Call: move(state(atwindow,onbox,atwindow,hasnot),_165,_205) ? 6 4 Fail: move(state(atwindow,onbox,atwindow,hasnot),_165,_193) ? 5 3 Fail: canget(state(atwindow,onbox,atwindow,hasnot)) ? 4 3 Redo: move(state(atwindow,onfloor,atwindow,hasnot),climb,state(atwindow,onbox,atwindow,hasnot)) ? 4 3 Exit: move(state(atwindow,onfloor,atwindow,hasnot),drag(atwindow,_138),state(_138,onfloor,_138,hasnot)) ? 5 3 Call: canget(state(_138,onfloor,_138,hasnot)) ? 6 4 Call: move(state(_138,onfloor,_138,hasnot),_168,_208) ? 6 4 Exit: move(state(_138,onfloor,_138,hasnot),climb,state(_138,onbox,_138,hasnot)) ? 7 4 Call: canget(state(_138,onbox,_138,hasnot)) ? 8 5 Call: move(state(_138,onbox,_138,hasnot),_223,_263) ? 8 5 Exit: move(state(middle,onbox,middle,hasnot),grasp,state(middle,onbox,middle,has)) ? 9 5 Call: canget(state(middle,onbox,middle,has)) ? 9 5 Exit: canget(state(middle,onbox,middle,has)) ? 7 4 Exit: canget(state(middle,onbox,middle,hasnot)) ? 5 3 Exit: canget(state(middle,onfloor,middle,hasnot)) ? 3 2 Exit: canget(state(atwindow,onfloor,atwindow,hasnot)) ? 1 1 Exit: canget(state(atdoor,onfloor,atwindow,hasnot)) ? true ? (78 ms) yes