不推荐使用Z3_mk_config和Z3_mk_context(Z3 C API)。我们现在应该使用哪些功能?

时间:2018-01-25 10:52:13

标签: c z3

我使用的是Z3的C API。我已经检查了这些示例,Z3_mk_config()和Z3_mk_context(Z3_config c)用于创建上下文,例如,

Z3_config  cfg;
Z3_context ctx;
cfg = Z3_mk_config();
Z3_set_param_value(cfg, "model", "true");
//...
ctx = Z3_mk_context(cfg);

但是,文档说所有这些功能都已弃用,但不要提及现在应该使用哪些功能。

有谁知道现在应该使用哪些函数来创建配置和上下文?

非常感谢任何帮助。谢谢!

1 个答案:

答案 0 :(得分:0)

TLDR:

  • 使用Z3_mk_config创建一个Z3_config
  • 使用Z3_global_param_set全局设置配置。
  • 使用Z3_set_param_value设置特定于上下文的配置。
  • 如果没有要设置的配置,只需
    1. Z3_config做一个Z3_mk_config
    2. 使用它创建上下文,
    3. 然后用Z3_del_config将其删除。

SergeyLebedev的评论可能引用了doc

中的这一评论。

在Z3的早期版本中,Z3_config用于存储全局和 模块配置。现在,我们应该使用Z3_global_param_set

过去几天,我正在查看源仓库。在示例文件test_capi.c中,他们经常使用此mk_context函数,该函数在与

Z3_context mk_context()
{
    Z3_config  cfg;
    Z3_context ctx;
    cfg = Z3_mk_config();
    ctx = mk_context_custom(cfg, error_handler);
    Z3_del_config(cfg);
    return ctx;
}

其中mk_context_custom

在同一文件中定义
Z3_context mk_context_custom(Z3_config cfg, Z3_error_handler err)
{
    Z3_context ctx;

    Z3_set_param_value(cfg, "model", "true");
    ctx = Z3_mk_context(cfg);
    Z3_set_error_handler(ctx, err);

    return ctx;
}

所以看起来Z3_mk_configZ3_set_param_value仍在使用。

医生说Z3_configZ3_context之类的东西应该是“不透明的指针”。但是,将其追到源头时,似乎Z3_config被声明为没有特定内容的结构,但似乎无论在何处使用,都将其强制转换为明确定义为类的context_params

Z3_config的类型z3_api_h

声明
DEFINE_TYPE(Z3_config);

其中DEFINE_TYPE(T)是在z3_macros.h中定义的宏,并扩展为typedef struct _ ## T *T。因此,实际上Z3_config仅在原型上声明为结构。

函数Z3_mk_configZ3_config的构造函数,是在z3_api.h中用

声明的
Z3_config Z3_API Z3_mk_config(void);

,在api_config_params.cpp中定义为

Z3_config Z3_API Z3_mk_config(void) {
    try {
        memory::initialize(UINT_MAX);
        LOG_Z3_mk_config();
        Z3_config r = reinterpret_cast<Z3_config>(alloc(context_params));
        RETURN_Z3(r);
    } catch (z3_exception & ex) {
        // The error handler is only available for contexts
        // Just throw a warning.
        warning_msg("%s", ex.msg());
        return nullptr;
    }
}

extern "C"块中。请注意,Z3_API是也在z3_macros.h中定义以设置__attribute__ ((visibility ("default")))的宏,而allocmemory_manager.h中具有#define alloc(T,...) new (memory::allocate(sizeof(T))) T(__VA_ARGS__)和{{ 1}}是在文件RETURN_Z3update_api.py生成的某些文件中定义的宏。

看来,当创建#define RETURN_Z3(Z3RES) if (_LOG_CTX.enabled()) { SetR(Z3RES); } return Z3RES时,会分配Z3_config大小的存储块并将其强制转换为context_params,实际上Z3_config context_params中明确定义的类。我忽略了内容,因为它现在不相关。

context_params.h

接下来,class context_params { .... }; Z3_set_param_value中用

定义
api_config_params.cpp

因此,在像普通对象一样使用该函数之前,该函数首先将void Z3_API Z3_set_param_value(Z3_config c, char const * param_id, char const * param_value) { LOG_Z3_set_param_value(c, param_id, param_value); try { context_params * p = reinterpret_cast<context_params*>(c); p->set(param_id, param_value); } catch (z3_exception & ex) { // The error handler is only available for contexts // Just throw a warning. warning_msg("%s", ex.msg()); } } 强制转换回Z3_config。我不是专家,但这可能有用,因为struct and class are almost the same位于引擎盖下面。

另一方面,在示例文件context_params中,他们像这样使用test_capi.c

Z3_global_param_set

在使用.... cfg = Z3_mk_config(); .... /* The current model finder for quantified formulas cannot handle injectivity. So, we are limiting the number of iterations to avoid a long "wait". */ Z3_global_param_set("smt.mbqi.max_iterations", "10"); ctx = mk_context_custom(cfg, error_handler); Z3_del_config(cfg); s = mk_solver(ctx); 进行配置时,他们仍然在创建上下文之前仍使用Z3_mk_config。因此,我想说的是,使用Z3_global_param_set来构造Z3_mk_config并没有什么问题,而文档所说的是,当您要全局设置某些内容时,不要访问Z3_config结构本身,因为无论如何您都无法将其转换为Z3_config;使用context_params代替。并且,当您要为特定的上下文设置特定的内容时,请使用Z3_global_param_set


问题仍然是,为什么我们要在结构和类之间切换?我不知道。我对C ++一点都不熟悉,但是我猜测,如果不是C API本身,它是为了使Z3_set_param_value部分for the Python API bindings有效。