Theorem: Batteries.UnionFind.equiv_link
File: .lake/packages/batteries/Batteries/Data/UnionFind/Lemmas.lean

tactic: obtain ⟨r, ha, hr⟩ := root_link xroot yroot
state_before: a b : Nat
self : UnionFind
x y : Fin self.size
xroot : self.parent ↑x = ↑x
yroot : self.parent ↑y = ↑y
this :
  ∀ {m : UnionFind} {x y : Fin self.size},
    self.rootD ↑x = ↑x →
      self.rootD ↑y = ↑y →
        (∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i) →
          (m.Equiv a b ↔ self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
⊢ (self.link x y yroot).Equiv a b ↔
    self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b
state_after: case intro.intro
a b : Nat
self : UnionFind
x y : Fin self.size
xroot : self.parent ↑x = ↑x
yroot : self.parent ↑y = ↑y
this :
  ∀ {m : UnionFind} {x y : Fin self.size},
    self.rootD ↑x = ↑x →
      self.rootD ↑y = ↑y →
        (∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i) →
          (m.Equiv a b ↔ self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
r : Fin self.size
ha : r = x ∨ r = y
hr : ∀ (i : Nat), (self.link x y yroot).rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑r else self.rootD i
⊢ (self.link x y yroot).Equiv a b ↔
    self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b

tactic: revert hr
state_before: case intro.intro
a b : Nat
self : UnionFind
x y : Fin self.size
xroot : self.parent ↑x = ↑x
yroot : self.parent ↑y = ↑y
this :
  ∀ {m : UnionFind} {x y : Fin self.size},
    self.rootD ↑x = ↑x →
      self.rootD ↑y = ↑y →
        (∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i) →
          (m.Equiv a b ↔ self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
r : Fin self.size
ha : r = x ∨ r = y
hr : ∀ (i : Nat), (self.link x y yroot).rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑r else self.rootD i
⊢ (self.link x y yroot).Equiv a b ↔
    self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b
state_after: case intro.intro
a b : Nat
self : UnionFind
x y : Fin self.size
xroot : self.parent ↑x = ↑x
yroot : self.parent ↑y = ↑y
this :
  ∀ {m : UnionFind} {x y : Fin self.size},
    self.rootD ↑x = ↑x →
      self.rootD ↑y = ↑y →
        (∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i) →
          (m.Equiv a b ↔ self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
r : Fin self.size
ha : r = x ∨ r = y
⊢ (∀ (i : Nat), (self.link x y yroot).rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑r else self.rootD i) →
    ((self.link x y yroot).Equiv a b ↔
      self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)

tactic: rw [← rootD_eq_self] at xroot yroot
state_before: case intro.intro
a b : Nat
self : UnionFind
x y : Fin self.size
xroot : self.parent ↑x = ↑x
yroot : self.parent ↑y = ↑y
this :
  ∀ {m : UnionFind} {x y : Fin self.size},
    self.rootD ↑x = ↑x →
      self.rootD ↑y = ↑y →
        (∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i) →
          (m.Equiv a b ↔ self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
r : Fin self.size
ha : r = x ∨ r = y
⊢ (∀ (i : Nat), (self.link x y yroot).rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑r else self.rootD i) →
    ((self.link x y yroot).Equiv a b ↔
      self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
state_after: case intro.intro
a b : Nat
self : UnionFind
x y : Fin self.size
xroot : self.rootD ↑x = ↑x
yroot✝ : self.parent ↑y = ↑y
yroot : self.rootD ↑y = ↑y
this :
  ∀ {m : UnionFind} {x y : Fin self.size},
    self.rootD ↑x = ↑x →
      self.rootD ↑y = ↑y →
        (∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i) →
          (m.Equiv a b ↔ self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
r : Fin self.size
ha : r = x ∨ r = y
⊢ (∀ (i : Nat), (self.link x y yroot✝).rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑r else self.rootD i) →
    ((self.link x y yroot✝).Equiv a b ↔
      self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)

tactic: obtain rfl | rfl := ha
state_before: case intro.intro
a b : Nat
self : UnionFind
x y : Fin self.size
xroot : self.rootD ↑x = ↑x
yroot✝ : self.parent ↑y = ↑y
yroot : self.rootD ↑y = ↑y
this :
  ∀ {m : UnionFind} {x y : Fin self.size},
    self.rootD ↑x = ↑x →
      self.rootD ↑y = ↑y →
        (∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i) →
          (m.Equiv a b ↔ self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
r : Fin self.size
ha : r = x ∨ r = y
⊢ (∀ (i : Nat), (self.link x y yroot✝).rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑r else self.rootD i) →
    ((self.link x y yroot✝).Equiv a b ↔
      self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
state_after: case intro.intro.inl
a b : Nat
self : UnionFind
y : Fin self.size
yroot✝ : self.parent ↑y = ↑y
yroot : self.rootD ↑y = ↑y
this :
  ∀ {m : UnionFind} {x y : Fin self.size},
    self.rootD ↑x = ↑x →
      self.rootD ↑y = ↑y →
        (∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i) →
          (m.Equiv a b ↔ self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
r : Fin self.size
xroot : self.rootD ↑r = ↑r
⊢ (∀ (i : Nat), (self.link r y yroot✝).rootD i = if self.rootD i = ↑r ∨ self.rootD i = ↑y then ↑r else self.rootD i) →
    ((self.link r y yroot✝).Equiv a b ↔
      self.Equiv a b ∨ self.Equiv a ↑r ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑r) b)

case intro.intro.inr
a b : Nat
self : UnionFind
x : Fin self.size
xroot : self.rootD ↑x = ↑x
this :
  ∀ {m : UnionFind} {x y : Fin self.size},
    self.rootD ↑x = ↑x →
      self.rootD ↑y = ↑y →
        (∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i) →
          (m.Equiv a b ↔ self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
r : Fin self.size
yroot✝ : self.parent ↑r = ↑r
yroot : self.rootD ↑r = ↑r
⊢ (∀ (i : Nat), (self.link x r yroot✝).rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑r then ↑r else self.rootD i) →
    ((self.link x r yroot✝).Equiv a b ↔
      self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑r) b ∨ self.Equiv a ↑r ∧ self.Equiv (↑x) b)

tactic: simp [Equiv, hm, xroot, yroot]
state_before: a b : Nat
self : UnionFind
x✝ y✝ : Fin self.size
xroot✝ : self.parent ↑x✝ = ↑x✝
yroot✝ : self.parent ↑y✝ = ↑y✝
m : UnionFind
x y : Fin self.size
xroot : self.rootD ↑x = ↑x
yroot : self.rootD ↑y = ↑y
hm : ∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i
⊢ m.Equiv a b ↔ self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b
state_after: a b : Nat
self : UnionFind
x✝ y✝ : Fin self.size
xroot✝ : self.parent ↑x✝ = ↑x✝
yroot✝ : self.parent ↑y✝ = ↑y✝
m : UnionFind
x y : Fin self.size
xroot : self.rootD ↑x = ↑x
yroot : self.rootD ↑y = ↑y
hm : ∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i
⊢ ((if self.rootD a = ↑x ∨ self.rootD a = ↑y then ↑x else self.rootD a) =
      if self.rootD b = ↑x ∨ self.rootD b = ↑y then ↑x else self.rootD b) ↔
    self.rootD a = self.rootD b ∨ self.rootD a = ↑x ∧ ↑y = self.rootD b ∨ self.rootD a = ↑y ∧ ↑x = self.rootD b

tactic: by_cases h1 : rootD self a = x <;> by_cases h2 : rootD self b = x <;>
  simp [h1, h2, imp_false, Decidable.not_not]
state_before: a b : Nat
self : UnionFind
x✝ y✝ : Fin self.size
xroot✝ : self.parent ↑x✝ = ↑x✝
yroot✝ : self.parent ↑y✝ = ↑y✝
m : UnionFind
x y : Fin self.size
xroot : self.rootD ↑x = ↑x
yroot : self.rootD ↑y = ↑y
hm : ∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i
⊢ ((if self.rootD a = ↑x ∨ self.rootD a = ↑y then ↑x else self.rootD a) =
      if self.rootD b = ↑x ∨ self.rootD b = ↑y then ↑x else self.rootD b) ↔
    self.rootD a = self.rootD b ∨ self.rootD a = ↑x ∧ ↑y = self.rootD b ∨ self.rootD a = ↑y ∧ ↑x = self.rootD b
state_after: case neg
a b : Nat
self : UnionFind
x✝ y✝ : Fin self.size
xroot✝ : self.parent ↑x✝ = ↑x✝
yroot✝ : self.parent ↑y✝ = ↑y✝
m : UnionFind
x y : Fin self.size
xroot : self.rootD ↑x = ↑x
yroot : self.rootD ↑y = ↑y
hm : ∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i
h1 : self.rootD a = ↑x
h2 : ¬self.rootD b = ↑x
⊢ (↑x = if self.rootD b = ↑y then ↑x else self.rootD b) ↔
    ↑x = self.rootD b ∨ ↑y = self.rootD b ∨ ↑x = ↑y ∧ ↑x = self.rootD b

case neg
a b : Nat
self : UnionFind
x✝ y✝ : Fin self.size
xroot✝ : self.parent ↑x✝ = ↑x✝
yroot✝ : self.parent ↑y✝ = ↑y✝
m : UnionFind
x y : Fin self.size
xroot : self.rootD ↑x = ↑x
yroot : self.rootD ↑y = ↑y
hm : ∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i
h1 : ¬self.rootD a = ↑x
h2 : ¬self.rootD b = ↑x
⊢ ((if self.rootD a = ↑y then ↑x else self.rootD a) = if self.rootD b = ↑y then ↑x else self.rootD b) ↔
    self.rootD a = self.rootD b ∨ self.rootD a = ↑y ∧ ↑x = self.rootD b

tactic: simp [h2, Ne.symm h2]
state_before: case neg
a b : Nat
self : UnionFind
x✝ y✝ : Fin self.size
xroot✝ : self.parent ↑x✝ = ↑x✝
yroot✝ : self.parent ↑y✝ = ↑y✝
m : UnionFind
x y : Fin self.size
xroot : self.rootD ↑x = ↑x
yroot : self.rootD ↑y = ↑y
hm : ∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i
h1 : self.rootD a = ↑x
h2 : ¬self.rootD b = ↑x
⊢ (↑x = if self.rootD b = ↑y then ↑x else self.rootD b) ↔
    ↑x = self.rootD b ∨ ↑y = self.rootD b ∨ ↑x = ↑y ∧ ↑x = self.rootD b
state_after: case neg
a b : Nat
self : UnionFind
x✝ y✝ : Fin self.size
xroot✝ : self.parent ↑x✝ = ↑x✝
yroot✝ : self.parent ↑y✝ = ↑y✝
m : UnionFind
x y : Fin self.size
xroot : self.rootD ↑x = ↑x
yroot : self.rootD ↑y = ↑y
hm : ∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i
h1 : self.rootD a = ↑x
h2 : ¬self.rootD b = ↑x
⊢ (↑x = if self.rootD b = ↑y then ↑x else self.rootD b) ↔ ↑y = self.rootD b

tactic: split <;> simp [@eq_comm _ _ (rootD self b), *]
state_before: case neg
a b : Nat
self : UnionFind
x✝ y✝ : Fin self.size
xroot✝ : self.parent ↑x✝ = ↑x✝
yroot✝ : self.parent ↑y✝ = ↑y✝
m : UnionFind
x y : Fin self.size
xroot : self.rootD ↑x = ↑x
yroot : self.rootD ↑y = ↑y
hm : ∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i
h1 : self.rootD a = ↑x
h2 : ¬self.rootD b = ↑x
⊢ (↑x = if self.rootD b = ↑y then ↑x else self.rootD b) ↔ ↑y = self.rootD b
state_after: no goals

tactic: by_cases h1 : rootD self a = y <;> by_cases h2 : rootD self b = y <;>
  simp [h1, h2, @eq_comm _ _ (rootD self b), *]
state_before: case neg
a b : Nat
self : UnionFind
x✝ y✝ : Fin self.size
xroot✝ : self.parent ↑x✝ = ↑x✝
yroot✝ : self.parent ↑y✝ = ↑y✝
m : UnionFind
x y : Fin self.size
xroot : self.rootD ↑x = ↑x
yroot : self.rootD ↑y = ↑y
hm : ∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i
h1 : ¬self.rootD a = ↑x
h2 : ¬self.rootD b = ↑x
⊢ ((if self.rootD a = ↑y then ↑x else self.rootD a) = if self.rootD b = ↑y then ↑x else self.rootD b) ↔
    self.rootD a = self.rootD b ∨ self.rootD a = ↑y ∧ ↑x = self.rootD b
state_after: no goals

tactic: exact this xroot yroot
state_before: case intro.intro.inl
a b : Nat
self : UnionFind
y : Fin self.size
yroot✝ : self.parent ↑y = ↑y
yroot : self.rootD ↑y = ↑y
this :
  ∀ {m : UnionFind} {x y : Fin self.size},
    self.rootD ↑x = ↑x →
      self.rootD ↑y = ↑y →
        (∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i) →
          (m.Equiv a b ↔ self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
r : Fin self.size
xroot : self.rootD ↑r = ↑r
⊢ (∀ (i : Nat), (self.link r y yroot✝).rootD i = if self.rootD i = ↑r ∨ self.rootD i = ↑y then ↑r else self.rootD i) →
    ((self.link r y yroot✝).Equiv a b ↔
      self.Equiv a b ∨ self.Equiv a ↑r ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑r) b)
state_after: no goals

tactic: simpa [or_comm, and_comm] using this yroot xroot
state_before: case intro.intro.inr
a b : Nat
self : UnionFind
x : Fin self.size
xroot : self.rootD ↑x = ↑x
this :
  ∀ {m : UnionFind} {x y : Fin self.size},
    self.rootD ↑x = ↑x →
      self.rootD ↑y = ↑y →
        (∀ (i : Nat), m.rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑y then ↑x else self.rootD i) →
          (m.Equiv a b ↔ self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑y) b ∨ self.Equiv a ↑y ∧ self.Equiv (↑x) b)
r : Fin self.size
yroot✝ : self.parent ↑r = ↑r
yroot : self.rootD ↑r = ↑r
⊢ (∀ (i : Nat), (self.link x r yroot✝).rootD i = if self.rootD i = ↑x ∨ self.rootD i = ↑r then ↑r else self.rootD i) →
    ((self.link x r yroot✝).Equiv a b ↔
      self.Equiv a b ∨ self.Equiv a ↑x ∧ self.Equiv (↑r) b ∨ self.Equiv a ↑r ∧ self.Equiv (↑x) b)
state_after: no goals