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

在SWI Prolog中求解无向图内部稳定性数(最大独立子图)问题

求解无向图的内部稳定性数(最大独立集规模)

看起来你已经把图的基础表示(顶点、边、非相邻顶点对)都搞定了,接下来核心就是找出最大独立集——也就是你说的最大空点子图,它的规模就是内部稳定性数。下面给你一步步的实现思路和Prolog代码:

一、明确独立集的核心规则

首先先锚定独立集的两个关键判定条件,方便后续代码实现:

  • 集合里的所有元素都是图的合法顶点(对应你定义的ver/1)
  • 集合中任意两个顶点都不相邻(也就是任意一对顶点都满足你实现的nonadjacency/2)

二、生成所有合法的独立集

我们可以用递归的方式枚举所有符合规则的独立集,逻辑很简单:

  1. 空集本身就是一个合法的独立集
  2. 对于一个已有的独立集Set,如果能找到一个顶点V——它不在Set里,且和Set里的所有顶点都不相邻——那么把V加入Set后得到的新集合也是独立集

对应的Prolog代码:

% 空集是基础独立集
independent_set([]).
% 递归生成更大的独立集:在已有集合基础上添加合法顶点
independent_set([V | Set]) :-
    ver(V),
    independent_set(Set),
    % 确保V不在已有集合中,且与集合内所有顶点都不相邻
    \+ member(V, Set),
    forall(member(U, Set), nonadjacency(V, U)).

三、找出规模最大的独立集

有了生成所有独立集的方法后,我们需要筛选出其中规模最大的集合,进而得到内部稳定性数。这里提供两种实现思路:

方法1:全量生成后筛选(适合小规模图)

先收集所有独立集,再找出长度最大的那些:

% 收集所有独立集到列表中
all_independent_sets(AllSets) :-
    findall(Set, independent_set(Set), AllSets).

% 找出列表中长度最大的独立集
max_independent_set(MaxSet) :-
    all_independent_sets(AllSets),
    % 提取所有集合的长度,找到最大值
    maplist(length, AllSets, Lengths),
    max_list(Lengths, MaxLen),
    % 筛选出长度为MaxLen的集合
    member(MaxSet, AllSets),
    length(MaxSet, MaxLen).

% 直接返回内部稳定性数(最大独立集的规模)
internal_stability_number(Num) :-
    max_independent_set(MaxSet),
    length(MaxSet, Num).

方法2:带剪枝的优化搜索(适合较大规模图)

如果图的顶点数量较多,全量生成所有独立集会比较低效。我们可以用回溯+剪枝的方式,在搜索过程中记录当前找到的最大长度,一旦后续搜索不可能超过这个长度就直接停止,节省资源:

% 初始调用:从第一个顶点开始搜索,初始化状态
max_independent_set_optimized(MaxSet) :-
    ver(First), !,
    max_independent_set_optimized([First], [First], 1, MaxSet, _).
max_independent_set_optimized([]). % 处理空图的边界情况

% 递归尝试添加新顶点,扩展当前独立集
max_independent_set_optimized(CurrentSet, Visited, CurrentMax, FinalSet, FinalMax) :-
    % 找到一个未访问、且与当前集合所有顶点不相邻的顶点
    ver(V),
    \+ member(V, Visited),
    forall(member(U, CurrentSet), nonadjacency(V, U)),
    NewSet = [V | CurrentSet],
    NewLen is CurrentMax + 1,
    NewVisited = [V | Visited],
    % 继续搜索更大的集合
    max_independent_set_optimized(NewSet, NewVisited, NewLen, FinalSet, FinalMax).

% 回溯逻辑:当前集合无法扩展时,对比更新最大集合
max_independent_set_optimized(CurrentSet, Visited, CurrentMax, FinalSet, FinalMax) :-
    % 判断是否还有可能找到更大的集合:剩余未访问顶点数量不足以超过当前最大长度,或者没有可添加的顶点
    (   findall(V, (ver(V), \+ member(V, Visited)), Remaining),
        length(Remaining, RemLen),
        CurrentMax + RemLen =< CurrentMax
    ;   \+ (ver(V), \+ member(V, Visited), forall(member(U, CurrentSet), nonadjacency(V, U)))
    ),
    % 更新最终的最大集合和长度
    (   CurrentMax > FinalMaxTemp
        -> FinalSet = CurrentSet, FinalMax = CurrentMax
        ; FinalSet = FinalSetTemp, FinalMax = FinalMaxTemp
    ), !.

四、测试你的示例图

对于你给出的测试图,运行internal_stability_number(Num)会返回Num = 3,和你标注的示例结果一致。比如[1,4,5]、[2,4,7]都是符合要求的最大独立集。

另外注意你现有代码里的小错误:dfs/4中的not(member(X, VisitedNode))应该是not(member(X, VisitedNodes))(变量名拼写错误),不过这个不影响独立集的求解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 19:32:34