Z3 查找两个节点之间的路径

Z3 查找两个节点之间的路径,z3,smt,z3py,Z3,Smt,Z3py,我想知道是否有一种方法可以在z3py中构建拓扑,如果给我6个节点,即:n1、n2、n3、n4、n5、n6,它们之间有某些链接,例如l12(这意味着节点n1和n2之间有链接)、l16、l23、l25、l34、l35、l36。我可以将l_{I}{j}定义为bool变量,以便它可以引用2个节点或节点之间是否存在任何链接(当然,我必须以这种方式定义所有可能的链接)。问题是如何在Z3py中定义路径的概念,这样我就可以知道两个节点之间是否存在任何路径(如果是SAT,那么是SAT还是UNSAT,哪个路径?)。

我想知道是否有一种方法可以在z3py中构建拓扑,如果给我6个节点,即:n1、n2、n3、n4、n5、n6,它们之间有某些链接,例如l12(这意味着节点n1和n2之间有链接)、l16、l23、l25、l34、l35、l36。我可以将l_{I}{j}定义为bool变量,以便它可以引用2个节点或节点之间是否存在任何链接(当然,我必须以这种方式定义所有可能的链接)。问题是如何在Z3py中定义路径的概念,这样我就可以知道两个节点之间是否存在任何路径(如果是SAT,那么是SAT还是UNSAT,哪个路径?)。我试着寻找z3py教程,但它不再在网上提供了,我是z3新手,所以请容忍我。我只能用python进行以下建模,这是非常幼稚的。在z3py中是否可以将路径建模为未解释的函数

graph = {'n1': ['n2', 'n6'],
         'n2': ['n3', 'n5'],
         'n3': ['n4', 'n5','n6'],
         'n4': ['n3'],
         'n5': ['n2', 'n3'],
         'n6': ['n3','n1']}
def path_finder (graph, start, end, path=[]):
    path = path + [start]
    if start == end:
        return path
    if not graph.has_key(start):
        return None
    for node in graph[start]:
        if node not in path:
            newpath = path_finder (graph, node, end, path)
            if newpath: return newpath
    return None

print path_finder (graph, 'n1','n4')
我修改了一个程序来完成路径搜索

from z3 import *

#  cf. https://ericpony.github.io/z3py-tutorial/fixpoint-examples.htm

fp = Fixedpoint()
fp.set(engine='datalog')

#  3 bits are sufficient to model our 6 nodes
s = BitVecSort(3)
edge = Function('edge', s, s, BoolSort())
path = Function('path', s, s, BoolSort())
a = Const('a', s)
b = Const('b', s)
c = Const('c', s)

#  the rules:
#  a path can be a single edge or
#  a combination of a path and an edge
fp.register_relation(path,edge)
fp.declare_var(a, b, c)
fp.rule(path(a, b), edge(a, b))
fp.rule(path(a, c), [edge(a, b), path(b, c)])

n1 = BitVecVal(1, s)
n2 = BitVecVal(2, s)
n3 = BitVecVal(3, s)
n4 = BitVecVal(4, s)
n5 = BitVecVal(5, s)
n6 = BitVecVal(6, s)
n7 = BitVecVal(7, s)

graph = {n1: [n2, n6, n7],
         n2: [n3, n5],
         n3: [n4, n5, n6],
         n4: [n3],
         n5: [n2, n3],
         n6: [n3, n1]}

#  establish facts by enumerating the graph dictionary
for i, (source, nodes) in enumerate(graph.items()):
    for destination in nodes:
        fp.fact(edge(source, destination))

print("current set of rules:\n", fp)

print(fp.query(path(n1, n4)), "yes, we can reach n4 from n1\n")

print(fp.query(path(n7, n1)), "no, we cannot reach n1 from n7\n")

是否有理由为此使用SMT/SAT?像Dijkstra的算法这样简单的东西应该可以做到这一点?PS。SAT公式如下。设n_i为布尔变量,表示节点i是否位于您感兴趣的路径上。如果有一个从节点i到节点j的链接,那么将隐含的n_i=>n_j添加到公式中。然后假设您想要从节点s到节点d的路径,然后假设n_s=true,并检查n_d的可满足性。