Theory IsaSAT_LBD
theory IsaSAT_LBD
imports IsaSAT_Setup
begin
definition mark_lbd_from_clause_heur :: ‹trail_pol ⇒ arena ⇒ nat ⇒ lbd ⇒ lbd nres› where
‹mark_lbd_from_clause_heur M N C lbd = do {
n ← mop_arena_length N C;
nfoldli [1..<n] (λ_. True)
(λi lbd. do {
L ← mop_arena_lit2 N C i;
ASSERT(get_level_pol_pre (M, L));
let lev = get_level_pol M L;
ASSERT(lev ≤ Suc (unat32_max div 2));
RETURN (if lev = 0 then lbd else lbd_write lbd lev)})
lbd}›
lemma count_decided_le_length: ‹count_decided M ≤ length M›
unfolding count_decided_def by (rule length_filter_le)
lemma mark_lbd_from_clause_heur_correctness:
assumes ‹(M, M') ∈ trail_pol 𝒜› and ‹valid_arena N N' vdom› ‹C ∈# dom_m N'› and
‹literals_are_in_ℒ⇩i⇩n 𝒜 (mset (N' ∝ C))›
shows ‹mark_lbd_from_clause_heur M N C lbd ≤ ⇓ Id (SPEC(λ_::bool list. True))›
using assms
unfolding mark_lbd_from_clause_heur_def
apply (refine_vcg mop_arena_length[THEN fref_to_Down_curry, THEN order_trans, of N' C _ _ vdom]
nfoldli_rule[where I = ‹ λ_ _ _. True›])
subgoal by auto
subgoal by auto
unfolding Down_id_eq comp_def
apply (refine_vcg mop_arena_length[THEN fref_to_Down_curry, THEN order_trans, of N' C _ _ vdom]
nfoldli_rule[where I = ‹ λ_ _ _. True›] mop_arena_lit[THEN order_trans])
subgoal by auto
apply assumption+
subgoal by simp
apply auto[]
subgoal H
by (metis append_cons_eq_upt(2) eq_upt_Cons_conv)
subgoal for x l1 l2 σ xa using H[of l1 x l2] apply -
by (auto intro!: get_level_pol_pre literals_are_in_ℒ⇩i⇩n_in_ℒ⇩a⇩l⇩l)
subgoal for x l1 l2 σ xa using H[of l1 x l2] apply -
using count_decided_ge_get_level[of M' xa] count_decided_le_length[of M']
by (auto simp: trail_pol_alt_def literals_are_in_ℒ⇩i⇩n_in_ℒ⇩a⇩l⇩l simp flip: get_level_get_level_pol)
done
definition calculate_LBD_st :: ‹(nat, nat) ann_lits ⇒ nat clauses_l ⇒ nat ⇒ nat clauses_l nres› where
‹calculate_LBD_st = (λM N C. RETURN N)›
abbreviation TIER_TWO_MAXIMUM where
‹TIER_TWO_MAXIMUM ≡ 6›
abbreviation TIER_ONE_MAXIMUM where
‹TIER_ONE_MAXIMUM ≡ 2›
definition calculate_LBD_heur_st :: ‹_ ⇒ arena ⇒ lbd ⇒ nat ⇒ (arena × lbd) nres› where
‹calculate_LBD_heur_st = (λM N lbd C. do{
old_glue ← mop_arena_lbd N C;
st ← mop_arena_status N C;
if st = IRRED then RETURN (N, lbd)
else if old_glue < TIER_TWO_MAXIMUM then do {
N ← mop_arena_mark_used2 N C;
RETURN (N, lbd)
}
else do {
lbd ← mark_lbd_from_clause_heur M N C lbd;
glue ← get_LBD lbd;
lbd ← lbd_empty lbd;
N ← (if glue < old_glue then mop_arena_update_lbd C glue N else RETURN N);
N ← (if glue < TIER_TWO_MAXIMUM ∨ old_glue < TIER_TWO_MAXIMUM then mop_arena_mark_used2 N C else mop_arena_mark_used N C);
RETURN (N, lbd)
}})›
lemma calculate_LBD_st_alt_def:
‹calculate_LBD_st = (λM N C. do {
old_glue :: nat ← SPEC(λ_ . True);
st :: clause_status ← SPEC(λ_ . True);
if st = IRRED then RETURN N
else if old_glue < 6 then do {
_ ← RETURN N;
RETURN N
}
else do {
lbd::bool list ← SPEC(λ_. True);
glue::nat ← get_LBD lbd;
_::bool list ← lbd_empty lbd;
_ ← RETURN N;
_ ← RETURN N;
RETURN N
}})› (is ‹?A = ?B›)
unfolding calculate_LBD_st_def get_LBD_def lbd_empty_def
by (auto intro!: ext rhs_step_bind_RES split: if_splits cong: if_cong)
lemma RF_COME_ON: ‹(x, y) ∈ Id ⟹ f x ≤ ⇓ Id (f y)›
by auto
lemma mop_arena_update_lbd:
‹C ∈# dom_m N ⟹ valid_arena arena N vdom ⟹
mop_arena_update_lbd C glue arena ≤ SPEC(λc. (c, N) ∈ {(c, N'). N'=N ∧ valid_arena c N vdom ∧
length c = length arena})›
unfolding mop_arena_update_lbd_def
by (auto simp: update_lbd_pre_def arena_is_valid_clause_idx_def
intro!: ASSERT_leI valid_arena_update_lbd)
lemma mop_arena_mark_used_valid:
‹C ∈# dom_m N ⟹ valid_arena arena N vdom ⟹
mop_arena_mark_used arena C ≤ SPEC(λc. (c, N) ∈ {(c, N'). N'=N ∧ valid_arena c N vdom ∧
length c = length arena})›
unfolding mop_arena_mark_used_def
by (auto simp: arena_act_pre_def arena_is_valid_clause_idx_def
intro!: ASSERT_leI valid_arena_mark_used)
lemma mop_arena_mark_used2_valid:
‹C ∈# dom_m N ⟹ valid_arena arena N vdom ⟹
mop_arena_mark_used2 arena C ≤ SPEC(λc. (c, N) ∈ {(c, N'). N'=N ∧ valid_arena c N vdom ∧
length c = length arena})›
unfolding mop_arena_mark_used2_def
by (auto simp: arena_act_pre_def arena_is_valid_clause_idx_def
intro!: ASSERT_leI valid_arena_mark_used2)
abbreviation twl_st_heur_conflict_ana'
:: ‹nat ⇒ clss_size ⇒ (isasat × nat twl_st_wl) set›
where
‹twl_st_heur_conflict_ana' r lcount ≡ {(S, T). (S, T) ∈ twl_st_heur_conflict_ana ∧
length (get_clauses_wl_heur S) = r ∧ get_learned_count S = lcount}›
lemma calculate_LBD_heur_st_calculate_LBD_st:
assumes ‹valid_arena arena N vdom›
‹(M, M') ∈ trail_pol 𝒜›
‹C ∈# dom_m N›
‹literals_are_in_ℒ⇩i⇩n 𝒜 (mset (N ∝ C))› ‹(C, C') ∈ nat_rel›
shows ‹calculate_LBD_heur_st M arena lbd C ≤
⇓{((arena', lbd), N'). valid_arena arena' N' vdom ∧ N = N' ∧ length arena = length arena'}
(calculate_LBD_st M' N C')›
proof -
have WTF: ‹(a, b) ∈ R ⟹ b=b' ⟹ (a, b') ∈ R› for a a' b b' R
by auto
show ?thesis
using assms
unfolding calculate_LBD_heur_st_def calculate_LBD_st_alt_def
apply (refine_vcg mark_lbd_from_clause_heur_correctness[of _ M'
𝒜 _ N vdom]
mop_arena_update_lbd[of _ _ _ vdom]
mop_arena_mark_used_valid[of _ N _ vdom]
mop_arena_mark_used2_valid[of _ N _ vdom])
subgoal
unfolding twl_st_heur_conflict_ana_def
by (auto simp: mop_arena_lbd_def get_clause_LBD_pre_def arena_is_valid_clause_idx_def
intro!: ASSERT_leI exI[of _ N] exI[of _ vdom])
subgoal
unfolding twl_st_heur_conflict_ana_def
by (auto simp: mop_arena_status_def arena_is_valid_clause_vdom_def arena_is_valid_clause_idx_def
intro!: ASSERT_leI exI[of _ N] exI[of _ vdom])
subgoal
by (auto simp: twl_st_heur_conflict_ana_def RETURN_RES_refine_iff)
subgoal
by (auto simp: twl_st_heur_conflict_ana_def RETURN_RES_refine_iff)
subgoal
by (auto simp: twl_st_heur_conflict_ana_def RETURN_RES_refine_iff)
subgoal
by (force simp: twl_st_heur_conflict_ana_def)
apply (rule RF_COME_ON)
subgoal
by auto
apply (rule RF_COME_ON)
subgoal
by auto
subgoal
unfolding twl_st_heur_conflict_ana_def
by (auto simp: mop_arena_lbd_def get_clause_LBD_pre_def arena_is_valid_clause_idx_def
intro!: ASSERT_leI exI[of _ ‹get_clauses_wl (fst y)›] exI[of _ ‹set (get_vdom (fst x))›])
subgoal
by (force simp: twl_st_heur_conflict_ana_def)
subgoal
by (force simp: twl_st_heur_conflict_ana_def)
subgoal
by (force simp: twl_st_heur_conflict_ana_def)
done
qed
definition mark_lbd_from_list :: ‹_› where
‹mark_lbd_from_list M C lbd = do {
nfoldli (drop 1 C) (λ_. True)
(λL lbd. RETURN (lbd_write lbd (get_level M L))) lbd
}›
definition mark_lbd_from_list_heur :: ‹trail_pol ⇒ nat clause_l ⇒ lbd ⇒ lbd nres› where
‹mark_lbd_from_list_heur M C lbd = do {
let n = length C;
nfoldli [1..<n] (λ_. True)
(λi lbd. do {
ASSERT(i < length C);
let L = C ! i;
ASSERT(get_level_pol_pre (M, L));
let lev = get_level_pol M L;
ASSERT(lev ≤ Suc (unat32_max div 2));
RETURN (if lev = 0 then lbd else lbd_write lbd lev)})
lbd}›
definition mark_lbd_from_conflict :: ‹isasat ⇒ isasat nres› where
‹mark_lbd_from_conflict = (λS. do{
lbd ← mark_lbd_from_list_heur (get_trail_wl_heur S) (get_outlearned_heur S) (get_lbd S);
RETURN (set_lbd_wl_heur lbd S)
})›
lemma mark_lbd_from_list_heur_correctness:
assumes ‹(M, M') ∈ trail_pol 𝒜› and ‹literals_are_in_ℒ⇩i⇩n 𝒜 (mset (tl C))›
shows ‹mark_lbd_from_list_heur M C lbd ≤ ⇓ Id (SPEC(λ_::bool list. True))›
using assms
unfolding mark_lbd_from_list_heur_def
apply (refine_vcg nfoldli_rule[where I = ‹λ_ _ _. True›])
subgoal by auto
subgoal
by (auto simp: upt_eq_lel_conv nth_tl)
subgoal for x l1 l2 σ
using literals_are_in_ℒ⇩i⇩n_in_ℒ⇩a⇩l⇩l[of 𝒜 ‹tl C› ‹x - 1›]
by (auto intro!: get_level_pol_pre simp: upt_eq_lel_conv nth_tl)
subgoal for x l1 l2 σ
using count_decided_ge_get_level[of M' ‹C ! x›] count_decided_le_length[of M']
using literals_are_in_ℒ⇩i⇩n_in_ℒ⇩a⇩l⇩l[of 𝒜 ‹tl C› ‹x - 1›]
by (auto simp: upt_eq_lel_conv nth_tl simp flip: get_level_get_level_pol)
(auto simp: trail_pol_alt_def)
done
definition mark_LBD_st :: ‹'v twl_st_wl ⇒ ('v twl_st_wl) nres› where
‹mark_LBD_st = (λS. SPEC (λ(T). S = T))›
lemma mark_LBD_st_alt_def:
‹mark_LBD_st S = do {n :: bool list ← SPEC (λ_. True); SPEC (λ(T). S = T)}›
unfolding mark_LBD_st_def
by auto
lemma mark_lbd_from_conflict_mark_LBD_st:
‹(mark_lbd_from_conflict, mark_LBD_st) ∈
[λS. get_conflict_wl S ≠ None ∧ literals_are_in_ℒ⇩i⇩n (all_atms_st S) (the (get_conflict_wl S))]⇩f
twl_st_heur_conflict_ana → ⟨twl_st_heur_conflict_ana⟩nres_rel›
unfolding mark_lbd_from_conflict_def mark_LBD_st_alt_def
apply (intro frefI nres_relI)
subgoal for x y
apply (refine_rcg mark_lbd_from_list_heur_correctness[of _ ‹get_trail_wl y› ‹all_atms_st y›,
THEN order_trans])
subgoal
by (force simp: twl_st_heur_conflict_ana_def)
subgoal
by (rule literals_are_in_ℒ⇩i⇩n_mono[of _ ‹(the (get_conflict_wl y))›])
(auto simp: twl_st_heur_conflict_ana_def out_learned_def)
subgoal by auto
subgoal by (auto simp: twl_st_heur_conflict_ana_def RETURN_RES_refine_iff)
done
done
definition update_lbd_and_mark_used where
‹update_lbd_and_mark_used i glue N =
(let N = update_lbd i glue N in
(if glue ≤ TIER_TWO_MAXIMUM then mark_used2 N i else mark_used N i))›
lemma length_update_lbd_and_mark_used[simp]: ‹length (update_lbd_and_mark_used i glue N) = length N›
by (auto simp: update_lbd_and_mark_used_def Let_def split: if_splits)
text ‹CaDiCaL sets the used flags of clauses only as 1, not as two.›
definition update_lbd_shrunk_clause where
‹update_lbd_shrunk_clause C N = do {
old_glue ← mop_arena_lbd N C;
st ← mop_arena_status N C;
le ← mop_arena_length N C;
ASSERT (le ≥ 2);
if st = IRRED then RETURN N
else do {
let new_glue = (if le - 1 ≥ old_glue then old_glue else le - 1);
ASSERT (update_lbd_pre ((C, new_glue), N));
RETURN (update_lbd_and_mark_used C new_glue N)
}
}›
lemma update_lbd_shrunk_clause_valid:
‹C ∈# dom_m N ⟹ valid_arena arena N vdom ⟹
update_lbd_shrunk_clause C arena ≤ SPEC(λc. (c, N) ∈ {(c, N'). N'=N ∧ valid_arena c N vdom ∧
length c = length arena})›
unfolding update_lbd_shrunk_clause_def mop_arena_lbd_def nres_monad3 mop_arena_status_def
mop_arena_length_def update_lbd_and_mark_used_def
apply refine_vcg
subgoal
unfolding get_clause_LBD_pre_def arena_is_valid_clause_idx_def
by auto
subgoal
unfolding arena_is_valid_clause_vdom_def
by auto
subgoal
unfolding arena_is_valid_clause_idx_def
by auto
subgoal
by (rule arena_lifting(18))
subgoal by auto
subgoal by (auto simp: update_lbd_pre_def)
subgoal by (auto simp: Let_def intro!: valid_arena_mark_used2 valid_arena_mark_used
valid_arena_update_lbd)
done
end