Theory IsaSAT_Simplify_Binaries_Defs
theory IsaSAT_Simplify_Binaries_Defs
imports IsaSAT_Setup
IsaSAT_Restart_Defs
IsaSAT_Simplify_Units_Defs
begin
type_synonym 'a ahm = ‹'a list × nat list›
definition ahm_get_marked :: ‹'a::zero ahm ⇒ nat literal ⇒ _› where
‹ahm_get_marked = (λ(C,stamp) L. do {
ASSERT(nat_of_lit L < length C);
RETURN (C!nat_of_lit L)
})›
definition get_marked :: ‹(nat literal ⇒ 'a option) × nat ⇒ nat literal ⇒ _› where
‹get_marked C L = do {
ASSERT(nat_of_lit L < snd C ∧ fst C L ≠ None);
RETURN (the (fst C L))
}›
definition array_hash_map_rel :: ‹('a :: zero × 'b) set ⇒ ('a ahm × _) set› where
‹array_hash_map_rel R = {((xs, support), (ys, m)). m = length xs ∧
(set support =nat_of_lit ` dom ys) ∧
(∀i∈set support. i < m) ∧ distinct support ∧
(∀L. nat_of_lit L < m ⟶ (ys L = None ⟷ xs ! nat_of_lit L = 0)) ∧
(∀L. nat_of_lit L < m ⟶ (∀a. ys L = Some a ⟶ xs ! nat_of_lit L ≠ 0 ∧ (xs ! nat_of_lit L, a) ∈ R))}›
definition ahm_is_marked :: ‹'a::zero ahm ⇒ nat literal ⇒ _› where
‹ahm_is_marked = (λ(C,stamp) L. do {
ASSERT(nat_of_lit L < length C);
RETURN (C!nat_of_lit L ≠ 0)
})›
definition is_marked :: ‹(nat literal ⇒ 'a option) × nat ⇒ nat literal ⇒ _› where
‹is_marked C L = do {
ASSERT(nat_of_lit L < snd C);
RETURN (fst C L ≠ None)
}›
definition update_marked :: ‹(nat literal ⇒ _ option) × nat ⇒ nat literal ⇒ _ ⇒
((nat literal ⇒ _ option) × nat) nres› where
‹update_marked C L v = do {
ASSERT (nat_of_lit L < snd C ∧ (fst C)L ≠ None);
RETURN ((fst C)(L := Some v), snd C)
}›
definition set_marked :: ‹(nat literal ⇒ _ option) × nat ⇒ nat literal ⇒ _ ⇒
((nat literal ⇒ _ option) × nat) nres› where
‹set_marked C L v = do {
ASSERT (nat_of_lit L < snd C ∧ (fst C)L = None);
RETURN ((fst C)(L := Some v), snd C)
}›
definition empty :: ‹(nat literal ⇒ 'b option) × nat ⇒ ((nat literal ⇒ 'b option) × nat) nres› where
‹empty = (λ(_, n). do {
RETURN (λ_. None, n)
})›
lemma ahm_is_marked_is_marked:
‹(uncurry ahm_is_marked, uncurry is_marked)
∈ (array_hash_map_rel R) ×⇩f nat_lit_lit_rel → ⟨bool_rel⟩nres_rel›
unfolding ahm_is_marked_def is_marked_def uncurry_def
apply (intro frefI nres_relI fun_relI)
apply refine_vcg
apply (auto simp: array_hash_map_rel_def ahm_is_marked_def is_marked_def
intro!: ASSERT_leI)[]
apply simp
by (auto simp: array_hash_map_rel_def ahm_is_marked_def is_marked_def
intro!: ASSERT_leI)
lemma ahm_get_marked_get_marked:
‹(uncurry ahm_get_marked, uncurry get_marked)
∈ (array_hash_map_rel R) ×⇩f nat_lit_lit_rel → ⟨R⟩nres_rel›
unfolding ahm_get_marked_def get_marked_def uncurry_def
apply (intro frefI nres_relI fun_relI)
apply refine_vcg
apply (auto simp: array_hash_map_rel_def ahm_is_marked_def is_marked_def
intro!: ASSERT_leI)[]
apply clarsimp
apply (auto simp: array_hash_map_rel_def ahm_is_marked_def is_marked_def
intro!: ASSERT_leI)[]
done
definition ahm_set_marked :: ‹'a :: zero ahm ⇒ nat literal ⇒ _› where
‹ahm_set_marked= (λ(C,stamp) L v. do {
ASSERT(nat_of_lit L < length C ∧ Suc (length stamp) ≤ length C);
RETURN (C[nat_of_lit L := v], stamp @ [nat_of_lit L])
})›
lemma ahm_set_marked_set_marked:
assumes [simp]: ‹⋀a. (0, a) ∉ R›
shows ‹(uncurry2 ahm_set_marked, uncurry2 set_marked)
∈ (array_hash_map_rel R) ×⇩f nat_lit_lit_rel ×⇩f R →⇩f ⟨array_hash_map_rel R⟩nres_rel›
proof -
have [intro!]: ‹Suc (length x2b) ≤ length x1d›
if
‹nat_of_lit x2 < length x1d› and
‹x1d ! nat_of_lit x2 = 0› and
‹set x2b = nat_of_lit ` {a. ∃y. ac a = Some y}› and
‹∀i. (∃y. ac i = Some y) ⟶ nat_of_lit i < length x1d› and
dist: ‹distinct x2b› and
‹∀L. nat_of_lit L < length x1d ⟶ (ac L = None) = (x1d ! nat_of_lit L = 0)›
for ac :: ‹nat literal ⇒ 'a option› and x2 :: ‹nat literal› and x2a :: 'a and x1d :: ‹'b list› and x2b :: ‹nat list› and x2d :: 'b
proof -
have ‹(set x2b) ⊆ nat_of_lit ` (dom ac) ∩ {0..<length x1d}›
using that by (auto simp add: dom_def)
moreover have ‹nat_of_lit x2 ∈ {0..<length x1d}› and notin: ‹nat_of_lit x2 ∉ set x2b›
using that by auto
ultimately have H: ‹insert (nat_of_lit x2) (set x2b) ⊆ {0..<length x1d}›
by blast
show ?thesis
using card_mono[OF _ H] notin dist
by (auto simp: distinct_card)
qed
show ?thesis
unfolding ahm_set_marked_def set_marked_def uncurry_def
apply (intro frefI fun_relI nres_relI)
apply refine_vcg
apply (auto simp: array_hash_map_rel_def ahm_is_marked_def is_marked_def dom_def
intro!: ASSERT_leI)
done
qed
definition ahm_update_marked :: ‹'a :: zero ahm ⇒ nat literal ⇒ _› where
‹ahm_update_marked= (λ(C,stamp) L v. do {
ASSERT(nat_of_lit L < length C);
RETURN (C[nat_of_lit L := v], stamp)
})›
lemma ahm_update_marked_update_marked:
assumes [simp]: ‹⋀a. (0, a) ∉ R›
shows ‹(uncurry2 ahm_update_marked, uncurry2 update_marked)
∈ (array_hash_map_rel R) ×⇩f nat_lit_lit_rel ×⇩f R →⇩f ⟨array_hash_map_rel R⟩nres_rel›
unfolding ahm_update_marked_def update_marked_def uncurry_def
apply (intro frefI nres_relI)
by refine_vcg
(auto simp: array_hash_map_rel_def ahm_is_marked_def is_marked_def dom_def
intro!: ASSERT_leI)
definition ahm_create :: ‹nat ⇒ 'a::zero ahm nres› where
‹ahm_create m = do {
RETURN (replicate m 0, [])
}›
definition create :: ‹nat ⇒ _› where
‹create m = do {
RETURN (λ_. None, m)
}›
lemma ahm_create_create:
‹(ahm_create, create) ∈ nat_rel → ⟨array_hash_map_rel R⟩nres_rel›
unfolding ahm_create_def create_def uncurry_def
by refine_vcg
(auto simp: array_hash_map_rel_def ahm_is_marked_def is_marked_def
intro!: ASSERT_leI)[]
definition ahm_empty :: ‹'a::zero ahm ⇒ 'a ahm nres› where
‹ahm_empty = (λ(CS, support). do {
let n = length support;
(_, CS) ← WHILE⇩T
(λ(i, CS). i < n)
(λ(i, CS). do {ASSERT (i < length support ∧ support ! i < length CS); RETURN (i+1, CS[support ! i := 0])})
(0, CS);
RETURN (CS, take 0 support)
})›
lemma ahm_empty_empty:
‹(ahm_empty, empty) ∈ (array_hash_map_rel R) → ⟨array_hash_map_rel R⟩nres_rel›
proof -
have [simp]: ‹dom (λaa. if nat_of_lit aa ∈ xs then None else m aa) =
dom m - {a. nat_of_lit a ∈ xs}› for xs m
by (auto split: if_splits)
have [simp]: ‹nat_of_lit ` dom x1 = set x2a ⟹ distinct x2a ⟹
nat_of_lit ` (dom x1 - {aa. nat_of_lit aa ∈ set (take a x2a)}) = set (drop a x2a)› for x2a a x1
apply (drule eq_commute[of _ "set x2a", THEN iffD1])
apply (auto simp: dom_def)
apply (metis (mono_tags, lifting) Reversed_Bit_Lists.atd_lem UnE image_subset_iff mem_Collect_eq set_append set_mset_mono set_mset_mset subset_mset.dual_order.refl)
apply (frule in_set_dropD)
apply simp
by (smt (verit, ccfv_threshold) DiffI IntI Reversed_Bit_Lists.atd_lem distinct_append empty_iff image_iff mem_Collect_eq)
show ?thesis
unfolding ahm_empty_def empty_def uncurry_def fref_param1
apply (intro ext frefI nres_relI)
subgoal for x y
apply (refine_vcg WHILET_rule[where I = ‹λ(i, CS). ((CS, drop i (snd x)), (λa. if nat_of_lit a ∈ set (take i (snd x)) then None else fst y a, snd y)) ∈array_hash_map_rel R› and
R = ‹measure (λ(i,_). length (snd x) -i)›])
subgoal by auto
subgoal by auto
subgoal by (clarsimp simp: array_hash_map_rel_def)
subgoal by (auto simp: array_hash_map_rel_def)
subgoal premises p for x1 x2 x1a x2a s a b x1b x2b
using p
by (clarsimp simp: array_hash_map_rel_def less_Suc_eq eq_commute[of _ ‹nat_of_lit ` dom _›]
simp flip: Cons_nth_drop_Suc)
(auto simp: take_Suc_conv_app_nth)
subgoal by (auto simp: nth_list_update' less_Suc_eq array_hash_map_rel_def)
subgoal for x1 x2 x1a x2a s a b
apply (auto simp: array_hash_map_rel_def)
apply (drule_tac x=L in spec)
apply (auto split: if_splits)
done
done
done
qed
definition isa_clause_remove_duplicate_clause_wl :: ‹nat ⇒ isasat ⇒ isasat nres› where
‹isa_clause_remove_duplicate_clause_wl C S = (do{
_ ← log_del_clause_heur S C;
let N' = get_clauses_wl_heur S;
st ← mop_arena_status N' C;
let st = st = IRRED;
ASSERT (mark_garbage_pre (N', C) ∧ arena_is_valid_clause_vdom (N') C);
let N' = extra_information_mark_to_delete (N') C;
let lcount = get_learned_count S;
ASSERT(¬st ⟶ clss_size_lcount lcount ≥ 1);
let lcount = (if st then lcount else (clss_size_decr_lcount lcount));
let stats = get_stats_heur S;
let stats = (incr_binary_red_removed (if st then decr_irred_clss stats else stats));
let S = set_clauses_wl_heur N' S;
let S = set_learned_count_wl_heur lcount S;
let S = set_stats_wl_heur stats S;
RETURN S
})›
definition isa_binary_clause_subres_lits_wl_pre :: ‹_› where
‹isa_binary_clause_subres_lits_wl_pre C L L' S ⟷
(∃T r u. (S, T)∈ twl_st_heur_restart_ana' r u ∧ binary_clause_subres_lits_wl_pre C L L' T)›
definition isa_binary_clause_subres_wl :: ‹_› where
‹isa_binary_clause_subres_wl C L L' S = do {
ASSERT (isa_binary_clause_subres_lits_wl_pre C L L' S);
let _ = log_del_binary_clause L (-L');
let M = get_trail_wl_heur S;
M ← cons_trail_Propagated_tr L 0 M;
let lcount = get_learned_count S;
let N' = get_clauses_wl_heur S;
st ← mop_arena_status N' C;
let st = st = IRRED;
ASSERT (mark_garbage_pre (N', C) ∧ arena_is_valid_clause_vdom (N') C);
let N' = extra_information_mark_to_delete (N') C;
ASSERT(¬st ⟶ (clss_size_lcount lcount ≥ 1 ∧ clss_size_lcountUEk (clss_size_decr_lcount lcount) < learned_clss_count S));
let lcount = (if st then lcount else (clss_size_incr_lcountUEk (clss_size_decr_lcount lcount)));
let stats = get_stats_heur S;
let stats = incr_binary_unit_derived (if st then decr_irred_clss stats else stats);
let stats = incr_units_since_last_GC (incr_uset stats);
let S = set_trail_wl_heur M S;
let S = set_clauses_wl_heur N' S;
let S = set_learned_count_wl_heur lcount S;
let S = set_stats_wl_heur stats S;
RETURN S
}›
definition isa_deduplicate_binary_clauses_wl :: ‹nat literal ⇒ _ ⇒ isasat ⇒ (_ × isasat) nres› where
‹isa_deduplicate_binary_clauses_wl L CS S⇩0 = do {
let CS = CS;
l ← mop_length_watched_by_int S⇩0 L;
ASSERT (l ≤ length (get_clauses_wl_heur S⇩0) - 2);
val ← mop_polarity_pol (get_trail_wl_heur S⇩0) L;
(_, _, CS, S) ← WHILE⇩T(λ(abort, i, CS, S). ¬abort ∧ i < l ∧ get_conflict_wl_is_None_heur S)
(λ(abort, i, CS, S).
do {
ASSERT (i < l);
ASSERT (length (get_clauses_wl_heur S) = length (get_clauses_wl_heur S⇩0));
ASSERT (learned_clss_count S ≤ learned_clss_count S⇩0);
(C,L', b) ← mop_watched_by_app_heur S L i;
ASSERT (C > 0 ∧ C < length (get_clauses_wl_heur S));
st ← mop_arena_status (get_clauses_wl_heur S) C;
if st = DELETED ∨ ¬b then
RETURN (abort, i+1, CS, S)
else do {
val ← mop_polarity_pol (get_trail_wl_heur S) L';
if val ≠ UNSET then do {
S ← isa_simplify_clause_with_unit_st2 C S;
val ← mop_polarity_pol (get_trail_wl_heur S) L;
RETURN (val ≠ UNSET, i+1, CS, S)
}
else do {
m ← is_marked CS (L');
n ← (if m then get_marked CS L' else RETURN (1, True));
if m then do {
let C' = (if ¬snd n ⟶ st = LEARNED then C else fst n);
CS ← (if ¬snd n ⟶ st = LEARNED then RETURN CS else update_marked CS (L') (C, st = IRRED));
S ← isa_clause_remove_duplicate_clause_wl C' S;
RETURN (abort, i+1, CS, S)
} else do {
m ← is_marked CS (-L') ;
if m then do {
S ← isa_binary_clause_subres_wl C L (-L') S;
RETURN (True, i+1, CS, S)
}
else do {
CS ← set_marked CS (L') (C, st = IRRED);
RETURN (abort, i+1, CS, S)
}
}
}
}
})
(val ≠ UNSET, 0, CS, S⇩0);
CS ← empty CS;
RETURN (CS, S)
}›
definition mark_duplicated_binary_clauses_as_garbage_pre_wl_heur :: ‹isasat ⇒ bool› where
‹mark_duplicated_binary_clauses_as_garbage_pre_wl_heur S ⟷
(∃S' r u. (S, S') ∈ twl_st_heur_restart_ana' r u ∧
mark_duplicated_binary_clauses_as_garbage_pre_wl S')›
definition isa_mark_duplicated_binary_clauses_as_garbage_wl :: ‹isasat ⇒ _ nres› where
‹isa_mark_duplicated_binary_clauses_as_garbage_wl S⇩0 = (do {
let ns = (get_vmtf_heur_array S⇩0);
ASSERT (mark_duplicated_binary_clauses_as_garbage_pre_wl_heur S⇩0);
skip ← RETURN (should_eliminate_pure_st S⇩0);
CS ← create (length (get_watched_wl_heur S⇩0));
(_, CS, S) ← WHILE⇩T⇗ λ(n,CS,S). ns = (get_vmtf_heur_array S)⇖(λ(n, CS,S). n ≠ None ∧ get_conflict_wl_is_None_heur S)
(λ(n, CS, S). do {
ASSERT (n ≠ None);
let A = the n;
ASSERT (A < length ns);
ASSERT (A ≤ unat32_max div 2);
S ← do {ASSERT (ns = (get_vmtf_heur_array S));
_ ← mop_is_marked_added_heur_st S A;
if ¬skip then RETURN (CS, S)
else do {
ASSERT (length (get_clauses_wl_heur S) ≤ length (get_clauses_wl_heur S⇩0) ∧ learned_clss_count S ≤ learned_clss_count S⇩0);
(CS, S) ← isa_deduplicate_binary_clauses_wl (Pos A) CS S;
ASSERT (length (get_clauses_wl_heur S) ≤ length (get_clauses_wl_heur S⇩0) ∧ learned_clss_count S ≤ learned_clss_count S⇩0);
(CS, S) ← isa_deduplicate_binary_clauses_wl (Neg A) CS S;
ASSERT (ns = (get_vmtf_heur_array S));
RETURN (CS, S)
}};
RETURN (get_next (ns ! A), S)
})
(Some (get_vmtf_heur_fst S⇩0), CS, S⇩0);
RETURN S
})›
definition isa_mark_duplicated_binary_clauses_as_garbage_wl2 :: ‹isasat ⇒ _ nres› where
‹isa_mark_duplicated_binary_clauses_as_garbage_wl2 S⇩0 = (do {
let ns = get_vmtf_heur_array S⇩0;
ASSERT (mark_duplicated_binary_clauses_as_garbage_pre_wl_heur S⇩0);
dedup ← RETURN (should_eliminate_pure_st S⇩0);
CS ← create (length (get_watched_wl_heur S⇩0));
(_, CS, S) ← WHILE⇩T⇗ λ(n,CS, S). get_vmtf_heur_array S⇩0 = (get_vmtf_heur_array S)⇖(λ(n, CS, S). n ≠ None ∧ get_conflict_wl_is_None_heur S)
(λ(n, CS, S). do {
ASSERT (n ≠ None);
let A = the n;
ASSERT (A < length (get_vmtf_heur_array S));
ASSERT (A ≤ unat32_max div 2);
(CS, S) ← do {
_ ← mop_is_marked_added_heur_st S A;
if ¬dedup then RETURN (CS, S)
else do {
ASSERT (length (get_clauses_wl_heur S) ≤ length (get_clauses_wl_heur S⇩0) ∧ learned_clss_count S ≤ learned_clss_count S⇩0);
(CS, S) ← isa_deduplicate_binary_clauses_wl (Pos A) CS S;
ASSERT (length (get_clauses_wl_heur S) ≤ length (get_clauses_wl_heur S⇩0) ∧ learned_clss_count S ≤ learned_clss_count S⇩0);
(CS, S) ← isa_deduplicate_binary_clauses_wl (Neg A) CS S;
ASSERT (ns = get_vmtf_heur_array S);
RETURN (CS, S)
}};
RETURN (get_next (get_vmtf_heur_array S ! A), CS, S)
})
(Some (get_vmtf_heur_fst S⇩0), CS, S⇩0);
RETURN S
})›
end