Prolog简单规划问题合法移动谓词补全咨询
问题修复说明
你现有代码的核心缺失分为两部分:
- 未定义位置互斥判断谓词
opposite/2,所有合法移动的前置判断无法执行 legal_move/3仅实现了农夫独自移动的规则,遗漏了农夫携带三类物品往返的合法动作定义
编写思路
- 先补全基础位置事实:问题场景仅有
yard、market两个位置,二者互为对侧,直接写事实规则即可 - 逐一定义三类带物移动的规则,每条规则必须满足三个约束:
- 被携带的物品当前与农夫(推车)处于同一位置
- 移动目标位置为农夫当前所在位置的对侧
- 移动完成后的新状态满足安全约束(不存在无农夫看管时,狐狸和鸡、鸡和谷物同处一侧的危险情况)
- 额外注意:现有搜索逻辑未做状态去重,补全移动规则后也容易出现往返空转的死循环,需要补充已访问状态判断避免重复搜索
补全代码
首先在现有代码末尾补充位置互斥规则:
opposite(yard, market). opposite(market, yard).
接着补充三个携带物品移动的legal_move子句,接在已有的go_alone规则后即可:
% 农夫带狐狸移动 legal_move([LocFox, LocHen, LocGrain, LocCart], take_fox(LocNew), [LocNew, LocHen, LocGrain, LocNew]) :- opposite(LocCart, LocNew), LocFox = LocCart, safe([LocNew, LocHen, LocGrain, LocNew]). % 农夫带鸡移动 legal_move([LocFox, LocHen, LocGrain, LocCart], take_hen(LocNew), [LocFox, LocNew, LocGrain, LocNew]) :- opposite(LocCart, LocNew), LocHen = LocCart, safe([LocFox, LocNew, LocGrain, LocNew]). % 农夫带谷物移动 legal_move([LocFox, LocHen, LocGrain, LocCart], take_grain(LocNew), [LocFox, LocHen, LocNew, LocNew]) :- opposite(LocCart, LocNew), LocGrain = LocCart, safe([LocFox, LocHen, LocNew, LocNew]).
可选搜索逻辑优化
现有reachable实现无状态记忆,搜索时会反复走到相同状态陷入死循环,建议修改为带已访问列表的版本:
% 重写plan入口,初始化空的已访问状态列表 plan(L) :- initial_state(I), goal_state(G), reachable(I,L,G, [I]). % 终止条件保持不变 reachable(S,[],S,_). % 递归时校验新状态未访问过,再加入已访问列表 reachable(S1,[M|L],S3, Visited) :- legal_move(S1,M,S2), \+ member(S2, Visited), reachable(S2,L,S3, [S2|Visited]).
补全后执行查询bplan(L)即可得到正确的7步规划结果,逻辑为:带鸡去市场→独自返回院子→带狐狸(或谷物)去市场→带鸡返回院子→带剩下的谷物(或狐狸)去市场→独自返回院子→带鸡去市场。
内容的提问来源于stack exchange,提问作者unmyelinated neuron
相关产品推荐
相关产品推荐

