theory MinWeightBasis
imports "../../Sepreftime" "../../Refine_Foreach"
"List-Index.List_Index" Matroids.Matroid
begin
abbreviation "sorted_wrt_w w == sorted_wrt (λe1 e2. w e1 ≤ w e2)"
locale minWeightBasis = matroid carrier indep for carrier::"'a set" and indep +
fixes w :: "'a ⇒ 'b::{linorder, ordered_comm_monoid_add}"
begin
section ‹minWeightBasis algorithm›
subsection ‹Proof that it computes an minimum Basis›
definition minBasis where "minBasis B ≡ basis B ∧ (∀B'. basis B' ⟶ sum w B ≤ sum w B')"
subsubsection ‹preparation›
fun in_sort_edge where
"in_sort_edge x [] = [x]"
| "in_sort_edge x (y#ys) = (if w x ≤ w y then x#y#ys else y# in_sort_edge x ys)"
lemma [simp]: "set (in_sort_edge x L) = insert x (set L)"
apply(induct L) by auto
lemma in_sort_edge: "sorted_wrt (λe1 e2. w e1 ≤ w e2) L ⟹ sorted_wrt (λe1 e2. w e1 ≤ w e2) (in_sort_edge x L)"
apply(induct L ) by auto
lemma in_sort_edge_distinct: "x ∉ set L ⟹ distinct L ⟹ distinct (in_sort_edge x L)"
apply(induct L) by auto
lemma finite_sorted_edge_distinct:
assumes "finite S"
obtains L where "distinct L" "sorted_wrt (λe1 e2. w e1 ≤ w e2) L" "S = set L"
proof -
{
have "∃L. distinct L ∧ sorted_wrt (λe1 e2. w e1 ≤ w e2) L ∧ S = set L"
using assms
apply(induct S)
apply(clarsimp)
apply(clarsimp)
subgoal for x L apply(rule exI[where x="in_sort_edge x L"])
by (auto simp: in_sort_edge in_sort_edge_distinct)
done
}
with that show ?thesis by blast
qed
abbreviation "wsorted == sorted_wrt_w w"
lemma sum_list_map_cons: "sum_list (map w (y # ys)) = w y + sum_list (map w ys)" by auto
lemma exists_greater:
assumes len: "length F = length F'"
and sum: "sum_list (map w F) > sum_list (map w F')"
shows "∃i<length F. w (F ! i) > w (F' ! i)"
using len sum
proof (induct rule: list_induct2)
case (Cons x xs y ys)
show ?case
proof(cases "w y < w x")
case True
then show ?thesis by auto
next
case False
from False Cons(3) have "sum_list (map w ys) < sum_list (map w xs)"
apply(simp add: sum_list_map_cons)
by (meson add_mono leD le_less_linear)
from Cons(2)[OF this] show ?thesis by auto
qed
qed simp
lemma wsorted_Cons: "wsorted (x#xs) = (wsorted xs & (ALL y:set xs. w x <= w y))"
by (induct xs arbitrary: x) auto
lemma wsorted_nth_mono: assumes "wsorted L" "i≤j" "j<length L"
shows "w (L!i) ≤ w (L!j)"
using assms apply (induct L arbitrary: i j rule: list.induct) by (auto simp: nth_Cons' wsorted_Cons)
definition "limi T g == {e. e∈T ∧ w e < g}"
lemma limi_subset: "limi T g ⊆ T" unfolding limi_def by auto
lemma limi_mono: "A ⊆ B ⟹ limi A g ⊆ limi B g"
unfolding limi_def by auto
definition "no_smallest_element_skipped E F = (∀e∈carrier - E. ∀g>w e. indep (insert e (limi F g)) ⟶ (e ∈ limi F g))"
lemma no_smallest_element_skipped_empty[simp]: "no_smallest_element_skipped carrier {}"
by(auto simp: no_smallest_element_skipped_def)
lemma no_smallest_element_skippedD: "no_smallest_element_skipped E F ⟹ (⋀e g. e ∈carrier - E ⟹ w e < g ⟹ (indep (insert e (limi F g)) ⟹ e∈ limi F g))"
by(auto simp: no_smallest_element_skipped_def)
subsubsection ‹the heart of the argument›
lemma greedy_approach_leads_to_minBasis: assumes "indep F"
and "∀e∈carrier - F. ¬ indep (insert e F)"
and "no_smallest_element_skipped {} F"
shows "minBasis F"
proof (rule ccontr)
from assms have bF: "basis F" using indep_not_basis by blast
assume notmin: "¬ minBasis F"
from bF notmin[unfolded minBasis_def] obtain B where bB: "basis B" and sum: "sum w B < sum w F"
by force
from bF basis_finite finite_sorted_edge_distinct
obtain FL where dF[simp]: "distinct FL" and wF[simp]: "wsorted FL" and sF[simp]: "F = set FL"
by blast
from bB basis_finite finite_sorted_edge_distinct
obtain BL where dB[simp]: "distinct BL" and wB[simp]: "wsorted BL" and sB[simp]: "B = set BL"
by blast
from sum have suml: "sum_list (map w BL) < sum_list (map w FL)"
by(simp add: sum.distinct_set_conv_list[symmetric])
from bB bF have "card B = card F"
using basis_card by blast
then have l: "length FL = length BL"
by (simp add: distinct_card)
from exists_greater[OF l suml] obtain i where i: "i<length FL" and gr: "w (BL ! i) < w (FL ! i)"
by auto
let ?FL_restricted = "limi (set FL) (w (FL ! i))"
let ?X = "take i FL"
have X_size: "card (set ?X) = i" using i
by (simp add: distinct_card)
have X_indep: "indep (set ?X)" using bF
using indep_iff_subset_basis set_take_subset by force
let ?Y = "take (Suc i) BL"
have Y_size: "card (set ?Y) = Suc i" using i l
by (simp add: distinct_card)
have Y_indep: "indep (set ?Y)" using bB
using indep_iff_subset_basis set_take_subset by force
have "card (set ?X) < card (set ?Y)" using X_size Y_size by simp
with Y_indep X_indep
obtain x where x: "x∈set (take (Suc i) BL) - set ?X" and indepX: "indep (insert x (set ?X))"
using augment by auto
have "x∈carrier" using indepX indep_subset_carrier by blast
from x have xs: "x∈set (take (Suc i) BL)" and xnX: "x ∉ set ?X" by auto
from xs have "w x ≤ w (BL ! i)" using wB
by (metis List.length_take Lists_Thms.nth_take Suc_leI Suc_le_mono dB distinct_Ex1 distinct_take i local.l min_Suc_gt(2) wsorted_nth_mono)
then have k: "w x < w (FL ! i)" using gr by auto
have "?FL_restricted ⊆ set ?X"
unfolding limi_def apply auto
by (smt dF i index_nth_id leD leI linorder_linear mem_Collect_eq set_conv_nth set_take_if_index wF wsorted_nth_mono)
have z': "insert x ?FL_restricted ⊆ insert x (set ?X)"
using xnX `?FL_restricted ⊆ set (take i FL)` by auto
from indep_subset[OF indepX z'] have add_x_stay_indep: "indep (insert x ?FL_restricted)" .
from `no_smallest_element_skipped {} F` `x∈carrier` `w x < w (FL ! i)` add_x_stay_indep
have "x ∈ ?FL_restricted" by (auto dest: no_smallest_element_skippedD)
with `?FL_restricted ⊆ set ?X` have "x ∈ set ?X" by auto
with xnX show "False" by auto
qed
lemma assumes createsCycle: "¬ indep (insert e F)"
and I: "no_smallest_element_skipped (E∪{e}) F"
and sorted: "(∀x∈F.∀y∈(E∪{e}). w x ≤ w y)"
shows I_preservation1': "no_smallest_element_skipped E F"
unfolding no_smallest_element_skipped_def
proof (clarsimp)
fix x g
assume x: "x ∈ carrier" "x ∉ E" "w x < g"
assume f: "indep (insert x (limi F g))"
show "(x ∈ limi F g)"
proof (cases "x=e")
case True
from True have "limi F g = F"
unfolding limi_def using ‹w x < g› sorted by fastforce
with createsCycle f True have "False" by auto
then show ?thesis by simp
next
case False
show ?thesis
apply(rule I[THEN no_smallest_element_skippedD, OF _ ‹w x < g›])
using x f False
by (auto simp add: )
qed
qed
lemma I_preservation2:
assumes "e ∈ E" "∀e∈carrier - E - F. ¬ indep (insert e F)"
shows "(∀x∈carrier - (E - {e}) - insert e F. ¬ indep (insert x (insert e F)))"
using assms by (smt Diff_insert Diff_insert2 indep_subset insert_Diff insert_commute subset_insertI)
lemma I_preservation3':
assumes I: "no_smallest_element_skipped (E∪{e}) F"
shows "no_smallest_element_skipped E (insert e F)"
unfolding no_smallest_element_skipped_def
proof (clarsimp)
fix x g
assume xc: "x ∈ carrier"
assume x: "x ∉ E"
assume wx: "w x < g"
assume f: "indep (insert x (limi (insert e F) g))"
show "(x ∈ limi (insert e F) g)"
proof(cases "x=e")
case True
then show ?thesis unfolding limi_def
using wx by blast
next
case False
have ind: "indep (insert x (limi F g))" apply(rule indep_subset[OF f]) using limi_mono by blast
have "indep (insert x (limi F g)) ⟹ x ∈ limi F g"
apply(rule I[THEN no_smallest_element_skippedD]) using False xc wx x by auto
with ind show ?thesis using limi_mono by blast
qed
qed
definition I_minWeightBasis_fine where
"I_minWeightBasis_fine == λ(T,E). indep T
∧ T ⊆ carrier
∧ E ⊆ carrier ∧ T ∩ E = {}
∧ (∀x∈T.∀y∈E. w x ≤ w y)
∧ (∀e∈carrier-E-T. ~indep (insert e T))
∧ no_smallest_element_skipped E T"
lemma I_minWeightBasis_fineD:
assumes
"I_minWeightBasis_fine (T,E)"
shows"indep T" "⋀e. e∈carrier-E-T ⟹ ~indep (insert e T)"
"E ⊆ carrier" "⋀x y. x∈T ⟹ y∈E ⟹ w x ≤ w y" "T ∩ E = {}" "T ⊆ carrier"
"no_smallest_element_skipped E T"
using assms by(auto simp: no_smallest_element_skipped_def I_minWeightBasis_fine_def)
lemma I_minWeightBasis_fineI:
assumes "indep T" "⋀e. e∈carrier-E-T ⟹ ~indep (insert e T)"
"E ⊆ carrier" "⋀x y. x∈T ⟹ y∈E ⟹ w x ≤ w y" "T ∩ E = {}" "T ⊆ carrier"
"no_smallest_element_skipped E T"
shows "I_minWeightBasis_fine (T,E)"
using assms by(auto simp: no_smallest_element_skipped_def I_minWeightBasis_fine_def)
lemma I_minWeightBasis_fineG: "I_minWeightBasis_fine (T,E) ⟹ no_smallest_element_skipped E T" by(auto simp: no_smallest_element_skipped_def I_minWeightBasis_fine_def)
lemma I_minWeightBasis_sorted: "I_minWeightBasis_fine (T,E) ⟹ (∀x∈T.∀y∈E. w x ≤ w y)" by(auto simp: no_smallest_element_skipped_def I_minWeightBasis_fine_def)
end
locale minWeightBasis_time = minWeightBasis +
fixes sorted_carrier_time :: nat
and empty_basis_time indep_test_time insert_time :: nat
begin
subsection ‹Refinement to an algorithm using sorted lists›
definition (in -) "obtain_sorted_carrier_aux sct c w ≡ SPECT (emb (λL. sorted_wrt_w w L ∧ distinct L ∧ set L = c) sct)"
abbreviation "obtain_sorted_carrier ≡ obtain_sorted_carrier_aux sorted_carrier_time carrier w"
section ‹minWeightBasis algorithm with nfoldi›
abbreviation "empty_basis ≡ {}"
definition (in -) minWeightBasis3_aux where
"minWeightBasis3_aux osc_t c we ebt itt it ind eb ≡ do {
l ← obtain_sorted_carrier_aux osc_t c we ;
ASSERT (set l = c);
s ← SPECT [eb↦ebt];
T ← nfoldli l (λ_. True)
(λe T. do {
ASSERT (e∉T ∧ ind T ∧ e∈c ∧ T⊆c);
b ← SPECT [ind (insert e T) ↦ itt];
if b then
SPECT [(insert e T)↦it]
else
RETURNT T
}) s;
RETURNT T
}"
abbreviation "minWeightBasis3 ≡ minWeightBasis3_aux sorted_carrier_time carrier w empty_basis_time
indep_test_time insert_time indep empty_basis"
lemma I_minWeightBasis_fine_empty: "I_minWeightBasis_fine ({}, carrier)"
by (auto simp: I_minWeightBasis_fine_def)
lemma I_minWeightBasis_fine_final: "I_minWeightBasis_fine (T, {}) ⟹ minBasis T"
by(auto simp: greedy_approach_leads_to_minBasis I_minWeightBasis_fine_def)
lemma preservation_else: "set x = carrier ⟹
x = l1 @ xa # l2 ⟹ I_minWeightBasis_fine (σ, set (xa # l2))
⟹ indep σ ⟹ ¬ indep (insert xa σ) ⟹ I_minWeightBasis_fine (σ, set l2)"
apply(rule I_minWeightBasis_fineI)
subgoal by simp
subgoal by (auto simp: DiffD2 I_minWeightBasis_fine_def)
subgoal by auto
subgoal by(auto simp: I_minWeightBasis_fine_def)
subgoal by(auto simp: I_minWeightBasis_fine_def)
subgoal by(auto simp: I_minWeightBasis_fine_def)
subgoal apply (rule I_preservation1')
by(auto intro!: simp: I_minWeightBasis_fine_def)
done
lemma I_preservation2':
assumes "e ∈ E" "∀e∈carrier - E - F. ¬ indep (insert e F)"
and "x∈carrier - (E - {e}) - insert e F"
shows "¬ indep (insert x (insert e F))"
using assms I_preservation2 by auto
lemma preservation_if: "wsorted x ⟹ distinct x ⟹ set x = carrier ⟹
x = l1 @ xa # l2 ⟹ I_minWeightBasis_fine (σ, set (xa # l2)) ⟹ True ⟹ xa ∉ σ
⟹ xa ∈ carrier ⟹ indep (insert xa σ) ⟹ I_minWeightBasis_fine (insert xa σ, set l2)"
apply(rule I_minWeightBasis_fineI)
subgoal by simp
subgoal unfolding I_minWeightBasis_fine_def apply(rule I_preservation2'[where E="set (xa # l2)"])
by simp_all
subgoal by auto
subgoal by (metis insert_iff list.set(2) I_minWeightBasis_sorted sorted_wrt_append wsorted_Cons)
subgoal by(auto simp: I_minWeightBasis_fine_def)
subgoal by(auto simp: I_minWeightBasis_fine_def)
subgoal apply (rule I_preservation3')
by(auto intro!: simp: I_minWeightBasis_fine_def)
done
definition "minBasis_time = sorted_carrier_time + empty_basis_time
+ card carrier * (indep_test_time + insert_time)"
lemma le_Id: "M ≤ M' ⟹ M ≤ ⇓ Id M'"
by auto
theorem minWeightBasis3_refine: "minWeightBasis3 ≤ ⇓ Id (SPECT (emb minBasis minBasis_time))"
unfolding minWeightBasis3_aux_def obtain_sorted_carrier_aux_def
unfolding nfoldliIE_def[where E="indep_test_time + insert_time" and I="λl1 l2 s. I_minWeightBasis_fine (s,set l2)", symmetric]
apply(rule le_Id)
apply(rule T_specifies_I)
unfolding nfoldliIE'_def[symmetric]
apply(vcg' ‹-› rules: nfoldliIE'_rule )
unfolding Some_le_emb'_conv
apply (safe)
oops
lemmas f = nfoldliIE_rule[where t="card carrier * (indep_test_time + insert_time)" and
P="λT. I_minWeightBasis_fine (T, {})", THEN T_specifies_rev, THEN T_conseq4]
theorem minWeightBasis3_refine: "minWeightBasis3 ≤ ⇓ Id (SPECT (emb minBasis minBasis_time))"
unfolding minWeightBasis3_aux_def obtain_sorted_carrier_aux_def
unfolding nfoldliIE_def[where E="indep_test_time + insert_time" and I="λl1 l2 s. I_minWeightBasis_fine (s,set l2)", symmetric]
apply(rule le_Id)
apply(rule T_specifies_I)
apply(vcg' ‹-› rules: f )
subgoal by (auto simp: I_minWeightBasis_fine_empty)
subgoal
apply(rule T_specifies_I)
apply(vcg' ‹-› rules: f )
apply(simp_all add: Some_le_emb'_conv )
subgoal apply(rule preservation_if) by (auto dest!: I_minWeightBasis_fineD(5))
subgoal apply(rule preservation_else) by (auto dest!: I_minWeightBasis_fineD(1))
subgoal by (auto simp: I_minWeightBasis_fine_def)
done
subgoal by simp
subgoal by simp
subgoal by (auto simp: distinct_card Some_le_emb'_conv )
subgoal by (auto simp: I_minWeightBasis_fine_final minBasis_time_def vcg_simp_rules)
subgoal by auto
done
end
end