有没有办法通过API查询或访问Z3表达式的结构

时间:2012-12-29 18:26:26

标签: z3

我正在从F#访问托管API。我可以使用ctx.MkFalse,MkImplies,MkMul等构建Z3表达式,但是如何遍历Z3表达式来发现它的结构呢?有没有像e.Op或e.IsFalse,e.IsImplies等。

1 个答案:

答案 0 :(得分:3)

您应该查看Expr.cs的文档。

这是一个遍历表达式的简单F#示例:

let traverse (expr: Expr) =
    printfn "num args: %O" expr.NumArgs
    printfn "children: %A" expr.Args
    printfn "1st child: %O" expr.Args.[0]
    printfn "2nd child: %O" expr.Args.[1]
    printfn "operator: %O" expr.FuncDecl
    printfn "op name: %O" expr.FuncDecl.Name

Expr类还公开了发现表达式结构所需的所有Term Kind Tests including IsTrue, IsAnd, isImplies, etc。在F#中,您应该定义一组活动模式:

let (|True|_|) (expr: Expr) = if expr.IsTrue then Some() else None
let (|False|_|) (expr: Expr) = if expr.IsFalse then Some() else None

let (|And|_|) (expr: Expr) = if expr.IsAnd then Some expr.Args else None
let (|Or|_|) (expr: Expr) = if expr.IsOr then Some expr.Args else None
let (|Not|_|) (expr: Expr) = if expr.IsNot && expr.NumArgs = 1u 
                             then Some(expr.Args.[0]) else None

let (|Iff|_|) (expr: Expr) = if expr.IsIff && expr.NumArgs = 2u 
                             then Some(expr.Args.[0], expr.Args.[1]) else None
let (|Implies|_|) (expr: Expr) = if expr.IsImplies && expr.NumArgs = 2u 
                                 then Some(expr.Args.[0], expr.Args.[1]) else None

这样您就可以通过模式匹配轻松查询表达式的结构,即使是以递归方式:

match e with
| True -> (* boolean literal *)
| False -> (* boolean literal *)
| And es -> (* query es; possibly by pattern matching *)
| Or es -> (* query es; possibly by pattern matching *)
| Not e' -> (* query e; possibly by pattern matching *)
| Iff(e1, e2) -> (* query e1, e2; possibly by pattern matching *)
| Implies(e1, e2) -> (* query e1, e2; possibly by pattern matching *)
| _ -> (* Not a boolean expression; do something else *)