2013-03-05 42 views
3

在公式中用函數符號替代函數符號的最佳方法是什麼? Z3py的substitute似乎只適用於表達式,我現在所做的是嘗試猜測可以應用該函數的const/vars的所有可能組合,然後用另一個函數的應用替換那些組合。有沒有更好的方法來做到這一點?在z3公式中替換函數符號

回答

3

我們可以實現一個簡單的自下而上的重寫,鑑於術語s,功能f和期限tt[r_1, ..., r_n]取代每f -application f(r_1, ..., r_n)s。我使用t[r_1, ..., r_n]表示通過將t中的自由變量替換爲術語r_1,...,r_n而獲得的術語。

重寫器可以實現Z3 API。我使用AstMap來緩存結果,並使用todo列表來存儲仍然需要處理的表達式。

下面是一個簡單的例子,它代替f-表示f(t)的應用g(t+1)s中的應用。

x = Var(0, IntSort()) 
print rewrite(s, f, g(x + 1)) 

這裏是代碼和更多的例子。當心,我只在一小組示例中測試代碼。

from z3 import * 

def update_term(t, args): 
    # Update the children of term t with args. 
    # len(args) must be equal to the number of children in t. 
    # If t is an application, then len(args) == t.num_args() 
    # If t is a quantifier, then len(args) == 1 
    n = len(args) 
    _args = (Ast * n)() 
    for i in range(n): 
     _args[i] = args[i].as_ast() 
    return z3._to_expr_ref(Z3_update_term(t.ctx_ref(), t.as_ast(), n, _args), t.ctx) 

def rewrite(s, f, t): 
    """ 
    Replace f-applications f(r_1, ..., r_n) with t[r_1, ..., r_n] in s. 
    """ 
    todo = [] # to do list 
    todo.append(s) 
    cache = AstMap(ctx=s.ctx) 
    while todo: 
     n = todo[len(todo) - 1] 
     if is_var(n): 
      todo.pop() 
      cache[n] = n 
     elif is_app(n): 
      visited = True 
      new_args = [] 
      for i in range(n.num_args()): 
       arg = n.arg(i) 
       if not arg in cache: 
        todo.append(arg) 
        visited = False 
       else: 
        new_args.append(cache[arg]) 
      if visited: 
       todo.pop() 
       g = n.decl() 
       if eq(g, f): 
        new_n = substitute_vars(t, *new_args) 
       else: 
        new_n = update_term(n, new_args) 
       cache[n] = new_n 
     else: 
      assert(is_quantifier(n)) 
      b = n.body() 
      if b in cache: 
       todo.pop() 
       new_n = update_term(n, [ cache[b] ]) 
       cache[n] = new_n 
      else: 
       todo.append(b) 
    return cache[s] 

f = Function('f', IntSort(), IntSort()) 
a, b = Ints('a b') 
s = Or(f(a) == 0, f(a) == 1, f(a+a) == 2) 
# Example 1: replace all f-applications with b 
print rewrite(s, f, b) 

# Example 2: replace all f-applications f(t) with g(t+1) 
g = Function('g', IntSort(), IntSort()) 
x = Var(0, IntSort()) 
print rewrite(s, f, g(x + 1)) 

# Now, f and g are binary functions. 
f = Function('f', IntSort(), IntSort(), IntSort()) 
g = Function('g', IntSort(), IntSort(), IntSort()) 

# Example 3: replace all f-applications f(t1, t2) with g(t2, t1) 
s = Or(f(a, f(a, b)) == 0, f(b, a) == 1, f(f(1,0), 0) == 2) 
# The first argument is variable 0, and the second is variable 1. 
y = Var(1, IntSort()) 
print rewrite(s, f, g(y, x)) 

# Example 4: quantifiers 
s = ForAll([a], f(a, b) >= 0) 
print rewrite(s, f, g(y, x + 1)) 
+0

在未來的版本中可以添加到官方/標準API(如expr.substitute)嗎?看起來這是一個有用的功能---我需要做很多工作,並在前一段時間在我的工具中實現了一種方法。你的方法比我的更好,特別是在性能方面。 – Taylor 2013-03-07 22:26:29

+0

是的,這是可能的。我會把這個項目放在待辦事項列表中。請隨時添加任何功能請求:http://z3.codeplex.com/discussions – 2013-03-08 15:52:30

+0

太好了,非常感謝---我會在codeplex上發佈任何其他請求! – Taylor 2013-03-08 16:35:56