module -- This is a companion file for `grind_indexmap.lean`, -- showing what an outline of this file might look like before any proofs are written. import Std.Data.HashMap open Std structure IndexMap (α : Type u) (β : Type v) [BEq α] [Hashable α] where indices : HashMap α Nat keys : Array α values : Array β size_keys' : keys.size = values.size := by grind WF : ∀ (i : Nat) (a : α), keys[i]? = some a ↔ indices[a]? = some i := by grind namespace IndexMap variable {α : Type u} {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] [LawfulHashable α] variable {m : IndexMap α β} {a : α} {b : β} {i : Nat} @[inline] def size (m : IndexMap α β) : Nat := m.values.size def emptyWithCapacity (capacity := 8) : IndexMap α β where indices := HashMap.emptyWithCapacity capacity keys := Array.emptyWithCapacity capacity values := Array.emptyWithCapacity capacity instance : EmptyCollection (IndexMap α β) where emptyCollection := emptyWithCapacity instance : Inhabited (IndexMap α β) where default := ∅ @[inline] def contains (m : IndexMap α β) (a : α) : Bool := m.indices.contains a instance : Membership α (IndexMap α β) where mem m a := a ∈ m.indices instance {m : IndexMap α β} {a : α} : Decidable (a ∈ m) := inferInstanceAs (Decidable (a ∈ m.indices)) @[inline] def findIdx? (m : IndexMap α β) (a : α) : Option Nat := m.indices[a]? @[inline] def findIdx (m : IndexMap α β) (a : α) (h : a ∈ m := by get_elem_tactic) : Nat := m.indices[a] @[inline] def getIdx? (m : IndexMap α β) (i : Nat) : Option β := m.values[i]? @[inline] def getIdx (m : IndexMap α β) (i : Nat) (h : i < m.size := by get_elem_tactic) : β := m.values[i] instance : GetElem? (IndexMap α β) α β (fun m a => a ∈ m) where getElem m a h := m.values[m.indices[a]'h]'(by sorry) getElem? m a := m.indices[a]?.bind (fun i => (m.values[i]?)) getElem! m a := m.indices[a]?.bind (fun i => (m.values[i]?)) |>.getD default instance : LawfulGetElem (IndexMap α β) α β (fun m a => a ∈ m) where getElem?_def := sorry getElem!_def := sorry @[inline] def insert (m : IndexMap α β) (a : α) (b : β) : IndexMap α β := match h : m.indices[a]? with | some i => { indices := m.indices keys := m.keys.set i a sorry values := m.values.set i b sorry size_keys' := sorry WF := sorry } | none => { indices := m.indices.insert a m.size keys := m.keys.push a values := m.values.push b size_keys' := sorry WF := sorry } instance : Singleton (α × β) (IndexMap α β) := ⟨fun ⟨a, b⟩ => (∅ : IndexMap α β).insert a b⟩ instance : Insert (α × β) (IndexMap α β) := ⟨fun ⟨a, b⟩ s => s.insert a b⟩ instance : LawfulSingleton (α × β) (IndexMap α β) := ⟨fun _ => rfl⟩ /-- Erase the key-value pair with the given key, moving the last pair into its place in the order. If the key is not present, the map is unchanged. -/ @[inline] def eraseSwap (m : IndexMap α β) (a : α) : IndexMap α β := match h : m.indices[a]? with | some i => if w : i = m.size - 1 then { indices := m.indices.erase a keys := m.keys.pop values := m.values.pop size_keys' := sorry WF := sorry } else let lastKey := m.keys.back sorry let lastValue := m.values.back sorry { indices := (m.indices.erase a).insert lastKey i keys := m.keys.pop.set i lastKey sorry values := m.values.pop.set i lastValue sorry size_keys' := sorry WF := sorry } | none => m /-! ### Verification theorems -/ theorem getIdx_findIdx (m : IndexMap α β) (a : α) (h : a ∈ m) : m.getIdx (m.findIdx a h) sorry = m[a] := sorry theorem mem_insert (m : IndexMap α β) (a a' : α) (b : β) : a' ∈ m.insert a b ↔ a' = a ∨ a' ∈ m := by sorry theorem getElem_insert (m : IndexMap α β) (a a' : α) (b : β) (h : a' ∈ m.insert a b) : (m.insert a b)[a']'h = if h' : a' == a then b else m[a']'sorry := by sorry theorem findIdx_insert_self (m : IndexMap α β) (a : α) (b : β) : (m.insert a b).findIdx a sorry = if h : a ∈ m then m.findIdx a h else m.size := by sorry end IndexMap