l3lab/ntp-mathlib huggingface dataset:
/-- The gcd and lcm operations on positive integers correspond
 to the inf and sup operations on multisets. -/
theorem factorMultiset_gcd (m n : ℕ+) :
    factorMultiset (gcd m n) = factorMultiset m ⊓ factorMultiset n := by
  apply le_antisymm
  · apply le_inf_iff.mpr; constructor <;> apply factorMultiset_le_iff.mpr
    exact gcd_dvd_left m n
    exact gcd_dvd_right m n
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply dvd_gcd <;> 

Proof state:
case a.hn
m n : ℕ+
⊢ PrimeMultiset.prod (factorMultiset m ⊓ factorMultiset n) ∣ n

Next tactic:
rw [PrimeMultiset.prod_dvd_iff']
/-- The gcd and lcm operations on positive integers correspond
 to the inf and sup operations on multisets. -/
theorem factorMultiset_gcd (m n : ℕ+) :
    factorMultiset (gcd m n) = factorMultiset m ⊓ factorMultiset n := by
  apply le_antisymm
  · apply le_inf_iff.mpr; constructor <;> apply factorMultiset_le_iff.mpr
    exact gcd_dvd_left m n
    exact gcd_dvd_right m n
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply dvd_gcd <;> rw [PrimeMultiset.prod_dvd_iff']
    

Proof state:
case a.hm
m n : ℕ+
⊢ factorMultiset m ⊓ factorMultiset n ≤ factorMultiset m
case a.hn m n : ℕ+ ⊢ factorMultiset m ⊓ factorMultiset n ≤ factorMultiset n

Next tactic:
exact inf_le_left
/-- The gcd and lcm operations on positive integers correspond
 to the inf and sup operations on multisets. -/
theorem factorMultiset_gcd (m n : ℕ+) :
    factorMultiset (gcd m n) = factorMultiset m ⊓ factorMultiset n := by
  apply le_antisymm
  · apply le_inf_iff.mpr; constructor <;> apply factorMultiset_le_iff.mpr
    exact gcd_dvd_left m n
    exact gcd_dvd_right m n
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply dvd_gcd <;> rw [PrimeMultiset.prod_dvd_iff']
    exact inf_le_left
    

Proof state:
case a.hn
m n : ℕ+
⊢ factorMultiset m ⊓ factorMultiset n ≤ factorMultiset n

Next tactic:
exact inf_le_right
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  

Proof state:
m n : ℕ+
⊢ factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n

Next tactic:
apply le_antisymm
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  apply le_antisymm
  · 

Proof state:
case a
m n : ℕ+
⊢ factorMultiset (lcm m n) ≤ factorMultiset m ⊔ factorMultiset n

Next tactic:
rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  apply le_antisymm
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    

Proof state:
case a
m n : ℕ+
⊢ lcm m n ∣ PrimeMultiset.prod (factorMultiset m ⊔ factorMultiset n)

Next tactic:
apply lcm_dvd
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  apply le_antisymm
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply lcm_dvd <;> 

Proof state:
case a.hm
m n : ℕ+
⊢ m ∣ PrimeMultiset.prod (factorMultiset m ⊔ factorMultiset n)

Next tactic:
rw [← factorMultiset_le_iff']
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  apply le_antisymm
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply lcm_dvd <;> 

Proof state:
case a.hn
m n : ℕ+
⊢ n ∣ PrimeMultiset.prod (factorMultiset m ⊔ factorMultiset n)

Next tactic:
rw [← factorMultiset_le_iff']
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  apply le_antisymm
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply lcm_dvd <;> rw [← factorMultiset_le_iff']
    

Proof state:
case a.hm
m n : ℕ+
⊢ factorMultiset m ≤ factorMultiset m ⊔ factorMultiset n
case a.hn m n : ℕ+ ⊢ factorMultiset n ≤ factorMultiset m ⊔ factorMultiset n

Next tactic:
exact le_sup_left
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  apply le_antisymm
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply lcm_dvd <;> rw [← factorMultiset_le_iff']
    exact le_sup_left
    

Proof state:
case a.hn
m n : ℕ+
⊢ factorMultiset n ≤ factorMultiset m ⊔ factorMultiset n

Next tactic:
exact le_sup_right
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  apply le_antisymm
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply lcm_dvd <;> rw [← factorMultiset_le_iff']
    exact le_sup_left
    exact le_sup_right
  · 

Proof state:
case a
m n : ℕ+
⊢ factorMultiset m ⊔ factorMultiset n ≤ factorMultiset (lcm m n)

Next tactic:
apply sup_le_iff.mpr
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  apply le_antisymm
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply lcm_dvd <;> rw [← factorMultiset_le_iff']
    exact le_sup_left
    exact le_sup_right
  · apply sup_le_iff.mpr; 

Proof state:
case a
m n : ℕ+
⊢ factorMultiset m ≤ factorMultiset (lcm m n) ∧ factorMultiset n ≤ factorMultiset (lcm m n)

Next tactic:
constructor
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  apply le_antisymm
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply lcm_dvd <;> rw [← factorMultiset_le_iff']
    exact le_sup_left
    exact le_sup_right
  · apply sup_le_iff.mpr; constructor <;> 

Proof state:
case a.left
m n : ℕ+
⊢ factorMultiset m ≤ factorMultiset (lcm m n)

Next tactic:
apply factorMultiset_le_iff.mpr
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  apply le_antisymm
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply lcm_dvd <;> rw [← factorMultiset_le_iff']
    exact le_sup_left
    exact le_sup_right
  · apply sup_le_iff.mpr; constructor <;> 

Proof state:
case a.right
m n : ℕ+
⊢ factorMultiset n ≤ factorMultiset (lcm m n)

Next tactic:
apply factorMultiset_le_iff.mpr
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  apply le_antisymm
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply lcm_dvd <;> rw [← factorMultiset_le_iff']
    exact le_sup_left
    exact le_sup_right
  · apply sup_le_iff.mpr; constructor <;> apply factorMultiset_le_iff.mpr
    

Proof state:
case a.left
m n : ℕ+
⊢ m ∣ lcm m n
case a.right m n : ℕ+ ⊢ n ∣ lcm m n

Next tactic:
exact dvd_lcm_left m n
theorem factorMultiset_lcm (m n : ℕ+) :
    factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n := by
  apply le_antisymm
  · rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
    apply lcm_dvd <;> rw [← factorMultiset_le_iff']
    exact le_sup_left
    exact le_sup_right
  · apply sup_le_iff.mpr; constructor <;> apply factorMultiset_le_iff.mpr
    exact dvd_lcm_left m n
    

Proof state:
case a.right
m n : ℕ+
⊢ n ∣ lcm m n

Next tactic:
exact dvd_lcm_right m n
/-- The number of occurrences of p in the factor multiset of m
 is the same as the p-adic valuation of m. -/
theorem count_factorMultiset (m : ℕ+) (p : Nat.Primes) (k : ℕ) :
    Pow.pow (p : ℕ+) k ∣ m ↔ k ≤ m.factorMultiset.count p := by
  

Proof state:
m : ℕ+
p : Nat.Primes
k : ℕ
⊢ Pow.pow (↑p) k ∣ m ↔ k ≤ Multiset.count p (factorMultiset m)

Next tactic:
intros
/-- The number of occurrences of p in the factor multiset of m
 is the same as the p-adic valuation of m. -/
theorem count_factorMultiset (m : ℕ+) (p : Nat.Primes) (k : ℕ) :
    Pow.pow (p : ℕ+) k ∣ m ↔ k ≤ m.factorMultiset.count p := by
  intros
  

Proof state:
m : ℕ+
p : Nat.Primes
k : ℕ
⊢ Pow.pow (↑p) k ∣ m ↔ k ≤ Multiset.count p (factorMultiset m)

Next tactic:
rw [Multiset.le_count_iff_replicate_le, ← factorMultiset_le_iff, factorMultiset_pow,
    factorMultiset_ofPrime]
/-- The number of occurrences of p in the factor multiset of m
 is the same as the p-adic valuation of m. -/
theorem count_factorMultiset (m : ℕ+) (p : Nat.Primes) (k : ℕ) :
    Pow.pow (p : ℕ+) k ∣ m ↔ k ≤ m.factorMultiset.count p := by
  intros
  rw [Multiset.le_count_iff_replicate_le, ← factorMultiset_le_iff, factorMultiset_pow,
    factorMultiset_ofPrime]
  

Proof state:
m : ℕ+
p : Nat.Primes
k : ℕ
⊢ k • PrimeMultiset.ofPrime p ≤ factorMultiset m ↔ Multiset.replicate k p ≤ factorMultiset m

Next tactic:
congr! 2
/-- The number of occurrences of p in the factor multiset of m
 is the same as the p-adic valuation of m. -/
theorem count_factorMultiset (m : ℕ+) (p : Nat.Primes) (k : ℕ) :
    Pow.pow (p : ℕ+) k ∣ m ↔ k ≤ m.factorMultiset.count p := by
  intros
  rw [Multiset.le_count_iff_replicate_le, ← factorMultiset_le_iff, factorMultiset_pow,
    factorMultiset_ofPrime]
  congr! 2
  

Proof state:
case a.h.e'_3.h
m : ℕ+
p : Nat.Primes
k : ℕ
e_1✝ : PrimeMultiset = Multiset Nat.Primes
⊢ k • PrimeMultiset.ofPrime p = Multiset.replicate k p

Next tactic:
apply Multiset.eq_replicate.mpr
/-- The number of occurrences of p in the factor multiset of m
 is the same as the p-adic valuation of m. -/
theorem count_factorMultiset (m : ℕ+) (p : Nat.Primes) (k : ℕ) :
    Pow.pow (p : ℕ+) k ∣ m ↔ k ≤ m.factorMultiset.count p := by
  intros
  rw [Multiset.le_count_iff_replicate_le, ← factorMultiset_le_iff, factorMultiset_pow,
    factorMultiset_ofPrime]
  congr! 2
  apply Multiset.eq_replicate.mpr
  

Proof state:
case a.h.e'_3.h
m : ℕ+
p : Nat.Primes
k : ℕ
e_1✝ : PrimeMultiset = Multiset Nat.Primes
⊢ Multiset.card (k • PrimeMultiset.ofPrime p) = k ∧ ∀ b ∈ k • PrimeMultiset.ofPrime p, b = p

Next tactic:
constructor
/-- The number of occurrences of p in the factor multiset of m
 is the same as the p-adic valuation of m. -/
theorem count_factorMultiset (m : ℕ+) (p : Nat.Primes) (k : ℕ) :
    Pow.pow (p : ℕ+) k ∣ m ↔ k ≤ m.factorMultiset.count p := by
  intros
  rw [Multiset.le_count_iff_replicate_le, ← factorMultiset_le_iff, factorMultiset_pow,
    factorMultiset_ofPrime]
  congr! 2
  apply Multiset.eq_replicate.mpr
  constructor
  · 

Proof state:
case a.h.e'_3.h.left
m : ℕ+
p : Nat.Primes
k : ℕ
e_1✝ : PrimeMultiset = Multiset Nat.Primes
⊢ Multiset.card (k • PrimeMultiset.ofPrime p) = k

Next tactic:
rw [Multiset.card_nsmul, PrimeMultiset.card_ofPrime, mul_one]
/-- The number of occurrences of p in the factor multiset of m
 is the same as the p-adic valuation of m. -/
theorem count_factorMultiset (m : ℕ+) (p : Nat.Primes) (k : ℕ) :
    Pow.pow (p : ℕ+) k ∣ m ↔ k ≤ m.factorMultiset.count p := by
  intros
  rw [Multiset.le_count_iff_replicate_le, ← factorMultiset_le_iff, factorMultiset_pow,
    factorMultiset_ofPrime]
  congr! 2
  apply Multiset.eq_replicate.mpr
  constructor
  · rw [Multiset.card_nsmul, PrimeMultiset.card_ofPrime, mul_one]
  · 

Proof state:
case a.h.e'_3.h.right
m : ℕ+
p : Nat.Primes
k : ℕ
e_1✝ : PrimeMultiset = Multiset Nat.Primes
⊢ ∀ b ∈ k • PrimeMultiset.ofPrime p, b = p

Next tactic:
intro q h
/-- The number of occurrences of p in the factor multiset of m
 is the same as the p-adic valuation of m. -/
theorem count_factorMultiset (m : ℕ+) (p : Nat.Primes) (k : ℕ) :
    Pow.pow (p : ℕ+) k ∣ m ↔ k ≤ m.factorMultiset.count p := by
  intros
  rw [Multiset.le_count_iff_replicate_le, ← factorMultiset_le_iff, factorMultiset_pow,
    factorMultiset_ofPrime]
  congr! 2
  apply Multiset.eq_replicate.mpr
  constructor
  · rw [Multiset.card_nsmul, PrimeMultiset.card_ofPrime, mul_one]
  · intro q h
    

Proof state:
case a.h.e'_3.h.right
m : ℕ+
p : Nat.Primes
k : ℕ
e_1✝ : PrimeMultiset = Multiset Nat.Primes
q : Nat.Primes
h : q ∈ k • PrimeMultiset.ofPrime p
⊢ q = p

Next tactic:
rw [PrimeMultiset.ofPrime, Multiset.nsmul_singleton _ k] at h
/-- The number of occurrences of p in the factor multiset of m
 is the same as the p-adic valuation of m. -/
theorem count_factorMultiset (m : ℕ+) (p : Nat.Primes) (k : ℕ) :
    Pow.pow (p : ℕ+) k ∣ m ↔ k ≤ m.factorMultiset.count p := by
  intros
  rw [Multiset.le_count_iff_replicate_le, ← factorMultiset_le_iff, factorMultiset_pow,
    factorMultiset_ofPrime]
  congr! 2
  apply Multiset.eq_replicate.mpr
  constructor
  · rw [Multiset.card_nsmul, PrimeMultiset.card_ofPrime, mul_one]
  · intro q h
    rw [PrimeMultiset.ofPrime, Multiset.nsmul_singleton _ k] at h
    

Proof state:
case a.h.e'_3.h.right
m : ℕ+
p : Nat.Primes
k : ℕ
e_1✝ : PrimeMultiset = Multiset Nat.Primes
q : Nat.Primes
h : q ∈ Multiset.replicate k p
⊢ q = p

Next tactic:
exact Multiset.eq_of_mem_replicate h
theorem prod_inf (u v : PrimeMultiset) : (u ⊓ v).prod = PNat.gcd u.prod v.prod := by
  

Proof state:
u v : PrimeMultiset
⊢ prod (u ⊓ v) = PNat.gcd (prod u) (prod v)

Next tactic:
let n := u.prod
theorem prod_inf (u v : PrimeMultiset) : (u ⊓ v).prod = PNat.gcd u.prod v.prod := by
  let n := u.prod
  

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
⊢ prod (u ⊓ v) = PNat.gcd (prod u) (prod v)

Next tactic:
let m := v.prod
theorem prod_inf (u v : PrimeMultiset) : (u ⊓ v).prod = PNat.gcd u.prod v.prod := by
  let n := u.prod
  let m := v.prod
  

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
⊢ prod (u ⊓ v) = PNat.gcd (prod u) (prod v)

Next tactic:
change (u ⊓ v).prod = PNat.gcd n m
theorem prod_inf (u v : PrimeMultiset) : (u ⊓ v).prod = PNat.gcd u.prod v.prod := by
  let n := u.prod
  let m := v.prod
  change (u ⊓ v).prod = PNat.gcd n m
  

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
⊢ prod (u ⊓ v) = PNat.gcd n m

Next tactic:
have : u = n.factorMultiset := u.factorMultiset_prod.symm
theorem prod_inf (u v : PrimeMultiset) : (u ⊓ v).prod = PNat.gcd u.prod v.prod := by
  let n := u.prod
  let m := v.prod
  change (u ⊓ v).prod = PNat.gcd n m
  have : u = n.factorMultiset := u.factorMultiset_prod.symm; 

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this : u = PNat.factorMultiset n
⊢ prod (u ⊓ v) = PNat.gcd n m

Next tactic:
rw [this]
theorem prod_inf (u v : PrimeMultiset) : (u ⊓ v).prod = PNat.gcd u.prod v.prod := by
  let n := u.prod
  let m := v.prod
  change (u ⊓ v).prod = PNat.gcd n m
  have : u = n.factorMultiset := u.factorMultiset_prod.symm; rw [this]
  

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this : u = PNat.factorMultiset n
⊢ prod (PNat.factorMultiset n ⊓ v) = PNat.gcd n m

Next tactic:
have : v = m.factorMultiset := v.factorMultiset_prod.symm
theorem prod_inf (u v : PrimeMultiset) : (u ⊓ v).prod = PNat.gcd u.prod v.prod := by
  let n := u.prod
  let m := v.prod
  change (u ⊓ v).prod = PNat.gcd n m
  have : u = n.factorMultiset := u.factorMultiset_prod.symm; rw [this]
  have : v = m.factorMultiset := v.factorMultiset_prod.symm; 

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this✝ : u = PNat.factorMultiset n
this : v = PNat.factorMultiset m
⊢ prod (PNat.factorMultiset n ⊓ v) = PNat.gcd n m

Next tactic:
rw [this]
theorem prod_inf (u v : PrimeMultiset) : (u ⊓ v).prod = PNat.gcd u.prod v.prod := by
  let n := u.prod
  let m := v.prod
  change (u ⊓ v).prod = PNat.gcd n m
  have : u = n.factorMultiset := u.factorMultiset_prod.symm; rw [this]
  have : v = m.factorMultiset := v.factorMultiset_prod.symm; rw [this]
  

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this✝ : u = PNat.factorMultiset n
this : v = PNat.factorMultiset m
⊢ prod (PNat.factorMultiset n ⊓ PNat.factorMultiset m) = PNat.gcd n m

Next tactic:
rw [← PNat.factorMultiset_gcd n m, PNat.prod_factorMultiset]
theorem prod_sup (u v : PrimeMultiset) : (u ⊔ v).prod = PNat.lcm u.prod v.prod := by
  

Proof state:
u v : PrimeMultiset
⊢ prod (u ⊔ v) = PNat.lcm (prod u) (prod v)

Next tactic:
let n := u.prod
theorem prod_sup (u v : PrimeMultiset) : (u ⊔ v).prod = PNat.lcm u.prod v.prod := by
  let n := u.prod
  

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
⊢ prod (u ⊔ v) = PNat.lcm (prod u) (prod v)

Next tactic:
let m := v.prod
theorem prod_sup (u v : PrimeMultiset) : (u ⊔ v).prod = PNat.lcm u.prod v.prod := by
  let n := u.prod
  let m := v.prod
  

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
⊢ prod (u ⊔ v) = PNat.lcm (prod u) (prod v)

Next tactic:
change (u ⊔ v).prod = PNat.lcm n m
theorem prod_sup (u v : PrimeMultiset) : (u ⊔ v).prod = PNat.lcm u.prod v.prod := by
  let n := u.prod
  let m := v.prod
  change (u ⊔ v).prod = PNat.lcm n m
  

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
⊢ prod (u ⊔ v) = PNat.lcm n m

Next tactic:
have : u = n.factorMultiset := u.factorMultiset_prod.symm
theorem prod_sup (u v : PrimeMultiset) : (u ⊔ v).prod = PNat.lcm u.prod v.prod := by
  let n := u.prod
  let m := v.prod
  change (u ⊔ v).prod = PNat.lcm n m
  have : u = n.factorMultiset := u.factorMultiset_prod.symm; 

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this : u = PNat.factorMultiset n
⊢ prod (u ⊔ v) = PNat.lcm n m

Next tactic:
rw [this]
theorem prod_sup (u v : PrimeMultiset) : (u ⊔ v).prod = PNat.lcm u.prod v.prod := by
  let n := u.prod
  let m := v.prod
  change (u ⊔ v).prod = PNat.lcm n m
  have : u = n.factorMultiset := u.factorMultiset_prod.symm; rw [this]
  

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this : u = PNat.factorMultiset n
⊢ prod (PNat.factorMultiset n ⊔ v) = PNat.lcm n m

Next tactic:
have : v = m.factorMultiset := v.factorMultiset_prod.symm
theorem prod_sup (u v : PrimeMultiset) : (u ⊔ v).prod = PNat.lcm u.prod v.prod := by
  let n := u.prod
  let m := v.prod
  change (u ⊔ v).prod = PNat.lcm n m
  have : u = n.factorMultiset := u.factorMultiset_prod.symm; rw [this]
  have : v = m.factorMultiset := v.factorMultiset_prod.symm; 

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this✝ : u = PNat.factorMultiset n
this : v = PNat.factorMultiset m
⊢ prod (PNat.factorMultiset n ⊔ v) = PNat.lcm n m

Next tactic:
rw [this]
theorem prod_sup (u v : PrimeMultiset) : (u ⊔ v).prod = PNat.lcm u.prod v.prod := by
  let n := u.prod
  let m := v.prod
  change (u ⊔ v).prod = PNat.lcm n m
  have : u = n.factorMultiset := u.factorMultiset_prod.symm; rw [this]
  have : v = m.factorMultiset := v.factorMultiset_prod.symm; rw [this]
  

Proof state:
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this✝ : u = PNat.factorMultiset n
this : v = PNat.factorMultiset m
⊢ prod (PNat.factorMultiset n ⊔ PNat.factorMultiset m) = PNat.lcm n m

Next tactic:
rw [← PNat.factorMultiset_lcm n m, PNat.prod_factorMultiset]
@[simp]
theorem charmatrix_apply_eq (M : Matrix n n R) (i : n) :
    charmatrix M i i = (X : R[X]) - C (M i i) := by
  

Proof state:
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
i : n
⊢ charmatrix M i i = X - C (M i i)

Next tactic:
simp only [charmatrix, RingHom.mapMatrix_apply, sub_apply, scalar_apply, map_apply,
    diagonal_apply_eq]
@[simp]
theorem charmatrix_apply_ne (M : Matrix n n R) (i j : n) (h : i ≠ j) :
    charmatrix M i j = -C (M i j) := by
  

Proof state:
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
i j : n
h : i ≠ j
⊢ charmatrix M i j = -C (M i j)

Next tactic:
simp only [charmatrix, RingHom.mapMatrix_apply, sub_apply, scalar_apply, diagonal_apply_ne _ h,
    map_apply, sub_eq_neg_self]
theorem matPolyEquiv_charmatrix (M : Matrix n n R) : matPolyEquiv (charmatrix M) = X - C M := by
  

Proof state:
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
⊢ matPolyEquiv (charmatrix M) = X - C M

Next tactic:
ext k i j
theorem matPolyEquiv_charmatrix (M : Matrix n n R) : matPolyEquiv (charmatrix M) = X - C M := by
  ext k i j
  

Proof state:
case a.a.h
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
k : ℕ
i j : n
⊢ coeff (matPolyEquiv (charmatrix M)) k i j = coeff (X - C M) k i j

Next tactic:
simp only [matPolyEquiv_coeff_apply, coeff_sub, Pi.sub_apply]
theorem matPolyEquiv_charmatrix (M : Matrix n n R) : matPolyEquiv (charmatrix M) = X - C M := by
  ext k i j
  simp only [matPolyEquiv_coeff_apply, coeff_sub, Pi.sub_apply]
  

Proof state:
case a.a.h
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
k : ℕ
i j : n
⊢ coeff (charmatrix M i j) k = (coeff X k - coeff (C M) k) i j

Next tactic:
by_cases h : i = j
theorem matPolyEquiv_charmatrix (M : Matrix n n R) : matPolyEquiv (charmatrix M) = X - C M := by
  ext k i j
  simp only [matPolyEquiv_coeff_apply, coeff_sub, Pi.sub_apply]
  by_cases h : i = j
  · 

Proof state:
case pos
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
k : ℕ
i j : n
h : i = j
⊢ coeff (charmatrix M i j) k = (coeff X k - coeff (C M) k) i j

Next tactic:
subst h
theorem matPolyEquiv_charmatrix (M : Matrix n n R) : matPolyEquiv (charmatrix M) = X - C M := by
  ext k i j
  simp only [matPolyEquiv_coeff_apply, coeff_sub, Pi.sub_apply]
  by_cases h : i = j
  · subst h
    

Proof state:
case pos
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
k : ℕ
i : n
⊢ coeff (charmatrix M i i) k = (coeff X k - coeff (C M) k) i i

Next tactic:
rw [charmatrix_apply_eq, coeff_sub]
theorem matPolyEquiv_charmatrix (M : Matrix n n R) : matPolyEquiv (charmatrix M) = X - C M := by
  ext k i j
  simp only [matPolyEquiv_coeff_apply, coeff_sub, Pi.sub_apply]
  by_cases h : i = j
  · subst h
    rw [charmatrix_apply_eq, coeff_sub]
    

Proof state:
case pos
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
k : ℕ
i : n
⊢ coeff X k - coeff (C (M i i)) k = (coeff X k - coeff (C M) k) i i

Next tactic:
simp only [coeff_X, coeff_C]
theorem matPolyEquiv_charmatrix (M : Matrix n n R) : matPolyEquiv (charmatrix M) = X - C M := by
  ext k i j
  simp only [matPolyEquiv_coeff_apply, coeff_sub, Pi.sub_apply]
  by_cases h : i = j
  · subst h
    rw [charmatrix_apply_eq, coeff_sub]
    simp only [coeff_X, coeff_C]
    

Proof state:
case pos
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
k : ℕ
i : n
⊢ ((if 1 = k then 1 else 0) - if k = 0 then M i i else 0) = ((if 1 = k then 1 else 0) - if k = 0 then M else 0) i i

Next tactic:
split_ifs
theorem matPolyEquiv_charmatrix (M : Matrix n n R) : matPolyEquiv (charmatrix M) = X - C M := by
  ext k i j
  simp only [matPolyEquiv_coeff_apply, coeff_sub, Pi.sub_apply]
  by_cases h : i = j
  · subst h
    rw [charmatrix_apply_eq, coeff_sub]
    simp only [coeff_X, coeff_C]
    split_ifs <;> 

Proof state:
case pos
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
k : ℕ
i : n
h✝¹ : 1 = k
h✝ : k = 0
⊢ 1 - M i i = (1 - M) i i

Next tactic:
simp
theorem matPolyEquiv_charmatrix (M : Matrix n n R) : matPolyEquiv (charmatrix M) = X - C M := by
  ext k i j
  simp only [matPolyEquiv_coeff_apply, coeff_sub, Pi.sub_apply]
  by_cases h : i = j
  · subst h
    rw [charmatrix_apply_eq, coeff_sub]
    simp only [coeff_X, coeff_C]
    split_ifs <;> 

Proof state:
case neg
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
k : ℕ
i : n
h✝¹ : 1 = k
h✝ : ¬k = 0
⊢ 1 - 0 = (1 - 0) i i

Next tactic:
simp
theorem matPolyEquiv_charmatrix (M : Matrix n n R) : matPolyEquiv (charmatrix M) = X - C M := by
  ext k i j
  simp only [matPolyEquiv_coeff_apply, coeff_sub, Pi.sub_apply]
  by_cases h : i = j
  · subst h
    rw [charmatrix_apply_eq, coeff_sub]
    simp only [coeff_X, coeff_C]
    split_ifs <;> 

Proof state:
case pos
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
k : ℕ
i : n
h✝¹ : ¬1 = k
h✝ : k = 0
⊢ 0 - M i i = (0 - M) i i

Next tactic:
simp
theorem matPolyEquiv_charmatrix (M : Matrix n n R) : matPolyEquiv (charmatrix M) = X - C M := by
  ext k i j
  simp only [matPolyEquiv_coeff_apply, coeff_sub, Pi.sub_apply]
  by_cases h : i = j
  · subst h
    rw [charmatrix_apply_eq, coeff_sub]
    simp only [coeff_X, coeff_C]
    split_ifs <;> 

Proof state:
case neg
R : Type u
inst✝² : CommRing R
n : Type w
inst✝¹ : DecidableEq n
inst✝ : Fintype n
M : Matrix n n R
k : ℕ
i : n
h✝¹ : ¬1 = k
h✝ : ¬k = 0
⊢ 0 - 0 = (0 - 0) i i

Next tactic:
simp