l3lab/ntp-mathlib huggingface dataset:
theorem gcd_props :
    let d := gcdD a b
    let w := gcdW a b
    let x := gcdX a b
    let y := gcdY a b
    let z := gcdZ a b
    let a' := gcdA' a b
    let b' := gcdB' a b
    w * z = succPNat (x * y) ∧
      a = a' * d ∧
        b = b' * d ∧
          z * a' = succPNat (x * b') ∧
            w * b' = succPNat (y * a') ∧ (z * a : ℕ) = x * b + d ∧ (w * b : ℕ) = y * a + d := by
  intros d w x y z a' b'
  let u := XgcdType.start a b
  let ur := u.reduce

  have _ : d = ur.a := rfl
  have hb : d = ur.b := u.reduce_isReduced'
  have ha' : (a' : ℕ) = w + x := gcdA'_coe a b
  have hb' : (b' : ℕ) = y + z := gcdB'_coe a b
  have hdet : w * z = succPNat (x * y) := u.reduce_isSpecial' rfl
  constructor
  exact hdet
  have hdet' : (w * z : ℕ) = x * y + 1 := by rw [← mul_coe, hdet, succPNat_coe]
  have _ : u.v = ⟨a, b⟩ := XgcdType.start_v a b
  let hv : Prod.mk (w * d + x * ur.b : ℕ) (y * d + z * ur.b : ℕ) = ⟨a, b⟩ :=
    u.reduce_v.trans (XgcdType.start_v a b)
  rw [← hb, ← add_mul, ← add_mul, ← ha', ← hb'] at hv
  have ha'' : (a : ℕ) = a' * d := (congr_arg Prod.fst hv).symm
  have hb'' : (b : ℕ) = b' * d := (congr_arg Prod.snd hv).symm
  constructor
  exact eq ha''
  constructor
  exact eq hb''
  have hza' : (z * a' : ℕ) = x * b' + 1 := by
    rw [ha', hb', mul_add, mul_add, mul_comm (z : ℕ), hdet']
    ring
  have hwb' : (w * b' : ℕ) = y * a' + 1 := by
    rw [ha', hb', mul_add, mul_add, hdet']
    ring
  constructor
  · apply eq
    rw [succPNat_coe, Nat.succ_eq_add_one, mul_coe, hza']
  constructor
  · apply eq
    rw [succPNat_coe, Nat.succ_eq_add_one, mul_coe, hwb']
  rw [ha'', hb'']
  repeat' 

Proof state:
case right.right.right.right.right
a b : ℕ+
d : ℕ+ := gcdD a b
w : ℕ+ := gcdW a b
x : ℕ := gcdX a b
y : ℕ := gcdY a b
z : ℕ+ := gcdZ a b
a' : ℕ+ := gcdA' a b
b' : ℕ+ := gcdB' a b
u : XgcdType := XgcdType.start a b
ur : XgcdType := XgcdType.reduce u
x✝¹ : d = XgcdType.a ur
hb : d = XgcdType.b ur
ha' : ↑a' = ↑w + x
hb' : ↑b' = y + ↑z
hdet : w * z = succPNat (x * y)
hdet' : ↑w * ↑z = x * y + 1
x✝ : XgcdType.v u = (↑a, ↑b)
hv : (↑a' * ↑d, ↑b' * ↑d) = (↑a, ↑b)
ha'' : ↑a = ↑a' * ↑d
hb'' : ↑b = ↑b' * ↑d
hza' : ↑z * ↑a' = x * ↑b' + 1
hwb' : ↑w * ↑b' = y * ↑a' + 1
⊢ ↑z * ↑a' * ↑d = x * ↑b' * ↑d + ↑d ∧ ↑w * ↑b' * ↑d = y * ↑a' * ↑d + ↑d

Next tactic:
rw [← @mul_assoc]
theorem gcd_props :
    let d := gcdD a b
    let w := gcdW a b
    let x := gcdX a b
    let y := gcdY a b
    let z := gcdZ a b
    let a' := gcdA' a b
    let b' := gcdB' a b
    w * z = succPNat (x * y) ∧
      a = a' * d ∧
        b = b' * d ∧
          z * a' = succPNat (x * b') ∧
            w * b' = succPNat (y * a') ∧ (z * a : ℕ) = x * b + d ∧ (w * b : ℕ) = y * a + d := by
  intros d w x y z a' b'
  let u := XgcdType.start a b
  let ur := u.reduce

  have _ : d = ur.a := rfl
  have hb : d = ur.b := u.reduce_isReduced'
  have ha' : (a' : ℕ) = w + x := gcdA'_coe a b
  have hb' : (b' : ℕ) = y + z := gcdB'_coe a b
  have hdet : w * z = succPNat (x * y) := u.reduce_isSpecial' rfl
  constructor
  exact hdet
  have hdet' : (w * z : ℕ) = x * y + 1 := by rw [← mul_coe, hdet, succPNat_coe]
  have _ : u.v = ⟨a, b⟩ := XgcdType.start_v a b
  let hv : Prod.mk (w * d + x * ur.b : ℕ) (y * d + z * ur.b : ℕ) = ⟨a, b⟩ :=
    u.reduce_v.trans (XgcdType.start_v a b)
  rw [← hb, ← add_mul, ← add_mul, ← ha', ← hb'] at hv
  have ha'' : (a : ℕ) = a' * d := (congr_arg Prod.fst hv).symm
  have hb'' : (b : ℕ) = b' * d := (congr_arg Prod.snd hv).symm
  constructor
  exact eq ha''
  constructor
  exact eq hb''
  have hza' : (z * a' : ℕ) = x * b' + 1 := by
    rw [ha', hb', mul_add, mul_add, mul_comm (z : ℕ), hdet']
    ring
  have hwb' : (w * b' : ℕ) = y * a' + 1 := by
    rw [ha', hb', mul_add, mul_add, hdet']
    ring
  constructor
  · apply eq
    rw [succPNat_coe, Nat.succ_eq_add_one, mul_coe, hza']
  constructor
  · apply eq
    rw [succPNat_coe, Nat.succ_eq_add_one, mul_coe, hwb']
  rw [ha'', hb'']
  repeat' rw [← @mul_assoc]
  

Proof state:
case right.right.right.right.right
a b : ℕ+
d : ℕ+ := gcdD a b
w : ℕ+ := gcdW a b
x : ℕ := gcdX a b
y : ℕ := gcdY a b
z : ℕ+ := gcdZ a b
a' : ℕ+ := gcdA' a b
b' : ℕ+ := gcdB' a b
u : XgcdType := XgcdType.start a b
ur : XgcdType := XgcdType.reduce u
x✝¹ : d = XgcdType.a ur
hb : d = XgcdType.b ur
ha' : ↑a' = ↑w + x
hb' : ↑b' = y + ↑z
hdet : w * z = succPNat (x * y)
hdet' : ↑w * ↑z = x * y + 1
x✝ : XgcdType.v u = (↑a, ↑b)
hv : (↑a' * ↑d, ↑b' * ↑d) = (↑a, ↑b)
ha'' : ↑a = ↑a' * ↑d
hb'' : ↑b = ↑b' * ↑d
hza' : ↑z * ↑a' = x * ↑b' + 1
hwb' : ↑w * ↑b' = y * ↑a' + 1
⊢ ↑z * ↑a' * ↑d = x * ↑b' * ↑d + ↑d ∧ ↑w * ↑b' * ↑d = y * ↑a' * ↑d + ↑d

Next tactic:
rw [hza', hwb']
theorem gcd_props :
    let d := gcdD a b
    let w := gcdW a b
    let x := gcdX a b
    let y := gcdY a b
    let z := gcdZ a b
    let a' := gcdA' a b
    let b' := gcdB' a b
    w * z = succPNat (x * y) ∧
      a = a' * d ∧
        b = b' * d ∧
          z * a' = succPNat (x * b') ∧
            w * b' = succPNat (y * a') ∧ (z * a : ℕ) = x * b + d ∧ (w * b : ℕ) = y * a + d := by
  intros d w x y z a' b'
  let u := XgcdType.start a b
  let ur := u.reduce

  have _ : d = ur.a := rfl
  have hb : d = ur.b := u.reduce_isReduced'
  have ha' : (a' : ℕ) = w + x := gcdA'_coe a b
  have hb' : (b' : ℕ) = y + z := gcdB'_coe a b
  have hdet : w * z = succPNat (x * y) := u.reduce_isSpecial' rfl
  constructor
  exact hdet
  have hdet' : (w * z : ℕ) = x * y + 1 := by rw [← mul_coe, hdet, succPNat_coe]
  have _ : u.v = ⟨a, b⟩ := XgcdType.start_v a b
  let hv : Prod.mk (w * d + x * ur.b : ℕ) (y * d + z * ur.b : ℕ) = ⟨a, b⟩ :=
    u.reduce_v.trans (XgcdType.start_v a b)
  rw [← hb, ← add_mul, ← add_mul, ← ha', ← hb'] at hv
  have ha'' : (a : ℕ) = a' * d := (congr_arg Prod.fst hv).symm
  have hb'' : (b : ℕ) = b' * d := (congr_arg Prod.snd hv).symm
  constructor
  exact eq ha''
  constructor
  exact eq hb''
  have hza' : (z * a' : ℕ) = x * b' + 1 := by
    rw [ha', hb', mul_add, mul_add, mul_comm (z : ℕ), hdet']
    ring
  have hwb' : (w * b' : ℕ) = y * a' + 1 := by
    rw [ha', hb', mul_add, mul_add, hdet']
    ring
  constructor
  · apply eq
    rw [succPNat_coe, Nat.succ_eq_add_one, mul_coe, hza']
  constructor
  · apply eq
    rw [succPNat_coe, Nat.succ_eq_add_one, mul_coe, hwb']
  rw [ha'', hb'']
  repeat' rw [← @mul_assoc]
  rw [hza', hwb']
  

Proof state:
case right.right.right.right.right
a b : ℕ+
d : ℕ+ := gcdD a b
w : ℕ+ := gcdW a b
x : ℕ := gcdX a b
y : ℕ := gcdY a b
z : ℕ+ := gcdZ a b
a' : ℕ+ := gcdA' a b
b' : ℕ+ := gcdB' a b
u : XgcdType := XgcdType.start a b
ur : XgcdType := XgcdType.reduce u
x✝¹ : d = XgcdType.a ur
hb : d = XgcdType.b ur
ha' : ↑a' = ↑w + x
hb' : ↑b' = y + ↑z
hdet : w * z = succPNat (x * y)
hdet' : ↑w * ↑z = x * y + 1
x✝ : XgcdType.v u = (↑a, ↑b)
hv : (↑a' * ↑d, ↑b' * ↑d) = (↑a, ↑b)
ha'' : ↑a = ↑a' * ↑d
hb'' : ↑b = ↑b' * ↑d
hza' : ↑z * ↑a' = x * ↑b' + 1
hwb' : ↑w * ↑b' = y * ↑a' + 1
⊢ (x * ↑b' + 1) * ↑d = x * ↑b' * ↑d + ↑d ∧ (y * ↑a' + 1) * ↑d = y * ↑a' * ↑d + ↑d

Next tactic:
constructor
theorem gcd_props :
    let d := gcdD a b
    let w := gcdW a b
    let x := gcdX a b
    let y := gcdY a b
    let z := gcdZ a b
    let a' := gcdA' a b
    let b' := gcdB' a b
    w * z = succPNat (x * y) ∧
      a = a' * d ∧
        b = b' * d ∧
          z * a' = succPNat (x * b') ∧
            w * b' = succPNat (y * a') ∧ (z * a : ℕ) = x * b + d ∧ (w * b : ℕ) = y * a + d := by
  intros d w x y z a' b'
  let u := XgcdType.start a b
  let ur := u.reduce

  have _ : d = ur.a := rfl
  have hb : d = ur.b := u.reduce_isReduced'
  have ha' : (a' : ℕ) = w + x := gcdA'_coe a b
  have hb' : (b' : ℕ) = y + z := gcdB'_coe a b
  have hdet : w * z = succPNat (x * y) := u.reduce_isSpecial' rfl
  constructor
  exact hdet
  have hdet' : (w * z : ℕ) = x * y + 1 := by rw [← mul_coe, hdet, succPNat_coe]
  have _ : u.v = ⟨a, b⟩ := XgcdType.start_v a b
  let hv : Prod.mk (w * d + x * ur.b : ℕ) (y * d + z * ur.b : ℕ) = ⟨a, b⟩ :=
    u.reduce_v.trans (XgcdType.start_v a b)
  rw [← hb, ← add_mul, ← add_mul, ← ha', ← hb'] at hv
  have ha'' : (a : ℕ) = a' * d := (congr_arg Prod.fst hv).symm
  have hb'' : (b : ℕ) = b' * d := (congr_arg Prod.snd hv).symm
  constructor
  exact eq ha''
  constructor
  exact eq hb''
  have hza' : (z * a' : ℕ) = x * b' + 1 := by
    rw [ha', hb', mul_add, mul_add, mul_comm (z : ℕ), hdet']
    ring
  have hwb' : (w * b' : ℕ) = y * a' + 1 := by
    rw [ha', hb', mul_add, mul_add, hdet']
    ring
  constructor
  · apply eq
    rw [succPNat_coe, Nat.succ_eq_add_one, mul_coe, hza']
  constructor
  · apply eq
    rw [succPNat_coe, Nat.succ_eq_add_one, mul_coe, hwb']
  rw [ha'', hb'']
  repeat' rw [← @mul_assoc]
  rw [hza', hwb']
  constructor <;> 

Proof state:
case right.right.right.right.right.left
a b : ℕ+
d : ℕ+ := gcdD a b
w : ℕ+ := gcdW a b
x : ℕ := gcdX a b
y : ℕ := gcdY a b
z : ℕ+ := gcdZ a b
a' : ℕ+ := gcdA' a b
b' : ℕ+ := gcdB' a b
u : XgcdType := XgcdType.start a b
ur : XgcdType := XgcdType.reduce u
x✝¹ : d = XgcdType.a ur
hb : d = XgcdType.b ur
ha' : ↑a' = ↑w + x
hb' : ↑b' = y + ↑z
hdet : w * z = succPNat (x * y)
hdet' : ↑w * ↑z = x * y + 1
x✝ : XgcdType.v u = (↑a, ↑b)
hv : (↑a' * ↑d, ↑b' * ↑d) = (↑a, ↑b)
ha'' : ↑a = ↑a' * ↑d
hb'' : ↑b = ↑b' * ↑d
hza' : ↑z * ↑a' = x * ↑b' + 1
hwb' : ↑w * ↑b' = y * ↑a' + 1
⊢ (x * ↑b' + 1) * ↑d = x * ↑b' * ↑d + ↑d

Next tactic:
ring
theorem gcd_props :
    let d := gcdD a b
    let w := gcdW a b
    let x := gcdX a b
    let y := gcdY a b
    let z := gcdZ a b
    let a' := gcdA' a b
    let b' := gcdB' a b
    w * z = succPNat (x * y) ∧
      a = a' * d ∧
        b = b' * d ∧
          z * a' = succPNat (x * b') ∧
            w * b' = succPNat (y * a') ∧ (z * a : ℕ) = x * b + d ∧ (w * b : ℕ) = y * a + d := by
  intros d w x y z a' b'
  let u := XgcdType.start a b
  let ur := u.reduce

  have _ : d = ur.a := rfl
  have hb : d = ur.b := u.reduce_isReduced'
  have ha' : (a' : ℕ) = w + x := gcdA'_coe a b
  have hb' : (b' : ℕ) = y + z := gcdB'_coe a b
  have hdet : w * z = succPNat (x * y) := u.reduce_isSpecial' rfl
  constructor
  exact hdet
  have hdet' : (w * z : ℕ) = x * y + 1 := by rw [← mul_coe, hdet, succPNat_coe]
  have _ : u.v = ⟨a, b⟩ := XgcdType.start_v a b
  let hv : Prod.mk (w * d + x * ur.b : ℕ) (y * d + z * ur.b : ℕ) = ⟨a, b⟩ :=
    u.reduce_v.trans (XgcdType.start_v a b)
  rw [← hb, ← add_mul, ← add_mul, ← ha', ← hb'] at hv
  have ha'' : (a : ℕ) = a' * d := (congr_arg Prod.fst hv).symm
  have hb'' : (b : ℕ) = b' * d := (congr_arg Prod.snd hv).symm
  constructor
  exact eq ha''
  constructor
  exact eq hb''
  have hza' : (z * a' : ℕ) = x * b' + 1 := by
    rw [ha', hb', mul_add, mul_add, mul_comm (z : ℕ), hdet']
    ring
  have hwb' : (w * b' : ℕ) = y * a' + 1 := by
    rw [ha', hb', mul_add, mul_add, hdet']
    ring
  constructor
  · apply eq
    rw [succPNat_coe, Nat.succ_eq_add_one, mul_coe, hza']
  constructor
  · apply eq
    rw [succPNat_coe, Nat.succ_eq_add_one, mul_coe, hwb']
  rw [ha'', hb'']
  repeat' rw [← @mul_assoc]
  rw [hza', hwb']
  constructor <;> 

Proof state:
case right.right.right.right.right.right
a b : ℕ+
d : ℕ+ := gcdD a b
w : ℕ+ := gcdW a b
x : ℕ := gcdX a b
y : ℕ := gcdY a b
z : ℕ+ := gcdZ a b
a' : ℕ+ := gcdA' a b
b' : ℕ+ := gcdB' a b
u : XgcdType := XgcdType.start a b
ur : XgcdType := XgcdType.reduce u
x✝¹ : d = XgcdType.a ur
hb : d = XgcdType.b ur
ha' : ↑a' = ↑w + x
hb' : ↑b' = y + ↑z
hdet : w * z = succPNat (x * y)
hdet' : ↑w * ↑z = x * y + 1
x✝ : XgcdType.v u = (↑a, ↑b)
hv : (↑a' * ↑d, ↑b' * ↑d) = (↑a, ↑b)
ha'' : ↑a = ↑a' * ↑d
hb'' : ↑b = ↑b' * ↑d
hza' : ↑z * ↑a' = x * ↑b' + 1
hwb' : ↑w * ↑b' = y * ↑a' + 1
⊢ (y * ↑a' + 1) * ↑d = y * ↑a' * ↑d + ↑d

Next tactic:
ring
theorem gcd_eq : gcdD a b = gcd a b := by
  

Proof state:
a b : ℕ+
⊢ gcdD a b = gcd a b

Next tactic:
rcases gcd_props a b with ⟨_, h₁, h₂, _, _, h₅, _⟩
theorem gcd_eq : gcdD a b = gcd a b := by
  rcases gcd_props a b with ⟨_, h₁, h₂, _, _, h₅, _⟩
  

Proof state:
case intro.intro.intro.intro.intro.intro
a b : ℕ+
left✝² : gcdW a b * gcdZ a b = succPNat (gcdX a b * gcdY a b)
h₁ : a = gcdA' a b * gcdD a b
h₂ : b = gcdB' a b * gcdD a b
left✝¹ : gcdZ a b * gcdA' a b = succPNat (gcdX a b * ↑(gcdB' a b))
left✝ : gcdW a b * gcdB' a b = succPNat (gcdY a b * ↑(gcdA' a b))
h₅ : ↑(gcdZ a b) * ↑a = gcdX a b * ↑b + ↑(gcdD a b)
right✝ : ↑(gcdW a b) * ↑b = gcdY a b * ↑a + ↑(gcdD a b)
⊢ gcdD a b = gcd a b

Next tactic:
apply dvd_antisymm
theorem gcd_eq : gcdD a b = gcd a b := by
  rcases gcd_props a b with ⟨_, h₁, h₂, _, _, h₅, _⟩
  apply dvd_antisymm
  · 

Proof state:
case intro.intro.intro.intro.intro.intro.a
a b : ℕ+
left✝² : gcdW a b * gcdZ a b = succPNat (gcdX a b * gcdY a b)
h₁ : a = gcdA' a b * gcdD a b
h₂ : b = gcdB' a b * gcdD a b
left✝¹ : gcdZ a b * gcdA' a b = succPNat (gcdX a b * ↑(gcdB' a b))
left✝ : gcdW a b * gcdB' a b = succPNat (gcdY a b * ↑(gcdA' a b))
h₅ : ↑(gcdZ a b) * ↑a = gcdX a b * ↑b + ↑(gcdD a b)
right✝ : ↑(gcdW a b) * ↑b = gcdY a b * ↑a + ↑(gcdD a b)
⊢ gcdD a b ∣ gcd a b

Next tactic:
apply dvd_gcd
theorem gcd_eq : gcdD a b = gcd a b := by
  rcases gcd_props a b with ⟨_, h₁, h₂, _, _, h₅, _⟩
  apply dvd_antisymm
  · apply dvd_gcd
    

Proof state:
case intro.intro.intro.intro.intro.intro.a.hm
a b : ℕ+
left✝² : gcdW a b * gcdZ a b = succPNat (gcdX a b * gcdY a b)
h₁ : a = gcdA' a b * gcdD a b
h₂ : b = gcdB' a b * gcdD a b
left✝¹ : gcdZ a b * gcdA' a b = succPNat (gcdX a b * ↑(gcdB' a b))
left✝ : gcdW a b * gcdB' a b = succPNat (gcdY a b * ↑(gcdA' a b))
h₅ : ↑(gcdZ a b) * ↑a = gcdX a b * ↑b + ↑(gcdD a b)
right✝ : ↑(gcdW a b) * ↑b = gcdY a b * ↑a + ↑(gcdD a b)
⊢ gcdD a b ∣ a
case intro.intro.intro.intro.intro.intro.a.hn
a b : ℕ+
left✝² : gcdW a b * gcdZ a b = succPNat (gcdX a b * gcdY a b)
h₁ : a = gcdA' a b * gcdD a b
h₂ : b = gcdB' a b * gcdD a b
left✝¹ : gcdZ a b * gcdA' a b = succPNat (gcdX a b * ↑(gcdB' a b))
left✝ : gcdW a b * gcdB' a b = succPNat (gcdY a b * ↑(gcdA' a b))
h₅ : ↑(gcdZ a b) * ↑a = gcdX a b * ↑b + ↑(gcdD a b)
right✝ : ↑(gcdW a b) * ↑b = gcdY a b * ↑a + ↑(gcdD a b)
⊢ gcdD a b ∣ b

Next tactic:
exact Dvd.intro (gcdA' a b) (h₁.trans (mul_comm _ _)).symm
theorem gcd_eq : gcdD a b = gcd a b := by
  rcases gcd_props a b with ⟨_, h₁, h₂, _, _, h₅, _⟩
  apply dvd_antisymm
  · apply dvd_gcd
    exact Dvd.intro (gcdA' a b) (h₁.trans (mul_comm _ _)).symm
    

Proof state:
case intro.intro.intro.intro.intro.intro.a.hn
a b : ℕ+
left✝² : gcdW a b * gcdZ a b = succPNat (gcdX a b * gcdY a b)
h₁ : a = gcdA' a b * gcdD a b
h₂ : b = gcdB' a b * gcdD a b
left✝¹ : gcdZ a b * gcdA' a b = succPNat (gcdX a b * ↑(gcdB' a b))
left✝ : gcdW a b * gcdB' a b = succPNat (gcdY a b * ↑(gcdA' a b))
h₅ : ↑(gcdZ a b) * ↑a = gcdX a b * ↑b + ↑(gcdD a b)
right✝ : ↑(gcdW a b) * ↑b = gcdY a b * ↑a + ↑(gcdD a b)
⊢ gcdD a b ∣ b

Next tactic:
exact Dvd.intro (gcdB' a b) (h₂.trans (mul_comm _ _)).symm
theorem gcd_eq : gcdD a b = gcd a b := by
  rcases gcd_props a b with ⟨_, h₁, h₂, _, _, h₅, _⟩
  apply dvd_antisymm
  · apply dvd_gcd
    exact Dvd.intro (gcdA' a b) (h₁.trans (mul_comm _ _)).symm
    exact Dvd.intro (gcdB' a b) (h₂.trans (mul_comm _ _)).symm
  · 

Proof state:
case intro.intro.intro.intro.intro.intro.a
a b : ℕ+
left✝² : gcdW a b * gcdZ a b = succPNat (gcdX a b * gcdY a b)
h₁ : a = gcdA' a b * gcdD a b
h₂ : b = gcdB' a b * gcdD a b
left✝¹ : gcdZ a b * gcdA' a b = succPNat (gcdX a b * ↑(gcdB' a b))
left✝ : gcdW a b * gcdB' a b = succPNat (gcdY a b * ↑(gcdA' a b))
h₅ : ↑(gcdZ a b) * ↑a = gcdX a b * ↑b + ↑(gcdD a b)
right✝ : ↑(gcdW a b) * ↑b = gcdY a b * ↑a + ↑(gcdD a b)
⊢ gcd a b ∣ gcdD a b

Next tactic:
have h₇ : (gcd a b : ℕ) ∣ gcdZ a b * a := (Nat.gcd_dvd_left a b).trans (dvd_mul_left _ _)
theorem gcd_eq : gcdD a b = gcd a b := by
  rcases gcd_props a b with ⟨_, h₁, h₂, _, _, h₅, _⟩
  apply dvd_antisymm
  · apply dvd_gcd
    exact Dvd.intro (gcdA' a b) (h₁.trans (mul_comm _ _)).symm
    exact Dvd.intro (gcdB' a b) (h₂.trans (mul_comm _ _)).symm
  · have h₇ : (gcd a b : ℕ) ∣ gcdZ a b * a := (Nat.gcd_dvd_left a b).trans (dvd_mul_left _ _)
    

Proof state:
case intro.intro.intro.intro.intro.intro.a
a b : ℕ+
left✝² : gcdW a b * gcdZ a b = succPNat (gcdX a b * gcdY a b)
h₁ : a = gcdA' a b * gcdD a b
h₂ : b = gcdB' a b * gcdD a b
left✝¹ : gcdZ a b * gcdA' a b = succPNat (gcdX a b * ↑(gcdB' a b))
left✝ : gcdW a b * gcdB' a b = succPNat (gcdY a b * ↑(gcdA' a b))
h₅ : ↑(gcdZ a b) * ↑a = gcdX a b * ↑b + ↑(gcdD a b)
right✝ : ↑(gcdW a b) * ↑b = gcdY a b * ↑a + ↑(gcdD a b)
h₇ : ↑(gcd a b) ∣ ↑(gcdZ a b) * ↑a
⊢ gcd a b ∣ gcdD a b

Next tactic:
have h₈ : (gcd a b : ℕ) ∣ gcdX a b * b := (Nat.gcd_dvd_right a b).trans (dvd_mul_left _ _)
theorem gcd_eq : gcdD a b = gcd a b := by
  rcases gcd_props a b with ⟨_, h₁, h₂, _, _, h₅, _⟩
  apply dvd_antisymm
  · apply dvd_gcd
    exact Dvd.intro (gcdA' a b) (h₁.trans (mul_comm _ _)).symm
    exact Dvd.intro (gcdB' a b) (h₂.trans (mul_comm _ _)).symm
  · have h₇ : (gcd a b : ℕ) ∣ gcdZ a b * a := (Nat.gcd_dvd_left a b).trans (dvd_mul_left _ _)
    have h₈ : (gcd a b : ℕ) ∣ gcdX a b * b := (Nat.gcd_dvd_right a b).trans (dvd_mul_left _ _)
    

Proof state:
case intro.intro.intro.intro.intro.intro.a
a b : ℕ+
left✝² : gcdW a b * gcdZ a b = succPNat (gcdX a b * gcdY a b)
h₁ : a = gcdA' a b * gcdD a b
h₂ : b = gcdB' a b * gcdD a b
left✝¹ : gcdZ a b * gcdA' a b = succPNat (gcdX a b * ↑(gcdB' a b))
left✝ : gcdW a b * gcdB' a b = succPNat (gcdY a b * ↑(gcdA' a b))
h₅ : ↑(gcdZ a b) * ↑a = gcdX a b * ↑b + ↑(gcdD a b)
right✝ : ↑(gcdW a b) * ↑b = gcdY a b * ↑a + ↑(gcdD a b)
h₇ : ↑(gcd a b) ∣ ↑(gcdZ a b) * ↑a
h₈ : ↑(gcd a b) ∣ gcdX a b * ↑b
⊢ gcd a b ∣ gcdD a b

Next tactic:
rw [h₅] at h₇
theorem gcd_eq : gcdD a b = gcd a b := by
  rcases gcd_props a b with ⟨_, h₁, h₂, _, _, h₅, _⟩
  apply dvd_antisymm
  · apply dvd_gcd
    exact Dvd.intro (gcdA' a b) (h₁.trans (mul_comm _ _)).symm
    exact Dvd.intro (gcdB' a b) (h₂.trans (mul_comm _ _)).symm
  · have h₇ : (gcd a b : ℕ) ∣ gcdZ a b * a := (Nat.gcd_dvd_left a b).trans (dvd_mul_left _ _)
    have h₈ : (gcd a b : ℕ) ∣ gcdX a b * b := (Nat.gcd_dvd_right a b).trans (dvd_mul_left _ _)
    rw [h₅] at h₇
    

Proof state:
case intro.intro.intro.intro.intro.intro.a
a b : ℕ+
left✝² : gcdW a b * gcdZ a b = succPNat (gcdX a b * gcdY a b)
h₁ : a = gcdA' a b * gcdD a b
h₂ : b = gcdB' a b * gcdD a b
left✝¹ : gcdZ a b * gcdA' a b = succPNat (gcdX a b * ↑(gcdB' a b))
left✝ : gcdW a b * gcdB' a b = succPNat (gcdY a b * ↑(gcdA' a b))
h₅ : ↑(gcdZ a b) * ↑a = gcdX a b * ↑b + ↑(gcdD a b)
right✝ : ↑(gcdW a b) * ↑b = gcdY a b * ↑a + ↑(gcdD a b)
h₇ : ↑(gcd a b) ∣ gcdX a b * ↑b + ↑(gcdD a b)
h₈ : ↑(gcd a b) ∣ gcdX a b * ↑b
⊢ gcd a b ∣ gcdD a b

Next tactic:
rw [dvd_iff]
theorem gcd_eq : gcdD a b = gcd a b := by
  rcases gcd_props a b with ⟨_, h₁, h₂, _, _, h₅, _⟩
  apply dvd_antisymm
  · apply dvd_gcd
    exact Dvd.intro (gcdA' a b) (h₁.trans (mul_comm _ _)).symm
    exact Dvd.intro (gcdB' a b) (h₂.trans (mul_comm _ _)).symm
  · have h₇ : (gcd a b : ℕ) ∣ gcdZ a b * a := (Nat.gcd_dvd_left a b).trans (dvd_mul_left _ _)
    have h₈ : (gcd a b : ℕ) ∣ gcdX a b * b := (Nat.gcd_dvd_right a b).trans (dvd_mul_left _ _)
    rw [h₅] at h₇
    rw [dvd_iff]
    

Proof state:
case intro.intro.intro.intro.intro.intro.a
a b : ℕ+
left✝² : gcdW a b * gcdZ a b = succPNat (gcdX a b * gcdY a b)
h₁ : a = gcdA' a b * gcdD a b
h₂ : b = gcdB' a b * gcdD a b
left✝¹ : gcdZ a b * gcdA' a b = succPNat (gcdX a b * ↑(gcdB' a b))
left✝ : gcdW a b * gcdB' a b = succPNat (gcdY a b * ↑(gcdA' a b))
h₅ : ↑(gcdZ a b) * ↑a = gcdX a b * ↑b + ↑(gcdD a b)
right✝ : ↑(gcdW a b) * ↑b = gcdY a b * ↑a + ↑(gcdD a b)
h₇ : ↑(gcd a b) ∣ gcdX a b * ↑b + ↑(gcdD a b)
h₈ : ↑(gcd a b) ∣ gcdX a b * ↑b
⊢ ↑(gcd a b) ∣ ↑(gcdD a b)

Next tactic:
exact (Nat.dvd_add_iff_right h₈).mpr h₇
theorem ne_bot {b : α} (hb : b ∈ P.parts) : b ≠ ⊥ := by
  

Proof state:
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P : Finpartition a
b : α
hb : b ∈ P.parts
⊢ b ≠ ⊥

Next tactic:
intro h
theorem ne_bot {b : α} (hb : b ∈ P.parts) : b ≠ ⊥ := by
  intro h
  

Proof state:
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P : Finpartition a
b : α
hb : b ∈ P.parts
h : b = ⊥
⊢ False

Next tactic:
refine' P.not_bot_mem (_)
theorem ne_bot {b : α} (hb : b ∈ P.parts) : b ≠ ⊥ := by
  intro h
  refine' P.not_bot_mem (_)
  

Proof state:
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P : Finpartition a
b : α
hb : b ∈ P.parts
h : b = ⊥
⊢ ⊥ ∈ P.parts

Next tactic:
rw [h] at hb
theorem ne_bot {b : α} (hb : b ∈ P.parts) : b ≠ ⊥ := by
  intro h
  refine' P.not_bot_mem (_)
  rw [h] at hb
  

Proof state:
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P : Finpartition a
b : α
hb : ⊥ ∈ P.parts
h : b = ⊥
⊢ ⊥ ∈ P.parts

Next tactic:
exact hb
theorem parts_eq_empty_iff : P.parts = ∅ ↔ a = ⊥ := by
  

Proof state:
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P : Finpartition a
⊢ P.parts = ∅ ↔ a = ⊥

Next tactic:
simp_rw [← P.supParts]
theorem parts_eq_empty_iff : P.parts = ∅ ↔ a = ⊥ := by
  simp_rw [← P.supParts]
  

Proof state:
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P : Finpartition a
⊢ P.parts = ∅ ↔ sup P.parts id = ⊥

Next tactic:
refine' ⟨fun h ↦ _, fun h ↦ eq_empty_iff_forall_not_mem.2 fun b hb ↦ P.not_bot_mem _⟩
theorem parts_eq_empty_iff : P.parts = ∅ ↔ a = ⊥ := by
  simp_rw [← P.supParts]
  refine' ⟨fun h ↦ _, fun h ↦ eq_empty_iff_forall_not_mem.2 fun b hb ↦ P.not_bot_mem _⟩
  · 

Proof state:
case refine'_1
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P : Finpartition a
h : P.parts = ∅
⊢ sup P.parts id = ⊥

Next tactic:
rw [h]
theorem parts_eq_empty_iff : P.parts = ∅ ↔ a = ⊥ := by
  simp_rw [← P.supParts]
  refine' ⟨fun h ↦ _, fun h ↦ eq_empty_iff_forall_not_mem.2 fun b hb ↦ P.not_bot_mem _⟩
  · rw [h]
    

Proof state:
case refine'_1
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P : Finpartition a
h : P.parts = ∅
⊢ sup ∅ id = ⊥

Next tactic:
exact Finset.sup_empty
theorem parts_eq_empty_iff : P.parts = ∅ ↔ a = ⊥ := by
  simp_rw [← P.supParts]
  refine' ⟨fun h ↦ _, fun h ↦ eq_empty_iff_forall_not_mem.2 fun b hb ↦ P.not_bot_mem _⟩
  · rw [h]
    exact Finset.sup_empty
  · 

Proof state:
case refine'_2
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P : Finpartition a
h : sup P.parts id = ⊥
b : α
hb : b ∈ P.parts
⊢ ⊥ ∈ P.parts

Next tactic:
rwa [← le_bot_iff.1 ((le_sup hb).trans h.le)]
theorem parts_nonempty_iff : P.parts.Nonempty ↔ a ≠ ⊥ := by
  

Proof state:
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P : Finpartition a
⊢ Finset.Nonempty P.parts ↔ a ≠ ⊥

Next tactic:
rw [nonempty_iff_ne_empty, not_iff_not, parts_eq_empty_iff]
instance : Unique (Finpartition (⊥ : α)) :=
  { (inferInstance : Inhabited (Finpartition (⊥ : α))) with
    uniq := fun P ↦ by
      

Proof state:
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P✝ : Finpartition a
src✝ : Inhabited (Finpartition ⊥) := inferInstance
P : Finpartition ⊥
⊢ P = default

Next tactic:
ext a
instance : Unique (Finpartition (⊥ : α)) :=
  { (inferInstance : Inhabited (Finpartition (⊥ : α))) with
    uniq := fun P ↦ by
      ext a
      

Proof state:
case parts.a
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a✝ : α
P✝ : Finpartition a✝
src✝ : Inhabited (Finpartition ⊥) := inferInstance
P : Finpartition ⊥
a : α
⊢ a ∈ P.parts ↔ a ∈ default.parts

Next tactic:
exact iff_of_false (fun h ↦ P.ne_bot h <| le_bot_iff.1 <| P.le h) (not_mem_empty a)
/-- There's a unique partition of an atom. -/
@[reducible]
def _root_.IsAtom.uniqueFinpartition (ha : IsAtom a) : Unique (Finpartition a)
    where
  default := indiscrete ha.1
  uniq P := by
    

Proof state:
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P✝ : Finpartition a
ha : IsAtom a
P : Finpartition a
⊢ P = default

Next tactic:
have h : ∀ b ∈ P.parts, b = a := fun _ hb ↦
      (ha.le_iff.mp <| P.le hb).resolve_left (P.ne_bot hb)
/-- There's a unique partition of an atom. -/
@[reducible]
def _root_.IsAtom.uniqueFinpartition (ha : IsAtom a) : Unique (Finpartition a)
    where
  default := indiscrete ha.1
  uniq P := by
    have h : ∀ b ∈ P.parts, b = a := fun _ hb ↦
      (ha.le_iff.mp <| P.le hb).resolve_left (P.ne_bot hb)
    

Proof state:
α : Type u_1
inst✝¹ : Lattice α
inst✝ : OrderBot α
a : α
P✝ : Finpartition a
ha : IsAtom a
P : Finpartition a
h : ∀ b ∈ P.parts, b = a
⊢ P = default

Next tactic:
ext b