[sledge] Add formula invariant to check NNF

Reviewed By: jvillard

Differential Revision: D24306107

fbshipit-source-id: 44d914ba9
master
Josh Berdine 4 years ago committed by Facebook GitHub Bot
parent 6427b99a16
commit 93ed599153

@ -296,6 +296,13 @@ end = struct
| Lit of Predsym.t * trm array
[@@deriving compare, equal, sexp]
let invariant f =
let@ () = Invariant.invariant [%here] f [%sexp_of: fml] in
match f with
(* formulas are in negation-normal form *)
| Not (Not _ | And _ | Or _ | Cond _) -> assert false
| _ -> ()
let sort_fml x y = if compare_fml x y <= 0 then (x, y) else (y, x)
(** Some normalization is necessary for [embed_into_fml] (defined below)
@ -304,8 +311,8 @@ end = struct
[0 (p ? 1 : 0)] ==> [(p ? 0 1 : 0 0)] ==> [(p ? tt : ff)]
==> [p]. *)
let _Tt = Tt
let _Ff = Not Tt
let _Tt = Tt |> check invariant
let _Ff = Not Tt |> check invariant
(** classification of terms as either semantically equal or disequal, or
if semantic relationship is unknown, as either syntactically less than
@ -321,29 +328,33 @@ end = struct
if ord < 0 then SynLt else if ord = 0 then SemEq else SynGt
let _Eq0 x =
match compare_semantic_syntactic zero x with
( match compare_semantic_syntactic zero x with
(* 0 = 0 ==> tt *)
| SemEq -> Tt
(* 0 = N ==> ff for N ≢ 0 *)
| SemDq -> _Ff
| SynLt | SynGt -> Eq0 x
| SynLt | SynGt -> Eq0 x )
|> check invariant
let _Eq x y =
if x == zero then _Eq0 y
( if x == zero then _Eq0 y
else if y == zero then _Eq0 x
else
match compare_semantic_syntactic x y with
| SemEq -> Tt
| SemDq -> _Ff
| SynLt -> Eq (x, y)
| SynGt -> Eq (y, x)
| SynGt -> Eq (y, x) )
|> check invariant
let _Gt0 = function
let _Gt0 x =
( match x with
| Z z -> if Z.gt z Z.zero then Tt else _Ff
| Q q -> if Q.gt q Q.zero then Tt else _Ff
| x -> Gt0 x
| x -> Gt0 x )
|> check invariant
let _Lit p xs = Lit (p, xs)
let _Lit p xs = Lit (p, xs) |> check invariant
let rec is_negative = function
| Not (Tt | Eq _ | Eq0 _ | Gt0 _ | Lit _ | Iff _) | Or _ -> true
@ -375,7 +386,7 @@ end = struct
| _ -> if equal_fml p q then Equal else Unknown
let _And p q =
match (p, q) with
( match (p, q) with
| Tt, p | p, Tt -> p
| Not Tt, _ | _, Not Tt -> _Ff
| _ -> (
@ -384,10 +395,11 @@ end = struct
| Opposite -> _Ff
| Unknown ->
let p, q = sort_fml p q in
And (p, q) )
And (p, q) ) )
|> check invariant
let _Or p q =
match (p, q) with
( match (p, q) with
| Not Tt, p | p, Not Tt -> p
| Tt, _ | _, Tt -> Tt
| _ -> (
@ -396,10 +408,11 @@ end = struct
| Opposite -> Tt
| Unknown ->
let p, q = sort_fml p q in
Or (p, q) )
Or (p, q) ) )
|> check invariant
let rec _Iff p q =
match (p, q) with
( match (p, q) with
| Tt, p | p, Tt -> p
| Not Tt, p | p, Not Tt -> _Not p
| _ -> (
@ -408,17 +421,20 @@ end = struct
| Opposite -> _Ff
| Unknown ->
let p, q = sort_fml p q in
Iff (p, q) )
Iff (p, q) ) )
|> check invariant
and _Not = function
and _Not p =
( match p with
| Not x -> x
| And (x, y) -> _Or (_Not x) (_Not y)
| Or (x, y) -> _And (_Not x) (_Not y)
| Cond {cnd; pos; neg} -> _Cond cnd (_Not pos) (_Not neg)
| (Tt | Eq _ | Eq0 _ | Gt0 _ | Lit _ | Iff _) as x -> Not x
| Tt | Eq _ | Eq0 _ | Gt0 _ | Lit _ | Iff _ -> Not p )
|> check invariant
and _Cond cnd pos neg =
match (cnd, pos, neg) with
( match (cnd, pos, neg) with
(* (tt ? p : n) ==> p *)
| Tt, _, _ -> pos
(* (ff ? p : n) ==> n *)
@ -445,7 +461,8 @@ end = struct
| Unknown when is_negative cnd ->
Cond {cnd= _Not cnd; pos= neg; neg= pos}
(* (c ? p : n) *)
| _ -> Cond {cnd; pos; neg} )
| _ -> Cond {cnd; pos; neg} ) )
|> check invariant
end
open Fml

Loading…
Cancel
Save