我正在尝试使用 Z3 来求解涉及未知投影函数的方程,以找到满足方程的函数的有效解释。例如,对于等式:snd . f = g . fst
一个有效的解释是f = \(x,y) -> (y,x)
和g = id
。我知道 Z3 不是更高阶的,所以我一直在尝试以一阶形式对问题进行编码。因此,例如对于f = g.fst
我使用:
(declare-datatypes (T) ((Tree (leaf (value T)) (node (children TreeList)))
(TreeList nil (cons (head Tree) (tail TreeList)))))
(define-fun fst ((x (Tree Int))) (Tree Int) (head (children x)))
(define-fun snd ((x (Tree Int))) (Tree Int) (head (tail (children x))))
(declare-fun f ((Tree Int)) (Tree Int))
(declare-fun g ((Tree Int)) (Tree Int))
(assert (forall ((x (Tree Int))) (= (f x) (g (fst x)))))
(check-sat)
(get-model)
返回的作品类型:
(define-fun g ((x!1 (Tree Int))) (Tree Int)
(leaf 0))
(define-fun f ((x!1 (Tree Int))) (Tree Int)
(g (head (children x!1))))
但是对于snd . f = g . fst
(我已经将树简化为对尝试和帮助):
(declare-datatypes (T) ((Pair (leaf (value T)) (pair (fst Pair) (snd Pair)))))
(declare-fun f ((Pair Int)) (Pair Int))
(declare-fun g ((Pair Int)) (Pair Int))
(assert (forall ((x (Pair Int))) (= (snd (f x)) (g (fst x)))))
我明白了unknown
。
我还尝试在不使用 ADT 的情况下仅使用布尔值或整数作为参数来编码类似的问题,但是模型只是将常量值分配给函数。我还尝试为函数常量、恒等函数以及成对和顺序组合定义一个简单的 ADT,然后定义一个可以简化表达式的“等于”函数,例如f.id = f
,但这要么涉及递归函数,例如:
(declare-datatypes () (
(Fun id
(fun (funnum Int))
(seq (after Fun) (before Fun))
(pair (fst Fun) (snd Fun)) )))
(define-fun eq ((x Fun) (y Fun)) Bool (or
(= x y)
(eq x (seq y id)) ; id neutral for seq
(eq x (seq id y))
(eq y (seq x id))
(eq y (seq id x))))
(declare-const f Fun)
(declare-const g Fun)
(assert (eq f (seq id g)))
(check-sat)
(get-model)
这显然是无效的。或者,如果我使用未解释的函数,它会使“eq”成为常量函数,即
(declare-fun eq (Fun Fun) Bool)
(assert (forall ((x Fun) (y Fun)) ; semantic equality
(= (eq x y) (or
(= x y) ; syntactic eq
(eq x (seq y id)) ; id neutral for seq
(eq x (seq id y))
(eq y (seq x id))
(eq y (seq id x))
))
))
=>
(define-fun eq ((x!1 Fun) (x!2 Fun)) Bool
true)
与涉及 Int -> Int 类型函数的方程类似,这将返回 f 和 g 的常数函数:
(declare-fun f (Int) Int)
(declare-fun g (Int) Int)
(assert (forall ((x Int)) (= (+ (f x) 1) (+ (g x) 2)) ))
并添加这些时间:
(assert (forall ((x Int) (y Int)) (=>
(not (= x y))
(not (= (g x) (g y))))))
(assert (forall ((x Int) (y Int)) (=>
(not (= x y))
(not (= (f x) (f y))))))
有什么想法可以让这种事情发挥作用吗?
非常感谢!