是否支持对未来版本进行酸洗(或序列化)Z3对象?我目前正在尝试将Z3 Python API生成的模型挑选到一个文件中,并且我收到错误消息ctypes objects containing pointers cannot be pickled
,我认为这意味着Python API仅仅是Z3 DLL的包装。
或者是否有更好的方法将Z3 Python API生成的对象保存到文件中以供将来使用?
谢谢!
答案 0 :(得分:2)
是的,Z3 Python API是Z3共享库(即Windows上的DLL)的包装器。
将方法__getstate__()
和__setstate(state)__
添加到包含公式,模型等的Z3 Python对象是可行的。如果这些方法可用,Python pickler将使用它们。
因此,原则上可以添加此功能。也就是说,我们可以添加Z3 API(C API)程序,用于将Z3表达式/公式和模块编码/解码为字节流。然后,这些API用于实现__getstate__()
和__setstate(state)__
。有一些细节:
共享:假设我们有一个Z3表达式的Python列表,这些表达式共享很多子表达式。 Python pickler将为列表的每个元素调用__getstate__()
,Z3将多次编码共享子表达式。问题在于,对于Python,每个Z3表达式都是“blob”,并且Z3编码器/序列化器不知道这些不同的表达式是更大的Python数据结构的一部分。因此,用户在挑选包含对许多不同Z3对象的引用的Python对象时应该小心。请注意,在某些情况下,很容易解决此问题。例如,我们可以使用Z3 ASTVector
而不是Z3表达式的Python列表。然后,Z3可以将ASTVector
编码为一个大的“blob”,其中每个共享子表达式只编码一次。
Z3对象(例如表达式和模型)与上下文相关联。请注意,Python API中的大多数过程都有一个额外的ctx
参数。例如,Int('x')
在默认上下文中创建名为x
的整数变量,Int('x', ctx)
在上下文ctx
中创建它。多个上下文很有用,因为我们可以从不同的执行线程同时访问它们。当我们取消对Z3对象的去除时,我们必须决定在哪个上下文中存储它。可能性是设置指定要使用的上下文的全局参数。如果未设置,则使用默认上下文。 这不是一个完美的解决方案。假设我们有一个Python数据结构,其中包含对来自不同上下文的Z3表达式的引用,我们腌制它。然后,当我们解开数据时,所有表达式都将被添加到相同的Z3上下文中。也许,这不是一个大问题,因为大多数用户只使用一个Z3上下文,而使用多个上下文的用户通常不会在同一个Python对象中存储来自不同上下文的表达式的引用。
请随时提出替代解决方案。 Z3团队中没有一个人是Python专家。