Files
why3/examples/prover/Prover.mlw
2018-06-15 16:45:58 +02:00

1666 lines
83 KiB
Plaintext

module Types
use Functions.Func
use Firstorder_term_spec.Spec
(* The prover return a contradictory assignment.
To be perfectly correct, its initial
input (even before preprocessing) should not
contain any free variable of kind term. *)
type prover_return = {
ghost contradictory_assignment : int -> (fo_term int int) ;
}
end
module Logic
use FormulaTransformations.Types
use FormulaTransformations.Logic
use Firstorder_formula_list_spec.Spec
use Firstorder_formula_spec.Spec
use Firstorder_symbol_spec.Spec
use Firstorder_term_spec.Spec
use Firstorder_tableau_spec.Spec
use Functions.Func
use bool.Bool
use Firstorder_semantics.Sem
predicate is_atom_list (phil:fo_formula_list 'ls 'b) = match phil with
| FOFNil -> true
| FOFCons x q -> is_atom x /\ is_atom_list q
end
let lemma is_atom_subst (phi:fo_formula 'ls 'b)
(sigma:'b -> (fo_term 'ls 'c)) : unit
requires { is_atom phi }
ensures { is_atom (subst_fo_formula phi subst_id_symbol sigma) }
=
match phi with
| PApp _ _ -> ()
| Not (PApp _ _ ) -> ()
| _ -> absurd
end
let rec lemma is_atom_list_subst (phil:fo_formula_list 'ls 'b)
(sigma:'b -> (fo_term 'ls 'c)) : unit
requires { is_atom_list phil }
ensures { is_atom_list (subst_fo_formula_list phil subst_id_symbol sigma) }
variant { size_fo_formula_list phil }
=
match phil with
| FOFNil -> ()
| FOFCons x q -> is_atom_list_subst q sigma
end
predicate is_procedure_tableau (t:tableau 'ls 'b) = match t with
| Root -> true
| Node tnext phi0 phib -> is_procedure_tableau tnext /\
is_atom phi0 /\ is_atom_list phib
end
let rec lemma is_procedure_tableau_subst (t:tableau 'ls 'b)
(sigma:'b -> (fo_term 'ls 'c)) : unit
requires { is_procedure_tableau t }
ensures { is_procedure_tableau (subst_tableau t subst_id_symbol sigma) }
variant { size_tableau t }
=
match t with
| Root -> ()
| Node tnext phi0 phib -> is_procedure_tableau_subst tnext sigma
end
(*let rec lemma tableau_semantic_increasing (t:tableau 'ls 'b)
(b1 b2:bool) (m:model 'ls 'st) (rho:'b -> 'st) : unit
requires { implb b1 b2 = True }
ensures { tableau_semantic_with t b1 m rho ->
tableau_semantic_with t b2 m rho }
variant { size_tableau t }
=
match t with
| Root -> ()
| Node tnext phi0 phib ->
tableau_semantic_increasing tnext (tableau_node b1 phib phi0 m rho)
(tableau_node b2 phib phi0 m rho) m rho
end*)
end
module Impl
use Firstorder_semantics.Sem
use Firstorder_symbol_spec.Spec
use Firstorder_symbol_impl.Types
use Firstorder_symbol_impl.Logic
use Firstorder_symbol_impl.Impl
use Firstorder_term_spec.Spec
use Firstorder_term_impl.Types
use Firstorder_term_impl.Logic
use Firstorder_term_impl.Impl
use Firstorder_formula_spec.Spec
use Firstorder_formula_impl.Types
use Firstorder_formula_impl.Logic
use Firstorder_formula_impl.Impl
use Firstorder_formula_list_spec.Spec
use Firstorder_formula_list_impl.Types
use Firstorder_formula_list_impl.Logic
use Firstorder_formula_list_impl.Impl
use Firstorder_tableau_spec.Spec
use Firstorder_tableau_impl.Types
use Firstorder_tableau_impl.Logic
use Firstorder_tableau_impl.Impl
use FormulaTransformations.Types
use FormulaTransformations.Logic
use FormulaTransformations.Impl
use Unification.Types
use Unification.Logic
use Unification.Impl
use BacktrackArray.Logic
use BacktrackArray.Impl
use Functions.Func
use option.Option
use OptionFuncs.Funcs
use bool.Bool
use int.Int
use Types
use Logic
use ref.Ref
use list.List
exception Failure
let rec merge (phi1 phi2:nlimpl_fo_formula_list) (ghost st:'st) : nlimpl_fo_formula_list
requires { nlimpl_fo_formula_list_ok phi1 }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
phi1.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_fo_formula_list_ok phi2 }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
phi2.model_fo_formula_list_field -> x >= 0 }
requires { is_atom_list phi1.model_fo_formula_list_field }
requires { is_atom_list phi2.model_fo_formula_list_field }
ensures { nlimpl_fo_formula_list_ok result }
ensures { forall x:int. is_fo_term_free_var_in_fo_formula_list x
result.model_fo_formula_list_field -> x >= 0 }
ensures { forall m:model int 'st,rho:int -> 'st.
formula_list_disj_semantic result.model_fo_formula_list_field m rho <->
formula_list_disj_semantic phi1.model_fo_formula_list_field m rho \/
formula_list_disj_semantic phi2.model_fo_formula_list_field m rho }
ensures { is_atom_list result.model_fo_formula_list_field }
variant { size_fo_formula_list phi1.model_fo_formula_list_field }
=
let phi1m = phi1.model_fo_formula_list_field in
let phi2m = phi2.model_fo_formula_list_field in
match destruct_fo_formula_list phi1 with
| NLC_FOFNil -> phi2
| NLC_FOFCons phi0 q ->
let phi0m = phi0.model_fo_formula_field in
let qm = q.model_fo_formula_list_field in
assert { phi1m = FOFCons phi0m qm } ;
let phi3 = construct_fo_formula_list (NLC_FOFCons phi0 phi2) in
let phi3m = phi3.model_fo_formula_list_field in
assert { phi3m = FOFCons phi0m phi2m } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x phi0m ->
is_fo_term_free_var_in_fo_formula_list x phi1m && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x phi3m ->
(is_fo_term_free_var_in_fo_formula x phi0m \/
is_fo_term_free_var_in_fo_formula_list x phi2m) && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x qm ->
is_fo_term_free_var_in_fo_formula_list x phi1m && x >= 0 } ;
merge q phi3 st
end
(* extend the current tableau branch by the given formula list.
equivalent to contraction of empty branches
until a non-empty branch is found. *)
let rec contract_tableau (tab:nlimpl_tableau)
(branch:nlimpl_fo_formula_list) (ndepth:ref int) (ghost st:'st) : option nlimpl_tableau
requires { nlimpl_tableau_ok tab }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab.model_tableau_field -> x >= 0 }
requires { nlimpl_fo_formula_list_ok branch }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
branch.model_fo_formula_list_field -> x >= 0 }
requires { is_procedure_tableau tab.model_tableau_field }
requires { is_atom_list branch.model_fo_formula_list_field }
returns { None -> forall m:model int 'st,rho:int -> 'st.
let b = if formula_list_disj_semantic branch.model_fo_formula_list_field m rho
then True
else False in
not(tableau_semantic_with tab.model_tableau_field b m rho)
| Some x -> (forall m:model int 'st,rho:int -> 'st.
let b = if formula_list_disj_semantic branch.model_fo_formula_list_field m rho
then True
else False in
tableau_semantic_with tab.model_tableau_field b m rho ->
tableau_semantic_with x.model_tableau_field True m rho) /\
is_procedure_tableau x.model_tableau_field /\
nlimpl_tableau_ok x /\
(forall y:int. is_fo_term_free_var_in_tableau y x.model_tableau_field
-> y >= 0) }
variant { size_tableau tab.model_tableau_field }
=
let tabm = tab.model_tableau_field in
let brm = branch.model_fo_formula_list_field in
match destruct_fo_formula_list branch with
| NLC_FOFNil -> assert { brm = FOFNil } ;
assert { forall m:model int 'st,rho:int -> 'st.
not(formula_list_disj_semantic brm m rho) } ;
match destruct_tableau tab with
| NLC_Root -> assert { tabm = Root } ; None
| NLC_Node tnext phi0 phib ->
let tnm = tnext.model_tableau_field in
let phi0m = phi0.model_fo_formula_field in
let phibm = phib.model_fo_formula_list_field in
assert { tabm = Node tnm phi0m phibm } ;
assert { forall x:int. is_fo_term_free_var_in_tableau x tnm ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x phibm ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { forall m:model int 'st,rho:int -> 'st.
tableau_semantic_with tab.model_tableau_field False m rho ->
let b = if formula_list_disj_semantic phibm m rho
then True
else False in
tableau_semantic_with tnm b m rho } ;
ndepth := !ndepth + 1 ;
contract_tableau tnext phib ndepth st
end
| NLC_FOFCons phi0 qb -> let phi0m = phi0.model_fo_formula_field in
let qbm = qb.model_fo_formula_list_field in
assert { brm = FOFCons phi0m qbm } ;
let ftab = construct_tableau (NLC_Node tab phi0 qb) in
let ftabm = ftab.model_tableau_field in
assert { ftabm = Node tabm phi0m qbm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x phi0m ->
is_fo_term_free_var_in_fo_formula_list x brm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x qbm ->
is_fo_term_free_var_in_fo_formula_list x brm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_tableau x ftabm ->
(is_fo_term_free_var_in_tableau x tabm
\/ is_fo_term_free_var_in_fo_formula x phi0m
\/ is_fo_term_free_var_in_fo_formula_list x qbm) && x >= 0 } ;
Some ftab
end
let rec branch_conflict_atom (p1:int) (t1:nlimpl_fo_term_list) (tab:nlimpl_tableau)
(rhob:subst) (ghost rho:unifier_subst) : unit
requires { nlimpl_fo_term_list_ok t1 }
requires { forall x:int. is_fo_term_free_var_in_fo_term_list x
t1.model_fo_term_list_field -> x >= 0 }
requires { nlimpl_tableau_ok tab }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab.model_tableau_field -> x >= 0 }
requires { unifier_subst_ok rhob rho }
requires { is_procedure_tableau tab.model_tableau_field }
ensures { precede (old rhob) rhob }
ensures { unifier_subst_ok rhob rho }
raises { Failure -> precede (old rhob) rhob /\ correct rhob }
diverges (* variant { size_tableau tab.model_tableau_field } *)
=
let tabm = tab.model_tableau_field in
match destruct_tableau tab with
| NLC_Root -> ()
| NLC_Node tnext phi1 phib ->
let tnextm = tnext.model_tableau_field in
let phi1m = phi1.model_fo_formula_field in
let phibm = phib.model_fo_formula_list_field in
assert { tabm = Node tnextm phi1m phibm } ;
assert { is_atom phi1m } ;
assert { forall x:int. is_fo_term_free_var_in_tableau x tnextm ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
match destruct_fo_formula phi1 with
| NLC_PApp p2 t2 -> let p2m = p2.model_symbol_field in
let t2m = t2.model_fo_term_list_field in
assert { forall x:int. is_fo_term_free_var_in_fo_term_list x t2m ->
is_fo_term_free_var_in_fo_formula x phi1m &&
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
let p3 = match destruct_symbol p2 with
| NLCVar_symbol p3 -> p3 end in
if p1 = p3
then begin
try conflict t1 t2 rhob rho with UnificationFailure ->
raise Failure end ;
branch_conflict_atom p1 t1 tnext rhob rho
end
else branch_conflict_atom p1 t1 tnext rhob rho
| NLC_Not _ -> branch_conflict_atom p1 t1 tnext rhob rho
| _ -> absurd
end
end
let rec branch_conflict_neg_atom (p1:int) (t1:nlimpl_fo_term_list) (tab:nlimpl_tableau)
(rhob:subst) (ghost rho:unifier_subst) : unit
requires { nlimpl_fo_term_list_ok t1 }
requires { forall x:int. is_fo_term_free_var_in_fo_term_list x
t1.model_fo_term_list_field -> x >= 0 }
requires { nlimpl_tableau_ok tab }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab.model_tableau_field -> x >= 0 }
requires { unifier_subst_ok rhob rho }
requires { is_procedure_tableau tab.model_tableau_field }
ensures { precede (old rhob) rhob }
ensures { unifier_subst_ok rhob rho }
raises { Failure -> precede (old rhob) rhob /\ correct rhob }
diverges (* variant { size_tableau tab.model_tableau_field } *)
=
let tabm = tab.model_tableau_field in
match destruct_tableau tab with
| NLC_Root -> ()
| NLC_Node tnext phi1 phib ->
let tnextm = tnext.model_tableau_field in
let phi1m = phi1.model_fo_formula_field in
let phibm = phib.model_fo_formula_list_field in
assert { tabm = Node tnextm phi1m phibm } ;
assert { is_atom phi1m } ;
assert { forall x:int. is_fo_term_free_var_in_tableau x tnextm ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
match destruct_fo_formula phi1 with
| NLC_Not phi2 -> let phi2m = phi2.model_fo_formula_field in
assert { phi1m = Not phi2m } ;
match destruct_fo_formula phi2 with
| NLC_PApp p2 t2 -> let p2m = p2.model_symbol_field in
let t2m = t2.model_fo_term_list_field in
assert { forall x:int. is_fo_term_free_var_in_fo_term_list x t2m ->
is_fo_term_free_var_in_fo_formula x phi1m &&
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
let p3 = match destruct_symbol p2 with
| NLCVar_symbol p3 -> p3 end in
if p1 = p3
then begin
try conflict t1 t2 rhob rho with UnificationFailure ->
raise Failure end ;
branch_conflict_atom p1 t1 tnext rhob rho
end
else branch_conflict_atom p1 t1 tnext rhob rho
| _ -> absurd
end
| NLC_PApp _ _ -> branch_conflict_atom p1 t1 tnext rhob rho
| _ -> absurd
end
end
let rec clause_conflicts (phil:nlimpl_fo_formula_list) (tab:nlimpl_tableau)
(rhob:subst) (ghost rho:unifier_subst) : unit
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
phil.model_fo_formula_list_field -> x >= 0 }
requires { is_atom_list phil.model_fo_formula_list_field }
requires { nlimpl_fo_formula_list_ok phil }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab.model_tableau_field -> x >= 0 }
requires { is_procedure_tableau tab.model_tableau_field }
requires { nlimpl_tableau_ok tab }
requires { unifier_subst_ok rhob rho }
ensures { precede (old rhob) rhob }
ensures { unifier_subst_ok rhob rho }
raises { Failure -> precede (old rhob) rhob /\ correct rhob }
diverges (* variant { size_fo_formula_list phil.model_fo_formula_list_field } *)
=
let philm = phil.model_fo_formula_list_field in
match destruct_fo_formula_list phil with
| NLC_FOFNil -> ()
| NLC_FOFCons phi0 phiq -> let phi0m = phi0.model_fo_formula_field in
let phiqm = phiq.model_fo_formula_list_field in
assert { philm = FOFCons phi0m phiqm } ;
assert { is_atom phi0m } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x phiqm ->
is_fo_term_free_var_in_fo_formula_list x philm && x >= 0 } ;
match destruct_fo_formula phi0 with
| NLC_PApp p1 t1 -> let p1m = p1.model_symbol_field in
let t1m = t1.model_fo_term_list_field in
assert { phi0m = PApp p1m t1m } ;
let p1' = match destruct_symbol p1 with
| NLCVar_symbol p1' -> p1'
end in
assert { forall x:int. is_fo_term_free_var_in_fo_term_list x t1m ->
is_fo_term_free_var_in_fo_formula x phi0m &&
is_fo_term_free_var_in_fo_formula_list x philm && x >= 0 } ;
branch_conflict_atom p1' t1 tab rhob rho ;
clause_conflicts phiq tab rhob rho
| NLC_Not phi1 -> let phi1m = phi1.model_fo_formula_field in
assert { phi0m = Not phi1m } ;
match destruct_fo_formula phi1 with
| NLC_PApp p1 t1 -> let p1' = match destruct_symbol p1 with
| NLCVar_symbol p1' -> p1'
end in
let t1m = t1.model_fo_term_list_field in
let p1m = p1.model_symbol_field in
assert { phi1m = PApp p1m t1m } ;
assert { forall x:int. is_fo_term_free_var_in_fo_term_list x t1m ->
is_fo_term_free_var_in_fo_formula x phi1m &&
is_fo_term_free_var_in_fo_formula x phi0m &&
is_fo_term_free_var_in_fo_formula_list x philm && x >= 0 } ;
branch_conflict_neg_atom p1' t1 tab rhob rho ;
clause_conflicts phiq tab rhob rho
| _ -> absurd
end
| _ -> absurd
end
end
(* base:set of initial (preprocessed) formula.
tab:context still to be proved.
Return: nothing, if successful, base is unsatisfiable.
May fail without justification.
*)
let rec decompose (base:nlimpl_fo_formula_list)
(tab:nlimpl_tableau)
(unifb:subst)
(ghost unif:unifier_subst)
(fresh:int)
(phi0:nlimpl_fo_formula)
(clause:nlimpl_fo_formula_list)
(remaining:nlimpl_fo_formula_list)
(depth:int)
(goalnum:int) (ghost st:'st) : prover_return
requires { fresh >= 0 }
requires { nlimpl_fo_formula_list_ok base }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
base.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_tableau_ok tab }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab.model_tableau_field -> x >= 0 }
requires { unifier_subst_ok unifb unif }
requires { nlimpl_fo_formula_ok phi0 }
requires { forall x:int. is_fo_term_free_var_in_fo_formula x
phi0.model_fo_formula_field -> x >= 0 }
requires { nlimpl_fo_formula_list_ok clause }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
clause.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_fo_formula_list_ok remaining }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
remaining.model_fo_formula_list_field -> x >= 0 }
requires { is_procedure_tableau tab.model_tableau_field }
requires { is_simpl_list base.model_fo_formula_list_field }
requires { is_nnf_list base.model_fo_formula_list_field }
requires { no_existential_list base.model_fo_formula_list_field }
requires { is_simpl phi0.model_fo_formula_field }
requires { no_existential phi0.model_fo_formula_field }
requires { is_nnf phi0.model_fo_formula_field }
requires { is_atom_list clause.model_fo_formula_list_field }
requires { is_simpl_list remaining.model_fo_formula_list_field }
requires { is_nnf_list remaining.model_fo_formula_list_field }
requires { no_existential_list remaining.model_fo_formula_list_field }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
tableau_semantic_with tab.model_tableau_field True m rhos }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
formula_semantic phi0.model_fo_formula_field m rhos \/
formula_list_disj_semantic clause.model_fo_formula_list_field m rhos \/
formula_list_disj_semantic remaining.model_fo_formula_list_field m rhos }
diverges
ensures { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst result.contradictory_assignment m rho in
not(formula_list_conj_semantic base.model_fo_formula_list_field m rhos) }
ensures { precede (old unifb) unifb /\ correct unifb }
raises { Failure -> precede (old unifb) unifb /\ correct unifb }
=
let phi0m = phi0.model_fo_formula_field in
let rmgm = remaining.model_fo_formula_list_field in
let basem = base.model_fo_formula_list_field in
let clausem = clause.model_fo_formula_list_field in
let tabm = tab.model_tableau_field in
match destruct_fo_formula phi0 with
| NLC_Or a b ->
let am = a.model_fo_formula_field in
let bm = b.model_fo_formula_field in
assert { phi0m = Or am bm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x am ->
is_fo_term_free_var_in_fo_formula x phi0m && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x bm ->
is_fo_term_free_var_in_fo_formula x phi0m && x >= 0 } ;
let rmg = construct_fo_formula_list (NLC_FOFCons b remaining) in
let rmg'_m = rmg.model_fo_formula_list_field in
assert { rmg'_m = FOFCons bm rmgm } ;
decompose base tab unifb unif fresh a clause rmg depth goalnum st
| NLC_And a b -> let am = a.model_fo_formula_field in
let bm = b.model_fo_formula_field in
assert { phi0m = And am bm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x am ->
is_fo_term_free_var_in_fo_formula x phi0m && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x bm ->
is_fo_term_free_var_in_fo_formula x phi0m && x >= 0 } ;
label B in
let tp = stamp unifb in
try decompose base tab unifb unif fresh a clause remaining depth goalnum st
with Failure -> label F in backtrack tp unifb ;
assert { backtrack_to (unifb at B) (unifb at F) unifb } ;
decompose base tab unifb unif fresh b clause remaining depth goalnum st end
| NLC_Exists _ _ -> absurd
| NLC_FTrue -> absurd
| NLC_FFalse -> absurd
| NLC_Forall x phi1 ->
let phi1m = phi1.model_fo_formula_field in
let vfresh = construct_fo_term (NLCVar_fo_term fresh) in
let phi2 = nlsubst_fo_term_in_fo_formula phi1 x vfresh in
let phi2m = phi2.model_fo_formula_field in
let ghost r0 = some[x <- None] in
let ghost r1 = ocase identity x in
let ghost r2 = ocase identity fresh in
let ghost r3 = identity[x <- fresh] in
let ghost sid = (subst_id_fo_term:int -> (fo_term int int)) in
let ghost s3 = sid[x <- Var_fo_term fresh] in
let ghost s3' = rcompose r3 sid in
let ghost s2 = rcompose r2 sid in
assert { extensionalEqual s3' s3 } ;
let ghost phi3m = rename_fo_formula phi1m identity r0 in
assert { phi0m = Forall phi3m &&
phi1m = rename_fo_formula phi3m identity r1 } ;
assert { phi2m = subst_fo_formula phi1m (rcompose identity subst_id_symbol) s3'
= rename_fo_formula phi1m identity r3 } ;
assert { extensionalEqual r3 (rcompose r0 r2) } ;
assert { phi2m = rename_fo_formula phi3m identity r2 =
subst_fo_formula phi3m subst_id_symbol s2 } ;
assert { forall m:model int 'st, rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
let s0 = semantic_subst s2 m rhos in
let s1 = ocase rhos (term_semantic (Var_fo_term fresh) m rhos) in
s0 None = s1 None &&
(forall x:int. s2 (Some x) = Var_fo_term x &&
s0 (Some x) = term_semantic (Var_fo_term x) m rhos = s1 (Some x)) &&
extensionalEqual s0 s1 &&
(formula_semantic phi0m m rhos ->
formula_semantic phi2m m rhos)
} ;
assert { forall x:int.
(forall y:option int. is_fo_term_free_var_in_fo_formula y phi3m /\
r2 y = x -> match y with None -> x = fresh && x >= 0
| Some y -> x = y &&
is_fo_term_free_var_in_fo_formula (Some x) phi3m &&
is_fo_term_free_var_in_fo_formula x phi0m && x >= 0 end &&
x >= 0) &&
(is_fo_term_free_var_in_fo_formula x phi2m ->
(exists y:option int. is_fo_term_free_var_in_fo_formula y phi3m /\
r2 y = x) && x >= 0) &&
(is_fo_term_free_var_in_fo_formula x phi2m -> x >= 0)
} ;
decompose base tab unifb unif (fresh + 1) phi2 clause remaining depth goalnum st
| NLC_PApp p l -> assert { is_atom phi0m } ;
decompose_literal base tab unifb unif fresh phi0 clause remaining depth goalnum st
| NLC_Not phi1 -> assert { is_atom phi0m } ;
decompose_literal base tab unifb unif fresh phi0 clause remaining depth goalnum st
end
with decompose_literal (base:nlimpl_fo_formula_list)
(tab:nlimpl_tableau)
(unifb:subst)
(ghost unif:unifier_subst)
(fresh:int)
(phi0:nlimpl_fo_formula)
(clause:nlimpl_fo_formula_list)
(remaining:nlimpl_fo_formula_list)
(depth:int)
(goalnum:int) (ghost st:'st) : prover_return
requires { fresh >= 0 }
requires { nlimpl_fo_formula_list_ok base }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
base.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_tableau_ok tab }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab.model_tableau_field -> x >= 0 }
requires { unifier_subst_ok unifb unif }
requires { nlimpl_fo_formula_ok phi0 }
requires { forall x:int. is_fo_term_free_var_in_fo_formula x
phi0.model_fo_formula_field -> x >= 0 }
requires { nlimpl_fo_formula_list_ok clause }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
clause.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_fo_formula_list_ok remaining }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
remaining.model_fo_formula_list_field -> x >= 0 }
requires { is_procedure_tableau tab.model_tableau_field }
requires { is_simpl_list base.model_fo_formula_list_field }
requires { is_nnf_list base.model_fo_formula_list_field }
requires { no_existential_list base.model_fo_formula_list_field }
requires { is_atom phi0.model_fo_formula_field }
requires { is_atom_list clause.model_fo_formula_list_field }
requires { is_simpl_list remaining.model_fo_formula_list_field }
requires { is_nnf_list remaining.model_fo_formula_list_field }
requires { no_existential_list remaining.model_fo_formula_list_field }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
tableau_semantic_with tab.model_tableau_field True m rhos }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
formula_semantic phi0.model_fo_formula_field m rhos \/
formula_list_disj_semantic clause.model_fo_formula_list_field m rhos \/
formula_list_disj_semantic remaining.model_fo_formula_list_field m rhos }
diverges
ensures { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst result.contradictory_assignment m rho in
not(formula_list_conj_semantic base.model_fo_formula_list_field m rhos) }
ensures { precede (old unifb) unifb /\ correct unifb }
raises { Failure -> precede (old unifb) unifb /\ correct unifb }
=
let phi0m = phi0.model_fo_formula_field in
let rmgm = remaining.model_fo_formula_list_field in
let basem = base.model_fo_formula_list_field in
let clausem = clause.model_fo_formula_list_field in
let tabm = tab.model_tableau_field in
match destruct_fo_formula_list remaining with
| NLC_FOFNil -> assert { rmgm = FOFNil } ;
match destruct_tableau tab with
| NLC_Root -> (* Topmost decomposition,
do not look for contradiction here. *)
let tab' = construct_tableau (NLC_Node tab phi0 clause) in
let tab'_m = tab'.model_tableau_field in
assert { tab'_m = Node tabm phi0m clausem } ;
if depth = 0 then raise Failure else
select_lemma base base tab' unifb unif fresh (depth-1) goalnum (-1) st
| NLC_Node tnext phi1 phib ->
let clse = construct_fo_formula_list (NLC_FOFCons phi0 clause) in
let clsem = clse.model_fo_formula_list_field in
let phi1m = phi1.model_fo_formula_field in
let tnextm = tnext.model_tableau_field in
let phibm = phib.model_fo_formula_list_field in
assert { clsem = FOFCons phi0m clausem } ;
assert { is_atom_list clsem } ;
assert { tabm = Node tnextm phi1m phibm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x phibm ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x phi1m ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_tableau x tnextm ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
let fonil = construct_fo_formula_list NLC_FOFNil in
assert { fonil.model_fo_formula_list_field = FOFNil } ;
assert { is_atom phi1m } ;
match destruct_fo_formula phi1 with
| NLC_PApp ptab ttab ->
let ptabm = ptab.model_symbol_field in
let ttabm = ttab.model_fo_term_list_field in
assert { phi1m = PApp ptabm ttabm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_term_list x ttabm ->
is_fo_term_free_var_in_fo_formula x phi1m && x >= 0 } ;
let ptab2 = match destruct_symbol ptab with
| NLCVar_symbol ptab2 -> assert { ptabm = Var_symbol ptab2 } ;
ptab2
end in
contradiction_atom base tab unifb unif fresh ptab2 ttab phibm tnextm clsem clse fonil depth goalnum st
| NLC_Not phi2 -> let phi2m = phi2.model_fo_formula_field in
assert { phi1m = Not phi2m } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x phi2m
-> is_fo_term_free_var_in_fo_formula x phi1m && x >= 0 } ;
match destruct_fo_formula phi2 with
| NLC_PApp ptab ttab ->
let ptabm = ptab.model_symbol_field in
let ttabm = ttab.model_fo_term_list_field in
assert { phi2m = PApp ptabm ttabm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_term_list x ttabm ->
is_fo_term_free_var_in_fo_formula x phi2m && x >= 0 } ;
let ptab2 = match destruct_symbol ptab with
| NLCVar_symbol ptab2 -> assert { ptabm = Var_symbol ptab2 } ;
ptab2
end in
contradiction_neg_atom base tab unifb unif fresh ptab2 ttab phibm tnextm clsem clse fonil depth goalnum st
| _ -> absurd
end
| _ -> absurd
end
end
| NLC_FOFCons phi1 qr ->
let phi1m = phi1.model_fo_formula_field in
let qrm = qr.model_fo_formula_list_field in
assert { rmgm = FOFCons phi1m qrm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x phi1m ->
is_fo_term_free_var_in_fo_formula_list x rmgm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x qrm ->
is_fo_term_free_var_in_fo_formula_list x rmgm && x >= 0 } ;
let clse = construct_fo_formula_list (NLC_FOFCons phi0 clause) in
let clsem = clse.model_fo_formula_list_field in
assert { clsem = FOFCons phi0m clausem } ;
decompose base tab unifb unif fresh phi1 clse qr depth goalnum st
end
(* find a contradiction with the current leaf of the tableau,
if it is a non-negated literal. *)
with contradiction_atom (base:nlimpl_fo_formula_list)
(tab:nlimpl_tableau)
(unifb:subst)
(ghost unif:unifier_subst)
(fresh:int)
(p:int)
(t:nlimpl_fo_term_list)
(ghost phit:fo_formula_list int int)
(ghost tnext:tableau int int)
(ghost clsem:fo_formula_list int int)
(phil:nlimpl_fo_formula_list)
(phiacc:nlimpl_fo_formula_list)
(depth:int)
(goalnum:int) (ghost st:'st) : prover_return
requires { fresh >= 0 }
requires { nlimpl_fo_formula_list_ok base }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
base.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_tableau_ok tab }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab.model_tableau_field -> x >= 0 }
requires { nlimpl_fo_formula_list_ok phil }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
phil.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_fo_formula_list_ok phiacc }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
phiacc.model_fo_formula_list_field -> x >= 0 }
requires { unifier_subst_ok unifb unif }
requires { nlimpl_fo_term_list_ok t }
requires { forall x:int. is_fo_term_free_var_in_fo_term_list x
t.model_fo_term_list_field -> x >= 0 }
requires { tab.model_tableau_field =
Node tnext (PApp (Var_symbol p) t.model_fo_term_list_field) phit }
requires { is_procedure_tableau tab.model_tableau_field }
requires { is_simpl_list base.model_fo_formula_list_field }
requires { is_nnf_list base.model_fo_formula_list_field }
requires { no_existential_list base.model_fo_formula_list_field }
requires { is_atom_list phil.model_fo_formula_list_field }
requires { is_atom_list phiacc.model_fo_formula_list_field }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
tableau_semantic_with tab.model_tableau_field True m rhos }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
formula_list_disj_semantic clsem m rhos }
requires { forall m:model int 'st, rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_disj_semantic clsem m rhos <->
formula_list_disj_semantic phil.model_fo_formula_list_field m rhos \/
formula_list_disj_semantic phiacc.model_fo_formula_list_field m rhos }
diverges
ensures { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst result.contradictory_assignment m rho in
not(formula_list_conj_semantic base.model_fo_formula_list_field m rhos) }
ensures { precede (old unifb) unifb /\ correct unifb }
raises { Failure -> precede (old unifb) unifb /\ correct unifb }
=
let basem = base.model_fo_formula_list_field in
let tabm = tab.model_tableau_field in
let tm = t.model_fo_term_list_field in
let philm = phil.model_fo_formula_list_field in
let phiaccm = phiacc.model_fo_formula_list_field in
let phibasem = PApp (Var_symbol p) tm in
match destruct_fo_formula_list phil with
| NLC_FOFNil -> raise Failure (* no contradiction found. *)
| NLC_FOFCons phi0 q -> (* Maybe phi0 is a contradiction. *)
let phi0m = phi0.model_fo_formula_field in
let qm = q.model_fo_formula_list_field in
assert { philm = FOFCons phi0m qm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x phi0m ->
is_fo_term_free_var_in_fo_formula_list x philm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x qm ->
is_fo_term_free_var_in_fo_formula_list x philm && x >= 0 } ;
assert { is_atom phi0m } ;
(* prepare backtracking data. *)
let phiacc2 = construct_fo_formula_list (NLC_FOFCons phi0 phiacc) in
let phiacc2m = phiacc2.model_fo_formula_list_field in
assert { phiacc2m = FOFCons phi0m phiaccm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x phiacc2m ->
(is_fo_term_free_var_in_fo_formula x phi0m \/
is_fo_term_free_var_in_fo_formula_list x phiaccm) && x >= 0 } ;
match destruct_fo_formula phi0 with
| NLC_Not phi1 -> let phi1m = phi1.model_fo_formula_field in
assert { phi0m = Not phi1m } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x phi1m ->
is_fo_term_free_var_in_fo_formula x phi0m && x >= 0 } ;
match destruct_fo_formula phi1 with
| NLC_PApp p2 t2 -> match destruct_symbol p2 with
| NLCVar_symbol p3 -> let t2m = t2.model_fo_term_list_field in
assert { phi1m = PApp (Var_symbol p3) t2m } ;
assert { forall x:int. is_fo_term_free_var_in_fo_term_list x t2m ->
is_fo_term_free_var_in_fo_formula x phi1m && x >= 0 } ;
if p = p3
then (* let-try. *)
label B in let tp = stamp unifb in
let l0 = ref Nil in
match try let u = unify_term_list t t2 l0 unifb unif in Some u
with UnificationFailure -> None end with
(* Contradiction found. *)
| Some u -> let unif2 = u.final_unifier in
(* should walk back in the tableau
until a non-empty branch is found. *)
let phifinal = merge phiacc q st in
let b = try clause_conflicts phifinal tab unifb unif2;
False with Failure -> True end in
match b with
| True -> label T in backtrack tp unifb ;
assert { backtrack_to (unifb at B) (unifb at T) unifb } ;
contradiction_atom base tab unifb unif fresh p t phit tnext clsem q phiacc2 depth goalnum st
| False -> assert { precede (unifb at B) unifb } ;
let phifm = phifinal.model_fo_formula_list_field in
assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif2.unifier m rho in
let rhos0 = semantic_subst u.unifier_factor m rho in
(forall x:int.
eval unif2.unifier x = subst_fo_term (eval unif.unifier x)
(rcompose identity subst_id_symbol) u.unifier_factor &&
rhos x = term_semantic (eval unif2.unifier x) m rho
= term_semantic (eval unif.unifier x) (model_rename identity m) rhos0
= semantic_subst unif.unifier m rhos0 x) &&
extensionalEqual rhos
(semantic_subst unif.unifier m rhos0) &&
subst_fo_formula phi1m subst_id_symbol unif2.unifier =
subst_fo_formula phibasem subst_id_symbol unif2.unifier &&
(formula_semantic phi1m m rhos <->
formula_semantic phibasem m rhos) &&
not(formula_semantic phi0m m rhos /\
formula_semantic phibasem m rhos) &&
(formula_list_conj_semantic basem m rhos ->
tableau_semantic_with tabm True m rhos &&
(formula_list_disj_semantic clsem m rhos) &&
(formula_list_disj_semantic phifm m rhos \/
formula_semantic phi0m m rhos) &&
let b = if formula_list_disj_semantic phifm m rhos
then True
else False in
tableau_semantic_with tabm b m rhos) } ;
let nd = ref depth in
let ct = contract_tableau tab phifinal nd st in
let depth = !nd in
match ct with
| None -> assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif2.unifier m rho in
let b = if formula_list_disj_semantic phifm m rhos
then True
else False in
not(tableau_semantic_with tabm b m rhos) &&
not(formula_list_conj_semantic basem m rhos) } ;
{ contradictory_assignment = unif2.unifier }
(* continue proof search. If fail,
backtrack to find another contradiction. *)
| Some tab2 ->
let tab2m = tab2.model_tableau_field in
assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif2.unifier m rho in
formula_list_conj_semantic basem m rhos ->
let b = if formula_list_disj_semantic phifm m rhos
then True
else False in
tableau_semantic_with tabm b m rhos &&
tableau_semantic_with tab2m True m rhos
} ;
match !l0 with
| Nil -> extend_branch base tab2 unifb unif2 fresh depth goalnum st
| _ -> try extend_branch base tab2 unifb unif2 fresh depth goalnum st
with Failure ->
label F in backtrack tp unifb ;
assert { backtrack_to (unifb at B) (unifb at F) unifb } ;
try conflict t t2 unifb unif
with UnificationFailure -> raise Failure end ;
contradiction_atom base tab unifb unif fresh p t phit tnext clsem q phiacc2 depth goalnum st
end
end
end end
| None -> label N in backtrack tp unifb ;
assert { backtrack_to (unifb at B) (unifb at N) unifb } ;
contradiction_atom base tab unifb unif fresh p t phit tnext clsem q phiacc2 depth goalnum st
end
else (* do not conflict. *)
contradiction_atom base tab unifb unif fresh p t phit tnext clsem q phiacc2 depth goalnum st
end
| _ -> absurd (* phi0 is literal. *)
end
| NLC_PApp _ _ -> (* do not conflict. *)
contradiction_atom base tab unifb unif fresh p t phit tnext clsem q phiacc2 depth goalnum st
| _ -> absurd (* phi0 is literal. *)
end
end
(* find a contradiction with the current leaf of the tableau,
if it is a negated literal. *)
with contradiction_neg_atom (base:nlimpl_fo_formula_list)
(tab:nlimpl_tableau)
(unifb:subst)
(ghost unif:unifier_subst)
(fresh:int)
(p:int)
(t:nlimpl_fo_term_list)
(ghost phit:fo_formula_list int int)
(ghost tnext:tableau int int)
(ghost clsem:fo_formula_list int int)
(phil:nlimpl_fo_formula_list)
(phiacc:nlimpl_fo_formula_list)
(depth:int)
(goalnum:int) (ghost st:'st) : prover_return
requires { fresh >= 0 }
requires { nlimpl_fo_formula_list_ok base }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
base.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_tableau_ok tab }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab.model_tableau_field -> x >= 0 }
requires { nlimpl_fo_formula_list_ok phil }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
phil.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_fo_formula_list_ok phiacc }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
phiacc.model_fo_formula_list_field -> x >= 0 }
requires { unifier_subst_ok unifb unif }
requires { nlimpl_fo_term_list_ok t }
requires { forall x:int. is_fo_term_free_var_in_fo_term_list x
t.model_fo_term_list_field -> x >= 0 }
requires { tab.model_tableau_field =
Node tnext (Not (PApp (Var_symbol p) t.model_fo_term_list_field)) phit }
requires { is_procedure_tableau tab.model_tableau_field }
requires { is_simpl_list base.model_fo_formula_list_field }
requires { is_nnf_list base.model_fo_formula_list_field }
requires { no_existential_list base.model_fo_formula_list_field }
requires { is_atom_list phil.model_fo_formula_list_field }
requires { is_atom_list phiacc.model_fo_formula_list_field }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
tableau_semantic_with tab.model_tableau_field True m rhos }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
formula_list_disj_semantic clsem m rhos }
requires { forall m:model int 'st, rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_disj_semantic clsem m rhos <->
formula_list_disj_semantic phil.model_fo_formula_list_field m rhos \/
formula_list_disj_semantic phiacc.model_fo_formula_list_field m rhos }
ensures { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst result.contradictory_assignment m rho in
not(formula_list_conj_semantic base.model_fo_formula_list_field m rhos) }
ensures { precede (old unifb) unifb /\ correct unifb }
diverges
raises { Failure -> precede (old unifb) unifb /\ correct unifb }
=
let basem = base.model_fo_formula_list_field in
let tabm = tab.model_tableau_field in
let tm = t.model_fo_term_list_field in
let philm = phil.model_fo_formula_list_field in
let phiaccm = phiacc.model_fo_formula_list_field in
let phi1m = PApp (Var_symbol p) tm in
let phibasem = Not phi1m in
match destruct_fo_formula_list phil with
| NLC_FOFNil -> raise Failure (* no contradiction found. *)
| NLC_FOFCons phi0 q -> (* Maybe phi0 is a contradiction. *)
let phi0m = phi0.model_fo_formula_field in
let qm = q.model_fo_formula_list_field in
assert { philm = FOFCons phi0m qm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x phi0m ->
is_fo_term_free_var_in_fo_formula_list x philm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x qm ->
is_fo_term_free_var_in_fo_formula_list x philm && x >= 0 } ;
assert { is_atom phi0m } ;
(* prepare backtracking data. *)
let phiacc2 = construct_fo_formula_list (NLC_FOFCons phi0 phiacc) in
let phiacc2m = phiacc2.model_fo_formula_list_field in
assert { phiacc2m = FOFCons phi0m phiaccm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x phiacc2m ->
(is_fo_term_free_var_in_fo_formula x phi0m \/
is_fo_term_free_var_in_fo_formula_list x phiaccm) && x >= 0 } ;
match destruct_fo_formula phi0 with
| NLC_PApp p2 t2 -> match destruct_symbol p2 with
| NLCVar_symbol p3 -> let t2m = t2.model_fo_term_list_field in
assert { phi0m = PApp (Var_symbol p3) t2m } ;
assert { forall x:int. is_fo_term_free_var_in_fo_term_list x t2m ->
is_fo_term_free_var_in_fo_formula x phi0m && x >= 0 } ;
if p = p3
then (* let-try. *)
label B in let tp = stamp unifb in
let l0 = ref Nil in
match try let u = unify_term_list t t2 l0 unifb unif in Some u
with UnificationFailure -> None end with
(* Contradiction found. *)
| Some u -> let unif2 = u.final_unifier in
(* should walk back in the tableau
until a non-empty branch is found. *)
let phifinal = merge phiacc q st in
let b = try clause_conflicts phifinal tab unifb unif2 ;
False with Failure -> True end in
match b with
| True -> label T in backtrack tp unifb ;
assert { backtrack_to (unifb at B) (unifb at T) unifb } ;
contradiction_neg_atom base tab unifb unif fresh p t phit tnext clsem q phiacc2 depth goalnum st
| False -> assert { precede (unifb at B) unifb } ;
let phifm = phifinal.model_fo_formula_list_field in
assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif2.unifier m rho in
let rhos0 = semantic_subst u.unifier_factor m rho in
(forall x:int.
eval unif2.unifier x = subst_fo_term (eval unif.unifier x)
(rcompose identity subst_id_symbol) u.unifier_factor &&
rhos x = term_semantic (eval unif2.unifier x) m rho
= term_semantic (eval unif.unifier x) (model_rename identity m) rhos0
= semantic_subst unif.unifier m rhos0 x) &&
extensionalEqual rhos
(semantic_subst unif.unifier m rhos0) &&
subst_fo_formula phi1m subst_id_symbol unif2.unifier =
(*PApp (subst_symbol (Var_symbol p) subst_id_symbol)
(subst_fo_term_list tm subst_id_symbol unif2.unifier) =
PApp (subst_symbol (Var_symbol p) subst_id_symbol)
(subst_fo_term_list t2m subst_id_symbol unif2.unifier) =*)
subst_fo_formula phi0m subst_id_symbol unif2.unifier &&
(formula_semantic phi0m m rhos <->
formula_semantic phi1m m rhos) &&
not(formula_semantic phi0m m rhos /\
formula_semantic phibasem m rhos) &&
(formula_list_conj_semantic basem m rhos ->
tableau_semantic_with tabm True m rhos &&
(formula_list_disj_semantic clsem m rhos) &&
(formula_list_disj_semantic phifm m rhos \/
formula_semantic phi0m m rhos) &&
let b = if formula_list_disj_semantic phifm m rhos
then True
else False in
tableau_semantic_with tabm b m rhos) } ;
let nd = ref depth in
let ct = contract_tableau tab phifinal nd st in
let depth = !nd in
match ct with
| None -> assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif2.unifier m rho in
let b = if formula_list_disj_semantic phifm m rhos
then True
else False in
not(tableau_semantic_with tabm b m rhos) &&
not(formula_list_conj_semantic basem m rhos) } ;
{ contradictory_assignment = unif2.unifier }
(* continue proof search. If fail,
backtrack to find another contradiction. *)
| Some tab2 ->
let tab2m = tab2.model_tableau_field in
assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif2.unifier m rho in
formula_list_conj_semantic basem m rhos ->
let b = if formula_list_disj_semantic phifm m rhos
then True
else False in
tableau_semantic_with tabm b m rhos &&
tableau_semantic_with tab2m True m rhos
} ;
match !l0 with
| Nil -> extend_branch base tab2 unifb unif2 fresh depth goalnum st
| _ -> try extend_branch base tab2 unifb unif2 fresh depth goalnum st
with Failure ->
label F in backtrack tp unifb ;
assert { backtrack_to (unifb at B) (unifb at F) unifb } ;
try conflict t t2 unifb unif
with UnificationFailure -> raise Failure end ;
contradiction_neg_atom base tab unifb unif fresh p t phit tnext clsem q phiacc2 depth goalnum st
end
end
end end
| None -> label N in backtrack tp unifb ;
assert { backtrack_to (unifb at B) (unifb at N) unifb } ;
contradiction_neg_atom base tab unifb unif fresh p t phit tnext clsem q phiacc2 depth goalnum st
end
else (* do not conflict. *)
contradiction_neg_atom base tab unifb unif fresh p t phit tnext clsem q phiacc2 depth goalnum st
end
| NLC_Not _ -> (* do not conflict. *)
contradiction_neg_atom base tab unifb unif fresh p t phit tnext clsem q phiacc2 depth goalnum st
| _ -> absurd (* phi0 is literal. *)
end
end
(* Technically speaking, the entry point of the main loop.
Should be called with a preprocessed set of formula
independent of the interpretation (no free variable),
and a empty unifier (identity substitution). *)
with extend_branch (base:nlimpl_fo_formula_list)
(tab:nlimpl_tableau)
(unifb:subst)
(ghost unif:unifier_subst)
(fresh:int)
(depth:int)
(goalnum:int) (ghost st:'st) : prover_return
requires { fresh >= 0 }
requires { nlimpl_fo_formula_list_ok base }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
base.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_tableau_ok tab }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab.model_tableau_field -> x >= 0 }
requires { unifier_subst_ok unifb unif }
requires { is_procedure_tableau tab.model_tableau_field }
requires { is_simpl_list base.model_fo_formula_list_field }
requires { is_nnf_list base.model_fo_formula_list_field }
requires { no_existential_list base.model_fo_formula_list_field }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
tableau_semantic_with tab.model_tableau_field True m rhos }
ensures { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst result.contradictory_assignment m rho in
not(formula_list_conj_semantic base.model_fo_formula_list_field m rhos) }
ensures { precede (old unifb) unifb /\ correct unifb }
diverges
raises { Failure -> precede (old unifb) unifb /\ correct unifb }
=
let tabm = tab.model_tableau_field in
let basem = base.model_fo_formula_list_field in
match destruct_tableau tab with
| NLC_Root -> if depth = 0
then raise Failure
else let depth = depth - 1 in
select_lemma base base tab unifb unif fresh depth goalnum goalnum st
| NLC_Node tnext phi0 phib -> let tnextm = tnext.model_tableau_field in
let phi0m = phi0.model_fo_formula_field in
let phibm = phib.model_fo_formula_list_field in
assert { tabm = Node tnextm phi0m phibm } ;
assert { forall x:int. is_fo_term_free_var_in_tableau x tnextm ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x phi0m ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x phibm ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { is_atom phi0m } ;
assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic basem m rhos ->
let b1 = if tableau_node True phibm phi0m m rhos
then True
else False in
tableau_semantic_with tnextm b1 m rhos &&
(tableau_semantic_with tnextm True m rhos \/
tableau_semantic_with tnextm False m rhos) } ;
match destruct_fo_formula phi0 with
| NLC_PApp ps t -> let psm = ps.model_symbol_field in
let tm = t.model_fo_term_list_field in
assert { phi0m = PApp psm tm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_term_list x tm ->
is_fo_term_free_var_in_fo_formula x phi0m && x >= 0 } ;
let p = match destruct_symbol ps with
| NLCVar_symbol p -> assert { psm = Var_symbol p } ; p
end in
contradiction_find_atom base tab tnext tnext unifb unif fresh p t phib depth goalnum st
| NLC_Not phi1 -> let phi1m = phi1.model_fo_formula_field in
assert { phi0m = Not phi1m } ;
match destruct_fo_formula phi1 with
| NLC_PApp ps t ->
let psm = ps.model_symbol_field in
let tm = t.model_fo_term_list_field in
assert { phi1m = PApp psm tm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_term_list x tm ->
is_fo_term_free_var_in_fo_formula x phi1m &&
is_fo_term_free_var_in_fo_formula x phi0m && x >= 0 } ;
let p = match destruct_symbol ps with
| NLCVar_symbol p -> assert { psm = Var_symbol p } ; p
end in
contradiction_find_neg_atom base tab tnext tnext unifb unif fresh p t phib depth goalnum st
| _ -> absurd
end
| _ -> absurd
end
end
(* Look for a contradiction inside the current branch. *)
with contradiction_find_atom (base:nlimpl_fo_formula_list)
(tab0 tab1 tab:nlimpl_tableau)
(unifb:subst)
(ghost unif:unifier_subst)
(fresh:int)
(p:int)
(t:nlimpl_fo_term_list)
(philist:nlimpl_fo_formula_list)
(depth:int)
(goalnum:int) (ghost st:'st) : prover_return
requires { fresh >= 0 }
requires { nlimpl_fo_formula_list_ok base }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
base.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_tableau_ok tab0 }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab0.model_tableau_field -> x >= 0 }
requires { nlimpl_tableau_ok tab1 }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab1.model_tableau_field -> x >= 0 }
requires { nlimpl_tableau_ok tab }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab.model_tableau_field -> x >= 0 }
requires { unifier_subst_ok unifb unif }
requires { nlimpl_fo_term_list_ok t }
requires { forall x:int. is_fo_term_free_var_in_fo_term_list x
t.model_fo_term_list_field -> x >= 0 }
requires { nlimpl_fo_formula_list_ok philist }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
philist.model_fo_formula_list_field -> x >= 0 }
requires { is_procedure_tableau tab0.model_tableau_field }
requires { is_procedure_tableau tab.model_tableau_field }
requires { is_simpl_list base.model_fo_formula_list_field }
requires { is_nnf_list base.model_fo_formula_list_field }
requires { no_existential_list base.model_fo_formula_list_field }
requires { is_atom_list philist.model_fo_formula_list_field }
requires { tab0.model_tableau_field =
Node tab1.model_tableau_field
(PApp (Var_symbol p) t.model_fo_term_list_field)
philist.model_fo_formula_list_field }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
tableau_semantic_with tab0.model_tableau_field True m rhos }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
tableau_semantic_with tab.model_tableau_field True m rhos \/
tableau_semantic_with tab.model_tableau_field False m rhos }
requires { forall m:model int 'st,rho:int -> 'st,b:bool.
let rhos = semantic_subst unif.unifier m rho in
(tableau_semantic_with tab.model_tableau_field True m rhos <->
tableau_semantic_with tab.model_tableau_field False m rhos) ->
(tableau_semantic_with tab0.model_tableau_field True m rhos <->
tableau_semantic_with tab0.model_tableau_field False m rhos) }
ensures { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst result.contradictory_assignment m rho in
not(formula_list_conj_semantic base.model_fo_formula_list_field m rhos) }
ensures { precede (old unifb) unifb /\ correct unifb }
diverges
raises { Failure -> precede (old unifb) unifb /\ correct unifb }
=
let tab0m = tab0.model_tableau_field in
let tab1m = tab1.model_tableau_field in
let tabm = tab.model_tableau_field in
let tm = t.model_fo_term_list_field in
let philm = philist.model_fo_formula_list_field in
let basem = base.model_fo_formula_list_field in
let phibasem = PApp (Var_symbol p) tm in
match destruct_tableau tab with
| NLC_Root -> (* No branch contradiction found, try to instantiate
a lemma. *)
if depth = 0
then raise Failure
else select_lemma base base tab0 unifb unif fresh (depth-1) goalnum (-1) st
| NLC_Node tnext phi0 phib ->
let tnextm = tnext.model_tableau_field in
let phi0m = phi0.model_fo_formula_field in
let phibm = phib.model_fo_formula_list_field in
assert { tabm = Node tnextm phi0m phibm } ;
assert { forall x:int. is_fo_term_free_var_in_tableau x tnextm ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x phi0m ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x phibm ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { is_atom phi0m } ;
assert { forall m:model int 'st,rho:int -> 'st.
(tableau_semantic_with tnextm True m rho <->
tableau_semantic_with tnextm False m rho) ->
(tableau_semantic_with tabm True m rho <->
tableau_semantic_with tabm False m rho) } ;
assert { forall m:model int 'st,rho:int -> 'st,b:bool.
tableau_semantic_with tabm b m rho ->
let b1 = if tableau_node b phibm phi0m m rho
then True
else False in
tableau_semantic_with tnextm b1 m rho &&
(tableau_semantic_with tnextm True m rho \/
tableau_semantic_with tnextm False m rho) } ;
match destruct_fo_formula phi0 with
| NLC_PApp _ _ -> contradiction_find_atom base tab0 tab1 tnext unifb unif fresh p t philist depth goalnum st
| NLC_Not phi1 -> let phi1m = phi1.model_fo_formula_field in
assert { phi0m = Not phi1m } ;
match destruct_fo_formula phi1 with
| NLC_PApp p2 t2 ->
let p2m = p2.model_symbol_field in
let t2m = t2.model_fo_term_list_field in
assert { phi1m = PApp p2m t2m } ;
assert { forall x:int. is_fo_term_free_var_in_fo_term_list x t2m ->
is_fo_term_free_var_in_fo_formula x phi1m &&
is_fo_term_free_var_in_fo_formula x phi0m && x >= 0 } ;
let p3 = match destruct_symbol p2 with
| NLCVar_symbol p3 -> p3
end in
assert { p2m = Var_symbol p3 } ;
(* Unification attempt. *)
if p = p3
then (* let-try. *) label B in let tp = stamp unifb in
let l0 = ref Nil in
match try let u = unify_term_list t t2 l0 unifb unif in Some u
with UnificationFailure -> None end with
| Some u -> (* Unifiable. *)
let unif2 = u.final_unifier in
assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif2.unifier m rho in
let rhos0 = semantic_subst u.unifier_factor m rho in
(forall x:int.
eval unif2.unifier x = subst_fo_term (eval unif.unifier x)
(rcompose identity subst_id_symbol) u.unifier_factor &&
rhos x = term_semantic (eval unif2.unifier x) m rho
= term_semantic (eval unif.unifier x) (model_rename identity m) rhos0
= semantic_subst unif.unifier m rhos0 x) &&
extensionalEqual rhos
(semantic_subst unif.unifier m rhos0) &&
subst_fo_formula phi1m subst_id_symbol unif2.unifier =
subst_fo_formula phibasem subst_id_symbol unif2.unifier &&
(formula_semantic phi1m m rhos <->
formula_semantic phibasem m rhos) &&
not(formula_semantic phi0m m rhos /\
formula_semantic phibasem m rhos) &&
(formula_list_conj_semantic basem m rhos ->
tableau_semantic_with tab0m True m rhos &&
(if formula_semantic phibasem m rhos
then (tableau_semantic_with tabm True m rhos <->
tableau_semantic_with tabm False m rhos) &&
tableau_semantic_with tabm False m rhos &&
tableau_semantic_with tab0m False m rhos
else tableau_semantic_with tab0m False m rhos) &&
tableau_semantic_with tab0m False m rhos &&
let b = if formula_list_disj_semantic philm m rhos
then True
else False in
tableau_semantic_with tab1m b m rhos) } ;
let nd = ref depth in
let ct = contract_tableau tab1 philist nd st in
let depth = !nd in
match ct with
| Some tab2 ->
let tab2m = tab2.model_tableau_field in
assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif2.unifier m rho in
formula_list_conj_semantic basem m rhos ->
let b = if formula_list_disj_semantic philm m rhos
then True
else False in
tableau_semantic_with tab1m b m rhos &&
tableau_semantic_with tab2m True m rhos
} ;
match !l0 with
| Nil -> extend_branch base tab2 unifb unif2 fresh depth goalnum st
| _ -> try extend_branch base tab2 unifb unif2 fresh depth goalnum st
with Failure -> label F in
backtrack tp unifb ;
assert { backtrack_to (unifb at B) (unifb at F) unifb } ;
try conflict t t2 unifb unif
with UnificationFailure -> raise Failure end ;
contradiction_find_atom base tab0 tab1 tnext unifb unif fresh p t philist depth goalnum st
end end
| None -> assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif2.unifier m rho in
let b = if formula_list_disj_semantic philm m rhos
then True
else False in
not(tableau_semantic_with tab1m b m rhos) &&
not(formula_list_conj_semantic basem m rhos) } ;
{ contradictory_assignment = unif2.unifier }
end
| None -> label N in backtrack tp unifb ;
assert { backtrack_to (unifb at B) (unifb at N) unifb } ;
contradiction_find_atom base tab0 tab1 tnext unifb unif fresh p t philist depth goalnum st
end
else contradiction_find_atom base tab0 tab1 tnext unifb unif fresh p t philist depth goalnum st
| _ -> absurd (* atomic. *)
end
| _ -> absurd (* atomic. *)
end
end
(* Look for a contradiction inside the current branch,
negated version. *)
with contradiction_find_neg_atom (base:nlimpl_fo_formula_list)
(tab0 tab1 tab:nlimpl_tableau)
(unifb:subst)
(ghost unif:unifier_subst)
(fresh:int)
(p:int)
(t:nlimpl_fo_term_list)
(philist:nlimpl_fo_formula_list)
(depth:int)
(goalnum:int) (ghost st:'st) : prover_return
requires { fresh >= 0 }
requires { nlimpl_fo_formula_list_ok base }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
base.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_tableau_ok tab0 }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab0.model_tableau_field -> x >= 0 }
requires { nlimpl_tableau_ok tab1 }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab1.model_tableau_field -> x >= 0 }
requires { nlimpl_tableau_ok tab }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab.model_tableau_field -> x >= 0 }
requires { unifier_subst_ok unifb unif }
requires { nlimpl_fo_term_list_ok t }
requires { forall x:int. is_fo_term_free_var_in_fo_term_list x
t.model_fo_term_list_field -> x >= 0 }
requires { nlimpl_fo_formula_list_ok philist }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
philist.model_fo_formula_list_field -> x >= 0 }
requires { is_procedure_tableau tab0.model_tableau_field }
requires { is_procedure_tableau tab.model_tableau_field }
requires { is_simpl_list base.model_fo_formula_list_field }
requires { is_nnf_list base.model_fo_formula_list_field }
requires { no_existential_list base.model_fo_formula_list_field }
requires { is_atom_list philist.model_fo_formula_list_field }
requires { tab0.model_tableau_field =
Node tab1.model_tableau_field
(Not (PApp (Var_symbol p) t.model_fo_term_list_field))
philist.model_fo_formula_list_field }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
tableau_semantic_with tab0.model_tableau_field True m rhos }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
tableau_semantic_with tab.model_tableau_field True m rhos \/
tableau_semantic_with tab.model_tableau_field False m rhos }
requires { forall m:model int 'st,rho:int -> 'st,b:bool.
let rhos = semantic_subst unif.unifier m rho in
(tableau_semantic_with tab.model_tableau_field True m rhos <->
tableau_semantic_with tab.model_tableau_field False m rhos) ->
(tableau_semantic_with tab0.model_tableau_field True m rhos <->
tableau_semantic_with tab0.model_tableau_field False m rhos) }
ensures { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst result.contradictory_assignment m rho in
not(formula_list_conj_semantic base.model_fo_formula_list_field m rhos) }
ensures { precede (old unifb) unifb /\ correct unifb }
diverges
raises { Failure -> precede (old unifb) unifb /\ correct unifb }
=
let tab0m = tab0.model_tableau_field in
let tab1m = tab1.model_tableau_field in
let tabm = tab.model_tableau_field in
let tm = t.model_fo_term_list_field in
let philm = philist.model_fo_formula_list_field in
let basem = base.model_fo_formula_list_field in
let phi1m = PApp (Var_symbol p) tm in
let phibasem = Not phi1m in
match destruct_tableau tab with
| NLC_Root -> if depth = 0
then raise Failure
else select_lemma base base tab0 unifb unif fresh (depth-1) goalnum (-1) st
| NLC_Node tnext phi0 phib ->
let tnextm = tnext.model_tableau_field in
let phi0m = phi0.model_fo_formula_field in
let phibm = phib.model_fo_formula_list_field in
assert { tabm = Node tnextm phi0m phibm } ;
assert { forall x:int. is_fo_term_free_var_in_tableau x tnextm ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x phi0m ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x phibm ->
is_fo_term_free_var_in_tableau x tabm && x >= 0 } ;
assert { is_atom phi0m } ;
assert { forall m:model int 'st,rho:int -> 'st.
(tableau_semantic_with tnextm True m rho <->
tableau_semantic_with tnextm False m rho) ->
(tableau_semantic_with tabm True m rho <->
tableau_semantic_with tabm False m rho) } ;
assert { forall m:model int 'st,rho:int -> 'st,b:bool.
tableau_semantic_with tabm b m rho ->
let b1 = if tableau_node b phibm phi0m m rho
then True
else False in
tableau_semantic_with tnextm b1 m rho &&
(tableau_semantic_with tnextm True m rho \/
tableau_semantic_with tnextm False m rho) } ;
match destruct_fo_formula phi0 with
| NLC_Not _ -> contradiction_find_neg_atom base tab0 tab1 tnext unifb unif fresh p t philist depth goalnum st
| NLC_PApp p2 t2 ->
let p2m = p2.model_symbol_field in
let t2m = t2.model_fo_term_list_field in
assert { phi0m = PApp p2m t2m } ;
assert { forall x:int. is_fo_term_free_var_in_fo_term_list x t2m ->
is_fo_term_free_var_in_fo_formula x phi0m && x >= 0 } ;
let p3 = match destruct_symbol p2 with
| NLCVar_symbol p3 -> p3
end in
assert { p2m = Var_symbol p3 } ;
(* Unification attempt. *)
if p = p3
then (* let-try. *) label B in let tp = stamp unifb in
let l0 = ref Nil in
match try let u = unify_term_list t t2 l0 unifb unif in Some u
with UnificationFailure -> None end with
| Some u -> (* Unifiable. *)
let unif2 = u.final_unifier in
assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif2.unifier m rho in
let rhos0 = semantic_subst u.unifier_factor m rho in
(forall x:int.
eval unif2.unifier x = subst_fo_term (eval unif.unifier x)
(rcompose identity subst_id_symbol) u.unifier_factor &&
rhos x = term_semantic (eval unif2.unifier x) m rho
= term_semantic (eval unif.unifier x) (model_rename identity m) rhos0
= semantic_subst unif.unifier m rhos0 x) &&
extensionalEqual rhos
(semantic_subst unif.unifier m rhos0) &&
subst_fo_formula phi1m subst_id_symbol unif2.unifier =
subst_fo_formula phi0m subst_id_symbol unif2.unifier &&
(formula_semantic phi0m m rhos <->
formula_semantic phi1m m rhos) &&
not(formula_semantic phi0m m rhos /\
formula_semantic phibasem m rhos) &&
(formula_list_conj_semantic basem m rhos ->
tableau_semantic_with tab0m True m rhos &&
(if formula_semantic phibasem m rhos
then (tableau_semantic_with tabm True m rhos <->
tableau_semantic_with tabm False m rhos) &&
tableau_semantic_with tabm False m rhos &&
tableau_semantic_with tab0m False m rhos
else tableau_semantic_with tab0m False m rhos) &&
tableau_semantic_with tab0m False m rhos &&
let b = if formula_list_disj_semantic philm m rhos
then True
else False in
tableau_semantic_with tab1m b m rhos) } ;
let nd = ref depth in
let ct = contract_tableau tab1 philist nd st in
let depth = !nd in
match ct with
| Some tab2 ->
let tab2m = tab2.model_tableau_field in
assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif2.unifier m rho in
formula_list_conj_semantic basem m rhos ->
let b = if formula_list_disj_semantic philm m rhos
then True
else False in
tableau_semantic_with tab1m b m rhos &&
tableau_semantic_with tab2m True m rhos
} ;
match !l0 with
| Nil -> extend_branch base tab2 unifb unif2 fresh depth goalnum st
(* no need to backtrack ! *)
| _ -> try
extend_branch base tab2 unifb unif2 fresh depth goalnum st
with Failure -> label F in
backtrack tp unifb ;
assert { backtrack_to (unifb at B) (unifb at F) unifb } ;
try conflict t t2 unifb unif
with UnificationFailure -> raise Failure end;
contradiction_find_neg_atom base tab0 tab1 tnext unifb unif fresh p t philist depth goalnum st
end end
| None -> assert { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif2.unifier m rho in
let b = if formula_list_disj_semantic philm m rhos
then True
else False in
not(tableau_semantic_with tab1m b m rhos) &&
not(formula_list_conj_semantic basem m rhos) } ;
{ contradictory_assignment = unif2.unifier }
end
| None -> label N in backtrack tp unifb ;
assert { backtrack_to (unifb at B) (unifb at N) unifb } ;
contradiction_find_neg_atom base tab0 tab1 tnext unifb unif fresh p t philist depth goalnum st
end
else contradiction_find_neg_atom base tab0 tab1 tnext unifb unif fresh p t philist depth goalnum st
| _ -> absurd (* atomic. *)
end
end
(* Iterate through every lemma of the base formula set. *)
with select_lemma (base:nlimpl_fo_formula_list) (basecursor:nlimpl_fo_formula_list)
(tab:nlimpl_tableau)
(unifb:subst)
(ghost unif:unifier_subst)
(fresh:int)
(depth:int)
(goalnum:int)
(number:int) (ghost st:'st) : prover_return
requires { fresh >= 0 }
requires { nlimpl_fo_formula_list_ok base }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
base.model_fo_formula_list_field -> x >= 0 }
requires { nlimpl_tableau_ok tab }
requires { forall x:int. is_fo_term_free_var_in_tableau x
tab.model_tableau_field -> x >= 0 }
requires { unifier_subst_ok unifb unif }
requires { nlimpl_fo_formula_list_ok basecursor }
requires { forall x:int. is_fo_term_free_var_in_fo_formula_list x
basecursor.model_fo_formula_list_field -> x >= 0 }
requires { is_procedure_tableau tab.model_tableau_field }
requires { is_simpl_list base.model_fo_formula_list_field }
requires { is_nnf_list base.model_fo_formula_list_field }
requires { no_existential_list base.model_fo_formula_list_field }
requires { is_simpl_list basecursor.model_fo_formula_list_field }
requires { is_nnf_list basecursor.model_fo_formula_list_field }
requires { no_existential_list basecursor.model_fo_formula_list_field }
requires { forall m:model int 'st,rho:int -> 'st.
formula_list_conj_semantic base.model_fo_formula_list_field m rho ->
formula_list_conj_semantic basecursor.model_fo_formula_list_field m rho }
requires { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst unif.unifier m rho in
formula_list_conj_semantic base.model_fo_formula_list_field m rhos ->
tableau_semantic_with tab.model_tableau_field True m rhos }
ensures { forall m:model int 'st,rho:int -> 'st.
let rhos = semantic_subst result.contradictory_assignment m rho in
not(formula_list_conj_semantic base.model_fo_formula_list_field m rhos) }
ensures { precede (old unifb) unifb /\ correct unifb }
diverges
raises { Failure -> precede (old unifb) unifb /\ correct unifb }
=
if number = 0
then raise Failure ;
let bcm = basecursor.model_fo_formula_list_field in
match destruct_fo_formula_list basecursor with
| NLC_FOFNil -> raise Failure
| NLC_FOFCons x q -> let qm = q.model_fo_formula_list_field in
let xm = x.model_fo_formula_field in
assert { bcm = FOFCons xm qm } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula x xm ->
is_fo_term_free_var_in_fo_formula_list x bcm && x >= 0 } ;
assert { forall x:int. is_fo_term_free_var_in_fo_formula_list x qm ->
is_fo_term_free_var_in_fo_formula_list x bcm && x >= 0 } ;
let fonil = construct_fo_formula_list NLC_FOFNil in
assert { fonil.model_fo_formula_list_field = FOFNil } ;
label B in let tp = stamp unifb in
try decompose base tab unifb unif fresh x fonil fonil depth goalnum st
with Failure -> label F in backtrack tp unifb ;
assert { backtrack_to (unifb at B) (unifb at F) unifb } ;
select_lemma base q tab unifb unif fresh depth goalnum (number-1) st end
end
end