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

Proof state:
case neg
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_le ctx (cancelAux fuel m₁ m₂ r₁ r₂) → denote_le ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂)
r₁ r₂ m₁✝ m₂✝ : Poly
k₁ : Nat
v₁ : Var
m₁ : List (Nat × Var)
k₂ : Nat
m₂ : List (Nat × Var)
h :
  denote_le 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₂)
hltv hgtv : ¬blt v₁ v₁ = true
⊢ denote_le ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)

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

Result:
case pos
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_le ctx (cancelAux fuel m₁ m₂ r₁ r₂) → denote_le ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂)
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_le ctx (cancelAux fuel m₁ m₂ r₁ ((k₂ - k₁, v₁) :: r₂))
⊢ denote_le ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)

case neg
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_le ctx (cancelAux fuel m₁ m₂ r₁ r₂) → denote_le ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂)
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_le ctx (bif k₂.blt k₁ then cancelAux fuel m₁ m₂ ((k₁ - k₂, v₁) :: r₁) r₂ else cancelAux fuel m₁ m₂ r₁ r₂)
⊢ denote_le ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)

Proof state:
case succ
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_le ctx (cancelAux fuel m₁ m₂ r₁ r₂) → denote_le ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂)
m₁ m₂ r₁ r₂ : Poly
h :
  denote_le ctx
    (match m₁, m₂ with
    | m₁, [] => (List.reverse r₁ ++ m₁, List.reverse r₂)
    | [], m₂ => (List.reverse r₁, List.reverse r₂ ++ m₂)
    | (k₁, v₁) :: m₁, (k₂, v₂) :: m₂ =>
      bif blt v₁ v₂ then cancelAux fuel m₁ ((k₂, v₂) :: m₂) ((k₁, v₁) :: r₁) r₂
      else
        bif blt v₂ v₁ then cancelAux fuel ((k₁, v₁) :: m₁) m₂ r₁ ((k₂, v₂) :: r₂)
        else
          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₂)
⊢ denote_le ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂)

Tactic:
split at h <;> try (simp; assumption)

Result:
case succ.h_3
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_le ctx (cancelAux fuel m₁ m₂ r₁ r₂) → denote_le ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂)
r₁ r₂ m₁✝¹ m₂✝¹ : Poly
k₁✝ : Nat
v₁✝ : Var
m₁✝ : List (Nat × Var)
k₂✝ : Nat
v₂✝ : Var
m₂✝ : List (Nat × Var)
h :
  denote_le ctx
    (bif blt v₁✝ v₂✝ then cancelAux fuel m₁✝ ((k₂✝, v₂✝) :: m₂✝) ((k₁✝, v₁✝) :: r₁) r₂
    else
      bif blt v₂✝ v₁✝ then cancelAux fuel ((k₁✝, v₁✝) :: m₁✝) m₂✝ r₁ ((k₂✝, v₂✝) :: r₂)
      else
        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₂)
⊢ denote_le ctx (List.reverse r₁ ++ (k₁✝, v₁✝) :: m₁✝, List.reverse r₂ ++ (k₂✝, v₂✝) :: m₂✝)

Proof state:
case neg
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_le ctx (cancelAux fuel m₁ m₂ r₁ r₂) → denote_le ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂)
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_le ctx (bif k₂.blt k₁ then cancelAux fuel m₁ m₂ ((k₁ - k₂, v₁) :: r₁) r₂ else cancelAux fuel m₁ m₂ r₁ r₂)
⊢ denote_le ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)

Tactic:
by_cases hgtk : Nat.blt k₂ k₁ <;> simp [hgtk] at h

Result:
case pos
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_le ctx (cancelAux fuel m₁ m₂ r₁ r₂) → denote_le ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂)
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
hgtk : k₂.blt k₁ = true
h : denote_le ctx (cancelAux fuel m₁ m₂ ((k₁ - k₂, v₁) :: r₁) r₂)
⊢ denote_le ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)

case neg
ctx : Context
fuel : Nat
ih :
  ∀ (m₁ m₂ r₁ r₂ : Poly),
    denote_le ctx (cancelAux fuel m₁ m₂ r₁ r₂) → denote_le ctx (List.reverse r₁ ++ m₁, List.reverse r₂ ++ m₂)
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
hgtk : ¬k₂.blt k₁ = true
h : denote_le ctx (cancelAux fuel m₁ m₂ r₁ r₂)
⊢ denote_le ctx (List.reverse r₁ ++ (k₁, v₁) :: m₁, List.reverse r₂ ++ (k₂, v₁) :: m₂)