theory CDCL_NOT
imports
Weidenbach_Book_Base.WB_List_More
Weidenbach_Book_Base.Wellfounded_More
Entailment_Definition.Partial_Annotated_Herbrand_Interpretation
CDCL_WNOT_Measure
begin
section ‹NOT's CDCL›
subsection ‹Auxiliary Lemmas and Measure›
text ‹We define here some more simplification rules, or rules that have been useful as help
for some tactic›
lemma atms_of_uminus_lit_atm_of_lit_of:
‹atms_of {# -lit_of x. x ∈# A#} = atm_of ` (lit_of ` (set_mset A))›
unfolding atms_of_def by (auto simp add: Fun.image_comp)
lemma atms_of_ms_single_image_atm_of_lit_of:
‹atms_of_ms (unmark_s A) = atm_of ` (lit_of ` A)›
unfolding atms_of_ms_def by auto
subsection ‹Initial Definitions›
subsubsection ‹The State›
text ‹We define here an abstraction over operation on the state we are manipulating.›
locale dpll_state_ops =
fixes
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st›
begin
abbreviation state⇩N⇩O⇩T :: ‹'st ⇒ ('v, unit) ann_lit list × 'v clauses› where
‹state⇩N⇩O⇩T S ≡ (trail S, clauses⇩N⇩O⇩T S)›
end
text ‹NOT's state is basically a pair composed of the trail (i.e.\ the candidate model) and the
set of clauses. We abstract this state to convert this state to other states. like Weidenbach's
five-tuple.›
locale dpll_state =
dpll_state_ops
trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› +
assumes
prepend_trail⇩N⇩O⇩T:
‹state⇩N⇩O⇩T (prepend_trail L st) = (L # trail st, clauses⇩N⇩O⇩T st)› and
tl_trail⇩N⇩O⇩T:
‹state⇩N⇩O⇩T (tl_trail st) = (tl (trail st), clauses⇩N⇩O⇩T st)› and
add_cls⇩N⇩O⇩T:
‹state⇩N⇩O⇩T (add_cls⇩N⇩O⇩T C st) = (trail st, add_mset C (clauses⇩N⇩O⇩T st))› and
remove_cls⇩N⇩O⇩T:
‹state⇩N⇩O⇩T (remove_cls⇩N⇩O⇩T C st) = (trail st, removeAll_mset C (clauses⇩N⇩O⇩T st))›
begin
lemma
trail_prepend_trail[simp]:
‹trail (prepend_trail L st) = L # trail st›
and
trail_tl_trail⇩N⇩O⇩T[simp]: ‹trail (tl_trail st) = tl (trail st)› and
trail_add_cls⇩N⇩O⇩T[simp]: ‹trail (add_cls⇩N⇩O⇩T C st) = trail st› and
trail_remove_cls⇩N⇩O⇩T[simp]: ‹trail (remove_cls⇩N⇩O⇩T C st) = trail st› and
clauses_prepend_trail[simp]:
‹clauses⇩N⇩O⇩T (prepend_trail L st) = clauses⇩N⇩O⇩T st›
and
clauses_tl_trail[simp]: ‹clauses⇩N⇩O⇩T (tl_trail st) = clauses⇩N⇩O⇩T st› and
clauses_add_cls⇩N⇩O⇩T[simp]:
‹clauses⇩N⇩O⇩T (add_cls⇩N⇩O⇩T C st) = add_mset C (clauses⇩N⇩O⇩T st)› and
clauses_remove_cls⇩N⇩O⇩T[simp]:
‹clauses⇩N⇩O⇩T (remove_cls⇩N⇩O⇩T C st) = removeAll_mset C (clauses⇩N⇩O⇩T st)›
using prepend_trail⇩N⇩O⇩T[of L st] tl_trail⇩N⇩O⇩T[of st] add_cls⇩N⇩O⇩T[of C st] remove_cls⇩N⇩O⇩T[of C st]
by (cases ‹state⇩N⇩O⇩T st›; auto)+
text ‹We define the following function doing the backtrack in the trail:›
function reduce_trail_to⇩N⇩O⇩T :: ‹'a list ⇒ 'st ⇒ 'st› where
‹reduce_trail_to⇩N⇩O⇩T F S =
(if length (trail S) = length F ∨ trail S = [] then S else reduce_trail_to⇩N⇩O⇩T F (tl_trail S))›
by fast+
termination by (relation ‹measure (λ(_, S). length (trail S))›) auto
declare reduce_trail_to⇩N⇩O⇩T.simps[simp del]
text ‹Then we need several lemmas about the @{term reduce_trail_to⇩N⇩O⇩T}.›
lemma
shows
reduce_trail_to⇩N⇩O⇩T_Nil[simp]: ‹trail S = [] ⟹ reduce_trail_to⇩N⇩O⇩T F S = S› and
reduce_trail_to⇩N⇩O⇩T_eq_length[simp]: ‹length (trail S) = length F ⟹ reduce_trail_to⇩N⇩O⇩T F S = S›
by (auto simp: reduce_trail_to⇩N⇩O⇩T.simps)
lemma reduce_trail_to⇩N⇩O⇩T_length_ne[simp]:
‹length (trail S) ≠ length F ⟹ trail S ≠ [] ⟹
reduce_trail_to⇩N⇩O⇩T F S = reduce_trail_to⇩N⇩O⇩T F (tl_trail S)›
by (auto simp: reduce_trail_to⇩N⇩O⇩T.simps)
lemma trail_reduce_trail_to⇩N⇩O⇩T_length_le:
assumes ‹length F > length (trail S)›
shows ‹trail (reduce_trail_to⇩N⇩O⇩T F S) = []›
using assms by (induction F S rule: reduce_trail_to⇩N⇩O⇩T.induct)
(simp add: less_imp_diff_less reduce_trail_to⇩N⇩O⇩T.simps)
lemma trail_reduce_trail_to⇩N⇩O⇩T_Nil[simp]:
‹trail (reduce_trail_to⇩N⇩O⇩T [] S) = []›
by (induction ‹[]› S rule: reduce_trail_to⇩N⇩O⇩T.induct)
(simp add: less_imp_diff_less reduce_trail_to⇩N⇩O⇩T.simps)
lemma clauses_reduce_trail_to⇩N⇩O⇩T_Nil:
‹clauses⇩N⇩O⇩T (reduce_trail_to⇩N⇩O⇩T [] S) = clauses⇩N⇩O⇩T S›
by (induction ‹[]› S rule: reduce_trail_to⇩N⇩O⇩T.induct)
(simp add: less_imp_diff_less reduce_trail_to⇩N⇩O⇩T.simps)
lemma trail_reduce_trail_to⇩N⇩O⇩T_drop:
‹trail (reduce_trail_to⇩N⇩O⇩T F S) =
(if length (trail S) ≥ length F
then drop (length (trail S) - length F) (trail S)
else [])›
apply (induction F S rule: reduce_trail_to⇩N⇩O⇩T.induct)
apply (rename_tac F S, case_tac ‹trail S›)
apply auto[]
apply (rename_tac list, case_tac ‹Suc (length list) > length F›)
prefer 2 apply simp
apply (subgoal_tac ‹Suc (length list) - length F = Suc (length list - length F)›)
apply simp
apply simp
done
lemma reduce_trail_to⇩N⇩O⇩T_skip_beginning:
assumes ‹trail S = F' @ F›
shows ‹trail (reduce_trail_to⇩N⇩O⇩T F S) = F›
using assms by (auto simp: trail_reduce_trail_to⇩N⇩O⇩T_drop)
lemma reduce_trail_to⇩N⇩O⇩T_clauses[simp]:
‹clauses⇩N⇩O⇩T (reduce_trail_to⇩N⇩O⇩T F S) = clauses⇩N⇩O⇩T S›
by (induction F S rule: reduce_trail_to⇩N⇩O⇩T.induct)
(simp add: less_imp_diff_less reduce_trail_to⇩N⇩O⇩T.simps)
lemma trail_eq_reduce_trail_to⇩N⇩O⇩T_eq:
‹trail S = trail T ⟹ trail (reduce_trail_to⇩N⇩O⇩T F S) = trail (reduce_trail_to⇩N⇩O⇩T F T)›
apply (induction F S arbitrary: T rule: reduce_trail_to⇩N⇩O⇩T.induct)
by (metis trail_tl_trail⇩N⇩O⇩T reduce_trail_to⇩N⇩O⇩T_eq_length reduce_trail_to⇩N⇩O⇩T_length_ne
reduce_trail_to⇩N⇩O⇩T_Nil)
lemma trail_reduce_trail_to⇩N⇩O⇩T_add_cls⇩N⇩O⇩T[simp]:
‹no_dup (trail S) ⟹
trail (reduce_trail_to⇩N⇩O⇩T F (add_cls⇩N⇩O⇩T C S)) = trail (reduce_trail_to⇩N⇩O⇩T F S)›
by (rule trail_eq_reduce_trail_to⇩N⇩O⇩T_eq) simp
lemma reduce_trail_to⇩N⇩O⇩T_trail_tl_trail_decomp[simp]:
‹trail S = F' @ Decided K # F ⟹
trail (reduce_trail_to⇩N⇩O⇩T F (tl_trail S)) = F›
apply (rule reduce_trail_to⇩N⇩O⇩T_skip_beginning[of _ ‹tl (F' @ Decided K # [])›])
by (cases F') (auto simp add:tl_append reduce_trail_to⇩N⇩O⇩T_skip_beginning)
lemma reduce_trail_to⇩N⇩O⇩T_length:
‹length M = length M' ⟹ reduce_trail_to⇩N⇩O⇩T M S = reduce_trail_to⇩N⇩O⇩T M' S›
apply (induction M S rule: reduce_trail_to⇩N⇩O⇩T.induct)
by (simp add: reduce_trail_to⇩N⇩O⇩T.simps)
abbreviation trail_weight where
‹trail_weight S ≡ map ((λl. 1 + length l) o snd) (get_all_ann_decomposition (trail S))›
text ‹As we are defining abstract states, the Isabelle equality about them is too strong: we want
the weaker equivalence stating that two states are equal if they cannot be distinguished, i.e.\
given the getter @{term trail} and @{term clauses⇩N⇩O⇩T} do not distinguish them.›
definition state_eq⇩N⇩O⇩T :: ‹'st ⇒ 'st ⇒ bool› (infix "∼" 50) where
‹S ∼ T ⟷ trail S = trail T ∧ clauses⇩N⇩O⇩T S = clauses⇩N⇩O⇩T T›
lemma state_eq⇩N⇩O⇩T_ref[intro, simp]:
‹S ∼ S›
unfolding state_eq⇩N⇩O⇩T_def by auto
lemma state_eq⇩N⇩O⇩T_sym:
‹S ∼ T ⟷ T ∼ S›
unfolding state_eq⇩N⇩O⇩T_def by auto
lemma state_eq⇩N⇩O⇩T_trans:
‹S ∼ T ⟹ T ∼ U ⟹ S ∼ U›
unfolding state_eq⇩N⇩O⇩T_def by auto
lemma
shows
state_eq⇩N⇩O⇩T_trail: ‹S ∼ T ⟹ trail S = trail T› and
state_eq⇩N⇩O⇩T_clauses: ‹S ∼ T ⟹ clauses⇩N⇩O⇩T S = clauses⇩N⇩O⇩T T›
unfolding state_eq⇩N⇩O⇩T_def by auto
lemmas state_simp⇩N⇩O⇩T[simp] = state_eq⇩N⇩O⇩T_trail state_eq⇩N⇩O⇩T_clauses
lemma reduce_trail_to⇩N⇩O⇩T_state_eq⇩N⇩O⇩T_compatible:
assumes ST: ‹S ∼ T›
shows ‹reduce_trail_to⇩N⇩O⇩T F S ∼ reduce_trail_to⇩N⇩O⇩T F T›
proof -
have ‹clauses⇩N⇩O⇩T (reduce_trail_to⇩N⇩O⇩T F S) = clauses⇩N⇩O⇩T (reduce_trail_to⇩N⇩O⇩T F T)›
using ST by auto
moreover have ‹trail (reduce_trail_to⇩N⇩O⇩T F S) = trail (reduce_trail_to⇩N⇩O⇩T F T)›
using trail_eq_reduce_trail_to⇩N⇩O⇩T_eq[of S T F] ST by auto
ultimately show ?thesis by (auto simp del: state_simp⇩N⇩O⇩T simp: state_eq⇩N⇩O⇩T_def)
qed
end
subsubsection ‹Definition of the Transitions›
text ‹Each possible is in its own locale.›
locale propagate_ops =
dpll_state trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› +
fixes
propagate_conds :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st ⇒ bool›
begin
inductive propagate⇩N⇩O⇩T :: ‹'st ⇒ 'st ⇒ bool› where
propagate⇩N⇩O⇩T[intro]: ‹add_mset L C ∈# clauses⇩N⇩O⇩T S ⟹ trail S ⊨as CNot C
⟹ undefined_lit (trail S) L
⟹ propagate_conds (Propagated L ()) S T
⟹ T ∼ prepend_trail (Propagated L ()) S
⟹ propagate⇩N⇩O⇩T S T›
inductive_cases propagate⇩N⇩O⇩TE[elim]: ‹propagate⇩N⇩O⇩T S T›
end
locale decide_ops =
dpll_state trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› +
fixes
decide_conds :: ‹'st ⇒ 'st ⇒ bool›
begin
inductive decide⇩N⇩O⇩T :: ‹'st ⇒ 'st ⇒ bool› where
decide⇩N⇩O⇩T[intro]:
‹undefined_lit (trail S) L ⟹
atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S) ⟹
T ∼ prepend_trail (Decided L) S ⟹
decide_conds S T ⟹
decide⇩N⇩O⇩T S T›
inductive_cases decide⇩N⇩O⇩TE[elim]: ‹decide⇩N⇩O⇩T S S'›
end
locale backjumping_ops =
dpll_state trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› +
fixes
backjump_conds :: ‹'v clause ⇒ 'v clause ⇒ 'v literal ⇒ 'st ⇒ 'st ⇒ bool›
begin
inductive backjump where
‹trail S = F' @ Decided K # F
⟹ T ∼ prepend_trail (Propagated L ()) (reduce_trail_to⇩N⇩O⇩T F S)
⟹ C ∈# clauses⇩N⇩O⇩T S
⟹ trail S ⊨as CNot C
⟹ undefined_lit F L
⟹ atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))
⟹ clauses⇩N⇩O⇩T S ⊨pm add_mset L C'
⟹ F ⊨as CNot C'
⟹ backjump_conds C C' L S T
⟹ backjump S T›
inductive_cases backjumpE: ‹backjump S T›
text ‹The condition @{term ‹atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))›}
is not implied by the the condition @{term ‹clauses⇩N⇩O⇩T S ⊨pm add_mset L C'›} (no negation).›
end
subsection ‹DPLL with Backjumping›
locale dpll_with_backjumping_ops =
propagate_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T propagate_conds +
decide_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T decide_conds +
backjumping_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T backjump_conds
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
inv :: ‹'st ⇒ bool› and
decide_conds :: ‹'st ⇒ 'st ⇒ bool› and
backjump_conds :: ‹'v clause ⇒ 'v clause ⇒ 'v literal ⇒ 'st ⇒ 'st ⇒ bool› and
propagate_conds :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st ⇒ bool› +
assumes
bj_can_jump:
‹⋀S C F' K F L.
inv S ⟹
trail S = F' @ Decided K # F ⟹
C ∈# clauses⇩N⇩O⇩T S ⟹
trail S ⊨as CNot C ⟹
undefined_lit F L ⟹
atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (F' @ Decided K # F)) ⟹
clauses⇩N⇩O⇩T S ⊨pm add_mset L C' ⟹
F ⊨as CNot C' ⟹
¬no_step backjump S› and
can_propagate_or_decide_or_backjump:
‹atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S) ⟹
undefined_lit (trail S) L ⟹
satisfiable (set_mset (clauses⇩N⇩O⇩T S)) ⟹
inv S ⟹
no_dup (trail S) ⟹
∃T. decide⇩N⇩O⇩T S T ∨ propagate⇩N⇩O⇩T S T ∨ backjump S T›
begin
text ‹We cannot add a like condition @{term ‹atms_of C' ⊆ atms_of_ms N›} to ensure that we
can backjump even if the last decision variable has disappeared from the set of clauses.
The part of the condition @{term ‹atm_of L ∈ atm_of ` (lits_of_l (F' @ Decided K # F))›} is
important, otherwise you are not sure that you can backtrack.›
subsubsection ‹Definition›
text ‹We define dpll with backjumping:›
inductive dpll_bj :: ‹'st ⇒ 'st ⇒ bool› for S :: 'st where
bj_decide⇩N⇩O⇩T: ‹decide⇩N⇩O⇩T S S' ⟹ dpll_bj S S'› |
bj_propagate⇩N⇩O⇩T: ‹propagate⇩N⇩O⇩T S S' ⟹ dpll_bj S S'› |
bj_backjump: ‹backjump S S' ⟹ dpll_bj S S'›
lemmas dpll_bj_induct = dpll_bj.induct[split_format(complete)]
thm dpll_bj_induct[OF dpll_with_backjumping_ops_axioms]
lemma dpll_bj_all_induct[consumes 2, case_names decide⇩N⇩O⇩T propagate⇩N⇩O⇩T backjump]:
fixes S T :: ‹'st›
assumes
‹dpll_bj S T› and
‹inv S›
‹⋀L T. undefined_lit (trail S) L ⟹ atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S)
⟹ T ∼ prepend_trail (Decided L) S
⟹ P S T› and
‹⋀C L T. add_mset L C ∈# clauses⇩N⇩O⇩T S ⟹ trail S ⊨as CNot C ⟹ undefined_lit (trail S) L
⟹ T ∼ prepend_trail (Propagated L ()) S
⟹ P S T› and
‹⋀C F' K F L C' T. C ∈# clauses⇩N⇩O⇩T S ⟹ F' @ Decided K # F ⊨as CNot C
⟹ trail S = F' @ Decided K # F
⟹ undefined_lit F L
⟹ atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (F' @ Decided K # F))
⟹ clauses⇩N⇩O⇩T S ⊨pm add_mset L C'
⟹ F ⊨as CNot C'
⟹ T ∼ prepend_trail (Propagated L ()) (reduce_trail_to⇩N⇩O⇩T F S)
⟹ P S T›
shows ‹P S T›
apply (induct T rule: dpll_bj_induct[OF local.dpll_with_backjumping_ops_axioms])
apply (rule assms(1))
using assms(3) apply blast
apply (elim propagate⇩N⇩O⇩TE) using assms(4) apply blast
apply (elim backjumpE) using assms(5) ‹inv S› by simp
subsubsection ‹Basic properties›
paragraph ‹First, some better suited induction principle›
lemma dpll_bj_clauses:
assumes ‹dpll_bj S T› and ‹inv S›
shows ‹clauses⇩N⇩O⇩T S = clauses⇩N⇩O⇩T T›
using assms by (induction rule: dpll_bj_all_induct) auto
paragraph ‹No duplicates in the trail›
lemma dpll_bj_no_dup:
assumes ‹dpll_bj S T› and ‹inv S›
and ‹no_dup (trail S)›
shows ‹no_dup (trail T)›
using assms by (induction rule: dpll_bj_all_induct)
(auto simp add: defined_lit_map reduce_trail_to⇩N⇩O⇩T_skip_beginning dest: no_dup_appendD)
paragraph ‹Valuations›
lemma dpll_bj_sat_iff:
assumes ‹dpll_bj S T› and ‹inv S›
shows ‹I ⊨sm clauses⇩N⇩O⇩T S ⟷ I ⊨sm clauses⇩N⇩O⇩T T›
using assms by (induction rule: dpll_bj_all_induct) auto
paragraph ‹Clauses›
lemma dpll_bj_atms_of_ms_clauses_inv:
assumes
‹dpll_bj S T› and
‹inv S›
shows ‹atms_of_mm (clauses⇩N⇩O⇩T S) = atms_of_mm (clauses⇩N⇩O⇩T T)›
using assms by (induction rule: dpll_bj_all_induct) auto
lemma dpll_bj_atms_in_trail:
assumes
‹dpll_bj S T› and
‹inv S› and
‹atm_of ` (lits_of_l (trail S)) ⊆ atms_of_mm (clauses⇩N⇩O⇩T S)›
shows ‹atm_of ` (lits_of_l (trail T)) ⊆ atms_of_mm (clauses⇩N⇩O⇩T S)›
using assms by (induction rule: dpll_bj_all_induct)
(auto simp: in_plus_implies_atm_of_on_atms_of_ms reduce_trail_to⇩N⇩O⇩T_skip_beginning)
lemma dpll_bj_atms_in_trail_in_set:
assumes ‹dpll_bj S T›and
‹inv S› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ A› and
‹atm_of ` (lits_of_l (trail S)) ⊆ A›
shows ‹atm_of ` (lits_of_l (trail T)) ⊆ A›
using assms by (induction rule: dpll_bj_all_induct)
(auto simp: in_plus_implies_atm_of_on_atms_of_ms)
lemma dpll_bj_all_decomposition_implies_inv:
assumes
‹dpll_bj S T› and
inv: ‹inv S› and
decomp: ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T T) (get_all_ann_decomposition (trail T))›
using assms(1,2)
proof (induction rule:dpll_bj_all_induct)
case decide⇩N⇩O⇩T
then show ?case using decomp by auto
next
case (propagate⇩N⇩O⇩T C L T) note propa = this(1) and undef = this(3) and T = this(4)
let ?M' = ‹trail (prepend_trail (Propagated L ()) S)›
let ?N = ‹clauses⇩N⇩O⇩T S›
obtain a y l where ay: ‹get_all_ann_decomposition ?M' = (a, y) # l›
by (cases ‹get_all_ann_decomposition ?M'›) fastforce+
then have M': ‹?M' = y @ a› using get_all_ann_decomposition_decomp[of ?M'] by auto
have M: ‹get_all_ann_decomposition (trail S) = (a, tl y) # l›
using ay undef by (cases ‹ get_all_ann_decomposition (trail S)›) auto
have y⇩0: ‹y = (Propagated L ()) # (tl y)›
using ay undef by (auto simp add: M)
from arg_cong[OF this, of set] have y[simp]: ‹set y = insert (Propagated L ()) (set (tl y))›
by simp
have tr_S: ‹trail S = tl y @ a›
using arg_cong[OF M', of tl] y⇩0 M get_all_ann_decomposition_decomp by force
have a_Un_N_M: ‹unmark_l a ∪ set_mset ?N ⊨ps unmark_l (tl y)›
using decomp ay unfolding all_decomposition_implies_def by (simp add: M)+
moreover have ‹unmark_l a ∪ set_mset ?N ⊨p {#L#}› (is ‹?I ⊨p _›)
proof (rule true_clss_cls_plus_CNot)
show ‹?I ⊨p add_mset L C›
using propa propagate⇩N⇩O⇩T.prems by (auto dest!: true_clss_clss_in_imp_true_clss_cls)
next
have ‹unmark_l ?M' ⊨ps CNot C›
using ‹trail S ⊨as CNot C› undef by (auto simp add: true_annots_true_clss_clss)
have a1: ‹unmark_l a ∪ unmark_l (tl y) ⊨ps CNot C›
using propagate⇩N⇩O⇩T.hyps(2) tr_S true_annots_true_clss_clss
by (force simp add: image_Un sup_commute)
then have ‹unmark_l a ∪ set_mset (clauses⇩N⇩O⇩T S) ⊨ps unmark_l a ∪ unmark_l (tl y)›
using a_Un_N_M true_clss_clss_def by blast
then show ‹unmark_l a ∪ set_mset (clauses⇩N⇩O⇩T S) ⊨ps CNot C›
using a1 by (meson true_clss_clss_left_right true_clss_clss_union_and
true_clss_clss_union_l_r)
qed
ultimately have ‹unmark_l a ∪ set_mset ?N ⊨ps unmark_l ?M'›
unfolding M' by (auto simp add: all_in_true_clss_clss image_Un)
then show ?case
using decomp T M undef unfolding ay all_decomposition_implies_def by (auto simp add: ay)
next
case (backjump C F' K F L D T) note confl = this(2) and tr = this(3) and undef = this(4) and
L = this(5) and N_C = this(6) and vars_D = this(5) and T = this(8)
have decomp: ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition F)›
using decomp unfolding tr all_decomposition_implies_def
by (metis (no_types, lifting) get_all_ann_decomposition.simps(1)
get_all_ann_decomposition_never_empty hd_Cons_tl insert_iff list.sel(3) list.set(2)
tl_get_all_ann_decomposition_skip_some)
obtain a b li where F: ‹get_all_ann_decomposition F = (a, b) # li›
by (cases ‹get_all_ann_decomposition F›) auto
have ‹F = b @ a›
using get_all_ann_decomposition_decomp[of F a b] F by auto
have a_N_b:‹unmark_l a ∪ set_mset (clauses⇩N⇩O⇩T S) ⊨ps unmark_l b›
using decomp unfolding all_decomposition_implies_def by (auto simp add: F)
have F_D: ‹unmark_l F ⊨ps CNot D›
using ‹F ⊨as CNot D› by (simp add: true_annots_true_clss_clss)
then have ‹unmark_l a ∪ unmark_l b ⊨ps CNot D›
unfolding ‹F = b @ a› by (simp add: image_Un sup.commute)
have a_N_CNot_D: ‹unmark_l a ∪ set_mset (clauses⇩N⇩O⇩T S) ⊨ps CNot D ∪ unmark_l b›
apply (rule true_clss_clss_left_right)
using a_N_b F_D unfolding ‹F = b @ a› by (auto simp add: image_Un ac_simps)
have a_N_D_L: ‹unmark_l a ∪ set_mset (clauses⇩N⇩O⇩T S) ⊨p add_mset L D›
by (simp add: N_C)
have ‹unmark_l a ∪ set_mset (clauses⇩N⇩O⇩T S) ⊨p {#L#}›
using a_N_D_L a_N_CNot_D by (blast intro: true_clss_cls_plus_CNot)
then show ?case
using decomp T tr undef unfolding all_decomposition_implies_def by (auto simp add: F)
qed
subsubsection ‹Termination›
paragraph ‹Using a proper measure›
lemma length_get_all_ann_decomposition_append_Decided:
‹length (get_all_ann_decomposition (F' @ Decided K # F)) =
length (get_all_ann_decomposition F')
+ length (get_all_ann_decomposition (Decided K # F))
- 1›
by (induction F' rule: ann_lit_list_induct) auto
lemma take_length_get_all_ann_decomposition_decided_sandwich:
‹take (length (get_all_ann_decomposition F))
(map (f o snd) (rev (get_all_ann_decomposition (F' @ Decided K # F))))
=
map (f o snd) (rev (get_all_ann_decomposition F))
›
proof (induction F' rule: ann_lit_list_induct)
case Nil
then show ?case by auto
next
case (Decided K)
then show ?case by (simp add: length_get_all_ann_decomposition_append_Decided)
next
case (Propagated L m F') note IH = this(1)
obtain a b l where F': ‹get_all_ann_decomposition (F' @ Decided K # F) = (a, b) # l›
by (cases ‹get_all_ann_decomposition (F' @ Decided K # F)›) auto
have ‹length (get_all_ann_decomposition F) - length l = 0›
using length_get_all_ann_decomposition_append_Decided[of F' K F]
unfolding F' by (cases ‹get_all_ann_decomposition F'›) auto
then show ?case
using IH by (simp add: F')
qed
lemma length_get_all_ann_decomposition_length:
‹length (get_all_ann_decomposition M) ≤ 1 + length M›
by (induction M rule: ann_lit_list_induct) auto
lemma length_in_get_all_ann_decomposition_bounded:
assumes i:‹i ∈ set (trail_weight S)›
shows ‹i ≤ Suc (length (trail S))›
proof -
obtain a b where
‹(a, b) ∈ set (get_all_ann_decomposition (trail S))› and
ib: ‹i = Suc (length b)›
using i by auto
then obtain c where ‹trail S = c @ b @ a›
using get_all_ann_decomposition_exists_prepend' by metis
from arg_cong[OF this, of length] show ?thesis using i ib by auto
qed
paragraph ‹Well-foundedness›
text ‹The bounds are the following:
▪ @{term ‹1+card (atms_of_ms A)›}: @{term ‹card (atms_of_ms A)›} is an upper bound on the length
of the list. As @{term get_all_ann_decomposition} appends an possibly empty couple at the end,
adding one is needed.
▪ @{term ‹2+card (atms_of_ms A)›}: @{term ‹card (atms_of_ms A)›} is an upper bound on the number
of elements, where adding one is necessary for the same reason as for the bound on the list, and
one is needed to have a strict bound.
›
abbreviation unassigned_lit :: ‹'b clause set ⇒ 'a list ⇒ nat› where
‹unassigned_lit N M ≡ card (atms_of_ms N) - length M›
lemma dpll_bj_trail_mes_increasing_prop:
fixes M :: ‹('v, unit) ann_lits › and N :: ‹'v clauses›
assumes
‹dpll_bj S T› and
‹inv S› and
NA: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
MA: ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
finite: ‹finite A›
shows ‹μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight T)
> μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight S)›
using assms(1,2)
proof (induction rule: dpll_bj_all_induct)
case (propagate⇩N⇩O⇩T C L T) note CLN = this(1) and MC = this(2) and undef_L = this(3) and T = this(4)
have incl: ‹atm_of ` lits_of_l (Propagated L () # trail S) ⊆ atms_of_ms A›
using propagate⇩N⇩O⇩T dpll_bj_atms_in_trail_in_set bj_propagate⇩N⇩O⇩T NA MA CLN
by (auto simp: in_plus_implies_atm_of_on_atms_of_ms)
have no_dup: ‹no_dup (Propagated L () # trail S)›
using defined_lit_map n_d undef_L by auto
obtain a b l where M: ‹get_all_ann_decomposition (trail S) = (a, b) # l›
by (cases ‹get_all_ann_decomposition (trail S)›) auto
have b_le_M: ‹length b ≤ length (trail S)›
using get_all_ann_decomposition_decomp[of ‹trail S›] by (simp add: M)
have ‹finite (atms_of_ms A)› using finite by simp
then have ‹length (Propagated L () # trail S) ≤ card (atms_of_ms A)›
using incl finite unfolding no_dup_length_eq_card_atm_of_lits_of_l[OF no_dup]
by (simp add: card_mono)
then have latm: ‹unassigned_lit A b = Suc (unassigned_lit A (Propagated L () # b))›
using b_le_M by auto
then show ?case using T undef_L by (auto simp: latm M μ⇩C_cons)
next
case (decide⇩N⇩O⇩T L) note undef_L = this(1) and MC = this(2) and T = this(3)
have incl: ‹atm_of ` lits_of_l (Decided L # (trail S)) ⊆ atms_of_ms A›
using dpll_bj_atms_in_trail_in_set bj_decide⇩N⇩O⇩T decide⇩N⇩O⇩T.decide⇩N⇩O⇩T[OF decide⇩N⇩O⇩T.hyps] NA MA MC
by auto
have no_dup: ‹no_dup (Decided L # (trail S))›
using defined_lit_map n_d undef_L by auto
obtain a b l where M: ‹get_all_ann_decomposition (trail S) = (a, b) # l›
by (cases ‹get_all_ann_decomposition (trail S)›) auto
then have ‹length (Decided L # (trail S)) ≤ card (atms_of_ms A)›
using incl finite unfolding no_dup_length_eq_card_atm_of_lits_of_l[OF no_dup]
by (simp add: card_mono)
show ?case using T undef_L by (simp add: μ⇩C_cons)
next
case (backjump C F' K F L C' T) note undef_L = this(4) and MC = this(1) and tr_S = this(3) and
L = this(5) and T = this(8)
have incl: ‹atm_of ` lits_of_l (Propagated L () # F) ⊆ atms_of_ms A›
using dpll_bj_atms_in_trail_in_set NA MA L by (auto simp: tr_S)
have no_dup: ‹no_dup (Propagated L () # F)›
using defined_lit_map n_d undef_L tr_S by (auto dest: no_dup_appendD)
obtain a b l where M: ‹get_all_ann_decomposition (trail S) = (a, b) # l›
by (cases ‹get_all_ann_decomposition (trail S)›) auto
have b_le_M: ‹length b ≤ length (trail S)›
using get_all_ann_decomposition_decomp[of ‹trail S›] by (simp add: M)
have fin_atms_A: ‹finite (atms_of_ms A)› using finite by simp
then have F_le_A: ‹length (Propagated L () # F) ≤ card (atms_of_ms A)›
using incl finite unfolding no_dup_length_eq_card_atm_of_lits_of_l[OF no_dup]
by (simp add: card_mono)
have tr_S_le_A: ‹length (trail S) ≤ card (atms_of_ms A)›
using n_d MA by (metis fin_atms_A card_mono no_dup_length_eq_card_atm_of_lits_of_l)
obtain a b l where F: ‹get_all_ann_decomposition F = (a, b) # l›
by (cases ‹get_all_ann_decomposition F›) auto
then have ‹F = b @ a›
using get_all_ann_decomposition_decomp[of ‹Propagated L () # F› a
‹Propagated L () # b›] by simp
then have latm: ‹unassigned_lit A b = Suc (unassigned_lit A (Propagated L () # b))›
using F_le_A by simp
obtain rem where
rem:‹map (λa. Suc (length (snd a))) (rev (get_all_ann_decomposition (F' @ Decided K # F)))
= map (λa. Suc (length (snd a))) (rev (get_all_ann_decomposition F)) @ rem›
using take_length_get_all_ann_decomposition_decided_sandwich[of F ‹λa. Suc (length a)› F' K]
unfolding o_def by (metis append_take_drop_id)
then have rem: ‹map (λa. Suc (length (snd a)))
(get_all_ann_decomposition (F' @ Decided K # F))
= rev rem @ map (λa. Suc (length (snd a))) ((get_all_ann_decomposition F))›
by (simp add: rev_map[symmetric] rev_swap)
have ‹length (rev rem @ map (λa. Suc (length (snd a))) (get_all_ann_decomposition F))
≤ Suc (card (atms_of_ms A))›
using arg_cong[OF rem, of length] tr_S_le_A
length_get_all_ann_decomposition_length[of ‹F' @ Decided K # F›] tr_S by auto
moreover {
{ fix i :: nat and xs :: ‹'a list›
have ‹i < length xs ⟹ length xs - Suc i < length xs›
by auto
then have H: ‹i<length xs ⟹ rev xs ! i ∈ set xs›
using rev_nth[of i xs] unfolding in_set_conv_nth by (force simp add: in_set_conv_nth)
} note H = this
have ‹∀i<length rem. rev rem ! i < card (atms_of_ms A) + 2›
using tr_S_le_A length_in_get_all_ann_decomposition_bounded[of _ S] unfolding tr_S
by (force simp add: o_def rem dest!: H intro: length_get_all_ann_decomposition_length) }
ultimately show ?case
using μ⇩C_bounded[of ‹rev rem› ‹card (atms_of_ms A)+2› ‹unassigned_lit A l›] T undef_L
by (simp add: rem μ⇩C_append μ⇩C_cons F tr_S)
qed
lemma dpll_bj_trail_mes_decreasing_prop:
assumes dpll: ‹dpll_bj S T› and inv: ‹inv S› and
N_A: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
M_A: ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
nd: ‹no_dup (trail S)› and
fin_A: ‹finite A›
shows ‹(2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A))
- μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight T)
< (2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A))
- μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight S)›
proof -
let ?b = ‹2+card (atms_of_ms A)›
let ?s = ‹1+card (atms_of_ms A)›
let ?μ = ‹μ⇩C ?s ?b›
have M'_A: ‹atm_of ` lits_of_l (trail T) ⊆ atms_of_ms A›
by (meson M_A N_A dpll dpll_bj_atms_in_trail_in_set inv)
have nd': ‹no_dup (trail T)›
using ‹dpll_bj S T› dpll_bj_no_dup nd inv by blast
{ fix i :: nat and xs :: ‹'a list›
have ‹i < length xs ⟹ length xs - Suc i < length xs›
by auto
then have H: ‹i<length xs ⟹ xs ! i ∈ set xs›
using rev_nth[of i xs] unfolding in_set_conv_nth by (force simp add: in_set_conv_nth)
} note H = this
have l_M_A: ‹length (trail S) ≤ card (atms_of_ms A)›
by (simp add: fin_A M_A card_mono no_dup_length_eq_card_atm_of_lits_of_l nd)
have l_M'_A: ‹length (trail T) ≤ card (atms_of_ms A)›
by (simp add: fin_A M'_A card_mono no_dup_length_eq_card_atm_of_lits_of_l nd')
have l_trail_weight_M: ‹length (trail_weight T) ≤ 1+card (atms_of_ms A)›
using l_M'_A length_get_all_ann_decomposition_length[of ‹trail T›] by auto
have bounded_M: ‹∀i<length (trail_weight T). (trail_weight T)! i < card (atms_of_ms A) + 2›
using length_in_get_all_ann_decomposition_bounded[of _ T] l_M'_A
by (metis (no_types, lifting) H Nat.le_trans add_2_eq_Suc' not_le not_less_eq_eq)
from dpll_bj_trail_mes_increasing_prop[OF dpll inv N_A M_A nd fin_A]
have ‹μ⇩C ?s ?b (trail_weight S) < μ⇩C ?s ?b (trail_weight T)› by simp
moreover from μ⇩C_bounded[OF bounded_M l_trail_weight_M]
have ‹μ⇩C ?s ?b (trail_weight T) ≤ ?b ^ ?s› by auto
ultimately show ?thesis by linarith
qed
lemma wf_dpll_bj:
assumes fin: ‹finite A›
shows ‹wf {(T, S). dpll_bj S T
∧ atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A ∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A
∧ no_dup (trail S) ∧ inv S}›
(is ‹wf ?A›)
proof (rule wf_bounded_measure[of _
‹λ_. (2 + card (atms_of_ms A))^(1 + card (atms_of_ms A))›
‹λS. μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight S)›])
fix a b :: ‹'st›
let ?b = ‹2+card (atms_of_ms A)›
let ?s = ‹1+card (atms_of_ms A)›
let ?μ = ‹μ⇩C ?s ?b›
assume ab: ‹(b, a) ∈ ?A›
have fin_A: ‹finite (atms_of_ms A)›
using fin by auto
have
dpll_bj: ‹dpll_bj a b› and
N_A: ‹atms_of_mm (clauses⇩N⇩O⇩T a) ⊆ atms_of_ms A› and
M_A: ‹atm_of ` lits_of_l (trail a) ⊆ atms_of_ms A› and
nd: ‹no_dup (trail a)› and
inv: ‹inv a›
using ab by auto
have M'_A: ‹atm_of ` lits_of_l (trail b) ⊆ atms_of_ms A›
by (meson M_A N_A ‹dpll_bj a b› dpll_bj_atms_in_trail_in_set inv)
have nd': ‹no_dup (trail b)›
using ‹dpll_bj a b› dpll_bj_no_dup nd inv by blast
{ fix i :: nat and xs :: ‹'a list›
have ‹i < length xs ⟹ length xs - Suc i < length xs›
by auto
then have H: ‹i<length xs ⟹ xs ! i ∈ set xs›
using rev_nth[of i xs] unfolding in_set_conv_nth by (force simp add: in_set_conv_nth)
} note H = this
have l_M_A: ‹length (trail a) ≤ card (atms_of_ms A)›
by (simp add: fin_A M_A card_mono no_dup_length_eq_card_atm_of_lits_of_l nd)
have l_M'_A: ‹length (trail b) ≤ card (atms_of_ms A)›
by (simp add: fin_A M'_A card_mono no_dup_length_eq_card_atm_of_lits_of_l nd')
have l_trail_weight_M: ‹length (trail_weight b) ≤ 1+card (atms_of_ms A)›
using l_M'_A length_get_all_ann_decomposition_length[of ‹trail b›] by auto
have bounded_M: ‹∀i<length (trail_weight b). (trail_weight b)! i < card (atms_of_ms A) + 2›
using length_in_get_all_ann_decomposition_bounded[of _ b] l_M'_A
by (metis (no_types, lifting) Nat.le_trans One_nat_def Suc_1 add.right_neutral add_Suc_right
le_imp_less_Suc less_eq_Suc_le nth_mem)
from dpll_bj_trail_mes_increasing_prop[OF dpll_bj inv N_A M_A nd fin]
have ‹μ⇩C ?s ?b (trail_weight a) < μ⇩C ?s ?b (trail_weight b)› by simp
moreover from μ⇩C_bounded[OF bounded_M l_trail_weight_M]
have ‹μ⇩C ?s ?b (trail_weight b) ≤ ?b ^ ?s› by auto
ultimately show ‹?b ^ ?s ≤ ?b ^ ?s ∧
μ⇩C ?s ?b (trail_weight b) ≤ ?b ^ ?s ∧
μ⇩C ?s ?b (trail_weight a) < μ⇩C ?s ?b (trail_weight b)›
by blast
qed
paragraph ‹Alternative termination proof›
abbreviation DPLL_mes⇩W where
‹DPLL_mes⇩W A M ≡
map (λL. if is_decided L then 2::nat else 1) (rev M) @ replicate (card A - length M) 3›
lemma distinctcard_atm_of_lit_of_eq_length:
assumes "no_dup S"
shows "card (atm_of ` lits_of_l S) = length S"
using assms by (induct S) (auto simp add: image_image lits_of_def no_dup_def)
lemma dpll_bj_trail_mes_decreasing_less_than:
assumes dpll: ‹dpll_bj S T› and inv: ‹inv S› and
N_A: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
M_A: ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
nd: ‹no_dup (trail S)› and
fin_A: ‹finite A›
shows ‹(DPLL_mes⇩W (atms_of_ms A) (trail T), DPLL_mes⇩W (atms_of_ms A) (trail S)) ∈
lexn less_than (card ((atms_of_ms A)))›
using assms(1,2)
proof (induction rule: dpll_bj_all_induct)
case (decide⇩N⇩O⇩T L T)
define n where
‹n = card (atms_of_ms A) - card (atm_of ` lits_of_l (trail S))›
have [simp]: ‹length (trail S) = card (atm_of ` lits_of_l (trail S))›
using nd by (auto simp: no_dup_def lits_of_def image_image dest: distinct_card)
have ‹atm_of L ∉ atm_of ` lits_of_l (trail S)›
by (metis decide⇩N⇩O⇩T.hyps(1) defined_lit_map imageE in_lits_of_l_defined_litD)
have ‹card (atms_of_ms A) > card (atm_of ` lits_of_l (trail S))›
by (metis N_A ‹atm_of L ∉ atm_of ` lits_of_l (trail S)› atms_of_ms_finite card_seteq decide⇩N⇩O⇩T.hyps(2)
M_A fin_A not_le subsetCE)
then have
n_0: ‹n > 0› and
n_Suc: ‹card (atms_of_ms A) - Suc (card (atm_of ` lits_of_l (trail S))) = n - 1›
unfolding n_def by auto
show ?case
using fin_A decide⇩N⇩O⇩T n_0 unfolding state_eq⇩N⇩O⇩T_trail[OF decide⇩N⇩O⇩T(3)]
by (cases n) (auto simp: prepend_same_lexn n_def[symmetric] n_Suc lexn_Suc
simp del: state_simp⇩N⇩O⇩T lexn.simps)
next
case (propagate⇩N⇩O⇩T C L T) note C = this(1) and undef = this(3) and T = this(3)
then have ‹card (atms_of_ms A) > length (trail S)›
proof -
have f7: "atm_of L ∈ atms_of_ms A"
using N_A C in_m_in_literals by blast
have "undefined_lit (trail S) (- L)"
using undef by auto
then show ?thesis
using f7 nd fin_A M_A undef by (metis atm_of_in_atm_of_set_in_uminus atms_of_ms_finite
card_seteq in_lits_of_l_defined_litD leI no_dup_length_eq_card_atm_of_lits_of_l)
qed
then show ?case
using fin_A unfolding state_eq⇩N⇩O⇩T_trail[OF propagate⇩N⇩O⇩T(4)]
by (cases ‹card (atms_of_ms A) - length (trail S)›)
(auto simp: prepend_same_lexn lexn_Suc
simp del: state_simp⇩N⇩O⇩T lexn.simps)
next
case (backjump C F' K F L C' T) note tr_S = this(3)
have ‹trail (reduce_trail_to⇩N⇩O⇩T F S) = F›
by (simp add: tr_S)
have ‹no_dup F›
using nd tr_S by (auto dest: no_dup_appendD)
then have card_A_F: ‹card (atms_of_ms A) > length F›
using distinctcard_atm_of_lit_of_eq_length[of ‹trail S›] card_mono[OF _ M_A] fin_A nd tr_S
by auto
have ‹no_dup (F' @ F)›
using nd tr_S by (auto dest: no_dup_appendD)
then have ‹no_dup F'›
apply (subst (asm) no_dup_rev[symmetric])
using nd tr_S by (auto dest: no_dup_appendD)
then have card_A_F': ‹card (atms_of_ms A) > length F' + length F›
using distinctcard_atm_of_lit_of_eq_length[of ‹trail S›] card_mono[OF _ M_A] fin_A nd tr_S
by auto
show ?case
using card_A_F card_A_F'
unfolding state_eq⇩N⇩O⇩T_trail[OF backjump(8)]
by (cases ‹card (atms_of_ms A) - length F›)
(auto simp: tr_S prepend_same_lexn lexn_Suc simp del: state_simp⇩N⇩O⇩T lexn.simps)
qed
lemma
assumes fin[simp]: ‹finite A›
shows ‹wf {(T, S). dpll_bj S T
∧ atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A ∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A
∧ no_dup (trail S) ∧ inv S}›
(is ‹wf ?A›)
unfolding conj_commute[of ‹dpll_bj _ _›]
apply (rule wf_wf_if_measure'[of _ _ _ ‹λS. DPLL_mes⇩W ((atms_of_ms A)) (trail S)›])
apply (rule wf_lexn)
apply (rule wf_less_than)
by (rule dpll_bj_trail_mes_decreasing_less_than; use fin in simp)
subsubsection ‹Normal Forms›
text ‹
We prove that given a normal form of DPLL, with some structural invariants, then either @{term N}
is satisfiable and the built valuation @{term M} is a model; or @{term N} is unsatisfiable.
Idea of the proof: We have to prove tat @{term ‹satisfiable N›}, @{term ‹¬M⊨as N›}
and there is no remaining step is incompatible.
▸ The @{term decide} rule tells us that every variable in @{term N} has a value.
▸ The assumption @{term ‹¬M⊨as N›} implies that there is conflict.
▸ There is at least one decision in the trail (otherwise, @{term M} would be a model of the set
of clauses @{term N}).
▸ Now if we build the clause with all the decision literals of the trail, we can apply the
@{term backjump} rule.
The assumption are saying that we have a finite upper bound @{term A} for the literals, that we
cannot do any step @{term ‹no_step dpll_bj S›}›
theorem dpll_backjump_final_state:
fixes A :: ‹'v clause set› and S T :: ‹'st›
assumes
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
‹no_dup (trail S)› and
‹finite A› and
inv: ‹inv S› and
n_d: ‹no_dup (trail S)› and
n_s: ‹no_step dpll_bj S› and
decomp: ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T S))
∨ (trail S ⊨asm clauses⇩N⇩O⇩T S ∧ satisfiable (set_mset (clauses⇩N⇩O⇩T S)))›
proof -
let ?N = ‹set_mset (clauses⇩N⇩O⇩T S)›
let ?M = ‹trail S›
consider
(sat) ‹satisfiable ?N› and ‹?M ⊨as ?N›
| (sat') ‹satisfiable ?N› and ‹¬ ?M ⊨as ?N›
| (unsat) ‹unsatisfiable ?N›
by auto
then show ?thesis
proof cases
case sat' note sat = this(1) and M = this(2)
obtain C where ‹C ∈ ?N› and ‹¬?M ⊨a C› using M unfolding true_annots_def by auto
obtain I :: ‹'v literal set› where
‹I ⊨s ?N› and
cons: ‹consistent_interp I› and
tot: ‹total_over_m I ?N› and
atm_I_N: ‹atm_of `I ⊆ atms_of_ms ?N›
using sat unfolding satisfiable_def_min by auto
let ?I = ‹I ∪ {P| P. P ∈ lits_of_l ?M ∧ atm_of P ∉ atm_of ` I}›
let ?O = ‹{unmark L |L. is_decided L ∧ L ∈ set ?M ∧ atm_of (lit_of L) ∉ atms_of_ms ?N}›
have cons_I': ‹consistent_interp ?I›
using cons using ‹no_dup ?M› unfolding consistent_interp_def
by (auto simp add: atm_of_in_atm_of_set_iff_in_set_or_uminus_in_set lits_of_def
dest!: no_dup_cannot_not_lit_and_uminus)
have tot_I': ‹total_over_m ?I (?N ∪ unmark_l ?M)›
using tot atm_I_N unfolding total_over_m_def total_over_set_def
by (fastforce simp: image_iff lits_of_def)
have ‹{P |P. P ∈ lits_of_l ?M ∧ atm_of P ∉ atm_of ` I} ⊨s ?O›
using ‹I⊨s ?N› atm_I_N by (auto simp add: atm_of_eq_atm_of true_clss_def lits_of_def)
then have I'_N: ‹?I ⊨s ?N ∪ ?O›
using ‹I⊨s ?N› true_clss_union_increase by force
have tot': ‹total_over_m ?I (?N∪?O)›
using atm_I_N tot unfolding total_over_m_def total_over_set_def
by (force simp: lits_of_def elim!: is_decided_ex_Decided)
have atms_N_M: ‹atms_of_ms ?N ⊆ atm_of ` lits_of_l ?M›
proof (rule ccontr)
assume ‹¬ ?thesis›
then obtain l :: 'v where
l_N: ‹l ∈ atms_of_ms ?N› and
l_M: ‹l ∉ atm_of ` lits_of_l ?M›
by auto
have ‹undefined_lit ?M (Pos l)›
using l_M by (metis Decided_Propagated_in_iff_in_lits_of_l
atm_of_in_atm_of_set_iff_in_set_or_uminus_in_set literal.sel(1))
then show False
using l_N n_s can_propagate_or_decide_or_backjump[of ‹Pos l› S] inv n_d sat
by (auto dest: dpll_bj.intros)
qed
have ‹?M ⊨as CNot C›
apply (rule all_variables_defined_not_imply_cnot)
using ‹C ∈ set_mset (clauses⇩N⇩O⇩T S)› ‹¬ trail S ⊨a C›
atms_N_M by (auto dest: atms_of_atms_of_ms_mono)
have ‹∃l ∈ set ?M. is_decided l›
proof (rule ccontr)
let ?O = ‹{unmark L |L. is_decided L ∧ L ∈ set ?M ∧ atm_of (lit_of L) ∉ atms_of_ms ?N}›
have θ[iff]: ‹⋀I. total_over_m I (?N ∪ ?O ∪ unmark_l ?M)
⟷ total_over_m I (?N ∪unmark_l ?M)›
unfolding total_over_set_def total_over_m_def atms_of_ms_def by blast
assume ‹¬ ?thesis›
then have [simp]:‹{unmark L |L. is_decided L ∧ L ∈ set ?M}
= {unmark L |L. is_decided L ∧ L ∈ set ?M ∧ atm_of (lit_of L) ∉ atms_of_ms ?N}›
by auto
then have ‹?N ∪ ?O ⊨ps unmark_l ?M›
using all_decomposition_implies_propagated_lits_are_implied[OF decomp] by auto
then have ‹?I ⊨s unmark_l ?M›
using cons_I' I'_N tot_I' ‹?I ⊨s ?N ∪ ?O› unfolding θ true_clss_clss_def by blast
then have ‹lits_of_l ?M ⊆ ?I›
unfolding true_clss_def lits_of_def by auto
then have ‹?M ⊨as ?N›
using I'_N ‹C ∈ ?N› ‹¬ ?M ⊨a C› cons_I' atms_N_M
by (meson ‹trail S ⊨as CNot C› consistent_CNot_not rev_subsetD sup_ge1 true_annot_def
true_annots_def true_cls_mono_set_mset_l true_clss_def)
then show False using M by fast
qed
from List.split_list_first_propE[OF this] obtain K :: ‹'v literal› and
F F' :: ‹('v, unit) ann_lits› where
M_K: ‹?M = F' @ Decided K # F› and
nm: ‹∀f∈set F'. ¬is_decided f›
by (metis (full_types) is_decided_ex_Decided old.unit.exhaust)
let ?K = ‹Decided K :: ('v, unit) ann_lit›
have ‹?K ∈ set ?M›
unfolding M_K by auto
let ?C = ‹image_mset lit_of {#L∈#mset ?M. is_decided L ∧ L≠?K#} :: 'v clause›
let ?C' = ‹set_mset (image_mset (λL::'v literal. {#L#}) (?C + unmark ?K))›
have ‹?N ∪ {unmark L |L. is_decided L ∧ L ∈ set ?M} ⊨ps unmark_l ?M›
using all_decomposition_implies_propagated_lits_are_implied[OF decomp] .
moreover have C': ‹?C' = {unmark L |L. is_decided L ∧ L ∈ set ?M}›
unfolding M_K by standard force+
ultimately have N_C_M: ‹?N ∪ ?C' ⊨ps unmark_l ?M›
by auto
have N_M_False: ‹?N ∪ (λL. unmark L) ` (set ?M) ⊨ps {{#}}›
unfolding true_clss_clss_def true_annots_def Ball_def true_annot_def
proof (intro allI impI)
fix LL :: "'v literal set"
assume
tot: ‹total_over_m LL (set_mset (clauses⇩N⇩O⇩T S) ∪ unmark_l (trail S) ∪ {{#}})› and
cons: ‹consistent_interp LL› and
LL: ‹LL ⊨s set_mset (clauses⇩N⇩O⇩T S) ∪ unmark_l (trail S)›
have ‹total_over_m LL (CNot C)›
by (metis ‹C ∈# clauses⇩N⇩O⇩T S› insert_absorb tot total_over_m_CNot_toal_over_m
total_over_m_insert total_over_m_union)
then have "total_over_m LL (unmark_l (trail S) ∪ CNot C)"
using tot by force
then show "LL ⊨s {{#}}"
using tot cons LL
by (metis (no_types) ‹C ∈# clauses⇩N⇩O⇩T S› ‹trail S ⊨as CNot C› consistent_CNot_not
true_annots_true_clss_clss true_clss_clss_def true_clss_def true_clss_union)
qed
have ‹undefined_lit F K› using ‹no_dup ?M› unfolding M_K by (auto simp: defined_lit_map)
moreover {
have ‹?N ∪ ?C' ⊨ps {{#}}›
proof -
have A: ‹?N ∪ ?C' ∪ unmark_l ?M = ?N ∪ unmark_l ?M›
unfolding M_K by auto
show ?thesis
using true_clss_clss_left_right[OF N_C_M, of ‹{{#}}›] N_M_False unfolding A by auto
qed
have ‹?N ⊨p image_mset uminus ?C + {#-K#}›
unfolding true_clss_cls_def true_clss_clss_def total_over_m_def
proof (intro allI impI)
fix I
assume
tot: ‹total_over_set I (atms_of_ms (?N ∪ {image_mset uminus ?C+ {#- K#}}))› and
cons: ‹consistent_interp I› and
‹I ⊨s ?N›
have ‹(K ∈ I ∧ -K ∉ I) ∨ (-K ∈ I ∧ K ∉ I)›
using cons tot unfolding consistent_interp_def by (cases K) auto
have ‹ {a ∈ set (trail S). is_decided a ∧ a ≠ Decided K} =
set (trail S) ∩ {L. is_decided L ∧ L ≠ Decided K}›
by auto
then have tot': ‹total_over_set I
(atm_of ` lit_of ` (set ?M ∩ {L. is_decided L ∧ L ≠ Decided K}))›
using tot by (auto simp add: atms_of_uminus_lit_atm_of_lit_of)
{ fix x :: ‹('v, unit) ann_lit›
assume
a3: ‹lit_of x ∉ I› and
a1: ‹x ∈ set ?M› and
a4: ‹is_decided x› and
a5: ‹x ≠ Decided K›
then have ‹Pos (atm_of (lit_of x)) ∈ I ∨ Neg (atm_of (lit_of x)) ∈ I›
using a5 a4 tot' a1 unfolding total_over_set_def atms_of_s_def by blast
moreover have f6: ‹Neg (atm_of (lit_of x)) = - Pos (atm_of (lit_of x))›
by simp
ultimately have ‹- lit_of x ∈ I›
using f6 a3 by (metis (no_types) atm_of_in_atm_of_set_iff_in_set_or_uminus_in_set
literal.sel(1))
} note H = this
have ‹¬I ⊨s ?C'›
using ‹?N ∪ ?C' ⊨ps {{#}}› tot cons ‹I ⊨s ?N›
unfolding true_clss_clss_def total_over_m_def
by (simp add: atms_of_uminus_lit_atm_of_lit_of atms_of_ms_single_image_atm_of_lit_of)
then show ‹I ⊨ image_mset uminus ?C + {#- K#}›
unfolding true_clss_def true_cls_def using ‹(K ∈ I ∧ -K ∉ I) ∨ (-K ∈ I ∧ K ∉ I)›
by (auto dest!: H)
qed }
moreover have ‹F ⊨as CNot (image_mset uminus ?C)›
using nm unfolding true_annots_def CNot_def M_K by (auto simp add: lits_of_def)
ultimately have False
using bj_can_jump[of S F' K F C ‹-K›
‹image_mset uminus (image_mset lit_of {# L :# mset ?M. is_decided L ∧ L ≠ Decided K#})›]
‹C∈?N› n_s ‹?M ⊨as CNot C› bj_backjump inv ‹no_dup (trail S)› sat
unfolding M_K by auto
then show ?thesis by fast
qed auto
qed
end
locale dpll_with_backjumping =
dpll_with_backjumping_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T inv
decide_conds backjump_conds propagate_conds
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
inv :: ‹'st ⇒ bool› and
decide_conds :: ‹'st ⇒ 'st ⇒ bool› and
backjump_conds :: ‹'v clause ⇒ 'v clause ⇒ 'v literal ⇒ 'st ⇒ 'st ⇒ bool› and
propagate_conds :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st ⇒ bool›
+
assumes dpll_bj_inv: ‹⋀S T. dpll_bj S T ⟹ inv S ⟹ inv T›
begin
lemma rtranclp_dpll_bj_inv:
assumes ‹dpll_bj⇧*⇧* S T› and ‹inv S›
shows ‹inv T›
using assms by (induction rule: rtranclp_induct)
(auto simp add: dpll_bj_no_dup intro: dpll_bj_inv)
lemma rtranclp_dpll_bj_no_dup:
assumes ‹dpll_bj⇧*⇧* S T› and ‹inv S›
and ‹no_dup (trail S)›
shows ‹no_dup (trail T)›
using assms by (induction rule: rtranclp_induct)
(auto simp add: dpll_bj_no_dup dest: rtranclp_dpll_bj_inv dpll_bj_inv)
lemma rtranclp_dpll_bj_atms_of_ms_clauses_inv:
assumes
‹dpll_bj⇧*⇧* S T› and ‹inv S›
shows ‹atms_of_mm (clauses⇩N⇩O⇩T S) = atms_of_mm (clauses⇩N⇩O⇩T T)›
using assms by (induction rule: rtranclp_induct)
(auto dest: rtranclp_dpll_bj_inv dpll_bj_atms_of_ms_clauses_inv)
lemma rtranclp_dpll_bj_atms_in_trail:
assumes
‹dpll_bj⇧*⇧* S T› and
‹inv S› and
‹atm_of ` (lits_of_l (trail S)) ⊆ atms_of_mm (clauses⇩N⇩O⇩T S)›
shows ‹atm_of ` (lits_of_l (trail T)) ⊆ atms_of_mm (clauses⇩N⇩O⇩T T)›
using assms apply (induction rule: rtranclp_induct)
using dpll_bj_atms_in_trail dpll_bj_atms_of_ms_clauses_inv rtranclp_dpll_bj_inv by auto
lemma rtranclp_dpll_bj_sat_iff:
assumes ‹dpll_bj⇧*⇧* S T› and ‹inv S›
shows ‹I ⊨sm clauses⇩N⇩O⇩T S ⟷ I ⊨sm clauses⇩N⇩O⇩T T›
using assms by (induction rule: rtranclp_induct)
(auto dest!: dpll_bj_sat_iff simp: rtranclp_dpll_bj_inv)
lemma rtranclp_dpll_bj_atms_in_trail_in_set:
assumes
‹dpll_bj⇧*⇧* S T› and
‹inv S›
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ A› and
‹atm_of ` (lits_of_l (trail S)) ⊆ A›
shows ‹atm_of ` (lits_of_l (trail T)) ⊆ A›
using assms by (induction rule: rtranclp_induct)
(auto dest: rtranclp_dpll_bj_inv
simp: dpll_bj_atms_in_trail_in_set rtranclp_dpll_bj_atms_of_ms_clauses_inv rtranclp_dpll_bj_inv)
lemma rtranclp_dpll_bj_all_decomposition_implies_inv:
assumes
‹dpll_bj⇧*⇧* S T› and
‹inv S›
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T T) (get_all_ann_decomposition (trail T))›
using assms by (induction rule: rtranclp_induct)
(auto intro: dpll_bj_all_decomposition_implies_inv simp: rtranclp_dpll_bj_inv)
lemma rtranclp_dpll_bj_inv_incl_dpll_bj_inv_trancl:
‹{(T, S). dpll_bj⇧+⇧+ S T
∧ atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A ∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A
∧ no_dup (trail S) ∧ inv S}
⊆ {(T, S). dpll_bj S T ∧ atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A
∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A ∧ no_dup (trail S) ∧ inv S}⇧+›
(is ‹?A ⊆ ?B⇧+›)
proof standard
fix x
assume x_A: ‹x ∈ ?A›
obtain S T::‹'st› where
x[simp]: ‹x = (T, S)› by (cases x) auto
have
‹dpll_bj⇧+⇧+ S T› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
‹no_dup (trail S)› and
‹inv S›
using x_A by auto
then show ‹x ∈ ?B⇧+› unfolding x
proof (induction rule: tranclp_induct)
case base
then show ?case by auto
next
case (step T U) note step = this(1) and ST = this(2) and IH = this(3)[OF this(4-7)]
and N_A = this(4) and M_A = this(5) and nd = this(6) and inv = this(7)
have [simp]: ‹atms_of_mm (clauses⇩N⇩O⇩T S) = atms_of_mm (clauses⇩N⇩O⇩T T)›
using step rtranclp_dpll_bj_atms_of_ms_clauses_inv tranclp_into_rtranclp inv by fastforce
have ‹no_dup (trail T)›
using local.step nd rtranclp_dpll_bj_no_dup tranclp_into_rtranclp inv by fastforce
moreover have ‹atm_of ` (lits_of_l (trail T)) ⊆ atms_of_ms A›
by (metis inv M_A N_A local.step rtranclp_dpll_bj_atms_in_trail_in_set
tranclp_into_rtranclp)
moreover have ‹inv T›
using inv local.step rtranclp_dpll_bj_inv tranclp_into_rtranclp by fastforce
ultimately have ‹(U, T) ∈ ?B› using ST N_A M_A inv by auto
then show ?case using IH by (rule trancl_into_trancl2)
qed
qed
lemma wf_tranclp_dpll_bj:
assumes fin: ‹finite A›
shows ‹wf {(T, S). dpll_bj⇧+⇧+ S T
∧ atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A ∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A
∧ no_dup (trail S) ∧ inv S}›
using wf_trancl[OF wf_dpll_bj[OF fin]] rtranclp_dpll_bj_inv_incl_dpll_bj_inv_trancl
by (rule wf_subset)
lemma dpll_bj_sat_ext_iff:
‹dpll_bj S T ⟹ inv S ⟹ I⊨sextm clauses⇩N⇩O⇩T S ⟷ I⊨sextm clauses⇩N⇩O⇩T T›
by (simp add: dpll_bj_clauses)
lemma rtranclp_dpll_bj_sat_ext_iff:
‹dpll_bj⇧*⇧* S T ⟹ inv S ⟹ I⊨sextm clauses⇩N⇩O⇩T S ⟷ I⊨sextm clauses⇩N⇩O⇩T T›
by (induction rule: rtranclp_induct) (simp_all add: rtranclp_dpll_bj_inv dpll_bj_sat_ext_iff)
theorem full_dpll_backjump_final_state:
fixes A :: ‹'v clause set› and S T :: ‹'st›
assumes
full: ‹full dpll_bj S T› and
atms_S: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
atms_trail: ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
‹finite A› and
inv: ‹inv S› and
decomp: ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T S))
∨ (trail T ⊨asm clauses⇩N⇩O⇩T S ∧ satisfiable (set_mset (clauses⇩N⇩O⇩T S)))›
proof -
have st: ‹dpll_bj⇧*⇧* S T› and ‹no_step dpll_bj T›
using full unfolding full_def by fast+
moreover have ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_ms A›
using atms_S inv rtranclp_dpll_bj_atms_of_ms_clauses_inv st by blast
moreover have ‹atm_of ` lits_of_l (trail T) ⊆ atms_of_ms A›
using atms_S atms_trail inv rtranclp_dpll_bj_atms_in_trail_in_set st by auto
moreover have ‹no_dup (trail T)›
using n_d inv rtranclp_dpll_bj_no_dup st by blast
moreover have inv: ‹inv T›
using inv rtranclp_dpll_bj_inv st by blast
moreover
have decomp: ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T T) (get_all_ann_decomposition (trail T))›
using ‹inv S› decomp rtranclp_dpll_bj_all_decomposition_implies_inv st by blast
ultimately have ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T T))
∨ (trail T ⊨asm clauses⇩N⇩O⇩T T ∧ satisfiable (set_mset (clauses⇩N⇩O⇩T T)))›
using ‹finite A› dpll_backjump_final_state by force
then show ?thesis
by (meson ‹inv S› rtranclp_dpll_bj_sat_iff satisfiable_carac st true_annots_true_cls)
qed
corollary full_dpll_backjump_final_state_from_init_state:
fixes A :: ‹'v clause set› and S T :: ‹'st›
assumes
full: ‹full dpll_bj S T› and
‹trail S = []› and
‹clauses⇩N⇩O⇩T S = N› and
‹inv S›
shows ‹unsatisfiable (set_mset N) ∨ (trail T ⊨asm N ∧ satisfiable (set_mset N))›
using assms full_dpll_backjump_final_state[of S T ‹set_mset N›] by auto
lemma tranclp_dpll_bj_trail_mes_decreasing_prop:
assumes dpll: ‹dpll_bj⇧+⇧+ S T› and inv: ‹inv S› and
N_A: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
M_A: ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
fin_A: ‹finite A›
shows ‹(2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A))
- μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight T)
< (2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A))
- μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight S)›
using dpll
proof induction
case base
then show ?case
using N_A M_A n_d dpll_bj_trail_mes_decreasing_prop fin_A inv by blast
next
case (step T U) note st = this(1) and dpll = this(2) and IH = this(3)
have ‹atms_of_mm (clauses⇩N⇩O⇩T S) = atms_of_mm (clauses⇩N⇩O⇩T T)›
using rtranclp_dpll_bj_atms_of_ms_clauses_inv by (metis dpll_bj_clauses dpll_bj_inv inv st
tranclpD)
then have N_A': ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_ms A›
using N_A by auto
moreover have M_A': ‹atm_of ` lits_of_l (trail T) ⊆ atms_of_ms A›
by (meson M_A N_A inv rtranclp_dpll_bj_atms_in_trail_in_set st dpll
tranclp.r_into_trancl tranclp_into_rtranclp tranclp_trans)
moreover have nd: ‹no_dup (trail T)›
by (metis inv n_d rtranclp_dpll_bj_no_dup st tranclp_into_rtranclp)
moreover have ‹inv T›
by (meson dpll dpll_bj_inv inv rtranclp_dpll_bj_inv st tranclp_into_rtranclp)
ultimately show ?case
using IH dpll_bj_trail_mes_decreasing_prop[of T U A] dpll fin_A by linarith
qed
end
subsection ‹CDCL›
text ‹In this section we will now define the conflict driven clause learning above DPLL: we first
introduce the rules learn and forget, and the add these rules to the DPLL calculus.›
subsubsection ‹Learn and Forget›
text ‹Learning adds a new clause where all the literals are already included in the clauses.›
locale learn_ops =
dpll_state trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› +
fixes
learn_conds :: ‹'v clause ⇒ 'st ⇒ bool›
begin
inductive learn :: ‹'st ⇒ 'st ⇒ bool› where
learn⇩N⇩O⇩T_rule: ‹clauses⇩N⇩O⇩T S ⊨pm C ⟹
atms_of C ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S)) ⟹
learn_conds C S ⟹
T ∼ add_cls⇩N⇩O⇩T C S ⟹
learn S T›
inductive_cases learn⇩N⇩O⇩TE: ‹learn S T›
lemma learn_μ⇩C_stable:
assumes ‹learn S T› and ‹no_dup (trail S)›
shows ‹μ⇩C A B (trail_weight S) = μ⇩C A B (trail_weight T)›
using assms by (auto elim: learn⇩N⇩O⇩TE)
end
text ‹Forget removes an information that can be deduced from the context (e.g.\ redundant clauses,
tautologies)›
locale forget_ops =
dpll_state trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› +
fixes
forget_conds :: ‹'v clause ⇒ 'st ⇒ bool›
begin
inductive forget⇩N⇩O⇩T :: ‹'st ⇒ 'st ⇒ bool› where
forget⇩N⇩O⇩T:
‹removeAll_mset C(clauses⇩N⇩O⇩T S) ⊨pm C ⟹
forget_conds C S ⟹
C ∈# clauses⇩N⇩O⇩T S ⟹
T ∼ remove_cls⇩N⇩O⇩T C S ⟹
forget⇩N⇩O⇩T S T›
inductive_cases forget⇩N⇩O⇩TE: ‹forget⇩N⇩O⇩T S T›
lemma forget_μ⇩C_stable:
assumes ‹forget⇩N⇩O⇩T S T›
shows ‹μ⇩C A B (trail_weight S) = μ⇩C A B (trail_weight T)›
using assms by (auto elim!: forget⇩N⇩O⇩TE)
end
locale learn_and_forget⇩N⇩O⇩T =
learn_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T learn_conds +
forget_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T forget_conds
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
learn_conds forget_conds :: ‹'v clause ⇒ 'st ⇒ bool›
begin
inductive learn_and_forget⇩N⇩O⇩T :: ‹'st ⇒ 'st ⇒ bool›
where
lf_learn: ‹learn S T ⟹ learn_and_forget⇩N⇩O⇩T S T› |
lf_forget: ‹forget⇩N⇩O⇩T S T ⟹ learn_and_forget⇩N⇩O⇩T S T›
end
subsubsection ‹Definition of CDCL›
locale conflict_driven_clause_learning_ops =
dpll_with_backjumping_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
inv decide_conds backjump_conds propagate_conds +
learn_and_forget⇩N⇩O⇩T trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T learn_conds
forget_conds
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
inv :: ‹'st ⇒ bool› and
decide_conds :: ‹'st ⇒ 'st ⇒ bool› and
backjump_conds :: ‹'v clause ⇒ 'v clause ⇒ 'v literal ⇒ 'st ⇒ 'st ⇒ bool› and
propagate_conds :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st ⇒ bool› and
learn_conds forget_conds :: ‹'v clause ⇒ 'st ⇒ bool›
begin
inductive cdcl⇩N⇩O⇩T :: ‹'st ⇒ 'st ⇒ bool› for S :: 'st where
c_dpll_bj: ‹dpll_bj S S' ⟹ cdcl⇩N⇩O⇩T S S'› |
c_learn: ‹learn S S' ⟹ cdcl⇩N⇩O⇩T S S'› |
c_forget⇩N⇩O⇩T: ‹forget⇩N⇩O⇩T S S' ⟹ cdcl⇩N⇩O⇩T S S'›
lemma cdcl⇩N⇩O⇩T_all_induct[consumes 1, case_names dpll_bj learn forget⇩N⇩O⇩T]:
fixes S T :: ‹'st›
assumes ‹cdcl⇩N⇩O⇩T S T› and
dpll: ‹⋀T. dpll_bj S T ⟹ P S T› and
learning:
‹⋀C T. clauses⇩N⇩O⇩T S ⊨pm C ⟹
atms_of C ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S)) ⟹
T ∼ add_cls⇩N⇩O⇩T C S ⟹
P S T› and
forgetting: ‹⋀C T. removeAll_mset C (clauses⇩N⇩O⇩T S) ⊨pm C ⟹
C ∈# clauses⇩N⇩O⇩T S ⟹
T ∼ remove_cls⇩N⇩O⇩T C S ⟹
P S T›
shows ‹P S T›
using assms(1) by (induction rule: cdcl⇩N⇩O⇩T.induct)
(auto intro: assms(2, 3, 4) elim!: learn⇩N⇩O⇩TE forget⇩N⇩O⇩TE)+
lemma cdcl⇩N⇩O⇩T_no_dup:
assumes
‹cdcl⇩N⇩O⇩T S T› and
‹inv S› and
‹no_dup (trail S)›
shows ‹no_dup (trail T)›
using assms by (induction rule: cdcl⇩N⇩O⇩T_all_induct) (auto intro: dpll_bj_no_dup)
paragraph ‹Consistency of the trail›
lemma cdcl⇩N⇩O⇩T_consistent:
assumes
‹cdcl⇩N⇩O⇩T S T› and
‹inv S› and
‹no_dup (trail S)›
shows ‹consistent_interp (lits_of_l (trail T))›
using cdcl⇩N⇩O⇩T_no_dup[OF assms] distinct_consistent_interp by fast
text ‹The subtle problem here is that tautologies can be removed, meaning that some variable can
disappear of the problem. It is also means that some variable of the trail might not be present
in the clauses anymore.›
lemma cdcl⇩N⇩O⇩T_atms_of_ms_clauses_decreasing:
assumes ‹cdcl⇩N⇩O⇩T S T›and ‹inv S›
shows ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))›
using assms by (induction rule: cdcl⇩N⇩O⇩T_all_induct)
(auto dest!: dpll_bj_atms_of_ms_clauses_inv set_mp simp add: atms_of_ms_def Union_eq)
lemma cdcl⇩N⇩O⇩T_atms_in_trail:
assumes ‹cdcl⇩N⇩O⇩T S T›and ‹inv S›
and ‹atm_of ` (lits_of_l (trail S)) ⊆ atms_of_mm (clauses⇩N⇩O⇩T S)›
shows ‹atm_of ` (lits_of_l (trail T)) ⊆ atms_of_mm (clauses⇩N⇩O⇩T S)›
using assms by (induction rule: cdcl⇩N⇩O⇩T_all_induct) (auto simp add: dpll_bj_atms_in_trail)
lemma cdcl⇩N⇩O⇩T_atms_in_trail_in_set:
assumes
‹cdcl⇩N⇩O⇩T S T› and ‹inv S› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ A› and
‹atm_of ` (lits_of_l (trail S)) ⊆ A›
shows ‹atm_of ` (lits_of_l (trail T)) ⊆ A›
using assms
by (induction rule: cdcl⇩N⇩O⇩T_all_induct)
(simp_all add: dpll_bj_atms_in_trail_in_set dpll_bj_atms_of_ms_clauses_inv)
lemma cdcl⇩N⇩O⇩T_all_decomposition_implies:
assumes ‹cdcl⇩N⇩O⇩T S T› and ‹inv S› and
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T T) (get_all_ann_decomposition (trail T))›
using assms(1,2,3)
proof (induction rule: cdcl⇩N⇩O⇩T_all_induct)
case dpll_bj
then show ?case
using dpll_bj_all_decomposition_implies_inv by blast
next
case learn
then show ?case by (auto simp add: all_decomposition_implies_def)
next
case (forget⇩N⇩O⇩T C T) note cls_C = this(1) and C = this(2) and T = this(3) and inv = this(4) and
decomp = this(5)
show ?case
unfolding all_decomposition_implies_def Ball_def
proof (intro allI, clarify)
fix a b
assume ‹(a, b) ∈ set (get_all_ann_decomposition (trail T))›
then have ‹unmark_l a ∪ set_mset (clauses⇩N⇩O⇩T S) ⊨ps unmark_l b›
using decomp T by (auto simp add: all_decomposition_implies_def)
moreover
have a1:‹C ∈ set_mset (clauses⇩N⇩O⇩T S)›
using C by blast
have ‹clauses⇩N⇩O⇩T T = clauses⇩N⇩O⇩T (remove_cls⇩N⇩O⇩T C S)›
using T state_eq⇩N⇩O⇩T_clauses by blast
then have ‹set_mset (clauses⇩N⇩O⇩T T) ⊨ps set_mset (clauses⇩N⇩O⇩T S)›
using a1 by (metis (no_types) clauses_remove_cls⇩N⇩O⇩T cls_C insert_Diff order_refl
set_mset_minus_replicate_mset(1) true_clss_clss_def true_clss_clss_insert)
ultimately show ‹unmark_l a ∪ set_mset (clauses⇩N⇩O⇩T T)
⊨ps unmark_l b›
using true_clss_clss_generalise_true_clss_clss by blast
qed
qed
paragraph ‹Extension of models›
lemma cdcl⇩N⇩O⇩T_bj_sat_ext_iff:
assumes ‹cdcl⇩N⇩O⇩T S T›and ‹inv S›
shows ‹I⊨sextm clauses⇩N⇩O⇩T S ⟷ I⊨sextm clauses⇩N⇩O⇩T T›
using assms
proof (induction rule:cdcl⇩N⇩O⇩T_all_induct)
case dpll_bj
then show ?case by (simp add: dpll_bj_clauses)
next
case (learn C T) note T = this(3)
{ fix J
assume
‹I ⊨sextm clauses⇩N⇩O⇩T S› and
‹I ⊆ J› and
tot: ‹total_over_m J (set_mset (add_mset C (clauses⇩N⇩O⇩T S)))› and
cons: ‹consistent_interp J›
then have ‹J ⊨sm clauses⇩N⇩O⇩T S› unfolding true_clss_ext_def by auto
moreover
with ‹clauses⇩N⇩O⇩T S⊨pm C› have ‹J ⊨ C›
using tot cons unfolding true_clss_cls_def by auto
ultimately have ‹J ⊨sm {#C#} + clauses⇩N⇩O⇩T S› by auto
}
then have H: ‹I ⊨sextm (clauses⇩N⇩O⇩T S) ⟹ I ⊨sext insert C (set_mset (clauses⇩N⇩O⇩T S))›
unfolding true_clss_ext_def by auto
show ?case
apply standard
using T apply (auto simp add: H)[]
using T apply simp
by (metis Diff_insert_absorb insert_subset subsetI subset_antisym
true_clss_ext_decrease_right_remove_r)
next
case (forget⇩N⇩O⇩T C T) note cls_C = this(1) and T = this(3)
{ fix J
assume
‹I ⊨sext set_mset (clauses⇩N⇩O⇩T S) - {C}› and
‹I ⊆ J› and
tot: ‹total_over_m J (set_mset (clauses⇩N⇩O⇩T S))› and
cons: ‹consistent_interp J›
then have ‹J ⊨s set_mset (clauses⇩N⇩O⇩T S) - {C}›
unfolding true_clss_ext_def by (meson Diff_subset total_over_m_subset)
moreover
with cls_C have ‹J ⊨ C›
using tot cons unfolding true_clss_cls_def
by (metis Un_commute forget⇩N⇩O⇩T.hyps(2) insert_Diff insert_is_Un order_refl
set_mset_minus_replicate_mset(1))
ultimately have ‹J ⊨sm (clauses⇩N⇩O⇩T S)› by (metis insert_Diff_single true_clss_insert)
}
then have H: ‹I ⊨sext set_mset (clauses⇩N⇩O⇩T S) - {C} ⟹ I ⊨sextm (clauses⇩N⇩O⇩T S)›
unfolding true_clss_ext_def by blast
show ?case using T by (auto simp: true_clss_ext_decrease_right_remove_r H)
qed
end
subsubsection ‹CDCL with invariant›
locale conflict_driven_clause_learning =
conflict_driven_clause_learning_ops +
assumes cdcl⇩N⇩O⇩T_inv: ‹⋀S T. cdcl⇩N⇩O⇩T S T ⟹ inv S ⟹ inv T›
begin
sublocale dpll_with_backjumping
apply unfold_locales
using cdcl⇩N⇩O⇩T.simps cdcl⇩N⇩O⇩T_inv by auto
lemma rtranclp_cdcl⇩N⇩O⇩T_inv:
‹cdcl⇩N⇩O⇩T⇧*⇧* S T ⟹ inv S ⟹ inv T›
by (induction rule: rtranclp_induct) (auto simp add: cdcl⇩N⇩O⇩T_inv)
lemma rtranclp_cdcl⇩N⇩O⇩T_no_dup:
assumes ‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and ‹inv S›
and ‹no_dup (trail S)›
shows ‹no_dup (trail T)›
using assms by (induction rule: rtranclp_induct) (auto intro: cdcl⇩N⇩O⇩T_no_dup rtranclp_cdcl⇩N⇩O⇩T_inv)
lemma rtranclp_cdcl⇩N⇩O⇩T_trail_clauses_bound:
assumes
cdcl: ‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and
inv: ‹inv S› and
atms_clauses_S: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ A› and
atms_trail_S: ‹atm_of `(lits_of_l (trail S)) ⊆ A›
shows ‹atm_of ` (lits_of_l (trail T)) ⊆ A ∧ atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ A›
using cdcl
proof (induction rule: rtranclp_induct)
case base
then show ?case using atms_clauses_S atms_trail_S by simp
next
case (step T U) note st = this(1) and cdcl⇩N⇩O⇩T = this(2) and IH = this(3)
have ‹inv T› using inv st rtranclp_cdcl⇩N⇩O⇩T_inv by blast
have ‹atms_of_mm (clauses⇩N⇩O⇩T U) ⊆ A›
using cdcl⇩N⇩O⇩T_atms_of_ms_clauses_decreasing[OF cdcl⇩N⇩O⇩T] IH ‹inv T› by fast
moreover
have ‹atm_of `(lits_of_l (trail U)) ⊆ A›
using cdcl⇩N⇩O⇩T_atms_in_trail_in_set[OF cdcl⇩N⇩O⇩T, of A]
by (meson atms_trail_S atms_clauses_S IH ‹inv T› cdcl⇩N⇩O⇩T )
ultimately show ?case by fast
qed
lemma rtranclp_cdcl⇩N⇩O⇩T_all_decomposition_implies:
assumes ‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and ‹inv S› and ‹no_dup (trail S)› and
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T T) (get_all_ann_decomposition (trail T))›
using assms by (induction)
(auto intro: rtranclp_cdcl⇩N⇩O⇩T_inv cdcl⇩N⇩O⇩T_all_decomposition_implies rtranclp_cdcl⇩N⇩O⇩T_no_dup)
lemma rtranclp_cdcl⇩N⇩O⇩T_bj_sat_ext_iff:
assumes ‹cdcl⇩N⇩O⇩T⇧*⇧* S T›and ‹inv S›
shows ‹I⊨sextm clauses⇩N⇩O⇩T S ⟷ I⊨sextm clauses⇩N⇩O⇩T T›
using assms apply (induction rule: rtranclp_induct)
using cdcl⇩N⇩O⇩T_bj_sat_ext_iff by (auto intro: rtranclp_cdcl⇩N⇩O⇩T_inv rtranclp_cdcl⇩N⇩O⇩T_no_dup)
definition cdcl⇩N⇩O⇩T_NOT_all_inv where
‹cdcl⇩N⇩O⇩T_NOT_all_inv A S ⟷ (finite A ∧ inv S ∧ atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A
∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A ∧ no_dup (trail S))›
lemma cdcl⇩N⇩O⇩T_NOT_all_inv:
assumes ‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and ‹cdcl⇩N⇩O⇩T_NOT_all_inv A S›
shows ‹cdcl⇩N⇩O⇩T_NOT_all_inv A T›
using assms unfolding cdcl⇩N⇩O⇩T_NOT_all_inv_def
by (simp add: rtranclp_cdcl⇩N⇩O⇩T_inv rtranclp_cdcl⇩N⇩O⇩T_no_dup rtranclp_cdcl⇩N⇩O⇩T_trail_clauses_bound)
abbreviation learn_or_forget where
‹learn_or_forget S T ≡ learn S T ∨ forget⇩N⇩O⇩T S T›
lemma rtranclp_learn_or_forget_cdcl⇩N⇩O⇩T:
‹learn_or_forget⇧*⇧* S T ⟹ cdcl⇩N⇩O⇩T⇧*⇧* S T›
using rtranclp_mono[of learn_or_forget cdcl⇩N⇩O⇩T] by (blast intro: cdcl⇩N⇩O⇩T.c_learn cdcl⇩N⇩O⇩T.c_forget⇩N⇩O⇩T)
lemma learn_or_forget_dpll_μ⇩C:
assumes
l_f: ‹learn_or_forget⇧*⇧* S T› and
dpll: ‹dpll_bj T U› and
inv: ‹cdcl⇩N⇩O⇩T_NOT_all_inv A S›
shows ‹(2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A))
- μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight U)
< (2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A))
- μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight S)›
(is ‹?μ U < ?μ S›)
proof -
have ‹?μ S = ?μ T›
using l_f
proof (induction)
case base
then show ?case by simp
next
case (step T U)
moreover then have ‹no_dup (trail T)›
using rtranclp_cdcl⇩N⇩O⇩T_no_dup[of S T] cdcl⇩N⇩O⇩T_NOT_all_inv_def inv
rtranclp_learn_or_forget_cdcl⇩N⇩O⇩T by auto
ultimately show ?case
using forget_μ⇩C_stable learn_μ⇩C_stable inv unfolding cdcl⇩N⇩O⇩T_NOT_all_inv_def by presburger
qed
moreover have ‹cdcl⇩N⇩O⇩T_NOT_all_inv A T›
using rtranclp_learn_or_forget_cdcl⇩N⇩O⇩T cdcl⇩N⇩O⇩T_NOT_all_inv l_f inv by blast
ultimately show ?thesis
using dpll_bj_trail_mes_decreasing_prop[of T U A, OF dpll] finite
unfolding cdcl⇩N⇩O⇩T_NOT_all_inv_def by presburger
qed
lemma infinite_cdcl⇩N⇩O⇩T_exists_learn_and_forget_infinite_chain:
assumes
‹⋀i. cdcl⇩N⇩O⇩T (f i) (f(Suc i))› and
inv: ‹cdcl⇩N⇩O⇩T_NOT_all_inv A (f 0)›
shows ‹∃j. ∀i≥j. learn_or_forget (f i) (f (Suc i))›
using assms
proof (induction ‹(2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A))
- μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight (f 0))›
arbitrary: f
rule: nat_less_induct_case)
case (Suc n) note IH = this(1) and μ = this(2) and cdcl⇩N⇩O⇩T = this(3) and inv = this(4)
consider
(dpll_end) ‹∃j. ∀i≥j. learn_or_forget (f i) (f (Suc i))›
| (dpll_more) ‹¬(∃j. ∀i≥j. learn_or_forget (f i) (f (Suc i)))›
by blast
then show ?case
proof cases
case dpll_end
then show ?thesis by auto
next
case dpll_more
then have j: ‹∃i. ¬ learn (f i) (f (Suc i)) ∧ ¬forget⇩N⇩O⇩T (f i) (f (Suc i))›
by blast
obtain i where
i_learn_forget: ‹¬learn (f i) (f (Suc i)) ∧ ¬forget⇩N⇩O⇩T (f i) (f (Suc i))› and
‹∀k<i. learn_or_forget (f k) (f (Suc k))›
proof -
obtain i⇩0 where ‹¬ learn (f i⇩0) (f (Suc i⇩0)) ∧ ¬forget⇩N⇩O⇩T (f i⇩0) (f (Suc i⇩0))›
using j by auto
then have ‹{i. i≤i⇩0 ∧ ¬ learn (f i) (f (Suc i)) ∧ ¬forget⇩N⇩O⇩T (f i) (f (Suc i))} ≠ {}›
by auto
let ?I = ‹{i. i≤i⇩0 ∧ ¬ learn (f i) (f (Suc i)) ∧ ¬forget⇩N⇩O⇩T (f i) (f (Suc i))}›
let ?i = ‹Min ?I›
have ‹finite ?I›
by auto
have ‹¬ learn (f ?i) (f (Suc ?i)) ∧ ¬forget⇩N⇩O⇩T (f ?i) (f (Suc ?i))›
using Min_in[OF ‹finite ?I› ‹?I ≠ {}›] by auto
moreover have ‹∀k<?i. learn_or_forget (f k) (f (Suc k))›
using Min.coboundedI[of ‹{i. i ≤ i⇩0 ∧ ¬ learn (f i) (f (Suc i)) ∧ ¬ forget⇩N⇩O⇩T (f i)
(f (Suc i))}›, simplified]
by (meson ‹¬ learn (f i⇩0) (f (Suc i⇩0)) ∧ ¬ forget⇩N⇩O⇩T (f i⇩0) (f (Suc i⇩0))› less_imp_le
dual_order.trans not_le)
ultimately show ?thesis using that by blast
qed
define g where ‹g = (λn. f (n + Suc i))›
have ‹dpll_bj (f i) (g 0)›
using i_learn_forget cdcl⇩N⇩O⇩T cdcl⇩N⇩O⇩T.cases unfolding g_def by auto
{
fix j
assume ‹j ≤ i›
then have ‹learn_or_forget⇧*⇧* (f 0) (f j)›
apply (induction j)
apply simp
by (metis (no_types, lifting) Suc_leD Suc_le_lessD rtranclp.simps
‹∀k<i. learn (f k) (f (Suc k)) ∨ forget⇩N⇩O⇩T (f k) (f (Suc k))›)
}
then have ‹learn_or_forget⇧*⇧* (f 0) (f i)› by blast
then have ‹(2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A))
- μ⇩C (1 + card (atms_of_ms A)) (2 + card (atms_of_ms A)) (trail_weight (g 0))
< (2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A))
- μ⇩C (1 + card (atms_of_ms A)) (2 + card (atms_of_ms A)) (trail_weight (f 0))›
using learn_or_forget_dpll_μ⇩C[of ‹f 0› ‹f i› ‹g 0› A] inv ‹dpll_bj (f i) (g 0)›
unfolding cdcl⇩N⇩O⇩T_NOT_all_inv_def by linarith
moreover have cdcl⇩N⇩O⇩T_i: ‹cdcl⇩N⇩O⇩T⇧*⇧* (f 0) (g 0)›
using rtranclp_learn_or_forget_cdcl⇩N⇩O⇩T[of ‹f 0› ‹f i›] ‹learn_or_forget⇧*⇧* (f 0) (f i)›
cdcl⇩N⇩O⇩T[of i] unfolding g_def by auto
moreover have ‹⋀i. cdcl⇩N⇩O⇩T (g i) (g (Suc i))›
using cdcl⇩N⇩O⇩T g_def by auto
moreover have ‹cdcl⇩N⇩O⇩T_NOT_all_inv A (g 0)›
using inv cdcl⇩N⇩O⇩T_i rtranclp_cdcl⇩N⇩O⇩T_trail_clauses_bound g_def cdcl⇩N⇩O⇩T_NOT_all_inv by auto
ultimately obtain j where j: ‹⋀i. i≥j ⟹ learn_or_forget (g i) (g (Suc i))›
using IH unfolding μ[symmetric] by presburger
show ?thesis
proof
{
fix k
assume ‹k ≥ j + Suc i›
then have ‹learn_or_forget (f k) (f (Suc k))›
using j[of ‹k-Suc i›] unfolding g_def by auto
}
then show ‹∀k≥j+Suc i. learn_or_forget (f k) (f (Suc k))›
by auto
qed
qed
next
case 0 note H = this(1) and cdcl⇩N⇩O⇩T = this(2) and inv = this(3)
show ?case
proof (rule ccontr)
assume ‹¬ ?case›
then have j: ‹∃i. ¬ learn (f i) (f (Suc i)) ∧ ¬forget⇩N⇩O⇩T (f i) (f (Suc i))›
by blast
obtain i where
‹¬learn (f i) (f (Suc i)) ∧ ¬forget⇩N⇩O⇩T (f i) (f (Suc i))› and
‹∀k<i. learn_or_forget (f k) (f (Suc k))›
proof -
obtain i⇩0 where ‹¬ learn (f i⇩0) (f (Suc i⇩0)) ∧ ¬forget⇩N⇩O⇩T (f i⇩0) (f (Suc i⇩0))›
using j by auto
then have ‹{i. i≤i⇩0 ∧ ¬ learn (f i) (f (Suc i)) ∧ ¬forget⇩N⇩O⇩T (f i) (f (Suc i))} ≠ {}›
by auto
let ?I = ‹{i. i≤i⇩0 ∧ ¬ learn (f i) (f (Suc i)) ∧ ¬forget⇩N⇩O⇩T (f i) (f (Suc i))}›
let ?i = ‹Min ?I›
have ‹finite ?I›
by auto
have ‹¬ learn (f ?i) (f (Suc ?i)) ∧ ¬forget⇩N⇩O⇩T (f ?i) (f (Suc ?i))›
using Min_in[OF ‹finite ?I› ‹?I ≠ {}›] by auto
moreover have ‹∀k<?i. learn_or_forget (f k) (f (Suc k))›
using Min.coboundedI[of ‹{i. i ≤ i⇩0 ∧ ¬ learn (f i) (f (Suc i)) ∧ ¬ forget⇩N⇩O⇩T (f i)
(f (Suc i))}›, simplified]
by (meson ‹¬ learn (f i⇩0) (f (Suc i⇩0)) ∧ ¬ forget⇩N⇩O⇩T (f i⇩0) (f (Suc i⇩0))› less_imp_le
dual_order.trans not_le)
ultimately show ?thesis using that by blast
qed
have ‹dpll_bj (f i) (f (Suc i))›
using ‹¬ learn (f i) (f (Suc i)) ∧ ¬ forget⇩N⇩O⇩T (f i) (f (Suc i))› cdcl⇩N⇩O⇩T cdcl⇩N⇩O⇩T.cases
by blast
{
fix j
assume ‹j ≤ i›
then have ‹learn_or_forget⇧*⇧* (f 0) (f j)›
apply (induction j)
apply simp
by (metis (no_types, lifting) Suc_leD Suc_le_lessD rtranclp.simps
‹∀k<i. learn (f k) (f (Suc k)) ∨ forget⇩N⇩O⇩T (f k) (f (Suc k))›)
}
then have ‹learn_or_forget⇧*⇧* (f 0) (f i)› by blast
then show False
using learn_or_forget_dpll_μ⇩C[of ‹f 0› ‹f i› ‹f (Suc i)› A] inv 0
‹dpll_bj (f i) (f (Suc i))› unfolding cdcl⇩N⇩O⇩T_NOT_all_inv_def by linarith
qed
qed
lemma wf_cdcl⇩N⇩O⇩T_no_learn_and_forget_infinite_chain:
assumes
no_infinite_lf: ‹⋀f j. ¬ (∀i≥j. learn_or_forget (f i) (f (Suc i)))›
shows ‹wf {(T, S). cdcl⇩N⇩O⇩T S T ∧ cdcl⇩N⇩O⇩T_NOT_all_inv A S}›
(is ‹wf {(T, S). cdcl⇩N⇩O⇩T S T ∧ ?inv S}›)
unfolding wf_iff_no_infinite_down_chain
proof (rule ccontr)
assume ‹¬ ¬ (∃f. ∀i. (f (Suc i), f i) ∈ {(T, S). cdcl⇩N⇩O⇩T S T ∧ ?inv S})›
then obtain f where
‹∀i. cdcl⇩N⇩O⇩T (f i) (f (Suc i)) ∧ ?inv (f i)›
by fast
then have ‹∃j. ∀i≥j. learn_or_forget (f i) (f (Suc i))›
using infinite_cdcl⇩N⇩O⇩T_exists_learn_and_forget_infinite_chain[of f] by meson
then show False using no_infinite_lf by blast
qed
lemma inv_and_tranclp_cdcl_⇩N⇩O⇩T_tranclp_cdcl⇩N⇩O⇩T_and_inv:
‹cdcl⇩N⇩O⇩T⇧+⇧+ S T ∧ cdcl⇩N⇩O⇩T_NOT_all_inv A S ⟷ (λS T. cdcl⇩N⇩O⇩T S T ∧ cdcl⇩N⇩O⇩T_NOT_all_inv A S)⇧+⇧+ S T›
(is ‹?A ∧ ?I ⟷ ?B›)
proof
assume ‹?A ∧ ?I›
then have ?A and ?I by blast+
then show ?B
apply induction
apply (simp add: tranclp.r_into_trancl)
by (subst tranclp.simps) (auto intro: cdcl⇩N⇩O⇩T_NOT_all_inv tranclp_into_rtranclp)
next
assume ?B
then have ?A by induction auto
moreover have ?I using ‹?B› tranclpD by fastforce
ultimately show ‹?A ∧ ?I› by blast
qed
lemma wf_tranclp_cdcl⇩N⇩O⇩T_no_learn_and_forget_infinite_chain:
assumes
no_infinite_lf: ‹⋀f j. ¬ (∀i≥j. learn_or_forget (f i) (f (Suc i)))›
shows ‹wf {(T, S). cdcl⇩N⇩O⇩T⇧+⇧+ S T ∧ cdcl⇩N⇩O⇩T_NOT_all_inv A S}›
using wf_trancl[OF wf_cdcl⇩N⇩O⇩T_no_learn_and_forget_infinite_chain[OF no_infinite_lf]]
apply (rule wf_subset)
by (auto simp: trancl_set_tranclp inv_and_tranclp_cdcl_⇩N⇩O⇩T_tranclp_cdcl⇩N⇩O⇩T_and_inv)
lemma cdcl⇩N⇩O⇩T_final_state:
assumes
n_s: ‹no_step cdcl⇩N⇩O⇩T S› and
inv: ‹cdcl⇩N⇩O⇩T_NOT_all_inv A S› and
decomp: ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T S))
∨ (trail S ⊨asm clauses⇩N⇩O⇩T S ∧ satisfiable (set_mset (clauses⇩N⇩O⇩T S)))›
proof -
have n_s': ‹no_step dpll_bj S›
using n_s by (auto simp: cdcl⇩N⇩O⇩T.simps)
show ?thesis
apply (rule dpll_backjump_final_state[of S A])
using inv decomp n_s' unfolding cdcl⇩N⇩O⇩T_NOT_all_inv_def by auto
qed
lemma full_cdcl⇩N⇩O⇩T_final_state:
assumes
full: ‹full cdcl⇩N⇩O⇩T S T› and
inv: ‹cdcl⇩N⇩O⇩T_NOT_all_inv A S› and
n_d: ‹no_dup (trail S)› and
decomp: ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T T))
∨ (trail T ⊨asm clauses⇩N⇩O⇩T T ∧ satisfiable (set_mset (clauses⇩N⇩O⇩T T)))›
proof -
have st: ‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and n_s: ‹no_step cdcl⇩N⇩O⇩T T›
using full unfolding full_def by blast+
have n_s': ‹cdcl⇩N⇩O⇩T_NOT_all_inv A T›
using cdcl⇩N⇩O⇩T_NOT_all_inv inv st by blast
moreover have ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T T) (get_all_ann_decomposition (trail T))›
using cdcl⇩N⇩O⇩T_NOT_all_inv_def decomp inv rtranclp_cdcl⇩N⇩O⇩T_all_decomposition_implies st by auto
ultimately show ?thesis
using cdcl⇩N⇩O⇩T_final_state n_s by blast
qed
end
subsubsection ‹Termination›
text ‹To prove termination we need to restrict learn and forget. Otherwise we could forget and
relearn the exact same clause over and over. A first idea is to forbid removing clauses that
can be used to backjump. This does not change the rules of the calculus. A second idea is to
``merge'' backjump and learn: that way, though closer to implementation, needs a change of the
rules, since the backjump-rule learns the clause used to backjump.›
subsubsection ‹Restricting learn and forget›
locale conflict_driven_clause_learning_learning_before_backjump_only_distinct_learnt =
dpll_state trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T +
conflict_driven_clause_learning trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
inv decide_conds backjump_conds propagate_conds
‹λC S. distinct_mset C ∧ ¬tautology C ∧ learn_restrictions C S ∧
(∃F K d F' C' L. trail S = F' @ Decided K # F ∧ C = add_mset L C' ∧ F ⊨as CNot C'
∧ add_mset L C' ∉# clauses⇩N⇩O⇩T S)›
‹λC S. ¬(∃F' F K d L. trail S = F' @ Decided K # F ∧ F ⊨as CNot (remove1_mset L C))
∧ forget_restrictions C S›
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
inv :: ‹'st ⇒ bool› and
decide_conds :: ‹'st ⇒ 'st ⇒ bool› and
backjump_conds :: ‹'v clause ⇒ 'v clause ⇒ 'v literal ⇒ 'st ⇒ 'st ⇒ bool› and
propagate_conds :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st ⇒ bool› and
learn_restrictions forget_restrictions :: ‹'v clause ⇒ 'st ⇒ bool›
begin
lemma cdcl⇩N⇩O⇩T_learn_all_induct[consumes 1, case_names dpll_bj learn forget⇩N⇩O⇩T]:
fixes S T :: ‹'st›
assumes ‹cdcl⇩N⇩O⇩T S T› and
dpll: ‹⋀T. dpll_bj S T ⟹ P S T› and
learning:
‹⋀C F K F' C' L T. clauses⇩N⇩O⇩T S ⊨pm C ⟹
atms_of C ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S)) ⟹
distinct_mset C ⟹
¬ tautology C ⟹
learn_restrictions C S ⟹
trail S = F' @ Decided K # F ⟹
C = add_mset L C' ⟹
F ⊨as CNot C' ⟹
add_mset L C' ∉# clauses⇩N⇩O⇩T S ⟹
T ∼ add_cls⇩N⇩O⇩T C S ⟹
P S T› and
forgetting: ‹⋀C T. removeAll_mset C (clauses⇩N⇩O⇩T S) ⊨pm C ⟹
C ∈# clauses⇩N⇩O⇩T S ⟹
¬(∃F' F K L. trail S = F' @ Decided K # F ∧ F ⊨as CNot (C - {#L#})) ⟹
T ∼ remove_cls⇩N⇩O⇩T C S ⟹
forget_restrictions C S ⟹
P S T›
shows ‹P S T›
using assms(1)
apply (induction rule: cdcl⇩N⇩O⇩T.induct)
apply (auto dest: assms(2) simp add: learn_ops_axioms)[]
apply (auto elim!: learn_ops.learn.cases[OF learn_ops_axioms] dest: assms(3))[]
apply (auto elim!: forget_ops.forget⇩N⇩O⇩T.cases[OF forget_ops_axioms] dest!: assms(4))
done
lemma rtranclp_cdcl⇩N⇩O⇩T_inv:
‹cdcl⇩N⇩O⇩T⇧*⇧* S T ⟹ inv S ⟹ inv T›
apply (induction rule: rtranclp_induct)
apply simp
using cdcl⇩N⇩O⇩T_inv unfolding conflict_driven_clause_learning_def
conflict_driven_clause_learning_axioms_def by blast
lemma learn_always_simple_clauses:
assumes
learn: ‹learn S T› and
n_d: ‹no_dup (trail S)›
shows ‹set_mset (clauses⇩N⇩O⇩T T - clauses⇩N⇩O⇩T S)
⊆ simple_clss (atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` lits_of_l (trail S))›
proof
fix C assume C: ‹C ∈ set_mset (clauses⇩N⇩O⇩T T - clauses⇩N⇩O⇩T S)›
have ‹distinct_mset C› ‹¬tautology C› using learn C n_d by (elim learn⇩N⇩O⇩TE; auto)+
then have ‹C ∈ simple_clss (atms_of C)›
using distinct_mset_not_tautology_implies_in_simple_clss by blast
moreover have ‹atms_of C ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` lits_of_l (trail S)›
using learn C n_d by (elim learn⇩N⇩O⇩TE) (auto simp: atms_of_ms_def atms_of_def image_Un
true_annots_CNot_all_atms_defined)
moreover have ‹finite (atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` lits_of_l (trail S))›
by auto
ultimately show ‹C ∈ simple_clss (atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` lits_of_l (trail S))›
using simple_clss_mono by (metis (no_types) insert_subset mk_disjoint_insert)
qed
definition ‹conflicting_bj_clss S ≡
{C+{#L#} |C L. C+{#L#} ∈# clauses⇩N⇩O⇩T S ∧ distinct_mset (C+{#L#})
∧ ¬tautology (C+{#L#})
∧ (∃F' K F. trail S = F' @ Decided K # F ∧ F ⊨as CNot C)}›
lemma conflicting_bj_clss_remove_cls⇩N⇩O⇩T[simp]:
‹conflicting_bj_clss (remove_cls⇩N⇩O⇩T C S) = conflicting_bj_clss S - {C}›
unfolding conflicting_bj_clss_def by fastforce
lemma conflicting_bj_clss_remove_cls⇩N⇩O⇩T'[simp]:
‹T ∼ remove_cls⇩N⇩O⇩T C S ⟹ conflicting_bj_clss T = conflicting_bj_clss S - {C}›
unfolding conflicting_bj_clss_def by fastforce
lemma conflicting_bj_clss_add_cls⇩N⇩O⇩T_state_eq:
assumes
T: ‹T ∼ add_cls⇩N⇩O⇩T C' S› and
n_d: ‹no_dup (trail S)›
shows ‹conflicting_bj_clss T
= conflicting_bj_clss S
∪ (if ∃C L. C' = add_mset L C ∧ distinct_mset (add_mset L C) ∧ ¬tautology (add_mset L C)
∧ (∃F' K d F. trail S = F' @ Decided K # F ∧ F ⊨as CNot C)
then {C'} else {})›
proof -
define P where ‹P = (λC L T. distinct_mset (add_mset L C) ∧ ¬ tautology (add_mset L C) ∧
(∃F' K F. trail T = F' @ Decided K # F ∧ F ⊨as CNot C))›
have conf: ‹⋀T. conflicting_bj_clss T = {add_mset L C |C L. add_mset L C ∈# clauses⇩N⇩O⇩T T ∧ P C L T}›
unfolding conflicting_bj_clss_def P_def by auto
have P_S_T: ‹⋀C L. P C L T = P C L S›
using T n_d unfolding P_def by auto
have P: ‹conflicting_bj_clss T = {add_mset L C |C L. add_mset L C ∈# clauses⇩N⇩O⇩T S ∧ P C L T} ∪
{add_mset L C |C L. add_mset L C ∈# {#C'#} ∧ P C L T}›
using T n_d unfolding conf by auto
moreover have ‹{add_mset L C |C L. add_mset L C ∈# clauses⇩N⇩O⇩T S ∧ P C L T} = conflicting_bj_clss S›
using T n_d unfolding P_def conflicting_bj_clss_def by auto
moreover have ‹{add_mset L C |C L. add_mset L C ∈# {#C'#} ∧ P C L T} =
(if ∃C L. C' = add_mset L C ∧ P C L S then {C'} else {})›
using n_d T by (force simp: P_S_T)
ultimately show ?thesis unfolding P_def by presburger
qed
lemma conflicting_bj_clss_add_cls⇩N⇩O⇩T:
‹no_dup (trail S) ⟹
conflicting_bj_clss (add_cls⇩N⇩O⇩T C' S)
= conflicting_bj_clss S
∪ (if ∃C L. C' = C +{#L#}∧ distinct_mset (C+{#L#}) ∧ ¬tautology (C+{#L#})
∧ (∃F' K d F. trail S = F' @ Decided K # F ∧ F ⊨as CNot C)
then {C'} else {})›
using conflicting_bj_clss_add_cls⇩N⇩O⇩T_state_eq by auto
lemma conflicting_bj_clss_incl_clauses:
‹conflicting_bj_clss S ⊆ set_mset (clauses⇩N⇩O⇩T S)›
unfolding conflicting_bj_clss_def by auto
lemma finite_conflicting_bj_clss[simp]:
‹finite (conflicting_bj_clss S)›
using conflicting_bj_clss_incl_clauses[of S] rev_finite_subset by blast
lemma learn_conflicting_increasing:
‹no_dup (trail S) ⟹ learn S T ⟹ conflicting_bj_clss S ⊆ conflicting_bj_clss T›
apply (elim learn⇩N⇩O⇩TE)
by (subst conflicting_bj_clss_add_cls⇩N⇩O⇩T_state_eq[of T]) auto
abbreviation ‹conflicting_bj_clss_yet b S ≡
3 ^ b - card (conflicting_bj_clss S)›
abbreviation μ⇩L :: ‹nat ⇒ 'st ⇒ nat × nat› where
‹μ⇩L b S ≡ (conflicting_bj_clss_yet b S, card (set_mset (clauses⇩N⇩O⇩T S)))›
lemma do_not_forget_before_backtrack_rule_clause_learned_clause_untouched:
assumes ‹forget⇩N⇩O⇩T S T›
shows ‹conflicting_bj_clss S = conflicting_bj_clss T›
using assms apply (elim forget⇩N⇩O⇩TE)
apply rule
apply (subst conflicting_bj_clss_remove_cls⇩N⇩O⇩T'[of T], simp)
apply (fastforce simp: conflicting_bj_clss_def remove1_mset_add_mset_If split: if_splits)
apply fastforce
done
lemma forget_μ⇩L_decrease:
assumes forget⇩N⇩O⇩T: ‹forget⇩N⇩O⇩T S T›
shows ‹(μ⇩L b T, μ⇩L b S) ∈ less_than <*lex*> less_than›
proof -
have ‹card (set_mset (clauses⇩N⇩O⇩T S)) > 0›
using forget⇩N⇩O⇩T by (elim forget⇩N⇩O⇩TE) (auto simp: size_mset_removeAll_mset_le_iff card_gt_0_iff)
then have ‹card (set_mset (clauses⇩N⇩O⇩T T)) < card (set_mset (clauses⇩N⇩O⇩T S))›
using forget⇩N⇩O⇩T by (elim forget⇩N⇩O⇩TE) (auto simp: size_mset_removeAll_mset_le_iff)
then show ?thesis
unfolding do_not_forget_before_backtrack_rule_clause_learned_clause_untouched[OF forget⇩N⇩O⇩T]
by auto
qed
lemma set_condition_or_split:
‹{a. (a = b ∨ Q a) ∧ S a} = (if S b then {b} else {}) ∪ {a. Q a ∧ S a}›
by auto
lemma set_insert_neq:
‹A ≠ insert a A ⟷ a ∉ A›
by auto
lemma learn_μ⇩L_decrease:
assumes learnST: ‹learn S T› and n_d: ‹no_dup (trail S)› and
A: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` lits_of_l (trail S) ⊆ A› and
fin_A: ‹finite A›
shows ‹(μ⇩L (card A) T, μ⇩L (card A) S) ∈ less_than <*lex*> less_than›
proof -
have [simp]: ‹(atms_of_mm (clauses⇩N⇩O⇩T T) ∪ atm_of ` lits_of_l (trail T))
= (atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` lits_of_l (trail S))›
using learnST n_d by (elim learn⇩N⇩O⇩TE) auto
then have ‹card (atms_of_mm (clauses⇩N⇩O⇩T T) ∪ atm_of ` lits_of_l (trail T))
= card (atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` lits_of_l (trail S))›
by (auto intro!: card_mono)
then have 3: ‹(3::nat) ^ card (atms_of_mm (clauses⇩N⇩O⇩T T) ∪ atm_of ` lits_of_l (trail T))
= 3 ^ card (atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` lits_of_l (trail S))›
by (auto intro: power_mono)
moreover have ‹conflicting_bj_clss S ⊆ conflicting_bj_clss T›
using learnST n_d by (simp add: learn_conflicting_increasing)
moreover have ‹conflicting_bj_clss S ≠ conflicting_bj_clss T›
using learnST
proof (elim learn⇩N⇩O⇩TE, goal_cases)
case (1 C) note clss_S = this(1) and atms_C = this(2) and inv = this(3) and T = this(4)
then obtain F K F' C' L where
tr_S: ‹trail S = F' @ Decided K # F› and
C: ‹C = add_mset L C'› and
F: ‹F ⊨as CNot C'› and
C_S:‹add_mset L C' ∉# clauses⇩N⇩O⇩T S›
by blast
moreover have ‹distinct_mset C› ‹¬ tautology C› using inv by blast+
ultimately have ‹add_mset L C' ∈ conflicting_bj_clss T›
using T n_d unfolding conflicting_bj_clss_def by fastforce
moreover have ‹add_mset L C' ∉ conflicting_bj_clss S›
using C_S unfolding conflicting_bj_clss_def by auto
ultimately show ?case by blast
qed
moreover have fin_T: ‹finite (conflicting_bj_clss T)›
using learnST by induction (auto simp add: conflicting_bj_clss_add_cls⇩N⇩O⇩T )
ultimately have ‹card (conflicting_bj_clss T) ≥ card (conflicting_bj_clss S)›
using card_mono by blast
moreover
have fin': ‹finite (atms_of_mm (clauses⇩N⇩O⇩T T) ∪ atm_of ` lits_of_l (trail T))›
by auto
have 1:‹atms_of_ms (conflicting_bj_clss T) ⊆ atms_of_mm (clauses⇩N⇩O⇩T T)›
unfolding conflicting_bj_clss_def atms_of_ms_def by auto
have 2: ‹⋀x. x∈ conflicting_bj_clss T ⟹ ¬ tautology x ∧ distinct_mset x›
unfolding conflicting_bj_clss_def by auto
have T: ‹conflicting_bj_clss T
⊆ simple_clss (atms_of_mm (clauses⇩N⇩O⇩T T) ∪ atm_of ` lits_of_l (trail T))›
by standard (meson 1 2 fin' ‹finite (conflicting_bj_clss T)› simple_clss_mono
distinct_mset_set_def simplified_in_simple_clss subsetCE sup.coboundedI1)
moreover
then have #: ‹3 ^ card (atms_of_mm (clauses⇩N⇩O⇩T T) ∪ atm_of ` lits_of_l (trail T))
≥ card (conflicting_bj_clss T)›
by (meson Nat.le_trans simple_clss_card simple_clss_finite card_mono fin')
have ‹atms_of_mm (clauses⇩N⇩O⇩T T) ∪ atm_of ` lits_of_l (trail T) ⊆ A›
using learn⇩N⇩O⇩TE[OF learnST] A by simp
then have ‹3 ^ (card A) ≥ card (conflicting_bj_clss T)›
using # fin_A by (meson simple_clss_card simple_clss_finite
simple_clss_mono calculation(2) card_mono dual_order.trans)
ultimately show ?thesis
using psubset_card_mono[OF fin_T ]
unfolding less_than_iff lex_prod_def by clarify
(meson ‹conflicting_bj_clss S ≠ conflicting_bj_clss T›
‹conflicting_bj_clss S ⊆ conflicting_bj_clss T›
diff_less_mono2 le_less_trans not_le psubsetI)
qed
text ‹We have to assume the following:
▪ @{term ‹inv S›}: the invariant holds in the inital state.
▪ @{term A} is a (finite @{term ‹finite A›}) superset of the literals in the trail
@{term ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A›}
and in the clauses @{term ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A›}. This can the the set of all
the literals in the starting set of clauses.
▪ @{term ‹no_dup (trail S)›}: no duplicate in the trail. This is invariant along the path.›
definition μ⇩C⇩D⇩C⇩L where
‹μ⇩C⇩D⇩C⇩L A T ≡ ((2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A))
- μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight T),
conflicting_bj_clss_yet (card (atms_of_ms A)) T, card (set_mset (clauses⇩N⇩O⇩T T)))›
lemma cdcl⇩N⇩O⇩T_decreasing_measure:
assumes
‹cdcl⇩N⇩O⇩T S T› and
inv: ‹inv S› and
atm_clss: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
atm_lits: ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
fin_A: ‹finite A›
shows ‹(μ⇩C⇩D⇩C⇩L A T, μ⇩C⇩D⇩C⇩L A S)
∈ less_than <*lex*> (less_than <*lex*> less_than)›
using assms(1)
proof induction
case (c_dpll_bj T)
from dpll_bj_trail_mes_decreasing_prop[OF this(1) inv atm_clss atm_lits n_d fin_A]
show ?case unfolding μ⇩C⇩D⇩C⇩L_def
by (meson in_lex_prod less_than_iff)
next
case (c_learn T) note learn = this(1)
then have S: ‹trail S = trail T›
using inv atm_clss atm_lits n_d fin_A
by (elim learn⇩N⇩O⇩TE) auto
show ?case
using learn_μ⇩L_decrease[OF learn n_d, of ‹atms_of_ms A›] atm_clss atm_lits fin_A n_d
unfolding S μ⇩C⇩D⇩C⇩L_def by auto
next
case (c_forget⇩N⇩O⇩T T) note forget⇩N⇩O⇩T = this(1)
have ‹trail S = trail T› using forget⇩N⇩O⇩T by induction auto
then show ?case
using forget_μ⇩L_decrease[OF forget⇩N⇩O⇩T] unfolding μ⇩C⇩D⇩C⇩L_def by auto
qed
lemma wf_cdcl⇩N⇩O⇩T_restricted_learning:
assumes ‹finite A›
shows ‹wf {(T, S).
(atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A ∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A
∧ no_dup (trail S)
∧ inv S)
∧ cdcl⇩N⇩O⇩T S T }›
by (rule wf_wf_if_measure'[of ‹less_than <*lex*> (less_than <*lex*> less_than)›])
(auto intro: cdcl⇩N⇩O⇩T_decreasing_measure[OF _ _ _ _ _ assms])
definition μ⇩C' :: ‹'v clause set ⇒ 'st ⇒ nat› where
‹μ⇩C' A T ≡ μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight T)›
definition μ⇩C⇩D⇩C⇩L' :: ‹'v clause set ⇒ 'st ⇒ nat› where
‹μ⇩C⇩D⇩C⇩L' A T ≡
((2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A)) - μ⇩C' A T) * (1+ 3^card (atms_of_ms A)) * 2
+ conflicting_bj_clss_yet (card (atms_of_ms A)) T * 2
+ card (set_mset (clauses⇩N⇩O⇩T T))›
lemma cdcl⇩N⇩O⇩T_decreasing_measure':
assumes
‹cdcl⇩N⇩O⇩T S T› and
inv: ‹inv S› and
atms_clss: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
atms_trail: ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
fin_A: ‹finite A›
shows ‹μ⇩C⇩D⇩C⇩L' A T < μ⇩C⇩D⇩C⇩L' A S›
using assms(1)
proof (induction rule: cdcl⇩N⇩O⇩T_learn_all_induct)
case (dpll_bj T)
then have ‹(2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A)) - μ⇩C' A T
< (2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A)) - μ⇩C' A S›
using dpll_bj_trail_mes_decreasing_prop fin_A inv n_d atms_clss atms_trail
unfolding μ⇩C'_def by blast
then have XX: ‹((2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A)) - μ⇩C' A T) + 1
≤ (2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A)) - μ⇩C' A S›
by auto
from mult_le_mono1[OF this, of ‹1 + 3 ^ card (atms_of_ms A)›]
have ‹((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A T) *
(1 + 3 ^ card (atms_of_ms A)) + (1 + 3 ^ card (atms_of_ms A))
≤ ((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A S)
* (1 + 3 ^ card (atms_of_ms A))›
unfolding Nat.add_mult_distrib
by presburger
moreover
have cl_T_S: ‹clauses⇩N⇩O⇩T T = clauses⇩N⇩O⇩T S›
using dpll_bj.hyps inv dpll_bj_clauses by auto
have ‹conflicting_bj_clss_yet (card (atms_of_ms A)) S < 1+ 3 ^ card (atms_of_ms A)›
by simp
ultimately have ‹((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A T)
* (1 + 3 ^ card (atms_of_ms A)) + conflicting_bj_clss_yet (card (atms_of_ms A)) T
< ((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A S) *(1 + 3 ^ card (atms_of_ms A))›
by linarith
then have ‹((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A T)
* (1 + 3 ^ card (atms_of_ms A))
+ conflicting_bj_clss_yet (card (atms_of_ms A)) T
< ((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A S)
* (1 + 3 ^ card (atms_of_ms A))
+ conflicting_bj_clss_yet (card (atms_of_ms A)) S›
by linarith
then have ‹((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A T)
* (1 + 3 ^ card (atms_of_ms A)) * 2
+ conflicting_bj_clss_yet (card (atms_of_ms A)) T * 2
< ((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A S)
* (1 + 3 ^ card (atms_of_ms A)) * 2
+ conflicting_bj_clss_yet (card (atms_of_ms A)) S * 2›
by linarith
then show ?case unfolding μ⇩C⇩D⇩C⇩L'_def cl_T_S by presburger
next
case (learn C F' K F C' L T) note clss_S_C = this(1) and atms_C = this(2) and dist = this(3)
and tauto = this(4) and learn_restr = this(5) and tr_S = this(6) and C' = this(7) and
F_C = this(8) and C_new = this(9) and T = this(10)
have ‹insert C (conflicting_bj_clss S) ⊆ simple_clss (atms_of_ms A)›
proof -
have ‹C ∈ simple_clss (atms_of_ms A)›
using C'
by (metis (no_types, hide_lams) Un_subset_iff simple_clss_mono
contra_subsetD dist distinct_mset_not_tautology_implies_in_simple_clss
dual_order.trans atms_C atms_clss atms_trail tauto)
moreover have ‹conflicting_bj_clss S ⊆ simple_clss (atms_of_ms A)›
proof
fix x :: ‹'v clause›
assume ‹x ∈ conflicting_bj_clss S›
then have ‹x ∈# clauses⇩N⇩O⇩T S ∧ distinct_mset x ∧ ¬ tautology x›
unfolding conflicting_bj_clss_def by blast
then show ‹x ∈ simple_clss (atms_of_ms A)›
by (meson atms_clss atms_of_atms_of_ms_mono atms_of_ms_finite simple_clss_mono
distinct_mset_not_tautology_implies_in_simple_clss fin_A finite_subset
set_rev_mp)
qed
ultimately show ?thesis
by auto
qed
then have ‹card (insert C (conflicting_bj_clss S)) ≤ 3 ^ (card (atms_of_ms A))›
by (meson Nat.le_trans atms_of_ms_finite simple_clss_card simple_clss_finite
card_mono fin_A)
moreover have [simp]: ‹card (insert C (conflicting_bj_clss S))
= Suc (card ((conflicting_bj_clss S)))›
by (metis (no_types) C' C_new card_insert_if conflicting_bj_clss_incl_clauses contra_subsetD
finite_conflicting_bj_clss)
moreover have [simp]: ‹conflicting_bj_clss (add_cls⇩N⇩O⇩T C S) = conflicting_bj_clss S ∪ {C}›
using dist tauto F_C by (subst conflicting_bj_clss_add_cls⇩N⇩O⇩T[OF n_d]) (force simp: C' tr_S n_d)
ultimately have [simp]: ‹conflicting_bj_clss_yet (card (atms_of_ms A)) S
= Suc (conflicting_bj_clss_yet (card (atms_of_ms A)) (add_cls⇩N⇩O⇩T C S))›
by simp
have 1: ‹clauses⇩N⇩O⇩T T = clauses⇩N⇩O⇩T (add_cls⇩N⇩O⇩T C S)› using T by auto
have 2: ‹conflicting_bj_clss_yet (card (atms_of_ms A)) T
= conflicting_bj_clss_yet (card (atms_of_ms A)) (add_cls⇩N⇩O⇩T C S)›
using T unfolding conflicting_bj_clss_def by auto
have 3: ‹μ⇩C' A T = μ⇩C' A (add_cls⇩N⇩O⇩T C S)›
using T unfolding μ⇩C'_def by auto
have ‹((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A (add_cls⇩N⇩O⇩T C S))
* (1 + 3 ^ card (atms_of_ms A)) * 2
= ((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A S)
* (1 + 3 ^ card (atms_of_ms A)) * 2›
using n_d unfolding μ⇩C'_def by auto
moreover
have ‹conflicting_bj_clss_yet (card (atms_of_ms A)) (add_cls⇩N⇩O⇩T C S)
* 2
+ card (set_mset (clauses⇩N⇩O⇩T (add_cls⇩N⇩O⇩T C S)))
< conflicting_bj_clss_yet (card (atms_of_ms A)) S * 2
+ card (set_mset (clauses⇩N⇩O⇩T S))›
by (simp add: C' C_new n_d)
ultimately show ?case unfolding μ⇩C⇩D⇩C⇩L'_def 1 2 3 by presburger
next
case (forget⇩N⇩O⇩T C T) note T = this(4)
have [simp]: ‹μ⇩C' A (remove_cls⇩N⇩O⇩T C S) = μ⇩C' A S›
unfolding μ⇩C'_def by auto
have ‹forget⇩N⇩O⇩T S T›
apply (rule forget⇩N⇩O⇩T.intros) using forget⇩N⇩O⇩T by auto
then have ‹conflicting_bj_clss T = conflicting_bj_clss S›
using do_not_forget_before_backtrack_rule_clause_learned_clause_untouched by blast
moreover have ‹card (set_mset (clauses⇩N⇩O⇩T T)) < card (set_mset (clauses⇩N⇩O⇩T S))›
by (metis T card_Diff1_less clauses_remove_cls⇩N⇩O⇩T finite_set_mset forget⇩N⇩O⇩T.hyps(2)
order_refl set_mset_minus_replicate_mset(1) state_eq⇩N⇩O⇩T_clauses)
ultimately show ?case unfolding μ⇩C⇩D⇩C⇩L'_def
using T ‹μ⇩C' A (remove_cls⇩N⇩O⇩T C S) = μ⇩C' A S› by (metis (no_types) add_le_cancel_left
μ⇩C'_def not_le state_eq⇩N⇩O⇩T_trail)
qed
lemma cdcl⇩N⇩O⇩T_clauses_bound:
assumes
‹cdcl⇩N⇩O⇩T S T› and
‹inv S› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ A› and
‹atm_of `(lits_of_l (trail S)) ⊆ A› and
n_d: ‹no_dup (trail S)› and
fin_A[simp]: ‹finite A›
shows ‹set_mset (clauses⇩N⇩O⇩T T) ⊆ set_mset (clauses⇩N⇩O⇩T S) ∪ simple_clss A›
using assms
proof (induction rule: cdcl⇩N⇩O⇩T_learn_all_induct)
case dpll_bj
then show ?case using dpll_bj_clauses by simp
next
case forget⇩N⇩O⇩T
then show ?case using clauses_remove_cls⇩N⇩O⇩T unfolding state_eq⇩N⇩O⇩T_def by auto
next
case (learn C F K d F' C' L) note atms_C = this(2) and dist = this(3) and tauto = this(4) and
T = this(10) and atms_clss_S = this(12) and atms_trail_S = this(13)
have ‹atms_of C ⊆ A›
using atms_C atms_clss_S atms_trail_S by fast
then have ‹simple_clss (atms_of C) ⊆ simple_clss A›
by (simp add: simple_clss_mono)
then have ‹C ∈ simple_clss A›
using finite dist tauto by (auto dest: distinct_mset_not_tautology_implies_in_simple_clss)
then show ?case using T n_d by auto
qed
lemma rtranclp_cdcl⇩N⇩O⇩T_clauses_bound:
assumes
‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and
‹inv S› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ A› and
‹atm_of `(lits_of_l (trail S)) ⊆ A› and
n_d: ‹no_dup (trail S)› and
finite: ‹finite A›
shows ‹set_mset (clauses⇩N⇩O⇩T T) ⊆ set_mset (clauses⇩N⇩O⇩T S) ∪ simple_clss A›
using assms(1-5)
proof induction
case base
then show ?case by simp
next
case (step T U) note st = this(1) and cdcl⇩N⇩O⇩T = this(2) and IH = this(3)[OF this(4-7)] and
inv = this(4) and atms_clss_S = this(5) and atms_trail_S = this(6) and finite_cls_S = this(7)
have ‹inv T›
using rtranclp_cdcl⇩N⇩O⇩T_inv st inv by blast
moreover have ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ A› and ‹atm_of ` lits_of_l (trail T) ⊆ A›
using rtranclp_cdcl⇩N⇩O⇩T_trail_clauses_bound[OF st] inv atms_clss_S atms_trail_S n_d by auto
moreover have ‹no_dup (trail T)›
using rtranclp_cdcl⇩N⇩O⇩T_no_dup[OF st ‹inv S› n_d] by simp
ultimately have ‹set_mset (clauses⇩N⇩O⇩T U) ⊆ set_mset (clauses⇩N⇩O⇩T T) ∪ simple_clss A›
using cdcl⇩N⇩O⇩T finite n_d by (auto simp: cdcl⇩N⇩O⇩T_clauses_bound)
then show ?case using IH by auto
qed
lemma rtranclp_cdcl⇩N⇩O⇩T_card_clauses_bound:
assumes
‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and
‹inv S› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ A› and
‹atm_of `(lits_of_l (trail S)) ⊆ A› and
n_d: ‹no_dup (trail S)› and
finite: ‹finite A›
shows ‹card (set_mset (clauses⇩N⇩O⇩T T)) ≤ card (set_mset (clauses⇩N⇩O⇩T S)) + 3 ^ (card A)›
using rtranclp_cdcl⇩N⇩O⇩T_clauses_bound[OF assms] finite by (meson Nat.le_trans
simple_clss_card simple_clss_finite card_Un_le card_mono finite_UnI
finite_set_mset nat_add_left_cancel_le)
lemma rtranclp_cdcl⇩N⇩O⇩T_card_clauses_bound':
assumes
‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and
‹inv S› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ A› and
‹atm_of `(lits_of_l (trail S)) ⊆ A› and
n_d: ‹no_dup (trail S)› and
finite: ‹finite A›
shows ‹card {C|C. C ∈# clauses⇩N⇩O⇩T T ∧ (tautology C ∨ ¬distinct_mset C)}
≤ card {C|C. C∈# clauses⇩N⇩O⇩T S ∧ (tautology C ∨ ¬distinct_mset C)} + 3 ^ (card A)›
(is ‹card ?T ≤ card ?S + _›)
using rtranclp_cdcl⇩N⇩O⇩T_clauses_bound[OF assms] finite
proof -
have ‹?T ⊆ ?S ∪ simple_clss A›
using rtranclp_cdcl⇩N⇩O⇩T_clauses_bound[OF assms] by force
then have ‹card ?T ≤ card (?S ∪ simple_clss A)›
using finite by (simp add: assms(5) simple_clss_finite card_mono)
then show ?thesis
by (meson le_trans simple_clss_card card_Un_le local.finite nat_add_left_cancel_le)
qed
lemma rtranclp_cdcl⇩N⇩O⇩T_card_simple_clauses_bound:
assumes
‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and
‹inv S› and
NA: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ A› and
MA: ‹atm_of ` (lits_of_l (trail S)) ⊆ A› and
n_d: ‹no_dup (trail S)› and
finite: ‹finite A›
shows ‹card (set_mset (clauses⇩N⇩O⇩T T))
≤ card {C. C ∈# clauses⇩N⇩O⇩T S ∧ (tautology C ∨ ¬distinct_mset C)} + 3 ^ (card A)›
(is ‹card ?T ≤ card ?S + _›)
using rtranclp_cdcl⇩N⇩O⇩T_clauses_bound[OF assms] finite
proof -
have ‹⋀x. x ∈# clauses⇩N⇩O⇩T T ⟹ ¬ tautology x ⟹ distinct_mset x ⟹ x ∈ simple_clss A›
using rtranclp_cdcl⇩N⇩O⇩T_clauses_bound[OF assms] by (metis (no_types, hide_lams) Un_iff NA
atms_of_atms_of_ms_mono simple_clss_mono contra_subsetD subset_trans
distinct_mset_not_tautology_implies_in_simple_clss)
then have ‹set_mset (clauses⇩N⇩O⇩T T) ⊆ ?S ∪ simple_clss A›
using rtranclp_cdcl⇩N⇩O⇩T_clauses_bound[OF assms] by auto
then have ‹card(set_mset (clauses⇩N⇩O⇩T T)) ≤ card (?S ∪ simple_clss A)›
using finite by (simp add: assms(5) simple_clss_finite card_mono)
then show ?thesis
by (meson le_trans simple_clss_card card_Un_le local.finite nat_add_left_cancel_le)
qed
definition μ⇩C⇩D⇩C⇩L'_bound :: ‹'v clause set ⇒ 'st ⇒ nat› where
‹μ⇩C⇩D⇩C⇩L'_bound A S =
((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A))) * (1 + 3 ^ card (atms_of_ms A)) * 2
+ 2*3 ^ (card (atms_of_ms A))
+ card {C. C ∈# clauses⇩N⇩O⇩T S ∧ (tautology C ∨ ¬distinct_mset C)} + 3 ^ (card (atms_of_ms A))›
lemma μ⇩C⇩D⇩C⇩L'_bound_reduce_trail_to⇩N⇩O⇩T[simp]:
‹μ⇩C⇩D⇩C⇩L'_bound A (reduce_trail_to⇩N⇩O⇩T M S) = μ⇩C⇩D⇩C⇩L'_bound A S›
unfolding μ⇩C⇩D⇩C⇩L'_bound_def by auto
lemma rtranclp_cdcl⇩N⇩O⇩T_μ⇩C⇩D⇩C⇩L'_bound_reduce_trail_to⇩N⇩O⇩T:
assumes
‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and
‹inv S› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
‹atm_of `(lits_of_l (trail S)) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
finite: ‹finite (atms_of_ms A)› and
U: ‹U ∼ reduce_trail_to⇩N⇩O⇩T M T›
shows ‹μ⇩C⇩D⇩C⇩L' A U ≤ μ⇩C⇩D⇩C⇩L'_bound A S›
proof -
have ‹ ((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A U)
≤ (2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A))›
by auto
then have ‹((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A U)
* (1 + 3 ^ card (atms_of_ms A)) * 2
≤ (2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) * (1 + 3 ^ card (atms_of_ms A)) * 2›
using mult_le_mono1 by blast
moreover
have ‹conflicting_bj_clss_yet (card (atms_of_ms A)) T * 2 ≤ 2 * 3 ^ card (atms_of_ms A)›
by linarith
moreover have ‹card (set_mset (clauses⇩N⇩O⇩T U))
≤ card {C. C ∈# clauses⇩N⇩O⇩T S ∧ (tautology C ∨ ¬distinct_mset C)} + 3 ^ card (atms_of_ms A)›
using rtranclp_cdcl⇩N⇩O⇩T_card_simple_clauses_bound[OF assms(1-6)] U by auto
ultimately show ?thesis
unfolding μ⇩C⇩D⇩C⇩L'_def μ⇩C⇩D⇩C⇩L'_bound_def by linarith
qed
lemma rtranclp_cdcl⇩N⇩O⇩T_μ⇩C⇩D⇩C⇩L'_bound:
assumes
‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and
‹inv S› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
‹atm_of `(lits_of_l (trail S)) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
finite: ‹finite (atms_of_ms A)›
shows ‹μ⇩C⇩D⇩C⇩L' A T ≤ μ⇩C⇩D⇩C⇩L'_bound A S›
proof -
have ‹μ⇩C⇩D⇩C⇩L' A (reduce_trail_to⇩N⇩O⇩T (trail T) T) = μ⇩C⇩D⇩C⇩L' A T›
unfolding μ⇩C⇩D⇩C⇩L'_def μ⇩C'_def conflicting_bj_clss_def by auto
then show ?thesis using rtranclp_cdcl⇩N⇩O⇩T_μ⇩C⇩D⇩C⇩L'_bound_reduce_trail_to⇩N⇩O⇩T[OF assms, of _ ‹trail T›]
state_eq⇩N⇩O⇩T_ref by fastforce
qed
lemma rtranclp_μ⇩C⇩D⇩C⇩L'_bound_decreasing:
assumes
‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and
‹inv S› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
‹atm_of `(lits_of_l (trail S)) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
finite[simp]: ‹finite (atms_of_ms A)›
shows ‹μ⇩C⇩D⇩C⇩L'_bound A T ≤ μ⇩C⇩D⇩C⇩L'_bound A S›
proof -
have ‹{C. C ∈# clauses⇩N⇩O⇩T T ∧ (tautology C ∨ ¬ distinct_mset C)}
⊆ {C. C ∈# clauses⇩N⇩O⇩T S ∧ (tautology C ∨ ¬ distinct_mset C)}› (is ‹?T ⊆ ?S›)
proof (rule Set.subsetI)
fix C assume ‹C ∈ ?T›
then have C_T: ‹C ∈# clauses⇩N⇩O⇩T T› and t_d: ‹tautology C ∨ ¬ distinct_mset C›
by auto
then have ‹C ∉ simple_clss (atms_of_ms A)›
by (auto dest: simple_clssE)
then show ‹C ∈ ?S›
using C_T rtranclp_cdcl⇩N⇩O⇩T_clauses_bound[OF assms] t_d by force
qed
then have ‹card {C. C ∈# clauses⇩N⇩O⇩T T ∧ (tautology C ∨ ¬ distinct_mset C)} ≤
card {C. C ∈# clauses⇩N⇩O⇩T S ∧ (tautology C ∨ ¬ distinct_mset C)}›
by (simp add: card_mono)
then show ?thesis
unfolding μ⇩C⇩D⇩C⇩L'_bound_def by auto
qed
end
subsection ‹CDCL with Restarts›
subsubsection‹Definition›
locale restart_ops =
fixes
cdcl⇩N⇩O⇩T :: ‹'st ⇒ 'st ⇒ bool› and
restart :: ‹'st ⇒ 'st ⇒ bool›
begin
inductive cdcl⇩N⇩O⇩T_raw_restart :: ‹'st ⇒ 'st ⇒ bool› where
‹cdcl⇩N⇩O⇩T S T ⟹ cdcl⇩N⇩O⇩T_raw_restart S T› |
‹restart S T ⟹ cdcl⇩N⇩O⇩T_raw_restart S T›
end
locale conflict_driven_clause_learning_with_restarts =
conflict_driven_clause_learning trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
inv decide_conds backjump_conds propagate_conds learn_conds forget_conds
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
inv :: ‹'st ⇒ bool› and
decide_conds :: ‹'st ⇒ 'st ⇒ bool› and
backjump_conds :: ‹'v clause ⇒ 'v clause ⇒ 'v literal ⇒ 'st ⇒ 'st ⇒ bool› and
propagate_conds :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st ⇒ bool› and
learn_conds forget_conds :: ‹'v clause ⇒ 'st ⇒ bool›
begin
lemma cdcl⇩N⇩O⇩T_iff_cdcl⇩N⇩O⇩T_raw_restart_no_restarts:
‹cdcl⇩N⇩O⇩T S T ⟷ restart_ops.cdcl⇩N⇩O⇩T_raw_restart cdcl⇩N⇩O⇩T (λ_ _. False) S T›
(is ‹?C S T ⟷ ?R S T›)
proof
fix S T
assume ‹?C S T›
then show ‹?R S T› by (simp add: restart_ops.cdcl⇩N⇩O⇩T_raw_restart.intros(1))
next
fix S T
assume ‹?R S T›
then show ‹?C S T›
apply (cases rule: restart_ops.cdcl⇩N⇩O⇩T_raw_restart.cases)
using ‹?R S T› by fast+
qed
lemma cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_raw_restart:
‹cdcl⇩N⇩O⇩T S T ⟹ restart_ops.cdcl⇩N⇩O⇩T_raw_restart cdcl⇩N⇩O⇩T restart S T›
by (simp add: restart_ops.cdcl⇩N⇩O⇩T_raw_restart.intros(1))
end
subsubsection ‹Increasing restarts›
paragraph ‹Definition›
text ‹
We define our increasing restart very abstractly: the predicate (called @{term cdcl⇩N⇩O⇩T}) does not
have to be a CDCL calculus. We just need some assuptions to prove termination:
▪ a function @{term f} that is strictly monotonic. The first step is actually only used as a
restart to clean the state (e.g. to ensure that the trail is empty). Then we assume that
@{term ‹f n ≥ 1›} for @{term ‹n ≥ 1›}: it means that between two consecutive
restarts, at least one step will be done. This is necessary to avoid sequence. like: full --
restart -- full -- ...
▪ a measure @{term μ}: it should decrease under the assumptions @{term bound_inv}, whenever a
@{term cdcl⇩N⇩O⇩T} or a @{term restart} is done. A parameter is given to @{term μ}: for conflict-
driven clause learning, it is an upper-bound of the clauses. We are assuming that such a bound
can be found after a restart whenever the invariant holds.
▪ we also assume that the measure decrease after any @{term cdcl⇩N⇩O⇩T} step.
▪ an invariant on the states @{term cdcl⇩N⇩O⇩T_inv} that also holds after restarts.
▪ it is ∗‹not required› that the measure decrease with respect to restarts, but the measure has to
be bound by some function @{term μ_bound} taking the same parameter as @{term μ} and the initial
state of the considered @{term cdcl⇩N⇩O⇩T} chain.›
locale cdcl⇩N⇩O⇩T_increasing_restarts_ops =
restart_ops cdcl⇩N⇩O⇩T restart for
restart :: ‹'st ⇒ 'st ⇒ bool› and
cdcl⇩N⇩O⇩T :: ‹'st ⇒ 'st ⇒ bool› +
fixes
f :: ‹nat ⇒ nat› and
bound_inv :: ‹'bound ⇒ 'st ⇒ bool› and
μ :: ‹'bound ⇒ 'st ⇒ nat› and
cdcl⇩N⇩O⇩T_inv :: ‹'st ⇒ bool› and
μ_bound :: ‹'bound ⇒ 'st ⇒ nat›
assumes
f: ‹unbounded f› and
f_ge_1: ‹⋀n. n≥1 ⟹ f n ≠ 0› and
bound_inv: ‹⋀A S T. cdcl⇩N⇩O⇩T_inv S ⟹ bound_inv A S ⟹ cdcl⇩N⇩O⇩T S T ⟹ bound_inv A T› and
cdcl⇩N⇩O⇩T_measure: ‹⋀A S T. cdcl⇩N⇩O⇩T_inv S ⟹ bound_inv A S ⟹ cdcl⇩N⇩O⇩T S T ⟹ μ A T < μ A S› and
measure_bound2: ‹⋀A T U. cdcl⇩N⇩O⇩T_inv T ⟹ bound_inv A T ⟹ cdcl⇩N⇩O⇩T⇧*⇧* T U
⟹ μ A U ≤ μ_bound A T› and
measure_bound4: ‹⋀A T U. cdcl⇩N⇩O⇩T_inv T ⟹ bound_inv A T ⟹ cdcl⇩N⇩O⇩T⇧*⇧* T U
⟹ μ_bound A U ≤ μ_bound A T› and
cdcl⇩N⇩O⇩T_restart_inv: ‹⋀A U V. cdcl⇩N⇩O⇩T_inv U ⟹ restart U V ⟹ bound_inv A U ⟹ bound_inv A V›
and
exists_bound: ‹⋀R S. cdcl⇩N⇩O⇩T_inv R ⟹ restart R S ⟹ ∃A. bound_inv A S› and
cdcl⇩N⇩O⇩T_inv: ‹⋀S T. cdcl⇩N⇩O⇩T_inv S ⟹ cdcl⇩N⇩O⇩T S T ⟹ cdcl⇩N⇩O⇩T_inv T› and
cdcl⇩N⇩O⇩T_inv_restart: ‹⋀S T. cdcl⇩N⇩O⇩T_inv S ⟹ restart S T ⟹ cdcl⇩N⇩O⇩T_inv T›
begin
lemma cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv:
assumes
‹(cdcl⇩N⇩O⇩T^^n) S T› and
‹cdcl⇩N⇩O⇩T_inv S›
shows ‹cdcl⇩N⇩O⇩T_inv T›
using assms by (induction n arbitrary: T) (auto intro:bound_inv cdcl⇩N⇩O⇩T_inv)
lemma cdcl⇩N⇩O⇩T_bound_inv:
assumes
‹(cdcl⇩N⇩O⇩T^^n) S T› and
‹cdcl⇩N⇩O⇩T_inv S›
‹bound_inv A S›
shows ‹bound_inv A T›
using assms by (induction n arbitrary: T) (auto intro:bound_inv cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv)
lemma rtranclp_cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv:
assumes
‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and
‹cdcl⇩N⇩O⇩T_inv S›
shows ‹cdcl⇩N⇩O⇩T_inv T›
using assms by induction (auto intro: cdcl⇩N⇩O⇩T_inv)
lemma rtranclp_cdcl⇩N⇩O⇩T_bound_inv:
assumes
‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and
‹bound_inv A S› and
‹cdcl⇩N⇩O⇩T_inv S›
shows ‹bound_inv A T›
using assms by induction (auto intro:bound_inv rtranclp_cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv)
lemma cdcl⇩N⇩O⇩T_comp_n_le:
assumes
‹(cdcl⇩N⇩O⇩T^^(Suc n)) S T› and
‹bound_inv A S›
‹cdcl⇩N⇩O⇩T_inv S›
shows ‹μ A T < μ A S - n›
using assms
proof (induction n arbitrary: T)
case 0
then show ?case using cdcl⇩N⇩O⇩T_measure by auto
next
case (Suc n) note IH = this(1)[OF _ this(3) this(4)] and S_T = this(2) and b_inv = this(3) and
c_inv = this(4)
obtain U :: 'st where S_U: ‹(cdcl⇩N⇩O⇩T^^(Suc n)) S U› and U_T: ‹cdcl⇩N⇩O⇩T U T› using S_T by auto
then have ‹μ A U < μ A S - n› using IH[of U] by simp
moreover
have ‹bound_inv A U›
using S_U b_inv cdcl⇩N⇩O⇩T_bound_inv c_inv by blast
then have ‹μ A T < μ A U› using cdcl⇩N⇩O⇩T_measure[OF _ _ U_T] S_U c_inv cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv by auto
ultimately show ?case by linarith
qed
lemma wf_cdcl⇩N⇩O⇩T:
‹wf {(T, S). cdcl⇩N⇩O⇩T S T ∧ cdcl⇩N⇩O⇩T_inv S ∧ bound_inv A S}› (is ‹wf ?A›)
apply (rule wfP_if_measure2[of _ _ ‹μ A›])
using cdcl⇩N⇩O⇩T_comp_n_le[of 0 _ _ A] by auto
lemma rtranclp_cdcl⇩N⇩O⇩T_measure:
assumes
‹cdcl⇩N⇩O⇩T⇧*⇧* S T› and
‹bound_inv A S› and
‹cdcl⇩N⇩O⇩T_inv S›
shows ‹μ A T ≤ μ A S›
using assms
proof (induction rule: rtranclp_induct)
case base
then show ?case by auto
next
case (step T U) note IH = this(3)[OF this(4) this(5)] and st = this(1) and cdcl⇩N⇩O⇩T = this(2) and
b_inv = this(4) and c_inv = this(5)
have ‹bound_inv A T›
by (meson cdcl⇩N⇩O⇩T_bound_inv rtranclp_imp_relpowp st step.prems)
moreover have ‹cdcl⇩N⇩O⇩T_inv T›
using c_inv rtranclp_cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv st by blast
ultimately have ‹μ A U < μ A T› using cdcl⇩N⇩O⇩T_measure[OF _ _ cdcl⇩N⇩O⇩T] by auto
then show ?case using IH by linarith
qed
lemma cdcl⇩N⇩O⇩T_comp_bounded:
assumes
‹bound_inv A S› and ‹cdcl⇩N⇩O⇩T_inv S› and ‹m ≥ 1+μ A S›
shows ‹¬(cdcl⇩N⇩O⇩T ^^ m) S T›
using assms cdcl⇩N⇩O⇩T_comp_n_le[of ‹m-1› S T A] by fastforce
text ‹
▪ @{term ‹m > f n›} ensures that at least one step has been done.›
inductive cdcl⇩N⇩O⇩T_restart where
restart_step: ‹(cdcl⇩N⇩O⇩T^^m) S T ⟹ m ≥ f n ⟹ restart T U
⟹ cdcl⇩N⇩O⇩T_restart (S, n) (U, Suc n)› |
restart_full: ‹full1 cdcl⇩N⇩O⇩T S T ⟹ cdcl⇩N⇩O⇩T_restart (S, n) (T, Suc n)›
lemmas cdcl⇩N⇩O⇩T_with_restart_induct = cdcl⇩N⇩O⇩T_restart.induct[split_format(complete),
OF cdcl⇩N⇩O⇩T_increasing_restarts_ops_axioms]
lemma cdcl⇩N⇩O⇩T_restart_cdcl⇩N⇩O⇩T_raw_restart:
‹cdcl⇩N⇩O⇩T_restart S T ⟹ cdcl⇩N⇩O⇩T_raw_restart⇧*⇧* (fst S) (fst T)›
proof (induction rule: cdcl⇩N⇩O⇩T_restart.induct)
case (restart_step m S T n U)
then have ‹cdcl⇩N⇩O⇩T⇧*⇧* S T› by (meson relpowp_imp_rtranclp)
then have ‹cdcl⇩N⇩O⇩T_raw_restart⇧*⇧* S T› using cdcl⇩N⇩O⇩T_raw_restart.intros(1)
rtranclp_mono[of cdcl⇩N⇩O⇩T cdcl⇩N⇩O⇩T_raw_restart] by blast
moreover have ‹cdcl⇩N⇩O⇩T_raw_restart T U›
using ‹restart T U› cdcl⇩N⇩O⇩T_raw_restart.intros(2) by blast
ultimately show ?case by auto
next
case (restart_full S T)
then have ‹cdcl⇩N⇩O⇩T⇧*⇧* S T› unfolding full1_def by auto
then show ?case using cdcl⇩N⇩O⇩T_raw_restart.intros(1)
rtranclp_mono[of cdcl⇩N⇩O⇩T cdcl⇩N⇩O⇩T_raw_restart] by auto
qed
lemma cdcl⇩N⇩O⇩T_with_restart_bound_inv:
assumes
‹cdcl⇩N⇩O⇩T_restart S T› and
‹bound_inv A (fst S)› and
‹cdcl⇩N⇩O⇩T_inv (fst S)›
shows ‹bound_inv A (fst T)›
using assms apply (induction rule: cdcl⇩N⇩O⇩T_restart.induct)
prefer 2 apply (metis rtranclp_unfold fstI full1_def rtranclp_cdcl⇩N⇩O⇩T_bound_inv)
by (metis cdcl⇩N⇩O⇩T_bound_inv cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv cdcl⇩N⇩O⇩T_restart_inv fst_conv)
lemma cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv:
assumes
‹cdcl⇩N⇩O⇩T_restart S T› and
‹cdcl⇩N⇩O⇩T_inv (fst S)›
shows ‹cdcl⇩N⇩O⇩T_inv (fst T)›
using assms apply induction
apply (metis cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv cdcl⇩N⇩O⇩T_inv_restart fst_conv)
apply (metis fstI full_def full_unfold rtranclp_cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv)
done
lemma rtranclp_cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv:
assumes
‹cdcl⇩N⇩O⇩T_restart⇧*⇧* S T› and
‹cdcl⇩N⇩O⇩T_inv (fst S)›
shows ‹cdcl⇩N⇩O⇩T_inv (fst T)›
using assms by induction (auto intro: cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv)
lemma rtranclp_cdcl⇩N⇩O⇩T_with_restart_bound_inv:
assumes
‹cdcl⇩N⇩O⇩T_restart⇧*⇧* S T› and
‹cdcl⇩N⇩O⇩T_inv (fst S)› and
‹bound_inv A (fst S)›
shows ‹bound_inv A (fst T)›
using assms apply induction
apply (simp add: cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv cdcl⇩N⇩O⇩T_with_restart_bound_inv)
using cdcl⇩N⇩O⇩T_with_restart_bound_inv rtranclp_cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv by blast
lemma cdcl⇩N⇩O⇩T_with_restart_increasing_number:
‹cdcl⇩N⇩O⇩T_restart S T ⟹ snd T = 1 + snd S›
by (induction rule: cdcl⇩N⇩O⇩T_restart.induct) auto
end
locale cdcl⇩N⇩O⇩T_increasing_restarts =
cdcl⇩N⇩O⇩T_increasing_restarts_ops restart cdcl⇩N⇩O⇩T f bound_inv μ cdcl⇩N⇩O⇩T_inv μ_bound +
dpll_state trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
f :: ‹nat ⇒ nat› and
restart :: ‹'st ⇒ 'st ⇒ bool› and
bound_inv :: ‹'bound ⇒ 'st ⇒ bool› and
μ :: ‹'bound ⇒ 'st ⇒ nat› and
cdcl⇩N⇩O⇩T :: ‹'st ⇒ 'st ⇒ bool› and
cdcl⇩N⇩O⇩T_inv :: ‹'st ⇒ bool› and
μ_bound :: ‹'bound ⇒ 'st ⇒ nat› +
assumes
measure_bound: ‹⋀A T V n. cdcl⇩N⇩O⇩T_inv T ⟹ bound_inv A T
⟹ cdcl⇩N⇩O⇩T_restart (T, n) (V, Suc n) ⟹ μ A V ≤ μ_bound A T› and
cdcl⇩N⇩O⇩T_raw_restart_μ_bound:
‹cdcl⇩N⇩O⇩T_restart (T, a) (V, b) ⟹ cdcl⇩N⇩O⇩T_inv T ⟹ bound_inv A T
⟹ μ_bound A V ≤ μ_bound A T›
begin
lemma rtranclp_cdcl⇩N⇩O⇩T_raw_restart_μ_bound:
‹cdcl⇩N⇩O⇩T_restart⇧*⇧* (T, a) (V, b) ⟹ cdcl⇩N⇩O⇩T_inv T ⟹ bound_inv A T
⟹ μ_bound A V ≤ μ_bound A T›
apply (induction rule: rtranclp_induct2)
apply simp
by (metis cdcl⇩N⇩O⇩T_raw_restart_μ_bound dual_order.trans fst_conv
rtranclp_cdcl⇩N⇩O⇩T_with_restart_bound_inv rtranclp_cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv)
lemma cdcl⇩N⇩O⇩T_raw_restart_measure_bound:
‹cdcl⇩N⇩O⇩T_restart (T, a) (V, b) ⟹ cdcl⇩N⇩O⇩T_inv T ⟹ bound_inv A T
⟹ μ A V ≤ μ_bound A T›
apply (cases rule: cdcl⇩N⇩O⇩T_restart.cases)
apply simp
using measure_bound relpowp_imp_rtranclp apply fastforce
by (metis full_def full_unfold measure_bound2 prod.inject)
lemma rtranclp_cdcl⇩N⇩O⇩T_raw_restart_measure_bound:
‹cdcl⇩N⇩O⇩T_restart⇧*⇧* (T, a) (V, b) ⟹ cdcl⇩N⇩O⇩T_inv T ⟹ bound_inv A T
⟹ μ A V ≤ μ_bound A T›
apply (induction rule: rtranclp_induct2)
apply (simp add: measure_bound2)
by (metis dual_order.trans fst_conv measure_bound2 r_into_rtranclp rtranclp.rtrancl_refl
rtranclp_cdcl⇩N⇩O⇩T_with_restart_bound_inv rtranclp_cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv
rtranclp_cdcl⇩N⇩O⇩T_raw_restart_μ_bound)
lemma wf_cdcl⇩N⇩O⇩T_restart:
‹wf {(T, S). cdcl⇩N⇩O⇩T_restart S T ∧ cdcl⇩N⇩O⇩T_inv (fst S)}› (is ‹wf ?A›)
proof (rule ccontr)
assume ‹¬ ?thesis›
then obtain g where
g: ‹⋀i. cdcl⇩N⇩O⇩T_restart (g i) (g (Suc i))› and
cdcl⇩N⇩O⇩T_inv_g: ‹⋀i. cdcl⇩N⇩O⇩T_inv (fst (g i))›
unfolding wf_iff_no_infinite_down_chain by fast
have snd_g: ‹⋀i. snd (g i) = i + snd (g 0)›
apply (induct_tac i)
apply simp
by (metis Suc_eq_plus1_left add.commute add.left_commute
cdcl⇩N⇩O⇩T_with_restart_increasing_number g)
then have snd_g_0: ‹⋀i. i > 0 ⟹ snd (g i) = i + snd (g 0)›
by blast
have unbounded_f_g: ‹unbounded (λi. f (snd (g i)))›
using f unfolding bounded_def by (metis add.commute f less_or_eq_imp_le snd_g
not_bounded_nat_exists_larger not_le le_iff_add)
{ fix i
have H: ‹⋀T Ta m. (cdcl⇩N⇩O⇩T ^^ m) T Ta ⟹ no_step cdcl⇩N⇩O⇩T T ⟹ m = 0›
apply (case_tac m) by simp (meson relpowp_E2)
have ‹∃ T m. (cdcl⇩N⇩O⇩T ^^ m) (fst (g i)) T ∧ m ≥ f (snd (g i))›
using g[of i] apply (cases rule: cdcl⇩N⇩O⇩T_restart.cases)
apply auto[]
using g[of ‹Suc i›] f_ge_1 apply (cases rule: cdcl⇩N⇩O⇩T_restart.cases)
apply (auto simp add: full1_def full_def dest: H dest: tranclpD)
using H Suc_leI leD by blast
} note H = this
obtain A where ‹bound_inv A (fst (g 1))›
using g[of 0] cdcl⇩N⇩O⇩T_inv_g[of 0] apply (cases rule: cdcl⇩N⇩O⇩T_restart.cases)
apply (metis One_nat_def cdcl⇩N⇩O⇩T_inv exists_bound fst_conv relpowp_imp_rtranclp
rtranclp_induct)
using H[of 1] unfolding full1_def by (metis One_nat_def Suc_eq_plus1 diff_is_0_eq' diff_zero
f_ge_1 fst_conv le_add2 relpowp_E2 snd_conv)
let ?j = ‹μ_bound A (fst (g 1)) + 1›
obtain j where
j: ‹f (snd (g j)) > ?j› and ‹j > 1›
using unbounded_f_g not_bounded_nat_exists_larger by blast
{
fix i j
have cdcl⇩N⇩O⇩T_with_restart: ‹j ≥ i ⟹ cdcl⇩N⇩O⇩T_restart⇧*⇧* (g i) (g j)›
apply (induction j)
apply simp
by (metis g le_Suc_eq rtranclp.rtrancl_into_rtrancl rtranclp.rtrancl_refl)
} note cdcl⇩N⇩O⇩T_restart = this
have ‹cdcl⇩N⇩O⇩T_inv (fst (g (Suc 0)))›
by (simp add: cdcl⇩N⇩O⇩T_inv_g)
have ‹cdcl⇩N⇩O⇩T_restart⇧*⇧* (fst (g 1), snd (g 1)) (fst (g j), snd (g j))›
using ‹j> 1› by (simp add: cdcl⇩N⇩O⇩T_restart)
have ‹μ A (fst (g j)) ≤ μ_bound A (fst (g 1))›
apply (rule rtranclp_cdcl⇩N⇩O⇩T_raw_restart_measure_bound)
using ‹cdcl⇩N⇩O⇩T_restart⇧*⇧* (fst (g 1), snd (g 1)) (fst (g j), snd (g j))› apply blast
apply (simp add: cdcl⇩N⇩O⇩T_inv_g)
using ‹bound_inv A (fst (g 1))› apply simp
done
then have ‹μ A (fst (g j)) ≤ ?j›
by auto
have inv: ‹bound_inv A (fst (g j))›
using ‹bound_inv A (fst (g 1))› ‹cdcl⇩N⇩O⇩T_inv (fst (g (Suc 0)))›
‹cdcl⇩N⇩O⇩T_restart⇧*⇧* (fst (g 1), snd (g 1)) (fst (g j), snd (g j))›
rtranclp_cdcl⇩N⇩O⇩T_with_restart_bound_inv by auto
obtain T m where
cdcl⇩N⇩O⇩T_m: ‹(cdcl⇩N⇩O⇩T ^^ m) (fst (g j)) T› and
f_m: ‹f (snd (g j)) ≤ m›
using H[of j] by blast
have ‹?j < m›
using f_m j Nat.le_trans by linarith
then show False
using ‹μ A (fst (g j)) ≤ μ_bound A (fst (g 1))›
cdcl⇩N⇩O⇩T_comp_bounded[OF inv cdcl⇩N⇩O⇩T_inv_g, of ] cdcl⇩N⇩O⇩T_inv_g cdcl⇩N⇩O⇩T_m
‹?j < m› by auto
qed
lemma cdcl⇩N⇩O⇩T_restart_steps_bigger_than_bound:
assumes
‹cdcl⇩N⇩O⇩T_restart S T› and
‹bound_inv A (fst S)› and
‹cdcl⇩N⇩O⇩T_inv (fst S)› and
‹f (snd S) > μ_bound A (fst S)›
shows ‹full1 cdcl⇩N⇩O⇩T (fst S) (fst T)›
using assms
proof (induction rule: cdcl⇩N⇩O⇩T_restart.induct)
case restart_full
then show ?case by auto
next
case (restart_step m S T n U) note st = this(1) and f = this(2) and bound_inv = this(4) and
cdcl⇩N⇩O⇩T_inv = this(5) and μ = this(6)
then obtain m' where m: ‹m = Suc m'› by (cases m) auto
have ‹μ A S - m' = 0›
using f bound_inv cdcl⇩N⇩O⇩T_inv μ m rtranclp_cdcl⇩N⇩O⇩T_raw_restart_measure_bound by fastforce
then have False using cdcl⇩N⇩O⇩T_comp_n_le[of m' S T A] restart_step unfolding m by simp
then show ?case by fast
qed
lemma rtranclp_cdcl⇩N⇩O⇩T_with_inv_inv_rtranclp_cdcl⇩N⇩O⇩T:
assumes
inv: ‹cdcl⇩N⇩O⇩T_inv S› and
binv: ‹bound_inv A S›
shows ‹(λS T. cdcl⇩N⇩O⇩T S T ∧ cdcl⇩N⇩O⇩T_inv S ∧ bound_inv A S)⇧*⇧* S T ⟷ cdcl⇩N⇩O⇩T⇧*⇧* S T›
(is ‹?A⇧*⇧* S T ⟷ ?B⇧*⇧* S T›)
apply (rule iffI)
using rtranclp_mono[of ?A ?B] apply blast
apply (induction rule: rtranclp_induct)
using inv binv apply simp
by (metis (mono_tags, lifting) binv inv rtranclp.simps rtranclp_cdcl⇩N⇩O⇩T_bound_inv
rtranclp_cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv)
lemma no_step_cdcl⇩N⇩O⇩T_restart_no_step_cdcl⇩N⇩O⇩T:
assumes
n_s: ‹no_step cdcl⇩N⇩O⇩T_restart S› and
inv: ‹cdcl⇩N⇩O⇩T_inv (fst S)› and
binv: ‹bound_inv A (fst S)›
shows ‹no_step cdcl⇩N⇩O⇩T (fst S)›
proof (rule ccontr)
assume ‹¬ ?thesis›
then obtain T where T: ‹cdcl⇩N⇩O⇩T (fst S) T›
by blast
then obtain U where U: ‹full (λS T. cdcl⇩N⇩O⇩T S T ∧ cdcl⇩N⇩O⇩T_inv S ∧ bound_inv A S) T U›
using wf_exists_normal_form_full[OF wf_cdcl⇩N⇩O⇩T, of A T] by auto
moreover have inv_T: ‹cdcl⇩N⇩O⇩T_inv T›
using ‹cdcl⇩N⇩O⇩T (fst S) T› cdcl⇩N⇩O⇩T_inv inv by blast
moreover have b_inv_T: ‹bound_inv A T›
using ‹cdcl⇩N⇩O⇩T (fst S) T› binv bound_inv inv by blast
ultimately have ‹full cdcl⇩N⇩O⇩T T U›
using rtranclp_cdcl⇩N⇩O⇩T_with_inv_inv_rtranclp_cdcl⇩N⇩O⇩T rtranclp_cdcl⇩N⇩O⇩T_bound_inv
rtranclp_cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv unfolding full_def by blast
then have ‹full1 cdcl⇩N⇩O⇩T (fst S) U›
using T full_fullI by metis
then show False by (metis n_s prod.collapse restart_full)
qed
end
subsection ‹Merging backjump and learning›
locale cdcl⇩N⇩O⇩T_merge_bj_learn_ops =
decide_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T decide_conds +
forget_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T forget_conds +
propagate_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T propagate_conds
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
decide_conds :: ‹'st ⇒ 'st ⇒ bool› and
propagate_conds :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st ⇒ bool› and
forget_conds :: ‹'v clause ⇒ 'st ⇒ bool› +
fixes backjump_l_cond :: ‹'v clause ⇒ 'v clause ⇒ 'v literal ⇒ 'st ⇒ 'st ⇒ bool›
begin
text ‹We have a new backjump that combines the backjumping on the trail and the learning of the
used clause (called @{term C''} below)›
inductive backjump_l where
backjump_l: ‹trail S = F' @ Decided K # F
⟹ T ∼ prepend_trail (Propagated L ()) (reduce_trail_to⇩N⇩O⇩T F (add_cls⇩N⇩O⇩T C'' S))
⟹ C ∈# clauses⇩N⇩O⇩T S
⟹ trail S ⊨as CNot C
⟹ undefined_lit F L
⟹ atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))
⟹ clauses⇩N⇩O⇩T S ⊨pm add_mset L C'
⟹ C'' = add_mset L C'
⟹ F ⊨as CNot C'
⟹ backjump_l_cond C C' L S T
⟹ backjump_l S T›
text ‹Avoid (meaningless) simplification in the theorem generated by ‹inductive_cases›:›
declare reduce_trail_to⇩N⇩O⇩T_length_ne[simp del] Set.Un_iff[simp del] Set.insert_iff[simp del]
inductive_cases backjump_lE: ‹backjump_l S T›
thm backjump_lE
declare reduce_trail_to⇩N⇩O⇩T_length_ne[simp] Set.Un_iff[simp] Set.insert_iff[simp]
inductive cdcl⇩N⇩O⇩T_merged_bj_learn :: ‹'st ⇒ 'st ⇒ bool› for S :: 'st where
cdcl⇩N⇩O⇩T_merged_bj_learn_decide⇩N⇩O⇩T: ‹decide⇩N⇩O⇩T S S' ⟹ cdcl⇩N⇩O⇩T_merged_bj_learn S S'› |
cdcl⇩N⇩O⇩T_merged_bj_learn_propagate⇩N⇩O⇩T: ‹propagate⇩N⇩O⇩T S S' ⟹ cdcl⇩N⇩O⇩T_merged_bj_learn S S'› |
cdcl⇩N⇩O⇩T_merged_bj_learn_backjump_l: ‹backjump_l S S' ⟹ cdcl⇩N⇩O⇩T_merged_bj_learn S S'› |
cdcl⇩N⇩O⇩T_merged_bj_learn_forget⇩N⇩O⇩T: ‹forget⇩N⇩O⇩T S S' ⟹ cdcl⇩N⇩O⇩T_merged_bj_learn S S'›
lemma cdcl⇩N⇩O⇩T_merged_bj_learn_no_dup_inv:
‹cdcl⇩N⇩O⇩T_merged_bj_learn S T ⟹ no_dup (trail S) ⟹ no_dup (trail T)›
apply (induction rule: cdcl⇩N⇩O⇩T_merged_bj_learn.induct)
using defined_lit_map apply fastforce
using defined_lit_map apply fastforce
apply (force simp: defined_lit_map elim!: backjump_lE dest: no_dup_appendD)[]
using forget⇩N⇩O⇩T.simps apply (auto; fail)
done
end
locale cdcl⇩N⇩O⇩T_merge_bj_learn_proxy =
cdcl⇩N⇩O⇩T_merge_bj_learn_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
decide_conds propagate_conds forget_conds
‹λC C' L' S T. backjump_l_cond C C' L' S T
∧ distinct_mset C' ∧ L' ∉# C' ∧ ¬tautology (add_mset L' C')›
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
decide_conds :: ‹'st ⇒ 'st ⇒ bool› and
propagate_conds :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st ⇒ bool› and
forget_conds :: ‹'v clause ⇒ 'st ⇒ bool› and
backjump_l_cond :: ‹'v clause ⇒ 'v clause ⇒ 'v literal ⇒ 'st ⇒ 'st ⇒ bool› +
fixes
inv :: ‹'st ⇒ bool›
begin
abbreviation backjump_conds :: ‹'v clause ⇒ 'v clause ⇒ 'v literal ⇒ 'st ⇒ 'st ⇒ bool›
where
‹backjump_conds ≡ λC C' L' S T. distinct_mset C' ∧ L' ∉# C' ∧ ¬tautology (add_mset L' C')›
sublocale backjumping_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
backjump_conds
by standard
end
locale cdcl⇩N⇩O⇩T_merge_bj_learn =
cdcl⇩N⇩O⇩T_merge_bj_learn_proxy trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
decide_conds propagate_conds forget_conds backjump_l_cond inv
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
decide_conds :: ‹'st ⇒ 'st ⇒ bool› and
propagate_conds :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st ⇒ bool› and
forget_conds :: ‹'v clause ⇒ 'st ⇒ bool› and
backjump_l_cond :: ‹'v clause ⇒ 'v clause ⇒ 'v literal ⇒ 'st ⇒ 'st ⇒ bool› and
inv :: ‹'st ⇒ bool› +
assumes
bj_merge_can_jump:
‹⋀S C F' K F L.
inv S
⟹ trail S = F' @ Decided K # F
⟹ C ∈# clauses⇩N⇩O⇩T S
⟹ trail S ⊨as CNot C
⟹ undefined_lit F L
⟹ atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (F' @ Decided K # F))
⟹ clauses⇩N⇩O⇩T S ⊨pm add_mset L C'
⟹ F ⊨as CNot C'
⟹ ¬no_step backjump_l S› and
cdcl_merged_inv: ‹⋀S T. cdcl⇩N⇩O⇩T_merged_bj_learn S T ⟹ inv S ⟹ inv T› and
can_propagate_or_decide_or_backjump_l:
‹atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S) ⟹
undefined_lit (trail S) L ⟹
inv S ⟹
satisfiable (set_mset (clauses⇩N⇩O⇩T S)) ⟹
∃T. decide⇩N⇩O⇩T S T ∨ propagate⇩N⇩O⇩T S T ∨ backjump_l S T›
begin
lemma backjump_no_step_backjump_l:
‹backjump S T ⟹ inv S ⟹ ¬no_step backjump_l S›
apply (elim backjumpE)
apply (rule bj_merge_can_jump)
apply auto[7]
by blast
lemma tautology_single_add:
‹tautology (L + {#a#}) ⟷ tautology L ∨ -a ∈# L›
unfolding tautology_decomp by (cases a) auto
lemma backjump_l_implies_exists_backjump:
assumes bj: ‹backjump_l S T› and ‹inv S› and n_d: ‹no_dup (trail S)›
shows ‹∃U. backjump S U›
proof -
obtain C F' K F L C' where
tr: ‹trail S = F' @ Decided K # F› and
C: ‹C ∈# clauses⇩N⇩O⇩T S› and
T: ‹T ∼ prepend_trail (Propagated L ()) (reduce_trail_to⇩N⇩O⇩T F (add_cls⇩N⇩O⇩T (add_mset L C') S))› and
tr_C: ‹trail S ⊨as CNot C› and
undef: ‹undefined_lit F L› and
L: ‹atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))› and
S_C_L: ‹clauses⇩N⇩O⇩T S ⊨pm add_mset L C'› and
F_C': ‹F ⊨as CNot C'› and
cond: ‹backjump_l_cond C C' L S T› and
dist: ‹distinct_mset (add_mset L C')› and
taut: ‹¬ tautology (add_mset L C')›
using bj by (elim backjump_lE) force
have ‹L ∉# C'›
using dist by auto
show ?thesis
using backjump.intros[OF tr _ C tr_C undef L S_C_L F_C'] cond dist taut
by auto
qed
text ‹Without additional knowledge on @{term backjump_l_cond}, it is impossible to have the same
invariant.›
sublocale dpll_with_backjumping_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
inv decide_conds backjump_conds propagate_conds
proof (unfold_locales, goal_cases)
case 1
{ fix S S'
assume bj: ‹backjump_l S S'›
then obtain F' K F L C' C D where
S': ‹S' ∼ prepend_trail (Propagated L ()) (reduce_trail_to⇩N⇩O⇩T F (add_cls⇩N⇩O⇩T D S))›
and
tr_S: ‹trail S = F' @ Decided K # F› and
C: ‹C ∈# clauses⇩N⇩O⇩T S› and
tr_S_C: ‹trail S ⊨as CNot C› and
undef_L: ‹undefined_lit F L› and
atm_L:
‹atm_of L ∈ insert (atm_of K) (atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l F' ∪ lits_of_l F))›
and
cls_S_C': ‹clauses⇩N⇩O⇩T S ⊨pm add_mset L C'› and
F_C': ‹F ⊨as CNot C'› and
dist: ‹distinct_mset (add_mset L C')› and
not_tauto: ‹¬ tautology (add_mset L C')› and
cond: ‹backjump_l_cond C C' L S S'›
‹D = add_mset L C'›
by (elim backjump_lE) simp
interpret backjumping_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
backjump_conds
by unfold_locales
have ‹∃T. backjump S T›
apply rule
apply (rule backjump.intros)
using tr_S apply simp
apply (rule state_eq⇩N⇩O⇩T_ref)
using C apply simp
using tr_S_C apply simp
using undef_L apply simp
using atm_L tr_S apply simp
using cls_S_C' apply simp
using F_C' apply simp
using dist not_tauto cond by simp
}
then show ?case using 1 bj_merge_can_jump by meson
next
case 2
then show ?case
using can_propagate_or_decide_or_backjump_l backjump_l_implies_exists_backjump by blast
qed
sublocale conflict_driven_clause_learning_ops trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T
remove_cls⇩N⇩O⇩T inv decide_conds backjump_conds propagate_conds
‹λC _. distinct_mset C ∧ ¬tautology C›
forget_conds
by unfold_locales
lemma backjump_l_learn_backjump:
assumes bt: ‹backjump_l S T› and inv: ‹inv S›
shows ‹∃C' L D. learn S (add_cls⇩N⇩O⇩T D S)
∧ D = add_mset L C'
∧ backjump (add_cls⇩N⇩O⇩T D S) T
∧ atms_of (add_mset L C') ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))›
proof -
obtain C F' K F L l C' D where
tr_S: ‹trail S = F' @ Decided K # F› and
T: ‹T ∼ prepend_trail (Propagated L l) (reduce_trail_to⇩N⇩O⇩T F (add_cls⇩N⇩O⇩T D S))› and
C_cls_S: ‹C ∈# clauses⇩N⇩O⇩T S› and
tr_S_CNot_C: ‹trail S ⊨as CNot C› and
undef: ‹undefined_lit F L› and
atm_L: ‹atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))› and
clss_C: ‹clauses⇩N⇩O⇩T S ⊨pm D› and
D: ‹D = add_mset L C'›
‹F ⊨as CNot C'› and
distinct: ‹distinct_mset D› and
not_tauto: ‹¬ tautology D› and
cond: ‹backjump_l_cond C C' L S T›
using bt inv by (elim backjump_lE) simp
have atms_C': ‹atms_of C' ⊆ atm_of ` (lits_of_l F)›
by (metis D(2) atms_of_def image_subsetI true_annots_CNot_all_atms_defined)
then have ‹atms_of (add_mset L C') ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))›
using atm_L tr_S by auto
moreover have learn: ‹learn S (add_cls⇩N⇩O⇩T D S)›
apply (rule learn.intros)
apply (rule clss_C)
using atms_C' atm_L D apply (fastforce simp add: tr_S in_plus_implies_atm_of_on_atms_of_ms)
apply standard
apply (rule distinct)
apply (rule not_tauto)
apply simp
done
moreover have bj: ‹backjump (add_cls⇩N⇩O⇩T D S) T›
apply (rule backjump.intros[of _ _ _ _ _ L C C'])
using ‹F ⊨as CNot C'› C_cls_S tr_S_CNot_C undef T distinct not_tauto D cond
by (auto simp: tr_S state_eq⇩N⇩O⇩T_def simp del: state_simp⇩N⇩O⇩T)
ultimately show ?thesis using D by blast
qed
lemma backjump_l_backjump_learn:
assumes bt: ‹backjump_l S T› and inv: ‹inv S›
shows ‹∃C' L D S'. backjump S S'
∧ learn S' T
∧ D = (add_mset L C')
∧ T ∼ add_cls⇩N⇩O⇩T D S'
∧ atms_of (add_mset L C') ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))
∧ clauses⇩N⇩O⇩T S ⊨pm D›
proof -
obtain C F' K F L l C' D where
tr_S: ‹trail S = F' @ Decided K # F› and
T: ‹T ∼ prepend_trail (Propagated L l) (reduce_trail_to⇩N⇩O⇩T F (add_cls⇩N⇩O⇩T D S))› and
C_cls_S: ‹C ∈# clauses⇩N⇩O⇩T S› and
tr_S_CNot_C: ‹trail S ⊨as CNot C› and
undef: ‹undefined_lit F L› and
atm_L: ‹atm_of L ∈ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))› and
clss_C: ‹clauses⇩N⇩O⇩T S ⊨pm D› and
D: ‹D = add_mset L C'›
‹F ⊨as CNot C'› and
distinct: ‹distinct_mset D› and
not_tauto: ‹¬ tautology D› and
cond: ‹backjump_l_cond C C' L S T›
using bt inv by (elim backjump_lE) simp
let ?S' = ‹prepend_trail (Propagated L ()) (reduce_trail_to⇩N⇩O⇩T F S)›
have atms_C': ‹atms_of C' ⊆ atm_of ` (lits_of_l F)›
by (metis D(2) atms_of_def image_subsetI true_annots_CNot_all_atms_defined)
then have ‹atms_of (add_mset L C') ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))›
using atm_L tr_S by auto
moreover have learn: ‹learn ?S' T›
apply (rule learn.intros)
using clss_C apply auto[]
using atms_C' atm_L D apply (fastforce simp add: tr_S in_plus_implies_atm_of_on_atms_of_ms)
apply standard
apply (rule distinct)
apply (rule not_tauto)
using T apply (auto simp: tr_S state_eq⇩N⇩O⇩T_def simp del: state_simp⇩N⇩O⇩T)
done
moreover have bj: ‹backjump S (prepend_trail (Propagated L ()) (reduce_trail_to⇩N⇩O⇩T F S))›
apply (rule backjump.intros[of S F' K F _ L])
using ‹F ⊨as CNot C'› C_cls_S tr_S_CNot_C undef T distinct not_tauto D cond clss_C atm_L
by (auto simp: tr_S)
moreover have ‹T ∼ (add_cls⇩N⇩O⇩T D ?S')›
using T by (auto simp: tr_S state_eq⇩N⇩O⇩T_def simp del: state_simp⇩N⇩O⇩T)
ultimately show ?thesis
using D clss_C by blast
qed
lemma cdcl⇩N⇩O⇩T_merged_bj_learn_is_tranclp_cdcl⇩N⇩O⇩T:
‹cdcl⇩N⇩O⇩T_merged_bj_learn S T ⟹ inv S ⟹ cdcl⇩N⇩O⇩T⇧+⇧+ S T›
proof (induction rule: cdcl⇩N⇩O⇩T_merged_bj_learn.induct)
case (cdcl⇩N⇩O⇩T_merged_bj_learn_decide⇩N⇩O⇩T T)
then have ‹cdcl⇩N⇩O⇩T S T›
using bj_decide⇩N⇩O⇩T cdcl⇩N⇩O⇩T.simps by fastforce
then show ?case by auto
next
case (cdcl⇩N⇩O⇩T_merged_bj_learn_propagate⇩N⇩O⇩T T)
then have ‹cdcl⇩N⇩O⇩T S T›
using bj_propagate⇩N⇩O⇩T cdcl⇩N⇩O⇩T.simps by fastforce
then show ?case by auto
next
case (cdcl⇩N⇩O⇩T_merged_bj_learn_forget⇩N⇩O⇩T T)
then have ‹cdcl⇩N⇩O⇩T S T›
using c_forget⇩N⇩O⇩T by blast
then show ?case by auto
next
case (cdcl⇩N⇩O⇩T_merged_bj_learn_backjump_l T) note bt = this(1) and inv = this(2)
obtain C' :: ‹'v clause› and L :: ‹'v literal› and D :: ‹'v clause› where
f3: ‹learn S (add_cls⇩N⇩O⇩T D S) ∧
backjump (add_cls⇩N⇩O⇩T D S) T ∧
atms_of (add_mset L C') ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` lits_of_l (trail S)› and
D: ‹D = add_mset L C'›
using backjump_l_learn_backjump[OF bt inv] by blast
then have f4: ‹cdcl⇩N⇩O⇩T S (add_cls⇩N⇩O⇩T D S)›
using c_learn by blast
have ‹cdcl⇩N⇩O⇩T (add_cls⇩N⇩O⇩T D S) T›
using f3 bj_backjump c_dpll_bj by blast
then show ?case
using f4 by (meson tranclp.r_into_trancl tranclp.trancl_into_trancl)
qed
lemma rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T_and_inv:
‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T ⟹ inv S ⟹ cdcl⇩N⇩O⇩T⇧*⇧* S T ∧ inv T›
proof (induction rule: rtranclp_induct)
case base
then show ?case by auto
next
case (step T U) note st = this(1) and cdcl⇩N⇩O⇩T = this(2) and IH = this(3)[OF this(4-)] and
inv = this(4)
have ‹cdcl⇩N⇩O⇩T⇧*⇧* T U›
using cdcl⇩N⇩O⇩T_merged_bj_learn_is_tranclp_cdcl⇩N⇩O⇩T[OF cdcl⇩N⇩O⇩T] IH
inv by auto
then have ‹cdcl⇩N⇩O⇩T⇧*⇧* S U› using IH by fastforce
moreover have ‹inv U› using IH cdcl⇩N⇩O⇩T cdcl_merged_inv inv by blast
ultimately show ?case using st by fast
qed
lemma rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T:
‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T ⟹ inv S ⟹ cdcl⇩N⇩O⇩T⇧*⇧* S T›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T_and_inv by blast
lemma rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_inv:
‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T ⟹ inv S ⟹ inv T›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T_and_inv by blast
lemma rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_no_dup_inv:
‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T ⟹ no_dup (trail S) ⟹ no_dup (trail T)›
by (induction rule: rtranclp_induct) (auto simp: cdcl⇩N⇩O⇩T_merged_bj_learn_no_dup_inv)
definition μ⇩C' :: ‹'v clause set ⇒ 'st ⇒ nat› where
‹μ⇩C' A T ≡ μ⇩C (1+card (atms_of_ms A)) (2+card (atms_of_ms A)) (trail_weight T)›
definition μ⇩C⇩D⇩C⇩L'_merged :: ‹'v clause set ⇒ 'st ⇒ nat› where
‹μ⇩C⇩D⇩C⇩L'_merged A T ≡
((2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A)) - μ⇩C' A T) * 2 + card (set_mset (clauses⇩N⇩O⇩T T))›
lemma cdcl⇩N⇩O⇩T_decreasing_measure':
assumes
‹cdcl⇩N⇩O⇩T_merged_bj_learn S T› and
inv: ‹inv S› and
atm_clss: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
atm_trail: ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
fin_A: ‹finite A›
shows ‹μ⇩C⇩D⇩C⇩L'_merged A T < μ⇩C⇩D⇩C⇩L'_merged A S›
using assms(1)
proof induction
case (cdcl⇩N⇩O⇩T_merged_bj_learn_decide⇩N⇩O⇩T T)
have ‹clauses⇩N⇩O⇩T S = clauses⇩N⇩O⇩T T›
using cdcl⇩N⇩O⇩T_merged_bj_learn_decide⇩N⇩O⇩T.hyps by auto
moreover have
‹(2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A))
- μ⇩C (1 + card (atms_of_ms A)) (2 + card (atms_of_ms A)) (trail_weight T)
< (2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A))
- μ⇩C (1 + card (atms_of_ms A)) (2 + card (atms_of_ms A)) (trail_weight S)›
apply (rule dpll_bj_trail_mes_decreasing_prop)
using cdcl⇩N⇩O⇩T_merged_bj_learn_decide⇩N⇩O⇩T fin_A atm_clss atm_trail n_d inv
by (simp_all add: bj_decide⇩N⇩O⇩T cdcl⇩N⇩O⇩T_merged_bj_learn_decide⇩N⇩O⇩T.hyps)
ultimately show ?case
unfolding μ⇩C⇩D⇩C⇩L'_merged_def μ⇩C'_def by simp
next
case (cdcl⇩N⇩O⇩T_merged_bj_learn_propagate⇩N⇩O⇩T T)
have ‹clauses⇩N⇩O⇩T S = clauses⇩N⇩O⇩T T›
using cdcl⇩N⇩O⇩T_merged_bj_learn_propagate⇩N⇩O⇩T.hyps
by (simp add: bj_propagate⇩N⇩O⇩T inv dpll_bj_clauses)
moreover have
‹(2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A))
- μ⇩C (1 + card (atms_of_ms A)) (2 + card (atms_of_ms A)) (trail_weight T)
< (2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A))
- μ⇩C (1 + card (atms_of_ms A)) (2 + card (atms_of_ms A)) (trail_weight S)›
apply (rule dpll_bj_trail_mes_decreasing_prop)
using inv n_d atm_clss atm_trail fin_A by (simp_all add: bj_propagate⇩N⇩O⇩T
cdcl⇩N⇩O⇩T_merged_bj_learn_propagate⇩N⇩O⇩T.hyps)
ultimately show ?case
unfolding μ⇩C⇩D⇩C⇩L'_merged_def μ⇩C'_def by simp
next
case (cdcl⇩N⇩O⇩T_merged_bj_learn_forget⇩N⇩O⇩T T)
have ‹card (set_mset (clauses⇩N⇩O⇩T T)) < card (set_mset (clauses⇩N⇩O⇩T S))›
using ‹forget⇩N⇩O⇩T S T› by (metis card_Diff1_less clauses_remove_cls⇩N⇩O⇩T finite_set_mset
forget⇩N⇩O⇩T.cases linear set_mset_minus_replicate_mset(1) state_eq⇩N⇩O⇩T_def)
moreover
have ‹trail S = trail T›
using ‹forget⇩N⇩O⇩T S T› by (auto elim: forget⇩N⇩O⇩TE)
then have
‹(2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A))
- μ⇩C (1 + card (atms_of_ms A)) (2 + card (atms_of_ms A)) (trail_weight T)
= (2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A))
- μ⇩C (1 + card (atms_of_ms A)) (2 + card (atms_of_ms A)) (trail_weight S)›
by auto
ultimately show ?case
unfolding μ⇩C⇩D⇩C⇩L'_merged_def μ⇩C'_def by simp
next
case (cdcl⇩N⇩O⇩T_merged_bj_learn_backjump_l T) note bj_l = this(1)
obtain C' L D S' where
learn: ‹learn S' T› and
bj: ‹backjump S S'› and
atms_C: ‹atms_of (add_mset L C') ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))› and
D: ‹D = add_mset L C'› and
T: ‹T ∼ add_cls⇩N⇩O⇩T D S'›
using bj_l inv backjump_l_backjump_learn [of S] n_d atm_clss atm_trail by blast
have card_T_S: ‹card (set_mset (clauses⇩N⇩O⇩T T)) ≤ 1+ card (set_mset (clauses⇩N⇩O⇩T S))›
using bj_l inv by (force elim!: backjump_lE simp: card_insert_if)
have tr_S_T: ‹trail_weight S' = trail_weight T›
using T by auto
have
‹((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A))
- μ⇩C (1 + card (atms_of_ms A)) (2 + card (atms_of_ms A)) (trail_weight S'))
< ((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A))
- μ⇩C (1 + card (atms_of_ms A)) (2 + card (atms_of_ms A))
(trail_weight S))›
apply (rule dpll_bj_trail_mes_decreasing_prop)
using bj bj_backjump apply blast
using inv apply blast
using atms_C atm_clss atm_trail D apply (simp add: n_d; fail)
using atm_trail n_d apply (simp; fail)
apply (simp add: n_d; fail)
using fin_A apply (simp; fail)
done
then show ?case
using card_T_S unfolding μ⇩C⇩D⇩C⇩L'_merged_def μ⇩C'_def tr_S_T by linarith
qed
lemma wf_cdcl⇩N⇩O⇩T_merged_bj_learn:
assumes
fin_A: ‹finite A›
shows ‹wf {(T, S).
(inv S ∧ atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A ∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A
∧ no_dup (trail S))
∧ cdcl⇩N⇩O⇩T_merged_bj_learn S T}›
apply (rule wfP_if_measure[of _ _ ‹μ⇩C⇩D⇩C⇩L'_merged A›])
using cdcl⇩N⇩O⇩T_decreasing_measure' fin_A by simp
lemma in_atms_neg_defined: ‹x ∈ atms_of C' ⟹ F ⊨as CNot C' ⟹ x ∈ atm_of ` lits_of_l F›
by (metis (no_types, lifting) atms_of_def imageE true_annots_CNot_all_atms_defined)
lemma cdcl⇩N⇩O⇩T_merged_bj_learn_atms_of_ms_clauses_decreasing:
assumes ‹cdcl⇩N⇩O⇩T_merged_bj_learn S T›and ‹inv S›
shows ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))›
using assms
apply (induction rule: cdcl⇩N⇩O⇩T_merged_bj_learn.induct)
prefer 4 apply (auto dest!: dpll_bj_atms_of_ms_clauses_inv set_mp
simp add: atms_of_ms_def Union_eq
elim!: decide⇩N⇩O⇩TE propagate⇩N⇩O⇩TE forget⇩N⇩O⇩TE)[3]
apply (elim backjump_lE)
by (auto dest!: in_atms_neg_defined simp del:)
lemma cdcl⇩N⇩O⇩T_merged_bj_learn_atms_in_trail_in_set:
assumes
‹cdcl⇩N⇩O⇩T_merged_bj_learn S T› and ‹inv S› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ A› and
‹atm_of ` (lits_of_l (trail S)) ⊆ A›
shows ‹atm_of ` (lits_of_l (trail T)) ⊆ A›
using assms
apply (induction rule: cdcl⇩N⇩O⇩T_merged_bj_learn.induct)
apply (meson bj_decide⇩N⇩O⇩T dpll_bj_atms_in_trail_in_set)
apply (meson bj_propagate⇩N⇩O⇩T dpll_bj_atms_in_trail_in_set)
defer
apply (metis forget⇩N⇩O⇩TE state_eq⇩N⇩O⇩T_trail trail_remove_cls⇩N⇩O⇩T)
by (metis (no_types, lifting) backjump_l_backjump_learn bj_backjump dpll_bj_atms_in_trail_in_set
state_eq⇩N⇩O⇩T_trail trail_add_cls⇩N⇩O⇩T)
lemma rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_trail_clauses_bound:
assumes
cdcl: ‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T› and
inv: ‹inv S› and
atms_clauses_S: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ A› and
atms_trail_S: ‹atm_of `(lits_of_l (trail S)) ⊆ A›
shows ‹atm_of ` (lits_of_l (trail T)) ⊆ A ∧ atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ A›
using cdcl
proof (induction rule: rtranclp_induct)
case base
then show ?case using atms_clauses_S atms_trail_S by simp
next
case (step T U) note st = this(1) and cdcl⇩N⇩O⇩T = this(2) and IH = this(3)
have ‹inv T› using inv st rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T_and_inv by blast
then have ‹atms_of_mm (clauses⇩N⇩O⇩T U) ⊆ A›
using cdcl⇩N⇩O⇩T_merged_bj_learn_atms_of_ms_clauses_decreasing cdcl⇩N⇩O⇩T IH ‹inv T› by fast
moreover
have ‹atm_of `(lits_of_l (trail U)) ⊆ A›
using cdcl⇩N⇩O⇩T_merged_bj_learn_atms_in_trail_in_set[of _ _ A] ‹inv T› cdcl⇩N⇩O⇩T step.IH by auto
ultimately show ?case by fast
qed
lemma cdcl⇩N⇩O⇩T_merged_bj_learn_trail_clauses_bound:
assumes
cdcl: ‹cdcl⇩N⇩O⇩T_merged_bj_learn S T› and
inv: ‹inv S› and
atms_clauses_S: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ A› and
atms_trail_S: ‹atm_of `(lits_of_l (trail S)) ⊆ A›
shows ‹atm_of ` (lits_of_l (trail T)) ⊆ A ∧ atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ A›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_trail_clauses_bound[of S T] assms by auto
lemma tranclp_cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_tranclp:
assumes
‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧+⇧+ S T› and
inv: ‹inv S› and
atm_clss: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
atm_trail: ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
fin_A[simp]: ‹finite A›
shows ‹(T, S) ∈ {(T, S).
(inv S ∧ atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A ∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A
∧ no_dup (trail S))
∧ cdcl⇩N⇩O⇩T_merged_bj_learn S T}⇧+› (is ‹_ ∈ ?P⇧+›)
using assms(1)
proof (induction rule: tranclp_induct)
case base
then show ?case using n_d atm_clss atm_trail inv by auto
next
case (step T U) note st = this(1) and cdcl⇩N⇩O⇩T = this(2) and IH = this(3)
have st: ‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T›
using [[simp_trace]]
by (simp add: rtranclp_unfold st)
have ‹cdcl⇩N⇩O⇩T⇧*⇧* S T›
apply (rule rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T)
using st cdcl⇩N⇩O⇩T inv n_d atm_clss atm_trail inv by auto
have ‹inv T›
apply (rule rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_inv)
using inv st cdcl⇩N⇩O⇩T n_d atm_clss atm_trail inv by auto
moreover have ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_ms A›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_trail_clauses_bound[OF st inv atm_clss atm_trail]
by fast
moreover have ‹atm_of ` (lits_of_l (trail T))⊆ atms_of_ms A›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_trail_clauses_bound[OF st inv atm_clss atm_trail]
by fast
moreover have ‹no_dup (trail T)›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_no_dup_inv[OF st n_d] by fast
ultimately have ‹(U, T) ∈ ?P›
using cdcl⇩N⇩O⇩T by auto
then show ?case using IH by (simp add: trancl_into_trancl2)
qed
lemma wf_tranclp_cdcl⇩N⇩O⇩T_merged_bj_learn:
assumes ‹finite A›
shows ‹wf {(T, S).
(inv S ∧ atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A ∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A
∧ no_dup (trail S))
∧ cdcl⇩N⇩O⇩T_merged_bj_learn⇧+⇧+ S T}›
apply (rule wf_subset)
apply (rule wf_trancl[OF wf_cdcl⇩N⇩O⇩T_merged_bj_learn])
using assms apply simp
using tranclp_cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_tranclp[OF _ _ _ _ _ ‹finite A›] by auto
lemma cdcl⇩N⇩O⇩T_merged_bj_learn_final_state:
fixes A :: ‹'v clause set› and S T :: ‹'st›
assumes
n_s: ‹no_step cdcl⇩N⇩O⇩T_merged_bj_learn S› and
atms_S: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
atms_trail: ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
‹finite A› and
inv: ‹inv S› and
decomp: ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T S))
∨ (trail S ⊨asm clauses⇩N⇩O⇩T S ∧ satisfiable (set_mset (clauses⇩N⇩O⇩T S)))›
proof -
let ?N = ‹set_mset (clauses⇩N⇩O⇩T S)›
let ?M = ‹trail S›
consider
(sat) ‹satisfiable ?N› and ‹?M ⊨as ?N›
| (sat') ‹satisfiable ?N› and ‹¬ ?M ⊨as ?N›
| (unsat) ‹unsatisfiable ?N›
by auto
then show ?thesis
proof cases
case sat' note sat = this(1) and M = this(2)
obtain C where ‹C ∈ ?N› and ‹¬?M ⊨a C› using M unfolding true_annots_def by auto
obtain I :: ‹'v literal set› where
‹I ⊨s ?N› and
cons: ‹consistent_interp I› and
tot: ‹total_over_m I ?N› and
atm_I_N: ‹atm_of `I ⊆ atms_of_ms ?N›
using sat unfolding satisfiable_def_min by auto
let ?I = ‹I ∪ {P| P. P ∈ lits_of_l ?M ∧ atm_of P ∉ atm_of ` I}›
let ?O = ‹{unmark L |L. is_decided L ∧ L ∈ set ?M ∧ atm_of (lit_of L) ∉ atms_of_ms ?N}›
have cons_I': ‹consistent_interp ?I›
using cons using ‹no_dup ?M› unfolding consistent_interp_def
by (auto simp add: atm_of_in_atm_of_set_iff_in_set_or_uminus_in_set lits_of_def
dest!: no_dup_cannot_not_lit_and_uminus)
have tot_I': ‹total_over_m ?I (?N ∪ unmark_l ?M)›
using tot atms_of_s_def unfolding total_over_m_def total_over_set_def
by (fastforce simp: image_iff)
have ‹{P |P. P ∈ lits_of_l ?M ∧ atm_of P ∉ atm_of ` I} ⊨s ?O›
using ‹I⊨s ?N› atm_I_N by (auto simp add: atm_of_eq_atm_of true_clss_def lits_of_def)
then have I'_N: ‹?I ⊨s ?N ∪ ?O›
using ‹I⊨s ?N› true_clss_union_increase by force
have tot': ‹total_over_m ?I (?N∪?O)›
using atm_I_N tot unfolding total_over_m_def total_over_set_def
by (force simp: lits_of_def elim!: is_decided_ex_Decided)
have atms_N_M: ‹atms_of_ms ?N ⊆ atm_of ` lits_of_l ?M›
proof (rule ccontr)
assume ‹¬ ?thesis›
then obtain l :: 'v where
l_N: ‹l ∈ atms_of_ms ?N› and
l_M: ‹l ∉ atm_of ` lits_of_l ?M›
by auto
have ‹undefined_lit ?M (Pos l)›
using l_M by (metis Decided_Propagated_in_iff_in_lits_of_l
atm_of_in_atm_of_set_iff_in_set_or_uminus_in_set literal.sel(1))
then show False
using can_propagate_or_decide_or_backjump_l[of ‹Pos l› S] l_N
cdcl⇩N⇩O⇩T_merged_bj_learn_decide⇩N⇩O⇩T n_s inv sat
by (auto dest!: cdcl⇩N⇩O⇩T_merged_bj_learn.intros)
qed
have ‹?M ⊨as CNot C›
apply (rule all_variables_defined_not_imply_cnot)
using atms_N_M ‹C ∈ ?N› ‹¬ ?M ⊨a C› atms_of_atms_of_ms_mono[OF ‹C ∈ ?N›]
by (auto dest: atms_of_atms_of_ms_mono)
have ‹∃l ∈ set ?M. is_decided l›
proof (rule ccontr)
let ?O = ‹{unmark L |L. is_decided L ∧ L ∈ set ?M ∧ atm_of (lit_of L) ∉ atms_of_ms ?N}›
have θ[iff]: ‹⋀I. total_over_m I (?N ∪ ?O ∪ unmark_l ?M)
⟷ total_over_m I (?N ∪unmark_l ?M)›
unfolding total_over_set_def total_over_m_def atms_of_ms_def by blast
assume ‹¬ ?thesis›
then have [simp]:‹{unmark L |L. is_decided L ∧ L ∈ set ?M}
= {unmark L |L. is_decided L ∧ L ∈ set ?M ∧ atm_of (lit_of L) ∉ atms_of_ms ?N}›
by auto
then have ‹?N ∪ ?O ⊨ps unmark_l ?M›
using all_decomposition_implies_propagated_lits_are_implied[OF decomp] by auto
then have ‹?I ⊨s unmark_l ?M›
using cons_I' I'_N tot_I' ‹?I ⊨s ?N ∪ ?O› unfolding θ true_clss_clss_def by blast
then have ‹lits_of_l ?M ⊆ ?I›
unfolding true_clss_def lits_of_def by auto
then have ‹?M ⊨as ?N›
using I'_N ‹C ∈ ?N› ‹¬ ?M ⊨a C› cons_I' atms_N_M
by (meson ‹trail S ⊨as CNot C› consistent_CNot_not rev_subsetD sup_ge1 true_annot_def
true_annots_def true_cls_mono_set_mset_l true_clss_def)
then show False using M by fast
qed
from List.split_list_first_propE[OF this] obtain K :: ‹'v literal› and d :: unit and
F F' :: ‹('v, unit) ann_lits› where
M_K: ‹?M = F' @ Decided K # F› and
nm: ‹∀f∈set F'. ¬is_decided f›
by (metis (full_types) is_decided_ex_Decided old.unit.exhaust)
let ?K = ‹Decided K::('v, unit) ann_lit›
have ‹?K ∈ set ?M›
unfolding M_K by auto
let ?C = ‹image_mset lit_of {#L∈#mset ?M. is_decided L ∧ L≠?K#} :: 'v clause›
let ?C' = ‹set_mset (image_mset (λL::'v literal. {#L#}) (?C + unmark ?K))›
have ‹?N ∪ {unmark L |L. is_decided L ∧ L ∈ set ?M} ⊨ps unmark_l ?M›
using all_decomposition_implies_propagated_lits_are_implied[OF decomp] .
moreover have C': ‹?C' = {unmark L |L. is_decided L ∧ L ∈ set ?M}›
unfolding M_K apply standard
apply force
by auto
ultimately have N_C_M: ‹?N ∪ ?C' ⊨ps unmark_l ?M›
by auto
have N_M_False: ‹?N ∪ (λL. unmark L) ` (set ?M) ⊨ps {{#}}›
unfolding true_clss_clss_def true_annots_def Ball_def true_annot_def
proof (intro allI impI)
fix LL :: "'v literal set"
assume
tot: ‹total_over_m LL (set_mset (clauses⇩N⇩O⇩T S) ∪ unmark_l (trail S) ∪ {{#}})› and
cons: ‹consistent_interp LL› and
LL: ‹LL ⊨s set_mset (clauses⇩N⇩O⇩T S) ∪ unmark_l (trail S)›
have ‹total_over_m LL (CNot C)›
by (metis ‹C ∈# clauses⇩N⇩O⇩T S› insert_absorb tot total_over_m_CNot_toal_over_m
total_over_m_insert total_over_m_union)
then have "total_over_m LL (unmark_l (trail S) ∪ CNot C)"
using tot by force
then show "LL ⊨s {{#}}"
using tot cons LL
by (metis (no_types) ‹C ∈# clauses⇩N⇩O⇩T S› ‹trail S ⊨as CNot C› consistent_CNot_not
true_annots_true_clss_clss true_clss_clss_def true_clss_def true_clss_union)
qed
have ‹undefined_lit F K› using ‹no_dup ?M› unfolding M_K by (auto simp: defined_lit_map)
moreover {
have ‹?N ∪ ?C' ⊨ps {{#}}›
proof -
have A: ‹?N ∪ ?C' ∪ unmark_l ?M = ?N ∪ unmark_l ?M›
unfolding M_K by auto
show ?thesis
using true_clss_clss_left_right[OF N_C_M, of ‹{{#}}›] N_M_False unfolding A by auto
qed
have ‹?N ⊨p image_mset uminus ?C + {#-K#}›
unfolding true_clss_cls_def true_clss_clss_def total_over_m_def
proof (intro allI impI)
fix I
assume
tot: ‹total_over_set I (atms_of_ms (?N ∪ {image_mset uminus ?C+ {#- K#}}))› and
cons: ‹consistent_interp I› and
‹I ⊨s ?N›
have ‹(K ∈ I ∧ -K ∉ I) ∨ (-K ∈ I ∧ K ∉ I)›
using cons tot unfolding consistent_interp_def by (cases K) auto
have ‹{a ∈ set (trail S). is_decided a ∧ a ≠ Decided K} =
set (trail S) ∩ {L. is_decided L ∧ L ≠ Decided K}›
by auto
then have tot': ‹total_over_set I
(atm_of ` lit_of ` (set ?M ∩ {L. is_decided L ∧ L ≠ Decided K}))›
using tot by (auto simp add: atms_of_uminus_lit_atm_of_lit_of)
{ fix x :: ‹('v, unit) ann_lit›
assume
a3: ‹lit_of x ∉ I› and
a1: ‹x ∈ set ?M› and
a4: ‹is_decided x› and
a5: ‹x ≠ Decided K›
then have ‹Pos (atm_of (lit_of x)) ∈ I ∨ Neg (atm_of (lit_of x)) ∈ I›
using a5 a4 tot' a1 unfolding total_over_set_def atms_of_s_def by blast
moreover have f6: ‹Neg (atm_of (lit_of x)) = - Pos (atm_of (lit_of x))›
by simp
ultimately have ‹- lit_of x ∈ I›
using f6 a3 by (metis (no_types) atm_of_in_atm_of_set_iff_in_set_or_uminus_in_set
literal.sel(1))
} note H = this
have ‹¬I ⊨s ?C'›
using ‹?N ∪ ?C' ⊨ps {{#}}› tot cons ‹I ⊨s ?N›
unfolding true_clss_clss_def total_over_m_def
by (simp add: atms_of_uminus_lit_atm_of_lit_of atms_of_ms_single_image_atm_of_lit_of)
then show ‹I ⊨ image_mset uminus ?C + {#- K#}›
unfolding true_clss_def true_cls_def Bex_def
using ‹(K ∈ I ∧ -K ∉ I) ∨ (-K ∈ I ∧ K ∉ I)›
by (auto dest!: H)
qed }
moreover have ‹F ⊨as CNot (image_mset uminus ?C)›
using nm unfolding true_annots_def CNot_def M_K by (auto simp add: lits_of_def)
ultimately have False
using bj_merge_can_jump[of S F' K F C ‹-K›
‹image_mset uminus (image_mset lit_of {# L :# mset ?M. is_decided L ∧ L ≠ Decided K#})›]
‹C∈?N› n_s ‹?M ⊨as CNot C› bj_backjump inv sat unfolding M_K
by (auto simp: cdcl⇩N⇩O⇩T_merged_bj_learn.simps)
then show ?thesis by fast
qed auto
qed
lemma cdcl⇩N⇩O⇩T_merged_bj_learn_all_decomposition_implies:
assumes ‹cdcl⇩N⇩O⇩T_merged_bj_learn S T› and inv: ‹inv S›
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T T) (get_all_ann_decomposition (trail T))›
using assms
proof (induction rule: cdcl⇩N⇩O⇩T_merged_bj_learn.induct)
case (cdcl⇩N⇩O⇩T_merged_bj_learn_backjump_l T) note bj_l = this(1)
obtain C' L D S' where
learn: ‹learn S' T› and
bj: ‹backjump S S'› and
atms_C: ‹atms_of (add_mset L C') ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))› and
D: ‹D = add_mset L C'› and
T: ‹T ∼ add_cls⇩N⇩O⇩T D S'›
using bj_l inv backjump_l_backjump_learn [of S] by blast
have ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S') (get_all_ann_decomposition (trail S'))›
using bj bj_backjump dpll_bj_clauses inv(1) inv(2)
by (fastforce simp: dpll_bj_all_decomposition_implies_inv)
then show ?case
using T by (auto simp: all_decomposition_implies_insert_single)
qed (auto simp: dpll_bj_all_decomposition_implies_inv cdcl⇩N⇩O⇩T_all_decomposition_implies
dest!: dpll_bj.intros cdcl⇩N⇩O⇩T.intros)
lemma rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_all_decomposition_implies:
assumes ‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T› and inv: ‹inv S›
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T T) (get_all_ann_decomposition (trail T))›
using assms
apply (induction rule: rtranclp_induct)
apply simp
using cdcl⇩N⇩O⇩T_merged_bj_learn_all_decomposition_implies
rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T_and_inv by blast
lemma full_cdcl⇩N⇩O⇩T_merged_bj_learn_final_state:
fixes A :: ‹'v clause set› and S T :: ‹'st›
assumes
full: ‹full cdcl⇩N⇩O⇩T_merged_bj_learn S T› and
atms_S: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
atms_trail: ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
‹finite A› and
inv: ‹inv S› and
decomp: ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T T))
∨ (trail T ⊨asm clauses⇩N⇩O⇩T T ∧ satisfiable (set_mset (clauses⇩N⇩O⇩T T)))›
proof -
have st: ‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T› and n_s: ‹no_step cdcl⇩N⇩O⇩T_merged_bj_learn T›
using full unfolding full_def by blast+
then have st': ‹cdcl⇩N⇩O⇩T⇧*⇧* S T›
using inv rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T_and_inv n_d by auto
have ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_ms A› and ‹atm_of ` lits_of_l (trail T) ⊆ atms_of_ms A›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_trail_clauses_bound[OF st inv atms_S atms_trail] by blast+
moreover have ‹no_dup (trail T)›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_no_dup_inv inv n_d st by blast
moreover have ‹inv T›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_inv inv st by blast
moreover have ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T T) (get_all_ann_decomposition (trail T))›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_all_decomposition_implies inv st decomp n_d by blast
ultimately show ?thesis
using cdcl⇩N⇩O⇩T_merged_bj_learn_final_state[of T A] ‹finite A› n_s by fast
qed
end
subsection ‹Instantiations›
text ‹In this section, we instantiate the previous locales to ensure that the assumption are not
contradictory.›
locale cdcl⇩N⇩O⇩T_with_backtrack_and_restarts =
conflict_driven_clause_learning_learning_before_backjump_only_distinct_learnt
trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
inv decide_conds backjump_conds propagate_conds learn_restrictions forget_restrictions
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
inv :: ‹'st ⇒ bool› and
decide_conds :: ‹'st ⇒ 'st ⇒ bool› and
backjump_conds :: ‹'v clause ⇒ 'v clause ⇒ 'v literal ⇒ 'st ⇒ 'st ⇒ bool› and
propagate_conds :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st ⇒ bool› and
learn_restrictions forget_restrictions :: ‹'v clause ⇒ 'st ⇒ bool›
+
fixes f :: ‹nat ⇒ nat›
assumes
unbounded: ‹unbounded f› and f_ge_1: ‹⋀n. n ≥ 1 ⟹ f n ≥ 1› and
inv_restart:‹⋀S T. inv S ⟹ T ∼ reduce_trail_to⇩N⇩O⇩T ([]::'a list) S ⟹ inv T›
begin
lemma bound_inv_inv:
assumes
‹inv S› and
n_d: ‹no_dup (trail S)› and
atms_clss_S_A: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
atms_trail_S_A:‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
‹finite A› and
cdcl⇩N⇩O⇩T: ‹cdcl⇩N⇩O⇩T S T›
shows
‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_ms A› and
‹atm_of ` lits_of_l (trail T) ⊆ atms_of_ms A› and
‹finite A›
proof -
have ‹cdcl⇩N⇩O⇩T S T›
using ‹inv S› cdcl⇩N⇩O⇩T by linarith
then have ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` lits_of_l (trail S)›
using ‹inv S›
by (meson conflict_driven_clause_learning_ops.cdcl⇩N⇩O⇩T_atms_of_ms_clauses_decreasing
conflict_driven_clause_learning_ops_axioms n_d)
then show ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_ms A›
using atms_clss_S_A atms_trail_S_A by blast
next
show ‹atm_of ` lits_of_l (trail T) ⊆ atms_of_ms A›
by (meson ‹inv S› atms_clss_S_A atms_trail_S_A cdcl⇩N⇩O⇩T cdcl⇩N⇩O⇩T_atms_in_trail_in_set n_d)
next
show ‹finite A›
using ‹finite A› by simp
qed
sublocale cdcl⇩N⇩O⇩T_increasing_restarts_ops ‹λS T. T ∼ reduce_trail_to⇩N⇩O⇩T ([]::'a list) S› cdcl⇩N⇩O⇩T f
‹λA S. atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A ∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A ∧
finite A›
μ⇩C⇩D⇩C⇩L' ‹λS. inv S ∧ no_dup (trail S)›
μ⇩C⇩D⇩C⇩L'_bound
apply unfold_locales
apply (simp add: unbounded)
using f_ge_1 apply force
using bound_inv_inv apply meson
apply (rule cdcl⇩N⇩O⇩T_decreasing_measure'; simp)
apply (rule rtranclp_cdcl⇩N⇩O⇩T_μ⇩C⇩D⇩C⇩L'_bound; simp)
apply (rule rtranclp_μ⇩C⇩D⇩C⇩L'_bound_decreasing; simp)
apply auto[]
apply auto[]
using cdcl⇩N⇩O⇩T_inv cdcl⇩N⇩O⇩T_no_dup apply blast
using inv_restart apply auto[]
done
lemma cdcl⇩N⇩O⇩T_with_restart_μ⇩C⇩D⇩C⇩L'_le_μ⇩C⇩D⇩C⇩L'_bound:
assumes
cdcl⇩N⇩O⇩T: ‹cdcl⇩N⇩O⇩T_restart (T, a) (V, b)› and
cdcl⇩N⇩O⇩T_inv:
‹inv T›
‹no_dup (trail T)› and
bound_inv:
‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_ms A›
‹atm_of ` lits_of_l (trail T) ⊆ atms_of_ms A›
‹finite A›
shows ‹μ⇩C⇩D⇩C⇩L' A V ≤ μ⇩C⇩D⇩C⇩L'_bound A T›
using cdcl⇩N⇩O⇩T_inv bound_inv
proof (induction rule: cdcl⇩N⇩O⇩T_with_restart_induct[OF cdcl⇩N⇩O⇩T])
case (1 m S T n U) note U = this(3)
show ?case
apply (rule rtranclp_cdcl⇩N⇩O⇩T_μ⇩C⇩D⇩C⇩L'_bound_reduce_trail_to⇩N⇩O⇩T[of S T])
using ‹(cdcl⇩N⇩O⇩T ^^ m) S T› apply (fastforce dest!: relpowp_imp_rtranclp)
using 1 by auto
next
case (2 S T n) note full = this(2)
show ?case
apply (rule rtranclp_cdcl⇩N⇩O⇩T_μ⇩C⇩D⇩C⇩L'_bound)
using full 2 unfolding full1_def by force+
qed
lemma cdcl⇩N⇩O⇩T_with_restart_μ⇩C⇩D⇩C⇩L'_bound_le_μ⇩C⇩D⇩C⇩L'_bound:
assumes
cdcl⇩N⇩O⇩T: ‹cdcl⇩N⇩O⇩T_restart (T, a) (V, b)› and
cdcl⇩N⇩O⇩T_inv:
‹inv T›
‹no_dup (trail T)› and
bound_inv:
‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_ms A›
‹atm_of ` lits_of_l (trail T) ⊆ atms_of_ms A›
‹finite A›
shows ‹μ⇩C⇩D⇩C⇩L'_bound A V ≤ μ⇩C⇩D⇩C⇩L'_bound A T›
using cdcl⇩N⇩O⇩T_inv bound_inv
proof (induction rule: cdcl⇩N⇩O⇩T_with_restart_induct[OF cdcl⇩N⇩O⇩T])
case (1 m S T n U) note U = this(3)
have ‹μ⇩C⇩D⇩C⇩L'_bound A T ≤ μ⇩C⇩D⇩C⇩L'_bound A S›
apply (rule rtranclp_μ⇩C⇩D⇩C⇩L'_bound_decreasing)
using ‹(cdcl⇩N⇩O⇩T ^^ m) S T› apply (fastforce dest: relpowp_imp_rtranclp)
using 1 by auto
then show ?case using U unfolding μ⇩C⇩D⇩C⇩L'_bound_def by auto
next
case (2 S T n) note full = this(2)
show ?case
apply (rule rtranclp_μ⇩C⇩D⇩C⇩L'_bound_decreasing)
using full 2 unfolding full1_def by force+
qed
sublocale cdcl⇩N⇩O⇩T_increasing_restarts _ _ _ _ _ _
f
‹λS T. T ∼ reduce_trail_to⇩N⇩O⇩T ([]::'a list) S›
‹λA S. atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A
∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A ∧ finite A›
μ⇩C⇩D⇩C⇩L' cdcl⇩N⇩O⇩T
‹λS. inv S ∧ no_dup (trail S)›
μ⇩C⇩D⇩C⇩L'_bound
apply unfold_locales
using cdcl⇩N⇩O⇩T_with_restart_μ⇩C⇩D⇩C⇩L'_le_μ⇩C⇩D⇩C⇩L'_bound apply simp
using cdcl⇩N⇩O⇩T_with_restart_μ⇩C⇩D⇩C⇩L'_bound_le_μ⇩C⇩D⇩C⇩L'_bound apply simp
done
lemma cdcl⇩N⇩O⇩T_restart_all_decomposition_implies:
assumes ‹cdcl⇩N⇩O⇩T_restart S T› and
‹inv (fst S)› and
‹no_dup (trail (fst S))›
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T (fst S)) (get_all_ann_decomposition (trail (fst S)))›
shows
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T (fst T)) (get_all_ann_decomposition (trail (fst T)))›
using assms apply (induction)
using rtranclp_cdcl⇩N⇩O⇩T_all_decomposition_implies by (auto dest!: tranclp_into_rtranclp
simp: full1_def)
lemma rtranclp_cdcl⇩N⇩O⇩T_restart_all_decomposition_implies:
assumes ‹cdcl⇩N⇩O⇩T_restart⇧*⇧* S T› and
inv: ‹inv (fst S)› and
n_d: ‹no_dup (trail (fst S))› and
decomp:
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T (fst S)) (get_all_ann_decomposition (trail (fst S)))›
shows
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T (fst T)) (get_all_ann_decomposition (trail (fst T)))›
using assms(1)
proof (induction rule: rtranclp_induct)
case base
then show ?case using decomp by simp
next
case (step T u) note st = this(1) and r = this(2) and IH = this(3)
have ‹inv (fst T)›
using rtranclp_cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv[OF st] inv n_d by blast
moreover have ‹no_dup (trail (fst T))›
using rtranclp_cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv[OF st] inv n_d by blast
ultimately show ?case
using cdcl⇩N⇩O⇩T_restart_all_decomposition_implies r IH n_d by fast
qed
lemma cdcl⇩N⇩O⇩T_restart_sat_ext_iff:
assumes
st: ‹cdcl⇩N⇩O⇩T_restart S T› and
n_d: ‹no_dup (trail (fst S))› and
inv: ‹inv (fst S)›
shows ‹I ⊨sextm clauses⇩N⇩O⇩T (fst S) ⟷ I ⊨sextm clauses⇩N⇩O⇩T (fst T)›
using assms
proof (induction)
case (restart_step m S T n U)
then show ?case
using rtranclp_cdcl⇩N⇩O⇩T_bj_sat_ext_iff n_d by (fastforce dest!: relpowp_imp_rtranclp)
next
case restart_full
then show ?case using rtranclp_cdcl⇩N⇩O⇩T_bj_sat_ext_iff unfolding full1_def
by (fastforce dest!: tranclp_into_rtranclp)
qed
lemma rtranclp_cdcl⇩N⇩O⇩T_restart_sat_ext_iff:
fixes S T :: ‹'st × nat›
assumes
st: ‹cdcl⇩N⇩O⇩T_restart⇧*⇧* S T› and
n_d: ‹no_dup (trail (fst S))› and
inv: ‹inv (fst S)›
shows ‹I ⊨sextm clauses⇩N⇩O⇩T (fst S) ⟷ I ⊨sextm clauses⇩N⇩O⇩T (fst T)›
using st
proof (induction)
case base
then show ?case by simp
next
case (step T U) note st = this(1) and r = this(2) and IH = this(3)
have ‹inv (fst T)›
using rtranclp_cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv[OF st] inv n_d by blast+
moreover have ‹no_dup (trail (fst T))›
using rtranclp_cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv rtranclp_cdcl⇩N⇩O⇩T_no_dup st inv n_d by blast
ultimately show ?case
using cdcl⇩N⇩O⇩T_restart_sat_ext_iff[OF r] IH by blast
qed
theorem full_cdcl⇩N⇩O⇩T_restart_backjump_final_state:
fixes A :: ‹'v clause set› and S T :: ‹'st›
assumes
full: ‹full cdcl⇩N⇩O⇩T_restart (S, n) (T, m)› and
atms_S: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
atms_trail: ‹atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A› and
n_d: ‹no_dup (trail S)› and
fin_A[simp]: ‹finite A› and
inv: ‹inv S› and
decomp: ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T S) (get_all_ann_decomposition (trail S))›
shows ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T S))
∨ (lits_of_l (trail T) ⊨sextm clauses⇩N⇩O⇩T S ∧ satisfiable (set_mset (clauses⇩N⇩O⇩T S)))›
proof -
have st: ‹cdcl⇩N⇩O⇩T_restart⇧*⇧* (S, n) (T, m)› and
n_s: ‹no_step cdcl⇩N⇩O⇩T_restart (T, m)›
using full unfolding full_def by fast+
have binv_T: ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_ms A›
‹atm_of ` lits_of_l (trail T) ⊆ atms_of_ms A›
using rtranclp_cdcl⇩N⇩O⇩T_with_restart_bound_inv[OF st, of A] inv n_d atms_S atms_trail
by auto
moreover have inv_T: ‹no_dup (trail T)› ‹inv T›
using rtranclp_cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv[OF st] inv n_d by auto
moreover have ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T T) (get_all_ann_decomposition (trail T))›
using rtranclp_cdcl⇩N⇩O⇩T_restart_all_decomposition_implies[OF st] inv n_d
decomp by auto
ultimately have T: ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T T))
∨ (trail T ⊨asm clauses⇩N⇩O⇩T T ∧ satisfiable (set_mset (clauses⇩N⇩O⇩T T)))›
using no_step_cdcl⇩N⇩O⇩T_restart_no_step_cdcl⇩N⇩O⇩T[of ‹(T, m)› A] n_s
cdcl⇩N⇩O⇩T_final_state[of T A] unfolding cdcl⇩N⇩O⇩T_NOT_all_inv_def by auto
have eq_sat_S_T:‹⋀I. I ⊨sextm clauses⇩N⇩O⇩T S ⟷ I ⊨sextm clauses⇩N⇩O⇩T T›
using rtranclp_cdcl⇩N⇩O⇩T_restart_sat_ext_iff[OF st] inv n_d atms_S
atms_trail by auto
have cons_T: ‹consistent_interp (lits_of_l (trail T))›
using inv_T(1) distinct_consistent_interp by blast
consider
(unsat) ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T T))›
| (sat) ‹trail T ⊨asm clauses⇩N⇩O⇩T T› and ‹satisfiable (set_mset (clauses⇩N⇩O⇩T T))›
using T by blast
then show ?thesis
proof cases
case unsat
then have ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T S))›
using eq_sat_S_T consistent_true_clss_ext_satisfiable true_clss_imp_true_cls_ext
unfolding satisfiable_def by blast
then show ?thesis by fast
next
case sat
then have ‹lits_of_l (trail T) ⊨sextm clauses⇩N⇩O⇩T S›
using rtranclp_cdcl⇩N⇩O⇩T_restart_sat_ext_iff[OF st] inv n_d atms_S
atms_trail by (auto simp: true_clss_imp_true_cls_ext true_annots_true_cls)
moreover then have ‹satisfiable (set_mset (clauses⇩N⇩O⇩T S))›
using cons_T consistent_true_clss_ext_satisfiable by blast
ultimately show ?thesis by blast
qed
qed
end
text ‹The restart does only reset the trail, contrary to Weidenbach's version where
forget and restart are always combined. But there is a forget rule.›
locale cdcl⇩N⇩O⇩T_merge_bj_learn_with_backtrack_restarts =
cdcl⇩N⇩O⇩T_merge_bj_learn trail clauses⇩N⇩O⇩T prepend_trail tl_trail add_cls⇩N⇩O⇩T remove_cls⇩N⇩O⇩T
decide_conds propagate_conds forget_conds
‹λC C' L' S T. distinct_mset C' ∧ L' ∉# C' ∧ backjump_l_cond C C' L' S T› inv
for
trail :: ‹'st ⇒ ('v, unit) ann_lits› and
clauses⇩N⇩O⇩T :: ‹'st ⇒ 'v clauses› and
prepend_trail :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st› and
tl_trail :: ‹'st ⇒'st› and
add_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
remove_cls⇩N⇩O⇩T :: ‹'v clause ⇒ 'st ⇒ 'st› and
decide_conds :: ‹'st ⇒ 'st ⇒ bool› and
propagate_conds :: ‹('v, unit) ann_lit ⇒ 'st ⇒ 'st ⇒ bool› and
inv :: ‹'st ⇒ bool› and
forget_conds :: ‹'v clause ⇒ 'st ⇒ bool› and
backjump_l_cond :: ‹'v clause ⇒ 'v clause ⇒ 'v literal ⇒ 'st ⇒ 'st ⇒ bool›
+
fixes f :: ‹nat ⇒ nat›
assumes
unbounded: ‹unbounded f› and f_ge_1: ‹⋀n. n ≥ 1 ⟹ f n ≥ 1› and
inv_restart:‹⋀S T. inv S ⟹ T ∼ reduce_trail_to⇩N⇩O⇩T [] S ⟹ inv T›
begin
definition not_simplified_cls :: ‹'b clause multiset ⇒ 'b clauses›
where
‹not_simplified_cls A ≡ {#C ∈# A. C ∉ simple_clss (atms_of_mm A)#}›
lemma not_simplified_cls_tautology_distinct_mset:
‹not_simplified_cls A = {#C ∈# A. tautology C ∨ ¬distinct_mset C#}›
unfolding not_simplified_cls_def by (rule filter_mset_cong) (auto simp: simple_clss_def)
lemma simple_clss_or_not_simplified_cls:
assumes ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
‹x ∈# clauses⇩N⇩O⇩T S› and ‹finite A›
shows ‹x ∈ simple_clss (atms_of_ms A) ∨ x ∈# not_simplified_cls (clauses⇩N⇩O⇩T S)›
proof -
consider
(simpl) ‹¬tautology x› and ‹distinct_mset x›
| (n_simp) ‹tautology x ∨ ¬distinct_mset x›
by auto
then show ?thesis
proof cases
case simpl
then have ‹x ∈ simple_clss (atms_of_ms A)›
by (meson assms atms_of_atms_of_ms_mono atms_of_ms_finite simple_clss_mono
distinct_mset_not_tautology_implies_in_simple_clss finite_subset
subsetCE)
then show ?thesis by blast
next
case n_simp
then have ‹x ∈# not_simplified_cls (clauses⇩N⇩O⇩T S)›
using ‹x ∈# clauses⇩N⇩O⇩T S› unfolding not_simplified_cls_tautology_distinct_mset by auto
then show ?thesis by blast
qed
qed
lemma cdcl⇩N⇩O⇩T_merged_bj_learn_clauses_bound:
assumes
‹cdcl⇩N⇩O⇩T_merged_bj_learn S T› and
inv: ‹inv S› and
atms_clss: ‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
atms_trail: ‹atm_of `(lits_of_l (trail S)) ⊆ atms_of_ms A› and
fin_A[simp]: ‹finite A›
shows ‹set_mset (clauses⇩N⇩O⇩T T) ⊆ set_mset (not_simplified_cls (clauses⇩N⇩O⇩T S))
∪ simple_clss (atms_of_ms A)›
using assms(1-4)
proof (induction rule: cdcl⇩N⇩O⇩T_merged_bj_learn.induct)
case cdcl⇩N⇩O⇩T_merged_bj_learn_decide⇩N⇩O⇩T
then show ?case using dpll_bj_clauses by (force dest!: simple_clss_or_not_simplified_cls)
next
case cdcl⇩N⇩O⇩T_merged_bj_learn_propagate⇩N⇩O⇩T
then show ?case using dpll_bj_clauses by (force dest!: simple_clss_or_not_simplified_cls)
next
case cdcl⇩N⇩O⇩T_merged_bj_learn_forget⇩N⇩O⇩T
then show ?case using clauses_remove_cls⇩N⇩O⇩T unfolding state_eq⇩N⇩O⇩T_def
by (force elim!: forget⇩N⇩O⇩TE dest: simple_clss_or_not_simplified_cls)
next
case (cdcl⇩N⇩O⇩T_merged_bj_learn_backjump_l T) note bj = this(1) and inv = this(2) and
atms_clss = this(3) and atms_trail = this(4)
have st: ‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T›
using bj inv cdcl⇩N⇩O⇩T_merged_bj_learn.simps by blast+
have ‹atm_of `(lits_of_l (trail T)) ⊆ atms_of_ms A› and ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_ms A›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_trail_clauses_bound[OF st] inv atms_trail atms_clss
by auto
obtain F' K F L l C' C D where
tr_S: ‹trail S = F' @ Decided K # F› and
T: ‹T ∼ prepend_trail (Propagated L l) (reduce_trail_to⇩N⇩O⇩T F (add_cls⇩N⇩O⇩T D S))› and
‹C ∈# clauses⇩N⇩O⇩T S› and
‹trail S ⊨as CNot C› and
undef: ‹undefined_lit F L› and
‹clauses⇩N⇩O⇩T S ⊨pm add_mset L C'› and
‹F ⊨as CNot C'› and
D: ‹D = add_mset L C'› and
dist: ‹distinct_mset (add_mset L C')› and
tauto: ‹¬ tautology (add_mset L C')› and
‹backjump_l_cond C C' L S T›
using ‹backjump_l S T› apply (elim backjump_lE) by auto
have ‹atms_of C' ⊆ atm_of ` (lits_of_l F)›
using ‹F ⊨as CNot C'› by (simp add: atm_of_in_atm_of_set_iff_in_set_or_uminus_in_set
atms_of_def image_subset_iff in_CNot_implies_uminus(2))
then have ‹atms_of (C'+{#L#}) ⊆ atms_of_ms A›
using T ‹atm_of ` lits_of_l (trail T) ⊆ atms_of_ms A› tr_S undef by auto
then have ‹simple_clss (atms_of (add_mset L C')) ⊆ simple_clss (atms_of_ms A)›
apply - by (rule simple_clss_mono) (simp_all)
then have ‹add_mset L C' ∈ simple_clss (atms_of_ms A)›
using distinct_mset_not_tautology_implies_in_simple_clss[OF dist tauto]
by auto
then show ?case
using T inv atms_clss undef tr_S D by (force dest!: simple_clss_or_not_simplified_cls)
qed
lemma cdcl⇩N⇩O⇩T_merged_bj_learn_not_simplified_decreasing:
assumes ‹cdcl⇩N⇩O⇩T_merged_bj_learn S T›
shows ‹not_simplified_cls (clauses⇩N⇩O⇩T T) ⊆# not_simplified_cls (clauses⇩N⇩O⇩T S)›
using assms apply induction
prefer 4
unfolding not_simplified_cls_tautology_distinct_mset apply (auto elim!: backjump_lE forget⇩N⇩O⇩TE)[3]
by (elim backjump_lE) auto
lemma rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_not_simplified_decreasing:
assumes ‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T›
shows ‹not_simplified_cls (clauses⇩N⇩O⇩T T) ⊆# not_simplified_cls (clauses⇩N⇩O⇩T S)›
using assms apply induction
apply simp
by (drule cdcl⇩N⇩O⇩T_merged_bj_learn_not_simplified_decreasing) auto
lemma rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_clauses_bound:
assumes
‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T› and
‹inv S› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
‹atm_of `(lits_of_l (trail S)) ⊆ atms_of_ms A› and
finite[simp]: ‹finite A›
shows ‹set_mset (clauses⇩N⇩O⇩T T) ⊆ set_mset (not_simplified_cls (clauses⇩N⇩O⇩T S))
∪ simple_clss (atms_of_ms A)›
using assms(1-4)
proof induction
case base
then show ?case by (auto dest!: simple_clss_or_not_simplified_cls)
next
case (step T U) note st = this(1) and cdcl⇩N⇩O⇩T = this(2) and IH = this(3)[OF this(4-6)] and
inv = this(4) and atms_clss_S = this(5) and atms_trail_S = this(6)
have st': ‹cdcl⇩N⇩O⇩T⇧*⇧* S T›
using inv rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T_and_inv st by blast
have ‹inv T›
using inv rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_inv st by blast
moreover
have ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_ms A› and
‹atm_of ` lits_of_l (trail T) ⊆ atms_of_ms A›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_trail_clauses_bound[OF st] inv atms_clss_S
atms_trail_S by blast+
ultimately have ‹set_mset (clauses⇩N⇩O⇩T U)
⊆ set_mset (not_simplified_cls (clauses⇩N⇩O⇩T T)) ∪ simple_clss (atms_of_ms A)›
using cdcl⇩N⇩O⇩T finite cdcl⇩N⇩O⇩T_merged_bj_learn_clauses_bound
by (auto intro!: cdcl⇩N⇩O⇩T_merged_bj_learn_clauses_bound)
moreover have ‹set_mset (not_simplified_cls (clauses⇩N⇩O⇩T T))
⊆ set_mset (not_simplified_cls (clauses⇩N⇩O⇩T S))›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_not_simplified_decreasing[OF st] by auto
ultimately show ?case using IH inv atms_clss_S
by (auto dest!: simple_clss_or_not_simplified_cls)
qed
abbreviation μ⇩C⇩D⇩C⇩L'_bound where
‹μ⇩C⇩D⇩C⇩L'_bound A T ≡ ((2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A))) * 2
+ card (set_mset (not_simplified_cls(clauses⇩N⇩O⇩T T)))
+ 3 ^ card (atms_of_ms A)›
lemma rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_clauses_bound_card:
assumes
‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T› and
‹inv S› and
‹atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A› and
‹atm_of `(lits_of_l (trail S)) ⊆ atms_of_ms A› and
finite: ‹finite A›
shows ‹μ⇩C⇩D⇩C⇩L'_merged A T ≤ μ⇩C⇩D⇩C⇩L'_bound A S›
proof -
have ‹set_mset (clauses⇩N⇩O⇩T T) ⊆ set_mset (not_simplified_cls(clauses⇩N⇩O⇩T S))
∪ simple_clss (atms_of_ms A)›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_clauses_bound[OF assms] .
moreover have ‹card (set_mset (not_simplified_cls(clauses⇩N⇩O⇩T S))
∪ simple_clss (atms_of_ms A))
≤ card (set_mset (not_simplified_cls(clauses⇩N⇩O⇩T S))) + 3 ^ card (atms_of_ms A)›
by (meson Nat.le_trans atms_of_ms_finite simple_clss_card card_Un_le finite
nat_add_left_cancel_le)
ultimately have ‹card (set_mset (clauses⇩N⇩O⇩T T))
≤ card (set_mset (not_simplified_cls(clauses⇩N⇩O⇩T S))) + 3 ^ card (atms_of_ms A)›
by (meson Nat.le_trans atms_of_ms_finite simple_clss_finite card_mono
finite_UnI finite_set_mset local.finite)
moreover have ‹((2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) - μ⇩C' A T) * 2
≤ (2 + card (atms_of_ms A)) ^ (1 + card (atms_of_ms A)) * 2›
by auto
ultimately show ?thesis unfolding μ⇩C⇩D⇩C⇩L'_merged_def by auto
qed
sublocale cdcl⇩N⇩O⇩T_increasing_restarts_ops ‹λS T. T ∼ reduce_trail_to⇩N⇩O⇩T ([]::'a list) S›
cdcl⇩N⇩O⇩T_merged_bj_learn f
‹λA S. atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A
∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A ∧ finite A›
μ⇩C⇩D⇩C⇩L'_merged
‹λS. inv S ∧ no_dup (trail S)›
μ⇩C⇩D⇩C⇩L'_bound
apply unfold_locales
using unbounded apply simp
using f_ge_1 apply force
using cdcl⇩N⇩O⇩T_merged_bj_learn_trail_clauses_bound apply meson
apply (simp add: cdcl⇩N⇩O⇩T_decreasing_measure')
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_clauses_bound_card apply blast
apply (drule rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_not_simplified_decreasing)
apply (auto simp: card_mono set_mset_mono)[]
apply simp
apply auto[]
using cdcl⇩N⇩O⇩T_merged_bj_learn_no_dup_inv cdcl_merged_inv apply blast
apply (auto simp: inv_restart)[]
done
lemma cdcl⇩N⇩O⇩T_restart_μ⇩C⇩D⇩C⇩L'_merged_le_μ⇩C⇩D⇩C⇩L'_bound:
assumes
‹cdcl⇩N⇩O⇩T_restart T V›
‹inv (fst T)› and
‹no_dup (trail (fst T))› and
‹atms_of_mm (clauses⇩N⇩O⇩T (fst T)) ⊆ atms_of_ms A› and
‹atm_of ` lits_of_l (trail (fst T)) ⊆ atms_of_ms A› and
‹finite A›
shows ‹μ⇩C⇩D⇩C⇩L'_merged A (fst V) ≤ μ⇩C⇩D⇩C⇩L'_bound A (fst T)›
using assms
proof induction
case (restart_full S T n)
show ?case
unfolding fst_conv
apply (rule rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_clauses_bound_card)
using restart_full unfolding full1_def by (force dest!: tranclp_into_rtranclp)+
next
case (restart_step m S T n U) note st = this(1) and U = this(3) and inv = this(4) and
n_d = this(5) and atms_clss = this(6) and atms_trail = this(7) and finite = this(8)
then have st': ‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T›
by (blast dest: relpowp_imp_rtranclp)
then have st'': ‹cdcl⇩N⇩O⇩T⇧*⇧* S T›
using inv n_d apply - by (rule rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T) auto
have ‹inv T›
apply (rule rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_inv)
using inv st' n_d by auto
then have ‹inv U›
using U by (auto simp: inv_restart)
have ‹atms_of_mm (clauses⇩N⇩O⇩T T) ⊆ atms_of_ms A›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_trail_clauses_bound[OF st'] inv atms_clss atms_trail n_d
by simp
then have ‹atms_of_mm (clauses⇩N⇩O⇩T U) ⊆ atms_of_ms A›
using U by simp
have ‹not_simplified_cls (clauses⇩N⇩O⇩T U) ⊆# not_simplified_cls (clauses⇩N⇩O⇩T T)›
using ‹U ∼ reduce_trail_to⇩N⇩O⇩T [] T› by auto
moreover have ‹not_simplified_cls (clauses⇩N⇩O⇩T T) ⊆# not_simplified_cls (clauses⇩N⇩O⇩T S)›
apply (rule rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_not_simplified_decreasing)
using ‹(cdcl⇩N⇩O⇩T_merged_bj_learn ^^ m) S T› by (auto dest!: relpowp_imp_rtranclp)
ultimately have U_S: ‹not_simplified_cls (clauses⇩N⇩O⇩T U) ⊆# not_simplified_cls (clauses⇩N⇩O⇩T S)›
by auto
have ‹(set_mset (clauses⇩N⇩O⇩T U))
⊆ set_mset (not_simplified_cls (clauses⇩N⇩O⇩T U)) ∪ simple_clss (atms_of_ms A)›
apply (rule rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_clauses_bound)
apply simp
using ‹inv U› apply simp
using ‹atms_of_mm (clauses⇩N⇩O⇩T U) ⊆ atms_of_ms A› apply simp
using U apply simp
using finite apply simp
done
then have f1: ‹card (set_mset (clauses⇩N⇩O⇩T U)) ≤ card (set_mset (not_simplified_cls (clauses⇩N⇩O⇩T U))
∪ simple_clss (atms_of_ms A))›
by (simp add: simple_clss_finite card_mono local.finite)
moreover have ‹set_mset (not_simplified_cls (clauses⇩N⇩O⇩T U)) ∪ simple_clss (atms_of_ms A)
⊆ set_mset (not_simplified_cls (clauses⇩N⇩O⇩T S)) ∪ simple_clss (atms_of_ms A)›
using U_S by auto
then have f2:
‹card (set_mset (not_simplified_cls (clauses⇩N⇩O⇩T U)) ∪ simple_clss (atms_of_ms A))
≤ card (set_mset (not_simplified_cls (clauses⇩N⇩O⇩T S)) ∪ simple_clss (atms_of_ms A))›
by (simp add: simple_clss_finite card_mono local.finite)
moreover have ‹card (set_mset (not_simplified_cls (clauses⇩N⇩O⇩T S))
∪ simple_clss (atms_of_ms A))
≤ card (set_mset (not_simplified_cls (clauses⇩N⇩O⇩T S))) + card (simple_clss (atms_of_ms A))›
using card_Un_le by blast
moreover have ‹card (simple_clss (atms_of_ms A)) ≤ 3 ^ card (atms_of_ms A)›
using atms_of_ms_finite simple_clss_card local.finite by blast
ultimately have ‹card (set_mset (clauses⇩N⇩O⇩T U))
≤ card (set_mset (not_simplified_cls (clauses⇩N⇩O⇩T S))) + 3 ^ card (atms_of_ms A)›
by linarith
then show ?case unfolding μ⇩C⇩D⇩C⇩L'_merged_def by auto
qed
lemma cdcl⇩N⇩O⇩T_restart_μ⇩C⇩D⇩C⇩L'_bound_le_μ⇩C⇩D⇩C⇩L'_bound:
assumes
‹cdcl⇩N⇩O⇩T_restart T V› and
‹no_dup (trail (fst T))› and
‹inv (fst T)› and
fin: ‹finite A›
shows ‹μ⇩C⇩D⇩C⇩L'_bound A (fst V) ≤ μ⇩C⇩D⇩C⇩L'_bound A (fst T)›
using assms(1-3)
proof induction
case (restart_full S T n)
have ‹not_simplified_cls (clauses⇩N⇩O⇩T T) ⊆# not_simplified_cls (clauses⇩N⇩O⇩T S)›
apply (rule rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_not_simplified_decreasing)
using ‹full1 cdcl⇩N⇩O⇩T_merged_bj_learn S T› unfolding full1_def
by (auto dest: tranclp_into_rtranclp)
then show ?case by (auto simp: card_mono set_mset_mono)
next
case (restart_step m S T n U) note st = this(1) and U = this(3) and n_d = this(4) and
inv = this(5)
then have st': ‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T›
by (blast dest: relpowp_imp_rtranclp)
then have st'': ‹cdcl⇩N⇩O⇩T⇧*⇧* S T›
using inv n_d apply - by (rule rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T) auto
have ‹inv T›
apply (rule rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_inv)
using inv st' n_d by auto
then have ‹inv U›
using U by (auto simp: inv_restart)
have ‹not_simplified_cls (clauses⇩N⇩O⇩T U) ⊆# not_simplified_cls (clauses⇩N⇩O⇩T T)›
using ‹U ∼ reduce_trail_to⇩N⇩O⇩T [] T› by auto
moreover have ‹not_simplified_cls (clauses⇩N⇩O⇩T T) ⊆# not_simplified_cls (clauses⇩N⇩O⇩T S)›
apply (rule rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_not_simplified_decreasing)
using ‹(cdcl⇩N⇩O⇩T_merged_bj_learn ^^ m) S T› by (auto dest!: relpowp_imp_rtranclp)
ultimately have U_S: ‹not_simplified_cls (clauses⇩N⇩O⇩T U) ⊆# not_simplified_cls (clauses⇩N⇩O⇩T S)›
by auto
then show ?case by (auto simp: card_mono set_mset_mono)
qed
sublocale cdcl⇩N⇩O⇩T_increasing_restarts _ _ _ _ _ _ f
‹λS T. T ∼ reduce_trail_to⇩N⇩O⇩T ([]::'a list) S›
‹λA S. atms_of_mm (clauses⇩N⇩O⇩T S) ⊆ atms_of_ms A
∧ atm_of ` lits_of_l (trail S) ⊆ atms_of_ms A ∧ finite A›
μ⇩C⇩D⇩C⇩L'_merged cdcl⇩N⇩O⇩T_merged_bj_learn
‹λS. inv S ∧ no_dup (trail S)›
‹λA T. ((2+card (atms_of_ms A)) ^ (1+card (atms_of_ms A))) * 2
+ card (set_mset (not_simplified_cls(clauses⇩N⇩O⇩T T)))
+ 3 ^ card (atms_of_ms A)›
apply unfold_locales
using cdcl⇩N⇩O⇩T_restart_μ⇩C⇩D⇩C⇩L'_merged_le_μ⇩C⇩D⇩C⇩L'_bound apply force
using cdcl⇩N⇩O⇩T_restart_μ⇩C⇩D⇩C⇩L'_bound_le_μ⇩C⇩D⇩C⇩L'_bound by fastforce
lemma true_clss_ext_decrease_right_insert: ‹I ⊨sext insert C (set_mset M) ⟹ I ⊨sextm M›
by (metis Diff_insert_absorb insert_absorb true_clss_ext_decrease_right_remove_r)
lemma true_clss_ext_decrease_add_implied:
assumes ‹M ⊨pm C›
shows ‹I⊨sext insert C (set_mset M) ⟷ I⊨sextm M›
proof -
{ fix J
assume
‹I ⊨sextm M› and
‹I ⊆ J› and
tot: ‹total_over_m J (set_mset ({#C#} + M))› and
cons: ‹consistent_interp J›
then have ‹J ⊨sm M› unfolding true_clss_ext_def by auto
moreover
with ‹M ⊨pm C› have ‹J ⊨ C›
using tot cons unfolding true_clss_cls_def by auto
ultimately have ‹J ⊨sm {#C#} + M› by auto
}
then have H: ‹I ⊨sextm M ⟹ I ⊨sext insert C (set_mset M)›
unfolding true_clss_ext_def by auto
then show ?thesis
by (auto simp: true_clss_ext_decrease_right_insert)
qed
lemma cdcl⇩N⇩O⇩T_merged_bj_learn_bj_sat_ext_iff:
assumes ‹cdcl⇩N⇩O⇩T_merged_bj_learn S T› and inv: ‹inv S›
shows ‹I⊨sextm clauses⇩N⇩O⇩T S ⟷ I⊨sextm clauses⇩N⇩O⇩T T›
using assms
proof (induction rule: cdcl⇩N⇩O⇩T_merged_bj_learn.induct)
case (cdcl⇩N⇩O⇩T_merged_bj_learn_backjump_l T) note bj_l = this(1)
obtain C' L D S' where
learn: ‹learn S' T› and
bj: ‹backjump S S'› and
atms_C: ‹atms_of (add_mset L C') ⊆ atms_of_mm (clauses⇩N⇩O⇩T S) ∪ atm_of ` (lits_of_l (trail S))› and
D: ‹D = add_mset L C'› and
T: ‹T ∼ add_cls⇩N⇩O⇩T D S'› and
clss_D: ‹clauses⇩N⇩O⇩T S ⊨pm D›
using bj_l inv backjump_l_backjump_learn [of S] by blast
have [simp]: ‹clauses⇩N⇩O⇩T S' = clauses⇩N⇩O⇩T S›
using bj by (auto elim: backjumpE)
have ‹(I ⊨sextm clauses⇩N⇩O⇩T S) ⟷ (I ⊨sextm clauses⇩N⇩O⇩T S')›
using bj bj_backjump dpll_bj_clauses inv by fastforce
then show ?case
using clss_D T by (auto simp: true_clss_ext_decrease_add_implied)
qed (auto simp: cdcl⇩N⇩O⇩T_bj_sat_ext_iff
dest!: dpll_bj.intros cdcl⇩N⇩O⇩T.intros)
lemma rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_bj_sat_ext_iff:
assumes ‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T›and ‹inv S›
shows ‹I⊨sextm clauses⇩N⇩O⇩T S ⟷ I⊨sextm clauses⇩N⇩O⇩T T›
using assms apply (induction rule: rtranclp_induct)
apply simp
using cdcl⇩N⇩O⇩T_merged_bj_learn_bj_sat_ext_iff
rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T_and_inv by blast
lemma cdcl⇩N⇩O⇩T_restart_eq_sat_iff:
assumes
‹cdcl⇩N⇩O⇩T_restart S T› and
inv: ‹inv (fst S)›
shows ‹I⊨sextm clauses⇩N⇩O⇩T (fst S) ⟷ I ⊨sextm clauses⇩N⇩O⇩T (fst T)›
using assms
proof (induction rule: cdcl⇩N⇩O⇩T_restart.induct)
case (restart_full S T n)
then have ‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T ›
by (simp add: tranclp_into_rtranclp full1_def)
then show ?case
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_bj_sat_ext_iff restart_full.prems by auto
next
case (restart_step m S T n U)
then have ‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T›
by (auto simp: tranclp_into_rtranclp full1_def dest!: relpowp_imp_rtranclp)
then have ‹I ⊨sextm clauses⇩N⇩O⇩T S ⟷ I ⊨sextm clauses⇩N⇩O⇩T T›
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_bj_sat_ext_iff restart_step.prems by auto
moreover have ‹I ⊨sextm clauses⇩N⇩O⇩T T ⟷ I ⊨sextm clauses⇩N⇩O⇩T U›
using restart_step.hyps(3) by auto
ultimately show ?case by auto
qed
lemma rtranclp_cdcl⇩N⇩O⇩T_restart_eq_sat_iff:
assumes
‹cdcl⇩N⇩O⇩T_restart⇧*⇧* S T› and
inv: ‹inv (fst S)› and n_d: ‹no_dup(trail (fst S))›
shows ‹I⊨sextm clauses⇩N⇩O⇩T (fst S) ⟷ I ⊨sextm clauses⇩N⇩O⇩T (fst T)›
using assms(1)
proof (induction rule: rtranclp_induct)
case base
then show ?case by simp
next
case (step T U) note st = this(1) and cdcl = this(2) and IH = this(3)
have ‹inv (fst T)› and ‹no_dup (trail (fst T))›
using rtranclp_cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv using st inv n_d by blast+
then have ‹I⊨sextm clauses⇩N⇩O⇩T (fst T) ⟷ I ⊨sextm clauses⇩N⇩O⇩T (fst U)›
using cdcl⇩N⇩O⇩T_restart_eq_sat_iff cdcl by blast
then show ?case using IH by blast
qed
lemma cdcl⇩N⇩O⇩T_restart_all_decomposition_implies_m:
assumes
‹cdcl⇩N⇩O⇩T_restart S T› and
inv: ‹inv (fst S)› and n_d: ‹no_dup(trail (fst S))› and
‹all_decomposition_implies_m (clauses⇩N⇩O⇩T (fst S))
(get_all_ann_decomposition (trail (fst S)))›
shows ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T (fst T))
(get_all_ann_decomposition (trail (fst T)))›
using assms
proof induction
case (restart_full S T n) note full = this(1) and inv = this(2) and n_d = this(3) and
decomp = this(4)
have st: ‹cdcl⇩N⇩O⇩T_merged_bj_learn⇧*⇧* S T› and
n_s: ‹no_step cdcl⇩N⇩O⇩T_merged_bj_learn T›
using full unfolding full1_def by (fast dest: tranclp_into_rtranclp)+
have st': ‹cdcl⇩N⇩O⇩T⇧*⇧* S T›
using inv rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_is_rtranclp_cdcl⇩N⇩O⇩T_and_inv st n_d by auto
have ‹inv T›
using rtranclp_cdcl⇩N⇩O⇩T_cdcl⇩N⇩O⇩T_inv[OF st] inv n_d by auto
then show ?case
using rtranclp_cdcl⇩N⇩O⇩T_merged_bj_learn_all_decomposition_implies[OF _ _ decomp] st inv by auto
next
case (restart_step m S T n U) note st = this(1) and U = this(3) and inv = this(4) and
n_d = this(5) and decomp = this(6)
show ?case using U by auto
qed
lemma rtranclp_cdcl⇩N⇩O⇩T_restart_all_decomposition_implies_m:
assumes
‹cdcl⇩N⇩O⇩T_restart⇧*⇧* S T› and
inv: ‹inv (fst S)› and n_d: ‹no_dup(trail (fst S))› and
decomp: ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T (fst S))
(get_all_ann_decomposition (trail (fst S)))›
shows ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T (fst T))
(get_all_ann_decomposition (trail (fst T)))›
using assms
proof induction
case base
then show ?case using decomp by simp
next
case (step T U) note st = this(1) and cdcl = this(2) and IH = this(3)[OF this(4-)] and
inv = this(4) and n_d = this(5) and decomp = this(6)
have ‹inv (fst T)› and ‹no_dup (trail (fst T))›
using rtranclp_cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv using st inv n_d by blast+
then show ?case
using cdcl⇩N⇩O⇩T_restart_all_decomposition_implies_m[OF cdcl] IH by auto
qed
lemma full_cdcl⇩N⇩O⇩T_restart_normal_form:
assumes
full: ‹full cdcl⇩N⇩O⇩T_restart S T› and
inv: ‹inv (fst S)› and n_d: ‹no_dup(trail (fst S))› and
decomp: ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T (fst S))
(get_all_ann_decomposition (trail (fst S)))› and
atms_cls: ‹atms_of_mm (clauses⇩N⇩O⇩T (fst S)) ⊆ atms_of_ms A› and
atms_trail: ‹atm_of ` lits_of_l (trail (fst S)) ⊆ atms_of_ms A› and
fin: ‹finite A›
shows ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T (fst S)))
∨ lits_of_l (trail (fst T)) ⊨sextm clauses⇩N⇩O⇩T (fst S) ∧
satisfiable (set_mset (clauses⇩N⇩O⇩T (fst S)))›
proof -
have inv_T: ‹inv (fst T)› and n_d_T: ‹no_dup (trail (fst T))›
using rtranclp_cdcl⇩N⇩O⇩T_with_restart_cdcl⇩N⇩O⇩T_inv using full inv n_d unfolding full_def by blast+
moreover have
atms_cls_T: ‹atms_of_mm (clauses⇩N⇩O⇩T (fst T)) ⊆ atms_of_ms A› and
atms_trail_T: ‹atm_of ` lits_of_l (trail (fst T)) ⊆ atms_of_ms A›
using rtranclp_cdcl⇩N⇩O⇩T_with_restart_bound_inv[of S T A] full atms_cls atms_trail fin inv n_d
unfolding full_def by blast+
ultimately have ‹no_step cdcl⇩N⇩O⇩T_merged_bj_learn (fst T)›
apply -
apply (rule no_step_cdcl⇩N⇩O⇩T_restart_no_step_cdcl⇩N⇩O⇩T[of _ A])
using full unfolding full_def apply simp
apply simp
using fin apply simp
done
moreover have ‹all_decomposition_implies_m (clauses⇩N⇩O⇩T (fst T))
(get_all_ann_decomposition (trail (fst T)))›
using rtranclp_cdcl⇩N⇩O⇩T_restart_all_decomposition_implies_m[of S T] inv n_d decomp
full unfolding full_def by auto
ultimately have ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T (fst T)))
∨ trail (fst T) ⊨asm clauses⇩N⇩O⇩T (fst T) ∧ satisfiable (set_mset (clauses⇩N⇩O⇩T (fst T)))›
apply -
apply (rule cdcl⇩N⇩O⇩T_merged_bj_learn_final_state)
using atms_cls_T atms_trail_T fin n_d_T fin inv_T by blast+
then consider
(unsat) ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T (fst T)))›
| (sat) ‹trail (fst T) ⊨asm clauses⇩N⇩O⇩T (fst T)› and ‹satisfiable (set_mset (clauses⇩N⇩O⇩T (fst T)))›
by auto
then show ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T (fst S)))
∨ lits_of_l (trail (fst T)) ⊨sextm clauses⇩N⇩O⇩T (fst S) ∧
satisfiable (set_mset (clauses⇩N⇩O⇩T (fst S)))›
proof cases
case unsat
then have ‹unsatisfiable (set_mset (clauses⇩N⇩O⇩T (fst S)))›
unfolding satisfiable_def apply auto
using rtranclp_cdcl⇩N⇩O⇩T_restart_eq_sat_iff[of S T ] full inv n_d
consistent_true_clss_ext_satisfiable true_clss_imp_true_cls_ext
unfolding satisfiable_def full_def by blast
then show ?thesis by blast
next
case sat
then have ‹lits_of_l (trail (fst T)) ⊨sextm clauses⇩N⇩O⇩T (fst T)›
using true_clss_imp_true_cls_ext by (auto simp: true_annots_true_cls)
then have ‹lits_of_l (trail (fst T)) ⊨sextm clauses⇩N⇩O⇩T (fst S)›
using rtranclp_cdcl⇩N⇩O⇩T_restart_eq_sat_iff[of S T] full inv n_d unfolding full_def by blast
moreover then have ‹satisfiable (set_mset (clauses⇩N⇩O⇩T (fst S)))›
using consistent_true_clss_ext_satisfiable distinct_consistent_interp n_d_T by fast
ultimately show ?thesis by fast
qed
qed
corollary full_cdcl⇩N⇩O⇩T_restart_normal_form_init_state:
assumes
init_state: ‹trail S = []› ‹clauses⇩N⇩O⇩T S = N› and
full: ‹full cdcl⇩N⇩O⇩T_restart (S, 0) T› and
inv: ‹inv S›
shows ‹unsatisfiable (set_mset N)
∨ lits_of_l (trail (fst T)) ⊨sextm N ∧ satisfiable (set_mset N)›
using full_cdcl⇩N⇩O⇩T_restart_normal_form[of ‹(S, 0)› T] assms by auto
end
end