Z3JavaAPI定义一个函数
Z3 Java API defining a function
我需要你帮助我用 Z3 Java API 定义一个函数。
我尝试解决这样的问题(在 z3.exe 过程中工作正常):
(declare-fun a () Real)
(declare-fun b () Real)
(declare-fun c () Bool)
(define-fun max2 ((x Real) (y Real)) Real (ite (<= x y) y x))
(assert (and (>= a 0.0) (<= a 100.0)))
(assert (or (= (max2 (+ 100.0 (* (- 1.0) a)) (/ 1.0 1000.0)) 0.0) c (not (= b 0.0))))
(check-sat-using (then simplify bit-blast qfnra))
(get-model)
此 smt 文件的结果是:
sat
(model
(define-fun a () Real
1.0)
(define-fun c () Bool
false)
(define-fun b () Real
1.0)
)
现在的问题是:没有选项,用javaAPI定义一个函数。在另一个 post (Equivalent of define-fun in Z3 API) 中,我注意到在 java API 中使用了以下语句:
(declare-fun max2 (Real Real) Real)
(assert (forall ((y Real) (x Real)) (= (max2 y x) (ite (<= x y) y x))))
所以我在我的 smt 文件中替换了 (define-fun max2 ((x Real) (y Real)) Real (ite (<= x y) y x)) 和再次启动 z3.exe 进程。结果如下:
unknown
(model
(define-fun b () Real
0.0)
)
因此,如您所见,不再有可满足的结果。在 java 中翻译它会得到相同的结果 UNKNOWN.
有什么想法,我能做什么?
没有等同于函数定义的东西,因为它们不是必需的,就像 define-fun 宏一样。在 API 中做的等效事情是为函数构建一个表达式,然后对于函数的每个应用程序,只需将参数值替换为输入值,例如,通过使用 Expr.Substitute.
就像您引用的 post 中提到的 Leo 一样,可以为此目的使用量词,但求解器通常会放弃 return unknown
因为它认为公式太难解了。我们可以通过使用宏查找器(参见引用 post)来解决这个问题,它会准确识别这种宏。
像这样声明一个函数如何:
private static RealExpr max2(Context ctx, ArithExpr x, ArithExpr y)
throws Z3Exception {
return (RealExpr) ctx.mkITE(ctx.mkLe(x, y), y, x);
}
并且可能像这样使用它:
Context ctx = new Context();
ArithExpr a = (ArithExpr) ctx.mkConst(ctx.mkSymbol("a"), ctx.getRealSort());
ArithExpr b = (ArithExpr) ctx.mkConst(ctx.mkSymbol("b"), ctx.getRealSort());
BoolExpr c = (BoolExpr) ctx.mkConst(ctx.mkSymbol("c"), ctx.getBoolSort());
Goal g = ctx.mkGoal(true, true, false);
g.add(ctx.mkAnd(ctx.mkGe(a, ctx.mkReal(0)), ctx.mkLe(a, ctx.mkReal(100))));
g.add(ctx.mkOr(
ctx.mkEq(
max2(ctx,
ctx.mkAdd(ctx.mkReal(100), ctx.mkMul(ctx.mkReal(-1), a)),
ctx.mkDiv(ctx.mkReal(1), ctx.mkReal(1000))),
ctx.mkReal(0)),
c,
(ctx.mkNot(ctx.mkEq(b, ctx.mkReal(0))))));
我需要你帮助我用 Z3 Java API 定义一个函数。 我尝试解决这样的问题(在 z3.exe 过程中工作正常):
(declare-fun a () Real)
(declare-fun b () Real)
(declare-fun c () Bool)
(define-fun max2 ((x Real) (y Real)) Real (ite (<= x y) y x))
(assert (and (>= a 0.0) (<= a 100.0)))
(assert (or (= (max2 (+ 100.0 (* (- 1.0) a)) (/ 1.0 1000.0)) 0.0) c (not (= b 0.0))))
(check-sat-using (then simplify bit-blast qfnra))
(get-model)
此 smt 文件的结果是:
sat
(model
(define-fun a () Real
1.0)
(define-fun c () Bool
false)
(define-fun b () Real
1.0)
)
现在的问题是:没有选项,用javaAPI定义一个函数。在另一个 post (Equivalent of define-fun in Z3 API) 中,我注意到在 java API 中使用了以下语句:
(declare-fun max2 (Real Real) Real)
(assert (forall ((y Real) (x Real)) (= (max2 y x) (ite (<= x y) y x))))
所以我在我的 smt 文件中替换了 (define-fun max2 ((x Real) (y Real)) Real (ite (<= x y) y x)) 和再次启动 z3.exe 进程。结果如下:
unknown
(model
(define-fun b () Real
0.0)
)
因此,如您所见,不再有可满足的结果。在 java 中翻译它会得到相同的结果 UNKNOWN.
有什么想法,我能做什么?
没有等同于函数定义的东西,因为它们不是必需的,就像 define-fun 宏一样。在 API 中做的等效事情是为函数构建一个表达式,然后对于函数的每个应用程序,只需将参数值替换为输入值,例如,通过使用 Expr.Substitute.
就像您引用的 post 中提到的 Leo 一样,可以为此目的使用量词,但求解器通常会放弃 return unknown
因为它认为公式太难解了。我们可以通过使用宏查找器(参见引用 post)来解决这个问题,它会准确识别这种宏。
像这样声明一个函数如何:
private static RealExpr max2(Context ctx, ArithExpr x, ArithExpr y)
throws Z3Exception {
return (RealExpr) ctx.mkITE(ctx.mkLe(x, y), y, x);
}
并且可能像这样使用它:
Context ctx = new Context();
ArithExpr a = (ArithExpr) ctx.mkConst(ctx.mkSymbol("a"), ctx.getRealSort());
ArithExpr b = (ArithExpr) ctx.mkConst(ctx.mkSymbol("b"), ctx.getRealSort());
BoolExpr c = (BoolExpr) ctx.mkConst(ctx.mkSymbol("c"), ctx.getBoolSort());
Goal g = ctx.mkGoal(true, true, false);
g.add(ctx.mkAnd(ctx.mkGe(a, ctx.mkReal(0)), ctx.mkLe(a, ctx.mkReal(100))));
g.add(ctx.mkOr(
ctx.mkEq(
max2(ctx,
ctx.mkAdd(ctx.mkReal(100), ctx.mkMul(ctx.mkReal(-1), a)),
ctx.mkDiv(ctx.mkReal(1), ctx.mkReal(1000))),
ctx.mkReal(0)),
c,
(ctx.mkNot(ctx.mkEq(b, ctx.mkReal(0))))));