import data.real.basic
import order.lattice
noncomputable theory

section curried

variables {α α' β γ δ : Type*}

class curried (α β γ δ : Type*) :=
(comp (f : γ → δ) : α → β)

instance curried_base : curried (α → γ) (α → δ) γ δ := ⟨λ f g x, f (g x)⟩

instance curried_induction [curried α β γ δ] : curried (α' → α) (α' → β) γ δ :=
⟨λ f g x, curried.comp f (g x)⟩

end curried

example: curried.comp (nat.succ) (λ x y z : ℕ, 0) = (λ x y z : ℕ, 1) := rfl

universe variables u v w x

-- Need filters for non-sets! (Mario already proposed that refactoring)
-- Add non-empty axiom?
structure filter (α : Type*) [partial_order α] :=
(elements : set α)
(nonempty : ∃ x, x ∈ elements)
(exists_inf (x y : α) : x ∈ elements → y ∈ elements → ∃ z, z ≤ x ∧ z ≤ y ∧ z ∈ elements)
(mem_elements_of_le (x y : α) : x ∈ elements → x ≤ y → y ∈ elements)

instance {α : Type*} [partial_order α] : has_mem α (filter α) := ⟨λ U F, U ∈ F.elements⟩

namespace filter
variables {α : Type u}
variables [partial_order α] {f g : filter α} {s t : α}

open set

@[simp] protected lemma mem_mk {t : set α} {h₁ h₂ h₃} : s ∈ mk t h₁ h₂ h₃ ↔ s ∈ t := iff.rfl

@[simp] protected lemma mem_elements : s ∈ f.elements ↔ s ∈ f := iff.rfl

lemma filter_eq : ∀{f g : filter α}, f.elements = g.elements → f = g
| ⟨_, _, _, _⟩ ⟨_, _, _, _⟩ rfl := rfl

lemma filter_eq_iff : f = g ↔ f.elements = g.elements :=
⟨congr_arg _, filter_eq⟩

protected lemma ext_iff : f = g ↔ ∀ s, s ∈ f ↔ s ∈ g :=
by simp only [filter_eq_iff, ext_iff, filter.mem_elements]

@[ext]
protected lemma ext : (∀ s, s ∈ f ↔ s ∈ g) → f = g :=
filter.ext_iff.2

lemma mem_sets_of_superset : ∀{x y : α}, x ∈ f → x ≤ y → y ∈ f :=
f.mem_elements_of_le

section principal

/-- The principal filter of `s` is the set of all elements larger than or equal to `s`. -/
def principal (s : α) : filter α :=
{ elements := {t | s ≤ t},
  nonempty := ⟨s, le_refl s⟩,
  exists_inf := λ x y hx hy, ⟨s, hx, hy, le_refl s⟩,
  mem_elements_of_le := λ x y hx hxy, le_trans hx hxy }

localized "notation `𝓟` := filter.principal" in filter

instance [inhabited α]: inhabited (filter α) :=
⟨𝓟 (default α)⟩

instance : complete_lattice (filter α) := sorry
end principal

open_locale filter

def at_top [preorder α] : filter (set α) := ⨅ a, 𝓟 (Ici a)

end filter

def filter.Limsup (f : filter (set ℝ)) : ℝ := Inf { a | {n | n ≤ a} ∈ f }

variables {α α' β γ δ : Type*} [partial_order β]

def filter.map (f : filter (set ℝ)) [curried α β ℝ Prop] (u : α) : filter β := sorry

def limsup (f : filter (set ℝ)) [curried α β ℝ Prop] (u : α) : ℝ := (f.map u).Limsup

def at_top [has_bot α] [partial_order β] [preorder γ] [curried α β ℝ Prop] : filter β :=
  ⨅ a : ℝ, filter.principal (curried.comp (λ x, a ≤ x) (⊥ : α))

-- section semilattice_inf

-- variables {α : Type u}
-- variables [semilattice_inf α] {f g : filter α} {s t : α}

-- open semilattice_inf

-- namespace filter

-- def of_semilattice (α : Type*) [semilattice_inf α] (elements : set α)
--   (inf_in_elements : ∀ x y, x ∈ elements → y ∈ elements → semilattice_inf.inf x y ∈ elements)
--   (in_elements_of_le : ∀ x y, x ∈ elements → x ≤ y → y ∈ elements) :
--   filter α :=

-- example: semilattice_inf (ℕ → ℕ → ℕ → ℕ → ℕ → ℕ → ℕ → Prop) := by apply_instance

-- def of_set (α : Type*) (elements : set (set α))
--   (inf_in_elements : ∀ x y, x ∈ elements → y ∈ elements → x ∩ y ∈ elements)
--   (in_elements_of_le : ∀ x y, x ∈ elements → x ⊆ y → y ∈ elements) :
--   filter (set α) :=
-- of_semilattice (set α) elements inf_in_elements in_elements_of_le

-- end filter

-- def solution (f : ℝ → ℝ) :=
-- { a : ℝ // a = filter.at_bot.liminf (λ x, f x)}

def solution (f : ℝ → ℝ) :=
Σ' a : ℝ, a = filter.at_bot.liminf (λ x, f x)

#check filter.liminf

#check optimize (λ (x : ℝ) (y : ℝ) (h : x + y ≤ 0), x - y)


/-
Copyright (c) 2017 Johannes Hölzl. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Johannes Hölzl
-/
import tactic.lint
import tactic.ext
import tactic.simps

open function

namespace subtype
variables {α : Sort*} {β : Sort*} {γ : Sort*} {p : α → Prop} {q : α → Prop}

/-- See Note [custom simps projection] -/
def simps.coe (x : subtype p) : α := x

initialize_simps_projections subtype (val → coe)

/-- A version of `x.property` or `x.2` where `p` is syntactically applied to the coercion of `x`
  instead of `x.1`. A similar result is `subtype.mem` in `data.set.basic`. -/
lemma prop (x : subtype p) : p x := x.2

@[simp] lemma val_eq_coe {x : subtype p} : x.1 = ↑x := rfl

@[simp] protected theorem «forall» {q : {a // p a} → Prop} :
  (∀ x, q x) ↔ (∀ a b, q ⟨a, b⟩) :=
⟨assume h a b, h ⟨a, b⟩, assume h ⟨a, b⟩, h a b⟩

/-- An alternative version of `subtype.forall`. This one is useful if Lean cannot figure out `q`
  when using `subtype.forall` from right to left. -/
protected theorem forall' {q : ∀x, p x → Prop} :
  (∀ x h, q x h) ↔ (∀ x : {a // p a}, q x x.2) :=
(@subtype.forall _ _ (λ x, q x.1 x.2)).symm

@[simp] protected theorem «exists» {q : {a // p a} → Prop} :
  (∃ x, q x) ↔ (∃ a b, q ⟨a, b⟩) :=
⟨assume ⟨⟨a, b⟩, h⟩, ⟨a, b, h⟩, assume ⟨a, b, h⟩, ⟨⟨a, b⟩, h⟩⟩

@[ext] protected lemma ext : ∀ {a1 a2 : {x // p x}}, (a1 : α) = (a2 : α) → a1 = a2
| ⟨x, h1⟩ ⟨.(x), h2⟩ rfl := rfl

lemma ext_iff {a1 a2 : {x // p x}} : a1 = a2 ↔ (a1 : α) = (a2 : α) :=
⟨congr_arg _, subtype.ext⟩

lemma heq_iff_coe_eq (h : ∀ x, p x ↔ q x) {a1 : {x // p x}} {a2 : {x // q x}} :
  a1 == a2 ↔ (a1 : α) = (a2 : α) :=
eq.rec (λ a2', heq_iff_eq.trans ext_iff) (funext $ λ x, propext (h x)) a2

lemma ext_val {a1 a2 : {x // p x}} : a1.1 = a2.1 → a1 = a2 :=
subtype.ext

lemma ext_iff_val {a1 a2 : {x // p x}} : a1 = a2 ↔ a1.1 = a2.1 :=
ext_iff

@[simp] theorem coe_eta (a : {a // p a}) (h : p a) : mk ↑a h = a := subtype.ext rfl

@[simp] theorem coe_mk (a h) : (@mk α p a h : α) = a := rfl

@[simp, nolint simp_nf] -- built-in reduction doesn't always work
theorem mk_eq_mk {a h a' h'} : @mk α p a h = @mk α p a' h' ↔ a = a' :=
ext_iff

theorem coe_eq_iff {a : {a // p a}} {b : α} : ↑a = b ↔ ∃ h, a = ⟨b, h⟩ :=
⟨λ h, h ▸ ⟨a.2, (coe_eta _ _).symm⟩, λ ⟨hb, ha⟩, ha.symm ▸ rfl⟩

theorem coe_injective : injective (coe : subtype p → α) :=
λ a b, subtype.ext

theorem val_injective : injective (@val _ p) :=
coe_injective

/-- Restrict a (dependent) function to a subtype -/
def restrict {α} {β : α → Type*} (f : Πx, β x) (p : α → Prop) (x : subtype p) : β x.1 :=
f x

lemma restrict_apply {α} {β : α → Type*} (f : Πx, β x) (p : α → Prop) (x : subtype p) :
  restrict f p x = f x.1 :=
by refl

lemma restrict_def {α β} (f : α → β) (p : α → Prop) : restrict f p = f ∘ coe :=
by refl

lemma restrict_injective {α β} {f : α → β} (p : α → Prop) (h : injective f) :
  injective (restrict f p) :=
h.comp coe_injective

/-- Defining a map into a subtype, this can be seen as an "coinduction principle" of `subtype`-/
@[simps] def coind {α β} (f : α → β) {p : β → Prop} (h : ∀a, p (f a)) : α → subtype p :=
λ a, ⟨f a, h a⟩

theorem coind_injective {α β} {f : α → β} {p : β → Prop} (h : ∀a, p (f a))
  (hf : injective f) : injective (coind f h) :=
λ x y hxy, hf $ by apply congr_arg subtype.val hxy

theorem coind_surjective {α β} {f : α → β} {p : β → Prop} (h : ∀a, p (f a))
  (hf : surjective f) : surjective (coind f h) :=
λ x, let ⟨a, ha⟩ := hf x in ⟨a, coe_injective ha⟩

theorem coind_bijective {α β} {f : α → β} {p : β → Prop} (h : ∀a, p (f a))
  (hf : bijective f) : bijective (coind f h) :=
⟨coind_injective h hf.1, coind_surjective h hf.2⟩

/-- Restriction of a function to a function on subtypes. -/
@[simps] def map {p : α → Prop} {q : β → Prop} (f : α → β) (h : ∀a, p a → q (f a)) :
  subtype p → subtype q :=
λ x, ⟨f x, h x x.prop⟩

theorem map_comp {p : α → Prop} {q : β → Prop} {r : γ → Prop} {x : subtype p}
  (f : α → β) (h : ∀a, p a → q (f a)) (g : β → γ) (l : ∀a, q a → r (g a)) :
  map g l (map f h x) = map (g ∘ f) (assume a ha, l (f a) $ h a ha) x :=
rfl

theorem map_id {p : α → Prop} {h : ∀a, p a → p (id a)} : map (@id α) h = id :=
funext $ assume ⟨v, h⟩, rfl

lemma map_injective {p : α → Prop} {q : β → Prop} {f : α → β} (h : ∀a, p a → q (f a))
  (hf : injective f) : injective (map f h) :=
coind_injective _ $ hf.comp coe_injective

lemma map_involutive {p : α → Prop} {f : α → α} (h : ∀a, p a → p (f a))
  (hf : involutive f) : involutive (map f h) :=
λ x, subtype.ext (hf x)

instance [has_equiv α] (p : α → Prop) : has_equiv (subtype p) :=
⟨λ s t, (s : α) ≈ (t : α)⟩

theorem equiv_iff [has_equiv α] {p : α → Prop} {s t : subtype p} :
  s ≈ t ↔ (s : α) ≈ (t : α) :=
iff.rfl

variables [setoid α]

protected theorem refl (s : subtype p) : s ≈ s :=
setoid.refl ↑s

protected theorem symm {s t : subtype p} (h : s ≈ t) : t ≈ s :=
setoid.symm h

protected theorem trans {s t u : subtype p} (h₁ : s ≈ t) (h₂ : t ≈ u) : s ≈ u :=
setoid.trans h₁ h₂

theorem equivalence (p : α → Prop) : equivalence (@has_equiv.equiv (subtype p) _) :=
mk_equivalence _ subtype.refl (@subtype.symm _ p _) (@subtype.trans _ p _)

instance (p : α → Prop) : setoid (subtype p) :=
setoid.mk (≈) (equivalence p)

end subtype

namespace subtype
/-! Some facts about sets, which require that `α` is a type. -/
variables {α : Type*} {β : Type*} {γ : Type*} {p : α → Prop}

@[simp] lemma coe_prop {S : set α} (a : {a // a ∈ S}) : ↑a ∈ S := a.prop

lemma val_prop {S : set α} (a : {a // a ∈ S}) : a.val ∈ S := a.property

end subtype


/-
Copyright (c) 2020 Scott Morrison. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Scott Morrison
-/
import category_theory.concrete_category.basic
import category_theory.reflects_isomorphisms

/-!
A `forget₂ C D` forgetful functor between concrete categories `C` and `D`
whose forgetful functors both reflect isomorphisms, itself reflects isomorphisms.
-/

universes u

namespace category_theory

instance : reflects_isomorphisms (forget (Type u)) :=
{ reflects := λ X Y f i, i }

variables (C : Type (u+1)) [category C] [concrete_category.{u} C]
variables (D : Type (u+1)) [category D] [concrete_category.{u} D]

/--
A `forget₂ C D` forgetful functor between concrete categories `C` and `D`
where `forget C` reflects isomorphisms, itself reflects isomorphisms.
-/
-- This should not be an instance, as it causes a typeclass loop
-- with `category_theory.has_forget_to_Type`
lemma reflects_isomorphisms_forget₂ [has_forget₂ C D] [reflects_isomorphisms (forget C)] :
  reflects_isomorphisms (forget₂ C D) :=
{ reflects := λ X Y f i,
  begin
    resetI,
    haveI i' : is_iso ((forget D).map ((forget₂ C D).map f)) := functor.map_is_iso (forget D) _,
    haveI : is_iso ((forget C).map f) :=
    begin
      have := has_forget₂.forget_comp,
      dsimp at this,
      rw ←this,
      exact i',
    end,
    apply is_iso_of_reflects_iso f (forget C),
  end }

end category_theory


import analysis.exponential analysis.polynomial
import ring_theory.prime_count

open complex polynomial finset

-- inductive lep (p : polynomial ℂ) : polynomial ℂ → Prop
-- | C_mul   : ∀ {a}, a ≠ 0 → lep (C a * p)
-- | mul     : ∀ {q}, lep q → lep (q * X)
-- | add     : ∀ {q} {a}, lep q → q ≠ -C a → lep (q + C a)

-- inductive ltp (p : polynomial ℂ) : polynomial ℂ → Prop
-- | mul_X : p ≠ 0 → ltp (p * X)
-- | mul_C : ∀ {a q}, a ≠ 0 → ltp q → ltp (C a * q)
-- | add   : ∀ {q} {a}, ltp q → q.eval 0 ≠ a → ltp (q + C a)

-- inductive ltp' : polynomial ℂ → polynomial ℂ → Prop
-- | mul_X : ∀ {p}, p ≠ 0 → ltp' p (p * X)
-- | mul_C : ∀ {p q a}, a ≠ 0 → ltp' p q → ltp' p (C a * q)
-- | add   : ∀ {p q a}, ltp' p q → q.eval 0 ≠ a → ltp' p (q + C a)

-- lemma growth_lemma_chris1 {p q : polynomial ℂ} (hpq : ltp p q) :
--   ∃ r : ℝ, ∀ z : ℂ, r < z.abs →
--    abs (p.eval z) < abs (q.eval z) :=
-- ltp.rec_on hpq
--   (λ hq g hpq, ⟨1, λ z hz, by rw [eval_mul, eval_X, complex.abs_mul];
--     exact _⟩)
--   _
--   (λ q a hqp hpa ih p, _)

-- lemma growth_lemma_chris1 {p q : polynomial ℂ} (hpq : ltp' q p) :
--   ∃ r : ℝ, ∀ z : ℂ, r < z.abs → abs (q.eval z) < abs (p.eval z) :=
-- ltp'.rec_on hpq
--   _
--   _
--   (λ p a hqp hpa _, _)

-- example : ∀ p : polynomial ℂ, ¬less_than p 0 :=
-- λ p h, less_than.rec_on h _ _ _

-- lemma polynomial_tendsto_infinity : ∀ {p : polynomial ℂ}, 0 < degree p →
--   ∀ x : ℝ, ∃ r : ℝ, ∀ z : ℂ, r < z.abs → x < (p.eval z).abs
-- | p := λ hp x, if h : degree p = 1
-- then
--   let ⟨n, hn⟩ := archimedean.arch (1 : ℝ)
--     (show 0 < abs (leading_coeff p),
--       from abs_pos.2 (λ hp0, by simp * at *; contradiction)) in
--   ⟨↑n * abs (p.eval 0) + n * (_root_.abs x), λ z hz,
--     calc x ≤ _root_.abs x : le_abs_self _
--     ... < abs (p.eval z) : lt_of_mul_lt_mul_left
--       (calc (n : ℝ) * _root_.abs x < abs z - n * abs (eval 0 p) :
--           lt_sub_iff_add_lt'.2 hz
--         ... ≤ n * abs (leading_coeff p * z) - n * abs (p.eval 0) :
--           sub_le_sub_right (by rw [complex.abs_mul, ← mul_assoc];
--           exact le_mul_of_ge_one_left (complex.abs_nonneg _)
--             (by simpa [mul_comm, add_monoid.smul_eq_mul] using hn)) _
--         ... = ↑n * (abs (leading_coeff p * z) - abs (-eval 0 p)) : by simp [mul_add]
--         ... ≤ ↑n * (abs (leading_coeff p * z - -eval 0 p)) :
--           mul_le_mul_of_nonneg_left
--             (le_trans (le_abs_self _) (complex.abs_abs_sub_le_abs_sub _ _))
--             (nat.cast_nonneg n)
--         ... = ↑n * abs (p.eval z) :
--           by conv_rhs {rw degree_eq_one h}; simp [coeff_zero_eq_eval_zero])
--       (nat.cast_nonneg n)⟩
-- else
--   have wf : degree (p /ₘ X) < degree p,
--     from degree_div_by_monic_lt _ monic_X (λ hp0, by simp * at *)
--       (by rw degree_X; exact dec_trivial),
--   have hp : 1 < degree p, from match degree p, hp, h with
--     | none    := dec_trivial
--     | (some n) := λ h0 h1, lt_of_le_of_ne (with_bot.coe_le_coe.2 (with_bot.coe_lt_coe.1 h0)) (ne.symm h1)
--     end,
--   have hXp : degree X ≤ degree p, from le_of_lt (by rw @degree_X ℂ; exact hp),
--   let ⟨r, hr⟩ := @polynomial_tendsto_infinity (p /ₘ X)
--     (@lt_of_add_lt_add_left' _ _ (1 : with_bot ℕ) _ _
--       (calc (1 : with_bot ℕ) + 0 < degree p : hp
--         ... = 1 + degree (p /ₘ X) : by rw [← @degree_X ℂ, degree_add_div_by_monic monic_X hXp]))
--   (x + (p.eval 0).abs) in
--   ⟨max 1 (r + (p.eval 0).abs), λ z hz,
--     calc x < abs (eval z (p /ₘ X)) - abs (eval 0 p) :
--       lt_sub_iff_add_lt.2 (hr z (lt_of_le_of_lt (le_add_of_nonneg_right (complex.abs_nonneg _))
--         (lt_of_le_of_lt (le_max_right _ _) hz)))
--     ... ≤ abs z * abs (eval z (p /ₘ X)) - abs (eval 0 p) :
--       sub_le_sub_right (le_mul_of_ge_one_left (complex.abs_nonneg _) (le_trans (le_max_left _ _) (le_of_lt hz))) _
--     ... ≤ _root_.abs (abs (z * eval z (p /ₘ X)) - abs (-eval 0 p)) : by rw [complex.abs_neg, ← complex.abs_mul];
--       exact le_abs_self _
--     ... ≤ abs (z * eval z (p /ₘ X) - -eval 0 p) : abs_abs_sub_le_abs_sub _ _
--     ... = abs (eval z p) : by conv_rhs {rw ← mod_by_monic_add_div p monic_X};
--       simp [coeff_zero_eq_eval_zero, mod_by_monic_X]⟩
-- using_well_founded {dec_tac := tactic.assumption}

-- @[elab_as_eliminator] protected lemma induction_on {M : polynomial ℂ → Prop} (p : polynomial ℂ )
--   (h_C : ∀a, M (C a))
--   (h_add : ∀p q, M p → M q → M (p + q))
--   (h_monomial : ∀(n : ℕ) (a : ℂ), M (C a * X^n) → M (C a * X^(n+1))) :
--   M p :=
-- have ∀{n:ℕ} {a}, M (C a * X^n),
-- begin
--   assume n a,
--   induction n with n ih,
--   { simp only [pow_zero, mul_one, h_C] },
--   { exact h_monomial _ _ ih }
-- end,
-- finsupp.induction p
--   (suffices M (C 0), by simpa only [C, single_zero],
--     h_C 0)
--   (assume n a p _ _ hp, suffices M (C a * X^n + p), by rwa [single_eq_C_mul_X],
--     h_add _ _ this hp)

inductive nonconstant : polynomial ℂ → Prop
| X   : ∀ {a}, a ≠ 0 → nonconstant (C a * X)
| mul : ∀ {p}, nonconstant p → nonconstant (p * X)
| add : ∀ {p} (a), nonconstant p → nonconstant (p + C a)

lemma nonconstant_of_degree_pos : ∀ {p : polynomial ℂ},
  0 < degree p → nonconstant p
| p := λ h,
have wf : degree (p /ₘ X) < degree p,
  from degree_div_by_monic_lt _ monic_X
  (λ hp0, by simp [hp0, lt_irrefl, *] at *)
  (by rw degree_X; exact dec_trivial),
by rw [← mod_by_monic_add_div p monic_X,
  add_comm, mod_by_monic_X, mul_comm] at *;
exact nonconstant.add _
  (if hpX : 0 < degree (p /ₘ X)
    then nonconstant.mul (nonconstant_of_degree_pos hpX)
    else by rw [eq_C_of_degree_le_zero (not_lt.1 hpX)] at *;
      exact if hc : coeff (p /ₘ X) 0 = 0
        then by simpa [hc, not_lt_of_ge degree_C_le] using h
        else nonconstant.X hc)
using_well_founded {dec_tac := tactic.assumption}

lemma polynomial_tendsto_infinity' {p : polynomial ℂ} (h : 0 < degree p) :
  ∀ x : ℝ, ∃ r : ℝ, ∀ z : ℂ, r < z.abs → x < (p.eval z).abs :=
nonconstant.rec_on (nonconstant_of_degree_pos h)
  (λ a ha x, ⟨x / a.abs, λ z hz,
    by simpa [(div_lt_iff' (complex.abs_pos.2 ha)).symm]⟩)
  (λ p hp ih x, let ⟨r, hr⟩ := ih x in
    ⟨max r 1, λ z hz, by rw [eval_mul, eval_X, complex.abs_mul];
        exact lt_of_lt_of_le (hr z (lt_of_le_of_lt (le_max_left _ _) hz))
          (le_mul_of_ge_one_right (complex.abs_nonneg _)
            (le_trans (le_max_right _ _) (le_of_lt hz)))⟩)
  (λ p a hp ih x, let ⟨r, hr⟩ := ih (x + a.abs) in
    ⟨r, λ z hz, by rw [eval_add, eval_C, ← sub_neg_eq_add];
      exact lt_of_lt_of_le (lt_sub_iff_add_lt.2
        (by rw complex.abs_neg; exact (hr z hz)))
        (le_trans (le_abs_self _) (complex.abs_abs_sub_le_abs_sub _ _))⟩)

lemma polynomial.is_unit_iff {p : polynomial ℂ} : is_unit p ↔ degree p = 0 :=
⟨λ h, let ⟨q, hq⟩ := is_unit_iff_dvd_one.1 h in
    have hp0 : p ≠ 0, from λ hp0, by simpa [hp0] using hq,
    have hq0 : q ≠ 0, from λ hp0, by simpa [hp0] using hq,
    have nat_degree (1 : polynomial ℂ) = nat_degree (p * q),
      from congr_arg _ hq,
    by rw [nat_degree_one, nat_degree_mul_eq hp0 hq0, eq_comm,
        add_eq_zero_iff, ← with_bot.coe_eq_coe,
        ← degree_eq_nat_degree hp0] at this;
      exact this.1,
  λ h, have degree p ≤ 0, by simp [*, le_refl],
    have hc : coeff p 0 ≠ 0, from λ hc,
        by rw [eq_C_of_degree_le_zero this, hc] at h;
        simpa using h,
    is_unit_iff_dvd_one.2 ⟨C (coeff p 0)⁻¹, begin
      conv in p { rw eq_C_of_degree_le_zero this },
      rw [← C_mul, _root_.mul_inv_cancel hc, C_1]
    end⟩⟩

instance decidable_dvd {α : Type*} [comm_ring α] [decidable_eq α] :
  decidable_rel ((∣) : polynomial α → polynomial α → Prop) :=
sorry

lemma polynomial.finite_of_degree_pos {α : Type*} [integral_domain α] [decidable_eq α]
  {p q : polynomial α} (hp : (0 : with_bot ℕ) < degree p) (hq : q ≠ 0) :
  prime_count.finite p q :=
⟨nat_degree q, λ ⟨r, hr⟩,
  have hp0 : p ≠ 0, from λ hp0, by simp [hp0] at hp; contradiction,
  have hr0 : r ≠ 0, from λ hr0, by simp * at *,
  have hpn0 : p ^ (nat_degree q + 1) ≠ 0,
    from pow_ne_zero _ hp0,
  have hnp : 0 < nat_degree p,
    by rw [← with_bot.coe_lt_coe, ← degree_eq_nat_degree hp0];
    exact hp,
  begin
    have := congr_arg nat_degree hr,
    rw [nat_degree_mul_eq hpn0 hr0, nat_degree_pow_eq, add_mul, add_assoc] at this,
    exact ne_of_lt (lt_add_of_le_of_pos (le_mul_of_ge_one_right' (nat.zero_le _) hnp)
      (add_pos_of_pos_of_nonneg (by rwa one_mul) (nat.zero_le _))) this
  end⟩

def polynomial.multiplicity {α : Type*} [integral_domain α] [decidable_eq α]
  (p : polynomial α) (a :  α) : ℕ :=
if h0 : p = 0 then 0 else
(prime_count (X - C a) p).get (polynomial.finite_of_degree_pos
  (by rw degree_X_sub_C; exact dec_trivial) h0)

lemma pow_multiplicity_dvd {α : Type*} [integral_domain α] [decidable_eq α]
  (p : polynomial α) (a : α) :
  (X - C a) ^ polynomial.multiplicity p a ∣ p :=
if h : p = 0 then by simp [h]
else by rw [polynomial.multiplicity, dif_neg h];
  exact prime_count.spec _

lemma div_by_monic_mul_pow_multiplicity_eq
  {α : Type*} [integral_domain α] [decidable_eq α]
  (p : polynomial α) (a : α) :
  p /ₘ ((X - C a) ^ polynomial.multiplicity p a) *
  (X - C a) ^ polynomial.multiplicity p a = p :=
have monic ((X - C a) ^ polynomial.multiplicity p a),
  from by rw [monic.def, leading_coeff_pow,
    (show _ = _, from monic_X_sub_C _), one_pow],
by conv_rhs { rw [← mod_by_monic_add_div p this,
    (dvd_iff_mod_by_monic_eq_zero this).2 (pow_multiplicity_dvd _ _)] };
  simp [mul_comm]

lemma eval_div_by_monic_pow_multiplicity_ne_zero
  {α : Type*} [integral_domain α] [decidable_eq α]
  {p : polynomial α} (a : α) (hp : p ≠ 0) :
  (p /ₘ ((X - C a) ^ polynomial.multiplicity p a)).eval a ≠ 0 :=
mt dvd_iff_is_root.2 $ λ ⟨q, hq⟩,
begin
  have := div_by_monic_mul_pow_multiplicity_eq p a,
  rw [mul_comm, hq, ← mul_assoc, ← pow_succ',
    polynomial.multiplicity, dif_neg hp] at this,
  refine prime_count.is_greatest'
    (polynomial.finite_of_degree_pos
    (show (0 : with_bot ℕ) < degree (X - C a),
      by rw degree_X_sub_C; exact dec_trivial) hp)
    (nat.lt_succ_self _) (dvd_of_mul_right_eq _ this)
end

axiom attains_infi (p : polynomial ℂ) :
  ∃ x, (p.eval x).abs = ⨅ y, (p.eval y).abs

axiom nth_root (n : ℕ) (z : ℂ) : ℂ

axiom nth_root_pow (n : ℕ) (z : ℂ) : nth_root n z ^ n = z

axiom abs_nth_root (n : ℕ) (z : ℂ) : abs (nth_root n z) =
  real.nth_root (abs z) n

#print real.nth_root

open euclidean_domain
local attribute [instance, priority 0] classical.prop_decidable
set_option trace.simplify.rewrite true
lemma FTA {f : polynomial ℂ} (hf : 0 < degree f) : ∃ z : ℂ, is_root f z :=
let ⟨z₀, hz₀⟩ := attains_infi f in
exists.intro z₀ $ by_contradiction $ λ hf0,
have hfX : f - C (f.eval z₀) ≠ 0,
  from mt sub_eq_zero.1 (λ h, not_le_of_gt hf
    (h.symm ▸ degree_C_le)),
let n := polynomial.multiplicity (f - C (f.eval z₀)) z₀ in
let g := (f - C (f.eval z₀)) /ₘ ((X - C z₀) ^ n) in
have hg0 : g.eval z₀ ≠ 0, from eval_div_by_monic_pow_multiplicity_ne_zero _ hfX,
have hg : g * (X - C z₀) ^ n = f - C (f.eval z₀),
  from div_by_monic_mul_pow_multiplicity_eq _ _,
have hn0 : 0 < n, from nat.pos_of_ne_zero $ λ hn0,
  by simpa [g, hn0] using hg0,
let ⟨δ', hδ'₁, hδ'₂⟩ := continuous_of_metric.1 (polynomial.continuous_eval g) z₀
  ((g.eval z₀).abs) (complex.abs_pos.2 hg0) in
let δ := min (min (δ' / 2) 1) (((f.eval z₀).abs / (g.eval z₀).abs) / 2) in
have hf0' : 0 < (f.eval z₀).abs, from complex.abs_pos.2 hf0,
have hfg0 : 0 < abs (eval z₀ f) * (abs (eval z₀ g))⁻¹,
  from div_pos hf0' (complex.abs_pos.2 hg0),
have hδ0 : 0 < δ, from lt_min
  (lt_min (half_pos hδ'₁) (by norm_num)) (half_pos hfg0),
have hδ : ∀ z : ℂ, abs (z - z₀) = δ → abs (g.eval z - g.eval z₀) <
  (g.eval z₀).abs,
  from λ z hz, hδ'₂ z (by rw [complex.dist_eq, hz];
    exact lt_of_le_of_lt (le_trans (min_le_left _ _) (min_le_left _ _))
      (half_lt_self hδ'₁)),
have hδ1 : δ ≤ 1, from le_trans (min_le_left _ _) (min_le_right _ _),
let F : polynomial ℂ := C (f.eval z₀) + C (g.eval z₀) * (X - C z₀) ^ n in
let z' := nth_root n (-f.eval z₀ * (g.eval z₀).abs * δ ^ n /
  ((f.eval z₀).abs * g.eval z₀)) + z₀ in
have hF₁ : F.eval z' = f.eval z₀ - f.eval z₀ * (g.eval z₀).abs
    * δ ^ n / (f.eval z₀).abs,
  by simp [F, nth_root_pow, div_eq_mul_inv, eval_pow, mul_assoc,
      mul_comm (g.eval z₀),
      mul_left_comm (g.eval z₀), mul_left_comm (g.eval z₀)⁻¹,
      mul_inv', inv_mul_cancel hg0];
    simp [mul_comm, mul_left_comm, mul_assoc],
have hδs : (g.eval z₀).abs * δ ^ n / (f.eval z₀).abs < 1,
  begin
    rw [div_eq_mul_inv, mul_right_comm, mul_comm,
      ← @inv_inv' _ _ (complex.abs _ * _), mul_inv',
      inv_inv', ← div_eq_mul_inv, div_lt_iff hfg0, one_mul],
    calc δ ^ n ≤ δ ^ 1 : pow_le_pow_of_le_one
        (le_of_lt hδ0) hδ1 hn0
      ... = δ : _root_.pow_one _
      ... ≤ ((f.eval z₀).abs / (g.eval z₀).abs) / 2 : min_le_right _ _
      ... < _ : half_lt_self hfg0
  end,
have hF₂ : (F.eval z').abs = (f.eval z₀).abs - (g.eval z₀).abs * δ ^ n,
  from calc (F.eval z').abs = (f.eval z₀ - f.eval z₀ * (g.eval z₀).abs
    * δ ^ n / (f.eval z₀).abs).abs : congr_arg abs hF₁
  ... = abs (f.eval z₀) * complex.abs (1 - (g.eval z₀).abs * δ ^ n /
      (f.eval z₀).abs : ℝ) : by rw [← complex.abs_mul];
        exact congr_arg complex.abs
          (by simp [mul_add, add_mul, mul_assoc, div_eq_mul_inv])
  ... = _ : by rw [complex.abs_of_nonneg (sub_nonneg.2 (le_of_lt hδs)),
      mul_sub, mul_div_cancel' _ (ne.symm (ne_of_lt hf0')), mul_one],
have hef0 : abs (eval z₀ g) * (eval z₀ f).abs ≠ 0,
  from mul_ne_zero (mt complex.abs_eq_zero.1 hg0)
    (mt complex.abs_eq_zero.1 hf0),
have hz'z₀ : abs (z' - z₀) = δ :=
  begin
     simp [z', mul_assoc, mul_left_comm _ (_ ^ n),
      mul_comm _ (_ ^ n), mul_comm (eval z₀ f).abs,
      _root_.mul_div_cancel _ hef0, of_real_mul,
      neg_mul_eq_neg_mul_symm, neg_div, abs_nth_root,
      is_absolute_value.abv_pow complex.abs],
  end,
have hF₃ : (f.eval z' - F.eval z').abs < (g.eval z₀).abs * δ ^ n,
  from calc (f.eval z' - F.eval z').abs
      = (g.eval z' - g.eval z₀).abs * (z' - z₀).abs ^ n :
        by rw [← eq_sub_iff_add_eq.1 hg, ← is_absolute_value.abv_pow complex.abs,
            ← complex.abs_mul, sub_mul];
          simp [F, eval_pow, eval_add, eval_mul,
            eval_sub, eval_C, eval_X, eval_neg, add_sub_cancel]
  ... = (g.eval z' - g.eval z₀).abs * δ ^ n : by rw hz'z₀
  ... < _ : (mul_lt_mul_right (pow_pos hδ0 _)).2 (hδ _ hz'z₀),
lt_irrefl (f.eval z₀).abs $
calc (f.eval z₀).abs = ⨅ y, (f.eval y).abs : hz₀
... ≤ (f.eval z').abs : lattice.cinfi_le
  ⟨0, λ _ ⟨z, hz⟩, by simp [hz.symm, complex.abs_nonneg]⟩
... = (F.eval z' + (f.eval z' - F.eval z')).abs : by simp
... ≤ (F.eval z').abs + (f.eval z' - F.eval z').abs : complex.abs_add _ _
... < (f.eval z₀).abs - (g.eval z₀).abs * δ ^ n + (g.eval z₀).abs * δ ^ n :
  add_lt_add_of_le_of_lt (by rw hF₂) hF₃
... = _ : by simp


import data.real.irrational
import topology.basic
import algebra.order.floor

--OUTPUT 1
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  have h1 : ∀ i j : ℤ, i ≠ j → (int.fract (α * ↑i)) ≠ (int.fract (α * ↑j)), by {
    assume (i j : ℤ) (h1 : i ≠ j),
    have h2 : α ≠ (int.fract (α * ↑i) - int.fract (α * ↑j)) / (i - j), from by {
      assume h2 : α = (int.fract (α * ↑i) - int.fract (α * ↑j)) / (i - j),
      have h3 : α = (int.fract (α * ↑i) - int.fract (α * ↑j)) / (i - j), from h2,
      have h4 : α = (int.fract (α * ↑i) - int.fract (α * ↑j)) / (i - j), from h3,
      have h5 : (i - j) ≠ 0, from by {
        assume h5 : (i - j) = 0,
        have h6 : i = j, from by {
          have h7 : i - j = 0, from sorry,
          have h8 : i - j = 0, from sorry,
          show i = j, from sorry,
        },
        have h6 : i = j, from sorry,
        show false, from h1 h6,
      },
      have h6 : (i - j) ≠ 0, from sorry,
      have h7 : (int.fract (α * ↑i) - int.fract (α * ↑j)) / (i - j) ∈ ℚ, from sorry,
      have h8 : (int.fract (α * ↑i) - int.fract (α * ↑j)) / (i - j) ∈ ℚ, from sorry,
      show false, from hα_irrat h7,
    },
    have h2 : α ≠ (int.fract (α * ↑i) - int.fract (α * ↑j)) / (i - j), from sorry,
    have h3 : α ≠ (int.fract (α * ↑i) - int.fract (α * ↑j)) / (i - j), from sorry,
    have h4 : α ≠ (int.fract (α * ↑i) - int.fract (α * ↑j)) / (i - j), from sorry,
    have h5 : (int.fract (α * ↑i)) ≠ (int.fract (α * ↑j)), from sorry,
    have h6 : (int.fract (α * ↑i)) ≠ (int.fract (α * ↑j)), from sorry,
    show (int.fract (α * ↑i)) ≠ (int.fract (α * ↑j)), from sorry,
  },
  have h1 : ∀ i j : ℤ, i ≠ j → (int.fract (α * ↑i)) ≠ (int.fract (α * ↑j)), from sorry,
  have h2 : ∀ i j : ℤ, i ≠ j → (int.fract (α * ↑i)) ≠ (int.fract (α * ↑j)), from sorry,
  have h3 : ∀ i j : ℤ, i ≠ j → (int.fract (α * ↑i)) ≠ (int.fract (α * ↑j)), from sorry,

  have h4 : ∀ i : ℤ, (int.fract (α * ↑i)) ∈ set.Icc 0 1, from by {
    assume (i : ℤ),
    have h5 : (int.fract (α * ↑i)) ∈ set.Icc 0 1, from sorry,
    show (int.fract (α * ↑i)) ∈ set.Icc 0 1, from sorry,
  },
  have h4 : ∀ i : ℤ, (int.fract (α * ↑i)) ∈ set.Icc 0 1, from sorry,

  have h5 : ∀ i : ℤ, (int.fract (α * ↑i)) ∈ set.Icc 0 1, from sorry,
  have h6 : ∀ i : ℤ, (int.fract (α * ↑i)) ∈ set.Icc 0 1, from sorry,

  have h7 : (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ) ⊆ set.Icc 0 1, from by {
    assume (i : ℤ),
    have h8 : (int.fract (α * ↑i)) ∈ set.Icc 0 1, from sorry,
    show (int.fract (α * ↑i)) ∈ set.Icc 0 1, from sorry,
  },
  have h7 : (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ) ⊆ set.Icc 0 1, from sorry,

  have h8 : (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ) ⊆ set.Icc 0 1, from sorry,

  have h9 : (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ) ⊆ set.Icc 0 1, from sorry,

  have h10 : closure ((λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ)) ⊆ set.Icc 0 1, from sorry,

  have h11 : ∀ y ∈ set.Icc 0 1, ∃ x ∈ (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ), ∀ ε > 0, ∃ N : ℤ, ∀ m ≥ N, abs (x - y) < ε, from by {
    assume (y : ℝ) (h11 : y ∈ set.Icc 0 1),
    have h12 : ∃ x ∈ (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ), ∀ ε > 0, ∃ N : ℤ, ∀ m ≥ N, abs (x - y) < ε, from sorry,
    show ∃ x ∈ (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ), ∀ ε > 0, ∃ N : ℤ, ∀ m ≥ N, abs (x - y) < ε, from sorry,
  },
  have h11 : ∀ y ∈ set.Icc 0 1, ∃ x ∈ (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ), ∀ ε > 0, ∃ N : ℤ, ∀ m ≥ N, abs (x - y) < ε, from sorry,

  have h12 : ∀ y ∈ set.Icc 0 1, ∃ x ∈ (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ), ∀ ε > 0, ∃ N : ℤ, ∀ m ≥ N, abs (x - y) < ε, from sorry,

  have h13 : ∀ y ∈ set.Icc 0 1, ∃ x ∈ (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ), ∀ ε > 0, ∃ N : ℤ, ∀ m ≥ N, abs (x - y) < ε, from sorry,

  have h14 : ∀ y ∈ set.Icc 0 1, ∃ x ∈ (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ), ∀ ε > 0, ∃ N : ℤ, ∀ m ≥ N, abs (x - y) < ε, from sorry,

  have h15 : ∀ y ∈ set.Icc 0 1, ∃ x ∈ (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ),
end --Needs more than 2000 tokens!

--OUTPUT 2
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  have h1 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ≠ int.fract (α * ↑j), from sorry,
  have h2 : ∀ i : ℤ, int.fract (α * ↑i) ∈ set.Icc 0 1, from sorry,
  have h3 : ∀ i : ℤ, int.fract (α * ↑i) ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ), from sorry,
  have h4 : ∀ i : ℤ, int.fract (α * ↑i) ∈ closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)), from sorry,
  have h5 : ∀ i : ℤ, int.fract (α * ↑i) ∈ set.Icc 0 1, from sorry,
  have h6 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h7 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h8 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h9 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h10 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h11 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h12 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h13 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h14 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h15 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h16 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h17 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h18 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h19 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h20 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h21 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h22 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h23 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h24 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h25 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h26 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h27 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h28 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h29 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h30 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h31 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h32 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h33 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h34 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h35 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry,
  have h36 : ∀ y : ℝ, y ∈ set.Icc 0 1 → ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc y (y + 1), from sorry
end --Needs more than 2000 tokens!

--OUTPUT 3
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  sorry
end

--OUTPUT 4
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  have h1 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from by {
    assume (m n : ℤ) (h1 : m ≠ n),
    have h2 : α ≠ ↑(int.nat_abs (m - n)) / ↑(m - n), from by {
      assume h2 : α = ↑(int.nat_abs (m - n)) / ↑(m - n),
      have h3 : irrational α, from hα_irrat,
      have h4 : rational (↑(int.nat_abs (m - n)) / ↑(m - n)), from sorry,
      have h5 : α ∈ set.Ioo 0 1, from sorry,
      have h6 : ↑(int.nat_abs (m - n)) / ↑(m - n) ∈ set.Ioo 0 1, from sorry,
      have h7 : ↑(int.nat_abs (m - n)) / ↑(m - n) = α, from sorry,
      show false, from sorry,
    },
    have h3 : int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
    show int.fract (α * ↑m) ≠ int.fract (α * ↑n), from h3,
  },
  have h2 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h3 : ∀ (m : ℤ), int.fract (α * ↑m) ∈ set.Icc 0 1, from by {
    assume (m : ℤ),
    show int.fract (α * ↑m) ∈ set.Icc 0 1, from sorry,
  },
  have h4 : ∀ (m : ℤ), int.fract (α * ↑m) ∈ set.Icc 0 1, from sorry,
  have h5 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h6 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h7 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h8 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h9 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h10 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h11 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h12 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h13 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h14 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h15 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h16 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h17 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h18 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h19 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h20 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h21 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h22 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h23 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h24 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h25 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h26 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h27 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h28 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h29 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h30 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h31 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h32 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h33 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h34 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h35 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h36 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from sorry,
  have h37 : ∀ (m n : ℤ), m ≠ n → int.fract (α * ↑m) ≠ int.fract
end --Needs more than 2000 tokens!

--OUTPUT 5
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  have h1 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ≠ int.fract (α * ↑j), from sorry,
  have h2 : ∀ i j : ℤ, i ≠ j → (int.fract (α * ↑i)) - (int.fract (α * ↑j)) ≠ 0, from sorry,
  have h3 : ∀ i j : ℤ, i ≠ j → (int.fract (α * ↑i)) - (int.fract (α * ↑j)) ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ), from sorry,
  have h4 : ∀ i j : ℤ, i ≠ j → (int.fract (α * ↑i)) - (int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h5 : ∀ i j : ℤ, i ≠ j → (int.fract (α * ↑i)) - (int.fract (α * ↑j)) ∈ closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)), from sorry,
  have h6 : ∀ i j : ℤ, i ≠ j → (int.fract (α * ↑i)) - (int.fract (α * ↑j)) ∈ closure (set.Icc 0 1), from sorry,
  have h7 : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) ⊆ closure (set.Icc 0 1), from sorry,
  have h8 : closure (set.Icc 0 1) ⊆ closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)), from sorry,
  show closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1, from sorry,
end

--OUTPUT 6
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  have h1 : ∀ (i j : ℤ), i ≠ j → int.fract (α * ↑i) ≠ int.fract (α * ↑j), from sorry,
  have h2 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ≠ 0, from sorry,
  have h3 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h4 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h5 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h6 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h7 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h8 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h9 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h10 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h11 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h12 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h13 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h14 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h15 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h16 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h17 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h18 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h19 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h20 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h21 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h22 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h23 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h24 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h25 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h26 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h27 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h28 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h29 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h30 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h31 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h32 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h33 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h34 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h35 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,

  have h36 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i) - int.fract (α * ↑j)) ∈ set.Icc 0 1, from sorry,
  have h37 : ∀ (i j : ℤ), i ≠ j → (int.fract (α * ↑i)
end --Needs more than 2000 tokens!

/- FEW SHOT PROMPTS TO CODEX(START)
/--`theorem`
Power Set is Closed under Intersection
Let $S$ be a set.

Let $\powerset S$ be the power set of $S$.

Then:
:$\forall A, B \in \powerset S: A \cap B \in \powerset S$
`proof`
Let $A, B \in \powerset S$.

Then by the definition of power set, $A \subseteq S$ and $B \subseteq S$.

From Intersection is Subset we have that $A \cap B \subseteq A$.

It follows from Subset Relation is Transitive that $A \cap B \subseteq S$.

Thus $A \cap B \in \powerset S$ and closure is proved.
{{qed}}
-/
theorem power_set_intersection_closed {α : Type*} (S : set α) : ∀ A B ∈ 𝒫 S, (A ∩ B) ∈ 𝒫 S :=
begin
  assume (A : set α) (hA : A ∈ 𝒫 S) (B : set α) (hB : B ∈ 𝒫 S),
  have h1 : (A ⊆ S) ∧ (B ⊆ S), from sorry,
  have h2 : (A ∩ B) ⊆ A, from sorry,
  have h3 : (A ∩ B) ⊆ S, from sorry,
  show (A ∩ B) ∈  𝒫 S, from sorry,
end

/--`theorem`
Square of Sum
 :$\forall x, y \in \R: \paren {x + y}^2 = x^2 + 2 x y + y^2$
`proof`
Follows from the distribution of multiplication over addition:

{{begin-eqn}}
{{eqn | l = \left({x + y}\right)^2
      | r = \left({x + y}\right) \cdot \left({x + y}\right)
}}
{{eqn | r = x \cdot \left({x + y}\right) + y \cdot \left({x + y}\right)
      | c = Real Multiplication Distributes over Addition
}}
{{eqn | r = x \cdot x + x \cdot y + y \cdot x + y \cdot y
      | c = Real Multiplication Distributes over Addition
}}
{{eqn | r = x^2 + 2xy + y^2
      | c =
}}
{{end-eqn}}
{{qed}}
-/
theorem square_of_sum (x y : ℝ) : (x + y)^2 = (x^2 + 2*x*y + y^2) :=
begin
  calc (x + y)^2 = (x+y)*(x+y) : by sorry
  ... = x*(x+y) + y*(x+y) : by sorry
  ... = x*x + x*y + y*x + y*y : by sorry
  ... = x^2 + 2*x*y + y^2 : by sorry,
end

/--`theorem`
Identity of Group is Unique
Let $\struct {G, \circ}$ be a group. Then there is a unique identity element $e \in G$.
`proof`
From Group has Latin Square Property, there exists a unique $x \in G$ such that:
:$a x = b$

and there exists a unique $y \in G$ such that:
:$y a = b$

Setting $b = a$, this becomes:

There exists a unique $x \in G$ such that:
:$a x = a$

and there exists a unique $y \in G$ such that:
:$y a = a$

These $x$ and $y$ are both $e$, by definition of identity element.
{{qed}}
-/
theorem group_identity_unique {G : Type*} [group G] : ∃! e : G, ∀ a : G, e * a = a ∧ a * e = a :=
begin
  have h1 : ∀ a b : G, ∃! x : G, a * x = b, from sorry,
  have h2 : ∀ a b : G, ∃! y : G, y * a = b, from sorry,

  have h3 : ∀ a : G, ∃! x : G, a * x = a, from sorry,
  have h4 : ∀ a : G, ∃! y : G, y * a = a, from sorry,

  have h5 : ∀ a : G, classical.some (h3 a) = (1 : G), from sorry,
  have h6 : ∀ a : G, classical.some (h4 a) = (1 : G), from sorry,

  show ∃! e : G, ∀ a : G, e * a = a ∧ a * e = a, from by {
    use (1 : G),
    have h7 : ∀ e : G, (∀ a : G, e * a = a ∧ a * e = a) → e = 1, from by {
      assume (e : G) (h7 : ∀ a : G, e * a = a ∧ a * e = a),
      have h8 : ∀ a : G, e = classical.some (h3 a), from sorry,
      have h9 : ∀ a : G, e = classical.some (h4 a), from sorry,
      show e = (1 : G), from sorry,
    },
    sorry,
  }
end

/--`theorem`
Density of irrational orbit
The fractional parts of the integer multiples of an irrational number form a dense subset of the unit interval
`proof`
Let $\alpha$ be an irrational number. Then for distinct $i, j \in \mathbb{Z}$, we must have $\{i \alpha\} \neq\{j \alpha\}$. If this were not true, then
$$
i \alpha-\lfloor i \alpha\rfloor=\{i \alpha\}=\{j \alpha\}=j \alpha-\lfloor j \alpha\rfloor,
$$
which yields the false statement $\alpha=\frac{\lfloor i \alpha\rfloor-\lfloor j \alpha\rfloor}{i-j} \in \mathbb{Q}$. Hence,
$$
S:=\{\{i \alpha\} \mid i \in \mathbb{Z}\}
$$
is an infinite subset of $\left[0,1\right]$.

By the Bolzano-Weierstrass theorem, $S$ has a limit point in $[0, 1]$. One can thus find pairs of elements of $S$ that are arbitrarily close. Since (the absolute value of) the difference of any two elements of $S$ is also an element of $S$, it follows that $0$ is a limit point of $S$.

To show that $S$ is dense in $[0, 1]$, consider $y \in[0,1]$, and $\epsilon>0$. Then by selecting $x \in S$ such that $\{x\}<\epsilon$ (which exists as $0$ is a limit point), and $N$ such that $N \cdot\{x\} \leq y<(N+1) \cdot\{x\}$, we get: $|y-\{N x\}|<\epsilon$.

QED
-/
theorem  irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
FEW SHOT PROMPTS TO CODEX(END)-/


abbrev ℕ := Nat

constant I : Type

structure Constraint where
  lhs : I
  rhs : I

structure EP where
  handle : ℕ
  predicate : String
  a : List I
  s : List I
  c : String

structure MRS (α : Type u) where
  gt : I
  index : I
  r : List EP
  i : List Constraint
  c : List Constraint

theorem and_commutative (p q : Prop) : p ∧ q → q ∧ p :=
  λ hpq : p ∧ q =>
  have hp : p := And.left hpq
  have hq : q := And.right hpq
  show q ∧ p from And.intro hq hp


/-
Copyright (c) 2018 Chris Hughes. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker

! This file was ported from Lean 3 source module data.polynomial.monomial
! leanprover-community/mathlib commit 69c6a5a12d8a2b159f20933e60115a4f2de62b58
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Data.Polynomial.Basic

/-!
# Univariate monomials

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

Preparatory lemmas for degree_basic.
-/

noncomputable section

namespace Polynomial

open Polynomial

universe u

variable {R : Type u} {a b : R} {m n : ℕ}

variable [Semiring R] {p q r : R[X]}

/- warning: polynomial.monomial_one_eq_iff -> Polynomial.monomial_one_eq_iff is a dubious translation:
lean 3 declaration is
  forall {R : Type.{u1}} [_inst_1 : Semiring.{u1} R] [_inst_2 : Nontrivial.{u1} R] {i : Nat} {j : Nat}, Iff (Eq.{succ u1} (Polynomial.{u1} R _inst_1) (coeFn.{succ u1, succ u1} (LinearMap.{u1, u1, u1, u1} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) R (Polynomial.{u1} R _inst_1) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1))) (fun (_x : LinearMap.{u1, u1, u1, u1} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) R (Polynomial.{u1} R _inst_1) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1))) => R -> (Polynomial.{u1} R _inst_1)) (LinearMap.hasCoeToFun.{u1, u1, u1, u1} R R R (Polynomial.{u1} R _inst_1) _inst_1 _inst_1 (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1)) (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (Polynomial.monomial.{u1} R _inst_1 i) (OfNat.ofNat.{u1} R 1 (OfNat.mk.{u1} R 1 (One.one.{u1} R (AddMonoidWithOne.toOne.{u1} R (AddCommMonoidWithOne.toAddMonoidWithOne.{u1} R (NonAssocSemiring.toAddCommMonoidWithOne.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)))))))) (coeFn.{succ u1, succ u1} (LinearMap.{u1, u1, u1, u1} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) R (Polynomial.{u1} R _inst_1) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1))) (fun (_x : LinearMap.{u1, u1, u1, u1} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) R (Polynomial.{u1} R _inst_1) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1))) => R -> (Polynomial.{u1} R _inst_1)) (LinearMap.hasCoeToFun.{u1, u1, u1, u1} R R R (Polynomial.{u1} R _inst_1) _inst_1 _inst_1 (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1)) (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (Polynomial.monomial.{u1} R _inst_1 j) (OfNat.ofNat.{u1} R 1 (OfNat.mk.{u1} R 1 (One.one.{u1} R (AddMonoidWithOne.toOne.{u1} R (AddCommMonoidWithOne.toAddMonoidWithOne.{u1} R (NonAssocSemiring.toAddCommMonoidWithOne.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))))))))) (Eq.{1} Nat i j)
but is expected to have type
  forall {R : Type.{u1}} [_inst_1 : Semiring.{u1} R] [_inst_2 : Nontrivial.{u1} R] {i : Nat} {j : Nat}, Iff (Eq.{succ u1} ((fun (x._@.Mathlib.Algebra.Module.LinearMap._hyg.6190 : R) => Polynomial.{u1} R _inst_1) (OfNat.ofNat.{u1} R 1 (One.toOfNat1.{u1} R (Semiring.toOne.{u1} R _inst_1)))) (FunLike.coe.{succ u1, succ u1, succ u1} (LinearMap.{u1, u1, u1, u1} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) R (Polynomial.{u1} R _inst_1) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1))) R (fun (_x : R) => (fun (x._@.Mathlib.Algebra.Module.LinearMap._hyg.6190 : R) => Polynomial.{u1} R _inst_1) _x) (LinearMap.instFunLikeLinearMap.{u1, u1, u1, u1} R R R (Polynomial.{u1} R _inst_1) _inst_1 _inst_1 (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1)) (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (Polynomial.monomial.{u1} R _inst_1 i) (OfNat.ofNat.{u1} R 1 (One.toOfNat1.{u1} R (Semiring.toOne.{u1} R _inst_1)))) (FunLike.coe.{succ u1, succ u1, succ u1} (LinearMap.{u1, u1, u1, u1} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) R (Polynomial.{u1} R _inst_1) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1))) R (fun (_x : R) => (fun (x._@.Mathlib.Algebra.Module.LinearMap._hyg.6190 : R) => Polynomial.{u1} R _inst_1) _x) (LinearMap.instFunLikeLinearMap.{u1, u1, u1, u1} R R R (Polynomial.{u1} R _inst_1) _inst_1 _inst_1 (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1)) (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (Polynomial.monomial.{u1} R _inst_1 j) (OfNat.ofNat.{u1} R 1 (One.toOfNat1.{u1} R (Semiring.toOne.{u1} R _inst_1))))) (Eq.{1} Nat i j)
Case conversion may be inaccurate. Consider using '#align polynomial.monomial_one_eq_iff Polynomial.monomial_one_eq_iffₓ'. -/
theorem monomial_one_eq_iff [Nontrivial R] {i j : ℕ} :
    (monomial i 1 : R[X]) = monomial j 1 ↔ i = j :=
  by
  simp_rw [← of_finsupp_single]
  exact add_monoid_algebra.of_injective.eq_iff
#align polynomial.monomial_one_eq_iff Polynomial.monomial_one_eq_iff

instance [Nontrivial R] : Infinite R[X] :=
  Infinite.of_injective (fun i => monomial i 1) fun m n h => by simpa [monomial_one_eq_iff] using h

/- warning: polynomial.card_support_le_one_iff_monomial -> Polynomial.card_support_le_one_iff_monomial is a dubious translation:
lean 3 declaration is
  forall {R : Type.{u1}} [_inst_1 : Semiring.{u1} R] {f : Polynomial.{u1} R _inst_1}, Iff (LE.le.{0} Nat Nat.hasLe (Finset.card.{0} Nat (Polynomial.support.{u1} R _inst_1 f)) (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne)))) (Exists.{1} Nat (fun (n : Nat) => Exists.{succ u1} R (fun (a : R) => Eq.{succ u1} (Polynomial.{u1} R _inst_1) f (coeFn.{succ u1, succ u1} (LinearMap.{u1, u1, u1, u1} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) R (Polynomial.{u1} R _inst_1) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1))) (fun (_x : LinearMap.{u1, u1, u1, u1} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) R (Polynomial.{u1} R _inst_1) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1))) => R -> (Polynomial.{u1} R _inst_1)) (LinearMap.hasCoeToFun.{u1, u1, u1, u1} R R R (Polynomial.{u1} R _inst_1) _inst_1 _inst_1 (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1)) (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (Polynomial.monomial.{u1} R _inst_1 n) a))))
but is expected to have type
  forall {R : Type.{u1}} [_inst_1 : Semiring.{u1} R] {f : Polynomial.{u1} R _inst_1}, Iff (LE.le.{0} Nat instLENat (Finset.card.{0} Nat (Polynomial.support.{u1} R _inst_1 f)) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (Exists.{1} Nat (fun (n : Nat) => Exists.{succ u1} R (fun (a : R) => Eq.{succ u1} (Polynomial.{u1} R _inst_1) f (FunLike.coe.{succ u1, succ u1, succ u1} (LinearMap.{u1, u1, u1, u1} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) R (Polynomial.{u1} R _inst_1) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1))) R (fun (_x : R) => (fun (x._@.Mathlib.Algebra.Module.LinearMap._hyg.6190 : R) => Polynomial.{u1} R _inst_1) _x) (LinearMap.instFunLikeLinearMap.{u1, u1, u1, u1} R R R (Polynomial.{u1} R _inst_1) _inst_1 _inst_1 (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u1} (Polynomial.{u1} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)))) (Semiring.toModule.{u1} R _inst_1) (Polynomial.module.{u1, u1} R _inst_1 R _inst_1 (Semiring.toModule.{u1} R _inst_1)) (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (Polynomial.monomial.{u1} R _inst_1 n) a))))
Case conversion may be inaccurate. Consider using '#align polynomial.card_support_le_one_iff_monomial Polynomial.card_support_le_one_iff_monomialₓ'. -/
theorem card_support_le_one_iff_monomial {f : R[X]} :
    Finset.card f.support ≤ 1 ↔ ∃ n a, f = monomial n a :=
  by
  constructor
  · intro H
    rw [Finset.card_le_one_iff_subset_singleton] at H
    rcases H with ⟨n, hn⟩
    refine' ⟨n, f.coeff n, _⟩
    ext i
    by_cases hi : i = n
    · simp [hi, coeff_monomial]
    · have : f.coeff i = 0 := by
        rw [← not_mem_support_iff]
        exact fun hi' => hi (Finset.mem_singleton.1 (hn hi'))
      simp [this, Ne.symm hi, coeff_monomial]
  · rintro ⟨n, a, rfl⟩
    rw [← Finset.card_singleton n]
    apply Finset.card_le_of_subset
    exact support_monomial' _ _
#align polynomial.card_support_le_one_iff_monomial Polynomial.card_support_le_one_iff_monomial

/- warning: polynomial.ring_hom_ext -> Polynomial.ringHom_ext is a dubious translation:
lean 3 declaration is
  forall {R : Type.{u1}} [_inst_1 : Semiring.{u1} R] {S : Type.{u2}} [_inst_2 : Semiring.{u2} S] {f : RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)} {g : RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)}, (forall (a : R), Eq.{succ u2} S (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) (fun (_x : RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) => (Polynomial.{u1} R _inst_1) -> S) (RingHom.hasCoeToFun.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) f (coeFn.{succ u1, succ u1} (RingHom.{u1, u1} R (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1))) (fun (_x : RingHom.{u1, u1} R (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1))) => R -> (Polynomial.{u1} R _inst_1)) (RingHom.hasCoeToFun.{u1, u1} R (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1))) (Polynomial.C.{u1} R _inst_1) a)) (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) (fun (_x : RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) => (Polynomial.{u1} R _inst_1) -> S) (RingHom.hasCoeToFun.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) g (coeFn.{succ u1, succ u1} (RingHom.{u1, u1} R (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1))) (fun (_x : RingHom.{u1, u1} R (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1))) => R -> (Polynomial.{u1} R _inst_1)) (RingHom.hasCoeToFun.{u1, u1} R (Polynomial.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1))) (Polynomial.C.{u1} R _inst_1) a))) -> (Eq.{succ u2} S (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) (fun (_x : RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) => (Polynomial.{u1} R _inst_1) -> S) (RingHom.hasCoeToFun.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) f (Polynomial.X.{u1} R _inst_1)) (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) (fun (_x : RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) => (Polynomial.{u1} R _inst_1) -> S) (RingHom.hasCoeToFun.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) g (Polynomial.X.{u1} R _inst_1))) -> (Eq.{max (succ u1) (succ u2)} (RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) f g)
but is expected to have type
  forall {R : Type.{u2}} [_inst_1 : Semiring.{u2} R] {S : Type.{u1}} [_inst_2 : Semiring.{u1} S] {f : RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)} {g : RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)}, (forall (a : R), Eq.{succ u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : Polynomial.{u2} R _inst_1) => S) (FunLike.coe.{succ u2, succ u2, succ u2} (RingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) R (fun (a : R) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : R) => Polynomial.{u2} R _inst_1) a) (MulHomClass.toFunLike.{u2, u2, u2} (RingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) R (Polynomial.{u2} R _inst_1) (NonUnitalNonAssocSemiring.toMul.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_1))) (NonUnitalNonAssocSemiring.toMul.{u2} (Polynomial.{u2} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)))) (NonUnitalRingHomClass.toMulHomClass.{u2, u2, u2} (RingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) R (Polynomial.{u2} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_1)) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) (RingHomClass.toNonUnitalRingHomClass.{u2, u2, u2} (RingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (RingHom.instRingHomClassRingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)))))) (Polynomial.C.{u2} R _inst_1) a)) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) (fun (_x : Polynomial.{u2} R _inst_1) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : Polynomial.{u2} R _inst_1) => S) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (NonUnitalNonAssocSemiring.toMul.{u2} (Polynomial.{u2} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)))) (NonUnitalNonAssocSemiring.toMul.{u1} S (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} S (Semiring.toNonAssocSemiring.{u1} S _inst_2))) (NonUnitalRingHomClass.toMulHomClass.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} S (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (RingHomClass.toNonUnitalRingHomClass.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2) (RingHom.instRingHomClassRingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2))))) f (FunLike.coe.{succ u2, succ u2, succ u2} (RingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) R (fun (_x : R) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : R) => Polynomial.{u2} R _inst_1) _x) (MulHomClass.toFunLike.{u2, u2, u2} (RingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) R (Polynomial.{u2} R _inst_1) (NonUnitalNonAssocSemiring.toMul.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_1))) (NonUnitalNonAssocSemiring.toMul.{u2} (Polynomial.{u2} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)))) (NonUnitalRingHomClass.toMulHomClass.{u2, u2, u2} (RingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) R (Polynomial.{u2} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_1)) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) (RingHomClass.toNonUnitalRingHomClass.{u2, u2, u2} (RingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (RingHom.instRingHomClassRingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)))))) (Polynomial.C.{u2} R _inst_1) a)) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) (fun (_x : Polynomial.{u2} R _inst_1) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : Polynomial.{u2} R _inst_1) => S) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (NonUnitalNonAssocSemiring.toMul.{u2} (Polynomial.{u2} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)))) (NonUnitalNonAssocSemiring.toMul.{u1} S (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} S (Semiring.toNonAssocSemiring.{u1} S _inst_2))) (NonUnitalRingHomClass.toMulHomClass.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} S (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (RingHomClass.toNonUnitalRingHomClass.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2) (RingHom.instRingHomClassRingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2))))) g (FunLike.coe.{succ u2, succ u2, succ u2} (RingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) R (fun (_x : R) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : R) => Polynomial.{u2} R _inst_1) _x) (MulHomClass.toFunLike.{u2, u2, u2} (RingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) R (Polynomial.{u2} R _inst_1) (NonUnitalNonAssocSemiring.toMul.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_1))) (NonUnitalNonAssocSemiring.toMul.{u2} (Polynomial.{u2} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)))) (NonUnitalRingHomClass.toMulHomClass.{u2, u2, u2} (RingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) R (Polynomial.{u2} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_1)) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) (RingHomClass.toNonUnitalRingHomClass.{u2, u2, u2} (RingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (RingHom.instRingHomClassRingHom.{u2, u2} R (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)))))) (Polynomial.C.{u2} R _inst_1) a))) -> (Eq.{succ u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : Polynomial.{u2} R _inst_1) => S) (Polynomial.X.{u2} R _inst_1)) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) (fun (_x : Polynomial.{u2} R _inst_1) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : Polynomial.{u2} R _inst_1) => S) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (NonUnitalNonAssocSemiring.toMul.{u2} (Polynomial.{u2} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)))) (NonUnitalNonAssocSemiring.toMul.{u1} S (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} S (Semiring.toNonAssocSemiring.{u1} S _inst_2))) (NonUnitalRingHomClass.toMulHomClass.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} S (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (RingHomClass.toNonUnitalRingHomClass.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2) (RingHom.instRingHomClassRingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2))))) f (Polynomial.X.{u2} R _inst_1)) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) (fun (_x : Polynomial.{u2} R _inst_1) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : Polynomial.{u2} R _inst_1) => S) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (NonUnitalNonAssocSemiring.toMul.{u2} (Polynomial.{u2} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)))) (NonUnitalNonAssocSemiring.toMul.{u1} S (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} S (Semiring.toNonAssocSemiring.{u1} S _inst_2))) (NonUnitalRingHomClass.toMulHomClass.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} S (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (RingHomClass.toNonUnitalRingHomClass.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2) (RingHom.instRingHomClassRingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2))))) g (Polynomial.X.{u2} R _inst_1))) -> (Eq.{max (succ u2) (succ u1)} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) f g)
Case conversion may be inaccurate. Consider using '#align polynomial.ring_hom_ext Polynomial.ringHom_extₓ'. -/
theorem ringHom_ext {S} [Semiring S] {f g : R[X] →+* S} (h₁ : ∀ a, f (C a) = g (C a))
    (h₂ : f X = g X) : f = g :=
  by
  set f' := f.comp (to_finsupp_iso R).symm.toRingHom with hf'
  set g' := g.comp (to_finsupp_iso R).symm.toRingHom with hg'
  have A : f' = g' := by
    ext
    · simp [h₁, RingEquiv.toRingHom_eq_coe]
    · simpa [RingEquiv.toRingHom_eq_coe] using h₂
  have B : f = f'.comp (to_finsupp_iso R) :=
    by
    rw [hf', RingHom.comp_assoc]
    ext x
    simp only [RingEquiv.toRingHom_eq_coe, RingEquiv.symm_apply_apply, Function.comp_apply,
      RingHom.coe_comp, RingEquiv.coe_toRingHom]
  have C : g = g'.comp (to_finsupp_iso R) :=
    by
    rw [hg', RingHom.comp_assoc]
    ext x
    simp only [RingEquiv.toRingHom_eq_coe, RingEquiv.symm_apply_apply, Function.comp_apply,
      RingHom.coe_comp, RingEquiv.coe_toRingHom]
  rw [B, C, A]
#align polynomial.ring_hom_ext Polynomial.ringHom_ext

/- warning: polynomial.ring_hom_ext' -> Polynomial.ringHom_ext' is a dubious translation:
lean 3 declaration is
  forall {R : Type.{u1}} [_inst_1 : Semiring.{u1} R] {S : Type.{u2}} [_inst_2 : Semiring.{u2} S] {f : RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)} {g : RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)}, (Eq.{max (succ u1) (succ u2)} (RingHom.{u1, u2} R S (Semiring.toNonAssocSemiring.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) (RingHom.comp.{u1, u1, u2} R (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2) f (Polynomial.C.{u1} R _inst_1)) (RingHom.comp.{u1, u1, u2} R (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} R _inst_1) (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2) g (Polynomial.C.{u1} R _inst_1))) -> (Eq.{succ u2} S (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) (fun (_x : RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) => (Polynomial.{u1} R _inst_1) -> S) (RingHom.hasCoeToFun.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) f (Polynomial.X.{u1} R _inst_1)) (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) (fun (_x : RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) => (Polynomial.{u1} R _inst_1) -> S) (RingHom.hasCoeToFun.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) g (Polynomial.X.{u1} R _inst_1))) -> (Eq.{max (succ u1) (succ u2)} (RingHom.{u1, u2} (Polynomial.{u1} R _inst_1) S (Semiring.toNonAssocSemiring.{u1} (Polynomial.{u1} R _inst_1) (Polynomial.semiring.{u1} R _inst_1)) (Semiring.toNonAssocSemiring.{u2} S _inst_2)) f g)
but is expected to have type
  forall {R : Type.{u2}} [_inst_1 : Semiring.{u2} R] {S : Type.{u1}} [_inst_2 : Semiring.{u1} S] {f : RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)} {g : RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)}, (Eq.{max (succ u2) (succ u1)} (RingHom.{u2, u1} R S (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (RingHom.comp.{u2, u2, u1} R (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2) f (Polynomial.C.{u2} R _inst_1)) (RingHom.comp.{u2, u2, u1} R (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2) g (Polynomial.C.{u2} R _inst_1))) -> (Eq.{succ u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : Polynomial.{u2} R _inst_1) => S) (Polynomial.X.{u2} R _inst_1)) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) (fun (_x : Polynomial.{u2} R _inst_1) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : Polynomial.{u2} R _inst_1) => S) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (NonUnitalNonAssocSemiring.toMul.{u2} (Polynomial.{u2} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)))) (NonUnitalNonAssocSemiring.toMul.{u1} S (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} S (Semiring.toNonAssocSemiring.{u1} S _inst_2))) (NonUnitalRingHomClass.toMulHomClass.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} S (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (RingHomClass.toNonUnitalRingHomClass.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2) (RingHom.instRingHomClassRingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2))))) f (Polynomial.X.{u2} R _inst_1)) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) (fun (_x : Polynomial.{u2} R _inst_1) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : Polynomial.{u2} R _inst_1) => S) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (NonUnitalNonAssocSemiring.toMul.{u2} (Polynomial.{u2} R _inst_1) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)))) (NonUnitalNonAssocSemiring.toMul.{u1} S (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} S (Semiring.toNonAssocSemiring.{u1} S _inst_2))) (NonUnitalRingHomClass.toMulHomClass.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1))) (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} S (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (RingHomClass.toNonUnitalRingHomClass.{max u2 u1, u2, u1} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2) (RingHom.instRingHomClassRingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2))))) g (Polynomial.X.{u2} R _inst_1))) -> (Eq.{max (succ u2) (succ u1)} (RingHom.{u2, u1} (Polynomial.{u2} R _inst_1) S (Semiring.toNonAssocSemiring.{u2} (Polynomial.{u2} R _inst_1) (Polynomial.semiring.{u2} R _inst_1)) (Semiring.toNonAssocSemiring.{u1} S _inst_2)) f g)
Case conversion may be inaccurate. Consider using '#align polynomial.ring_hom_ext' Polynomial.ringHom_ext'ₓ'. -/
@[ext]
theorem ringHom_ext' {S} [Semiring S] {f g : R[X] →+* S} (h₁ : f.comp C = g.comp C)
    (h₂ : f X = g X) : f = g :=
  ringHom_ext (RingHom.congr_fun h₁) h₂
#align polynomial.ring_hom_ext' Polynomial.ringHom_ext'

end Polynomial