Z3 带蕴涵的量化公式给出 unsat
Z3 quantified formula with implication giving unsat
我还是 Z3 的新手,因此不确定为什么我对下面的公式不满意;它应该至少对于那些 ts_var 数组,其中每个数组元素(位向量)(32 个数组元素)在 32 位的不同位置有 1,在所有其他位置有零(所以 bvxor结果会不同)。那么关于我做错了什么的任何建议或提示?
更新: 当我以与代码中相反的方式在 exp4 ((=> a!1 a!2)) 中进行暗示时,Z3 产生了坐!但这不是我想要的。我想找到一个数组,其中 2 个元素的不同组合在将它们异或在一起时给出不同的结果。这是代码中仍然给出不满意的含义。
(assert (exists ((ts_var (Array (_ BitVec 5) (_ BitVec 32))))
(forall ((k (_ BitVec 5)) (l (_ BitVec 5)) (m (_ BitVec 5)) (n (_ BitVec 5)))
(let ((a!1 (and (not (= k l))
(not (= n m))
(=> (= k m) (not (= l n)))
(=> (= l n) (not (= k m)))))
(a!2 (not (= (bvxor (select ts_var k) (select ts_var l))
(bvxor (select ts_var m) (select ts_var n))))))
(=> a!1 a!2)
)
)
)
)
(check-sat)
我最初使用 C-API:
编写给出此结果的代码
Z3_ast mk_var(Z3_context ctx, const char * name, Z3_sort ty)
{
Z3_symbol s = Z3_mk_string_symbol(ctx, name);
return Z3_mk_const(ctx, s, ty);
}
bv_w_sort = Z3_mk_bv_sort (ctx, 32);
index_w_sort = Z3_mk_bv_sort (ctx, 5);
array_sort = Z3_mk_array_sort(ctx, index_w_sort, bv_w_sort);
ts_var = mk_var(ctx, "ts_var" , array_sort);
fp1 = mk_var(ctx, "fp1" , bv_w_sort);
fp2 = mk_var(ctx, "fp2" , bv_w_sort);
fp1 = Z3_mk_bvxor(ctx, Z3_mk_select(ctx, ts_var, k) , Z3_mk_select(ctx, ts_var, l) );
fp2 = Z3_mk_bvxor(ctx, Z3_mk_select(ctx, ts_var, m) , Z3_mk_select(ctx, ts_var, n) );
cond_uniq = Z3_mk_not (ctx,Z3_mk_eq (ctx, fp1, fp2) );
cond_k_neq_l = Z3_mk_not (ctx,Z3_mk_eq (ctx, k, l));
cond_n_neq_m = Z3_mk_not (ctx,Z3_mk_eq (ctx, n, m));
cond_l_neq_n = Z3_mk_not (ctx,Z3_mk_eq (ctx, l, n));
cond_k_neq_m = Z3_mk_not (ctx,Z3_mk_eq (ctx, k, m));
cond_k_eq_m = Z3_mk_eq (ctx, k, m);
cond_l_eq_n = Z3_mk_eq (ctx, l, n);
cond_imply1 = Z3_mk_implies (ctx, cond_k_eq_m, cond_l_neq_n);
cond_imply2 = Z3_mk_implies (ctx, cond_l_eq_n, cond_k_neq_m);
args[0]= cond_k_neq_l;
args[1]= cond_n_neq_m;
args[2]= cond_imply1;
args[3]= cond_imply2;
exp4 = Z3_mk_and(ctx, 4, args);
bound[0] = (Z3_app) k;
bound[1] = (Z3_app) l;
bound[2] = (Z3_app) m;
bound[3] = (Z3_app) n;
bound4[0]= (Z3_app)ts_var;
exp2 = Z3_mk_implies(ctx, exp4, cond_uniq);
exp1 = Z3_mk_forall_const(ctx, 0, 4, bound, 0, 0, exp2);
q = Z3_mk_exists_const(ctx, 0, 1, bound4, 0, 0, exp1);
Z3_solver_assert(ctx, s, q);
我也不确定我是否必须像这里建议的那样对变量使用一些模式:Does Z3 support variable-only patterns in quantified formulas?
但根据我在本教程中阅读的内容 http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.225.8231&rep=rep1&type=pdf
不使用任何模式似乎没问题,对吧?
您选择 k
、l
、m
和 n
的方式允许对称。例如:
k = 0
l = 1
m = 1
n = 0
满足你的条件a!1
,但显然无法为ts_var
选择"distinct"个元素;这使得 a!2
错误。因此,您的整个查询变为 unsat
.
您可以将 a!1
的定义替换为以下内容:
(a!1 (distinct k l m n))
简明扼要地说这四个变量都是不同的。有了这个改变,z3 确实找到了一个模型。
我还是 Z3 的新手,因此不确定为什么我对下面的公式不满意;它应该至少对于那些 ts_var 数组,其中每个数组元素(位向量)(32 个数组元素)在 32 位的不同位置有 1,在所有其他位置有零(所以 bvxor结果会不同)。那么关于我做错了什么的任何建议或提示?
更新: 当我以与代码中相反的方式在 exp4 ((=> a!1 a!2)) 中进行暗示时,Z3 产生了坐!但这不是我想要的。我想找到一个数组,其中 2 个元素的不同组合在将它们异或在一起时给出不同的结果。这是代码中仍然给出不满意的含义。
(assert (exists ((ts_var (Array (_ BitVec 5) (_ BitVec 32))))
(forall ((k (_ BitVec 5)) (l (_ BitVec 5)) (m (_ BitVec 5)) (n (_ BitVec 5)))
(let ((a!1 (and (not (= k l))
(not (= n m))
(=> (= k m) (not (= l n)))
(=> (= l n) (not (= k m)))))
(a!2 (not (= (bvxor (select ts_var k) (select ts_var l))
(bvxor (select ts_var m) (select ts_var n))))))
(=> a!1 a!2)
)
)
)
)
(check-sat)
我最初使用 C-API:
编写给出此结果的代码Z3_ast mk_var(Z3_context ctx, const char * name, Z3_sort ty)
{
Z3_symbol s = Z3_mk_string_symbol(ctx, name);
return Z3_mk_const(ctx, s, ty);
}
bv_w_sort = Z3_mk_bv_sort (ctx, 32);
index_w_sort = Z3_mk_bv_sort (ctx, 5);
array_sort = Z3_mk_array_sort(ctx, index_w_sort, bv_w_sort);
ts_var = mk_var(ctx, "ts_var" , array_sort);
fp1 = mk_var(ctx, "fp1" , bv_w_sort);
fp2 = mk_var(ctx, "fp2" , bv_w_sort);
fp1 = Z3_mk_bvxor(ctx, Z3_mk_select(ctx, ts_var, k) , Z3_mk_select(ctx, ts_var, l) );
fp2 = Z3_mk_bvxor(ctx, Z3_mk_select(ctx, ts_var, m) , Z3_mk_select(ctx, ts_var, n) );
cond_uniq = Z3_mk_not (ctx,Z3_mk_eq (ctx, fp1, fp2) );
cond_k_neq_l = Z3_mk_not (ctx,Z3_mk_eq (ctx, k, l));
cond_n_neq_m = Z3_mk_not (ctx,Z3_mk_eq (ctx, n, m));
cond_l_neq_n = Z3_mk_not (ctx,Z3_mk_eq (ctx, l, n));
cond_k_neq_m = Z3_mk_not (ctx,Z3_mk_eq (ctx, k, m));
cond_k_eq_m = Z3_mk_eq (ctx, k, m);
cond_l_eq_n = Z3_mk_eq (ctx, l, n);
cond_imply1 = Z3_mk_implies (ctx, cond_k_eq_m, cond_l_neq_n);
cond_imply2 = Z3_mk_implies (ctx, cond_l_eq_n, cond_k_neq_m);
args[0]= cond_k_neq_l;
args[1]= cond_n_neq_m;
args[2]= cond_imply1;
args[3]= cond_imply2;
exp4 = Z3_mk_and(ctx, 4, args);
bound[0] = (Z3_app) k;
bound[1] = (Z3_app) l;
bound[2] = (Z3_app) m;
bound[3] = (Z3_app) n;
bound4[0]= (Z3_app)ts_var;
exp2 = Z3_mk_implies(ctx, exp4, cond_uniq);
exp1 = Z3_mk_forall_const(ctx, 0, 4, bound, 0, 0, exp2);
q = Z3_mk_exists_const(ctx, 0, 1, bound4, 0, 0, exp1);
Z3_solver_assert(ctx, s, q);
我也不确定我是否必须像这里建议的那样对变量使用一些模式:Does Z3 support variable-only patterns in quantified formulas?
但根据我在本教程中阅读的内容 http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.225.8231&rep=rep1&type=pdf 不使用任何模式似乎没问题,对吧?
您选择 k
、l
、m
和 n
的方式允许对称。例如:
k = 0
l = 1
m = 1
n = 0
满足你的条件a!1
,但显然无法为ts_var
选择"distinct"个元素;这使得 a!2
错误。因此,您的整个查询变为 unsat
.
您可以将 a!1
的定义替换为以下内容:
(a!1 (distinct k l m n))
简明扼要地说这四个变量都是不同的。有了这个改变,z3 确实找到了一个模型。