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

SWI-Prolog中模式匹配计数的高效算法实现咨询

高效SWI-Prolog模式计数优化方案(五子棋AI场景)

针对五子棋AI频繁棋盘评估的性能需求,以下是对原有模式计数实现的优化方案,核心目标是降低findall和append带来的开销,提升匹配与计数效率。

问题分析

原有实现依赖findall收集所有匹配结果再求和,且用append拆分列表实现子串匹配,在高频调用场景下会产生大量内存分配与列表操作开销,不利于AI决策的实时性。

优化方案1:递归累加计数+前缀匹配

该方案移除findall和append,改用递归遍历+前缀匹配的方式直接累加计数,避免临时列表存储与列表拆分开销。

% 主谓词:计算Pattern在List中的出现次数
count_occurrences(Pattern, List, Count) :-
    phrase(Pattern, PatternList),
    length(PatternList, PatternLen),
    count_occurrences_rec(List, PatternList, PatternLen, 0, Count).

% 递归终止条件:剩余列表长度不足模式长度,返回当前计数
count_occurrences_rec(List, _Pattern, PatternLen, Current, Current) :-
    length(List, L),
    L < PatternLen,
    !.
% 匹配成功:计数+1,从下一个元素继续遍历
count_occurrences_rec(List, Pattern, PatternLen, Current, Final) :-
    prefix(Pattern, List),
    !,
    NextCurrent is Current + 1,
    List = [_|Rest],
    count_occurrences_rec(Rest, Pattern, PatternLen, NextCurrent, Final).
% 匹配失败:直接遍历下一个元素
count_occurrences_rec([_|Rest], Pattern, PatternLen, Current, Final) :-
    count_occurrences_rec(Rest, Pattern, PatternLen, Current, Final).

% 高效前缀匹配谓词,替代原sublist实现
prefix([], _) :- !.
prefix([H|T], [H|Rest]) :-
    prefix(T, Rest).

% 原有DCG模式定义(修正HTML转义的箭头符号)
rep(S, L) --> [], {L is 0} | [S], {L is 1} | [S], { L_1 is L - 1 }, rep(S, L_1), !.
open_rep(S, L) --> [v], rep(S, L), [v], !.

测试验证

1 ?- count_occurrences(open_rep(n, 1), [v,n,v,n,v,v,v,v,v,v,n,v,v], Count).
Count = 3.

2 ?- count_occurrences(open_rep(n, 3), [v,n,v,n,v,v,v,v,v,v,n,n,n,v,v], Count).
Count = 1.

3 ?- count_occurrences(open_rep(n, 1), [v,n,v,n,v,v,v,v,v,v,n,n,n,v,v], Count).
Count = 2.

优化点说明

  • 移除findall与sum_list:递归累加计数,避免创建存储所有匹配结果的临时列表,减少内存开销
  • 前缀匹配替代列表拆分:prefix/2直接匹配列表前缀,无需用append拆分列表,大幅降低列表操作的时间消耗
  • 提前终止递归:当剩余列表长度小于模式长度时直接返回,避免无效匹配尝试

优化方案2:纯DCG流式计数

该方案完全基于DCG实现匹配与计数,省去将Pattern转换为列表的步骤,进一步提升性能。

% 主谓词:通过DCG直接计数Pattern出现次数
count_occurrences_dcg(Pattern, List, Count) :-
    phrase(count_pattern(Pattern, 0, Count), List).

% DCG规则:匹配成功则计数+1,继续遍历
count_pattern(Pattern, Current, Final) -->
    call(Pattern),
    !,
    { Next is Current + 1 },
    count_pattern(Pattern, Next, Final).
% DCG规则:匹配失败则遍历下一个元素
count_pattern(Pattern, Current, Final) -->
    [_],
    count_pattern(Pattern, Current, Final).
% DCG终止规则:遍历结束,返回最终计数
count_pattern(_, Final, Final) --> [].

% 原有DCG模式定义
rep(S, L) --> [], {L is 0} | [S], {L is 1} | [S], { L_1 is L - 1 }, rep(S, L_1), !.
open_rep(S, L) --> [v], rep(S, L), [v], !.

测试验证

1 ?- count_occurrences_dcg(open_rep(n, 1), [v,n,v,n,v,v,v,v,v,v,n,v,v], Count).
Count = 3.

2 ?- count_occurrences_dcg(open_rep(n, 3), [v,n,v,n,v,v,v,v,v,v,n,n,n,v,v], Count).
Count = 1.

3 ?- count_occurrences_dcg(open_rep(n, 1), [v,n,v,n,v,v,v,v,v,v,n,n,n,v,v], Count).
Count = 2.

优化点说明

  • 纯DCG流式处理:直接在DCG中调用Pattern进行匹配,省去phrase(Pattern, PatternList)的转换步骤,减少额外计算
  • 无中间存储:遍历列表时边匹配边计数,全程无需存储中间结果,性能更优

五子棋AI场景额外优化建议

  • 预编译常用模式:将五子棋中高频使用的模式(如连子、活二等)提前转换为固定列表,避免每次调用时重新解析DCG
  • 区域剪枝:在棋盘评估时,仅遍历可能形成目标模式的区域(如已有棋子的周边区域),减少无效遍历范围
  • 启用SWI-Prolog编译优化:执行set_prolog_flag(optimise, true)开启编译级优化,提升代码执行速度

内容的提问来源于stack exchange,提问作者René Chenard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 23:22:08