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

如何用Z3实现无向图连通性检测以解决中国邮路问题?

基于Z3的中国邮路问题求解器:补充连通性检测

你已经实现了欧拉回路的第一个条件(所有节点度数为偶数),但缺少连通性验证。用传递闭包检测无向图的连通性是可行的,下面是具体实现方案:

实现思路

无向图的连通性要求任意两个节点之间都存在路径,传递闭包正好可以描述这种可达关系:

  • 定义布尔矩阵reachable,reachable[i][j]表示节点i到j是否可达
  • 初始化:每个节点自身可达,直接相连的节点互相可达
  • 添加传递性约束:若i可达k且k可达j,则i可达j
  • 最终验证所有节点对之间都可达

修改后的完整代码

from z3 import *

solver = Solver()

nodes = ["A", "B", "C", "D", "E", "F", "G"]
numnodes = 7

edges = [ ["A", "B", 5], ["B", "C", 1], ["C", "D", 7], ["D", "A", 9], ["E", "F", 3], ["F", "G", 2], ["G", "E", 3]]

# 1. 处理度数为偶数的条件
degree = [0] * numnodes
for x, y, z in edges:
    degree[nodes.index(x)] += 1
    degree[nodes.index(y)] += 1

for i in range(numnodes):
    solver.add(degree[i] % 2 == 0)

# 2. 用传递闭包实现连通性检测
# 创建可达性布尔矩阵
reachable = [[Bool(f"reachable_{i}_{j}") for j in range(numnodes)] for i in range(numnodes)]

# 初始化:每个节点自身可达
for i in range(numnodes):
    solver.add(reachable[i][i] == True)

# 初始化:直接相连的节点互相可达(无向边)
for x, y, z in edges:
    i = nodes.index(x)
    j = nodes.index(y)
    solver.add(reachable[i][j] == True)
    solver.add(reachable[j][i] == True)

# 添加传递性约束:若i可达k且k可达j,则i可达j
for i in range(numnodes):
    for k in range(numnodes):
        for j in range(numnodes):
            solver.add(Implies(And(reachable[i][k], reachable[k][j]), reachable[i][j]))

# 要求所有节点两两可达
for i in range(numnodes):
    for j in range(numnodes):
        if i != j:
            solver.add(reachable[i][j] == True)

# 求解并输出结果
if solver.check() == sat:
    print("存在欧拉回路(中国邮路问题有最优解:直接走欧拉回路)")
else:
    print("不存在欧拉回路,需要添加重复边构建最优路径")

代码说明

  • 新增的reachable矩阵用于建模节点间的可达关系
  • 传递性约束通过Z3的Implies和And表达式实现,确保可达关系的传递性
  • 最后强制所有节点两两可达,保证图是连通的
  • 测试你的示例图时,因为存在两个独立的连通分量,求解器会返回unsat,输出正确的结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 13:04:55