l3lab/ntp-mathlib huggingface dataset:
@[symm]
theorem Coprime.symm {m n : ℕ+} : m.Coprime n → n.Coprime m := by
  unfold Coprime
  rw [gcd_comm]
  

Proof state:
m n : ℕ+
⊢ gcd n m = 1 → gcd n m = 1

Next tactic:
simp
theorem Coprime.coprime_dvd_left {m k n : ℕ+} : m ∣ k → k.Coprime n → m.Coprime n := by
  

Proof state:
m k n : ℕ+
⊢ m ∣ k → Coprime k n → Coprime m n

Next tactic:
rw [dvd_iff]
theorem Coprime.coprime_dvd_left {m k n : ℕ+} : m ∣ k → k.Coprime n → m.Coprime n := by
  rw [dvd_iff]
  

Proof state:
m k n : ℕ+
⊢ ↑m ∣ ↑k → Coprime k n → Coprime m n

Next tactic:
repeat' rw [← coprime_coe]
theorem Coprime.coprime_dvd_left {m k n : ℕ+} : m ∣ k → k.Coprime n → m.Coprime n := by
  rw [dvd_iff]
  repeat' 

Proof state:
m k n : ℕ+
⊢ ↑m ∣ ↑k → Coprime k n → Coprime m n

Next tactic:
rw [← coprime_coe]
theorem Coprime.coprime_dvd_left {m k n : ℕ+} : m ∣ k → k.Coprime n → m.Coprime n := by
  rw [dvd_iff]
  repeat' 

Proof state:
m k n : ℕ+
⊢ ↑m ∣ ↑k → Nat.Coprime ↑k ↑n → Coprime m n

Next tactic:
rw [← coprime_coe]
theorem Coprime.coprime_dvd_left {m k n : ℕ+} : m ∣ k → k.Coprime n → m.Coprime n := by
  rw [dvd_iff]
  repeat' 

Proof state:
m k n : ℕ+
⊢ ↑m ∣ ↑k → Nat.Coprime ↑k ↑n → Nat.Coprime ↑m ↑n

Next tactic:
rw [← coprime_coe]
theorem Coprime.coprime_dvd_left {m k n : ℕ+} : m ∣ k → k.Coprime n → m.Coprime n := by
  rw [dvd_iff]
  repeat' rw [← coprime_coe]
  

Proof state:
m k n : ℕ+
⊢ ↑m ∣ ↑k → Nat.Coprime ↑k ↑n → Nat.Coprime ↑m ↑n

Next tactic:
apply Nat.Coprime.coprime_dvd_left
theorem Coprime.factor_eq_gcd_left {a b m n : ℕ+} (cop : m.Coprime n) (am : a ∣ m) (bn : b ∣ n) :
    a = (a * b).gcd m := by
  

Proof state:
a b m n : ℕ+
cop : Coprime m n
am : a ∣ m
bn : b ∣ n
⊢ a = gcd (a * b) m

Next tactic:
rw [gcd_eq_left_iff_dvd] at am
theorem Coprime.factor_eq_gcd_left {a b m n : ℕ+} (cop : m.Coprime n) (am : a ∣ m) (bn : b ∣ n) :
    a = (a * b).gcd m := by
  rw [gcd_eq_left_iff_dvd] at am
  

Proof state:
a b m n : ℕ+
cop : Coprime m n
am : gcd a m = a
bn : b ∣ n
⊢ a = gcd (a * b) m

Next tactic:
conv_lhs => rw [← am]
theorem Coprime.factor_eq_gcd_left {a b m n : ℕ+} (cop : m.Coprime n) (am : a ∣ m) (bn : b ∣ n) :
    a = (a * b).gcd m := by
  rw [gcd_eq_left_iff_dvd] at am
  conv_lhs => 

Proof state:
a b m n : ℕ+
cop : Coprime m n
am : gcd a m = a
bn : b ∣ n
| a

Next tactic:
rw [← am]
theorem Coprime.factor_eq_gcd_left {a b m n : ℕ+} (cop : m.Coprime n) (am : a ∣ m) (bn : b ∣ n) :
    a = (a * b).gcd m := by
  rw [gcd_eq_left_iff_dvd] at am
  conv_lhs => rw [← am]
  

Proof state:
a b m n : ℕ+
cop : Coprime m n
am : gcd a m = a
bn : b ∣ n
⊢ gcd a m = gcd (a * b) m

Next tactic:
rw [eq_comm]
theorem Coprime.factor_eq_gcd_left {a b m n : ℕ+} (cop : m.Coprime n) (am : a ∣ m) (bn : b ∣ n) :
    a = (a * b).gcd m := by
  rw [gcd_eq_left_iff_dvd] at am
  conv_lhs => rw [← am]
  rw [eq_comm]
  

Proof state:
a b m n : ℕ+
cop : Coprime m n
am : gcd a m = a
bn : b ∣ n
⊢ gcd (a * b) m = gcd a m

Next tactic:
apply Coprime.gcd_mul_right_cancel a
theorem Coprime.factor_eq_gcd_left {a b m n : ℕ+} (cop : m.Coprime n) (am : a ∣ m) (bn : b ∣ n) :
    a = (a * b).gcd m := by
  rw [gcd_eq_left_iff_dvd] at am
  conv_lhs => rw [← am]
  rw [eq_comm]
  apply Coprime.gcd_mul_right_cancel a
  

Proof state:
a b m n : ℕ+
cop : Coprime m n
am : gcd a m = a
bn : b ∣ n
⊢ Coprime b m

Next tactic:
apply Coprime.coprime_dvd_left bn cop.symm
theorem Coprime.factor_eq_gcd_right {a b m n : ℕ+} (cop : m.Coprime n) (am : a ∣ m) (bn : b ∣ n) :
    a = (b * a).gcd m := by 

Proof state:
a b m n : ℕ+
cop : Coprime m n
am : a ∣ m
bn : b ∣ n
⊢ a = gcd (b * a) m

Next tactic:
rw [mul_comm]
theorem Coprime.factor_eq_gcd_right {a b m n : ℕ+} (cop : m.Coprime n) (am : a ∣ m) (bn : b ∣ n) :
    a = (b * a).gcd m := by rw [mul_comm]; 

Proof state:
a b m n : ℕ+
cop : Coprime m n
am : a ∣ m
bn : b ∣ n
⊢ a = gcd (a * b) m

Next tactic:
apply Coprime.factor_eq_gcd_left cop am bn
theorem Coprime.factor_eq_gcd_left_right {a b m n : ℕ+} (cop : m.Coprime n) (am : a ∣ m)
    (bn : b ∣ n) : a = m.gcd (a * b) := by 

Proof state:
a b m n : ℕ+
cop : Coprime m n
am : a ∣ m
bn : b ∣ n
⊢ a = gcd m (a * b)

Next tactic:
rw [gcd_comm]
theorem Coprime.factor_eq_gcd_left_right {a b m n : ℕ+} (cop : m.Coprime n) (am : a ∣ m)
    (bn : b ∣ n) : a = m.gcd (a * b) := by rw [gcd_comm]; 

Proof state:
a b m n : ℕ+
cop : Coprime m n
am : a ∣ m
bn : b ∣ n
⊢ a = gcd (a * b) m

Next tactic:
apply Coprime.factor_eq_gcd_left cop am bn
theorem Coprime.factor_eq_gcd_right_right {a b m n : ℕ+} (cop : m.Coprime n) (am : a ∣ m)
    (bn : b ∣ n) : a = m.gcd (b * a) := by
  

Proof state:
a b m n : ℕ+
cop : Coprime m n
am : a ∣ m
bn : b ∣ n
⊢ a = gcd m (b * a)

Next tactic:
rw [gcd_comm]
theorem Coprime.factor_eq_gcd_right_right {a b m n : ℕ+} (cop : m.Coprime n) (am : a ∣ m)
    (bn : b ∣ n) : a = m.gcd (b * a) := by
  rw [gcd_comm]
  

Proof state:
a b m n : ℕ+
cop : Coprime m n
am : a ∣ m
bn : b ∣ n
⊢ a = gcd (b * a) m

Next tactic:
apply Coprime.factor_eq_gcd_right cop am bn
theorem Coprime.gcd_mul (k : ℕ+) {m n : ℕ+} (h : m.Coprime n) :
    k.gcd (m * n) = k.gcd m * k.gcd n := by
  

Proof state:
k m n : ℕ+
h : Coprime m n
⊢ gcd k (m * n) = gcd k m * gcd k n

Next tactic:
rw [← coprime_coe] at h
theorem Coprime.gcd_mul (k : ℕ+) {m n : ℕ+} (h : m.Coprime n) :
    k.gcd (m * n) = k.gcd m * k.gcd n := by
  rw [← coprime_coe] at h; 

Proof state:
k m n : ℕ+
h : Nat.Coprime ↑m ↑n
⊢ gcd k (m * n) = gcd k m * gcd k n

Next tactic:
apply eq
theorem Coprime.gcd_mul (k : ℕ+) {m n : ℕ+} (h : m.Coprime n) :
    k.gcd (m * n) = k.gcd m * k.gcd n := by
  rw [← coprime_coe] at h; apply eq
  

Proof state:
case a
k m n : ℕ+
h : Nat.Coprime ↑m ↑n
⊢ ↑(gcd k (m * n)) = ↑(gcd k m * gcd k n)

Next tactic:
simp only [gcd_coe, mul_coe]
theorem Coprime.gcd_mul (k : ℕ+) {m n : ℕ+} (h : m.Coprime n) :
    k.gcd (m * n) = k.gcd m * k.gcd n := by
  rw [← coprime_coe] at h; apply eq
  simp only [gcd_coe, mul_coe]; 

Proof state:
case a
k m n : ℕ+
h : Nat.Coprime ↑m ↑n
⊢ Nat.gcd (↑k) (↑m * ↑n) = Nat.gcd ↑k ↑m * Nat.gcd ↑k ↑n

Next tactic:
apply Nat.Coprime.gcd_mul k h
theorem gcd_eq_left {m n : ℕ+} : m ∣ n → m.gcd n = m := by
  

Proof state:
m n : ℕ+
⊢ m ∣ n → gcd m n = m

Next tactic:
rw [dvd_iff]
theorem gcd_eq_left {m n : ℕ+} : m ∣ n → m.gcd n = m := by
  rw [dvd_iff]
  

Proof state:
m n : ℕ+
⊢ ↑m ∣ ↑n → gcd m n = m

Next tactic:
intro h
theorem gcd_eq_left {m n : ℕ+} : m ∣ n → m.gcd n = m := by
  rw [dvd_iff]
  intro h
  

Proof state:
m n : ℕ+
h : ↑m ∣ ↑n
⊢ gcd m n = m

Next tactic:
apply eq
theorem gcd_eq_left {m n : ℕ+} : m ∣ n → m.gcd n = m := by
  rw [dvd_iff]
  intro h
  apply eq
  

Proof state:
case a
m n : ℕ+
h : ↑m ∣ ↑n
⊢ ↑(gcd m n) = ↑m

Next tactic:
simp only [gcd_coe]
theorem gcd_eq_left {m n : ℕ+} : m ∣ n → m.gcd n = m := by
  rw [dvd_iff]
  intro h
  apply eq
  simp only [gcd_coe]
  

Proof state:
case a
m n : ℕ+
h : ↑m ∣ ↑n
⊢ Nat.gcd ↑m ↑n = ↑m

Next tactic:
apply Nat.gcd_eq_left h
theorem Coprime.pow {m n : ℕ+} (k l : ℕ) (h : m.Coprime n) : (m ^ k : ℕ).Coprime (n ^ l) := by
  

Proof state:
m n : ℕ+
k l : ℕ
h : Coprime m n
⊢ Nat.Coprime (↑m ^ k) (↑n ^ l)

Next tactic:
rw [← coprime_coe] at *
theorem Coprime.pow {m n : ℕ+} (k l : ℕ) (h : m.Coprime n) : (m ^ k : ℕ).Coprime (n ^ l) := by
  rw [← coprime_coe] at *; 

Proof state:
m n : ℕ+
k l : ℕ
h : Nat.Coprime ↑m ↑n
⊢ Nat.Coprime (↑m ^ k) (↑n ^ l)

Next tactic:
apply Nat.Coprime.pow
theorem Coprime.pow {m n : ℕ+} (k l : ℕ) (h : m.Coprime n) : (m ^ k : ℕ).Coprime (n ^ l) := by
  rw [← coprime_coe] at *; apply Nat.Coprime.pow; 

Proof state:
case H1
m n : ℕ+
k l : ℕ
h : Nat.Coprime ↑m ↑n
⊢ Nat.Coprime ↑m ↑n

Next tactic:
apply h
@[simp]
theorem comap_id_apply (x : σ → R) : comap (AlgHom.id R (MvPolynomial σ R)) x = x := by
  

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
x : σ → R
⊢ comap (AlgHom.id R (MvPolynomial σ R)) x = x

Next tactic:
funext i
@[simp]
theorem comap_id_apply (x : σ → R) : comap (AlgHom.id R (MvPolynomial σ R)) x = x := by
  funext i
  

Proof state:
case h
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
x : σ → R
i : σ
⊢ comap (AlgHom.id R (MvPolynomial σ R)) x i = x i

Next tactic:
simp only [comap, AlgHom.id_apply, id.def, aeval_X]
theorem comap_id : comap (AlgHom.id R (MvPolynomial σ R)) = id := by
  

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
⊢ comap (AlgHom.id R (MvPolynomial σ R)) = id

Next tactic:
funext x
theorem comap_id : comap (AlgHom.id R (MvPolynomial σ R)) = id := by
  funext x
  

Proof state:
case h
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
x : σ → R
⊢ comap (AlgHom.id R (MvPolynomial σ R)) x = id x

Next tactic:
exact comap_id_apply x
theorem comap_comp_apply (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) (x : υ → R) :
    comap (g.comp f) x = comap f (comap g x) := by
  

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
x : υ → R
⊢ comap (AlgHom.comp g f) x = comap f (comap g x)

Next tactic:
funext i
theorem comap_comp_apply (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) (x : υ → R) :
    comap (g.comp f) x = comap f (comap g x) := by
  funext i
  

Proof state:
case h
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
x : υ → R
i : σ
⊢ comap (AlgHom.comp g f) x i = comap f (comap g x) i

Next tactic:
trans aeval x (aeval (fun i => g (X i)) (f (X i)))
theorem comap_comp_apply (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) (x : υ → R) :
    comap (g.comp f) x = comap f (comap g x) := by
  funext i
  trans aeval x (aeval (fun i => g (X i)) (f (X i)))
  · 

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
x : υ → R
i : σ
⊢ comap (AlgHom.comp g f) x i = (aeval x) ((aeval fun i => g (X i)) (f (X i)))

Next tactic:
apply eval₂Hom_congr rfl rfl
theorem comap_comp_apply (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) (x : υ → R) :
    comap (g.comp f) x = comap f (comap g x) := by
  funext i
  trans aeval x (aeval (fun i => g (X i)) (f (X i)))
  · apply eval₂Hom_congr rfl rfl
    

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
x : υ → R
i : σ
⊢ (AlgHom.comp g f) (X i) = (aeval fun i => g (X i)) (f (X i))

Next tactic:
rw [AlgHom.comp_apply]
theorem comap_comp_apply (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) (x : υ → R) :
    comap (g.comp f) x = comap f (comap g x) := by
  funext i
  trans aeval x (aeval (fun i => g (X i)) (f (X i)))
  · apply eval₂Hom_congr rfl rfl
    rw [AlgHom.comp_apply]
    

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
x : υ → R
i : σ
⊢ g (f (X i)) = (aeval fun i => g (X i)) (f (X i))

Next tactic:
suffices g = aeval fun i => g (X i) by rw [← this]
theorem comap_comp_apply (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) (x : υ → R) :
    comap (g.comp f) x = comap f (comap g x) := by
  funext i
  trans aeval x (aeval (fun i => g (X i)) (f (X i)))
  · apply eval₂Hom_congr rfl rfl
    rw [AlgHom.comp_apply]
    suffices g = aeval fun i => g (X i) by 

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
x : υ → R
i : σ
this : g = aeval fun i => g (X i)
⊢ g (f (X i)) = (aeval fun i => g (X i)) (f (X i))

Next tactic:
rw [← this]
theorem comap_comp_apply (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) (x : υ → R) :
    comap (g.comp f) x = comap f (comap g x) := by
  funext i
  trans aeval x (aeval (fun i => g (X i)) (f (X i)))
  · apply eval₂Hom_congr rfl rfl
    rw [AlgHom.comp_apply]
    suffices g = aeval fun i => g (X i) by rw [← this]
    

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
x : υ → R
i : σ
⊢ g = aeval fun i => g (X i)

Next tactic:
exact aeval_unique g
theorem comap_comp_apply (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) (x : υ → R) :
    comap (g.comp f) x = comap f (comap g x) := by
  funext i
  trans aeval x (aeval (fun i => g (X i)) (f (X i)))
  · apply eval₂Hom_congr rfl rfl
    rw [AlgHom.comp_apply]
    suffices g = aeval fun i => g (X i) by rw [← this]
    exact aeval_unique g
  · 

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
x : υ → R
i : σ
⊢ (aeval x) ((aeval fun i => g (X i)) (f (X i))) = comap f (comap g x) i

Next tactic:
simp only [comap, aeval_eq_eval₂Hom, map_eval₂Hom, AlgHom.comp_apply]
theorem comap_comp_apply (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) (x : υ → R) :
    comap (g.comp f) x = comap f (comap g x) := by
  funext i
  trans aeval x (aeval (fun i => g (X i)) (f (X i)))
  · apply eval₂Hom_congr rfl rfl
    rw [AlgHom.comp_apply]
    suffices g = aeval fun i => g (X i) by rw [← this]
    exact aeval_unique g
  · simp only [comap, aeval_eq_eval₂Hom, map_eval₂Hom, AlgHom.comp_apply]
    

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
x : υ → R
i : σ
⊢ (eval₂Hom (RingHom.comp (eval₂Hom (algebraMap R R) x) (algebraMap R (MvPolynomial υ R))) fun i =>
        (eval₂Hom (algebraMap R R) x) (g (X i)))
      (f (X i)) =
    (eval₂Hom (algebraMap R R) (comap g x)) (f (X i))

Next tactic:
refine' eval₂Hom_congr _ rfl rfl
theorem comap_comp_apply (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) (x : υ → R) :
    comap (g.comp f) x = comap f (comap g x) := by
  funext i
  trans aeval x (aeval (fun i => g (X i)) (f (X i)))
  · apply eval₂Hom_congr rfl rfl
    rw [AlgHom.comp_apply]
    suffices g = aeval fun i => g (X i) by rw [← this]
    exact aeval_unique g
  · simp only [comap, aeval_eq_eval₂Hom, map_eval₂Hom, AlgHom.comp_apply]
    refine' eval₂Hom_congr _ rfl rfl
    

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
x : υ → R
i : σ
⊢ RingHom.comp (eval₂Hom (algebraMap R R) x) (algebraMap R (MvPolynomial υ R)) = algebraMap R R

Next tactic:
ext r
theorem comap_comp_apply (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) (x : υ → R) :
    comap (g.comp f) x = comap f (comap g x) := by
  funext i
  trans aeval x (aeval (fun i => g (X i)) (f (X i)))
  · apply eval₂Hom_congr rfl rfl
    rw [AlgHom.comp_apply]
    suffices g = aeval fun i => g (X i) by rw [← this]
    exact aeval_unique g
  · simp only [comap, aeval_eq_eval₂Hom, map_eval₂Hom, AlgHom.comp_apply]
    refine' eval₂Hom_congr _ rfl rfl
    ext r
    

Proof state:
case a
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
x : υ → R
i : σ
r : R
⊢ (RingHom.comp (eval₂Hom (algebraMap R R) x) (algebraMap R (MvPolynomial υ R))) r = (algebraMap R R) r

Next tactic:
apply aeval_C
theorem comap_comp (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) : comap (g.comp f) = comap f ∘ comap g := by
  

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
⊢ comap (AlgHom.comp g f) = comap f ∘ comap g

Next tactic:
funext x
theorem comap_comp (f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R)
    (g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R) : comap (g.comp f) = comap f ∘ comap g := by
  funext x
  

Proof state:
case h
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial τ R
g : MvPolynomial τ R →ₐ[R] MvPolynomial υ R
x : υ → R
⊢ comap (AlgHom.comp g f) x = (comap f ∘ comap g) x

Next tactic:
exact comap_comp_apply _ _ _
theorem comap_eq_id_of_eq_id (f : MvPolynomial σ R →ₐ[R] MvPolynomial σ R) (hf : ∀ φ, f φ = φ)
    (x : σ → R) : comap f x = x := by
  

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial σ R
hf : ∀ (φ : MvPolynomial σ R), f φ = φ
x : σ → R
⊢ comap f x = x

Next tactic:
convert comap_id_apply x
theorem comap_eq_id_of_eq_id (f : MvPolynomial σ R →ₐ[R] MvPolynomial σ R) (hf : ∀ φ, f φ = φ)
    (x : σ → R) : comap f x = x := by
  convert comap_id_apply x
  

Proof state:
case h.e'_2.h.e'_5
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial σ R
hf : ∀ (φ : MvPolynomial σ R), f φ = φ
x : σ → R
⊢ f = AlgHom.id R (MvPolynomial σ R)

Next tactic:
ext1 φ
theorem comap_eq_id_of_eq_id (f : MvPolynomial σ R →ₐ[R] MvPolynomial σ R) (hf : ∀ φ, f φ = φ)
    (x : σ → R) : comap f x = x := by
  convert comap_id_apply x
  ext1 φ
  

Proof state:
case h.e'_2.h.e'_5.hf
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R →ₐ[R] MvPolynomial σ R
hf : ∀ (φ : MvPolynomial σ R), f φ = φ
x : σ → R
φ : σ
⊢ f (X φ) = (AlgHom.id R (MvPolynomial σ R)) (X φ)

Next tactic:
simp [hf, AlgHom.id_apply]
theorem comap_rename (f : σ → τ) (x : τ → R) : comap (rename f) x = x ∘ f := by
  

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : σ → τ
x : τ → R
⊢ comap (rename f) x = x ∘ f

Next tactic:
funext
theorem comap_rename (f : σ → τ) (x : τ → R) : comap (rename f) x = x ∘ f := by
  funext
  

Proof state:
case h
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : σ → τ
x : τ → R
x✝ : σ
⊢ comap (rename f) x x✝ = (x ∘ f) x✝

Next tactic:
simp [rename_X, comap_apply, aeval_X]
/-- If two polynomial types over the same coefficient ring `R` are equivalent,
there is a bijection between the types of functions from their variable types to `R`.
-/
noncomputable def comapEquiv (f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R) : (τ → R) ≃ (σ → R) where
  toFun := comap f
  invFun := comap f.symm
  left_inv := by
    

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R
⊢ Function.LeftInverse (comap ↑(AlgEquiv.symm f)) (comap ↑f)

Next tactic:
intro x
/-- If two polynomial types over the same coefficient ring `R` are equivalent,
there is a bijection between the types of functions from their variable types to `R`.
-/
noncomputable def comapEquiv (f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R) : (τ → R) ≃ (σ → R) where
  toFun := comap f
  invFun := comap f.symm
  left_inv := by
    intro x
    

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R
x : τ → R
⊢ comap (↑(AlgEquiv.symm f)) (comap (↑f) x) = x

Next tactic:
rw [← comap_comp_apply]
/-- If two polynomial types over the same coefficient ring `R` are equivalent,
there is a bijection between the types of functions from their variable types to `R`.
-/
noncomputable def comapEquiv (f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R) : (τ → R) ≃ (σ → R) where
  toFun := comap f
  invFun := comap f.symm
  left_inv := by
    intro x
    rw [← comap_comp_apply]
    

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R
x : τ → R
⊢ comap (AlgHom.comp ↑f ↑(AlgEquiv.symm f)) x = x

Next tactic:
apply comap_eq_id_of_eq_id
/-- If two polynomial types over the same coefficient ring `R` are equivalent,
there is a bijection between the types of functions from their variable types to `R`.
-/
noncomputable def comapEquiv (f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R) : (τ → R) ≃ (σ → R) where
  toFun := comap f
  invFun := comap f.symm
  left_inv := by
    intro x
    rw [← comap_comp_apply]
    apply comap_eq_id_of_eq_id
    

Proof state:
case hf
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R
x : τ → R
⊢ ∀ (φ : MvPolynomial τ R), (AlgHom.comp ↑f ↑(AlgEquiv.symm f)) φ = φ

Next tactic:
intro
/-- If two polynomial types over the same coefficient ring `R` are equivalent,
there is a bijection between the types of functions from their variable types to `R`.
-/
noncomputable def comapEquiv (f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R) : (τ → R) ≃ (σ → R) where
  toFun := comap f
  invFun := comap f.symm
  left_inv := by
    intro x
    rw [← comap_comp_apply]
    apply comap_eq_id_of_eq_id
    intro
    

Proof state:
case hf
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R
x : τ → R
φ✝ : MvPolynomial τ R
⊢ (AlgHom.comp ↑f ↑(AlgEquiv.symm f)) φ✝ = φ✝

Next tactic:
simp only [AlgHom.id_apply, AlgEquiv.comp_symm]
/-- If two polynomial types over the same coefficient ring `R` are equivalent,
there is a bijection between the types of functions from their variable types to `R`.
-/
noncomputable def comapEquiv (f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R) : (τ → R) ≃ (σ → R) where
  toFun := comap f
  invFun := comap f.symm
  left_inv := by
    intro x
    rw [← comap_comp_apply]
    apply comap_eq_id_of_eq_id
    intro
    simp only [AlgHom.id_apply, AlgEquiv.comp_symm]
  right_inv := by
    

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R
⊢ Function.RightInverse (comap ↑(AlgEquiv.symm f)) (comap ↑f)

Next tactic:
intro x
/-- If two polynomial types over the same coefficient ring `R` are equivalent,
there is a bijection between the types of functions from their variable types to `R`.
-/
noncomputable def comapEquiv (f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R) : (τ → R) ≃ (σ → R) where
  toFun := comap f
  invFun := comap f.symm
  left_inv := by
    intro x
    rw [← comap_comp_apply]
    apply comap_eq_id_of_eq_id
    intro
    simp only [AlgHom.id_apply, AlgEquiv.comp_symm]
  right_inv := by
    intro x
    

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R
x : σ → R
⊢ comap (↑f) (comap (↑(AlgEquiv.symm f)) x) = x

Next tactic:
rw [← comap_comp_apply]
/-- If two polynomial types over the same coefficient ring `R` are equivalent,
there is a bijection between the types of functions from their variable types to `R`.
-/
noncomputable def comapEquiv (f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R) : (τ → R) ≃ (σ → R) where
  toFun := comap f
  invFun := comap f.symm
  left_inv := by
    intro x
    rw [← comap_comp_apply]
    apply comap_eq_id_of_eq_id
    intro
    simp only [AlgHom.id_apply, AlgEquiv.comp_symm]
  right_inv := by
    intro x
    rw [← comap_comp_apply]
    

Proof state:
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R
x : σ → R
⊢ comap (AlgHom.comp ↑(AlgEquiv.symm f) ↑f) x = x

Next tactic:
apply comap_eq_id_of_eq_id