-- Mathlib/.lake/packages/lean4/src/lean/Init/Data/Nat/Linear.lean
theorem Poly.denote_eq_cancelAux (ctx : Context) (fuel : Nat) (m₁ m₂ r₁ r₂ : Poly)
    (h : denote_eq ctx (r₁.reverse ++ m₁, r₂.reverse ++ m₂)) : denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)

Proof state:
case pos
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ : List (Nat × Var)
k₂ : Nat
m₂ : List (Nat × Var)
h : denote_eq ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)
hltv hgtv : ¬blt v₁ v₁ = true
hltk : k₁.blt k₂ = true
⊢ denote_eq ctx (cancelAux fuel m₁ m₂ r₁ ((k₂ - k₁, v₁) :: r₂))

Tactic:
apply ih

Result:
case pos.h
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ : List (Nat × Var)
k₂ : Nat
m₂ : List (Nat × Var)
h : denote_eq ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)
hltv hgtv : ¬blt v₁ v₁ = true
hltk : k₁.blt k₂ = true
⊢ denote_eq ctx (List.reverse r₁ ++ m₁, ((k₂ - k₁, v₁) :: r₂).reverse ++ m₂)

Proof state:
case zero
ctx : Context
m₁ m₂ r₁ r₂ : Poly
h : denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂)
⊢ denote_eq ctx (cancelAux 0 m₁ m₂ r₁ r₂)

Tactic:
assumption

Result:
no goals

Proof state:
case neg.h
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ m₂ : List (Nat × Var)
hltv hgtv : ¬blt v₁ v₁ = true
hltk hgtk : ¬k₁.blt k₁ = true
h : denote ctx r₁ + (denote ctx m₁ + k₁ * Var.denote ctx v₁) = denote ctx r₂ + (denote ctx m₂ + k₁ * Var.denote ctx v₁)
⊢ denote ctx r₁ + denote ctx m₁ = denote ctx r₂ + denote ctx m₂

Tactic:
rw [← Nat.add_assoc, ← Nat.add_assoc] at h

Result:
case neg.h
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ m₂ : List (Nat × Var)
hltv hgtv : ¬blt v₁ v₁ = true
hltk hgtk : ¬k₁.blt k₁ = true
h : denote ctx r₁ + denote ctx m₁ + k₁ * Var.denote ctx v₁ = denote ctx r₂ + denote ctx m₂ + k₁ * Var.denote ctx v₁
⊢ denote ctx r₁ + denote ctx m₁ = denote ctx r₂ + denote ctx m₂

Proof state:
case neg
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ : List (Nat × Var)
k₂ : Nat
v₂ : Var
m₂ : List (Nat × Var)
h : denote_eq ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₂) :: m₂)
hltv : ¬blt v₁ v₂ = true
hgtv : ¬blt v₂ v₁ = true
⊢ denote_eq ctx
    (bif k₁.blt k₂ then cancelAux fuel m₁ m₂ r₁ ((k₂ - k₁, v₁) :: r₂)
    else bif k₂.blt k₁ then cancelAux fuel m₁ m₂ ((k₁ - k₂, v₁) :: r₁) r₂ else cancelAux fuel m₁ m₂ r₁ r₂)

Tactic:
have heqv : v₁ = v₂ := eq_of_not_blt_eq_true hltv hgtv

Result:
case neg
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ : List (Nat × Var)
k₂ : Nat
v₂ : Var
m₂ : List (Nat × Var)
h : denote_eq ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₂) :: m₂)
hltv : ¬blt v₁ v₂ = true
hgtv : ¬blt v₂ v₁ = true
heqv : v₁ = v₂
⊢ denote_eq ctx
    (bif k₁.blt k₂ then cancelAux fuel m₁ m₂ r₁ ((k₂ - k₁, v₁) :: r₂)
    else bif k₂.blt k₁ then cancelAux fuel m₁ m₂ ((k₁ - k₂, v₁) :: r₁) r₂ else cancelAux fuel m₁ m₂ r₁ r₂)

Proof state:
case pos.h
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ : List (Nat × Var)
k₂ : Nat
m₂ : List (Nat × Var)
hltv hgtv : ¬blt v₁ v₁ = true
hltk : k₁.blt k₂ = true
h : denote ctx r₁ + (denote ctx m₁ + k₁ * Var.denote ctx v₁) = denote ctx r₂ + (denote ctx m₂ + k₂ * Var.denote ctx v₁)
haux : k₁ * Var.denote ctx v₁ ≤ k₂ * Var.denote ctx v₁
⊢ denote ctx r₁ + denote ctx m₁ = denote ctx r₂ + denote ctx m₂ + k₂ * Var.denote ctx v₁ - k₁ * Var.denote ctx v₁

Tactic:
apply Eq.symm

Result:
case pos.h.h
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ : List (Nat × Var)
k₂ : Nat
m₂ : List (Nat × Var)
hltv hgtv : ¬blt v₁ v₁ = true
hltk : k₁.blt k₂ = true
h : denote ctx r₁ + (denote ctx m₁ + k₁ * Var.denote ctx v₁) = denote ctx r₂ + (denote ctx m₂ + k₂ * Var.denote ctx v₁)
haux : k₁ * Var.denote ctx v₁ ≤ k₂ * Var.denote ctx v₁
⊢ denote ctx r₂ + denote ctx m₂ + k₂ * Var.denote ctx v₁ - k₁ * Var.denote ctx v₁ = denote ctx r₁ + denote ctx m₁

Proof state:
case pos
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ : List (Nat × Var)
k₂ : Nat
m₂ : List (Nat × Var)
h : denote_eq ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)
hltv hgtv : ¬blt v₁ v₁ = true
hltk : ¬k₁.blt k₂ = true
hgtk : k₂.blt k₁ = true
⊢ denote_eq ctx (cancelAux fuel m₁ m₂ ((k₁ - k₂, v₁) :: r₁) r₂)

Tactic:
apply ih

Result:
case pos.h
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ : List (Nat × Var)
k₂ : Nat
m₂ : List (Nat × Var)
h : denote_eq ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)
hltv hgtv : ¬blt v₁ v₁ = true
hltk : ¬k₁.blt k₂ = true
hgtk : k₂.blt k₁ = true
⊢ denote_eq ctx (((k₁ - k₂, v₁) :: r₁).reverse ++ m₁, List.reverse r₂ ++ m₂)

Proof state:
case neg
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ : List (Nat × Var)
k₂ : Nat
m₂ : List (Nat × Var)
h : denote_eq ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)
hltv hgtv : ¬blt v₁ v₁ = true
⊢ denote_eq ctx
    (bif k₁.blt k₂ then cancelAux fuel m₁ m₂ r₁ ((k₂ - k₁, v₁) :: r₂)
    else bif k₂.blt k₁ then cancelAux fuel m₁ m₂ ((k₁ - k₂, v₁) :: r₁) r₂ else cancelAux fuel m₁ m₂ r₁ r₂)

Tactic:
by_cases hltk : Nat.blt k₁ k₂ <;> simp [hltk]

Result:
case pos
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ : List (Nat × Var)
k₂ : Nat
m₂ : List (Nat × Var)
h : denote_eq ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)
hltv hgtv : ¬blt v₁ v₁ = true
hltk : k₁.blt k₂ = true
⊢ denote_eq ctx (cancelAux fuel m₁ m₂ r₁ ((k₂ - k₁, v₁) :: r₂))

case neg
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_eq ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂) → denote_eq ctx (cancelAux fuel m₁ m₂ r₁ r₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ : List (Nat × Var)
k₂ : Nat
m₂ : List (Nat × Var)
h : denote_eq ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)
hltv hgtv : ¬blt v₁ v₁ = true
hltk : ¬k₁.blt k₂ = true
⊢ denote_eq ctx (bif k₂.blt k₁ then cancelAux fuel m₁ m₂ ((k₁ - k₂, v₁) :: r₁) r₂ else cancelAux fuel m₁ m₂ r₁ r₂)