Theory Watched_Literals_Algorithm
theory Watched_Literals_Algorithm
imports
More_Sepref.WB_More_Refinement
Watched_Literals_Transition_System
Watched_Literals_All_Literals
begin
chapter ‹First Refinement: Deterministic Rule Application›
section ‹Unit Propagation Loops›
definition set_conflict_pre :: ‹'v twl_cls ⇒ 'v twl_st ⇒ bool› where
‹set_conflict_pre C S ⟷
(∃L C'. let S' = (set_clauses_to_update (add_mset (L, C') (clauses_to_update S)) S) in
twl_struct_invs S' ∧ twl_stgy_invs S' ∧ get_trail S' ⊨as CNot (clause C))›
definition set_conflicting :: ‹'v twl_cls ⇒ 'v twl_st ⇒ 'v twl_st› where
‹set_conflicting = (λC (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q).
(M, N, U, Some (clause C), NE, UE, NS, US, N0, U0, {#}, {#}))›
definition mop_set_conflicting :: ‹'v twl_cls ⇒ 'v twl_st ⇒ 'v twl_st nres› where
‹mop_set_conflicting = (λC S. do {
ASSERT (set_conflict_pre C S);
RETURN (set_conflicting C S)})›
definition propagate_lit_pre :: ‹'v literal ⇒ 'v twl_cls ⇒ 'v twl_st ⇒ bool› where
‹propagate_lit_pre L' C S ⟷
(∃L C'. let S' = (set_clauses_to_update (add_mset (L, C') (clauses_to_update S)) S) in
twl_struct_invs S' ∧ twl_stgy_invs S' ∧ undefined_lit (get_trail S) L' ∧
L' ∈# all_lits_of_mm (clauses (get_clauses S) + unit_clss S))›
definition propagate_lit :: ‹'v literal ⇒ 'v twl_cls ⇒ 'v twl_st ⇒ 'v twl_st› where
‹propagate_lit = (λL' C (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q). do {
(Propagated L' (clause C) # M, N, U, D, NE, UE, NS, US, N0, U0, WS, add_mset (-L') Q)})›
definition mop_propagate_lit :: ‹'v literal ⇒ 'v twl_cls ⇒ 'v twl_st ⇒ 'v twl_st nres› where
‹mop_propagate_lit = (λL' C S. do {
ASSERT(propagate_lit_pre L' C S);
RETURN (propagate_lit L' C S)})›
definition update_clauseS_pre :: ‹'v literal ⇒ 'v twl_cls ⇒ 'v twl_st ⇒ bool› where
‹update_clauseS_pre L C S ⟷
(let S = (set_clauses_to_update (add_mset (L, C) (clauses_to_update S)) S) in
L ∈# watched C ∧ C ∈# get_clauses S ∧ twl_struct_invs S ∧ twl_stgy_invs S)›
definition update_clauseS :: ‹'v literal ⇒ 'v twl_cls ⇒ 'v twl_st ⇒ 'v twl_st nres› where
‹update_clauseS = (λL C (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q). do {
ASSERT(update_clauseS_pre L C (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q));
K ← SPEC (λL. L ∈# unwatched C ∧ -L ∉ lits_of_l M);
if K ∈ lits_of_l M
then RETURN (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q)
else do {
(N', U') ← SPEC (λ(N', U'). update_clauses (N, U) C L K (N', U'));
RETURN (M, N', U', D, NE, UE, NS, US, N0, U0, WS, Q)
}
})›
definition all_lits_of_st :: ‹'v twl_st ⇒ 'v literal multiset› where
‹all_lits_of_st S ≡ all_lits_of_mm (clauses (get_clauses S) + unit_clss S + subsumed_clauses S +
get_all_clauses0 S)›
definition mop_lit_is_pos where
‹mop_lit_is_pos L S = do {
ASSERT(L ∈# all_lits_of_st S ∧
no_dup (get_trail S));
RETURN (L ∈ lits_of_l (get_trail S))
}›
definition unit_propagation_inner_loop_body :: ‹'v literal ⇒ 'v twl_cls ⇒
'v twl_st ⇒ 'v twl_st nres› where
‹unit_propagation_inner_loop_body = (λL C S. do {
do {
bL' ← SPEC (λK. K ∈# clause C);
val_bL' ← mop_lit_is_pos bL' S;
if val_bL'
then RETURN S
else do {
L' ← SPEC (λK. K ∈# watched C - {#L#});
ASSERT (watched C = {#L, L'#});
val_L' ← mop_lit_is_pos L' S;
if val_L'
then RETURN S
else
if ∀L ∈# unwatched C. -L ∈ lits_of_l (get_trail S)
then
if -L' ∈ lits_of_l (get_trail S)
then do {mop_set_conflicting C S}
else do {mop_propagate_lit L' C S}
else do {
update_clauseS L C S
}
}
}
})
›
definition unit_propagation_inner_loop :: ‹'v twl_st ⇒ 'v twl_st nres› where
‹unit_propagation_inner_loop S⇩0 = do {
n ← SPEC(λ_::nat. True);
(S, _) ← WHILE⇩T⇗λ(S, n). twl_struct_invs S ∧ twl_stgy_invs S ∧ cdcl_twl_cp⇧*⇧* S⇩0 S ∧
(clauses_to_update S ≠ {#} ∨ n > 0 ⟶ get_conflict S = None)⇖
(λ(S, n). clauses_to_update S ≠ {#} ∨ n > 0)
(λ(S, n). do {
b ← SPEC(λb. (b ⟶ n > 0) ∧ (¬b ⟶ clauses_to_update S ≠ {#}));
if ¬b then do {
ASSERT(clauses_to_update S ≠ {#});
(L, C) ← SPEC (λC. C ∈# clauses_to_update S);
let S' = set_clauses_to_update (clauses_to_update S - {#(L, C)#}) S;
T ← unit_propagation_inner_loop_body L C S';
RETURN (T, if get_conflict T = None then n else 0)
} else do {
RETURN (S, n - 1)
}
})
(S⇩0, n);
RETURN S
}
›
lemma unit_propagation_inner_loop_body:
fixes S :: ‹'v twl_st›
assumes
‹clauses_to_update S ≠ {#}› and
x_WS: ‹(L, C) ∈# clauses_to_update S› and
inv: ‹twl_struct_invs S› and
inv_s: ‹twl_stgy_invs S› and
confl: ‹get_conflict S = None›
shows
‹unit_propagation_inner_loop_body L C
(set_clauses_to_update (remove1_mset (L, C) (clauses_to_update S)) S)
≤ (SPEC (λT'. twl_struct_invs T' ∧ twl_stgy_invs T' ∧ cdcl_twl_cp⇧*⇧* S T' ∧
(T', S) ∈ measure (size ∘ clauses_to_update)))› (is ?spec is ‹_ ≤ ?R›) and
‹nofail (unit_propagation_inner_loop_body L C
(set_clauses_to_update (remove1_mset (L, C) (clauses_to_update S)) S))› (is ?fail)
proof -
obtain M N U D NE UE NS US N0 U0 WS Q where
S: ‹S = (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q)›
by (cases S) auto
have ‹C ∈# N + U› and struct: ‹struct_wf_twl_cls C› and L_C: ‹L ∈# watched C› and
uL_M: ‹-L ∈ lits_of_l M›
using inv multi_member_split[OF x_WS]
unfolding twl_struct_invs_def twl_st_inv.simps S
by force+
have uL: ‹- L ∈ lits_of_l M› and
all_struct: ‹cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv (state⇩W_of S)›
using inv x_WS unfolding twl_struct_invs_def S pcdcl_all_struct_invs_def by auto
have ‹cdcl⇩W_restart_mset.no_strange_atm (state⇩W_of S)› and
‹cdcl⇩W_restart_mset.cdcl⇩W_M_level_inv (state⇩W_of S)›
using all_struct unfolding cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv_def by fast+
then have alien_L: ‹L ∈# all_lits_of_mm (clauses N + clauses U + (NE + NS + UE + US + N0 + U0))› and
n_d: ‹no_dup M›
using uL unfolding cdcl⇩W_restart_mset.no_strange_atm_def
cdcl⇩W_restart_mset.cdcl⇩W_M_level_inv_def
by (auto simp: S cdcl⇩W_restart_mset_state in_all_lits_of_mm_ain_atms_of_iff)
have ‹C ∈# N + U ⟹ b ∈# clause C ⟹
b ∈# all_lits_of_mm (clauses N + clauses U + (NE + NS + UE + US + N0 + U0))› for b C
by (auto dest!: multi_member_split simp: all_lits_of_mm_add_mset all_lits_of_m_add_mset)
note [[goals_limit=15]]
show ?spec
using assms unfolding unit_propagation_inner_loop_body_def update_clause.simps
mop_lit_is_pos_def nres_monad3
proof (refine_vcg; (unfold prod.inject clauses_to_update.simps set_clauses_to_update.simps
ball_simps)?; clarify?; (unfold triv_forall_equality)?)
fix L' :: ‹'v literal›
assume
‹clauses_to_update S ≠ {#}› and
twl_inv: ‹twl_struct_invs S›
have ‹C ∈# N + U› and struct: ‹struct_wf_twl_cls C› and L_C: ‹L ∈# watched C›
using twl_inv x_WS unfolding twl_struct_invs_def twl_st_inv.simps S by (auto; fail)+
define WS' where ‹WS' = WS - {#(L, C)#}›
have WS_WS': ‹WS = add_mset (L, C) WS'›
using x_WS unfolding WS'_def S by auto
have D: ‹D = None›
using confl S by auto
let ?S' = ‹(M, N, U, None, NE, UE, NS, US, N0, U0, add_mset (L, C) WS', Q)›
let ?T = ‹(set_clauses_to_update (remove1_mset (L, C) (clauses_to_update S)) S)›
let ?T' = ‹(M, N, U, None, NE, UE, NS, US, N0, U0, WS', Q)›
{
fix K'
assume
K': ‹K' ∈# clause C›
show ‹K' ∈# all_lits_of_st (set_clauses_to_update
(remove1_mset (L, C) (clauses_to_update S)) S)›
using K' ‹C ∈# N + U› by (auto dest!: multi_member_split
simp: all_lits_of_mm_add_mset all_lits_of_m_add_mset clauses_def S all_lits_of_st_def)
show ‹no_dup (get_trail
(set_clauses_to_update
(remove1_mset (L, C)
(clauses_to_update S))
S))›
using n_d by (auto simp: S)
assume
L': ‹K' ∈ lits_of_l (get_trail ?T)›
have ‹cdcl_twl_cp ?S' ?T'›
by (rule cdcl_twl_cp.delete_from_working) (use L' K' S in simp_all)
then have cdcl: ‹cdcl_twl_cp S ?T›
using L' D by (simp add: S WS_WS')
show ‹twl_struct_invs ?T›
using cdcl inv D unfolding S WS_WS' by (force intro: cdcl_twl_cp_twl_struct_invs)
show ‹twl_stgy_invs ?T›
using cdcl inv_s inv D unfolding S WS_WS' by (force intro: cdcl_twl_cp_twl_stgy_invs)
show ‹cdcl_twl_cp⇧*⇧* S ?T›
using D WS_WS' cdcl by auto
show ‹(?T, S) ∈ measure (size ∘ clauses_to_update)›
by (simp add: WS'_def[symmetric] WS_WS' S)
}
assume L': ‹L' ∈# remove1_mset L (watched C)›
show watched: ‹watched C = {#L, L'#}›
by (cases C) (use struct L_C L' in ‹auto simp: size_2_iff›)
then have L_C': ‹L ∈# clause C› and L'_C': ‹L' ∈# clause C›
by (cases C; auto; fail)+
show ‹L' ∈# all_lits_of_st (set_clauses_to_update
(remove1_mset (L, C) (clauses_to_update S)) S)›
using L'_C' ‹C ∈# N + U› by (auto dest!: multi_member_split
simp: all_lits_of_mm_add_mset all_lits_of_m_add_mset clauses_def S all_lits_of_st_def)
{
assume L': ‹L' ∈ lits_of_l (get_trail ?T)›
have ‹cdcl_twl_cp ?S' ?T'›
by (rule cdcl_twl_cp.delete_from_working) (use L' L'_C' watched S in simp_all)
then have cdcl: ‹cdcl_twl_cp S ?T›
using L' watched D by (simp add: S WS_WS')
show ‹twl_struct_invs ?T›
using cdcl inv D unfolding S WS_WS' by (force intro: cdcl_twl_cp_twl_struct_invs)
show ‹twl_stgy_invs ?T›
using cdcl inv_s inv D unfolding S WS_WS' by (force intro: cdcl_twl_cp_twl_stgy_invs)
show ‹cdcl_twl_cp⇧*⇧* S ?T›
using D WS_WS' cdcl by auto
show ‹(?T, S) ∈ measure (size ∘ clauses_to_update)›
by (simp add: WS'_def[symmetric] WS_WS' S)
}
let ?M = ‹get_trail ?T›
assume L': ‹L' ∉ lits_of_l ?M›
{
{
assume unwatched: ‹∀L∈#unwatched C. - L ∈ lits_of_l ?M›
{
let ?T' = ‹(M, N, U, Some (clause C), NE, UE, NS, US, N0, U0, {#}, {#})›
let ?T = ‹set_conflicting C (set_clauses_to_update (remove1_mset (L, C) (clauses_to_update S)) S)›
assume uL': ‹-L' ∈ lits_of_l ?M›
have cdcl: ‹cdcl_twl_cp ?S' ?T'›
by (rule cdcl_twl_cp.conflict) (use uL' L' watched unwatched S in simp_all)
then have cdcl: ‹cdcl_twl_cp S ?T›
using uL' L' watched unwatched by (simp add: set_conflicting_def WS_WS' S D)
have ‹twl_struct_invs ?T›
using cdcl inv D unfolding WS_WS'
by (force intro: cdcl_twl_cp_twl_struct_invs)
moreover have ‹twl_stgy_invs ?T›
using cdcl inv inv_s D unfolding WS_WS'
by (force intro: cdcl_twl_cp_twl_stgy_invs)
moreover have ‹cdcl_twl_cp⇧*⇧* S ?T›
using D WS_WS' cdcl S by auto
moreover have ‹(?T, S) ∈ measure (size ∘ clauses_to_update)›
by (simp add: S WS'_def[symmetric] WS_WS' set_conflicting_def)
moreover have ‹get_trail (set_clauses_to_update (remove1_mset (L, C) (clauses_to_update S))
S) ⊨as CNot (clause C)›
using unwatched uL' watched L' uL_M by (cases C; auto simp: true_annots_true_cls_def_iff_negation_in_model S)
ultimately show ‹mop_set_conflicting C (set_clauses_to_update (remove1_mset (L, C) (clauses_to_update S)) S)
≤ ?R›
using assms
by (auto simp: mop_set_conflicting_def set_conflict_pre_def Let_def S
intro!: ASSERT_leI exI[of _ L] exI[of _ C])
}
{
let ?S = ‹(M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q)›
let ?T' = ‹(Propagated L' (clause C) # M, N, U, None, NE, UE, NS, US, N0, U0, WS', add_mset (- L') Q)›
let ?S' = ‹(M, N, U, None, NE, UE, NS, US, N0, U0, add_mset (L, C) WS', Q)›
let ?T = ‹propagate_lit L' C (set_clauses_to_update (remove1_mset (L, C) (clauses_to_update S)) S)›
assume uL': ‹- L' ∉ lits_of_l ?M›
have undef: ‹undefined_lit M L'›
using uL' L' by (auto simp: S defined_lit_map lits_of_def atm_of_eq_atm_of)
have cdcl: ‹cdcl_twl_cp ?S' ?T'›
by (rule cdcl_twl_cp.propagate) (use uL' L' undef watched unwatched D S in simp_all)
then have cdcl: ‹cdcl_twl_cp S ?T›
using uL' L' undef watched unwatched D S WS_WS' by (simp add: propagate_lit_def)
moreover have ‹twl_struct_invs ?T›
using cdcl inv D unfolding S WS_WS' by (force intro: cdcl_twl_cp_twl_struct_invs)
moreover have ‹cdcl_twl_cp⇧*⇧* S ?T›
using cdcl D WS_WS' by force
moreover have ‹twl_stgy_invs ?T›
using cdcl inv inv_s D unfolding S WS_WS' by (force intro: cdcl_twl_cp_twl_stgy_invs)
moreover have ‹L' ∈# all_lits_of_mm (clauses N + clauses U + (NE + UE))›
using L'_C' ‹C ∈# N + U› by (auto simp: all_lits_of_mm_add_mset all_lits_of_m_add_mset
dest!: multi_member_split)
ultimately show ‹mop_propagate_lit L' C (set_clauses_to_update (remove1_mset (L, C) (clauses_to_update S)) S)
≤ ?R›
using x_WS inv inv_s undef
by (auto simp: mop_propagate_lit_def propagate_lit_pre_def propagate_lit_def Let_def S
intro!: ASSERT_leI exI[of _ L] exI[of _ C] dest: multi_member_split)
}
}
fix La
{
let ?S = ‹(M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q)›
let ?S' = ‹(M, N, U, None, NE, UE, NS, US, N0, U0, add_mset (L, C) WS', Q)›
let ?T = ‹set_clauses_to_update (remove1_mset (L, C) (clauses_to_update S)) S›
fix K M' N' U' D' WS'' NE' UE' Q' N'' U''
have ‹update_clauseS L C (set_clauses_to_update (remove1_mset (L, C) (clauses_to_update S)) S)
≤ SPEC (λS'. twl_struct_invs S' ∧ twl_stgy_invs S' ∧ cdcl_twl_cp⇧*⇧* S S' ∧
(S', S) ∈ measure (size ∘ clauses_to_update))› (is ?upd)
apply (rewrite at ‹set_clauses_to_update _ ⌑› S)
apply (rewrite at ‹clauses_to_update ⌑› S)
unfolding update_clauseS_def clauses_to_update.simps set_clauses_to_update.simps
apply clarify
proof refine_vcg
fix x xa a b
show ‹update_clauseS_pre L C (M, N, U, D, NE, UE, NS, US, N0, U0, remove1_mset (L, C) WS, Q)›
using assms L_C ‹C ∈# N + U› unfolding update_clauseS_pre_def S Let_def
by auto
assume K: ‹x ∈# unwatched C ∧ - x ∉ lits_of_l M›
have uL: ‹- L ∈ lits_of_l M›
using inv unfolding twl_struct_invs_def S WS_WS' by auto
{
let ?T = ‹(M, N, U, D, NE, UE, NS, US, N0, U0, remove1_mset (L, C) WS, Q)›
let ?T' = ‹(M, N, U, None, NE, UE, NS, US, N0, U0, WS', Q)›
assume ‹x ∈ lits_of_l M›
have uL: ‹- L ∈ lits_of_l M›
using inv unfolding twl_struct_invs_def S WS_WS' by auto
have ‹L ∈# clause C› ‹x ∈# clause C›
using watched K by (cases C; simp; fail)+
have ‹cdcl_twl_cp ?S' ?T'›
by (rule cdcl_twl_cp.delete_from_working[OF ‹x ∈# clause C› ‹x ∈ lits_of_l M›])
then have cdcl: ‹cdcl_twl_cp S ?T›
by (auto simp: S D WS_WS')
show ‹twl_struct_invs ?T›
using cdcl inv D unfolding S WS_WS' by (force intro: cdcl_twl_cp_twl_struct_invs)
show ‹twl_stgy_invs ?T›
using cdcl inv inv_s D unfolding S WS_WS' by (force intro: cdcl_twl_cp_twl_stgy_invs)
show ‹cdcl_twl_cp⇧*⇧* S ?T›
using D WS_WS' cdcl by auto
show ‹(?T, S) ∈ measure (size ∘ clauses_to_update)›
by (simp add: WS'_def[symmetric] WS_WS' S)
}
assume
update: ‹case xa of (N', U') ⇒ update_clauses (N, U) C L x (N', U')› and
[simp]: ‹xa = (a, b)›
let ?T' = ‹(M, a, b, None, NE, UE, NS, US, N0, U0, WS', Q)›
let ?T = ‹(M, a, b, D, NE, UE, NS, US, N0, U0, remove1_mset (L, C) WS, Q)›
have ‹cdcl_twl_cp ?S' ?T'›
by (rule cdcl_twl_cp.update_clause)
(use uL L' K update watched S in ‹simp_all add: true_annot_iff_decided_or_true_lit›)
then have cdcl: ‹cdcl_twl_cp S ?T›
by (auto simp: S D WS_WS')
show ‹twl_struct_invs ?T›
using cdcl inv D unfolding S WS_WS' by (force intro: cdcl_twl_cp_twl_struct_invs)
have uL: ‹- L ∈ lits_of_l M›
using inv unfolding twl_struct_invs_def S WS_WS' by auto
show ‹twl_stgy_invs ?T›
using cdcl inv inv_s D unfolding S WS_WS' by (force intro: cdcl_twl_cp_twl_stgy_invs)
show ‹cdcl_twl_cp⇧*⇧* S ?T›
using D WS_WS' cdcl by auto
show ‹(?T, S) ∈ measure (size ∘ clauses_to_update)›
by (simp add: WS'_def[symmetric] WS_WS' S)
qed
moreover assume ‹¬?upd›
ultimately show ‹- La ∈
lits_of_l (get_trail (set_clauses_to_update (remove1_mset (L, C) (clauses_to_update S)) S))›
by fast
}
}
qed
from SPEC_nofail[OF this] show ?fail .
qed
declare unit_propagation_inner_loop_body(1)[THEN order_trans, refine_vcg]
lemma unit_propagation_inner_loop:
assumes ‹twl_struct_invs S› and inv: ‹twl_stgy_invs S› and ‹get_conflict S = None›
shows ‹unit_propagation_inner_loop S ≤ SPEC (λS'. twl_struct_invs S' ∧ twl_stgy_invs S' ∧
cdcl_twl_cp⇧*⇧* S S' ∧ clauses_to_update S' = {#})›
unfolding unit_propagation_inner_loop_def
apply (refine_vcg WHILEIT_rule[where R = ‹measure (λ(S, n). (size o clauses_to_update) S + n)›])
subgoal by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by (auto simp add: twl_struct_invs_def)
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by auto
done
declare unit_propagation_inner_loop[THEN order_trans, refine_vcg]
definition pop_literal_to_update_pre where
‹pop_literal_to_update_pre S ⟷
twl_struct_invs S ∧ twl_stgy_invs S ∧ clauses_to_update S = {#} ∧
literals_to_update S ≠ {#}›
definition mop_pop_literal_to_update :: ‹'v twl_st ⇒ ('v literal × 'v twl_st) nres› where
‹mop_pop_literal_to_update S = do {
ASSERT(pop_literal_to_update_pre S);
L ← SPEC (λL. L ∈# literals_to_update S);
let S' = set_clauses_to_update {#(L, C)|C ∈# get_clauses S. L ∈# watched C#}
(set_literals_to_update (literals_to_update S - {#L#}) S);
RETURN (L, S')
}›
definition unit_propagation_outer_loop :: ‹'v twl_st ⇒ 'v twl_st nres› where
‹unit_propagation_outer_loop S⇩0 =
WHILE⇩T⇗λS. twl_struct_invs S ∧ twl_stgy_invs S ∧ cdcl_twl_cp⇧*⇧* S⇩0 S ∧ clauses_to_update S = {#}⇖
(λS. literals_to_update S ≠ {#})
(λS. do {
(L, S') ← mop_pop_literal_to_update S;
ASSERT(cdcl_twl_cp S S');
unit_propagation_inner_loop S'
})
S⇩0
›
abbreviation unit_propagation_outer_loop_spec where
‹unit_propagation_outer_loop_spec S S' ≡ twl_struct_invs S' ∧ cdcl_twl_cp⇧*⇧* S S' ∧
literals_to_update S' = {#} ∧ (∀S'a. ¬ cdcl_twl_cp S' S'a) ∧ twl_stgy_invs S'›
lemma unit_propagation_outer_loop:
assumes ‹twl_struct_invs S› and ‹clauses_to_update S = {#}› and confl: ‹get_conflict S = None› and
‹twl_stgy_invs S›
shows ‹unit_propagation_outer_loop S ≤ SPEC (λS'. twl_struct_invs S' ∧ cdcl_twl_cp⇧*⇧* S S' ∧
literals_to_update S' = {#} ∧ no_step cdcl_twl_cp S' ∧ twl_stgy_invs S')›
proof -
have assert_twl_cp: ‹cdcl_twl_cp T T'› (is ?twl) and
assert_twl_struct_invs:
‹twl_struct_invs T'›
(is ‹twl_struct_invs ?T'›) and
assert_stgy_invs:
‹twl_stgy_invs T'› (is ?stgy)
if
p: ‹literals_to_update T ≠ {#}› and
L_T: ‹L ∈# literals_to_update T› and
invs: ‹twl_struct_invs T ∧ twl_stgy_invs T ∧cdcl_twl_cp⇧*⇧* S T ∧ clauses_to_update T = {#}› and
eq: ‹(L, set_clauses_to_update (Pair L `# {#C ∈# get_clauses T. L ∈# watched C#})
(set_literals_to_update (remove1_mset L (literals_to_update T)) T)) =
(L', T')›
for L T L' T'
proof -
from that have
p: ‹literals_to_update T ≠ {#}› and
L_T: ‹L ∈# literals_to_update T› and
struct_invs: ‹twl_struct_invs T› and
‹cdcl_twl_cp⇧*⇧* S T› and
w_q: ‹clauses_to_update T = {#}› and
eq[simp]: ‹L' = L› ‹T' = (set_clauses_to_update (Pair L `# {#Ca ∈# get_clauses T. L ∈# watched Ca#})
(set_literals_to_update (remove1_mset L (literals_to_update T)) T))›
by fast+
have ‹get_conflict T = None›
using w_q p invs unfolding twl_struct_invs_def by auto
then obtain M N U NE UE NS US N0 U0 Q where
T: ‹T = (M, N, U, None, NE, UE, NS, US, N0, U0, {#}, Q)›
using w_q p by (cases T) auto
define Q' where ‹Q' = remove1_mset L Q›
have Q: ‹Q = add_mset L Q'›
using L_T unfolding Q'_def T by auto
show twl: ?twl
unfolding eq T set_clauses_to_update.simps set_literals_to_update.simps literals_to_update.simps Q'_def[symmetric]
unfolding Q get_clauses.simps
by (rule cdcl_twl_cp.pop)
then show ‹twl_struct_invs ?T'›
using cdcl_twl_cp_twl_struct_invs struct_invs by blast
then show ?stgy
using twl cdcl_twl_cp_twl_stgy_invs[OF twl] invs by blast
qed
show ?thesis
unfolding unit_propagation_outer_loop_def mop_pop_literal_to_update_def nres_monad3
apply (refine_vcg WHILEIT_rule[where R = ‹{(T, S). twl_struct_invs S ∧ cdcl_twl_cp⇧+⇧+ S T}›])
apply ((simp_all add: assms tranclp_wf_cdcl_twl_cp; fail)+)[6]
subgoal unfolding pop_literal_to_update_pre_def by blast
subgoal by (rule assert_twl_cp)
subgoal by (rule assert_twl_struct_invs)
subgoal by (rule assert_stgy_invs)
subgoal for S L
by (cases S)
(auto simp: twl_st twl_struct_invs_def)
subgoal by (simp; fail)
subgoal by auto
subgoal by auto
subgoal by simp
subgoal by auto
subgoal
by simp
subgoal by simp
subgoal by auto
subgoal by (auto simp: cdcl_twl_cp.simps)
subgoal by simp
done
qed
declare unit_propagation_outer_loop[THEN order_trans, refine_vcg]
section ‹Other Rules›
subsection ‹Decide›
definition find_unassigned_lit :: ‹'v twl_st ⇒ 'v literal option nres› where
‹find_unassigned_lit = (λS.
SPEC (λL.
(L ≠ None ⟶ undefined_lit (get_trail S) (the L) ∧
(the L) ∈# all_lits_of_st S) ∧
(L = None ⟶ (∄L. undefined_lit (get_trail S) L ∧
L ∈# all_lits_of_st S))))›
definition propagate_dec where
‹propagate_dec = (λL (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q).
(Decided L # M, N, U, D, NE, UE, NS, US, N0, U0, WS, {#-L#}))›
definition decide_or_skip_pre :: ‹'v twl_st ⇒ bool› where
‹decide_or_skip_pre S ⟷
clauses_to_update S = {#} ∧ literals_to_update S = {#} ∧ get_conflict S = None ∧
twl_struct_invs S ∧ twl_stgy_invs S›
definition decide_or_skip :: ‹'v twl_st ⇒ (bool × 'v twl_st) nres› where
‹decide_or_skip S = do {
ASSERT(decide_or_skip_pre S);
L ← find_unassigned_lit S;
case L of
None ⇒ RETURN (True, S)
| Some L ⇒ RETURN (False, propagate_dec L S)
}
›
lemma decide_or_skip_spec:
assumes ‹clauses_to_update S = {#}› and ‹literals_to_update S = {#}› and ‹get_conflict S = None› and
twl: ‹twl_struct_invs S› and twl_s: ‹twl_stgy_invs S›
shows ‹decide_or_skip S ≤ SPEC(λ(brk, T). cdcl_twl_o⇧*⇧* S T ∧
get_conflict T = None ∧
no_step cdcl_twl_o T ∧ (brk ⟶ no_step cdcl_twl_stgy T) ∧ twl_struct_invs T ∧
twl_stgy_invs T ∧ clauses_to_update T = {#} ∧
(¬brk ⟶ literals_to_update T ≠ {#}) ∧
(¬no_step cdcl_twl_o S ⟶ cdcl_twl_o⇧+⇧+ S T))›
proof -
obtain M N U NE UE NS US N0 U0 where S: ‹S = (M, N, U, None, NE, UE, NS, US, N0, U0, {#}, {#})›
using assms by (cases S) auto
have atm_N_U:
‹atm_of L ∈ atms_of_ms (clause ` set_mset U) ⟹
atm_of L ∈ atms_of_mm (clauses N + NE + NS + N0)›
‹atms_of_mm (get_all_clss (M, N, U, None, NE, UE, NS, US, N0, U0, {#}, {#})) = atms_of_mm (clauses N + NE + NS + N0)›
for L
proof -
have ‹cdcl⇩W_restart_mset.no_strange_atm (state⇩W_of S)› and unit: ‹entailed_clss_inv (pstate⇩W_of S)›
using twl unfolding twl_struct_invs_def cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv_def
pcdcl_all_struct_invs_def
by auto
then show
‹atm_of L ∈ atms_of_ms (clause ` set_mset U) ⟹ atm_of L ∈ atms_of_mm (clauses N + NE + NS + N0)›
‹atms_of_mm (get_all_clss (M, N, U, None, NE, UE, NS, US, N0, U0, {#}, {#})) = atms_of_mm (clauses N + NE + NS + N0)›
by (auto simp: cdcl⇩W_restart_mset.no_strange_atm_def S cdcl⇩W_restart_mset_state image_Un)
qed
{
fix L
assume undef: ‹undefined_lit M L› and L: ‹atm_of L ∈ atms_of_mm (clauses N + NE + NS + N0)›
let ?T = ‹(Decided L # M, N, U, None, NE, UE, NS, US, N0, U0, {#}, {#- L#})›
have o: ‹cdcl_twl_o (M, N, U, None, NE, UE, NS, US, N0, U0, {#}, {#}) ?T›
by (rule cdcl_twl_o.decide) (use undef L in auto)
have twl': ‹twl_struct_invs ?T›
using S cdcl_twl_o_twl_struct_invs o twl by blast
have twl_s': ‹twl_stgy_invs ?T›
using S cdcl_twl_o_twl_stgy_invs o twl twl_s by blast
note o twl' twl_s'
} note H = this
have H'[unfolded S, simp]:
‹L ∈# all_lits_of_st S ⟷ atm_of L ∈ atms_of_mm (clauses N + NE + NS + N0)› for L
using atm_N_U(2)
by (auto simp: S all_lits_of_st_def all_lits_def in_all_lits_of_mm_ain_atms_of_iff)
show ?thesis
using assms unfolding S find_unassigned_lit_def propagate_dec_def decide_or_skip_def
atm_N_U
apply (refine_vcg)
subgoal unfolding decide_or_skip_pre_def by blast
subgoal by fast
subgoal by blast
subgoal by (force simp: H elim!: cdcl_twl_oE cdcl_twl_stgyE cdcl_twl_cpE dest!: atm_N_U(1))
subgoal by (force elim!: cdcl_twl_oE cdcl_twl_stgyE cdcl_twl_cpE)
subgoal by fast
subgoal by fast
subgoal by fast
subgoal by fast
subgoal by (auto elim!: cdcl_twl_oE)
subgoal using atm_N_U(1) H' by (auto simp: cdcl_twl_o.simps decide)
subgoal by auto
subgoal by (auto elim!: cdcl_twl_oE)
subgoal using atm_N_U H by auto
subgoal using H H' atm_N_U by auto
subgoal using H H' atm_N_U by auto
subgoal by auto
subgoal by auto
subgoal using H H' atm_N_U by auto
done
qed
declare decide_or_skip_spec[THEN order_trans, refine_vcg]
subsection ‹Skip and Resolve Loop›
definition skip_and_resolve_loop_inv where
‹skip_and_resolve_loop_inv S⇩0 =
(λ(brk, S). cdcl_twl_o⇧*⇧* S⇩0 S ∧ twl_struct_invs S ∧ twl_stgy_invs S ∧
clauses_to_update S = {#} ∧ literals_to_update S = {#} ∧
get_conflict S ≠ None ∧
count_decided (get_trail S) ≠ 0 ∧
get_trail S ≠ [] ∧
get_conflict S ≠ Some {#} ∧
(brk ⟶ no_step cdcl⇩W_restart_mset.skip (state⇩W_of S) ∧
no_step cdcl⇩W_restart_mset.resolve (state⇩W_of S)))›
definition tl_state :: ‹'v twl_st ⇒ (bool × 'v twl_st)› where
‹tl_state = (λ(M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q). do {
(False, (tl M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q))})›
definition mop_tl_state_pre :: ‹'v twl_st ⇒ bool› where
‹mop_tl_state_pre S ⟷ twl_struct_invs S ∧ twl_stgy_invs S ∧
clauses_to_update S = {#} ∧ literals_to_update S = {#} ∧
get_conflict S ≠ None ∧
count_decided (get_trail S) ≠ 0 ∧
get_trail S ≠ [] ∧
get_conflict S ≠ Some {#} ∧
is_proped (hd (get_trail S)) ∧
lit_of (hd (get_trail S)) ∈# all_lits_of_st S ∧
lit_of (hd (get_trail S)) ∉# the (get_conflict S) ∧
-lit_of (hd (get_trail S)) ∉# the (get_conflict S)›
definition mop_tl_state :: ‹'v twl_st ⇒ (bool × 'v twl_st) nres› where
‹mop_tl_state = (λS. do {
ASSERT(mop_tl_state_pre S);
RETURN(tl_state S)})›
definition update_confl_tl_pre :: ‹'v literal ⇒ 'v clause ⇒ 'v twl_st ⇒ bool› where
‹update_confl_tl_pre L D S ⟷ twl_struct_invs S ∧ twl_stgy_invs S ∧
clauses_to_update S = {#} ∧ literals_to_update S = {#} ∧
get_conflict S ≠ None ∧
count_decided (get_trail S) ≠ 0 ∧
get_trail S ≠ [] ∧
get_conflict S ≠ Some {#} ∧
L ∈# D ∧
-L ∈# the (get_conflict S) ∧
hd (get_trail S) = Propagated L D ∧
L ∈# all_lits_of_st S›
definition update_confl_tl :: ‹'v literal ⇒ 'v clause ⇒ 'v twl_st ⇒ (bool × 'v twl_st)› where
‹update_confl_tl = (λL C (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q).
(False, (tl M, N, U, Some (remove1_mset L (remove1_mset (-L) ((the D) ∪# C))), NE, UE, NS, US, N0, U0, WS, Q)))›
definition mop_update_confl_tl :: ‹'v literal ⇒ 'v clause ⇒ 'v twl_st ⇒ (bool × 'v twl_st) nres› where
‹mop_update_confl_tl = (λL C S. do {
ASSERT(update_confl_tl_pre L C S);
RETURN (update_confl_tl L C S)})›
definition mop_lit_notin_conflict :: ‹'v literal ⇒ 'v twl_st ⇒ bool nres› where
‹mop_lit_notin_conflict L S = do {
ASSERT(get_conflict S ≠ None ∧ -L ∉# the (get_conflict S) ∧ L ∈# all_lits_of_st S);
RETURN (L ∉# the (get_conflict S))
}›
definition mop_maximum_level_removed_pre :: ‹'v literal ⇒ 'v twl_st ⇒ bool› where
‹mop_maximum_level_removed_pre L S ⟷ twl_struct_invs S ∧ twl_stgy_invs S ∧
clauses_to_update S = {#} ∧ literals_to_update S = {#} ∧
get_conflict S ≠ None ∧
count_decided (get_trail S) ≠ 0 ∧
get_trail S ≠ [] ∧
get_conflict S ≠ Some {#} ∧
-L ∈# the (get_conflict S) ∧
L = lit_of (hd (get_trail S))›
definition mop_maximum_level_removed :: ‹'v literal ⇒ 'v twl_st ⇒ bool nres› where
‹mop_maximum_level_removed L S = do {
ASSERT (mop_maximum_level_removed_pre L S);
RETURN (get_maximum_level (get_trail S) (remove1_mset (-L) (the (get_conflict S))) = count_decided (get_trail S))
}›
definition mop_hd_trail_pre :: ‹'v twl_st ⇒ bool› where
‹mop_hd_trail_pre S ⟷ twl_struct_invs S ∧ twl_stgy_invs S ∧
clauses_to_update S = {#} ∧ literals_to_update S = {#} ∧
get_conflict S ≠ None ∧
get_trail S ≠ [] ∧ is_proped (hd (get_trail S)) ∧
get_conflict S ≠ Some {#}›
definition mop_hd_trail :: ‹'v twl_st ⇒ ('v literal × 'v clause) nres› where
‹mop_hd_trail S = do{
ASSERT(mop_hd_trail_pre S);
SPEC(λ(L, C). Propagated L C = hd (get_trail S))
}›
definition skip_and_resolve_loop :: ‹'v twl_st ⇒ 'v twl_st nres› where
‹skip_and_resolve_loop S⇩0 =
do {
(_, S) ←
WHILE⇩T⇗skip_and_resolve_loop_inv S⇩0⇖
(λ(uip, S). ¬uip ∧ ¬is_decided (hd (get_trail S)))
(λ(_, S).
do {
(L, C) ← mop_hd_trail S;
b ← mop_lit_notin_conflict (-L) S;
if b then
do {mop_tl_state S}
else do {
b ← mop_maximum_level_removed L S;
if b
then
do {mop_update_confl_tl L C S}
else
do {RETURN (True, S)}}
}
)
(False, S⇩0);
RETURN S
}
›
lemma skip_and_resolve_loop_spec:
assumes struct_S: ‹twl_struct_invs S› and stgy_S: ‹twl_stgy_invs S› and
‹clauses_to_update S = {#}› and ‹literals_to_update S = {#}› and
‹get_conflict S ≠ None› and count_dec: ‹count_decided (get_trail S) > 0›
shows ‹skip_and_resolve_loop S ≤ SPEC(λT. cdcl_twl_o⇧*⇧* S T ∧ twl_struct_invs T ∧ twl_stgy_invs T ∧
no_step cdcl⇩W_restart_mset.skip (state⇩W_of T) ∧
no_step cdcl⇩W_restart_mset.resolve (state⇩W_of T) ∧
get_conflict T ≠ None ∧ clauses_to_update T = {#} ∧ literals_to_update T = {#})›
(is ‹_ ≤ ?R›)
unfolding skip_and_resolve_loop_def mop_hd_trail_def nres_monad3 mop_lit_notin_conflict_def
mop_maximum_level_removed_def
proof (refine_vcg WHILEIT_rule[where R = ‹measure (λ(brk, S). Suc (length (get_trail S) - If brk 1 0))›];
remove_dummy_vars)
let ?R = ‹(λa b. SPEC
(λs'. skip_and_resolve_loop_inv S s' ∧
(s', a, b)
∈ measure
(λ(brk, S).
Suc (length (get_trail S) - (if brk then 1 else 0)))))›
show ‹wf (measure (λ(brk, S). Suc (length (get_trail S) - (if brk then 1 else 0))))›
by auto
have neg: ‹get_trail S ⊨as CNot (the (get_conflict S))› if ‹get_conflict S ≠ None›
using assms that unfolding twl_struct_invs_def cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv_def
cdcl⇩W_restart_mset.cdcl⇩W_conflicting_def pcdcl_all_struct_invs_def
by (cases S, auto simp add: cdcl⇩W_restart_mset_state)
then have ‹get_trail S ≠ []› if ‹get_conflict S ≠ Some {#}›
using that assms by auto
then show ‹skip_and_resolve_loop_inv S (False, S)›
using assms by (cases S) (auto simp: skip_and_resolve_loop_inv_def cdcl⇩W_restart_mset.skip.simps
cdcl⇩W_restart_mset.resolve.simps cdcl⇩W_restart_mset_state
twl_stgy_invs_def cdcl⇩W_restart_mset.conflict_non_zero_unless_level_0_def)
fix brk :: bool and T :: ‹'a twl_st›
assume
inv: ‹skip_and_resolve_loop_inv S (brk, T)› and
brk: ‹case (brk, T) of (brk, S) ⇒ ¬ brk ∧ ¬ is_decided (hd (get_trail S))›
have [simp]: ‹brk = False›
using brk by auto
have M_not_empty: ‹get_trail T ≠ []›
using brk inv unfolding skip_and_resolve_loop_inv_def by auto
then show ‹mop_hd_trail_pre T›
using brk inv unfolding skip_and_resolve_loop_inv_def mop_hd_trail_pre_def
by (cases ‹get_trail T›; cases ‹hd (get_trail T)›) auto
fix L :: ‹'a literal› and C
assume
LC: ‹case (L, C) of (L, C) ⇒ Propagated L C = hd (get_trail T)›
obtain M N U D NE UE NS US N0 U0 WS Q where
T: ‹T = (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q)›
by (cases T)
obtain M' :: ‹('a, 'a clause) ann_lits› and D' where
M: ‹get_trail T = Propagated L C # M'› and WS: ‹WS = {#}› and Q: ‹Q = {#}› and D: ‹D = Some D'› and
st: ‹cdcl_twl_o⇧*⇧* S T› and twl: ‹twl_struct_invs T› and D': ‹D' ≠ {#}› and
twl_stgy_S: ‹twl_stgy_invs T› and
count_dec[simp]: ‹count_decided (tl M) > 0› ‹count_decided (tl M) ≠ 0› ‹count_decided M ≠ 0›
using brk inv LC unfolding skip_and_resolve_loop_inv_def
by (cases ‹get_trail T›; cases ‹hd (get_trail T)›) (auto simp: T)
show ‹get_conflict T ≠ None›
by (auto simp: T D)
have ‹cdcl⇩W_restart_mset.cdcl⇩W_conflicting (state⇩W_of T)› and
‹cdcl⇩W_restart_mset.cdcl⇩W_M_level_inv (state⇩W_of T)› and
alien: ‹cdcl⇩W_restart_mset.no_strange_atm (state⇩W_of T)›
using twl D D' M unfolding twl_struct_invs_def cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv_def
pcdcl_all_struct_invs_def by auto
then have ‹M ⊨as CNot D'› and n_d: ‹no_dup M› and
confl_proped: ‹⋀L mark a b.
a @ Propagated L mark # b = trail (state⇩W_of T) ⟶
b ⊨as CNot (remove1_mset L mark) ∧ L ∈# mark›
using M unfolding cdcl⇩W_restart_mset.cdcl⇩W_conflicting_def cdcl⇩W_restart_mset.cdcl⇩W_M_level_inv_def
by (auto simp add: cdcl⇩W_restart_mset_state T D)
then show ‹- (- L) ∉# the (get_conflict T)›
using M by (auto simp: T D dest!: multi_member_split uminus_lits_of_l_definedD)
show alien_L: ‹- L ∈# all_lits_of_st T›
using alien M
by (cases T)
(auto simp: cdcl⇩W_restart_mset.no_strange_atm_def all_lits_of_st_def
cdcl⇩W_restart_mset_state in_all_lits_of_mm_ain_atms_of_iff)
have LD': ‹L ∉# D'›
using ‹M ⊨as CNot D'› M n_d
by (auto dest!: multi_member_split dest: uminus_lits_of_l_definedD simp: T)
{
assume LD: ‹- L ∉# the (get_conflict T)›
let ?T = ‹snd (tl_state T)›
have o_S_T: ‹cdcl_twl_o T ?T›
using cdcl_twl_o.skip[of L ‹the D› C M' N U NE UE NS US N0 U0]
using LD D inv M unfolding skip_and_resolve_loop_inv_def T WS Q D by (auto simp: tl_state_def)
have st_T: ‹cdcl_twl_o⇧*⇧* S ?T›
using st o_S_T by auto
moreover have twl_T: ‹twl_struct_invs ?T›
using struct_S twl o_S_T cdcl_twl_o_twl_struct_invs by blast
moreover have twl_stgy_T: ‹twl_stgy_invs ?T›
using twl o_S_T stgy_S twl_stgy_S cdcl_twl_o_twl_stgy_invs by blast
moreover have ‹tl M ≠ []›
using twl_T D D' unfolding twl_struct_invs_def cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv_def
cdcl⇩W_restart_mset.cdcl⇩W_conflicting_def pcdcl_all_struct_invs_def
by (auto simp: cdcl⇩W_restart_mset_state T tl_state_def)
moreover have ‹- lit_of (hd M) ∈# all_lits_of_st T› ‹is_proped (hd M)›
‹- lit_of (hd M) ∉# the (get_conflict T)› ‹lit_of (hd M) ∉# the (get_conflict T)›
using M alien_L LD LD' D
by (auto intro!: ASSERT_leI simp: T tl_state_def in_all_lits_of_mm_uminus_iff)
ultimately show ‹mop_tl_state T ≤ ?R brk T›
using WS Q D D' twl_stgy_S twl alien_L LD
unfolding skip_and_resolve_loop_inv_def mop_tl_state_pre_def mop_tl_state_def all_lits_of_st_def
by (auto intro!: ASSERT_leI simp: T tl_state_def in_all_lits_of_mm_uminus_iff)
}
{
assume
LD: ‹¬- L ∉# the (get_conflict T)›
have count_dec': ‹count_decided M' = count_decided M›
using M unfolding T by auto
then show mop_maximum_level_removed_pre: ‹mop_maximum_level_removed_pre L T›
using count_dec twl_stgy_S twl D' LD M unfolding mop_maximum_level_removed_pre_def
by (auto simp: T D WS Q simp del: count_dec)
assume
max: ‹get_maximum_level (get_trail T) (remove1_mset (-L) (the (get_conflict T)))
= count_decided (get_trail T)›
let ?D = ‹remove1_mset (- L) (the (get_conflict T)) ∪# remove1_mset L C›
let ?T = ‹snd (update_confl_tl L C T)›
have ‹cdcl⇩W_restart_mset.cdcl⇩W_conflicting (state⇩W_of T)›
using twl D D' M unfolding twl_struct_invs_def cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv_def
pcdcl_all_struct_invs_def by auto
then have ‹L ∈# C› ‹M' ⊨as CNot (remove1_mset L C)› ‹M ⊨as CNot D'›
using M
unfolding cdcl⇩W_restart_mset.cdcl⇩W_conflicting_def
by (force simp: T cdcl⇩W_restart_mset_state D)+
then have ‹-L ∉# C›
using n_d M by (auto simp: T add_mset_eq_add_mset Decided_Propagated_in_iff_in_lits_of_l
dest!: multi_member_split)
have ‹L ∉# D'›
using ‹M ⊨as CNot D'› M n_d
by (auto simp: T Decided_Propagated_in_iff_in_lits_of_l
dest!: multi_member_split)
then have D_alt[simp]: ‹D' ∪# C - {#L, - L#} = ?D›
‹the D ∪# C - {#L, - L#} = ?D›
using LD ‹L ∈# C› ‹-L ∉# C›
by (auto simp: T D sup_union_right1 dest!: multi_member_split)
have o_S_T: ‹cdcl_twl_o T ?T›
using cdcl_twl_o.resolve[of L ‹the D› C M' N U NE UE] LD D max M WS Q D
by (auto simp: T D update_confl_tl_def)
then have st_T: ‹cdcl_twl_o⇧*⇧* S ?T›
using st by auto
moreover have twl_T: ‹twl_struct_invs ?T›
using st_T twl o_S_T cdcl_twl_o_twl_struct_invs by blast
moreover have twl_stgy_T: ‹twl_stgy_invs ?T›
using twl o_S_T twl_stgy_S cdcl_twl_o_twl_stgy_invs by blast
moreover {
have ‹cdcl⇩W_restart_mset.cdcl⇩W_conflicting (state⇩W_of ?T)›
using twl_T D D' M unfolding twl_struct_invs_def cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv_def
pcdcl_all_struct_invs_def by auto
then have ‹tl M ⊨as CNot ?D›
using M unfolding cdcl⇩W_restart_mset.cdcl⇩W_conflicting_def
by (auto simp add: cdcl⇩W_restart_mset_state T update_confl_tl_def)
}
moreover have ‹get_conflict ?T ≠ Some {#}›
using twl_stgy_T count_dec unfolding twl_stgy_invs_def update_confl_tl_def
cdcl⇩W_restart_mset.conflict_non_zero_unless_level_0_def T
by (auto simp: trail.simps conflicting.simps)
moreover have ‹update_confl_tl_pre L C T›
using WS Q D D' mop_maximum_level_removed_pre twl_stgy_T twl twl_stgy_S M LD count_dec
confl_proped[of ‹[]› L C ‹M'›] alien_L
unfolding skip_and_resolve_loop_inv_def
by (auto simp add: cdcl⇩W_restart_mset.skip.simps cdcl⇩W_restart_mset.resolve.simps all_lits_of_st_def
cdcl⇩W_restart_mset_state update_confl_tl_def T update_confl_tl_pre_def in_all_lits_of_mm_uminus_iff)
ultimately show ‹mop_update_confl_tl L C T ≤ ?R brk T›
using WS Q D D' mop_maximum_level_removed_pre M count_dec unfolding skip_and_resolve_loop_inv_def
by (auto simp add: cdcl⇩W_restart_mset.skip.simps cdcl⇩W_restart_mset.resolve.simps
cdcl⇩W_restart_mset_state update_confl_tl_def T mop_update_confl_tl_def)
}
{
assume
LD: ‹¬- L ∉# the (get_conflict T)› and
max: ‹get_maximum_level (get_trail T) (remove1_mset (- L) (the (get_conflict T)))
≠ count_decided (get_trail T)›
show ‹skip_and_resolve_loop_inv S (True, T)›
using inv max LD D M unfolding skip_and_resolve_loop_inv_def
by (auto simp add: cdcl⇩W_restart_mset.skip.simps cdcl⇩W_restart_mset.resolve.simps
cdcl⇩W_restart_mset_state T)
show ‹((True, T), (brk, T)) ∈ measure (λ(brk, S). Suc (length (get_trail S) - (if brk then 1 else 0)))›
using M_not_empty by simp
}
next
fix brk T U
assume
inv: ‹skip_and_resolve_loop_inv S (brk, T)› and
brk: ‹¬(case (brk, T) of (brk, S) ⇒ ¬ brk ∧ ¬ is_decided (hd (get_trail S)))›
show ‹cdcl_twl_o⇧*⇧* S T›
using inv by (auto simp add: skip_and_resolve_loop_inv_def)
{ assume ‹is_decided (hd (get_trail T))›
then have ‹no_step cdcl⇩W_restart_mset.skip (state⇩W_of T)› and
‹no_step cdcl⇩W_restart_mset.resolve (state⇩W_of T)›
by (cases T; auto simp add: cdcl⇩W_restart_mset.skip.simps
cdcl⇩W_restart_mset.resolve.simps cdcl⇩W_restart_mset_state)+
}
moreover
{ assume ‹brk›
then have ‹no_step cdcl⇩W_restart_mset.skip (state⇩W_of T)› and
‹no_step cdcl⇩W_restart_mset.resolve (state⇩W_of T)›
using inv by (auto simp: skip_and_resolve_loop_inv_def)
}
ultimately show ‹¬ cdcl⇩W_restart_mset.skip (state⇩W_of T) U› and
‹¬ cdcl⇩W_restart_mset.resolve (state⇩W_of T) U›
using brk unfolding prod.case by blast+
show ‹twl_struct_invs T›
using inv unfolding skip_and_resolve_loop_inv_def by auto
show ‹twl_stgy_invs T›
using inv unfolding skip_and_resolve_loop_inv_def by auto
show ‹get_conflict T ≠ None›
using inv by (auto simp: skip_and_resolve_loop_inv_def)
show ‹clauses_to_update T = {#}›
using inv by (auto simp: skip_and_resolve_loop_inv_def)
show ‹literals_to_update T = {#}›
using inv by (auto simp: skip_and_resolve_loop_inv_def)
qed
declare skip_and_resolve_loop_spec[THEN order_trans, refine_vcg]
subsection ‹Backtrack›
:: ‹'v twl_st ⇒ bool› where
‹extract_shorter_conflict_pre S ⟷ twl_struct_invs S ∧ twl_stgy_invs S ∧
clauses_to_update S = {#} ∧ literals_to_update S = {#} ∧ get_trail S ≠ []›
:: ‹'v twl_st ⇒ 'v twl_st nres› where
‹extract_shorter_conflict = (λ(M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q). do {
ASSERT(extract_shorter_conflict_pre (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q));
SPEC(λS'. ∃D'. S' = (M, N, U, Some D', NE, UE, NS, US, N0, U0, WS, Q) ∧
D' ⊆# the D ∧ clause `# (N + U) + NE + NS + UE + US + N0 + U0 ⊨pm D' ∧ -lit_of (hd M) ∈# D')
})›
fun equality_except_conflict :: ‹'v twl_st ⇒ 'v twl_st ⇒ bool› where
‹equality_except_conflict (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q)
(M', N', U', D', NE', UE', NS', US', N0', U0', WS', Q') ⟷
M = M' ∧ N = N' ∧ U = U' ∧ NE = NE' ∧ UE = UE' ∧ NS = NS' ∧ US = US' ∧ N0 = N0' ∧ U0 = U0' ∧
WS = WS' ∧ Q = Q'›
lemma :
‹extract_shorter_conflict S = do {
ASSERT(extract_shorter_conflict_pre S);
SPEC(λS'. ∃D'. equality_except_conflict S S' ∧ Some D' = get_conflict S' ∧
D' ⊆# the (get_conflict S) ∧ clause `# (get_clauses S) + unit_clss S + subsumed_clauses S + get_all_clauses0 S ⊨pm D' ∧
-lit_of (hd (get_trail S)) ∈# D')}›
unfolding extract_shorter_conflict_def
by (cases S) (auto simp: ac_simps intro!: bind_cong[OF refl])
definition reduce_trail_bt :: ‹'v literal ⇒ 'v twl_st ⇒ 'v twl_st nres› where
‹reduce_trail_bt = (λL (M, N, U, D', NE, UE, WS, Q). do {
M1 ← SPEC(λM1. ∃K M2. (Decided K # M1, M2) ∈ set (get_all_ann_decomposition M) ∧
get_level M K = get_maximum_level M (the D' - {#-L#}) + 1);
RETURN (M1, N, U, D', NE, UE, WS, Q)
})›
definition propagate_bt_pre :: ‹'v literal ⇒ 'v literal ⇒ 'v twl_st ⇒ bool› where
‹propagate_bt_pre L L' S ⟷ (∃M N U D NE UE NS US WS Q M' D'.
S = (M, N, U, Some D, NE, UE,NS, US, WS, Q) ∧
twl_stgy_invs (M' @ M, N, U, Some D', NE, UE, NS, US, WS, Q) ∧
twl_struct_invs (M' @ M, N, U, Some D', NE, UE, NS, US, WS, Q) ∧
D ⊆# D' ∧
-L ∈# D ∧
get_conflict S ≠ None ∧
L' ∈# D - {#-L#} ∧
L ≠ -L' ∧
get_level (M) L' = get_maximum_level (M) (D - {#-L#}) ∧
undefined_lit M L ∧
L ∈# all_lits_of_st (M, N, U, Some D, NE, UE, NS, US, WS, Q)∧
L' ∈# all_lits_of_st (M, N, U, Some D, NE, UE, NS, US, WS, Q) ∧
(set_mset (all_lits_of_m D) ⊆
set_mset (all_lits_of_st (M, N, U, Some D, NE, UE, NS, US, WS, Q))))›
definition propagate_bt :: ‹'v literal ⇒ 'v literal ⇒ 'v twl_st ⇒ 'v twl_st› where
‹propagate_bt = (λL L' (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q). do {
(Propagated (-L) (the D) # M, N, add_mset (TWL_Clause {#-L, L'#} (the D - {#-L, L'#})) U,
None, NE, UE, NS, US, N0, U0, WS, {#L#})
})›
definition mop_propagate_bt :: ‹'v literal ⇒ 'v literal ⇒ 'v twl_st ⇒ 'v twl_st nres› where
‹mop_propagate_bt = (λL L' S. do {
ASSERT(propagate_bt_pre L L' S);
RETURN (propagate_bt L L' S)
})›
definition propagate_unit_bt_pre :: ‹'v literal ⇒ 'v twl_st ⇒ bool› where
‹propagate_unit_bt_pre L S ⟷ (∃M N U NE UE NS US N0 U0 WS Q M' D'.
S = (M, N, U, Some {#-L#}, NE, UE, NS, US, N0, U0, WS, Q) ∧
twl_stgy_invs (M' @ M, N, U, Some D', NE, UE, NS, US, N0, U0, WS, Q) ∧
twl_struct_invs (M' @ M, N, U, Some D', NE, UE, NS, US, N0, U0, WS, Q) ∧
{#-L#} ⊆# D' ∧
undefined_lit M L ∧
L ∈# all_lits_of_st (M, N, U, Some D', NE, UE, NS, US, N0, U0, WS, Q))›
definition propagate_unit_bt :: ‹'v literal ⇒ 'v twl_st ⇒ 'v twl_st› where
‹propagate_unit_bt = (λL (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q).
(Propagated (-L) (the D) # M, N, U, None, NE, add_mset (the D) UE, NS, US, N0, U0, WS, {#L#}))›
definition mop_propagate_unit_bt :: ‹'v literal ⇒ 'v twl_st ⇒ 'v twl_st nres› where
‹mop_propagate_unit_bt = (λL S. do {
ASSERT (propagate_unit_bt_pre L S);
RETURN (propagate_unit_bt L S)
})›
definition mop_lit_hd_trail_pre :: ‹'v twl_st ⇒ bool› where
‹mop_lit_hd_trail_pre S ⟷ twl_struct_invs S ∧ twl_stgy_invs S ∧
clauses_to_update S = {#} ∧ literals_to_update S = {#} ∧
get_conflict S ≠ None ∧
get_trail S ≠ [] ∧
get_conflict S ≠ Some {#}›
definition mop_lit_hd_trail :: ‹'v twl_st ⇒ ('v literal) nres› where
‹mop_lit_hd_trail S = do {
ASSERT(mop_lit_hd_trail_pre S);
SPEC(λL. L = lit_of (hd (get_trail S)))
}›
definition backtrack_inv where
‹backtrack_inv S ⟷ twl_struct_invs S ∧ twl_stgy_invs S ∧ get_trail S ≠ [] ∧
get_conflict S ≠ None ∧ get_conflict S ≠ Some {#} ∧ -lit_of (hd (get_trail S)) ∈# the (get_conflict S) ∧
no_step cdcl⇩W_restart_mset.skip (state⇩W_of S) ∧ no_step cdcl⇩W_restart_mset.resolve (state⇩W_of S)›
definition find_lit_of_max_level where
‹find_lit_of_max_level = (λS L. do {
ASSERT(distinct_mset (the (get_conflict S)) ∧ -L ∈# the (get_conflict S));
SPEC(λL'. L' ∈# the (get_conflict S) - {#-L#} ∧
get_level (get_trail S) L' = get_maximum_level (get_trail S) (the (get_conflict S) - {#-L#}))
})›
definition backtrack :: ‹'v twl_st ⇒ 'v twl_st nres› where
‹backtrack S =
do {
ASSERT(backtrack_inv S);
L ← mop_lit_hd_trail S;
S ← extract_shorter_conflict S;
S ← reduce_trail_bt L S;
if size (the (get_conflict S)) > 1
then do {
L' ← find_lit_of_max_level S L;
mop_propagate_bt L L' S
}
else do {
mop_propagate_unit_bt L S
}
}
›
lemma
assumes confl: ‹get_conflict S ≠ None› ‹get_conflict S ≠ Some {#}› and
w_q: ‹clauses_to_update S = {#}› and p: ‹literals_to_update S = {#}› and
ns_s: ‹no_step cdcl⇩W_restart_mset.skip (state⇩W_of S)› and
ns_r: ‹no_step cdcl⇩W_restart_mset.resolve (state⇩W_of S)› and
twl_struct: ‹twl_struct_invs S› and twl_stgy: ‹twl_stgy_invs S›
shows
backtrack_spec:
‹backtrack S ≤ SPEC (λT. cdcl_twl_o S T ∧ get_conflict T = None ∧ no_step cdcl_twl_o T ∧
twl_struct_invs T ∧ twl_stgy_invs T ∧ clauses_to_update T = {#} ∧
literals_to_update T ≠ {#})› (is ?spec) and
backtrack_nofail:
‹nofail (backtrack S)› (is ?fail)
proof -
let ?S = ‹state⇩W_of S›
have inv_s: ‹cdcl⇩W_restart_mset.cdcl⇩W_stgy_invariant ?S› and
inv: ‹cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv ?S›
using twl_struct twl_stgy unfolding pcdcl_all_struct_invs_def twl_struct_invs_def
twl_stgy_invs_def by auto
let ?D' = ‹the (conflicting ?S)›
have M_CNot_D': ‹trail ?S ⊨as CNot ?D'› and
dist: ‹distinct_mset ?D'›
using inv confl unfolding cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv_def
cdcl⇩W_restart_mset.cdcl⇩W_conflicting_def
cdcl⇩W_restart_mset.distinct_cdcl⇩W_state_def
by (cases ‹conflicting ?S›; cases S; auto simp: cdcl⇩W_restart_mset_state; fail)+
then have trail: ‹get_trail S ≠ []›
using confl unfolding true_annots_true_cls_def_iff_negation_in_model
by (cases S) (auto simp: cdcl⇩W_restart_mset_state)
have all_struct:
‹cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv (state⇩W_of S)›
using twl_struct
by (auto simp: twl_struct_invs_def pcdcl_all_struct_invs_def)
then have uL_D: ‹- lit_of (hd (get_trail S)) ∈# the (get_conflict S)›
using cdcl⇩W_restart_mset.no_step_skip_hd_in_conflicting[of
‹state⇩W_of S›] ns_s ns_r confl twl_stgy
by (auto simp: twl_st twl_stgy_invs_def pcdcl_all_struct_invs_def)
show ?spec
unfolding backtrack_def extract_shorter_conflict_def reduce_trail_bt_def
mop_lit_hd_trail_def mop_propagate_bt_def mop_propagate_unit_bt_def
find_lit_of_max_level_def
proof (refine_vcg; remove_dummy_vars; clarify?)
show ‹backtrack_inv S›
using uL_D trail confl assms unfolding backtrack_inv_def by fast
show ‹mop_lit_hd_trail_pre S›
using trail confl assms unfolding mop_lit_hd_trail_pre_def
by auto
fix M M1 M2 :: ‹('a, 'a clause) ann_lits› and
N U :: ‹'a twl_clss› and
D :: ‹'a clause option› and D' :: ‹'a clause› and NE UE NS US N0 U0 :: ‹'a clauses› and
WS :: ‹'a clauses_to_update› and Q :: ‹'a lit_queue› and K K' :: ‹'a literal›
let ?S = ‹(M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q)›
let ?T = ‹(M, N, U, Some D', NE, UE, NS, US, N0, U0, WS, Q)›
let ?U = ‹(M1, N, U, Some D', NE, UE, NS, US, N0, U0, WS, Q)›
let ?MS = ‹get_trail ?S›
let ?MT = ‹get_trail ?T›
assume
S: ‹S = (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q)›
show ‹extract_shorter_conflict_pre ?S›
using assms trail unfolding S extract_shorter_conflict_pre_def by auto
have alien: ‹cdcl⇩W_restart_mset.no_strange_atm (state⇩W_of S)› and
‹cdcl⇩W_restart_mset.cdcl⇩W_M_level_inv (state⇩W_of S)›
using inv unfolding cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv_def by fast+
then have alien_L: ‹lit_of (hd M) ∈# all_lits_of_st ?S›
using trail unfolding cdcl⇩W_restart_mset.no_strange_atm_def
cdcl⇩W_restart_mset.cdcl⇩W_M_level_inv_def all_lits_of_st_def
by (cases M) (auto simp: S cdcl⇩W_restart_mset_state in_all_lits_of_mm_ain_atms_of_iff)
assume
D'_D: ‹D' ⊆# the D› and
L_D': ‹-lit_of (hd M) ∈# D'›
show ‹distinct_mset (the (get_conflict ?U))›
using dist distinct_mset_mono[OF D'_D] by (auto simp: S cdcl⇩W_restart_mset_state)
show ‹- lit_of (hd (get_trail ?S)) ∈# the (get_conflict ?U)›
using L_D' by (auto simp: S)
assume
N_U_NE_UE_D': ‹clauses (N + U) + NE + NS + UE + US + N0 + U0 ⊨pm D'› and
decomp: ‹(Decided K' # M1, M2) ∈ set (get_all_ann_decomposition M)› and
lev_K': ‹get_level M K' = get_maximum_level M (remove1_mset (- lit_of (hd ?MS))
(the (Some D'))) + 1›
have WS: ‹WS = {#}› and Q: ‹Q = {#}›
using w_q p unfolding S by auto
have uL_D: ‹- lit_of (hd M) ∈# the D›
using decomp N_U_NE_UE_D' D'_D L_D' lev_K'
unfolding WS Q
by auto
have D_Some_the: ‹D = Some (the D)›
using confl S by auto
let ?S' = ‹state⇩W_of S›
have inv_s: ‹cdcl⇩W_restart_mset.cdcl⇩W_stgy_invariant ?S'› and
inv: ‹cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv ?S'›
using twl_struct twl_stgy unfolding twl_struct_invs_def twl_stgy_invs_def
pcdcl_all_struct_invs_def by auto
have Q: ‹Q = {#}› and WS: ‹WS = {#}›
using w_q p unfolding S by auto
have M_CNot_D': ‹M ⊨as CNot D'›
using M_CNot_D' S D'_D
by (auto simp: cdcl⇩W_restart_mset_state true_annots_true_cls_def_iff_negation_in_model)
obtain L'' M' where M: ‹M = L'' # M'›
using trail S by (cases M) auto
have D'_empty: ‹D' ≠ {#}›
using L_D' by auto
have L'_D: ‹-lit_of L'' ∈# D'›
using L_D' by (auto simp: cdcl⇩W_restart_mset_state M)
have lev_inv: ‹cdcl⇩W_restart_mset.cdcl⇩W_M_level_inv ?S'›
using inv unfolding cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv_def by fast
then have n_d: ‹no_dup M› and dec: ‹backtrack_lvl ?S' = count_decided M›
using S unfolding cdcl⇩W_restart_mset.cdcl⇩W_M_level_inv_def
by (auto simp: cdcl⇩W_restart_mset_state)
then have uL''_M: ‹-lit_of L'' ∉ lits_of_l M›
by (auto simp: Decided_Propagated_in_iff_in_lits_of_l M)
have ‹get_maximum_level M (remove1_mset (-lit_of (hd M)) D') < count_decided M›
proof (cases L'')
case (Decided x1) note L'' = this(1)
have ‹distinct_mset (the D)›
using inv S confl unfolding cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv_def
cdcl⇩W_restart_mset.distinct_cdcl⇩W_state_def
by (auto simp: cdcl⇩W_restart_mset_state)
then have ‹distinct_mset D'›
using D'_D by (blast intro: distinct_mset_mono)
then have ‹- x1 ∉# remove1_mset (- x1) D'›
using L'_D L'' D'_D by (auto dest: distinct_mem_diff_mset)
then have H: ‹∀x∈#remove1_mset (- lit_of (hd M)) D'. undefined_lit [L''] x›
using L'' M_CNot_D' uL''_M
by (fastforce simp: atms_of_def atm_of_eq_atm_of M true_annots_true_cls_def_iff_negation_in_model
dest: in_diffD)
have ‹get_maximum_level M (remove1_mset (- lit_of (hd M)) D') =
get_maximum_level M' (remove1_mset (- lit_of (hd M)) D')›
using get_maximum_level_skip_beginning[OF H, of M'] M
by auto
then show ?thesis
using count_decided_ge_get_maximum_level[of M' ‹remove1_mset (-lit_of (hd M)) D'›] M L''
by simp
next
case (Propagated L C) note L'' = this(1)
moreover {
have ‹∀L mark a b. a @ Propagated L mark # b = trail (state⇩W_of S) ⟶
b ⊨as CNot (remove1_mset L mark) ∧ L ∈# mark›
using inv unfolding cdcl⇩W_restart_mset.cdcl⇩W_all_struct_inv_def
cdcl⇩W_restart_mset.cdcl⇩W_conflicting_def
by blast
then have ‹L ∈# C›
by (force simp: S M cdcl⇩W_restart_mset_state L'') }
moreover have D_empty: ‹the D ≠ {#}›
using D'_D D'_empty by auto
moreover have ‹-L ∈# the D›
using ns_s L'' confl D_empty
by (force simp: cdcl⇩W_restart_mset.skip.simps S M cdcl⇩W_restart_mset_state)
ultimately have ‹get_maximum_level M (remove1_mset (- lit_of (hd M)) (the D))
< count_decided M›
using ns_r confl count_decided_ge_get_maximum_level[of M
‹remove1_mset (-lit_of (hd M)) (the D)›]
by (fastforce simp add: cdcl⇩W_restart_mset.resolve.simps S M
cdcl⇩W_restart_mset_state)
moreover have ‹get_maximum_level M (remove1_mset (- lit_of (hd M)) D') ≤
get_maximum_level M (remove1_mset (- lit_of (hd M)) (the D))›
by (rule get_maximum_level_mono) (use D'_D in ‹auto intro: mset_le_subtract›)
ultimately show ?thesis
by simp
qed
then have ‹∃K M1 M2. (Decided K # M1, M2) ∈ set (get_all_ann_decomposition M) ∧
get_level M K = get_maximum_level M (remove1_mset (-lit_of (hd M)) D') + 1›
using cdcl⇩W_restart_mset.backtrack_ex_decomp n_d
by (auto simp: cdcl⇩W_restart_mset_state S)
define i where ‹i = get_maximum_level M (remove1_mset (- lit_of (hd M)) D')›
let ?T = ‹(Propagated (-lit_of (hd M)) D' # M1, N,
add_mset (TWL_Clause {#-lit_of (hd M), K#} (D' - {#-lit_of (hd M), K#})) U,
None, NE, UE, NS, US, N0, U0, WS, {#lit_of (hd M)#})›
let ?T' = ‹(Propagated (-lit_of (hd M)) D' # M1, N,
add_mset (TWL_Clause {#-lit_of (hd M), K#} (D' - {#-lit_of (hd M), K#})) U,
None, NE, UE, NS, US, N0, U0, WS, {#- (-lit_of (hd M))#})›
have lev_D': ‹count_decided M = get_maximum_level (L'' # M') D'›
using count_decided_ge_get_maximum_level[of M D'] L'_D
get_maximum_level_ge_get_level[of ‹-lit_of L''› D' M] unfolding M
by (auto split: if_splits)
have ‹the D ≠ {#}›
using D'_D D'_empty L'_D by (auto)
have uL'_D: ‹lit_of L'' ∉# D'›
using L_D' n_d M_CNot_D' by (auto simp: cdcl⇩W_restart_mset_state M add_mset_eq_add_mset
Decided_Propagated_in_iff_in_lits_of_l
dest!: multi_member_split)
{
assume size_D: ‹1 < size (the (get_conflict ?U))› and
K_D: ‹K ∈# remove1_mset (- lit_of (hd ?MS)) (the (get_conflict ?U))› and
lev_K: ‹get_level (get_trail ?U) K = get_maximum_level (get_trail ?U)
(remove1_mset (- lit_of (hd (get_trail ?S))) (the (get_conflict ?U)))›
have neq: ‹lit_of (hd M) ≠ - K›
using dist K_D D'_D L_D' distinct_mset_mono[OF D'_D]
by (auto simp: S conflicting.simps M distinct_mset_remove1_All)
moreover have ‹undefined_lit M1 (lit_of (hd (get_trail ?S)))›
using decomp n_d M
apply (auto simp: dest!: get_all_ann_decomposition_exists_prepend)
apply (case_tac c; case_tac M2)
apply auto
done
moreover have ‹lit_of (hd (get_trail ?S)) ∈# all_lits_of_st ?S›
using alien_L by (auto simp: M)
moreover have ‹K ∈# all_lits_of_st ?S›
using alien neq mset_subset_eqD[OF D'_D in_diffD[OF K_D,
unfolded get_conflict.simps option.sel]] assms(1)
unfolding cdcl⇩W_restart_mset.no_strange_atm_def all_lits_of_st_def all_lits_of_st_def
by (auto simp: S cdcl⇩W_restart_mset_state in_all_lits_of_mm_ain_atms_of_iff
dest!: multi_member_split)
moreover have ‹set_mset (all_lits_of_m D') ⊆ set_mset (all_lits_of_st ?S)›
using alien assms(1) atms_of_subset_mset_mono[OF D'_D]
unfolding cdcl⇩W_restart_mset.no_strange_atm_def all_lits_of_st_def
by (fastforce simp: S cdcl⇩W_restart_mset_state in_all_lits_of_mm_ain_atms_of_iff
in_all_lits_of_m_ain_atms_of_iff)
ultimately show ‹propagate_bt_pre (lit_of (hd (get_trail ?S))) K ?U›
using ‹the D ≠ {#}› assms D'_D D'_empty L'_D K_D uL'_D lev_K
get_all_ann_decomposition_exists_prepend[OF decomp] uL_D
unfolding propagate_bt_pre_def S all_lits_of_st_def
by (auto simp: L_D' intro!: exI[of _ ‹take (length M - length M1) M›]
exI[of _ ‹the D›])
have ‹∀L' ∈# D'. -L' ∈ lits_of_l M›
using M_CNot_D' uL''_M
by (fastforce simp: atms_of_def atm_of_eq_atm_of M true_annots_true_cls_def_iff_negation_in_model
dest: in_diffD)
obtain c where c: ‹M = c @ M2 @ Decided K' # M1›
using get_all_ann_decomposition_exists_prepend[OF decomp] by blast
have ‹get_level M K' = Suc (count_decided M1)›
using n_d unfolding c by auto
then have i: ‹i = count_decided M1›
using lev_K' unfolding i_def by auto
have lev_M_M1: ‹∀L' ∈# D' - {#-lit_of (hd M)#}. get_level M L' = get_level M1 L'›
proof
fix L'
assume L': ‹L' ∈# D' - {#-lit_of (hd M)#}›
have ‹get_level M L' > count_decided M1› if ‹defined_lit (c @ M2 @ Decided K' # []) L'›
using get_level_skip_end[OF that, of M1] n_d that get_level_last_decided_ge[of ‹c @ M2›]
by (auto simp: c)
moreover have ‹get_level M L' ≤ i›
using get_maximum_level_ge_get_level[OF L', of M] unfolding i_def by auto
ultimately show ‹get_level M L' = get_level M1 L'›
using n_d c L' i by (cases ‹defined_lit (c @ M2 @ Decided K' # []) L'›) auto
qed
have ‹get_level M1 `# remove1_mset (- lit_of (hd M)) D' = get_level M `# remove1_mset (- lit_of (hd M)) D'›
by (rule image_mset_cong) (use lev_M_M1 in auto)
then have max_M1_M1_D: ‹get_maximum_level M1 (remove1_mset (- lit_of (hd M)) D') =
get_maximum_level M (remove1_mset (- lit_of (hd M)) D')›
unfolding get_maximum_level_def by argo
have ‹∃L' ∈# remove1_mset (-lit_of (hd M)) D'.
get_level M L' = get_maximum_level M (remove1_mset (- lit_of (hd M)) D')›
by (rule get_maximum_level_exists_lit_of_max_level)
(use size_D in ‹auto simp: remove1_mset_empty_iff›)
have D'_ne_single: ‹D' ≠ {#- lit_of (hd M)#}›
using size_D apply (cases D', simp)
apply (rename_tac L D'')
apply (case_tac D'')
by simp_all
have cdcl: ‹cdcl_twl_o (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q) ?T'›
unfolding Q WS option.sel list.sel
apply (subst D_Some_the)
apply (rule cdcl_twl_o.backtrack_nonunit_clause[of ‹-lit_of (hd M)› _ K' M1 M2 _ _ i])
subgoal using D'_D L_D' by blast
subgoal using L'_D decomp M by auto
subgoal using L'_D decomp M by auto
subgoal using L'_D M lev_D' by auto
subgoal using i lev_D' i_def by auto
subgoal using lev_K' i_def by auto
subgoal using D'_ne_single .
subgoal using D'_D .
subgoal using N_U_NE_UE_D' by (auto simp: ac_simps)
subgoal using L_D' .
subgoal using K_D by (auto dest: in_diffD)
subgoal using lev_K lev_M_M1 K_D by (simp add: i_def max_M1_M1_D)
done
moreover have ‹get_conflict ?T' = None ∧ clauses_to_update ?T' = {#} ∧ literals_to_update ?T' ≠ {#}›
unfolding WS Q
using S cdcl_twl_o_twl_struct_invs twl_struct by (auto simp: propagate_bt_def)
moreover have ‹(∀S'. ¬ cdcl_twl_o ?T' S')› by (auto simp: cdcl_twl_o.simps)
moreover have ‹twl_struct_invs ?T'›
using S cdcl cdcl_twl_o_twl_struct_invs[OF cdcl] twl_struct twl_stgy by auto
moreover have ‹twl_stgy_invs ?T'›
using S cdcl cdcl_twl_o_twl_stgy_invs[OF cdcl] twl_struct twl_stgy by auto
moreover have ‹clauses_to_update ?T' = {#}›
using WS by (auto simp: propagate_bt_def)
moreover have False if ‹cdcl_twl_o ?T' (an, ao, ap, aq, ar, as, at', b)›
for an ao ap aq ar as at' b
using that by (auto simp: cdcl_twl_o.simps propagate_bt_def)
ultimately show cdcl:
‹cdcl_twl_o ?S (propagate_bt (lit_of (hd (get_trail ?S))) K ?U)›
‹get_conflict (propagate_bt (lit_of (hd (get_trail ?S))) K ?U) = None›
‹twl_struct_invs (propagate_bt (lit_of (hd (get_trail ?S))) K ?U)›
‹twl_stgy_invs (propagate_bt (lit_of (hd (get_trail ?S))) K ?U)›
‹clauses_to_update (propagate_bt (lit_of (hd (get_trail ?S))) K ?U) = {#}›
‹⋀S'. cdcl_twl_o (propagate_bt (lit_of (hd (get_trail ?S))) K ?U) S' ⟹ False›
‹literals_to_update (propagate_bt (lit_of (hd (get_trail ?S))) K ?U) = {#} ⟹ False›
unfolding propagate_bt_def by auto
}
{
assume ‹¬ 1 < size (the (get_conflict ?U))›
then have D': ‹D' = {#-lit_of (hd M)#}›
using L'_D by (cases D') (auto simp: M)
let ?T = ‹(Propagated (- lit_of (hd M)) D' # M1, N, U, None, NE, add_mset D' UE, NS, US, N0, U0, WS,
unmark (hd M))›
let ?T' = ‹(Propagated (- lit_of (hd M)) D' # M1, N, U, None, NE, add_mset D' UE, NS, US, N0, U0, WS,
{#- (-lit_of (hd M))#})›
have i_0: ‹i = 0›
using i_def by (auto simp: D')
have cdcl: ‹cdcl_twl_o (M, N, U, D, NE, UE, NS, US, N0, U0, WS, Q) ?T'›
unfolding D' option.sel WS Q apply (subst D_Some_the)
apply (rule cdcl_twl_o.backtrack_unit_clause[of _ ‹the D› K' M1 M2 _ D' i])
subgoal using D'_D D' by auto
subgoal using decomp by simp
subgoal by (simp add: M)
subgoal using D' by (auto simp: get_maximum_level_add_mset)
subgoal using i_def by simp
subgoal using lev_K' i_def[symmetric] by auto
subgoal using D' .
subgoal using D'_D .
subgoal using N_U_NE_UE_D' by (auto simp: ac_simps)
done
moreover have ‹get_conflict ?T' = None›
by (auto simp add: propagate_unit_bt_def)
moreover have ‹twl_struct_invs ?T'›
using S cdcl cdcl_twl_o_twl_struct_invs twl_struct by blast
moreover have ‹twl_stgy_invs ?T'›
using S cdcl cdcl_twl_o_twl_stgy_invs twl_struct twl_stgy by blast
moreover have ‹clauses_to_update ?T' = {#}›
using WS by (auto simp add: propagate_unit_bt_def)
ultimately show cdcl:
‹cdcl_twl_o ?S (propagate_unit_bt (lit_of (hd (get_trail ?S))) ?U)›
‹get_conflict (propagate_unit_bt (lit_of (hd (get_trail ?S))) ?U) = None›
‹twl_struct_invs (propagate_unit_bt (lit_of (hd (get_trail ?S))) ?U)›
‹twl_stgy_invs (propagate_unit_bt (lit_of (hd (get_trail ?S))) ?U)›
‹clauses_to_update (propagate_unit_bt (lit_of (hd (get_trail ?S))) ?U) = {#}›
unfolding propagate_unit_bt_def by auto
show False if ‹literals_to_update (propagate_unit_bt (lit_of (hd (get_trail ?S))) ?U) = {#}›
using that by (auto simp add: propagate_unit_bt_def)
fix an ao ap aq ar as at' b
show False if ‹cdcl_twl_o (propagate_unit_bt (lit_of (hd (get_trail ?S))) ?U) (an, ao, ap, aq, ar, as, at', b)›
using that by (auto simp: cdcl_twl_o.simps propagate_unit_bt_def)
have ‹undefined_lit M1 (lit_of (hd (get_trail ?S)))›
using decomp n_d M
apply (auto simp: dest!: get_all_ann_decomposition_exists_prepend)
apply (case_tac c; case_tac M2)
apply auto
done
then show ‹propagate_unit_bt_pre (lit_of (hd (get_trail ?S))) ?U›
using ‹the D ≠ {#}› assms D'_D D'_empty L'_D uL'_D alien_L cdcl
get_all_ann_decomposition_exists_prepend[OF decomp] uL_D
unfolding propagate_unit_bt_pre_def S all_lits_of_st_def
by (auto simp: L_D' D' intro!: exI[of _ ‹take (length M - length M1) M›]
exI[of _ ‹the D›])
}
qed
then show ?fail
using nofail_simps(2) pwD1 by blast
qed
declare backtrack_spec[THEN order_trans, refine_vcg]
subsection ‹Full loop›
definition cdcl_twl_o_prog_pre :: ‹'v twl_st ⇒ bool› where
‹cdcl_twl_o_prog_pre S' ⟷
no_step cdcl_twl_cp S' ∧ twl_struct_invs S' ∧ twl_stgy_invs S' ∧
clauses_to_update S' = {#} ∧ literals_to_update S' = {#}›
definition cdcl_twl_o_prog :: ‹'v twl_st ⇒ (bool × 'v twl_st) nres› where
‹cdcl_twl_o_prog S =
do {
ASSERT(cdcl_twl_o_prog_pre S);
if get_conflict S = None
then decide_or_skip S
else do {
if count_decided (get_trail S) > 0
then do {
T ← skip_and_resolve_loop S;
ASSERT(get_conflict T ≠ None ∧ get_conflict T ≠ Some {#});
U ← backtrack T;
RETURN (False, U)
}
else
RETURN (True, S)
}
}
›
setup ‹map_theory_claset (fn ctxt => ctxt delSWrapper ("split_all_tac"))›
declare split_paired_All[simp del]
lemma skip_and_resolve_same_decision_level:
assumes ‹cdcl_twl_o S T› ‹get_conflict T ≠ None›
shows ‹count_decided (get_trail T) = count_decided (get_trail S)›
using assms by (induction rule: cdcl_twl_o.induct) auto
lemma skip_and_resolve_conflict_before:
assumes ‹cdcl_twl_o S T› ‹get_conflict T ≠ None›
shows ‹get_conflict S ≠ None›
using assms by (induction rule: cdcl_twl_o.induct) auto
lemma rtranclp_skip_and_resolve_same_decision_level:
‹cdcl_twl_o⇧*⇧* S T ⟹ get_conflict S ≠ None ⟹ get_conflict T ≠ None ⟹
count_decided (get_trail T) = count_decided (get_trail S)›
apply (induction rule: rtranclp_induct)
subgoal by auto
subgoal for T U
using skip_and_resolve_conflict_before[of T U]
by (auto simp: skip_and_resolve_same_decision_level)
done
lemma empty_conflict_lvl0:
‹twl_stgy_invs T ⟹ get_conflict T = Some {#} ⟹ count_decided (get_trail T) = 0›
by (cases T) (auto simp: twl_stgy_invs_def cdcl⇩W_restart_mset.conflict_non_zero_unless_level_0_def
trail.simps conflicting.simps)
abbreviation cdcl_twl_o_prog_spec where
‹cdcl_twl_o_prog_spec S ≡ λ(brk, T).
cdcl_twl_o⇧*⇧* S T ∧
(get_conflict T ≠ None ⟶ count_decided (get_trail T) = 0) ∧
(¬ brk ⟶ get_conflict T = None ∧ (∀S'. ¬ cdcl_twl_o T S')) ∧
(brk ⟶ get_conflict T ≠ None ∨ (∀S'. ¬ cdcl_twl_stgy T S')) ∧
twl_struct_invs T ∧ twl_stgy_invs T ∧ clauses_to_update T = {#} ∧
(¬ brk ⟶ literals_to_update T ≠ {#}) ∧
(¬brk ⟶ ¬ (∀S'. ¬ cdcl_twl_o S S') ⟶ cdcl_twl_o⇧+⇧+ S T) ∧
cdcl⇩W_restart_mset.cdcl⇩W_learned_clauses_entailed_by_init (state⇩W_of S)›
lemma cdcl_twl_o_prog_spec:
assumes ‹twl_struct_invs S› and ‹twl_stgy_invs S› and ‹clauses_to_update S = {#}› and
‹literals_to_update S = {#}› and
ns_cp: ‹no_step cdcl_twl_cp S› and
ent: ‹cdcl⇩W_restart_mset.cdcl⇩W_learned_clauses_entailed_by_init (state⇩W_of S)›
shows
‹cdcl_twl_o_prog S ≤ SPEC(cdcl_twl_o_prog_spec S)›
(is ‹_ ≤ ?S›)
proof -
have [iff]: ‹¬ cdcl_twl_cp S T› for T
using ns_cp by fast
show ?thesis
unfolding cdcl_twl_o_prog_def
apply (refine_vcg decide_or_skip_spec[THEN order_trans]; remove_dummy_vars)
subgoal using assms unfolding cdcl_twl_o_prog_pre_def by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal by simp
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal for T using assms empty_conflict_lvl0[of T]
rtranclp_skip_and_resolve_same_decision_level[of S T] by auto
subgoal using assms by auto
subgoal using assms by (auto elim!: cdcl_twl_oE simp: image_Un)
subgoal by (auto elim!: cdcl_twl_stgyE cdcl_twl_oE cdcl_twl_cpE)
subgoal by (auto simp: rtranclp_unfold elim!: cdcl_twl_oE)
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
subgoal using assms by auto
done
qed
declare cdcl_twl_o_prog_spec[THEN order_trans, refine_vcg]
section ‹Full Strategy›
abbreviation cdcl_twl_stgy_prog_inv where
‹cdcl_twl_stgy_prog_inv S⇩0 ≡ λ(brk, T). twl_struct_invs T ∧ twl_stgy_invs T ∧
(brk ⟶ final_twl_state T) ∧ cdcl_twl_stgy⇧*⇧* S⇩0 T ∧ clauses_to_update T = {#} ∧
(¬brk ⟶ get_conflict T = None)›
definition cdcl_twl_stgy_prog :: ‹'v twl_st ⇒ 'v twl_st nres› where
‹cdcl_twl_stgy_prog S⇩0 =
do {
do {
(brk, T) ← WHILE⇩T⇗cdcl_twl_stgy_prog_inv S⇩0⇖
(λ(brk, _). ¬brk)
(λ(brk, S).
do {
T ← unit_propagation_outer_loop S;
cdcl_twl_o_prog T
})
(False, S⇩0);
RETURN T
}
}
›
lemma wf_cdcl_twl_stgy_measure:
‹wf ({((brkT, T), (brkS, S)). twl_struct_invs S ∧ cdcl_twl_stgy⇧+⇧+ S T}
∪ {((brkT, T), (brkS, S)). S = T ∧ brkT ∧ ¬brkS})›
(is ‹wf (?TWL ∪ ?BOOL)›)
proof (rule wf_union_compatible)
show ‹wf ?TWL›
using tranclp_wf_cdcl_twl_stgy wf_snd_wf_pair by blast
show ‹?TWL O ?BOOL ⊆ ?TWL›
by auto
show ‹wf ?BOOL›
unfolding wf_iff_no_infinite_down_chain
proof clarify
fix f :: ‹nat ⇒ bool × 'b›
assume H: ‹∀i. (f (Suc i), f i) ∈ {((brkT, T), brkS, S). S = T ∧ brkT ∧ ¬ brkS}›
then have ‹(f (Suc 0), f 0) ∈ {((brkT, T), brkS, S). S = T ∧ brkT ∧ ¬ brkS}› and
‹(f (Suc 1), f 1) ∈ {((brkT, T), brkS, S). S = T ∧ brkT ∧ ¬ brkS}›
by presburger+
then show False
by auto
qed
qed
lemma cdcl_twl_o_final_twl_state:
assumes
‹cdcl_twl_stgy_prog_inv S (brk, T)› and
‹case (brk, T) of (brk, _) ⇒ ¬ brk› and
twl_o: ‹cdcl_twl_o_prog_spec U (True, V)›
shows ‹final_twl_state V›
proof -
have ‹cdcl_twl_o⇧*⇧* U V› and
confl_lev: ‹get_conflict V ≠ None ⟶ count_decided (get_trail V) = 0› and
final: ‹get_conflict V ≠ None ∨ (∀S'. ¬ cdcl_twl_stgy V S')›
‹twl_struct_invs V›
‹twl_stgy_invs V›
‹clauses_to_update V = {#}›
using twl_o
by force+
show ?thesis
unfolding final_twl_state_def
using confl_lev final
by auto
qed
lemma cdcl_twl_stgy_in_measure:
assumes
twl_stgy: ‹cdcl_twl_stgy_prog_inv S (brk0, T)› and
brk0: ‹case (brk0, T) of (brk, uu_) ⇒ ¬ brk› and
twl_o: ‹cdcl_twl_o_prog_spec U V› and
[simp]: ‹twl_struct_invs U› and
TU: ‹cdcl_twl_cp⇧*⇧* T U› and
‹literals_to_update U = {#}›
shows ‹(V, brk0, T)
∈ {((brkT, T), brkS, S). twl_struct_invs S ∧ cdcl_twl_stgy⇧+⇧+ S T} ∪
{((brkT, T), brkS, S). S = T ∧ brkT ∧ ¬ brkS}›
proof -
have [simp]: ‹twl_struct_invs T›
using twl_stgy by fast+
obtain brk' V' where
V: ‹V = (brk', V')›
by (cases V)
have
UV: ‹cdcl_twl_o⇧*⇧* U V'› and
‹(get_conflict V' ≠ None ⟶ count_decided (get_trail V') = 0)› and
not_brk': ‹(¬ brk' ⟶ get_conflict V' = None ∧ (∀S'. ¬ cdcl_twl_o V' S'))› and
brk': ‹(brk' ⟶ get_conflict V' ≠ None ∨ (∀S'. ¬ cdcl_twl_stgy V' S'))› and
[simp]: ‹twl_struct_invs V'›
‹twl_stgy_invs V'›
‹clauses_to_update V' = {#}› and
no_lits_to_upd: ‹(0 < count_decided (get_trail V') ⟶ ¬ brk' ⟶ literals_to_update V' ≠ {#})›
‹(¬brk' ⟶ ¬ (∀S'. ¬ cdcl_twl_o U S') ⟶ cdcl_twl_o⇧+⇧+ U V')›
using twl_o unfolding V
by fast+
have ‹cdcl_twl_stgy⇧*⇧* T V'›
using TU UV by (auto dest!: rtranclp_cdcl_twl_cp_stgyD rtranclp_cdcl_twl_o_stgyD)
then have TV_or_tranclp_TV: ‹T = V' ∨ cdcl_twl_stgy⇧+⇧+ T V'›
unfolding rtranclp_unfold by auto
have [simp]: ‹¬ cdcl_twl_stgy⇧+⇧+ V' V'›
using wf_not_refl[OF tranclp_wf_cdcl_twl_stgy, of V'] by auto
have [simp]: ‹brk0 = False›
using brk0 by auto
have ‹brk'› if ‹T = V'›
proof -
have ns_TV: ‹¬cdcl_twl_stgy⇧+⇧+ T V'›
using that[symmetric] wf_not_refl[OF tranclp_wf_cdcl_twl_stgy, of T] by auto
have ns_T_T: ‹¬cdcl_twl_o⇧+⇧+ T T›
using wf_not_refl[OF tranclp_wf_cdcl_twl_o, of T] by auto
have ‹T = U›
by (metis (no_types, opaque_lifting) TU UV ns_TV rtranclp_cdcl_twl_cp_stgyD
rtranclp_cdcl_twl_o_stgyD rtranclp_tranclp_tranclp rtranclp_unfold)
show ?thesis
using assms ‹literals_to_update U = {#}› unfolding V that[symmetric] ‹T = U›[symmetric]
by (auto simp: ns_T_T)
qed
then show ?thesis
using TV_or_tranclp_TV
unfolding V
by auto
qed
lemma cdcl_twl_o_prog_cdcl_twl_stgy:
assumes
twl_stgy: ‹cdcl_twl_stgy_prog_inv S (brk, S')› and
‹case (brk, S') of (brk, uu_) ⇒ ¬ brk› and
twl_o: ‹cdcl_twl_o_prog_spec T (brk', U)› and
‹twl_struct_invs T› and
cp: ‹cdcl_twl_cp⇧*⇧* S' T› and
‹literals_to_update T = {#}› and
‹∀S'. ¬ cdcl_twl_cp T S'› and
‹twl_stgy_invs T›
shows ‹cdcl_twl_stgy⇧*⇧* S U›
proof -
have ‹cdcl_twl_stgy⇧*⇧* S S'›
using twl_stgy by fast
moreover {
have ‹cdcl_twl_o⇧*⇧* T U›
using twl_o by fast
then have ‹cdcl_twl_stgy⇧*⇧* S' U›
using cp by (auto dest!: rtranclp_cdcl_twl_cp_stgyD rtranclp_cdcl_twl_o_stgyD)
}
ultimately show ?thesis by auto
qed
lemma cdcl_twl_stgy_prog_spec:
assumes ‹twl_struct_invs S› and ‹twl_stgy_invs S› and ‹clauses_to_update S = {#}› and
‹get_conflict S = None› and
‹cdcl⇩W_restart_mset.cdcl⇩W_learned_clauses_entailed_by_init (state⇩W_of S)›
shows
‹cdcl_twl_stgy_prog S ≤ conclusive_TWL_norestart_run S›
unfolding cdcl_twl_stgy_prog_def full_def conclusive_TWL_norestart_run_def
apply (refine_vcg WHILEIT_rule[where
R = ‹{((brkT, T), (brkS, S)). twl_struct_invs S ∧ cdcl_twl_stgy⇧+⇧+ S T} ∪
{((brkT, T), (brkS, S)). S = T ∧ brkT ∧ ¬brkS}›];
remove_dummy_vars)
subgoal using wf_cdcl_twl_stgy_measure .
subgoal using assms by simp
subgoal using assms by simp
subgoal using assms by simp
subgoal using assms by simp
subgoal using assms by simp
subgoal using assms by simp
subgoal by simp
subgoal by simp
subgoal by simp
subgoal by (simp add: no_step_cdcl_twl_cp_no_step_cdcl⇩W_cp)
subgoal by simp
subgoal for brk b x
apply (subgoal_tac ‹pcdcl⇧*⇧* (pstate⇩W_of S) (pstate⇩W_of x)›)
subgoal
using assms
rtranclp_pcdcl_entailed_by_init[of ‹pstate⇩W_of S› ‹pstate⇩W_of x›]
by (auto simp: twl_struct_invs_def)
subgoal
apply (auto simp: twl_struct_invs_def)
apply (meson assms(1) rtranclp_cdcl_twl_cp_stgyD rtranclp_cdcl_twl_stgy_cdcl⇩W_stgy rtranclp_pcdcl_stgy_pcdcl rtranclp_pcdcl_tcore_stgy_pcdcl_stgy' rtranclp_trans)+
done
done
subgoal by simp
subgoal by simp
subgoal by (rule cdcl_twl_o_final_twl_state)
subgoal by (rule cdcl_twl_o_prog_cdcl_twl_stgy)
subgoal by simp
subgoal for brk0 T U brl V
by clarsimp
subgoal for brk0 T U V
by (rule cdcl_twl_stgy_in_measure)
subgoal by simp
subgoal by fast
done
definition cdcl_twl_stgy_prog_break :: ‹'v twl_st ⇒ 'v twl_st nres› where
‹cdcl_twl_stgy_prog_break S⇩0 =
do {
b ← SPEC(λ_. True);
(b, brk, T) ← WHILE⇩T⇗λ(b, S). cdcl_twl_stgy_prog_inv S⇩0 S⇖
(λ(b, brk, _). b ∧ ¬brk)
(λ(_, brk, S). do {
T ← unit_propagation_outer_loop S;
T ← cdcl_twl_o_prog T;
b ← SPEC(λ_. True);
RETURN (b, T)
})
(b, False, S⇩0);
if brk then RETURN T
else
cdcl_twl_stgy_prog T
}
›
lemma wf_cdcl_twl_stgy_measure_break:
‹wf ({((bT, brkT, T), (bS, brkS, S)). twl_struct_invs S ∧ cdcl_twl_stgy⇧+⇧+ S T} ∪
{((bT, brkT, T), (bS, brkS, S)). S = T ∧ brkT ∧ ¬brkS}
)›
(is ‹?wf ?R›)
proof -
have 1: ‹wf ({((brkT, T), brkS, S). twl_struct_invs S ∧ cdcl_twl_stgy⇧+⇧+ S T} ∪
{((brkT, T), brkS, S). S = T ∧ brkT ∧ ¬ brkS})›
(is ‹wf ?S›)
by (rule wf_cdcl_twl_stgy_measure)
have ‹wf {((bT, T), (bS, S)). (T, S) ∈ ?S}›
apply (rule wf_snd_wf_pair)
apply (rule wf_subset)
apply (rule 1)
apply auto
done
then show ?thesis
apply (rule wf_subset)
apply auto
done
qed
lemma cdcl_twl_stgy_prog_break_spec:
assumes ‹twl_struct_invs S› and ‹twl_stgy_invs S› and ‹clauses_to_update S = {#}› and
‹get_conflict S = None› and
ent: ‹cdcl⇩W_restart_mset.cdcl⇩W_learned_clauses_entailed_by_init (state⇩W_of S)›
shows
‹cdcl_twl_stgy_prog_break S ≤ conclusive_TWL_norestart_run S›
unfolding cdcl_twl_stgy_prog_break_def full_def conclusive_TWL_norestart_run_def
apply (refine_vcg cdcl_twl_stgy_prog_spec[unfolded conclusive_TWL_norestart_run_def]
WHILEIT_rule[where
R = ‹{((bT, brkT, T), (bS, brkS, S)). twl_struct_invs S ∧ cdcl_twl_stgy⇧+⇧+ S T} ∪
{((bT, brkT, T), (bS, brkS, S)). S = T ∧ brkT ∧ ¬brkS}›];
remove_dummy_vars)
subgoal using wf_cdcl_twl_stgy_measure_break .
subgoal using assms by simp
subgoal using assms by simp
subgoal using assms by simp
subgoal using assms by simp
subgoal using assms by simp
subgoal using assms by simp
subgoal by simp
subgoal by simp
subgoal by simp
subgoal by (simp add: no_step_cdcl_twl_cp_no_step_cdcl⇩W_cp)
subgoal by simp+
subgoal for brk b x xa
apply (subgoal_tac ‹pcdcl⇧*⇧* (pstate⇩W_of S) (pstate⇩W_of xa)›)
subgoal
using assms
rtranclp_pcdcl_entailed_by_init[of ‹pstate⇩W_of S› ‹pstate⇩W_of xa›]
by (auto simp: twl_struct_invs_def)
subgoal
apply (auto simp: twl_struct_invs_def)
apply (meson assms(1) rtranclp_cdcl_twl_cp_stgyD rtranclp_cdcl_twl_stgy_cdcl⇩W_stgy rtranclp_pcdcl_stgy_pcdcl rtranclp_pcdcl_tcore_stgy_pcdcl_stgy' rtranclp_trans)+
done
done
subgoal by simp
subgoal by simp
subgoal for x a aa ba xa x1a
by (rule cdcl_twl_o_final_twl_state[of S a aa ba]) simp_all
subgoal for x a aa ba xa x1a
by (rule cdcl_twl_o_prog_cdcl_twl_stgy[of S a aa ba xa x1a]) fast+
subgoal by simp
subgoal for brk0 T U brl V
by clarsimp
subgoal for x a aa ba xa xb
using cdcl_twl_stgy_in_measure[of S a aa ba xa] by fast
subgoal by simp
subgoal by fast
subgoal by simp
subgoal by simp
subgoal by simp
subgoal by simp
subgoal for brk b x
apply (subgoal_tac ‹pcdcl⇧*⇧* (pstate⇩W_of S) (pstate⇩W_of x)›)
subgoal
using assms
rtranclp_pcdcl_entailed_by_init[of ‹pstate⇩W_of S› ‹pstate⇩W_of x›]
by (auto simp: twl_struct_invs_def)
subgoal
apply (auto simp: twl_struct_invs_def)
apply (meson assms(1) rtranclp_cdcl_twl_cp_stgyD rtranclp_cdcl_twl_stgy_cdcl⇩W_stgy rtranclp_pcdcl_stgy_pcdcl rtranclp_pcdcl_tcore_stgy_pcdcl_stgy' rtranclp_trans)+
done
done
subgoal using assms by auto
done
definition cdcl_twl_stgy_prog_early :: ‹'v twl_st ⇒ (bool × 'v twl_st) nres› where
‹cdcl_twl_stgy_prog_early S⇩0 =
do {
b ← SPEC(λ_. True);
(b, brk, T) ← WHILE⇩T⇗λ(b, S). cdcl_twl_stgy_prog_inv S⇩0 S⇖
(λ(b, brk, _). b ∧ ¬brk)
(λ(_, brk, S). do {
T ← unit_propagation_outer_loop S;
T ← cdcl_twl_o_prog T;
b ← SPEC(λ_. True);
RETURN (b, T)
})
(b, False, S⇩0);
RETURN (brk , T)
}
›
lemma cdcl_twl_stgy_prog_early_spec:
assumes ‹twl_struct_invs S› and ‹twl_stgy_invs S› and ‹clauses_to_update S = {#}› and
‹get_conflict S = None› and
‹cdcl⇩W_restart_mset.cdcl⇩W_learned_clauses_entailed_by_init (state⇩W_of S)›
shows
‹cdcl_twl_stgy_prog_early S ≤ partial_conclusive_TWL_norestart_run S›
unfolding cdcl_twl_stgy_prog_early_def full_def partial_conclusive_TWL_norestart_run_def
apply (refine_vcg
WHILEIT_rule[where
R = ‹{((bT, brkT, T), (bS, brkS, S)). twl_struct_invs S ∧ cdcl_twl_stgy⇧+⇧+ S T} ∪
{((bT, brkT, T), (bS, brkS, S)). S = T ∧ brkT ∧ ¬brkS}›];
remove_dummy_vars)
subgoal using wf_cdcl_twl_stgy_measure_break .
subgoal using assms by simp
subgoal using assms by simp
subgoal using assms by simp
subgoal using assms by simp
subgoal using assms by simp
subgoal using assms by simp
subgoal by simp
subgoal by simp
subgoal by simp
subgoal by (simp add: no_step_cdcl_twl_cp_no_step_cdcl⇩W_cp)
subgoal by simp
subgoal for brk b x xa
apply (subgoal_tac ‹pcdcl⇧*⇧* (pstate⇩W_of S) (pstate⇩W_of xa)›)
subgoal
using assms
rtranclp_pcdcl_entailed_by_init[of ‹pstate⇩W_of S› ‹pstate⇩W_of xa›]
by (auto simp: twl_struct_invs_def)
subgoal
apply (auto simp: twl_struct_invs_def)
apply (meson assms(1) rtranclp_cdcl_twl_cp_stgyD rtranclp_cdcl_twl_stgy_cdcl⇩W_stgy rtranclp_pcdcl_stgy_pcdcl rtranclp_pcdcl_tcore_stgy_pcdcl_stgy' rtranclp_trans)+
done
done
subgoal by simp
subgoal by simp
subgoal for x a aa ba xa x1a
by (rule cdcl_twl_o_final_twl_state[of S a aa ba]) simp_all
subgoal for x a aa ba xa x1a
by (rule cdcl_twl_o_prog_cdcl_twl_stgy[of S a aa ba xa x1a]) fast+
subgoal by simp
subgoal for brk0 T U brl V
by clarsimp
subgoal for x a aa ba xa xb
using cdcl_twl_stgy_in_measure[of S a aa ba xa] by fast
subgoal by simp
subgoal by fast
done
end