Z3,创建数据structure/class,使用数据类型

Z3, create data structure/class, using Datatype

也许创建一个包含与以下内容相同的信息的数据结构 Python class。

class Variable:
    def __init__(self):
        self.name = "v1"  #str
        self.size = 10    #int
        self.initialized = True    #bool

拥有三个不同类型的字段。

如果字段类型相同,例如“str”,我可以使用 z3.Array('a', StringSort(), StringSort())。有点像映射一样使用它。

如python代码所示,字段类型不同怎么办?

我调查了 Datatype,并阅读了 z3py 指南中有关他们如何创建 List 的示例。但是,我无法完全理解到底发生了什么。我认为 z3 文档中使用的术语可能与 OO 编程语言中常用的术语(如 Java、Python)略有不同?我真的很难掌握一些术语和例子...

*** 一个比较棘手的部分,你如何将这种变量存储在一个z3数组中? 例如我想使用 z3 约束求解在大小 > 10 的数组中找到变量对象的索引。

我和你情况一样,但我会尽力回答你的问题。

I could just use z3.Array('a', StringSort(), StringSort()). What do I do in this kind of situation?

是的,你应该实现它,但请记住 Z3(和 SMT)中的数组是无限大小的,如果你想要一个固定的数组,你可以:

vec = IntVector('vec', 10)

尊重你的另一个问题,我和你有类似的情况,因为我在正确理解Z3方面遇到了很多困难。如果你在 Haskell 工作,我会调整列表(为了更好地理解)

def funList(sort):
    List = Datatype('List')
    #Constructor insert: (Int, List) -> List
    List.declare('insert', ('head', sort), ('tail', List)) 
    List.declare('nil') #declaración de nil, así permito la opción de tener una lista vacía
    return List.create() #creo la lista

数据类型是一种可以有多个构造函数的结构:像树(叶或分支),或列表(nil,或 cons),或任何其他一般树状结构。

根据您的描述,您似乎实际上不需要数据类型,而是直接记录值。 (术语令人困惑。OO 人称之为数据类型的东西大部分时间只是一个 struct/record,而函数式编程或 SMT 人称之为数据类型的东西要丰富得多,有许多像列表一样递归的构造函数。这是不幸的是,但是你学过一次并且很容易记住的东西。)

显然,没有一种适合所有人的尺寸;而且您的问题描述相当模糊。但我猜你想表示一些 Variable 的概念,它具有关联的固定名称、大小和某种初始化字段。您想要的只是一个 Python class ,您可以在其中依靠灵活的类型将其用作具体变量,或用作 z3 可以操作的符号变量。基于此,我倾向于像这样编写您的问题:

from z3 import *

class Variable:
    def __init__(self, nm):
        self.name        = nm
        self.size        = Int(nm + '_size')
        self.initialized = Bool(nm + '_initialized')

    def __str__(self):
        return "<Name: %s, Size: %s, Initialized: %s>" % (self.name, self.size, self.initialized)

# Helper function to grab a variable from a z3 model
def getVar(m, v):
    var             = Variable(v.name)
    var.size        = m[v.size]
    var.initialized = m[v.initialized]
    return var

# Declare a few vars
myVar1 = Variable('myVar1')
myVar2 = Variable('myVar2')

# Add some constraints
s = Solver()

s.add(myVar1.size == 12)
s.add(myVar2.initialized == True);
s.add(myVar1.size > myVar2.size)
s.add(myVar1.initialized == Not(myVar2.initialized))

# Get a satisfying model
if s.check() == sat:
    m = s.model()
    print getVar(m, myVar1)
    print getVar(m, myVar2)

我使用 class Variable 来表示常规值,就像在 Python 中一样,但也可以存储符号大小(通过 Int(nm + '_size'))和符号初始化信息(通过 Bool(nm + '_initialized'))。语法可能看起来有点混乱,但如果您仔细阅读该程序,我相信您会明白其中的逻辑。函数 getVar 是一个助手,用于在调用 check 后获取这些变量之一的值,以访问模型值。

我在程序中添加了一些约束以使其变得有趣;显然,这是您将对原始问题进行编码的部分。当我 运行 这个程序时,我得到:

$ python a.py
<Name: myVar1, Size: 12, Initialized: False>
<Name: myVar2, Size: 11, Initialized: True>

这给了我一个很好的模型,它满足我指定的所有约束。

希望对您有所帮助!