File ‹~~/src/Tools/Argo/argo_clausify.ML›
signature ARGO_CLAUSIFY =
sig
val clausify: Argo_Rewr.context -> Argo_Expr.expr * Argo_Proof.proof ->
Argo_Proof.context * Argo_Core.context -> Argo_Proof.context * Argo_Core.context
end
structure Argo_Clausify: ARGO_CLAUSIFY =
struct
fun ite_clause simp k es (eps, (prf, core)) =
let
val e = Argo_Expr.mk_or es
val (p, prf) = Argo_Proof.mk_taut k e prf
val (ep, prf) = Argo_Rewr.with_proof (Argo_Rewr.args (Argo_Rewr.rewrite_top simp)) (e, p) prf
in (ep :: eps, (prf, core)) end
fun check_ite simp t (e as Argo_Expr.E (Argo_Expr.Ite, [e1, e2, e3])) (eps, (prf, core)) =
(case Argo_Core.identify (Argo_Term.Term t) core of
(Argo_Term.Known _, core) => (eps, (prf, core))
| (Argo_Term.New _, core) =>
(eps, (prf, core))
|> ite_clause simp Argo_Proof.Taut_Ite_Then [Argo_Expr.mk_not e1, Argo_Expr.mk_eq e e2]
|> ite_clause simp Argo_Proof.Taut_Ite_Else [e1, Argo_Expr.mk_eq e e3])
| check_ite _ _ _ cx = cx
fun lift_ites simp (t as Argo_Term.T (_, _, ts)) =
check_ite simp t (Argo_Term.expr_of t) #>
fold (lift_ites simp) ts
fun pos x = (true, x)
fun neg x = (false, x)
fun mk_lit true t = Argo_Lit.Pos t
| mk_lit false t = Argo_Lit.Neg t
fun expr_of (true, t) = Argo_Term.expr_of t
| expr_of (false, t) = Argo_Expr.mk_not (Argo_Term.expr_of t)
fun lit_for (polarity, x) (new_atoms, core) =
(case Argo_Core.add_atom x core of
(Argo_Term.Known t, core) => (mk_lit polarity t, (new_atoms, core))
| (Argo_Term.New t, core) => (mk_lit polarity t, (t :: new_atoms, core)))
fun lit_of (Argo_Expr.E (Argo_Expr.Not, [e])) = lit_for (neg (Argo_Term.Expr e))
| lit_of e = lit_for (pos (Argo_Term.Expr e))
fun lit_of' (pol, Argo_Term.T (_, Argo_Expr.Not, [t])) = lit_for (not pol, Argo_Term.Term t)
| lit_of' (pol, t) = lit_for (pol, Argo_Term.Term t)
fun add_clause f xs p (new_atoms, (prf, core)) =
let val (lits, (new_atoms, core)) = fold_map f xs (new_atoms, core)
in (new_atoms, (prf, Argo_Core.add_axiom (lits, p) core)) end
fun simp_lit (e as Argo_Expr.E (Argo_Expr.Not, [Argo_Expr.E (Argo_Expr.Not, [e'])])) =
Argo_Rewr.rewr Argo_Proof.Rewr_Not_Not e' e
| simp_lit e = Argo_Rewr.keep e
fun simp_clause (e as Argo_Expr.E (Argo_Expr.Or, _)) = Argo_Rewr.args simp_lit e
| simp_clause e = Argo_Rewr.keep e
fun new_clause k ls (new_atoms, (prf, core)) =
let
val e = Argo_Expr.mk_or (map expr_of ls)
val (p, prf) = Argo_Proof.mk_taut k e prf
val ((_, p), prf) = Argo_Rewr.with_proof simp_clause (e, p) prf
in add_clause lit_of' ls p (new_atoms, (prf, core)) end
fun clausify_and t ts cx =
let
val n = length ts
val k1 = Argo_Proof.Taut_And_1 n and k2 = Argo_Proof.Taut_And_2 o rpair n
in
cx
|> new_clause k1 (pos t :: map neg ts)
|> fold_index (fn (i, t') => new_clause (k2 i) [neg t, pos t']) ts
end
fun clausify_or t ts cx =
let
val n = length ts
val k1 = Argo_Proof.Taut_Or_1 o rpair n and k2 = Argo_Proof.Taut_Or_2 n
in
cx
|> fold_index (fn (i, t') => new_clause (k1 i) [pos t, neg t']) ts
|> new_clause k2 (neg t :: map pos ts)
end
fun clausify_iff t t1 t2 cx =
cx
|> new_clause Argo_Proof.Taut_Iff_1 [pos t, pos t1, pos t2]
|> new_clause Argo_Proof.Taut_Iff_2 [pos t, neg t1, neg t2]
|> new_clause Argo_Proof.Taut_Iff_3 [neg t, neg t1, pos t2]
|> new_clause Argo_Proof.Taut_Iff_4 [neg t, pos t1, neg t2]
fun clausify_lit (t as Argo_Term.T (_, Argo_Expr.And, ts)) = clausify_and t ts
| clausify_lit (t as Argo_Term.T (_, Argo_Expr.Or, ts)) = clausify_or t ts
| clausify_lit (t as Argo_Term.T (_, Argo_Expr.Iff, [t1, t2])) = clausify_iff t t1 t2
| clausify_lit _ = I
fun exhaust_new_atoms ([], cx) = cx
| exhaust_new_atoms (t :: new_atoms, cx) = exhaust_new_atoms (clausify_lit t (new_atoms, cx))
fun clausify_expr _ (Argo_Expr.E (Argo_Expr.True, _), _) cx = cx
| clausify_expr _ (Argo_Expr.E (Argo_Expr.False, _), p) _ = Argo_Proof.unsat p
| clausify_expr f (Argo_Expr.E (Argo_Expr.And, es), p) cx =
fold_index (clausify_conj f (length es) p) es cx
| clausify_expr f (Argo_Expr.E (Argo_Expr.Or, es), p) cx = add_clausify f es p cx
| clausify_expr f (e, p) cx = add_clausify f [e] p cx
and clausify_conj f n p (i, e) (prf, core) =
let val (p, prf) = Argo_Proof.mk_conj i n p prf
in clausify_expr f (e, p) (prf, core) end
and add_clausify f es p cx =
let val ecx as (new_atoms, _) = add_clause lit_of es p ([], cx)
in fold f new_atoms ([], exhaust_new_atoms ecx) |-> fold (clausify_expr (K I)) end
fun clausify simp ep cx = clausify_expr (lift_ites simp) ep cx
end