You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于生成测试法的SWI-Prolog寻路程序构建咨询

嘿,我来帮你一步步搞定这个基于生成测试法的SWI-Prolog寻路程序~咱们先把需求拆清楚,再落地到代码实现:

1. 先明确核心规则与元素

首先咱们把问题里的关键信息捋顺:

  • 起点L固定是(1,1),终点F是网格的右下角(Xmax, Ymax)(也就是例子里的(6,6))
  • 网格的边界由y_max(Ymax)和x_max(Xmax)定义,移动不能超出这个范围
  • pick_up(Y,X)是需要经过的拾取点(如果你的需求是必须经过所有拾取点的话,咱们后面会做这个测试)
  • 生成测试法的核心思路很直白:先生成所有可能的合法路径,再测试这些路径是否满足要求(比如到达终点、经过所有拾取点)
2. 实现基础的合法移动规则

首先得定义什么是“合法移动”:只能上下左右走相邻单元格,不能越界,也不能重复踩同一个点(避免无限循环)。咱们写一个谓词来判断:

% 合法移动:从(Y,X)到(NewY, NewX),未越界且未访问过
valid_move(Y, X, NewY, NewX, Visited) :-
    % 上下左右四个方向
    (NewY is Y+1 ; NewY is Y-1 ; NewX is X+1 ; NewX is X-1),
    % 排除原地不动的情况
    (NewY \= Y ; NewX \= X),
    % 检查是否在网格边界内
    y_max(Ymax), x_max(Xmax),
    NewY >= 1, NewY =< Ymax,
    NewX >= 1, NewX =< Xmax,
    % 确保这个点还没走过
    \+ member((NewY, NewX), Visited).
3. 生成所有可能的路径

接下来用递归的方式生成从起点到终点的所有路径:

% 基础情况:已经到达终点,路径就是当前节点
generate_path(Y, X, [(Y,X)]) :-
    y_max(Ymax), x_max(Xmax),
    Y = Ymax, X = Xmax.

% 递归情况:从当前点移动到合法的下一个点,继续生成路径
generate_path(Y, X, [(Y,X)|RestPath]) :-
    % 第一步移动要合法,且没走过当前点
    valid_move(Y, X, NewY, NewX, [(Y,X)]),
    % 递归生成后续路径
    generate_path(NewY, NewX, RestPath),
    % 确保整个路径里没有重复节点
    \+ member((Y,X), RestPath).
4. 测试路径是否符合要求

现在咱们需要测试生成的路径是否满足需求——比如必须经过所有拾取点。写一个测试谓词:

% 测试路径是否包含所有拾取点
test_path(Path) :-
    % 先把所有拾取点收集成列表
    findall((Y,X), pick_up(Y,X), PickUps),
    % 检查所有拾取点都在路径里
    subset(PickUps, Path).

% 主谓词:找到符合要求的路径
find_valid_path(Path) :-
    % 从起点(1,1)生成路径
    generate_path(1, 1, Path),
    % 测试路径是否满足条件
    test_path(Path).
5. 优化与扩展建议

生成测试法虽然简单直观,但在大网格里效率会比较低,这里给你几个优化方向:

  • 剪枝优化:在递归生成路径时,如果当前位置到终点的曼哈顿距离大于剩余可走步数,直接停止这条分支(不过需要先计算剩余步数的上限)
  • 灵活调整规则:如果不需要必须经过所有拾取点,直接去掉test_path(Path)的检查,只保留生成到终点的路径即可
  • 路径可视化:可以加一个打印路径的谓词,把路径在网格上标出来,方便调试:
    print_path(Path) :-
        y_max(Ymax), x_max(Xmax),
        % 从Ymax到1倒着打印(因为你的网格是Y从1到6,1在最下面)
        forall(between(Ymax, 1, Y), (
            write('|'),
            forall(between(1, Xmax, X), (
                (member((Y,X), Path) -> 
                    (Y=Ymax, X=Xmax -> write('F|') ; 
                     pick_up(Y,X) -> write('P|') ; 
                     Y=1, X=1 -> write('L|') ; 
                     write('*|')) ; 
                 write(' |'))
            )),
            nl, write('-------------'), nl
        )).
    
6. 测试运行

把你的知识库事实和上面的代码放到SWI-Prolog里加载:

y_max(6).
x_max(6).
pick_up(4,4).
pick_up(3,2).

然后查询find_valid_path(Path).就能得到符合要求的路径,或者用find_valid_path(Path), print_path(Path).直接可视化路径。

内容的提问来源于stack exchange,提问作者TheDarkHoarse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:53:18