l3lab/ntp-mathlib huggingface dataset:
/-- Taking the product of two maps with the same domain is equivalent to taking the product of
their codomains. -/
@[simps]
def prodEquiv : (A →⋆ₐ[R] B) × (A →⋆ₐ[R] C) ≃ (A →⋆ₐ[R] B × C)
    where
  toFun f := f.1.prod f.2
  invFun f := ((fst _ _ _).comp f, (snd _ _ _).comp f)
  left_inv f := by ext <;> rfl
  right_inv f := by ext <;> 

Proof state:
case h.a
R : Type u_1
A : Type u_2
B : Type u_3
C : Type u_4
inst✝⁹ : CommSemiring R
inst✝⁸ : Semiring A
inst✝⁷ : Algebra R A
inst✝⁶ : Star A
inst✝⁵ : Semiring B
inst✝⁴ : Algebra R B
inst✝³ : Star B
inst✝² : Semiring C
inst✝¹ : Algebra R C
inst✝ : Star C
f : A →⋆ₐ[R] B × C
x✝ : A
⊢ (((fun f => prod f.1 f.2) ((fun f => (comp (fst R B C) f, comp (snd R B C) f)) f)) x✝).1 = (f x✝).1

Next tactic:
rfl
/-- Taking the product of two maps with the same domain is equivalent to taking the product of
their codomains. -/
@[simps]
def prodEquiv : (A →⋆ₐ[R] B) × (A →⋆ₐ[R] C) ≃ (A →⋆ₐ[R] B × C)
    where
  toFun f := f.1.prod f.2
  invFun f := ((fst _ _ _).comp f, (snd _ _ _).comp f)
  left_inv f := by ext <;> rfl
  right_inv f := by ext <;> 

Proof state:
case h.a
R : Type u_1
A : Type u_2
B : Type u_3
C : Type u_4
inst✝⁹ : CommSemiring R
inst✝⁸ : Semiring A
inst✝⁷ : Algebra R A
inst✝⁶ : Star A
inst✝⁵ : Semiring B
inst✝⁴ : Algebra R B
inst✝³ : Star B
inst✝² : Semiring C
inst✝¹ : Algebra R C
inst✝ : Star C
f : A →⋆ₐ[R] B × C
x✝ : A
⊢ (((fun f => prod f.1 f.2) ((fun f => (comp (fst R B C) f, comp (snd R B C) f)) f)) x✝).2 = (f x✝).2

Next tactic:
rfl
instance (priority := 100) instStarAlgHomClass (F R A B : Type*) [CommSemiring R] [Semiring A]
    [Algebra R A] [Star A] [Semiring B] [Algebra R B] [Star B]
    [hF : StarAlgEquivClass F R A B] : StarAlgHomClass F R A B :=
  { hF with
    coe := fun f => f
    coe_injective' := FunLike.coe_injective
    map_one := map_one
    map_zero := map_zero
    commutes := fun f r => by 

Proof state:
F : Type u_1
R : Type u_2
A : Type u_3
B : Type u_4
inst✝⁶ : CommSemiring R
inst✝⁵ : Semiring A
inst✝⁴ : Algebra R A
inst✝³ : Star A
inst✝² : Semiring B
inst✝¹ : Algebra R B
inst✝ : Star B
hF : StarAlgEquivClass F R A B
f : F
r : R
⊢ f ((algebraMap R A) r) = (algebraMap R B) r

Next tactic:
simp only [Algebra.algebraMap_eq_smul_one, map_smul, map_one]
instance : StarAlgEquivClass (A ≃⋆ₐ[R] B) R A B
    where
  coe f := f.toFun
  inv f := f.invFun
  left_inv f := f.left_inv
  right_inv f := f.right_inv
  coe_injective' f g h₁ h₂ := by
    

Proof state:
F : Type u_1
R : Type u_2
A : Type u_3
B : Type u_4
C : Type u_5
inst✝¹¹ : Add A
inst✝¹⁰ : Add B
inst✝⁹ : Mul A
inst✝⁸ : Mul B
inst✝⁷ : SMul R A
inst✝⁶ : SMul R B
inst✝⁵ : Star A
inst✝⁴ : Star B
inst✝³ : Add C
inst✝² : Mul C
inst✝¹ : SMul R C
inst✝ : Star C
f g : A ≃⋆ₐ[R] B
h₁ : (fun f => f.toFun) f = (fun f => f.toFun) g
h₂ : (fun f => f.invFun) f = (fun f => f.invFun) g
⊢ f = g

Next tactic:
rcases f with ⟨⟨⟨_, _, _⟩, _⟩, _⟩
/-- Star algebra equivalences are symmetric. -/
@[symm]
nonrec def symm (e : A ≃⋆ₐ[R] B) : B ≃⋆ₐ[R] A :=
  { e.symm with
    map_star' := fun b => by
      

Proof state:
F : Type u_1
R : Type u_2
A : Type u_3
B : Type u_4
C : Type u_5
inst✝¹¹ : Add A
inst✝¹⁰ : Add B
inst✝⁹ : Mul A
inst✝⁸ : Mul B
inst✝⁷ : SMul R A
inst✝⁶ : SMul R B
inst✝⁵ : Star A
inst✝⁴ : Star B
inst✝³ : Add C
inst✝² : Mul C
inst✝¹ : SMul R C
inst✝ : Star C
e : A ≃⋆ₐ[R] B
src✝ : B ≃+* A := RingEquiv.symm e.toRingEquiv
b : B
⊢ Equiv.toFun
      { toEquiv := src✝.toEquiv,
          map_mul' :=
            (_ :
              ∀ (x y : B), Equiv.toFun src✝.toEquiv (x * y) = Equiv.toFun src✝.toEquiv x * Equiv.toFun src✝.toEquiv y),
          map_add' :=
            (_ :
              ∀ (x y : B),
                Equiv.toFun src✝.toEquiv (x + y) = Equiv.toFun src✝.toEquiv x + Equiv.toFun src✝.toEquiv y) }.toEquiv
      (star b) =
    star
      (Equiv.toFun
        { toEquiv := src✝.toEquiv,
            map_mul' :=
              (_ :
                ∀ (x y : B),
                  Equiv.toFun src✝.toEquiv (x * y) = Equiv.toFun src✝.toEquiv x * Equiv.toFun src✝.toEquiv y),
            map_add' :=
              (_ :
                ∀ (x y : B),
                  Equiv.toFun src✝.toEquiv (x + y) = Equiv.toFun src✝.toEquiv x + Equiv.toFun src✝.toEquiv y) }.toEquiv
        b)

Next tactic:
simpa only [apply_inv_apply, inv_apply_apply] using
        congr_arg (inv e) (map_star e (inv e b)).symm
/-- Star algebra equivalences are symmetric. -/
@[symm]
nonrec def symm (e : A ≃⋆ₐ[R] B) : B ≃⋆ₐ[R] A :=
  { e.symm with
    map_star' := fun b => by
      simpa only [apply_inv_apply, inv_apply_apply] using
        congr_arg (inv e) (map_star e (inv e b)).symm
    map_smul' := fun r b => by
      

Proof state:
F : Type u_1
R : Type u_2
A : Type u_3
B : Type u_4
C : Type u_5
inst✝¹¹ : Add A
inst✝¹⁰ : Add B
inst✝⁹ : Mul A
inst✝⁸ : Mul B
inst✝⁷ : SMul R A
inst✝⁶ : SMul R B
inst✝⁵ : Star A
inst✝⁴ : Star B
inst✝³ : Add C
inst✝² : Mul C
inst✝¹ : SMul R C
inst✝ : Star C
e : A ≃⋆ₐ[R] B
src✝ : B ≃+* A := RingEquiv.symm e.toRingEquiv
r : R
b : B
⊢ Equiv.toFun
      { toEquiv := src✝.toEquiv,
          map_mul' :=
            (_ :
              ∀ (x y : B), Equiv.toFun src✝.toEquiv (x * y) = Equiv.toFun src✝.toEquiv x * Equiv.toFun src✝.toEquiv y),
          map_add' :=
            (_ :
              ∀ (x y : B),
                Equiv.toFun src✝.toEquiv (x + y) = Equiv.toFun src✝.toEquiv x + Equiv.toFun src✝.toEquiv y) }.toEquiv
      (r • b) =
    r •
      Equiv.toFun
        { toEquiv := src✝.toEquiv,
            map_mul' :=
              (_ :
                ∀ (x y : B),
                  Equiv.toFun src✝.toEquiv (x * y) = Equiv.toFun src✝.toEquiv x * Equiv.toFun src✝.toEquiv y),
            map_add' :=
              (_ :
                ∀ (x y : B),
                  Equiv.toFun src✝.toEquiv (x + y) = Equiv.toFun src✝.toEquiv x + Equiv.toFun src✝.toEquiv y) }.toEquiv
        b

Next tactic:
simpa only [apply_inv_apply, inv_apply_apply] using
        congr_arg (inv e) (map_smul e r (inv e b)).symm
@[simp]
theorem symm_symm (e : A ≃⋆ₐ[R] B) : e.symm.symm = e := by
  

Proof state:
F : Type u_1
R : Type u_2
A : Type u_3
B : Type u_4
C : Type u_5
inst✝¹¹ : Add A
inst✝¹⁰ : Add B
inst✝⁹ : Mul A
inst✝⁸ : Mul B
inst✝⁷ : SMul R A
inst✝⁶ : SMul R B
inst✝⁵ : Star A
inst✝⁴ : Star B
inst✝³ : Add C
inst✝² : Mul C
inst✝¹ : SMul R C
inst✝ : Star C
e : A ≃⋆ₐ[R] B
⊢ symm (symm e) = e

Next tactic:
ext
@[simp]
theorem symm_symm (e : A ≃⋆ₐ[R] B) : e.symm.symm = e := by
  ext
  

Proof state:
case h
F : Type u_1
R : Type u_2
A : Type u_3
B : Type u_4
C : Type u_5
inst✝¹¹ : Add A
inst✝¹⁰ : Add B
inst✝⁹ : Mul A
inst✝⁸ : Mul B
inst✝⁷ : SMul R A
inst✝⁶ : SMul R B
inst✝⁵ : Star A
inst✝⁴ : Star B
inst✝³ : Add C
inst✝² : Mul C
inst✝¹ : SMul R C
inst✝ : Star C
e : A ≃⋆ₐ[R] B
a✝ : A
⊢ (symm (symm e)) a✝ = e a✝

Next tactic:
rfl
/-- Star algebra equivalences are transitive. -/
@[trans]
def trans (e₁ : A ≃⋆ₐ[R] B) (e₂ : B ≃⋆ₐ[R] C) : A ≃⋆ₐ[R] C :=
  { e₁.toRingEquiv.trans
      e₂.toRingEquiv with
    map_smul' := fun r a =>
      show e₂.toFun (e₁.toFun (r • a)) = r • e₂.toFun (e₁.toFun a) by
        rw [e₁.map_smul', e₂.map_smul']
    map_star' := fun a =>
      show e₂.toFun (e₁.toFun (star a)) = star (e₂.toFun (e₁.toFun a)) by
        

Proof state:
F : Type u_1
R : Type u_2
A : Type u_3
B : Type u_4
C : Type u_5
inst✝¹¹ : Add A
inst✝¹⁰ : Add B
inst✝⁹ : Mul A
inst✝⁸ : Mul B
inst✝⁷ : SMul R A
inst✝⁶ : SMul R B
inst✝⁵ : Star A
inst✝⁴ : Star B
inst✝³ : Add C
inst✝² : Mul C
inst✝¹ : SMul R C
inst✝ : Star C
e₁ : A ≃⋆ₐ[R] B
e₂ : B ≃⋆ₐ[R] C
src✝ : A ≃+* C := RingEquiv.trans e₁.toRingEquiv e₂.toRingEquiv
a : A
⊢ Equiv.toFun e₂.toEquiv (Equiv.toFun e₁.toEquiv (star a)) = star (Equiv.toFun e₂.toEquiv (Equiv.toFun e₁.toEquiv a))

Next tactic:
rw [e₁.map_star', e₂.map_star']
/-- Star algebra equivalences are transitive. -/
@[trans]
def trans (e₁ : A ≃⋆ₐ[R] B) (e₂ : B ≃⋆ₐ[R] C) : A ≃⋆ₐ[R] C :=
  { e₁.toRingEquiv.trans
      e₂.toRingEquiv with
    map_smul' := fun r a =>
      show e₂.toFun (e₁.toFun (r • a)) = r • e₂.toFun (e₁.toFun a) by
        

Proof state:
F : Type u_1
R : Type u_2
A : Type u_3
B : Type u_4
C : Type u_5
inst✝¹¹ : Add A
inst✝¹⁰ : Add B
inst✝⁹ : Mul A
inst✝⁸ : Mul B
inst✝⁷ : SMul R A
inst✝⁶ : SMul R B
inst✝⁵ : Star A
inst✝⁴ : Star B
inst✝³ : Add C
inst✝² : Mul C
inst✝¹ : SMul R C
inst✝ : Star C
e₁ : A ≃⋆ₐ[R] B
e₂ : B ≃⋆ₐ[R] C
src✝ : A ≃+* C := RingEquiv.trans e₁.toRingEquiv e₂.toRingEquiv
r : R
a : A
⊢ Equiv.toFun e₂.toEquiv (Equiv.toFun e₁.toEquiv (r • a)) = r • Equiv.toFun e₂.toEquiv (Equiv.toFun e₁.toEquiv a)

Next tactic:
rw [e₁.map_smul', e₂.map_smul']
theorem delta_lt_false {a b : ℕ} (h₁ : delta * a < b) (h₂ : delta * b < a) : False :=
  not_le_of_lt (lt_trans ((mul_lt_mul_left (by 

Proof state:
α : Type u_1
a b : ℕ
h₁ : delta * a < b
h₂ : delta * b < a
⊢ 0 < delta

Next tactic:
decide
theorem delta_lt_false {a b : ℕ} (h₁ : delta * a < b) (h₂ : delta * b < a) : False :=
  not_le_of_lt (lt_trans ((mul_lt_mul_left (by decide)).2 h₁) h₂) <| by
    

Proof state:
α : Type u_1
a b : ℕ
h₁ : delta * a < b
h₂ : delta * b < a
⊢ a ≤ delta * (delta * a)

Next tactic:
simpa [mul_assoc] using Nat.mul_le_mul_right a (by decide : 1 ≤ delta * delta)
theorem delta_lt_false {a b : ℕ} (h₁ : delta * a < b) (h₂ : delta * b < a) : False :=
  not_le_of_lt (lt_trans ((mul_lt_mul_left (by decide)).2 h₁) h₂) <| by
    simpa [mul_assoc] using Nat.mul_le_mul_right a (by 

Proof state:
α : Type u_1
a b : ℕ
h₁ : delta * a < b
h₂ : delta * b < a
⊢ 1 ≤ delta * delta

Next tactic:
decide
theorem Sized.eq_node' {s l x r} (h : @Sized α (node s l x r)) : node s l x r = .node' l x r := by
  

Proof state:
α : Type u_1
s : ℕ
l : Ordnode α
x : α
r : Ordnode α
h : Sized (node s l x r)
⊢ node s l x r = Ordnode.node' l x r

Next tactic:
rw [h.1]
@[elab_as_elim]
theorem Sized.induction {t} (hl : @Sized α t) {C : Ordnode α → Prop} (H0 : C nil)
    (H1 : ∀ l x r, C l → C r → C (.node' l x r)) : C t := by
  

Proof state:
α : Type u_1
t : Ordnode α
hl : Sized t
C : Ordnode α → Prop
H0 : C nil
H1 : ∀ (l : Ordnode α) (x : α) (r : Ordnode α), C l → C r → C (Ordnode.node' l x r)
⊢ C t

Next tactic:
induction t with
  | nil => exact H0
  | node _ _ _ _ t_ih_l t_ih_r =>
    rw [hl.eq_node']
    exact H1 _ _ _ (t_ih_l hl.2.1) (t_ih_r hl.2.2)
@[elab_as_elim]
theorem Sized.induction {t} (hl : @Sized α t) {C : Ordnode α → Prop} (H0 : C nil)
    (H1 : ∀ l x r, C l → C r → C (.node' l x r)) : C t := by
  induction t with
  

Proof state:
case nil
α : Type u_1
C : Ordnode α → Prop
H0 : C nil
H1 : ∀ (l : Ordnode α) (x : α) (r : Ordnode α), C l → C r → C (Ordnode.node' l x r)
hl : Sized nil
⊢ C nil

Next tactic:
| nil => exact H0
@[elab_as_elim]
theorem Sized.induction {t} (hl : @Sized α t) {C : Ordnode α → Prop} (H0 : C nil)
    (H1 : ∀ l x r, C l → C r → C (.node' l x r)) : C t := by
  induction t with
  | nil => 

Proof state:
case nil
α : Type u_1
C : Ordnode α → Prop
H0 : C nil
H1 : ∀ (l : Ordnode α) (x : α) (r : Ordnode α), C l → C r → C (Ordnode.node' l x r)
hl : Sized nil
⊢ C nil

Next tactic:
exact H0
@[elab_as_elim]
theorem Sized.induction {t} (hl : @Sized α t) {C : Ordnode α → Prop} (H0 : C nil)
    (H1 : ∀ l x r, C l → C r → C (.node' l x r)) : C t := by
  induction t with
  | nil => exact H0
  

Proof state:
case node
α : Type u_1
C : Ordnode α → Prop
H0 : C nil
H1 : ∀ (l : Ordnode α) (x : α) (r : Ordnode α), C l → C r → C (Ordnode.node' l x r)
size✝ : ℕ
l✝ : Ordnode α
x✝ : α
r✝ : Ordnode α
t_ih_l : Sized l✝ → C l✝
t_ih_r : Sized r✝ → C r✝
hl : Sized (node size✝ l✝ x✝ r✝)
⊢ C (node size✝ l✝ x✝ r✝)

Next tactic:
| node _ _ _ _ t_ih_l t_ih_r =>
    rw [hl.eq_node']
    exact H1 _ _ _ (t_ih_l hl.2.1) (t_ih_r hl.2.2)
@[elab_as_elim]
theorem Sized.induction {t} (hl : @Sized α t) {C : Ordnode α → Prop} (H0 : C nil)
    (H1 : ∀ l x r, C l → C r → C (.node' l x r)) : C t := by
  induction t with
  | nil => exact H0
  | node _ _ _ _ t_ih_l t_ih_r =>
    

Proof state:
case node
α : Type u_1
C : Ordnode α → Prop
H0 : C nil
H1 : ∀ (l : Ordnode α) (x : α) (r : Ordnode α), C l → C r → C (Ordnode.node' l x r)
size✝ : ℕ
l✝ : Ordnode α
x✝ : α
r✝ : Ordnode α
t_ih_l : Sized l✝ → C l✝
t_ih_r : Sized r✝ → C r✝
hl : Sized (node size✝ l✝ x✝ r✝)
⊢ C (node size✝ l✝ x✝ r✝)

Next tactic:
rw [hl.eq_node']
@[elab_as_elim]
theorem Sized.induction {t} (hl : @Sized α t) {C : Ordnode α → Prop} (H0 : C nil)
    (H1 : ∀ l x r, C l → C r → C (.node' l x r)) : C t := by
  induction t with
  | nil => exact H0
  | node _ _ _ _ t_ih_l t_ih_r =>
    rw [hl.eq_node']
    

Proof state:
case node
α : Type u_1
C : Ordnode α → Prop
H0 : C nil
H1 : ∀ (l : Ordnode α) (x : α) (r : Ordnode α), C l → C r → C (Ordnode.node' l x r)
size✝ : ℕ
l✝ : Ordnode α
x✝ : α
r✝ : Ordnode α
t_ih_l : Sized l✝ → C l✝
t_ih_r : Sized r✝ → C r✝
hl : Sized (node size✝ l✝ x✝ r✝)
⊢ C (Ordnode.node' l✝ x✝ r✝)

Next tactic:
exact H1 _ _ _ (t_ih_l hl.2.1) (t_ih_r hl.2.2)
theorem size_eq_realSize : ∀ {t : Ordnode α}, Sized t → size t = realSize t
  | nil, _ => rfl
  | node s l x r, ⟨h₁, h₂, h₃⟩ => by
    

Proof state:
α : Type u_1
s : ℕ
l : Ordnode α
x : α
r : Ordnode α
h₁ : s = size l + size r + 1
h₂ : Sized l
h₃ : Sized r
⊢ size (node s l x r) = realSize (node s l x r)

Next tactic:
rw [size, h₁, size_eq_realSize h₂, size_eq_realSize h₃]
theorem size_eq_realSize : ∀ {t : Ordnode α}, Sized t → size t = realSize t
  | nil, _ => rfl
  | node s l x r, ⟨h₁, h₂, h₃⟩ => by
    rw [size, h₁, size_eq_realSize h₂, size_eq_realSize h₃]; 

Proof state:
α : Type u_1
s : ℕ
l : Ordnode α
x : α
r : Ordnode α
h₁ : s = size l + size r + 1
h₂ : Sized l
h₃ : Sized r
⊢ realSize l + realSize r + 1 = realSize (node (realSize l + realSize r + 1) l x r)

Next tactic:
rfl
@[simp]
theorem Sized.size_eq_zero {t : Ordnode α} (ht : Sized t) : size t = 0 ↔ t = nil := by
  

Proof state:
α : Type u_1
t : Ordnode α
ht : Sized t
⊢ size t = 0 ↔ t = nil

Next tactic:
cases t <;> [simp;simp [ht.1]]
@[simp]
theorem Sized.size_eq_zero {t : Ordnode α} (ht : Sized t) : size t = 0 ↔ t = nil := by
  

Proof state:
α : Type u_1
t : Ordnode α
ht : Sized t
⊢ size t = 0 ↔ t = nil

Next tactic:
cases t
@[simp]
theorem Sized.size_eq_zero {t : Ordnode α} (ht : Sized t) : size t = 0 ↔ t = nil := by
  cases t <;> [

Proof state:
case nil
α : Type u_1
ht : Sized nil
⊢ size nil = 0 ↔ nil = nil

Next tactic:
simp
@[simp]
theorem Sized.size_eq_zero {t : Ordnode α} (ht : Sized t) : size t = 0 ↔ t = nil := by
  cases t <;> [simp;

Proof state:
case node
α : Type u_1
size✝ : ℕ
l✝ : Ordnode α
x✝ : α
r✝ : Ordnode α
ht : Sized (node size✝ l✝ x✝ r✝)
⊢ size (node size✝ l✝ x✝ r✝) = 0 ↔ node size✝ l✝ x✝ r✝ = nil

Next tactic:
simp [ht.1]
theorem Sized.pos {s l x r} (h : Sized (@node α s l x r)) : 0 < s := by
  

Proof state:
α : Type u_1
s : ℕ
l : Ordnode α
x : α
r : Ordnode α
h : Sized (node s l x r)
⊢ 0 < s

Next tactic:
rw [h.1]
theorem Sized.pos {s l x r} (h : Sized (@node α s l x r)) : 0 < s := by
  rw [h.1]; 

Proof state:
α : Type u_1
s : ℕ
l : Ordnode α
x : α
r : Ordnode α
h : Sized (node s l x r)
⊢ 0 < size l + size r + 1

Next tactic:
apply Nat.le_add_left
theorem dual_dual : ∀ t : Ordnode α, dual (dual t) = t
  | nil => rfl
  | node s l x r => by 

Proof state:
α : Type u_1
s : ℕ
l : Ordnode α
x : α
r : Ordnode α
⊢ dual (dual (node s l x r)) = node s l x r

Next tactic:
rw [dual, dual, dual_dual l, dual_dual r]
@[simp]
theorem size_dual (t : Ordnode α) : size (dual t) = size t := by 

Proof state:
α : Type u_1
t : Ordnode α
⊢ size (dual t) = size t

Next tactic:
cases t
@[simp]
theorem size_dual (t : Ordnode α) : size (dual t) = size t := by cases t <;> 

Proof state:
case nil
α : Type u_1
⊢ size (dual nil) = size nil

Next tactic:
rfl
@[simp]
theorem size_dual (t : Ordnode α) : size (dual t) = size t := by cases t <;> 

Proof state:
case node
α : Type u_1
size✝ : ℕ
l✝ : Ordnode α
x✝ : α
r✝ : Ordnode α
⊢ size (dual (node size✝ l✝ x✝ r✝)) = size (node size✝ l✝ x✝ r✝)

Next tactic:
rfl
instance Balanced.dec : DecidablePred (@Balanced α)
  | nil => by
    

Proof state:
α : Type u_1
⊢ Decidable (Balanced nil)

Next tactic:
unfold Balanced
instance Balanced.dec : DecidablePred (@Balanced α)
  | nil => by
    unfold Balanced
    

Proof state:
α : Type u_1
⊢ Decidable True

Next tactic:
infer_instance
instance Balanced.dec : DecidablePred (@Balanced α)
  | nil => by
    unfold Balanced
    infer_instance
  | node _ l _ r => by
    

Proof state:
α : Type u_1
size✝ : ℕ
l : Ordnode α
x✝ : α
r : Ordnode α
⊢ Decidable (Balanced (node size✝ l x✝ r))

Next tactic:
unfold Balanced
instance Balanced.dec : DecidablePred (@Balanced α)
  | nil => by
    unfold Balanced
    infer_instance
  | node _ l _ r => by
    unfold Balanced
    

Proof state:
α : Type u_1
size✝ : ℕ
l : Ordnode α
x✝ : α
r : Ordnode α
⊢ Decidable (BalancedSz (size l) (size r) ∧ Balanced l ∧ Balanced r)

Next tactic:
haveI := Balanced.dec l
instance Balanced.dec : DecidablePred (@Balanced α)
  | nil => by
    unfold Balanced
    infer_instance
  | node _ l _ r => by
    unfold Balanced
    haveI := Balanced.dec l
    

Proof state:
α : Type u_1
size✝ : ℕ
l : Ordnode α
x✝ : α
r : Ordnode α
this : Decidable (Balanced l)
⊢ Decidable (BalancedSz (size l) (size r) ∧ Balanced l ∧ Balanced r)

Next tactic:
haveI := Balanced.dec r
instance Balanced.dec : DecidablePred (@Balanced α)
  | nil => by
    unfold Balanced
    infer_instance
  | node _ l _ r => by
    unfold Balanced
    haveI := Balanced.dec l
    haveI := Balanced.dec r
    

Proof state:
α : Type u_1
size✝ : ℕ
l : Ordnode α
x✝ : α
r : Ordnode α
this✝ : Decidable (Balanced l)
this : Decidable (Balanced r)
⊢ Decidable (BalancedSz (size l) (size r) ∧ Balanced l ∧ Balanced r)

Next tactic:
infer_instance
@[symm]
theorem BalancedSz.symm {l r : ℕ} : BalancedSz l r → BalancedSz r l :=
  Or.imp (by 

Proof state:
α : Type u_1
l r : ℕ
⊢ l + r ≤ 1 → r + l ≤ 1

Next tactic:
rw [add_comm]
@[symm]
theorem BalancedSz.symm {l r : ℕ} : BalancedSz l r → BalancedSz r l :=
  Or.imp (by rw [add_comm]; 

Proof state:
α : Type u_1
l r : ℕ
⊢ r + l ≤ 1 → r + l ≤ 1

Next tactic:
exact id
theorem balancedSz_zero {l : ℕ} : BalancedSz l 0 ↔ l ≤ 1 := by
  

Proof state:
α : Type u_1
l : ℕ
⊢ BalancedSz l 0 ↔ l ≤ 1

Next tactic:
simp (config := { contextual := true }) [BalancedSz]
theorem balancedSz_up {l r₁ r₂ : ℕ} (h₁ : r₁ ≤ r₂) (h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l)
    (H : BalancedSz l r₁) : BalancedSz l r₂ := by
  

Proof state:
α : Type u_1
l r₁ r₂ : ℕ
h₁ : r₁ ≤ r₂
h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l
H : BalancedSz l r₁
⊢ BalancedSz l r₂

Next tactic:
refine' or_iff_not_imp_left.2 fun h => _
theorem balancedSz_up {l r₁ r₂ : ℕ} (h₁ : r₁ ≤ r₂) (h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l)
    (H : BalancedSz l r₁) : BalancedSz l r₂ := by
  refine' or_iff_not_imp_left.2 fun h => _
  

Proof state:
α : Type u_1
l r₁ r₂ : ℕ
h₁ : r₁ ≤ r₂
h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l
H : BalancedSz l r₁
h : ¬l + r₂ ≤ 1
⊢ l ≤ delta * r₂ ∧ r₂ ≤ delta * l

Next tactic:
refine' ⟨_, h₂.resolve_left h⟩
theorem balancedSz_up {l r₁ r₂ : ℕ} (h₁ : r₁ ≤ r₂) (h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l)
    (H : BalancedSz l r₁) : BalancedSz l r₂ := by
  refine' or_iff_not_imp_left.2 fun h => _
  refine' ⟨_, h₂.resolve_left h⟩
  

Proof state:
α : Type u_1
l r₁ r₂ : ℕ
h₁ : r₁ ≤ r₂
h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l
H : BalancedSz l r₁
h : ¬l + r₂ ≤ 1
⊢ l ≤ delta * r₂

Next tactic:
cases H with
  | inl H =>
    cases r₂
    · cases h (le_trans (Nat.add_le_add_left (Nat.zero_le _) _) H)
    · exact le_trans (le_trans (Nat.le_add_right _ _) H) (Nat.le_add_left 1 _)
  | inr H =>
    exact le_trans H.1 (Nat.mul_le_mul_left _ h₁)
theorem balancedSz_up {l r₁ r₂ : ℕ} (h₁ : r₁ ≤ r₂) (h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l)
    (H : BalancedSz l r₁) : BalancedSz l r₂ := by
  refine' or_iff_not_imp_left.2 fun h => _
  refine' ⟨_, h₂.resolve_left h⟩
  cases H with
  

Proof state:
case inl
α : Type u_1
l r₁ r₂ : ℕ
h₁ : r₁ ≤ r₂
h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l
h : ¬l + r₂ ≤ 1
H : l + r₁ ≤ 1
⊢ l ≤ delta * r₂

Next tactic:
| inl H =>
    cases r₂
    · cases h (le_trans (Nat.add_le_add_left (Nat.zero_le _) _) H)
    · exact le_trans (le_trans (Nat.le_add_right _ _) H) (Nat.le_add_left 1 _)
theorem balancedSz_up {l r₁ r₂ : ℕ} (h₁ : r₁ ≤ r₂) (h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l)
    (H : BalancedSz l r₁) : BalancedSz l r₂ := by
  refine' or_iff_not_imp_left.2 fun h => _
  refine' ⟨_, h₂.resolve_left h⟩
  cases H with
  | inl H =>
    

Proof state:
case inl
α : Type u_1
l r₁ r₂ : ℕ
h₁ : r₁ ≤ r₂
h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l
h : ¬l + r₂ ≤ 1
H : l + r₁ ≤ 1
⊢ l ≤ delta * r₂

Next tactic:
cases r₂
theorem balancedSz_up {l r₁ r₂ : ℕ} (h₁ : r₁ ≤ r₂) (h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l)
    (H : BalancedSz l r₁) : BalancedSz l r₂ := by
  refine' or_iff_not_imp_left.2 fun h => _
  refine' ⟨_, h₂.resolve_left h⟩
  cases H with
  | inl H =>
    cases r₂
    · 

Proof state:
case inl.zero
α : Type u_1
l r₁ : ℕ
H : l + r₁ ≤ 1
h₁ : r₁ ≤ Nat.zero
h₂ : l + Nat.zero ≤ 1 ∨ Nat.zero ≤ delta * l
h : ¬l + Nat.zero ≤ 1
⊢ l ≤ delta * Nat.zero

Next tactic:
cases h (le_trans (Nat.add_le_add_left (Nat.zero_le _) _) H)
theorem balancedSz_up {l r₁ r₂ : ℕ} (h₁ : r₁ ≤ r₂) (h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l)
    (H : BalancedSz l r₁) : BalancedSz l r₂ := by
  refine' or_iff_not_imp_left.2 fun h => _
  refine' ⟨_, h₂.resolve_left h⟩
  cases H with
  | inl H =>
    cases r₂
    · cases h (le_trans (Nat.add_le_add_left (Nat.zero_le _) _) H)
    · 

Proof state:
case inl.succ
α : Type u_1
l r₁ : ℕ
H : l + r₁ ≤ 1
n✝ : ℕ
h₁ : r₁ ≤ Nat.succ n✝
h₂ : l + Nat.succ n✝ ≤ 1 ∨ Nat.succ n✝ ≤ delta * l
h : ¬l + Nat.succ n✝ ≤ 1
⊢ l ≤ delta * Nat.succ n✝

Next tactic:
exact le_trans (le_trans (Nat.le_add_right _ _) H) (Nat.le_add_left 1 _)
theorem balancedSz_up {l r₁ r₂ : ℕ} (h₁ : r₁ ≤ r₂) (h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l)
    (H : BalancedSz l r₁) : BalancedSz l r₂ := by
  refine' or_iff_not_imp_left.2 fun h => _
  refine' ⟨_, h₂.resolve_left h⟩
  cases H with
  | inl H =>
    cases r₂
    · cases h (le_trans (Nat.add_le_add_left (Nat.zero_le _) _) H)
    · exact le_trans (le_trans (Nat.le_add_right _ _) H) (Nat.le_add_left 1 _)
  

Proof state:
case inr
α : Type u_1
l r₁ r₂ : ℕ
h₁ : r₁ ≤ r₂
h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l
h : ¬l + r₂ ≤ 1
H : l ≤ delta * r₁ ∧ r₁ ≤ delta * l
⊢ l ≤ delta * r₂

Next tactic:
| inr H =>
    exact le_trans H.1 (Nat.mul_le_mul_left _ h₁)
theorem balancedSz_up {l r₁ r₂ : ℕ} (h₁ : r₁ ≤ r₂) (h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l)
    (H : BalancedSz l r₁) : BalancedSz l r₂ := by
  refine' or_iff_not_imp_left.2 fun h => _
  refine' ⟨_, h₂.resolve_left h⟩
  cases H with
  | inl H =>
    cases r₂
    · cases h (le_trans (Nat.add_le_add_left (Nat.zero_le _) _) H)
    · exact le_trans (le_trans (Nat.le_add_right _ _) H) (Nat.le_add_left 1 _)
  | inr H =>
    

Proof state:
case inr
α : Type u_1
l r₁ r₂ : ℕ
h₁ : r₁ ≤ r₂
h₂ : l + r₂ ≤ 1 ∨ r₂ ≤ delta * l
h : ¬l + r₂ ≤ 1
H : l ≤ delta * r₁ ∧ r₁ ≤ delta * l
⊢ l ≤ delta * r₂

Next tactic:
exact le_trans H.1 (Nat.mul_le_mul_left _ h₁)
theorem Balanced.dual : ∀ {t : Ordnode α}, Balanced t → Balanced (dual t)
  | nil, _ => ⟨⟩
  | node _ l _ r, ⟨b, bl, br⟩ => ⟨by 

Proof state:
α : Type u_1
size✝ : ℕ
l : Ordnode α
x✝ : α
r : Ordnode α
b : BalancedSz (size l) (size r)
bl : Balanced l
br : Balanced r
⊢ BalancedSz (size (Ordnode.dual r)) (size (Ordnode.dual l))

Next tactic:
rw [size_dual, size_dual]
theorem Balanced.dual : ∀ {t : Ordnode α}, Balanced t → Balanced (dual t)
  | nil, _ => ⟨⟩
  | node _ l _ r, ⟨b, bl, br⟩ => ⟨by rw [size_dual, size_dual]; 

Proof state:
α : Type u_1
size✝ : ℕ
l : Ordnode α
x✝ : α
r : Ordnode α
b : BalancedSz (size l) (size r)
bl : Balanced l
br : Balanced r
⊢ BalancedSz (size r) (size l)

Next tactic:
exact b.symm
theorem dual_node' (l : Ordnode α) (x : α) (r : Ordnode α) :
    dual (node' l x r) = node' (dual r) x (dual l) := by 

Proof state:
α : Type u_1
l : Ordnode α
x : α
r : Ordnode α
⊢ dual (node' l x r) = node' (dual r) x (dual l)

Next tactic:
simp [node', add_comm]
theorem dual_node3L (l : Ordnode α) (x : α) (m : Ordnode α) (y : α) (r : Ordnode α) :
    dual (node3L l x m y r) = node3R (dual r) y (dual m) x (dual l) := by
  

Proof state:
α : Type u_1
l : Ordnode α
x : α
m : Ordnode α
y : α
r : Ordnode α
⊢ dual (node3L l x m y r) = node3R (dual r) y (dual m) x (dual l)

Next tactic:
simp [node3L, node3R, dual_node', add_comm]