Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 10 additions & 122 deletions Iris/Iris/Std/HeapInstances.lean
Original file line number Diff line number Diff line change
Expand Up @@ -84,32 +84,6 @@ end ClassicalAllocHeap

end Iris.Std

section Lemmas

/-- Merge an optional value with an optional key-value pair, using the pair's key in the
merge function. This is an internal helper for TreeMap heap proofs. -/
private def Option.pairMerge (f : K → V → V → V) (o1 : Option V)
(o2 : Option (K × V)) : Option V :=
o2.elim o1 fun ⟨k, v2⟩ => some (o1.elim v2 (f k · v2))

@[simp]
private theorem Option.pairMerge_none_right : pairMerge f o1 none = o1 := by
cases o1 <;> rfl

@[simp]
private theorem Option.pairMerge_some_right :
pairMerge f o1 (some (k, v)) = merge (f k) o1 (some v) := by
cases o1 <;> rfl

/-- Insert a value if none, or merge with existing value. Used in alter operations for
maps. This is `Option.merge f o (some v)` - inserting `v` when empty, or merging with
existing. -/
@[simp]
def Option.insertOrMerge (f : V → V → V) (v : V) (o : Option V) : Option V :=
merge f o (some v)

end Lemmas

namespace Std.TreeMap

/-! ## TreeMap Heap Instance -/
Expand All @@ -120,106 +94,20 @@ open Option Std.DTreeMap.Internal.Impl List TransCmp OrientedCmp LawfulEqCmp Ord
open Iris.Std

variable {K V : Type _} [Ord K] [TransOrd K] [LawfulEqOrd K]

private theorem get?_foldl_alter_impl_sigma {l : List ((_ : K) × V)}
(hinit : init.WF) (hl : l.Pairwise (fun x y => ¬ (compare x.1 y.1).isEq)) :
Const.get? (l.foldl (fun acc ⟨k, v⟩ => Const.alter! k (insertOrMerge (f k) v) acc) init) k =
pairMerge f (Const.get? init k)
((l.find? (fun x => (compare x.1 k).isEq)).map (fun kv => (kv.1, kv.2))) := by
induction l generalizing init with
| nil =>
simp [List.foldl_nil]
| cons hd tl IH =>
rw [List.foldl_cons, IH (WF.constAlter! hinit) (hl.tail), Const.get?_alter! hinit]
by_cases h : compare hd.1 k = .eq <;> simp [h]
rw [← Const.get?_congr hinit h]
have hhead_none : tl.find? (fun x => (compare x.1 k).isEq) = none := by
refine List.find?_eq_none.mpr fun _ hkv He => List.rel_of_pairwise_cons hl hkv ?_
refine isEq_iff_eq_eq.mpr <| compare_eq_iff_eq.mpr ?_
rw [eq_of_compare h, compare_eq_iff_eq.mp <| isEq_iff_eq_eq.mp He]
rw [hhead_none, map_none, pairMerge_none_right]

private theorem getElem?_foldl_alter {l : List (K × V)} {init : TreeMap K V compare}
(hl : l.Pairwise (fun a b => compare a.1 b.1 ≠ .eq)) :
(l.foldl (fun acc kv => acc.alter kv.1 (insertOrMerge (f kv.1) kv.2)) init)[k]? =
pairMerge f init[k]? (l.find? (fun kv => (compare kv.1 k).isEq)) := by
induction l generalizing init with
| nil =>
simp
| cons hd tl ih =>
rw [List.foldl_cons, ih (hl.tail)]
by_cases heq : compare hd.1 k = .eq
· have htl : tl.find? (fun kv => (compare kv.1 k).isEq) = none := by
refine List.find?_eq_none.mpr fun kv hkv h => ?_
refine List.rel_of_pairwise_cons hl hkv (eq_trans heq ?_)
rw [compare_eq_iff_eq.mp <| isEq_iff_eq_eq.mp h]
exact compare_self
simp [getElem?_congr (eq_symm heq), htl, heq]
cases _ : init[hd.1]? <;> rfl
· simp [getElem?_alter, heq]

private theorem getElem?_mergeWith_eq_foldl {t₁ t₂ : TreeMap K V compare}
{f : K → V → V → V} {k : K} :
(t₁.mergeWith f t₂)[k]? =
(t₂.toList.foldl (fun acc kv => acc.alter kv.1 (insertOrMerge (f kv.1) kv.2)) t₁)[k]? := by
rw [getElem?_foldl_alter (distinct_keys_toList (t := t₂))]
rw [show _[_]? = _ from
congrArg (Const.get? · k) (Const.mergeWith_eq_mergeWith! ..)]
have h_foldl :
Const.mergeWith! f t₁.inner.inner t₂.inner.inner =
.foldl (fun t a b₂ => Const.alter! a (insertOrMerge (f a) b₂) t)
t₁.inner.inner t₂.inner.inner := by
unfold Const.mergeWith!
congr
funext _ _ _
congr
funext o
cases o <;> rfl
rw [h_foldl]
rw [foldl_eq_foldl]
rw [show t₂.toList = _ from Const.toList_eq_toListModel_map]
have hfind_map : ∀ l : List ((_ : K) × V),
(l.map (fun e => (e.1, e.2))).find? (fun kv => (compare kv.1 k).isEq) =
(l.find? (fun kv => (compare kv.1 k).isEq)).map (fun e => (e.1, e.2)) :=
fun l => by induction l with grind [isEq]
rw [hfind_map]
refine get?_foldl_alter_impl_sigma t₁.inner.wf ?_
refine (List.pairwise_map.mp <|
SameKeys.ordered_iff_pairwise_keys.mp t₂.inner.wf.ordered).imp ?_
rintro hlt heq H
simp [H]
attribute [local instance low] beqOfOrd

@[simp]
theorem getElem?_mergeWith' {t₁ t₂ : TreeMap K V compare} {f : K → V → V → V} {k : K} :
(t₁.mergeWith f t₂)[k]? = merge (f k) t₁[k]? t₂[k]? := by
rw [getElem?_mergeWith_eq_foldl (t₁ := t₁) (t₂ := t₂) (f := f) (k := k),
getElem?_foldl_alter (distinct_keys_toList (t := t₂))]
cases h : t₂[k]? with
| none =>
rw [List.find?_eq_none.mpr, pairMerge_none_right, merge_none_right]
refine fun ⟨k', v'⟩ hkv' heq => ?_
have _ :=
(getElem?_eq_some_iff_exists_compare_eq_eq_and_mem_toList (k := k) (v := v')).mpr
⟨k', ?G, hkv'⟩
case G =>
replace h := compare_eq_iff_eq.mp <| isEq_iff_eq_eq.mp heq
simp only [isEq_iff_eq_eq, compare_eq_iff_eq] at heq
exact heq ▸ compare_self
grind
| some v =>
obtain ⟨k', hcmp, hmem⟩ :=
getElem?_eq_some_iff_exists_compare_eq_eq_and_mem_toList.mp h
have hpred : (compare k' k).isEq = true := by simp [eq_symm hcmp]
obtain ⟨kv, hfind⟩ := isSome_iff_exists.mp <|
List.find?_isSome (p := fun kv => (compare kv.1 k).isEq) |>.mpr ⟨(k', v), hmem, hpred⟩
have hkv_cmp : compare kv.1 k = .eq := by
simpa [beq_iff_eq] using List.find?_some hfind
have hval : kv.2 = v := by grind
have hfind : List.find? (fun kv => (compare kv.fst k).isEq) t₂.toList =
some (kv.fst, v) := by
simp [← hval, ← hfind]
simp [← hval, hfind]
simp [eq_of_compare hkv_cmp]
change Const.get? (Const.mergeWith f t₁.inner.inner t₂.inner.inner
t₁.inner.wf.balanced).impl k =
merge (f k) (Const.get? t₁.inner.inner k) (Const.get? t₂.inner.inner k)
have ht₁ : t₁.inner.inner.WF := t₁.inner.wf
have ht₂ : t₂.inner.inner.WF := t₂.inner.wf
have hmerge : (Const.mergeWith f t₁.inner.inner t₂.inner.inner
t₁.inner.wf.balanced).impl.WF := t₁.inner.wf.constMergeWith
simp_to_model [Const.mergeWith, Const.get?] using
Std.Internal.List.Const.getValue?_mergeWith

end HeapInstance

Expand Down
Loading