theory Impl_Uv_Set imports "../../Iterator/Iterator" "../Intf/Intf_Set" Native_Word.Uint begin subsection ‹Bit-Vectors as Lists of Words› subsubsection ‹Lookup› primrec lookup :: "nat ⇒ ('a::len) word list ⇒ bool" where "lookup _ [] ⟷ False" | "lookup n (w#ws) ⟷ (if n<LENGTH('a) then test_bit w n else lookup (n-LENGTH('a)) ws)" lemma lookup_append[simp]: "lookup n (w1@w2 :: 'a::len word list) ⟷ ( if n < LENGTH('a) * length w1 then lookup n w1 else lookup (n - LENGTH('a) * length w1) w2)" by (induction w1 arbitrary: n) auto lemma lookup_zeroes[simp]: "lookup i (replicate n (0::'a::len word)) = False" by (induction n arbitrary: i) auto lemma lookup_out_of_bound: fixes uv :: "'a::len word list" assumes "¬ i < LENGTH('a::len) * length uv" shows "¬ lookup i uv" using assms by (induction uv arbitrary: i) auto subsubsection ‹Empty› definition empty :: "'a::len word list" where "empty = []" subsubsection ‹Set and Reset Bit› function single_bit :: "nat ⇒ ('a::len) word list" where "single_bit n = ( if (n<LENGTH('a)) then [set_bit 0 n True] else 0#single_bit (n-LENGTH('a)))" by pat_completeness auto termination apply (relation "measure id") apply simp apply (simp add: not_less less_diff_conv2) done declare single_bit.simps[simp del] lemma lookup_single_bit[simp]: "lookup i ((single_bit n)::'a::len word list) ⟷ i = n" apply (induction n arbitrary: i rule: single_bit.induct) apply (subst single_bit.simps) apply (auto simp: bin_nth_sc_gen) done find_consts name: set_bit primrec set_bit :: "nat ⇒ 'a::len word list ⇒ 'a::len word list" where "set_bit i [] = single_bit i" | "set_bit i (w#ws) = ( if i<LENGTH('a) then Bits.set_bit w i True # ws else w # set_bit (i - LENGTH('a)) ws)" lemma set_bit_lookup[simp]: "lookup i (set_bit j ws) ⟷ (lookup i ws ∨ i=j)" apply (induction ws arbitrary: i j) apply (auto simp: test_bit_set_gen word_size) done primrec reset_bit :: "nat ⇒ 'a::len word list ⇒ 'a::len word list" where "reset_bit i [] = []" | "reset_bit i (w#ws) = ( if i<LENGTH('a) then Bits.set_bit w i False # ws else w # reset_bit (i - LENGTH('a)) ws)" lemma reset_bit_lookup[simp]: "lookup i (reset_bit j ws) ⟷ (lookup i ws ∧ i≠j)" apply (induction ws arbitrary: i j) apply (auto simp: test_bit_set_gen word_size) done subsubsection ‹Binary Operations› definition is_bin_op_impl :: "(bool⇒bool⇒bool) ⇒ ('a::len word ⇒ 'a::len word ⇒ 'a::len word) ⇒ bool" where "is_bin_op_impl f g ≡ (∀w v. ∀i<LENGTH('a). test_bit (g w v) i ⟷ f (test_bit w i) (test_bit v i))" definition "is_strict_bin_op_impl f g ≡ is_bin_op_impl f g ∧ f False False = False" fun binary :: "('a::len word ⇒ 'a::len word ⇒ 'a::len word) ⇒ 'a::len word list ⇒ 'a::len word list ⇒ 'a::len word list" where "binary f [] [] = []" | "binary f [] (w#ws) = f 0 w # binary f [] ws" | "binary f (v#vs) [] = f v 0 # binary f vs []" | "binary f (v#vs) (w#ws) = f v w # binary f vs ws" lemma binary_lookup: assumes "is_strict_bin_op_impl f g" shows "lookup i (binary g ws vs) ⟷ f (lookup i ws) (lookup i vs)" using assms apply (induction g ws vs arbitrary: i rule: binary.induct) apply (auto simp: is_strict_bin_op_impl_def is_bin_op_impl_def) done subsection ‹Abstraction to Sets of Naturals› definition "α uv ≡ {n. lookup n uv}" lemma memb_correct: "lookup i ws ⟷ i∈α ws" by (auto simp: α_def) lemma empty_correct: "α empty = {}" by (simp add: α_def empty_def) lemma single_bit_correct: "α (single_bit n) = {n}" by (simp add: α_def) lemma insert_correct: "α (set_bit i ws) = Set.insert i (α ws)" by (auto simp add: α_def) lemma delete_correct: "α (reset_bit i ws) = (α ws) - {i}" by (auto simp add: α_def) lemma binary_correct: assumes "is_strict_bin_op_impl f g" shows "α (binary g ws vs) = { i . f (i∈α ws) (i∈α vs) }" unfolding α_def by (auto simp add: binary_lookup[OF assms]) fun union :: "'a::len word list ⇒ 'a::len word list ⇒ 'a::len word list" where "union [] ws = ws" | "union vs [] = vs" | "union (v#vs) (w#ws) = (v OR w) # union vs ws" lemma union_lookup[simp]: fixes vs :: "'a::len word list" shows "lookup i (union vs ws) ⟷ lookup i vs ∨ lookup i ws" apply (induction vs ws arbitrary: i rule: union.induct) apply (auto simp: word_ao_nth) done lemma union_correct: "α (union ws vs) = α ws ∪ α vs" by (auto simp add: α_def) fun inter :: "'a::len word list ⇒ 'a::len word list ⇒ 'a::len word list" where "inter [] ws = []" | "inter vs [] = []" | "inter (v#vs) (w#ws) = (v AND w) # inter vs ws" lemma inter_lookup[simp]: fixes vs :: "'a::len word list" shows "lookup i (inter vs ws) ⟷ lookup i vs ∧ lookup i ws" apply (induction vs ws arbitrary: i rule: inter.induct) apply (auto simp: word_ao_nth) done lemma inter_correct: "α (inter ws vs) = α ws ∩ α vs" by (auto simp add: α_def) fun diff :: "'a::len word list ⇒ 'a::len word list ⇒ 'a::len word list" where "diff [] ws = []" | "diff vs [] = vs" | "diff (v#vs) (w#ws) = (v AND NOT w) # diff vs ws" lemma diff_lookup[simp]: fixes vs :: "'a::len word list" shows "lookup i (diff vs ws) ⟷ lookup i vs - lookup i ws" apply (induction vs ws arbitrary: i rule: diff.induct) apply (auto simp: word_ops_nth_size word_size) done lemma diff_correct: "α (diff ws vs) = α ws - α vs" by (auto simp add: α_def) fun zeroes :: "'a::len word list ⇒ bool" where "zeroes [] ⟷ True" | "zeroes (w#ws) ⟷ w=0 ∧ zeroes ws" lemma zeroes_lookup: "zeroes ws ⟷ (∀i. ¬lookup i ws)" apply (induction ws) apply (auto simp: word_eq_iff) by (metis diff_add_inverse2 not_add_less2) lemma isEmpty_correct: "zeroes ws ⟷ α ws = {}" by (auto simp: zeroes_lookup α_def) fun equal :: "'a::len word list ⇒ 'a::len word list ⇒ bool" where "equal [] [] ⟷ True" | "equal [] ws ⟷ zeroes ws" | "equal vs [] ⟷ zeroes vs" | "equal (v#vs) (w#ws) ⟷ v=w ∧ equal vs ws" lemma equal_lookup: fixes vs ws :: "'a::len word list" shows "equal vs ws ⟷ (∀i. lookup i vs = lookup i ws)" proof (induction vs ws rule: equal.induct) fix v w and vs ws :: "'a::len word list" assume IH: "equal vs ws = (∀i. lookup i vs = lookup i ws)" show "equal (v # vs) (w # ws) = (∀i. lookup i (v # vs) = lookup i (w # ws))" proof (rule iffI, rule allI) fix i assume "equal (v#vs) (w#ws)" thus "lookup i (v # vs) = lookup i (w # ws)" by (auto simp: IH) next assume "∀i. lookup i (v # vs) = lookup i (w # ws)" thus "equal (v # vs) (w # ws)" apply (auto simp: word_eq_iff IH) apply metis apply metis apply (drule_tac x="i + LENGTH('a)" in spec) apply auto [] apply (drule_tac x="i + LENGTH('a)" in spec) apply auto [] done qed qed (auto simp: zeroes_lookup) lemma equal_correct: "equal vs ws ⟷ α vs = α ws" by (auto simp: α_def equal_lookup) fun subseteq :: "'a::len word list ⇒ 'a::len word list ⇒ bool" where "subseteq [] ws ⟷ True" | "subseteq vs [] ⟷ zeroes vs" | "subseteq (v#vs) (w#ws) ⟷ (v AND NOT w = 0) ∧ subseteq vs ws" lemma subseteq_lookup: fixes vs ws :: "'a::len word list" shows "subseteq vs ws ⟷ (∀i. lookup i vs ⟶ lookup i ws)" apply (induction vs ws rule: subseteq.induct) apply simp apply (auto simp: zeroes_lookup) [] apply (auto simp: word_ops_nth_size word_size word_eq_iff) by (metis diff_add_inverse2 not_add_less2) lemma subseteq_correct: "subseteq vs ws ⟷ α vs ⊆ α ws" by (auto simp: α_def subseteq_lookup) fun subset :: "'a::len word list ⇒ 'a::len word list ⇒ bool" where "subset [] ws ⟷ ¬zeroes ws" | "subset vs [] ⟷ False" | "subset (v#vs) (w#ws) ⟷ (if v=w then subset vs ws else subseteq (v#vs) (w#ws))" lemma subset_lookup: fixes vs ws :: "'a::len word list" shows "subset vs ws ⟷ ((∀i. lookup i vs ⟶ lookup i ws) ∧ (∃i. ¬lookup i vs ∧ lookup i ws))" apply (induction vs ws rule: subset.induct) apply (simp add: zeroes_lookup) apply (simp add: zeroes_lookup) [] apply (simp del: subseteq_correct add: subseteq_lookup) apply safe apply simp_all apply (auto simp: word_ops_nth_size word_size word_eq_iff) done lemma subset_correct: "subset vs ws ⟷ α vs ⊂ α ws" by (auto simp: α_def subset_lookup) fun disjoint :: "'a::len word list ⇒ 'a::len word list ⇒ bool" where "disjoint [] ws ⟷ True" | "disjoint vs [] ⟷ True" | "disjoint (v#vs) (w#ws) ⟷ (v AND w = 0) ∧ disjoint vs ws" lemma disjoint_lookup: fixes vs ws :: "'a::len word list" shows "disjoint vs ws ⟷ (∀i. ¬(lookup i vs ∧ lookup i ws))" apply (induction vs ws rule: disjoint.induct) apply simp apply simp apply (auto simp: word_ops_nth_size word_size word_eq_iff) by (metis diff_add_inverse2 not_add_less2) lemma disjoint_correct: "disjoint vs ws ⟷ α vs ∩ α ws = {}" by (auto simp: α_def disjoint_lookup) subsection ‹Lifting to Uint› type_synonym uint_vector = "uint list" lift_definition uv_α :: "uint_vector ⇒ nat set" is α . lift_definition uv_lookup :: "nat ⇒ uint_vector ⇒ bool" is lookup . lift_definition uv_empty :: "uint_vector" is empty . lift_definition uv_single_bit :: "nat ⇒ uint_vector" is single_bit . lift_definition uv_set_bit :: "nat ⇒ uint_vector ⇒ uint_vector" is set_bit . lift_definition uv_reset_bit :: "nat ⇒ uint_vector ⇒ uint_vector" is reset_bit . lift_definition uv_union :: "uint_vector ⇒ uint_vector ⇒ uint_vector" is union . lift_definition uv_inter :: "uint_vector ⇒ uint_vector ⇒ uint_vector" is inter . lift_definition uv_diff :: "uint_vector ⇒ uint_vector ⇒ uint_vector" is diff . lift_definition uv_zeroes :: "uint_vector ⇒ bool" is zeroes . lift_definition uv_equal :: "uint_vector ⇒ uint_vector ⇒ bool" is equal . lift_definition uv_subseteq :: "uint_vector ⇒ uint_vector ⇒ bool" is subseteq . lift_definition uv_subset :: "uint_vector ⇒ uint_vector ⇒ bool" is subset . lift_definition uv_disjoint :: "uint_vector ⇒ uint_vector ⇒ bool" is disjoint . lemmas uv_memb_correct = memb_correct[where 'a=dflt_size, Transfer.transferred] lemmas uv_empty_correct = empty_correct[where 'a=dflt_size, Transfer.transferred] lemmas uv_single_bit_correct = single_bit_correct[where 'a=dflt_size, Transfer.transferred] lemmas uv_insert_correct = insert_correct[where 'a=dflt_size, Transfer.transferred] lemmas uv_delete_correct = delete_correct[where 'a=dflt_size, Transfer.transferred] lemmas uv_union_correct = union_correct[where 'a=dflt_size, Transfer.transferred] lemmas uv_inter_correct = inter_correct[where 'a=dflt_size, Transfer.transferred] lemmas uv_diff_correct = diff_correct[where 'a=dflt_size, Transfer.transferred] lemmas uv_isEmpty_correct = isEmpty_correct[where 'a=dflt_size, Transfer.transferred] lemmas uv_equal_correct = equal_correct[where 'a=dflt_size, Transfer.transferred] lemmas uv_subseteq_correct = subseteq_correct[where 'a=dflt_size, Transfer.transferred] lemmas uv_subset_correct = subset_correct[where 'a=dflt_size, Transfer.transferred] lemmas uv_disjoint_correct = disjoint_correct[where 'a=dflt_size, Transfer.transferred] lemmas [where 'a=dflt_size, Transfer.transferred, code] = lookup.simps empty_def single_bit.simps set_bit.simps reset_bit.simps union.simps inter.simps diff.simps zeroes.simps equal.simps subseteq.simps subset.simps disjoint.simps hide_const (open) α lookup empty single_bit set_bit reset_bit union inter diff zeroes equal subseteq subset disjoint subsection ‹Autoref Setup› definition uv_set_rel_def_internal: "uv_set_rel Rk ≡ if Rk=nat_rel then br uv_α (λ_. True) else {}" lemma uv_set_rel_def: "⟨nat_rel⟩uv_set_rel ≡ br uv_α (λ_. True)" unfolding uv_set_rel_def_internal relAPP_def by simp lemmas [autoref_rel_intf] = REL_INTFI[of "uv_set_rel" i_set] lemma uv_set_rel_sv[relator_props]: "single_valued (⟨nat_rel⟩uv_set_rel)" unfolding uv_set_rel_def by auto lemma uv_autoref[autoref_rules,param]: "(uv_lookup,(∈)) ∈ nat_rel → ⟨nat_rel⟩uv_set_rel → bool_rel" "(uv_empty,{}) ∈ ⟨nat_rel⟩uv_set_rel" "(uv_set_bit,insert) ∈ nat_rel → ⟨nat_rel⟩uv_set_rel → ⟨nat_rel⟩uv_set_rel" "(uv_reset_bit,op_set_delete) ∈ nat_rel → ⟨nat_rel⟩uv_set_rel → ⟨nat_rel⟩uv_set_rel" "(uv_union,(∪)) ∈ ⟨nat_rel⟩uv_set_rel → ⟨nat_rel⟩uv_set_rel → ⟨nat_rel⟩uv_set_rel" "(uv_inter,(∩)) ∈ ⟨nat_rel⟩uv_set_rel → ⟨nat_rel⟩uv_set_rel → ⟨nat_rel⟩uv_set_rel" "(uv_diff,(-)) ∈ ⟨nat_rel⟩uv_set_rel → ⟨nat_rel⟩uv_set_rel → ⟨nat_rel⟩uv_set_rel" "(uv_zeroes,op_set_isEmpty) ∈ ⟨nat_rel⟩uv_set_rel → bool_rel" "(uv_equal,(=)) ∈ ⟨nat_rel⟩uv_set_rel → ⟨nat_rel⟩uv_set_rel → bool_rel" "(uv_subseteq,(⊆)) ∈ ⟨nat_rel⟩uv_set_rel → ⟨nat_rel⟩uv_set_rel → bool_rel" "(uv_subset,(⊂)) ∈ ⟨nat_rel⟩uv_set_rel → ⟨nat_rel⟩uv_set_rel → bool_rel" "(uv_disjoint,op_set_disjoint) ∈ ⟨nat_rel⟩uv_set_rel → ⟨nat_rel⟩uv_set_rel → bool_rel" by (auto simp: uv_set_rel_def br_def simp: uv_memb_correct uv_empty_correct uv_insert_correct uv_delete_correct simp: uv_union_correct uv_inter_correct uv_diff_correct uv_isEmpty_correct simp: uv_equal_correct uv_subseteq_correct uv_subset_correct uv_disjoint_correct) export_code uv_lookup uv_empty uv_single_bit uv_set_bit uv_reset_bit uv_union uv_inter uv_diff uv_zeroes uv_equal uv_subseteq uv_subset uv_disjoint checking SML Scala Haskell? OCaml? end