File: .lake/packages/batteries/Batteries/Data/RBMap/Alter.lean

full_name: Batteries.RBNode.OnRoot
code: /-- Asserts that property `p` holds on the root of the tree, if any. -/
def OnRoot (p : α → Prop) : RBNode α → Prop
  
goal: Batteries.RBNode α → Prop

full_name: Batteries.RBNode.Path.fill'
code: /-- Same as `fill` but taking its arguments in a pair for easier composition with `zoom`. -/
@[inline] def fill' : RBNode α × Path α → RBNode α 
goal: Batteries.RBNode α × Batteries.RBNode.Path α → Batteries.RBNode α

full_name: Batteries.RBNode.Path.zoom_fill'
code: theorem zoom_fill' (cut : α → Ordering) (t : RBNode α) (path : Path α) :
    fill' (zoom cut t path) = path.fill t 
goal: Batteries.RBNode.Path.fill' (Batteries.RBNode.zoom cut t path) = path.fill t

full_name: Batteries.RBNode.Path.zoom_fill
code: theorem zoom_fill (H : zoom cut t path = (t', path')) : path.fill t = path'.fill t' 
goal: ∀ {α : Type u_1} {cut : α → Ordering} {t : Batteries.RBNode α} {path : Batteries.RBNode.Path α}
  {t' : Batteries.RBNode α} {path' : Batteries.RBNode.Path α},
  Batteries.RBNode.zoom cut t path = (t', path') → path.fill t = path'.fill t'

full_name: Batteries.RBNode.Path.Balanced.redL
code: /--
The balance invariant for a path. `path.Balanced c₀ n₀ c n` means that `path` is a red-black tree
with balance invariant `c₀, n₀`, but it has a "hole" where a tree with balance invariant `c, n`
has been removed. The defining property is `Balanced.fill`: if `path.Balanced c₀ n₀ c n` and you
fill the hole with a tree satisfying `t.Balanced c n`, then `(path.fill t).Balanced c₀ n₀` .
-/
protected inductive Balanced : Path α → RBColor → Nat → Prop where
  /-- The root of the tree is `c₀, n₀`-balanced by assumption. -/
  | protected root : Path.root.Balanced c₀ n₀
  /-- Descend into the left subtree of a red node. -/
  | redL : Balanced y black n → parent.Balanced red n →
    (Path.left red parent v y).Balanced black n
  /-- Descend into the right subtree of a red node. -/
  | redR : Balanced x black n → parent.Balanced red n →
    (Path.right red x v parent).Balanced black n
  /-- Descend into the left subtree of a black node. -/
  | blackL : Balanced y c₂ n → parent.Balanced black (n + 1) →
    (Path.left black parent v y).Balanced c₁ n
  /-- Descend into the right subtree of a black node. -/
  | blackR : Balanced x c₁ n → parent.Balanced black (n + 1) →
    (Path.right black x v parent).Balanced c₂ n
goal: y.Balanced Batteries.RBColor.black n →
  Batteries.RBNode.Path.Balanced c₀ n₀ parent Batteries.RBColor.red n →
    Batteries.RBNode.Path.Balanced c₀ n₀ (Batteries.RBNode.Path.left Batteries.RBColor.red parent v y)
      Batteries.RBColor.black n

full_name: Batteries.RBNode.Path.Balanced.blackL
code: /--
The balance invariant for a path. `path.Balanced c₀ n₀ c n` means that `path` is a red-black tree
with balance invariant `c₀, n₀`, but it has a "hole" where a tree with balance invariant `c, n`
has been removed. The defining property is `Balanced.fill`: if `path.Balanced c₀ n₀ c n` and you
fill the hole with a tree satisfying `t.Balanced c n`, then `(path.fill t).Balanced c₀ n₀` .
-/
protected inductive Balanced : Path α → RBColor → Nat → Prop where
  /-- The root of the tree is `c₀, n₀`-balanced by assumption. -/
  | protected root : Path.root.Balanced c₀ n₀
  /-- Descend into the left subtree of a red node. -/
  | redL : Balanced y black n → parent.Balanced red n →
    (Path.left red parent v y).Balanced black n
  /-- Descend into the right subtree of a red node. -/
  | redR : Balanced x black n → parent.Balanced red n →
    (Path.right red x v parent).Balanced black n
  /-- Descend into the left subtree of a black node. -/
  | blackL : Balanced y c₂ n → parent.Balanced black (n + 1) →
    (Path.left black parent v y).Balanced c₁ n
  /-- Descend into the right subtree of a black node. -/
  | blackR : Balanced x c₁ n → parent.Balanced black (n + 1) →
    (Path.right black x v parent).Balanced c₂ n
goal: y.Balanced c₂ n →
  Batteries.RBNode.Path.Balanced c₀ n₀ parent Batteries.RBColor.black (n + 1) →
    Batteries.RBNode.Path.Balanced c₀ n₀ (Batteries.RBNode.Path.left Batteries.RBColor.black parent v y) c₁ n

full_name: Batteries.RBNode.Path.Balanced.blackR
code: /--
The balance invariant for a path. `path.Balanced c₀ n₀ c n` means that `path` is a red-black tree
with balance invariant `c₀, n₀`, but it has a "hole" where a tree with balance invariant `c, n`
has been removed. The defining property is `Balanced.fill`: if `path.Balanced c₀ n₀ c n` and you
fill the hole with a tree satisfying `t.Balanced c n`, then `(path.fill t).Balanced c₀ n₀` .
-/
protected inductive Balanced : Path α → RBColor → Nat → Prop where
  /-- The root of the tree is `c₀, n₀`-balanced by assumption. -/
  | protected root : Path.root.Balanced c₀ n₀
  /-- Descend into the left subtree of a red node. -/
  | redL : Balanced y black n → parent.Balanced red n →
    (Path.left red parent v y).Balanced black n
  /-- Descend into the right subtree of a red node. -/
  | redR : Balanced x black n → parent.Balanced red n →
    (Path.right red x v parent).Balanced black n
  /-- Descend into the left subtree of a black node. -/
  | blackL : Balanced y c₂ n → parent.Balanced black (n + 1) →
    (Path.left black parent v y).Balanced c₁ n
  /-- Descend into the right subtree of a black node. -/
  | blackR : Balanced x c₁ n → parent.Balanced black (n + 1) →
    (Path.right black x v parent).Balanced c₂ n
goal: x.Balanced c₁ n →
  Batteries.RBNode.Path.Balanced c₀ n₀ parent Batteries.RBColor.black (n + 1) →
    Batteries.RBNode.Path.Balanced c₀ n₀ (Batteries.RBNode.Path.right Batteries.RBColor.black x v parent) c₂ n

full_name: Batteries.RBNode.Path.Balanced.redR
code: /--
The balance invariant for a path. `path.Balanced c₀ n₀ c n` means that `path` is a red-black tree
with balance invariant `c₀, n₀`, but it has a "hole" where a tree with balance invariant `c, n`
has been removed. The defining property is `Balanced.fill`: if `path.Balanced c₀ n₀ c n` and you
fill the hole with a tree satisfying `t.Balanced c n`, then `(path.fill t).Balanced c₀ n₀` .
-/
protected inductive Balanced : Path α → RBColor → Nat → Prop where
  /-- The root of the tree is `c₀, n₀`-balanced by assumption. -/
  | protected root : Path.root.Balanced c₀ n₀
  /-- Descend into the left subtree of a red node. -/
  | redL : Balanced y black n → parent.Balanced red n →
    (Path.left red parent v y).Balanced black n
  /-- Descend into the right subtree of a red node. -/
  | redR : Balanced x black n → parent.Balanced red n →
    (Path.right red x v parent).Balanced black n
  /-- Descend into the left subtree of a black node. -/
  | blackL : Balanced y c₂ n → parent.Balanced black (n + 1) →
    (Path.left black parent v y).Balanced c₁ n
  /-- Descend into the right subtree of a black node. -/
  | blackR : Balanced x c₁ n → parent.Balanced black (n + 1) →
    (Path.right black x v parent).Balanced c₂ n
goal: x.Balanced Batteries.RBColor.black n →
  Batteries.RBNode.Path.Balanced c₀ n₀ parent Batteries.RBColor.red n →
    Batteries.RBNode.Path.Balanced c₀ n₀ (Batteries.RBNode.Path.right Batteries.RBColor.red x v parent)
      Batteries.RBColor.black n

full_name: Batteries.RBNode.Path.Balanced
code: /--
The balance invariant for a path. `path.Balanced c₀ n₀ c n` means that `path` is a red-black tree
with balance invariant `c₀, n₀`, but it has a "hole" where a tree with balance invariant `c, n`
has been removed. The defining property is `Balanced.fill`: if `path.Balanced c₀ n₀ c n` and you
fill the hole with a tree satisfying `t.Balanced c n`, then `(path.fill t).Balanced c₀ n₀` .
-/
protected inductive Balanced : Path α → RBColor → Nat → Prop where
  /-- The root of the tree is `c₀, n₀`-balanced by assumption. -/
  | protected root : Path.root.Balanced c₀ n₀
  /-- Descend into the left subtree of a red node. -/
  | redL : Balanced y black n → parent.Balanced red n →
    (Path.left red parent v y).Balanced black n
  /-- Descend into the right subtree of a red node. -/
  | redR : Balanced x black n → parent.Balanced red n →
    (Path.right red x v parent).Balanced black n
  /-- Descend into the left subtree of a black node. -/
  | blackL : Balanced y c₂ n → parent.Balanced black (n + 1) →
    (Path.left black parent v y).Balanced c₁ n
  /-- Descend into the right subtree of a black node. -/
  | blackR : Balanced x c₁ n → parent.Balanced black (n + 1) →
    (Path.right black x v parent).Balanced c₂ n
goal: Batteries.RBNode.Path α → Batteries.RBColor → Nat → Prop

full_name: Batteries.RBNode.Path.Balanced.root
code: /--
The balance invariant for a path. `path.Balanced c₀ n₀ c n` means that `path` is a red-black tree
with balance invariant `c₀, n₀`, but it has a "hole" where a tree with balance invariant `c, n`
has been removed. The defining property is `Balanced.fill`: if `path.Balanced c₀ n₀ c n` and you
fill the hole with a tree satisfying `t.Balanced c n`, then `(path.fill t).Balanced c₀ n₀` .
-/
protected inductive Balanced : Path α → RBColor → Nat → Prop where
  /-- The root of the tree is `c₀, n₀`-balanced by assumption. -/
  | protected root : Path.root.Balanced c₀ n₀
  /-- Descend into the left subtree of a red node. -/
  | redL : Balanced y black n → parent.Balanced red n →
    (Path.left red parent v y).Balanced black n
  /-- Descend into the right subtree of a red node. -/
  | redR : Balanced x black n → parent.Balanced red n →
    (Path.right red x v parent).Balanced black n
  /-- Descend into the left subtree of a black node. -/
  | blackL : Balanced y c₂ n → parent.Balanced black (n + 1) →
    (Path.left black parent v y).Balanced c₁ n
  /-- Descend into the right subtree of a black node. -/
  | blackR : Balanced x c₁ n → parent.Balanced black (n + 1) →
    (Path.right black x v parent).Balanced c₂ n
goal: Batteries.RBNode.Path.Balanced c₀ n₀ Batteries.RBNode.Path.root c₀ n₀

full_name: Batteries.RBNode.Path.Balanced.fill
code: /--
The defining property of a balanced path: If `path` is a `c₀,n₀` tree with a `c,n` hole,
then filling the hole with a `c,n` tree yields a `c₀,n₀` tree.
-/
protected theorem Balanced.fill {path : Path α} {t} :
    path.Balanced c₀ n₀ c n → t.Balanced c n → (path.fill t).Balanced c₀ n₀
  
goal: Batteries.RBNode.Path.Balanced c₀ n₀ path c n → t.Balanced c n → (path.fill t).Balanced c₀ n₀

full_name: Batteries.RBNode.Balanced.zoom
code: protected theorem _root_.Batteries.RBNode.Balanced.zoom : t.Balanced c n → path.Balanced c₀ n₀ c n →
    zoom cut t path = (t', path') → ∃ c n, t'.Balanced c n ∧ path'.Balanced c₀ n₀ c n
  
goal: ∀ {α : Type u_1} {cut : α → Ordering} {t : Batteries.RBNode α} {path : Batteries.RBNode.Path α}
  {t' : Batteries.RBNode α} {path' : Batteries.RBNode.Path α} {c₀ : Batteries.RBColor} {n₀ : Nat}
  {c : Batteries.RBColor} {n : Nat},
  t.Balanced c n →
    Batteries.RBNode.Path.Balanced c₀ n₀ path c n →
      Batteries.RBNode.zoom cut t path = (t', path') →
        ∃ c n, t'.Balanced c n ∧ Batteries.RBNode.Path.Balanced c₀ n₀ path' c n

full_name: Batteries.RBNode.Path.Balanced.ins
code: protected theorem Balanced.ins {path : Path α}
    (hp : path.Balanced c₀ n₀ c n) (ht : t.RedRed (c = red) n) :
    ∃ n, (path.ins t).Balanced black n 
goal: ∃ n, (path.ins t).Balanced Batteries.RBColor.black n

full_name: Batteries.RBNode.Path.Balanced.insertNew
code: protected theorem Balanced.insertNew {path : Path α} (H : path.Balanced c n black 0) :
    ∃ n, (path.insertNew v).Balanced black n 
goal: ∃ n, (path.insertNew v).Balanced Batteries.RBColor.black n

full_name: Batteries.RBNode.Path.Balanced.del
code: protected theorem Balanced.del {path : Path α}
    (hp : path.Balanced c₀ n₀ c n) (ht : t.DelProp c' n) (hc : c = black → c' ≠ red) :
    ∃ n, (path.del t c').Balanced black n 
goal: ∃ n, (path.del t c').Balanced Batteries.RBColor.black n

full_name: Batteries.RBNode.Path.Zoomed
code: /--
The property of a path returned by `t.zoom cut`. Each of the parents visited along the path have
the appropriate ordering relation to the cut.
-/
def Zoomed (cut : α → Ordering) : Path α → Prop
  
goal: Batteries.RBNode.Path α → Prop

full_name: Batteries.RBNode.Path.zoom_zoomed₂
code: theorem zoom_zoomed₂ (e : zoom cut t path = (t', path'))
    (hp : path.Zoomed cut) : path'.Zoomed cut 
goal: ∀ {α : Type u_1} {cut : α → Ordering} {t : Batteries.RBNode α} {path : Batteries.RBNode.Path α}
  {t' : Batteries.RBNode α} {path' : Batteries.RBNode.Path α},
  Batteries.RBNode.zoom cut t path = (t', path') →
    Batteries.RBNode.Path.Zoomed cut path → Batteries.RBNode.Path.Zoomed cut path'

full_name: Batteries.RBNode.Path.RootOrdered
code: /--
`path.RootOrdered cmp v` is true if `v` would be able to fit into the hole
without violating the ordering invariant.
-/
def RootOrdered (cmp : α → α → Ordering) : Path α → α → Prop
  
goal: Batteries.RBNode.Path α → α → Prop

full_name: Batteries.RBNode.cmpEq.RootOrdered_congr
code: theorem _root_.Batteries.RBNode.cmpEq.RootOrdered_congr
    {cmp : α → α → Ordering} (h : cmpEq cmp a b) :
    ∀ {t : Path α}, t.RootOrdered cmp a ↔ t.RootOrdered cmp b
  
goal: Batteries.RBNode.Path.RootOrdered cmp t a ↔ Batteries.RBNode.Path.RootOrdered cmp t b

full_name: Batteries.RBNode.Path.Zoomed.toRootOrdered
code: theorem Zoomed.toRootOrdered {cmp} :
    ∀ {path : Path α}, path.Zoomed (cmp v) → path.RootOrdered cmp v
  
goal: Batteries.RBNode.Path.Zoomed (cmp v) path → Batteries.RBNode.Path.RootOrdered cmp path v

full_name: Batteries.RBNode.Path.Ordered
code: /-- The ordering invariant for a `Path`. -/
def Ordered (cmp : α → α → Ordering) : Path α → Prop
  
goal: Batteries.RBNode.Path α → Prop

full_name: Batteries.RBNode.Path.Ordered.fill
code: protected theorem Ordered.fill : ∀ {path : Path α} {t},
    (path.fill t).Ordered cmp ↔ path.Ordered cmp ∧ t.Ordered cmp ∧ t.All (path.RootOrdered cmp)
  
goal: Batteries.RBNode.Ordered cmp (path.fill t) ↔
  Batteries.RBNode.Path.Ordered cmp path ∧
    Batteries.RBNode.Ordered cmp t ∧ Batteries.RBNode.All (Batteries.RBNode.Path.RootOrdered cmp path) t

full_name: Batteries.RBNode.Ordered.zoom'
code: theorem _root_.Batteries.RBNode.Ordered.zoom' {t : RBNode α} {path : Path α}
    (ht : t.Ordered cmp) (hp : path.Ordered cmp) (tp : t.All (path.RootOrdered cmp))
    (pz : path.Zoomed cut) (eq : t.zoom cut path = (t', path')) :
    t'.Ordered cmp ∧ path'.Ordered cmp ∧ t'.All (path'.RootOrdered cmp) ∧ path'.Zoomed cut 
goal: Batteries.RBNode.Ordered cmp t' ∧
  Batteries.RBNode.Path.Ordered cmp path' ∧
    Batteries.RBNode.All (Batteries.RBNode.Path.RootOrdered cmp path') t' ∧ Batteries.RBNode.Path.Zoomed cut path'

full_name: Batteries.RBNode.Ordered.zoom
code: theorem _root_.Batteries.RBNode.Ordered.zoom {t : RBNode α}
    (ht : t.Ordered cmp) (eq : t.zoom cut = (t', path')) :
    t'.Ordered cmp ∧ path'.Ordered cmp ∧ t'.All (path'.RootOrdered cmp) ∧ path'.Zoomed cut 
goal: Batteries.RBNode.Ordered cmp t' ∧
  Batteries.RBNode.Path.Ordered cmp path' ∧
    Batteries.RBNode.All (Batteries.RBNode.Path.RootOrdered cmp path') t' ∧ Batteries.RBNode.Path.Zoomed cut path'

full_name: Batteries.RBNode.Path.Ordered.ins
code: theorem Ordered.ins : ∀ {path : Path α} {t : RBNode α},
    t.Ordered cmp → path.Ordered cmp → t.All (path.RootOrdered cmp) → (path.ins t).Ordered cmp
  
goal: Batteries.RBNode.Ordered cmp t →
  Batteries.RBNode.Path.Ordered cmp path →
    Batteries.RBNode.All (Batteries.RBNode.Path.RootOrdered cmp path) t → Batteries.RBNode.Ordered cmp (path.ins t)

full_name: Batteries.RBNode.Path.Ordered.insertNew
code: theorem Ordered.insertNew {path : Path α} (hp : path.Ordered cmp) (vp : path.RootOrdered cmp v) :
    (path.insertNew v).Ordered cmp 
goal: Batteries.RBNode.Ordered cmp (path.insertNew v)

full_name: Batteries.RBNode.Path.Ordered.del
code: theorem Ordered.del : ∀ {path : Path α} {t : RBNode α} {c},
    t.Ordered cmp → path.Ordered cmp → t.All (path.RootOrdered cmp) → (path.del t c).Ordered cmp
  
goal: Batteries.RBNode.Ordered cmp t →
  Batteries.RBNode.Path.Ordered cmp path →
    Batteries.RBNode.All (Batteries.RBNode.Path.RootOrdered cmp path) t → Batteries.RBNode.Ordered cmp (path.del t c)

full_name: Batteries.RBNode.Ordered.alter
code: /-- The `alter` function preserves the ordering invariants. -/
protected theorem Ordered.alter {t : RBNode α}
    (H : ∀ {x t' p}, t.zoom cut = (t', p) → f t'.root? = some x →
      p.RootOrdered cmp x ∧ t'.OnRoot (cmpEq cmp x))
    (h : t.Ordered cmp) : (alter cut f t).Ordered cmp 
goal: Batteries.RBNode.Ordered cmp (Batteries.RBNode.alter cut f t)

full_name: Batteries.RBNode.Balanced.alter
code: /-- The `alter` function preserves the balance invariants. -/
protected theorem Balanced.alter {t : RBNode α}
    (h : t.Balanced c n) : ∃ c n, (t.alter cut f).Balanced c n 
goal: ∃ c n, (Batteries.RBNode.alter cut f t).Balanced c n

full_name: Batteries.RBNode.modify_eq_alter
code: theorem modify_eq_alter (t : RBNode α) : t.modify cut f = t.alter cut (.map f) 
goal: Batteries.RBNode.modify cut f t = Batteries.RBNode.alter cut (Option.map f) t

full_name: Batteries.RBNode.Ordered.modify
code: /-- The `modify` function preserves the ordering invariants. -/
protected theorem Ordered.modify {t : RBNode α}
    (H : (t.zoom cut).1.OnRoot fun x => cmpEq cmp (f x) x)
    (h : t.Ordered cmp) : (modify cut f t).Ordered cmp 
goal: Batteries.RBNode.Ordered cmp (Batteries.RBNode.modify cut f t)

full_name: Batteries.RBNode.Balanced.modify
code: /-- The `modify` function preserves the balance invariants. -/
protected theorem Balanced.modify {t : RBNode α}
    (h : t.Balanced c n) : ∃ c n, (t.modify cut f).Balanced c n 
goal: ∃ c n, (Batteries.RBNode.modify cut f t).Balanced c n

full_name: Batteries.RBNode.WF.alter
code: theorem WF.alter {t : RBNode α}
    (H : ∀ {x t' p}, t.zoom cut = (t', p) → f t'.root? = some x →
      p.RootOrdered cmp x ∧ t'.OnRoot (cmpEq cmp x))
    (h : WF cmp t) : WF cmp (alter cut f t) 
goal: Batteries.RBNode.WF cmp (Batteries.RBNode.alter cut f t)

full_name: Batteries.RBNode.WF.modify
code: theorem WF.modify {t : RBNode α}
    (H : (t.zoom cut).1.OnRoot fun x => cmpEq cmp (f x) x)
    (h : WF cmp t) : WF cmp (t.modify cut f) 
goal: Batteries.RBNode.WF cmp (Batteries.RBNode.modify cut f t)

full_name: Batteries.RBNode.find?_eq_zoom
code: theorem find?_eq_zoom : ∀ {t : RBNode α} (p := .root), t.find? cut = (t.zoom cut p).1.root?
  
goal: Batteries.RBNode.find? cut t = (Batteries.RBNode.zoom cut t p).fst.root?

full_name: Batteries.RBSet.ModifyWF.of_eq
code: /--
A sufficient condition for `ModifyWF` is that the new element compares equal to the original.
-/
theorem ModifyWF.of_eq {t : RBSet α cmp}
    (H : ∀ {x}, RBNode.find? cut t.val = some x → cmpEq cmp (f x) x) : ModifyWF t cut f 
goal: t.ModifyWF cut f

full_name: Batteries.RBMap.modify
code: /--
`O(log n)`. In-place replace the corresponding to key `k`.
This takes the element out of the tree while `f` runs,
so it uses the element linearly if `t` is unshared.
-/
def modify (t : RBMap α β cmp) (k : α) (f : β → β) : RBMap α β cmp 
goal: Batteries.RBMap α β cmp

full_name: Batteries.RBMap.alter.adapt
code: /-- Auxiliary definition for `alter`. -/
def alter.adapt (k : α) (f : Option β → Option β) : Option (α × β) → Option (α × β)
  
goal: Option (α × β) → Option (α × β)

full_name: Batteries.RBMap.alter
code: /--
`O(log n)`. `alterP cut f t` simultaneously handles inserting, erasing and replacing an element
using a function `f : Option α → Option α`. It is passed the result of `t.findP? cut`
and can either return `none` to remove the element or `some a` to replace/insert
the element with `a` (which must have the same ordering properties as the original element).

The element is used linearly if `t` is unshared.

The `AlterWF` assumption is required because `f` may change
the ordering properties of the element, which would break the invariants.
-/
@[specialize] def alter
    (t : RBMap α β cmp) (k : α) (f : Option β → Option β) : RBMap α β cmp 
goal: Batteries.RBMap α β cmp