import tactic data.set.basic data.rel data.list.basic group_theory.congruence
set_option trace.simplify.rewrite true

@[instance] def list_has_mul {Ω : Type _} : has_mul (list Ω) :=
{
  mul := λ (u v : list Ω), u ++ v
}

def tras_right {Ω : Type _} (w : list Ω) : list Ω → list Ω :=
  λ (u : list Ω), w ++ u

def tras_left {Ω : Type _} (w : list Ω) : list Ω → list Ω :=
  λ (u : list Ω), u ++ w

def is_closed_right {Ω : Type _} (w : list Ω) (r : setoid (list Ω)) : Prop :=
  ∀ (u v : list Ω), setoid.r u v → setoid.r (tras_right w u) (tras_right w v)

def is_closed_left {Ω : Type _} (w : list Ω) (r : setoid (list Ω)) : Prop :=
  ∀ (u v : list Ω), setoid.r u v → setoid.r (tras_left w u) (tras_left w v)

structure is_tras_closed {Ω : Type _} (r : setoid (list Ω)) : Prop :=
  (rc : ∀ (w : list Ω), is_closed_right w r)
  (lc : ∀ (w : list Ω), is_closed_left w r)

def is_con {Ω : Type _} (r : setoid Ω) [has_mul Ω] : Prop :=
  ∀ {w x y z : Ω}, setoid.r w x → setoid.r y z → setoid.r (w * y) (x * z)

#print setoid

--Proposition 2_72
lemma con_iff_tras_closed {Ω : Type _} (r : setoid (list Ω)) :
  is_con r ↔ is_tras_closed r :=
begin
  split,
  {
    rw is_con,
    assume h1,
    split,
    {
      assume w,
      rw is_closed_right,
      assume u v,
      rw tras_right,
      simp,
      assume h2,
      apply h1,
      exact setoid.refl w,
      exact h2,
    },
    {
      assume w,
      rw is_closed_left,
      assume u v,
      rw tras_left,
      simp,
      assume h2,
      apply h1,
      exact h2,
      exact setoid.refl w,
    }
  },

  {
    rw is_con,
    assume h1,
    assume a b x y,
    assume h2,
    assume h3,
    have h4 : setoid.r (a*x) (a*y) :=
      begin
        apply h1.rc _,
        exact h3
      end,
    have h5 : setoid.r (a*y) (b*y) :=
      begin
        apply h1.lc _,
        exact h2
      end,
    exact setoid.trans h4 h5
  }
end

def is_recognizable {M : Type _} [monoid (M)] (L : set M) : Prop :=
 ∃ (N : Type _) [monoid N] [fintype N], ∃ (φ : @monoid_hom M N (monoid.to_mul_one_class M) (@monoid.to_mul_one_class N (_inst_2))), ∃ B : set N, L = φ ⁻¹' B


/-
Copyright (c) 2019 Scott Morrison. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Scott Morrison
-/
import Mathlib.PrePort
import Mathlib.Lean3Lib.init.default
import Mathlib.data.set.intervals.default
import Mathlib.data.set.finite
import Mathlib.data.pnat.intervals
import Mathlib.PostPort

namespace Mathlib

/-!
# fintype instances for intervals

We provide `fintype` instances for `Ico l u`, for `l u : ℕ`, and for `l u : ℤ`.
-/

namespace set

protected instance Ico_ℕ_fintype (l : ℕ) (u : ℕ) : fintype ↥(Ico l u) :=
  fintype.of_finset (finset.Ico l u) sorry

@[simp] theorem Ico_ℕ_card (l : ℕ) (u : ℕ) : fintype.card ↥(Ico l u) = u - l :=
  Eq.trans (fintype.card_of_finset (finset.Ico l u) (Ico_ℕ_fintype._proof_1 l u))
    (finset.Ico.card l u)

protected instance Ico_pnat_fintype (l : ℕ+) (u : ℕ+) : fintype ↥(Ico l u) :=
  fintype.of_finset (pnat.Ico l u) sorry

@[simp] theorem Ico_pnat_card (l : ℕ+) (u : ℕ+) : fintype.card ↥(Ico l u) = ↑u - ↑l :=
  Eq.trans (fintype.card_of_finset (pnat.Ico l u) (Ico_pnat_fintype._proof_1 l u))
    (pnat.Ico.card l u)

protected instance Ico_ℤ_fintype (l : ℤ) (u : ℤ) : fintype ↥(Ico l u) :=
  fintype.of_finset (finset.Ico_ℤ l u) sorry

@[simp] theorem Ico_ℤ_card (l : ℤ) (u : ℤ) : fintype.card ↥(Ico l u) = int.to_nat (u - l) :=
  Eq.trans (fintype.card_of_finset (finset.Ico_ℤ l u) (Ico_ℤ_fintype._proof_1 l u))
    (finset.Ico_ℤ.card l u)

end Mathlib


/-
Copyright (c) 2021 Yaël Dillies. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yaël Dillies
-/
import data.set.pairwise

/-!
# Antichains

This file defines antichains. An antichain is a set where any two distinct elements are not related.
If the relation is `(≤)`, this corresponds to incomparability and usual order antichains. If the
relation is `G.adj` for `G : simple_graph α`, this corresponds to independent sets of `G`.

## Definitions

* `is_antichain r s`: Any two elements of `s : set α` are unrelated by `r : α → α → Prop`.
* `is_antichain.mk r s`: Turns `s` into an antichain by keeping only the "maximal" elements.
-/

open function set

variables {α β : Type*} {r r₁ r₂ : α → α → Prop} {r' : β → β → Prop} {s t : set α} {a : α}

protected lemma symmetric.compl (h : symmetric r) : symmetric rᶜ := λ x y hr hr', hr $ h hr'

/-- An antichain is a set such that no two distinct elements are related. -/
def is_antichain (r : α → α → Prop) (s : set α) : Prop := s.pairwise rᶜ

namespace is_antichain

protected lemma subset (hs : is_antichain r s) (h : t ⊆ s) : is_antichain r t := hs.mono h

lemma mono (hs : is_antichain r₁ s) (h : r₂ ≤ r₁) : is_antichain r₂ s := hs.mono' $ compl_le_compl h

lemma eq_of_related (hs : is_antichain r s) {a b : α} (ha : a ∈ s) (hb : b ∈ s) (h : r a b) :
  a = b :=
of_not_not $ λ hab, hs _ ha _ hb hab h

protected lemma is_antisymm (h : is_antichain r univ) : is_antisymm α r :=
⟨λ a b ha _, h.eq_of_related trivial trivial ha⟩

protected lemma subsingleton [is_trichotomous α r] (h : is_antichain r s) : s.subsingleton :=
begin
  rintro a ha b hb,
  obtain hab | hab | hab := trichotomous_of r a b,
  { exact h.eq_of_related ha hb hab },
  { exact hab },
  { exact (h.eq_of_related hb ha hab).symm }
end

protected lemma flip (hs : is_antichain r s) : is_antichain (flip r) s :=
λ a ha b hb h, hs _ hb _ ha h.symm

lemma swap (hs : is_antichain r s) : is_antichain (swap r) s := hs.flip

lemma image (hs : is_antichain r s) (f : α → β) (h : ∀ ⦃a b⦄, r' (f a) (f b) → r a b) :
  is_antichain r' (f '' s) :=
begin
  rintro _ ⟨b, hb, rfl⟩ _ ⟨c, hc, rfl⟩ hbc hr,
  exact hs _ hb _ hc (ne_of_apply_ne _ hbc) (h hr),
end

lemma preimage (hs : is_antichain r s) {f : β → α} (hf : injective f)
  (h : ∀ ⦃a b⦄, r' a b → r (f a) (f b)) :
  is_antichain r' (f ⁻¹' s) :=
λ b hb c hc hbc hr, hs _ hb _ hc (hf.ne hbc) $ h hr

lemma _root_.is_antichain_insert :
  is_antichain r (insert a s) ↔ is_antichain r s ∧ ∀ ⦃b⦄, b ∈ s → a ≠ b → ¬ r a b ∧ ¬ r b a :=
set.pairwise_insert

protected lemma insert (hs : is_antichain r s) (hl : ∀ ⦃b⦄, b ∈ s → a ≠ b → ¬ r b a)
  (hr : ∀ ⦃b⦄, b ∈ s → a ≠ b → ¬ r a b) :
  is_antichain r (insert a s) :=
is_antichain_insert.2 ⟨hs, λ b hb hab, ⟨hr hb hab, hl hb hab⟩⟩

lemma _root_.is_antichain_insert_of_symmetric (hr : symmetric r) :
  is_antichain r (insert a s) ↔ is_antichain r s ∧ ∀ ⦃b⦄, b ∈ s → a ≠ b → ¬ r a b :=
pairwise_insert_of_symmetric hr.compl

lemma insert_of_symmetric (hs : is_antichain r s) (hr : symmetric r)
  (h : ∀ ⦃b⦄, b ∈ s → a ≠ b → ¬ r a b) :
  is_antichain r (insert a s) :=
(is_antichain_insert_of_symmetric hr).2 ⟨hs, h⟩

/-- Turns a set into an antichain by keeping only the "maximal" elements. -/
protected def mk (r : α → α → Prop) (s : set α) : set α := {a ∈ s | ∀ ⦃b⦄, b ∈ s → r a b → a = b}

lemma mk_is_antichain (r : α → α → Prop) (s : set α) : is_antichain r (is_antichain.mk r s) :=
λ a ha b hb hab h, hab $ ha.2 hb.1 h

lemma mk_subset : is_antichain.mk r s ⊆ s := sep_subset _ _

/-- If `is_antichain.mk r s` is included in but *shadows* the antichain `t`, then it is actually
equal to `t`. -/
lemma mk_max (ht : is_antichain r t) (h : is_antichain.mk r s ⊆ t)
  (hs : ∀ ⦃a⦄, a ∈ t → ∃ b ∈ is_antichain.mk r s, r a b) :
  t = is_antichain.mk r s :=
begin
  refine subset.antisymm (λ a ha, _) h,
  obtain ⟨b, hb, hr⟩ := hs ha,
  rwa of_not_not (λ hab, ht _ ha _ (h hb) hab hr),
end

end is_antichain

lemma set.subsingleton.is_antichain (hs : s.subsingleton) (r : α → α → Prop): is_antichain r s :=
hs.pairwise _


import tactic
import group_theory.quotient_group
import algebra.archimedean
import order.conditionally_complete_lattice

open_locale classical

def df (f : ℤ → ℤ) : ℤ → ℤ → ℤ := λ p q, f (p + q) - f (p) - f (q)

def almost_homo (f : ℤ → ℤ) : Prop := ∃ C, ∀ p q, abs (df f p q) < C

@[simp] lemma df_eq (f : ℤ → ℤ) (p q : ℤ) : df f p q = f (p + q) - f (p) - f (q) := rfl

def S := {f | almost_homo f}

def S.add : S → S → S := λ f g, ⟨λ z, f.1 z + g.1 z,
begin
  rcases f with ⟨f, C1, hf⟩,
  rcases g with ⟨g, C2, hg⟩,
  use C1 + C2,
  intros p q,
  specialize hf p q,
  specialize hg p q,
  have h1 : df (λ (z : ℤ), f z + g z) p q = df f p q + df g p q,
    simp,
    ring,
  rw h1,
  linarith [abs_add (df f p q) (df g p q)],
end⟩

def S.neg : S → S := λ f, ⟨λ p, - f.1 p,
begin
    rcases f with ⟨f, C1, hf⟩,
    use C1,
    simp,
    intros p q,
    specialize hf p q,
    simp at hf,
    have h : f p - f (p + q) + f q = - (f (p + q) - f p - f q),
      ring,
    rw [h, abs_neg],
    exact hf,
end⟩

def S.zero : S := ⟨λ p, 0, 1, by norm_num⟩

@[simp] lemma S.add_eq (f g : S) : S.add f g = ⟨λ p, f.1 p + g.1 p, S.add._proof_1 f g⟩ := rfl

@[simp] lemma S.neg_eq (f : S) : S.neg f = ⟨λ p, - f.1 p, S.neg._proof_1 f⟩ := rfl

instance add_group_S : add_group S := {
  add := λ f g, S.add f g,
  add_assoc := begin
    intros f g h,
    simp,
    ring,
  end,
  zero := ⟨λ p, 0, 1, by norm_num⟩,
  zero_add := begin
    intro f,
    show S.add ⟨λ p, 0, 1, by norm_num⟩ f = f,
    simp,
  end,
  add_zero := begin
    intro f,
    show S.add f ⟨λ p, 0, 1, by norm_num⟩ = f,
    simp,
  end,
  neg := λ f, ⟨λ p, - f.1 p, begin
    rcases f with ⟨f, C1, hf⟩,
    use C1,
    simp,
    intros p q,
    specialize hf p q,
    simp at hf,
    have h : f p - f (p + q) + f q = - (f (p + q) - f p - f q),
      ring,
    rw [h, abs_neg],
    exact hf,
  end⟩,
  add_left_neg := begin
    intro f,
    show S.add (S.neg f) f = ⟨λ (p : ℤ), 0, _⟩,
    simp,
  end }

@[simp] lemma S.add_eq' (f g : S) : f + g = S.add f g := rfl

@[simp] lemma S.neg_eq' (f : S) : -f = S.neg f := rfl

@[simp] lemma S.zero_eq' : (0 : S) = ⟨λ p, 0, 1, by norm_num⟩ := rfl

instance : add_comm_group S := {
  add_comm := begin
    intros f g,
    show S.add f g = S.add g f,
    simp,
    simp_rw [add_comm],
  end,
  ..add_group_S }

def B : add_subgroup S :=
{ carrier := {f : S | ∃ C, ∀ p, abs (f.1 p) < C},
  zero_mem' := begin
    use 1,
    intro p,
    norm_num,
  end,
  add_mem' := begin
    rintro f g ⟨C1, hf⟩ ⟨C2, hg⟩,
    use C1 + C2,
    intro p,
    specialize hf p,
    specialize hg p,
    simp,
    change abs (f.1 p + g.1 p) < C1 + C2,
    linarith [abs_add (f.1 p) (g.1 p)],
  end,
  neg_mem' := begin
    rintro f ⟨C, hf⟩,
    use C,
    intro p,
    specialize hf p,
    change abs (-(f.val p)) < C,
    simp,
    exact hf,
  end }

@[simp] lemma in_B_iff (f : S) : f ∈ B ↔ ∃ C, ∀ p, abs (f.1 p) < C := iff.rfl

def eudoxus_reals_group := quotient_add_group.quotient B
notation `𝔼` := eudoxus_reals_group

instance add_comm_group_𝔼 : add_comm_group 𝔼 := quotient_add_group.add_comm_group B

lemma lemma1 {f : ℤ → ℤ} (hf1 : almost_homo f) (hf2 : ∀ n (hn : 0 < n), ∃ p (hp : 0 < p), n < f p) :
∀ D, 0 < D → ∃ M (hM : 0 < M), ∀ m, 0 < m → (m + 1) * D < f (m * M) :=
begin
  rcases hf1 with ⟨C, hf1⟩,
  intros D hD,
  set E := C + D with hE,
  have key : ∃ M (hM : 0 < M), 2 * E < f M,
    have h2E : 0 < 2 * E,
      linarith [hf1 0 0, abs_nonneg (df f 0 0)],
    rcases hf2 (2 * E) h2E with ⟨M, hM, H⟩,
    use [M, hM],
    exact H,
  rcases key with ⟨M, hM, hfM⟩,
  use [M, hM],
  intros m hm,
  have hC : 0 ≤ C,
    specialize hf1 1 2,
    linarith [abs_nonneg (df f 1 2)],
  have hED : ∀ k, 0 < k → (k + 1) * D ≤ (k + 1) * E,
    intros k hk,
    rw mul_le_mul_left,
      linarith,
    linarith,
  apply lt_of_le_of_lt (hED m hm),
  induction m,
  { induction m with m h,
      exfalso,
      norm_num at hm,
    have hm0 : m = 0 ∨ 0 < m,
      exact nat.eq_zero_or_pos m,
    cases hm0,
    { rw hm0,
      simp,
      exact hfM, },
    { have hm0' : int.of_nat m > 0,
        exact int.lt_to_nat.mp hm0,
      specialize h hm0',
      have hdf1 : f ((int.of_nat m.succ) * M) =
        f (int.of_nat m * M) + f (M) + df f (int.of_nat m * M) (M),
        simp,
        ring,
        rw mul_comm,
      have hdf2 : -E < df f (int.of_nat m * M) M,
        specialize hf1 (int.of_nat m * M) M,
        rw abs_lt at hf1,
        linarith,
      have h1 : (int.of_nat m + 1) * E + 2 * E + (-E) <
        f (int.of_nat m * M) + f M + df f (int.of_nat m * M) M,
        linarith,
      have h2 : (int.of_nat m.succ + 1) * E = (int.of_nat m + 1) * E + 2 * E + (-E),
        dsimp,
        ring,
      linarith, }, },
  { exfalso,
    linarith [int.neg_succ_lt_zero m], },
end

theorem QRT : ∀ n m : ℤ, m > 0 → ∃ q r : ℤ, n = m * q + r ∧ (0 ≤ r ∧ r < m) :=
begin
  intros n m h,
  use (n / m),
  use (n % m),
  have HH:  n = m * (n / m)  + (n % m), from calc
    n = n % m + m * (n / m) : by rw [int.mod_add_div]
    ... = m * (n / m) + (n % m) : by rw add_comm,
  have HH1: 0 ≤ (n % m), from int.mod_nonneg n (ne_of_gt h),
  have HH2: (n % m) < m, from calc
    (n % m) < abs m : int.mod_lt n (ne_of_gt h)
    ... = m : abs_of_pos h,
  exact ⟨HH , ⟨HH1, HH2⟩⟩,
end

instance : has_coe_t ↥S 𝔼 := quotient_add_group.has_coe_t

instance : has_lift_t ↥S 𝔼 := coe_to_lift

lemma 𝔼.zero_eq : (0 : 𝔼) = ↑(0 : S) := rfl

def P := {e : 𝔼 | ∃ (f : S) (H : ↑f = e), ∀ n (hn : 0 < n), ∃ p (hp : 0 < p), n < f.1 p}

lemma P_eq : P = {e : 𝔼 | ∃ (f : S) (H : ↑f = e), ∀ n (hn : 0 < n), ∃ p (hp : 0 < p), n < f.1 p} := rfl

@[simp] lemma upper_bounds_eq {S : set ℤ} : upper_bounds S = {x : ℤ | ∀ ⦃a : ℤ⦄, a ∈ S → a ≤ x} := rfl

@[simp] lemma lower_bounds_eq {S : set ℤ} : lower_bounds S = {x : ℤ | ∀ ⦃a : ℤ⦄, a ∈ S → x ≤ a} := rfl

lemma lemma2 (f : S) (hf : ∀ n (hn : 0 < n), ∃ p (hp : 0 < p), n < f.1 p) :
  (∀ C (HC : 0 < C), ∃ N : ℤ, ∀ p (hNp : N < p), C < f.1 p) :=
begin
  rcases f.2 with ⟨D, hD⟩,
  have hD1 : ∀ (p q : ℤ), abs (df f.1 p q) < D := hD,
  specialize hD 1 2,
  have hD' : 0 < D,
    linarith [abs_nonneg (df f.1 1 2)],
  rcases lemma1 f.2 hf D hD' with ⟨M, hM0, hM⟩,
  have hE : ∃ E, ∀ r (h0r : 0 ≤ r) (hrM : r < M), abs(f.1 r) < E,
    have hfin : set.finite ((abs ∘ f.1) '' (set.Ico 0 M)),
      apply set.finite.image,
      split,
      apply fintype.of_finset (finset.Ico_ℤ 0 M),
      simp,
    have hbdd : bdd_above ((abs ∘ f.1) '' (set.Ico 0 M)),
      apply set.finite.bdd_above hfin,
    cases hbdd with m hm,
    simp at hm,
    use m + 1,
    intros r h0r hrM,
    specialize @hm (abs (f.1 r)) r h0r hrM rfl,
    linarith,
  cases hE with E hE,
  have hE1 : ∀ (r : ℤ), 0 ≤ r → r < M → abs (f.1 r) < E := hE,
  specialize hE 0 _ _,
  { set B := E + D with hB,
    intros C hC,
    have hBC0 : 0 < B + C,
      linarith [abs_nonneg (f.1 0)],
    have hn : ∃ n (hn0 : n > 0), B + C < (n + 1) * D,
      rcases (QRT (B + C) D hD') with ⟨n, r, hnr, h0r, hrD⟩,
      rw hnr at hBC0,
      have h0n : 0 ≤ n,
        by_contradiction hfalse,
        simp at hfalse,
        have hnn : ∃ (nn : ℤ) (hnn0 : nn > 0), n = -nn,
          use -n,
          split,
            linarith,
          simp,
        rcases hnn with ⟨nn, hnn0, hnn⟩,
        rw hnn at hBC0,
        have hDnnr : D * nn ≤ r,
          linarith,
        have hDDnn : D ≤ D * nn,
          exact (le_mul_iff_one_le_right hD').mpr (show nn ≥ 1, by linarith),
        linarith,
      use n + 1,
      split,
        linarith,
      have hfinal : (n + 1 + 1) * D = D * n + 2 * D,
        ring,
      rw hfinal,
      linarith,
    rcases hn with ⟨n, hn0, hn⟩,
    use n * M,
    intros p hp,
    rcases (QRT p M hM0) with ⟨d, r, hdr, h0r, hrM⟩,
    rw hdr at hp,
    have hndr : (n - d) * M < M,
      linarith,
    have hnd : n - d < 1,
      exact (mul_lt_iff_lt_one_left hM0).mp hndr,
    have hnd' : n ≤ d,
      linarith,
    have hd0 : 0 < d,
      linarith,
    have hfdm1 : B + C < f.1 (d * M),
      have hnDdD1 : n + 1 ≤ d + 1,
        linarith,
      have hnDdD2 : (n + 1) * D ≤ (d + 1) * D,
        exact (mul_le_mul_right hD').mpr hnDdD1,
      linarith [hM d hd0],
    have hfdMr : abs (f.1 p - f.1 (d * M)) < B,
      rw hdr,
      have heq1 : f.1 (M * d + r) = f.1 (M * d) + f.1 (r) + df f.1 (M * d) r,
        simp,
        ring,
      have heq2 : f.1 (d * M) + f.1 r + df f.1 (d * M) r - f.1 (d * M) = f.1 r + df f.1 (d * M) r,
        ring,
      rw [heq1, mul_comm, heq2],
      linarith [hD1 (d * M) r, hE1 r h0r hrM, abs_add (f.1 r) (df f.1 (d * M) r)],
    rw abs_lt at hfdMr,
    linarith, },
  { refl, },
  { exact hM0, },
end

lemma lemma3 (f : S) (hf : ∀ n (hn : n < 0), ∃ p (hp : 0 < p), f.1 p < n) :
  (∀ C (HC : 0 < C), ∃ N : ℤ, ∀ p (hNp : N < p), f.1 p < -C) :=
begin
  set g := -f with hgf,
  have hfval : ∀ p, (-f).val p = -(f.val p),
    intro p,
    refl,
  have key : ∀ (C : ℤ), 0 < C → (∃ (N : ℤ), ∀ (p : ℤ), N < p → C < g.val p),
    apply lemma2 g,
    simp_rw [hgf, hfval],
    intros n hn,
    have : -n < 0,
      linarith,
    specialize hf (-n) this,
    rcases hf with ⟨p, hp, hf⟩,
    use [p, hp],
    linarith,
  simp_rw [hgf, hfval] at key,
  rintro C hC,
  specialize key C hC,
  cases key with N key,
  use N,
  intros p hp,
  specialize key p hp,
  linarith,
end

lemma lemma4 (f : S) (hf : ∃ C, ∀ p (hp : 0 ≤ p), abs (f.1 p) < C) : ∃ B, ∀ p, abs (f.1 p) < B :=
begin
  cases f.2 with D hD,
  cases hf with C hC,
  have hneg : ∃ C', ∀ p (hp : p < 0), abs (f.1 p) < C',
    use C + D + abs (f.1 0),
    intros p hp,
    have hfp : f.1 p = f.1 0 - f.1 (-p) - df f.1 (-p) p,
      simp,
      ring,
    rw hfp,
    have hnegp : 0 < -p,
      exact neg_pos.mpr hp,
    have hnegp' : 0 ≤ -p,
      linarith,
    specialize hC (-p) hnegp',
    specialize hD (-p) p,
    have heq : f.val 0 - f.val (-p) - df f.val (-p) p = f.val 0 + (-f.val (-p)) + (-df f.val (-p) p),
      ring,
    rw heq,
    have habs3 : abs (f.val 0 + -f.val (-p) + -df f.val (-p) p) ≤
      abs (f.val 0) + abs (-f.val (-p)) + abs (-df f.val (-p) p),
      exact abs_add_three (f.val 0) (-f.val (-p)) (-df f.val (-p) p),
    rw [abs_neg, abs_neg] at habs3,
    linarith [abs_add_three (f.val 0) (-f.val (-p)) (-df f.val (-p) p)],
  cases hneg with C' hC',
  use C + C',
  intro p,
  have hp : 0 ≤ p ∨ p < 0 := le_or_lt 0 p,
  cases hp,
  { specialize hC p hp,
    have hne1 : (-1 : ℤ) < 0,
      norm_num,
    specialize hC' (-1) hne1,
    linarith [abs_nonneg (f.val (-1))], },
  { specialize hC' p hp,
    have h01 : (0 : ℤ) ≤ 1,
      norm_num,
    specialize hC 1 h01,
    linarith [abs_nonneg (f.val 1)], },
end

lemma lemma5 (f : S) : (∀ n (hn : 0 < n), ∃ p (hp : 0 < p), n < f.1 p) ∨
  (∀ n (hn : n < 0), ∃ p (hp : 0 < p), f.1 p < n) ∨ (∃ C, ∀ p (hp : 0 ≤ p), abs (f.1 p) < C) :=
begin
  by_cases h1 : ∀ n (hn : 0 < n), ∃ p (hp : 0 < p), n < f.1 p,
    left,
    exact h1,
  by_cases h2 : ∀ n (hn : n < 0), ∃ p (hp : 0 < p), f.1 p < n,
    right,
    left,
    exact h2,
  have h1' : ∃ n (hn : 0 < n), ∀ p (hp : 0 < p), f.1 p ≤ n,
    finish,
  have h2' : ∃ n (hn : n < 0), ∀ p (hp : 0 < p), n ≤ f.1 p,
    finish,
  rcases h1' with ⟨C1, hC1, h1'⟩,
  rcases h2' with ⟨C2, hC2, h2'⟩,
  right,
  right,
  use abs (C1) + abs (C2) + abs (f.val 0) + 1,
  intros p hp,
  have hfval0 : 0 < f.1 p ∨ f.1 p ≤ 0,
    exact lt_or_ge 0 (f.val p),
  cases hfval0,
  { have habs : abs (f.val p) ≤ abs C1 + abs (f.val 0),
      have := eq_or_lt_of_le hp,
      cases this,
        rw ← this,
        linarith [abs_nonneg C1],
      specialize h1' p this,
      have : abs (f.val p) ≤ abs C1,
        apply abs_le_abs h1',
        linarith,
      linarith [abs_nonneg (f.val 0)],
    linarith [abs_nonneg C2], },
  { have hfval0' : f.1 p < 0 ∨ f.1 p = 0,
      exact lt_or_eq_of_le hfval0,
    cases hfval0',
    { have habs : abs (f.val p) ≤ abs C2 + abs (f.val 0),
        have := eq_or_lt_of_le hp,
        cases this,
          rw ← this,
          linarith [abs_nonneg C2],
        specialize h2' p this,
        have habs : abs (f.val p) ≤ abs C2,
          rw abs_of_neg hfval0',
          have hC2 : C2 < 0,
            linarith,
          rw abs_of_neg hC2,
          linarith,
        linarith [abs_nonneg (f.val 0)],
      linarith [abs_nonneg C1], },
    { rw hfval0',
      simp only [abs_zero],
      linarith [abs_nonneg C1, abs_nonneg C2, abs_nonneg (f.1 0)], }, },
end

lemma lemma6 (f : S) : (∀ C (HC : 0 < C), ∃ N : ℤ, ∀ p (hNp : N < p), C < f.1 p) ∧
  (∀ C (HC : 0 < C), ∃ N : ℤ, ∀ p (hNp : N < p), f.1 p < -C) → false :=
begin
  rintro ⟨h1, h2⟩,
  have h01 : (0 : int) < 1,
    norm_num,
  specialize h1 1 h01,
  specialize h2 1 h01,
  cases h1 with N1 h1,
  cases h2 with N2 h2,
  have hN1 : N1 < abs N1 + abs N2 + 1,
    linarith [abs_nonneg N2, le_abs_self N1],
  have hN2 : N2 < abs N1 + abs N2 + 1,
    linarith [abs_nonneg N1, le_abs_self N2],
  specialize h1 (abs N1 + abs N2 + 1) hN1,
  specialize h2 (abs N1 + abs N2 + 1) hN2,
  linarith,
end

lemma lemma7 (f : S) : (∀ C (HC : 0 < C), ∃ N : ℤ, ∀ p (hNp : N < p), C < f.1 p) ∧
  (∃ B, ∀ p, abs (f.1 p) < B) → false :=
begin
  rintro ⟨h1, h2⟩,
  cases h2 with B h2,
  have h01 : (0 : int) < 1,
    norm_num,
  have h2' : ∀ (p : ℤ), abs (f.val p) < B := h2,
  specialize h2' 0,
  have hB : 0 < B,
    linarith [abs_nonneg (f.1 0)],
  specialize h1 B hB,
  cases h1 with N h1,
  have hN : N < N + 1,
    linarith,
  specialize h1 (N + 1) hN,
  specialize h2 (N + 1),
  rw abs_lt at h2,
  linarith,
end

lemma lemma8 (f : S) : (∀ n (hn : 0 < n), ∃ p (hp : 0 < p), n < f.1 p) ↔
  (∀ C (HC : 0 < C), ∃ N : ℤ, ∀ p (hNp : N < p), C < f.1 p) :=
begin
  split,
  { intro hf,
    exact lemma2 f hf, },
  { cases lemma5 f,
    { intro,
      exact h, },
    { cases h,
      { intro h1,
        exfalso,
        exact lemma6 f ⟨h1, lemma3 f h⟩, },
      { intro h1,
        exfalso,
        exact lemma7 f ⟨h1, lemma4 f h⟩, }, }, },
end

lemma lemma9 : ∀ a b ∈ P, a + b ∈ P :=
begin
  rintro a b ⟨f1, hf1a, h1⟩ ⟨f2, hf2b, h2⟩,
  use f1 + f2,
  split,
    rw [← hf1a, ← hf2b],
    refl,
  rw lemma8 at *,
  intros C hC,
  specialize h1 C hC,
  specialize h2 C hC,
  cases h1 with M h1,
  cases h2 with N h2,
  use max M N,
  intro p,
  intro hMNp,
  have hMNp': M < p ∧ N < p,
    rw ← max_lt_iff,
    exact hMNp,
  specialize h1 p hMNp'.1,
  specialize h2 p hMNp'.2,
  have hfinal : (f1 + f2).val p = f1.val p + f2.val p,
    refl,
  rw hfinal,
  linarith,
end

lemma lemma10 : (0 : 𝔼) ∈ P → false :=
begin
  intro hfalse,
  rw P_eq at hfalse,
  rcases hfalse with ⟨f, H, hfalse⟩,
  rw lemma8 at hfalse,
  rw 𝔼.zero_eq at H,
  rw quotient_add_group.eq at H,
  simp at H,
  exact lemma7 f ⟨hfalse, H⟩,
end

lemma lemma11 {a : 𝔼} : a ∈ P → -a ∈ P → false :=
begin
  rw P_eq,
  rintro ⟨f1, hf1, ha1⟩ ⟨f2, hf2, ha2⟩,
  rw ← hf1 at hf2,
  have hf1f2 : ↑f2 + ↑f1 = (0 : 𝔼),
    rw hf2,
    simp,
  have hf1f2' : (@coe ↥S 𝔼) eudoxus_reals_group.has_lift_t (0 : S) = ↑(f2 + f1),
    have heq : (@coe ↥S 𝔼) eudoxus_reals_group.has_lift_t (f2 + f1) = ↑f2 + ↑f1,
      refl,
    have h0 : (@coe ↥S 𝔼) eudoxus_reals_group.has_lift_t (0 : S) = (0 : 𝔼),
      refl,
    rw [heq, h0, ← hf1f2],
  rw quotient_add_group.eq at hf1f2',
  simp only [nonempty_of_inhabited, sub_zero, abs_zero, S.neg_eq', zero_add, df_eq, S.neg_eq,
    in_B_iff, neg_zero] at hf1f2',
  cases hf1f2' with C hf1f2',
  rw lemma8 at *,
  have h0C : 0 < C,
    linarith [hf1f2' 0, abs_nonneg ((f2 + f1).val 0)],
  cases ha1 C h0C with N1 ha1,
  cases ha2 C h0C with N2 ha2,
  have hN1 : N1 < max N1 N2 + 1,
    linarith [le_max_left N1 N2],
  have hN2 : N2 < max N1 N2 + 1,
    linarith [le_max_right N1 N2],
  specialize ha1 (max N1 N2 + 1) hN1,
  specialize ha2 (max N1 N2 + 1) hN2,
  specialize hf1f2' (max N1 N2 + 1),
  have heq : (f2 + f1).val (max N1 N2 + 1) = f2.val (max N1 N2 + 1) + f1.val (max N1 N2 + 1) := rfl,
  rw [heq, abs_lt] at hf1f2',
  linarith,
end

lemma lemma12 : ∀ a : 𝔼, ∃ f : S, ↑f = a := λ a, quot.exists_rep a

lemma lemma13 : ∀ {f : ℤ → ℤ} (C : ℤ), set.finite (f '' (set.Ioo (-C) C)) :=
begin
  intros f C,
  apply set.finite.image,
  exact ⟨fintype.of_finset (finset.Ico_ℤ (-C + 1) (C)) (by {simp [int.add_one_le_iff]})⟩,
end

lemma lemma14 : ∀ f g : S, f.1 ∘ g.1 ∈ S :=
begin
  intros f g,
  rcases f with ⟨f, C1, hf⟩,
  rcases g with ⟨g, C2, hg⟩,
  simp,
  have hfin : set.finite (f '' (set.Ioo (-C2) (C2))) := lemma13 C2,
  cases set.finite.bdd_above hfin with C3 hC3,
  simp at hC3,
  cases set.finite.bdd_below hfin with C4 hC4,
  simp at hC4,
  use C1 + C1 + max (abs (C4)) (abs (C3)),
  simp_rw df_eq at *,
  intros p q,
  have hf' := hf,
  set t := g (p + q) - g p - g q with ht,
  have heq : g (p + q) = t + (g p + g q),
    rw ht,
    ring,
  specialize hf (g p) (g q),
  specialize hg p q,
  specialize hf' t (g p + g q),
  rw [← ht, abs_lt] at hg,
  specialize @hC3 (f t) t hg.1 hg.2 rfl,
  specialize @hC4 (f t) t hg.1 hg.2 rfl,
  rw ← heq at hf',
  have h123 : abs ((f (g p + g q) - f (g p) - f (g q)) + (f (g (p + q)) - f t - f (g p + g q)) + f t)
    ≤ abs (f (g p + g q) - f (g p) - f (g q)) + abs (f (g (p + q)) - f t - f (g p + g q)) + abs (f t),
    exact abs_add_three (f (g p + g q) - f (g p) - f (g q)) (f (g (p + q)) - f t - f (g p + g q)) (f t),
  have heq : (f (g p + g q) - f (g p) - f (g q)) + (f (g (p + q)) - f t - f (g p + g q)) + f t =
    (f ∘ g) (p + q) - (f ∘ g) p - (f ∘ g) q,
    ring,
  rw heq at h123,
  have hft : abs (f t) ≤ max (abs (C4)) (abs (C3)),
    apply abs_le_max_abs_abs hC4 hC3,
  linarith,
end

lemma lemma15 : ∀ {f1 g1 f2 g2 : S}, (@coe ↥S 𝔼) eudoxus_reals_group.has_lift_t f1 = ↑f2 →
  (@coe ↥S 𝔼) eudoxus_reals_group.has_lift_t g1 = ↑g2 → -(⟨f1.1 ∘ g1.1, lemma14 f1 g1⟩ : S)
  + (⟨f2.1 ∘ g2.1, lemma14 f2 g2⟩ : S) ∈ B :=
begin
  rintros ⟨f1, hf1⟩ ⟨g1, hfg⟩ ⟨f2, Bf2, hf2⟩ ⟨g2, hg2⟩ hf1f2 hg1g2,
  rw quotient_add_group.eq at *,
  cases hf1f2 with Cf hf1f2,
  cases hg1g2 with Cg hg1g2,
  have hfin : set.finite (f2 '' (set.Ioo (-Cg) (Cg))) := lemma13 Cg,
  cases set.finite.bdd_above hfin with C3 hC3,
  simp at hC3,
  cases set.finite.bdd_below hfin with C4 hC4,
  simp at hC4,
  use Cf + Bf2 + max (abs (C4)) (abs (C3)),
  simp_rw df_eq at hf2,
  intros x,
  set t := -g1 x + g2 x with ht,
  have heq : g2 x = t + g1 x,
    rw ht,
    ring,
  specialize hf1f2 (g1 x),
  specialize hg1g2 x,
  specialize hf2 t (g1 x),
  simp at hf1f2,
  simp at hg1g2,
  rw [← ht, abs_lt] at hg1g2,
  specialize @hC3 (f2 t) t hg1g2.1 hg1g2.2 rfl,
  specialize @hC4 (f2 t) t hg1g2.1 hg1g2.2 rfl,
  rw ← heq at hf2,
  simp,
  have h123 := abs_add_three (-(f1 (g1 x))+ f2 (g1 x)) (f2 (g2 x) - f2 t - f2 (g1 x)) (f2 t),
  have heq : (-(f1 (g1 x)) + f2 (g1 x)) + (f2 (g2 x) - f2 t - f2 (g1 x)) + f2 t =
    -(f1 (g1 x)) + f2 (g2 x),
    ring,
  rw heq at h123,
  have hft : abs (f2 t) ≤ max (abs (C4)) (abs (C3)),
    apply abs_le_max_abs_abs hC4 hC3,
  linarith,
end

lemma lemma16 : (id : ℤ → ℤ) ∈ S :=
begin
  use 1,
  intros p q,
  norm_num,
end

noncomputable def 𝔼.mul : 𝔼 → 𝔼 → 𝔼 := λ a b,
begin
  choose f hf using lemma12 a,
  choose g hg using lemma12 b,
  let h : ↥S := ⟨f.1 ∘ g.1, lemma14 f g⟩,
  exact ↑h,
end

@[simp] lemma 𝔼.mul_eq (a b : 𝔼) : 𝔼.mul a b = (begin
  choose f hf using lemma12 a,
  choose g hg using lemma12 b,
  let h : ↥S := ⟨f.1 ∘ g.1, lemma14 f g⟩,
  exact ↑h,
end : 𝔼) := rfl

lemma lemma17 : ∀ x y : S, 𝔼.mul ↑x ↑y = ↑(⟨x.1 ∘ y.1, lemma14 x y⟩ : S) :=
begin
  intros x y,
  simp,
  rw quotient_add_group.eq,
  have hxeq := classical.some_spec (lemma12 ↑x),
  have hyeq := classical.some_spec (lemma12 ↑y),
  apply lemma15 hxeq hyeq,
end

lemma lemma18 : ∀ x y : S, x = y → -x + y ∈ B :=
begin
  intros x y hxy,
  rw hxy,
  simp,
  use 1,
  norm_num,
end

lemma lemma19 (f : S) : ∃ C, ∀ p (H : 0 ≤ p) q, abs (f.1 (p * q) - p * (f.1 q)) < (abs p + 1) * C :=
begin
  cases f.2 with C hC,
  use C,
  intros p H,
  induction p,
  { induction p with p hp,
    { intro q,
      simp,
      change abs (f.1 0) < C,
      have hf0 : abs (f.1 0) = abs (f.1 (0 + 0) - f.1 0 - f.1 0),
        simp,
      have hdf0 : df f.1 0 0 = f.1 (0 + 0) - f.1 0 - f.1 0 := rfl,
      rw [hf0, ← hdf0],
      exact hC 0 0, },
    { intro q,
      specialize hp (int.of_nat_nonneg p) q,
      have hkey : f.val (int.of_nat p.succ * q) - f.1 (p * q) - f.1 q = df f.1 (p * q) q,
        simp,
        ring,
      specialize hC (p * q) q,
      rw ← hkey at hC,
      have heq : f.val (int.of_nat p.succ * q) - int.of_nat p.succ * f.val q =
        (f.val (int.of_nat p.succ * q) - f.val (↑p * q) - f.val q) + (f.val (int.of_nat p * q) -
        int.of_nat p * f.val q),
        simp,
        ring,
      rw heq,
      have : (abs (int.of_nat p.succ) + 1) * C = C + (abs (int.of_nat p) + 1) * C,
        have hp1 : 0 < (↑p : ℤ) + 1,
          linarith,
        simp,
        rw [abs_of_pos hp1],
        ring,
      linarith [abs_add (f.val (int.of_nat p.succ * q) - f.val (↑p * q) - f.val q) (f.val (int.of_nat p * q) -
        int.of_nat p * f.val q)], }, },
    { exfalso,
      linarith [int.neg_succ_lt_zero p], },
end

lemma lemma20 (f : S) : ∃ C, ∀ p (H : 0 ≤ p) q, abs (f.1 ((-p) * q) - (-p) * (f.1 q)) < (abs (-p) + 1) * C :=
begin
  cases f.2 with C hC,
  use C,
  intros p H,
  induction p,
  { induction p with p hp,
    { intro q,
      simp,
      change abs (f.1 0) < C,
      have hf0 : abs (f.1 0) = abs (f.1 (0 + 0) - f.1 0 - f.1 0),
        simp,
      have hdf0 : df f.1 0 0 = f.1 (0 + 0) - f.1 0 - f.1 0 := rfl,
      rw [hf0, ← hdf0],
      exact hC 0 0, },
    { intro q,
      specialize hp (int.of_nat_nonneg p) q,
      have hkey : -f.1 (-int.of_nat p.succ * q) + f.1 (-(p * q)) - f.1 q = df f.1 (-(p + 1) * q) q,
        simp,
        have heq : (-1 + -↑p) * q + q = -(↑p * q),
          ring,
        rw heq,
        ring,
      specialize hC (-(↑p + 1) * q) q,
      rw ← hkey at hC,
      have heq : f.val (-int.of_nat p.succ * q) - -int.of_nat p.succ * f.val q =
        -(-f.val (-int.of_nat p.succ * q) + f.val (-(p * q)) - f.val q) + (f.val (-int.of_nat p * q) -
        -int.of_nat p * f.val q),
        simp,
        ring,
      rw heq,
      have : (abs (-int.of_nat p.succ) + 1) * C = C + (abs (-int.of_nat p) + 1) * C,
        have hp1 : 0 ≤ (↑p : ℤ) := int.of_nat_nonneg p,
        have hp2 : -1 + -(↑p : ℤ) < 0,
          linarith,
        simp,
        rw [abs_of_neg hp2],
        ring,
      have := abs_add (-(-f.val (-int.of_nat p.succ * q) + f.val (-(p * q)) - f.val q)) (f.val (-int.of_nat p * q) -
        -int.of_nat p * f.val q),
      rw abs_neg at this,
      linarith, }, },
    { exfalso,
      linarith [int.neg_succ_lt_zero p], },
end

lemma lemma21 (f : S) : ∃ C, ∀ p q,  abs (f.1 (p * q) - p * (f.1 q)) < (abs p + 1) * C :=
begin
  cases lemma19 f with C1 hC1,
  cases lemma20 f with C2 hC2,
  use max C1 C2,
  intro p,
  have hp0 := le_or_lt 0 p,
  cases hp0,
  { intro q,
    specialize hC1 p hp0 q,
    have := le_max_left C1 C2,
    have h0abs : 0 < abs p + 1,
      linarith [abs_nonneg p],
    have : (abs p + 1) * C1 ≤ (abs p + 1) * max C1 C2,
      have := @mul_le_mul_left ℤ (linear_ordered_ring.to_linear_ordered_semiring) C1 (max C1 C2) (abs p + 1),
      rw this,
        exact le_max_left C1 C2,
      linarith,
    linarith, },
  { intro q,
    set np := -p with hnp,
    have hnp0 : 0 ≤ np,
      linarith,
    specialize hC2 np hnp0 q,
    have hnpp : -np = p,
      rw hnp,
      simp,
    rw hnpp at hC2,
    have := le_max_left C1 C2,
    have h0abs : 0 < abs p + 1,
      linarith [abs_nonneg p],
    have : (abs p + 1) * C2 ≤ (abs p + 1) * max C1 C2,
      have := @mul_le_mul_left ℤ (linear_ordered_ring.to_linear_ordered_semiring) C2 (max C1 C2) (abs p + 1),
      rw this,
        exact le_max_right C1 C2,
      linarith,
    linarith, },
end

lemma lemma22 (f : S) : ∃ C, ∀ p q, abs (p * (f.1 q) - q * (f.1 p)) < (abs p + abs q + 2) * C :=
begin
  cases lemma21 f with C hC,
  use C,
  intros p q,
  have hC' := hC,
  specialize hC p q,
  specialize hC' q p,
  rw ← abs_neg at hC,
  have heq1 : (-(f.val (p * q) - p * f.val q)) + (f.val (q * p) - q * f.val p) = p * f.val q - q * f.val p,
    rw mul_comm,
    ring,
  have heq2 : (abs p + abs q + 2) * C = ((abs p + 1) * C) + ((abs q + 1) * C),
    ring,
  rw [← heq1, heq2],
  linarith [abs_add (-(f.val (p * q) - p * f.val q)) (f.val (q * p) - q * f.val p)],
end

lemma lemma23 (f : S) : ∃ A B (hA : 0 < A), ∀ p, abs (f.1 p) < A * abs p + B :=
begin
  cases lemma22 f with C hC,
  have hC0 : 0 < C + abs (f.1 1),
    specialize hC 0 0,
    simp at hC,
    linarith [abs_nonneg (f.1 1)],
  use [C + abs (f.1 1), 3 * C, hC0],
  intro p,
  specialize hC p 1,
  have heq1 : f.1 p = -(p * f.1 1 - f.1 p) + (p * f.1 1),
    ring,
  have heq2 : (C + abs (f.val 1)) * abs p + 3 * C = (abs p + 1 + 2) * C + abs (p * f.1 1),
    have : abs (p * f.1 1) = (abs p) * abs (f.1 1) := abs_mul p (f.1 1),
    rw this,
    ring,
  rw [heq1, heq2],
  simp at hC,
  change abs (p * f.1 1 - f.1 p) < (abs p + 1 + 2) * C at hC,
  rw ← abs_neg at hC,
  linarith [abs_add (-(p * f.val 1 - f.val p)) (p * f.1 1)],
end

lemma lemma24 (f g : S) : ∃ D E, ∀ p, abs p * abs (f.1 (g.1 p) - g.1 (f.1 p)) < D * abs p + E :=
begin
  have h1 : ∃ C, ∀ p, abs (p * f.1 (g.1 p) - g.1 p * f.1 p) < (abs p + abs (g.1 p) + 2) * C,
    cases lemma22 f with C hC,
    use C,
    intro p,
    specialize hC p (g.1 p),
    exact hC,
  have h2 : ∃ C, ∀ p, abs (g.1 p * f.1 p - p * g.1 (f.1 p)) < (abs p + abs (f.1 p) + 2) * C,
    cases lemma22 g with C hC,
    use C,
    intro p,
    specialize hC p (f.1 p),
    have heq : p * g.val (f.val p) - f.val p * g.val p = -(g.val p * f.val p - p * g.val (f.val p)),
      ring,
    rw [heq, abs_neg] at hC,
    exact hC,
  have h3 : ∃ C, ∀ p, abs (p * f.1 (g.1 p) - p * g.1 (f.1 p)) < (2 * abs p + abs (g.1 p) + abs (f.1 p) + 4) * C,
    cases h1 with C1 h1,
    cases h2 with C2 h2,
    use max C1 C2,
    intro p,
    specialize h1 p,
    specialize h2 p,
    have h0abs1 : 0 < abs p + abs (g.val p) + 2,
      linarith [abs_nonneg p, abs_nonneg (g.val p)],
    have h0abs2 : 0 < abs p + abs (f.val p) + 2,
      linarith [abs_nonneg p, abs_nonneg (f.val p)],
    have : (abs p + abs (g.val p) + 2) * C1 ≤ (abs p + abs (g.val p) + 2) * max C1 C2,
      have := @mul_le_mul_left ℤ (linear_ordered_ring.to_linear_ordered_semiring) C1 (max C1 C2) (abs p + abs (g.val p) + 2),
      rw this,
        exact le_max_left C1 C2,
      linarith,
    have : (abs p + abs (f.val p) + 2) * C2 ≤ (abs p + abs (f.val p) + 2) * max C1 C2,
      have := @mul_le_mul_left ℤ (linear_ordered_ring.to_linear_ordered_semiring) C2 (max C1 C2) (abs p + abs (f.val p) + 2),
      rw this,
        exact le_max_right C1 C2,
      linarith,
    have heq1 : (2 * abs p + abs (g.val p) + abs (f.val p) + 4) * max C1 C2 =
      (abs p + abs (g.val p) + 2) * max C1 C2 + (abs p + abs (f.val p) + 2) * max C1 C2,
      ring,
    have heq2 : p * f.val (g.val p) - p * g.val (f.val p) = (p * f.1 (g.1 p) - g.1 p * f.1 p) +
      (g.1 p * f.1 p - p * g.1 (f.1 p)),
      ring,
    rw [heq1, heq2],
    linarith [abs_add (p * f.1 (g.1 p) - g.1 p * f.1 p) (g.1 p * f.1 p - p * g.1 (f.1 p))],
  cases h3 with C h3,
  rcases lemma23 f with ⟨Af, Bf, hAf, hABf⟩,
  rcases lemma23 g with ⟨Ag, Bg, hAg, hABg⟩,
  have h4 : ∀ (p : ℤ), abs (p * f.val (g.val p) - p * g.val (f.val p)) <
    (2 * abs p + (Ag * abs p + Bg) + (Af * abs p + Bf) + 4) * C,
    intro p,
    specialize hABf p,
    specialize hABg p,
    specialize h3 p,
    have h0abs : 0 < (2 * abs p + abs (g.val p) + abs (f.val p) + 4),
      linarith [abs_nonneg p, abs_nonneg (g.val p), abs_nonneg (f.val p)],
    have : (2 * abs p + abs (g.val p) + abs (f.val p) + 4) * C <
      (2 * abs p + (Ag * abs p + Bg) + (Af * abs p + Bf) + 4) * C,
      have hfvalgval : (2 * abs p + abs (g.val p) + abs (f.val p) + 4) <
        (2 * abs p + (Ag * abs p + Bg) + (Af * abs p + Bf) + 4),
        linarith,
      apply mul_lt_mul hfvalgval (le_refl C),
        have := abs_nonneg (p * f.val (g.val p) - p * g.val (f.val p)),
        have h0mul : 0 < (2 * abs p + abs (g.val p) + abs (f.val p) + 4) * C,
          linarith,
        have : 0 < C,
          exact (zero_lt_mul_left h0abs).mp h0mul,
        linarith,
      linarith,
    linarith,
  use [(2 + Ag + Af) * C, (Bg + Bf + 4) * C],
  intro p,
  specialize h4 p,
  have heq1 : (2 * abs p + (Ag * abs p + Bg) + (Af * abs p + Bf) + 4) * C =
    (2 * abs p + (Ag * abs p + Bg) + (Af * abs p + Bf) + 4) * C,
    ring,
  have heq2 : abs p * abs (f.val (g.val p) - g.val (f.val p)) =
    abs (p * f.val (g.val p) - p * g.val (f.val p)),
    have := (abs_mul p (f.val (g.val p) - g.val (f.val p))).symm,
    convert this,
    ring,
  linarith,
end

lemma lemma25 (f g : S) : -(⟨f.1 ∘ g.1, lemma14 f g⟩ : S) + (⟨g.1 ∘ f.1, lemma14 g f⟩ : S) ∈ B :=
begin
  rcases lemma24 f g with ⟨D, E, hDE⟩,
  simp,
  change ∃ (C : ℤ), ∀ (p : ℤ), abs (-(f.1 (g.1 p)) + g.1 (f.1 p)) < C,
  have h1 : ∀ p (H : abs E < abs p), abs (f.val (g.val p) - g.val (f.val p)) < D + 1,
    intros p hp,
    specialize hDE p,
    have hDE' : abs p * abs (f.val (g.val p) - g.val (f.val p)) < D * abs p + abs E,
      linarith [le_abs_self E],
    have : abs p * abs (f.val (g.val p) - g.val (f.val p)) < abs p * (D + 1),
      linarith,
    have habsp : abs p > 0,
      linarith [abs_nonneg E],
    have hiff := @mul_lt_mul_left ℤ (linear_ordered_ring.to_linear_ordered_semiring) (abs (f.val (g.val p) - g.val (f.val p)))
      (D + 1) (abs p) habsp,
    rw ← hiff,
    exact this,
  have hB : ∃ B, ∀ (p : ℤ), abs p ≤ abs E → abs (f.val (g.val p) - g.val (f.val p)) < B,
    have hfin : set.finite ((λ p, abs (f.val (g.val p) - g.val (f.val p))) '' (set.Icc (-(abs E)) (abs E))),
      apply set.finite.image,
      exact ⟨fintype.of_finset (finset.Ico_ℤ (-(abs E)) (abs E + 1)) (by {simp [int.lt_add_one_iff]})⟩,
    have hbdd : bdd_above ((λ p, abs (f.val (g.val p) - g.val (f.val p))) '' (set.Icc (-(abs E)) (abs E))),
      apply set.finite.bdd_above hfin,
    cases hbdd with m hm,
    simp at hm,
    use m + 1,
    intros p hpE,
    rw abs_le at hpE,
    specialize @hm (abs (f.val (g.val p) - g.val (f.val p))) p hpE.1 hpE.2 rfl,
    linarith,
  cases hB with B hB,
  use max B (D + 1),
  intro p,
  rw ← abs_neg,
  have : -(-f.val (g.val p) + g.val (f.val p)) = f.val (g.val p) - g.val (f.val p),
    ring,
  rw this,
  have hpE := le_or_lt (abs p) (abs E),
  cases hpE,
    specialize hB p hpE,
    linarith [le_max_left B (D + 1)],
  specialize h1 p hpE,
  linarith [le_max_right B (D + 1)],
end

lemma 𝔼.mul_comm : ∀ (a b : 𝔼), 𝔼.mul a b = 𝔼.mul b a :=
begin
  intros a b,
  cases lemma12 a with u hu,
  cases lemma12 b with v hv,
  rw [← hu, ← hv, lemma17 u v, lemma17 v u, quotient_add_group.eq],
  apply lemma25,
end

lemma 𝔼.mul_right_distrib : ∀ (a b c : 𝔼), 𝔼.mul (a + b) c = 𝔼.mul a c + 𝔼.mul b c :=
begin
  intros a b c,
  cases lemma12 a with u hu,
  cases lemma12 b with v hv,
  cases lemma12 c with w hw,
  have H1 := lemma17 (u + v) w,
  have H2 := lemma17 u w,
  have H3 := lemma17 v w,
  have heq : ∀ v w, (@coe ↥S 𝔼) eudoxus_reals_group.has_lift_t (v + w) =
    @has_add.add 𝔼 (@add_semigroup.to_has_add 𝔼 (add_monoid.to_add_semigroup 𝔼)) ↑v ↑w := λ v w, rfl,
  rw heq at H1,
  rw [← hu, ← hv, ← hw],
    rw [H1, H2, H3, ← heq, quotient_add_group.eq],
    apply lemma18,
    simp,
end

noncomputable instance comm_ring_𝔼 : comm_ring 𝔼 := {
  mul := 𝔼.mul,
  mul_assoc := begin
    intros a b c,
    cases lemma12 a with u hu,
    cases lemma12 b with v hv,
    cases lemma12 c with w hw,
    set ab : ↥S := ⟨u.1 ∘ v.1, lemma14 u v⟩ with hab,
    set abc : ↥S := ⟨ab.1 ∘ w.1, lemma14 ab w⟩ with habc,
    set bc : ↥S := ⟨v.1 ∘ w.1, lemma14 v w⟩ with hbc,
    set abc' : ↥S := ⟨u.1 ∘ bc.1, lemma14 u bc⟩ with habc',
    have H1 := lemma17 u v,
    have H2 := lemma17 ab w,
    have H3 := lemma17 v w,
    have H4 := lemma17 u bc,
    rw [hu, hv] at H1,
    rw [hab, ← habc, ← H1, hw] at H2,
    rw [hv, hw] at H3,
    rw [hbc, ← habc', ← H3, hu] at H4,
    show 𝔼.mul (𝔼.mul a b) c = 𝔼.mul a (𝔼.mul b c),
    rw [H2, H4],
  end,
  one := ↑(⟨(id : ℤ → ℤ), lemma16⟩ : S),
  one_mul := begin
    intro a,
    cases lemma12 a with u hu,
    rw ← hu,
    change 𝔼.mul ↑(⟨(id : ℤ → ℤ), lemma16⟩ : S) (↑u : 𝔼) = ↑u,
    simp,
    rw quotient_add_group.eq,
    have h1 := classical.some_spec (lemma12 ↑u),
    have h2 := classical.some_spec (lemma12 ↑(⟨(id : ℤ → ℤ), lemma16⟩ : S)),
    have h3 := lemma15 h2 h1,
    have h4 : u = (⟨(⟨(id : ℤ → ℤ), lemma16⟩ : S).val ∘ u.val, lemma14 ⟨(id : ℤ → ℤ), lemma16⟩ u⟩ : S),
      simp,
    rw h4,
    convert h3,
    simp,
  end,
  mul_one := begin
    intro a,
    cases lemma12 a with u hu,
    rw ← hu,
    change 𝔼.mul (↑u : 𝔼) ↑(⟨(id : ℤ → ℤ), lemma16⟩ : S) = ↑u,
    simp,
    rw quotient_add_group.eq,
    have h1 := classical.some_spec (lemma12 ↑u),
    have h2 := classical.some_spec (lemma12 ↑(⟨(id : ℤ → ℤ), lemma16⟩ : S)),
    have h3 := lemma15 h1 h2,
    have h4 : u = (⟨(⟨(id : ℤ → ℤ), lemma16⟩ : S).val ∘ u.val, lemma14 ⟨(id : ℤ → ℤ), lemma16⟩ u⟩ : S),
      simp,
    rw h4,
    convert h3,
    simp,
  end,
  left_distrib := begin
    intros a b c,
    change 𝔼.mul a (b + c) = 𝔼.mul a b + 𝔼.mul a c,
    rw [𝔼.mul_comm],
    have := 𝔼.mul_comm a c,
    symmetry,
    rw [𝔼.mul_comm, this],
    symmetry,
    apply 𝔼.mul_right_distrib,
  end,
  right_distrib := begin
    intros a b c,
    change 𝔼.mul (a + b) c = 𝔼.mul a c + 𝔼.mul b c,
    apply 𝔼.mul_right_distrib,
  end,
  mul_comm := begin
    intros a b,
    apply 𝔼.mul_comm,
  end,
  ..add_comm_group_𝔼 }

@[simp] lemma 𝔼.mul_eq' (a b : 𝔼) : a * b = 𝔼.mul a b := rfl

@[simp] lemma 𝔼.one_eq' : (1 : 𝔼) = ↑(⟨(id : ℤ → ℤ), lemma16⟩ : S) := rfl

lemma lemma26 {f : ℤ → ℤ} : (∀ p < 0, f p = -(f (-p))) → (∃ C, ∀ m n (hm : 0 ≤ m) (hn : 0 ≤ n),
  abs (df f m n) < C) → f ∈ S :=
begin
  rintro h1 ⟨C, h2⟩,
  use C,
  intros p q,
  have hp := le_or_lt 0 p,
  have hq := le_or_lt 0 q,
  cases hp,
  { cases hq,
      exact h2 p q hp hq,
    have hpq := le_or_lt 0 (p + q),
    cases hpq,
      have h0q : 0 ≤ -q,
        linarith,
      simp,
      specialize h2 (p + q) (-q) hpq h0q,
      simp at h2,
      have : -(f (p + q) - f p - -f (-q)) = f p - f (p + q) - f (-q),
        ring,
      rw [h1 q hq, ← abs_neg, this],
      exact h2,
    have hpq' : 0 ≤ -(p + q),
      linarith,
    specialize h2 (-(p + q)) p hpq' hp,
    simp at h2,
    simp,
    have : -f (-(p + q)) - f p - -f (-q) = f (-q) - f (-q + -p) - f p,
      have : -(p + q) = -q + -p,
        ring,
      rw this,
      ring,
    rw [h1 q hq, h1 (p + q) hpq, this],
    exact h2, },
  cases hq,
  { have hpq := le_or_lt 0 (p + q),
    cases hpq,
      have h0p : 0 ≤ -p,
        linarith,
      simp,
      specialize h2 (p + q) (-p) hpq h0p,
      simp at h2,
      have : -(f (p + q) - -f (-p) - f q) = f (p + q + -p) - f (p + q) - f (-p),
        have : p + q + -p = q,
          ring,
        rw this,
        ring,
      rw [h1 p hp, ← abs_neg, this],
      simp [h2],
    have hpq' : 0 ≤ -(p + q),
      linarith,
    specialize h2 (-(p + q)) q hpq' hq,
    simp at h2,
    simp,
    have : -f (-(p + q)) - -f (-p) - f q = f (-q + -p + q) - f (-q + -p) - f q,
      have eq1 : -(p + q) = -q + -p,
        ring,
      have eq2 : -q + -p + q = -p,
        ring,
      rw [eq1, eq2],
      ring,
    rw [h1 p hp, h1 (p + q) hpq, this],
    simp [h2], },
  have H1 : df f p q = -(df f (-p) (-q)),
    have hpq : p + q < 0,
      linarith,
    have heq : -(p + q) = -p - q,
      ring,
    simp,
    rw [h1 p hp, h1 q hq, h1 (p + q) hpq],
    ring,
    rw heq,
    ring,
  have h0p : 0 ≤ -p,
    linarith,
  have h0q : 0 ≤ -q,
    linarith,
  specialize h2 (-p) (-q) h0p h0q,
  rw [H1, abs_neg],
  exact h2,
end

lemma lemma27 (S : set ℤ) : S.nonempty → (∀ n : ℤ, n ∈ S → 0 ≤ n) → ∃ n ∈ S, ∀ m ∈ S, n ≤ m :=
begin
  intros H1 H2,
  set S' := {a : ℕ | ∃ (s : ℤ) (Hs : s ∈ S), s = ↑a},
  have hS' : S'.nonempty,
    show ∃ (t : ℕ) (s : ℤ) (Hs : s ∈ S), s = ↑t,
    cases H1 with x hx,
    specialize H2 x hx,
    have := int.eq_coe_of_zero_le H2,
    cases this,
    use [this_w, x, hx, this_h],
  have hS'S : ∀ {a : ℕ}, a ∈ S' → ↑a ∈ S,
    rintro a ⟨a', ha', haa'⟩,
    rw ← haa',
    exact ha',
  use ↑(nat.find_x hS').1,
  cases (nat.find_x hS').2 with h1 h2,
  use hS'S h1,
  intros m hm,
  specialize H2 m hm,
  cases int.eq_coe_of_zero_le H2 with m' hm',
  specialize h2 m',
  have h2' : m' ∈ S' → (nat.find_x hS').val ≤ m',
    contrapose,
    simp only [exists_prop, not_le, exists_eq_right],
    exact h2,
  have : m' ∈ S' := ⟨m, hm, hm'⟩,
  specialize h2' this,
  rw hm',
  exact int.coe_nat_le.mpr h2',
end

def P' := {f : S | ∀ n (hn : 0 < n), ∃ p (hp : 0 < p), n < f.1 p}

@[simp] lemma in_P'_iff (f : S) : f ∈ P' ↔ ∀ n (hn : 0 < n), ∃ p (hp : 0 < p), n < f.1 p := iff.rfl

lemma lemma28 (f : P') : ∀ p (hp : 0 ≤ p), ∃ n (hn : n ∈ {m | p ≤ f.1.1 m ∧ 0 ≤ m}), ∀ x ∈ {m | p ≤ f.1.1 m ∧ 0 ≤ m}, n ≤ x :=
begin
  intros p hp,
  cases f with f hf,
  rw in_P'_iff at hf,
  rw lemma8 f at hf,
  have hp1 : 0 < p + 1,
    linarith,
  specialize hf (p + 1) hp1,
  have hnonempty : {m : ℤ | p ≤ f.val m ∧ 0 ≤ m}.nonempty,
    cases hf with N hf,
    have hN : N < max 0 (N + 1),
      rw lt_max_iff,
        right,
      linarith,
    specialize hf (max 0 (N + 1)) hN,
    use (max 0 (N + 1)),
    simp only [set.mem_set_of_eq],
    split,
      linarith,
    rw le_max_iff,
    left,
    linarith,
  have hall : ∀ n : ℤ, n ∈ {m : ℤ | p ≤ f.val m ∧ 0 ≤ m} → 0 ≤ n,
    intros n hn,
    exact hn.2,
  exact lemma27 {m : ℤ | p ≤ f.val m ∧ 0 ≤ m} hnonempty hall,
end

lemma lemma29 (a : 𝔼) : a ∈ P ∨ a = 0 ∨ -a ∈ P :=
begin
  cases lemma12 a with u hu,
  cases lemma5 u,
    left,
    use [u.1, u.2],
    simp only [subtype.coe_eta, subtype.val_eq_coe],
    use [hu, h],
  cases h,
    right,
    right,
    have : ↑-u = -a,
      rw ← hu,
      refl,
    use [-u, this],
    intros n hn,
    have hn0 : -n < 0,
      linarith,
    specialize h (-n) hn0,
    rcases h with ⟨p, hp, h⟩,
    use [p, hp],
    have huval : (-u).val p = -(u.val p) := rfl,
    linarith,
  right,
  left,
  have : (0 : 𝔼) = ↑(0 : S) := rfl,
  symmetry,
  rw [← hu, this, quotient_add_group.eq],
  simp,
  exact lemma4 u h,
end

lemma lemma30 {a : 𝔼} : a ∉ P → ¬(a = 0) → -a ∈ P :=
begin
  intros h1 h2,
  cases lemma29 a,
    exfalso,
    exact h1 h,
  cases h,
    exfalso,
    exact h2 h,
  exact h,
end

noncomputable def 𝔼.inv.g1 : P' → (ℤ → ℤ) := λ f, (λ p,
if hp : 0 ≤ p then begin
  choose n hn using lemma28 f p hp,
  exact n,
end
else begin
  have hp' : 0 ≤ -p,
    linarith,
  choose n hn using lemma28 f (-p) hp',
  exact -n,
end)

lemma lemma31 (f : P') :  ∀ n (hn : 0 ≤ n), 0 ≤ 𝔼.inv.g1 f n :=
begin
  intros n hn,
  simp only [𝔼.inv.g1],
  split_ifs,
  have := classical.some_spec (lemma28 f n hn),
  cases this with hsome1 hsome2,
  rw set.mem_set_of_eq at hsome1,
  exact hsome1.2,
end

lemma lemma32 (f : P') :  ∃ n (hn : 0 < n), 0 < 𝔼.inv.g1 f n :=
begin
  by_contradiction hfalse,
  have hfalse' : ∀ n (hn : 0 < n), 𝔼.inv.g1 f n ≤ 0,
    rw not_exists at hfalse,
    intros n hn,
    specialize hfalse n,
    rw not_exists at hfalse,
    specialize hfalse hn,
    linarith,
  clear hfalse,
  cases f with f hf,
  rw in_P'_iff at hf,
  have hfalse1 :  ∀ (n : ℤ), 0 < n → 𝔼.inv.g1 ⟨f, hf⟩ n = 0,
    intros n hn0,
    specialize hfalse' n hn0,
    have hn0' : 0 ≤ n,
      linarith,
    have := lemma31 ⟨f, hf⟩ n hn0',
    exact le_antisymm hfalse' this,
  have hfalse2 : ∀ (n : ℤ), 0 < n → n ≤ f.1 0,
    intros n hn,
    specialize hfalse1 n hn,
    simp only [𝔼.inv.g1] at hfalse1,
    split_ifs at hfalse1,
      have hn' : 0 ≤ n,
        linarith,
      have := classical.some_spec (lemma28 ⟨f, hf⟩ n hn'),
      cases this with hsome1 hsome2,
      simp at hsome1,
      rw ← hfalse1,
      simp,
      exact hsome1.1,
    exfalso,
    linarith,
  have hlt : 0 < max (f.val 0 + 1) 1,
    rw lt_max_iff,
      right,
    norm_num,
  specialize hfalse2 (max (f.val 0 + 1) 1) hlt,
  have : (f.val 0 + 1) ≤ max (f.val 0 + 1) 1 := le_max_left (f.val 0 + 1) 1,
  linarith,
end

lemma lemma33 (f : P') : ∀ n m (hn : 0 ≤ n) (hm : n ≤ m), 𝔼.inv.g1 f n ≤ 𝔼.inv.g1 f m :=
begin
  intros n m hn hm,
  simp only [𝔼.inv.g1],
  have hm' : 0 ≤ m,
    linarith,
  split_ifs,
  have h1 := classical.some_spec (lemma28 f n hn),
  have h2 := classical.some_spec (lemma28 f m hm'),
  set gn := classical.some (lemma28 f n hn) with hgn,
  set gm := classical.some (lemma28 f m hm') with hgm,
  rw ← hgn at *,
  rw ← hgm at *,
  cases h1 with h11 h12,
  cases h2 with h21 h22,
  rw set.mem_set_of_eq at *,
  have : n ≤ f.val.val gm,
    linarith,
  specialize h12 gm,
  rw set.mem_set_of_eq at h12,
  specialize h12 ⟨this, h21.2⟩,
  exact h12,
end

lemma lemma34 (f : P') :  ∃ N (HN : 0 < N), ∀ n (hn : N ≤ n), 0 < 𝔼.inv.g1 f n :=
begin
  rcases lemma32 f with ⟨N, hN, h⟩,
  have : 0 ≤ N,
    linarith,
  use [N, hN],
  intros n hNn,
  have := lemma33 f N n this hNn,
  linarith,
end

lemma lemma35 (f : P') :  ∀ n (hn : 0 ≤ n), n ≤ f.1.1 (𝔼.inv.g1 f n) :=
begin
  intros n h0n,
  simp only [𝔼.inv.g1],
  split_ifs,
  have := classical.some_spec (lemma28 f n h0n),
  set gn := classical.some (lemma28 f n h0n) with hgn,
  rw ← hgn at *,
  cases this with hgn1 hgn2,
  rw set.mem_set_of_eq at hgn1,
  exact hgn1.1,
end

lemma lemma36 (f g h : ℤ → ℤ → ℤ) {c : ℤ} {F : P'} : (∀ a b (ha : c ≤ a) (hb : 0 ≤ b) (hgb : 0 < 𝔼.inv.g1 F b), f a b > 0 ∧ g a b < 0) → (∃ C, ∀ a b, abs (h a b - f a b) < C) →
  (∃ D, ∀ a b, abs (h a b - g a b) < D) → (∃ E, ∀ a b (ha : c ≤ a) (hb : 0 ≤ b) (hgb : 0 < 𝔼.inv.g1 F b), abs (h a b) < E) :=
begin
  rintro h ⟨C, h1⟩ ⟨D, h2⟩,
  use C + D,
  intros a b ha hb hgb,
  specialize h a b ha hb hgb,
  specialize h1 a b,
  specialize h2 a b,
  cases h with hf hg,
  rw abs_lt at *,
  cases h1,
  cases h2,
  split,
    linarith,
  linarith,
end

lemma lemma37 (f : P') (T : set ℤ) : (∃ C, ∀ x ∈ T, abs (f.1.1 x) < C) → (∃ B, ∀ x ∈ T, abs x ≤ B) :=
begin
  rintro ⟨C, hC⟩,
  by_contradiction hfalse,
  have hfalse' : ∀ (B : ℤ), ∃ (x : ℤ), x ∈ T ∧ B < abs x,
    rw not_exists at hfalse,
    intro B,
    specialize hfalse B,
    rw not_forall at hfalse,
    cases hfalse with x hx,
    use x,
    rw not_imp at hx,
    use hx.1,
    have := hx.2,
    simp at this,
    exact this,
  clear hfalse,
  cases f with f hf,
  rw in_P'_iff at hf,
  have := lemma2 f hf,
  have hD : ∃ D, ∀ p, abs (f.1 p + f.1 (-p)) < D,
    rcases f with ⟨f, E, hE⟩,
    use E + abs (f 0),
    intro p,
    specialize hE p (-p),
    rw ← abs_neg at hE,
    simp at hE,
    simp,
    have heq : f p + f (-p) = (f (-p) - (f 0 - f p)) + f 0,
      ring,
    rw heq,
    linarith [abs_add (f (-p) - (f 0 - f p)) (f 0), le_abs_self (f 0)],
  cases hD with D hD,
  have h0D : 0 < D,
    linarith [hD 0, abs_nonneg (f.1 0 + f.1 (-0))],
  have hCD : 0 < max 0 C + D,
    linarith [le_max_left 0 C],
  specialize this (max 0 C + D) hCD,
  cases this with N hN,
  rcases hfalse' N with ⟨x, hxT, hNx⟩,
  rw lt_abs at hNx,
  cases hNx,
    specialize hC x hxT,
    specialize hN x hNx,
    simp at hC,
    simp at hN,
    linarith [le_abs_self ((↑f : (ℤ → ℤ)) x), le_max_left 0 C, le_max_right 0 C],
  specialize hC x hxT,
  specialize hN (-x) hNx,
  specialize hD x,
  simp at hC,
  simp at hN,
  have : abs ((↑f : ℤ → ℤ) (-x)) < C + D,
    rw ← abs_neg at hC,
    simp at hD,
    have : (↑f : ℤ → ℤ) (-x) = -(↑f : ℤ → ℤ) x + ((↑f : ℤ → ℤ) x + (↑f : ℤ → ℤ) (-x)),
      ring,
    rw this,
    linarith [abs_add (-(↑f : ℤ → ℤ) x) ((↑f : ℤ → ℤ) x + (↑f : ℤ → ℤ) (-x))],
  linarith [le_abs_self ((↑f : (ℤ → ℤ)) (-x)), le_max_right 0 C],
end

lemma lemma38 (f : P') : ∃ C, ∀ m n, abs ((f.1.1 (𝔼.inv.g1 f (m + n)) - f.1.1 (𝔼.inv.g1 f m) - f.1.1 (𝔼.inv.g1 f n)) -
  (f.1.1 (𝔼.inv.g1 f (m + n)) - f.1.1 (𝔼.inv.g1 f m - 1) - f.1.1 (𝔼.inv.g1 f n - 1))) < C :=
begin
  rcases f with ⟨⟨f, C, hC⟩, hf⟩,
  use 2 * C + 2 * abs (f 1),
  intros m n,
  simp,
  ring,
  have hC' := hC,
  specialize hC (𝔼.inv.g1 ⟨⟨f, _⟩, hf⟩ m - 1) 1,
  specialize hC' (𝔼.inv.g1 ⟨⟨f, _⟩, hf⟩ n - 1) 1,
  simp at hC,
  simp at hC',
  rw abs_lt at *,
  cases hC,
  cases hC',
  split,
    linarith [le_abs_self (f 1)],
  linarith [le_abs_self (-f 1), abs_neg (f 1)],
end

lemma lemma39 (f : P') : ∃ C, ∀ m n, abs ((f.1.1 (𝔼.inv.g1 f (m + n)) - f.1.1 (𝔼.inv.g1 f m) - f.1.1 (𝔼.inv.g1 f n)) -
  (f.1.1 (𝔼.inv.g1 f (m + n) - 1) - f.1.1 (𝔼.inv.g1 f m) - f.1.1 (𝔼.inv.g1 f n))) < C :=
begin
  rcases f with ⟨⟨f, C, hC⟩, hf⟩,
  use C + abs (f 1),
  intros m n,
  simp,
  ring,
  specialize hC (𝔼.inv.g1 ⟨⟨f, _⟩, hf⟩ (m + n) - 1) 1,
  simp at hC,
  rw abs_lt at *,
  cases hC,
  split,
    linarith [le_abs_self (-f 1), abs_neg (f 1)],
  linarith [le_abs_self (f 1)],
end

lemma lemma40 (f : P') : ∃ C, ∀ m n, abs (f.1.1 (𝔼.inv.g1 f (m + n) - (𝔼.inv.g1 f m) - (𝔼.inv.g1 f n)) -
  (f.1.1 (𝔼.inv.g1 f (m + n)) - f.1.1 (𝔼.inv.g1 f m) - f.1.1 (𝔼.inv.g1 f n))) < C :=
begin
  rcases f with ⟨⟨f, C, hC⟩, hf⟩,
  use 2 * C,
  intros m n,
  have : ∀ p q r, abs (f(r - p - q) - (f r - f p - f q)) < 2 * C,
    intros p q r,
    have hC' := hC,
    specialize hC (r - p - q) (p + q),
    specialize hC' p q,
    simp at hC,
    simp at hC',
    rw abs_lt at *,
    cases hC,
    cases hC',
    split,
      linarith,
    linarith,
  exact this (𝔼.inv.g1 ⟨⟨f, _⟩, hf⟩ m) (𝔼.inv.g1 ⟨⟨f, _⟩, hf⟩ n) (𝔼.inv.g1 ⟨⟨f, _⟩, hf⟩ (m + n)),
end

lemma lemma41 (f : P') : ∃ C, ∀ m n, abs (f.1.1 (𝔼.inv.g1 f (m + n) - (𝔼.inv.g1 f m) - (𝔼.inv.g1 f n)) -
  (f.1.1 (𝔼.inv.g1 f (m + n)) - f.1.1 (𝔼.inv.g1 f m - 1) - f.1.1 (𝔼.inv.g1 f n - 1))) < C :=
begin
  cases lemma38 f with C1 hC1,
  cases lemma40 f with C2 hC2,
  use C1 + C2,
  intros m n,
  specialize hC1 m n,
  specialize hC2 m n,
  rw abs_lt at *,
  split,
    linarith,
  linarith,
end

lemma lemma42 (f : P') : ∃ C, ∀ m n, abs (f.1.1 (𝔼.inv.g1 f (m + n) - (𝔼.inv.g1 f m) - (𝔼.inv.g1 f n)) -
  (f.1.1 (𝔼.inv.g1 f (m + n) - 1) - f.1.1 (𝔼.inv.g1 f m) - f.1.1 (𝔼.inv.g1 f n))) < C :=
begin
  cases lemma39 f with C1 hC1,
  cases lemma40 f with C2 hC2,
  use C1 + C2,
  intros m n,
  specialize hC1 m n,
  specialize hC2 m n,
  rw abs_lt at *,
  split,
    linarith,
  linarith,
end

lemma lemma43 (f : P') :  ∀ n (hn : 0 ≤ n), 0 < 𝔼.inv.g1 f n → (f.1.1 (𝔼.inv.g1 f n - 1) < n ∧ n ≤ f.1.1 (𝔼.inv.g1 f n)) :=
begin
  intros n h0n h,
  simp only [𝔼.inv.g1],
  split,
  { split_ifs,
    have := classical.some_spec (lemma28 f n h0n),
    set gn := classical.some (lemma28 f n h0n) with hgn,
    rw ← hgn at *,
    cases this with hgn1 hgn2,
    by_contradiction hfgn,
    rw not_lt at hfgn,
    specialize hgn2 (gn - 1),
    have : gn - 1 ∈ {m : ℤ | n ≤ f.val.val m ∧ 0 ≤ m},
      rw set.mem_set_of_eq,
      use hfgn,
      simp only [𝔼.inv.g1] at h,
      split_ifs at h,
      rw ← hgn at *,
      linarith,
    specialize hgn2 this,
    linarith, },
  { exact lemma35 f n h0n, },
end

lemma lemma44 (f : P') : ∃ C, ∀ m n (hgn : 0 = 𝔼.inv.g1 f n), abs ((f.1.1 (𝔼.inv.g1 f (m + n) - (𝔼.inv.g1 f m) - (𝔼.inv.g1 f n))) -
  (f.1.1 (𝔼.inv.g1 f (m + n)) - f.1.1 (𝔼.inv.g1 f m - 1))) < C :=
begin
  rcases f with ⟨⟨f, C, hC⟩, hf⟩,
  use 2 * C + abs (f 1),
  intros m n hgn,
  rw ←hgn,
  simp only [sub_zero, neg_add_rev, zero_add, set.mem_set_of_eq, add_neg_le_iff_le_add', neg_zero],
  have : ∀ p q, abs (f (p - q) - (f p - f (q - 1))) < 2 * C + abs (f 1),
    intros p q,
    have hC' := hC,
    specialize hC 1 (q - 1),
    specialize hC' (p - q) q,
    simp at hC,
    simp at hC',
    rw abs_lt at *,
    cases hC,
    cases hC',
    split,
      linarith [le_abs_self (f 1)],
    linarith [le_abs_self (-f 1), abs_neg (f 1)],
  specialize this (𝔼.inv.g1 ⟨⟨f, _⟩, hf⟩ (m + n)) (𝔼.inv.g1 ⟨⟨f, _⟩, hf⟩ (m)),
  exact this,
end

lemma lemma45 (f g h : ℤ → ℤ → ℤ) {c : ℤ} {F : P'} : (∀ a b (ha : c ≤ a) (hb : 0 ≤ b) (hgb : 0 = 𝔼.inv.g1 F b), f a b > 0 ∧ g a b < 0) → (∃ C, ∀ a b (hgb : 0 = 𝔼.inv.g1 F b),
  abs (h a b - f a b) < C) → (∃ D, ∀ a b, abs (h a b - g a b) < D) → (∃ E, ∀ a b (ha : c ≤ a) (hb : 0 ≤ b) (hgb : 0 = 𝔼.inv.g1 F b), abs (h a b) < E) :=
begin
  rintro h ⟨C, h1⟩ ⟨D, h2⟩,
  use C + D,
  intros a b ha hb hgb,
  specialize h a b ha hb hgb,
  specialize h1 a b hgb,
  specialize h2 a b,
  cases h with hf hg,
  rw abs_lt at *,
  cases h1,
  cases h2,
  split,
    linarith,
  linarith,
end

lemma lemma46 (f : P') : ∃ (N : ℤ) (C : ℤ) , ∀ (m n : ℤ), N ≤ m → 0 ≤ n → abs (df (λ (p : ℤ), 𝔼.inv.g1 f p) m n) < C :=
begin
  rcases lemma34 f with ⟨N, hN, hfN⟩,
  have h1 : ∀ m n (hm : N ≤ m) (h0n : 0 ≤ n) (hgn : 0 < 𝔼.inv.g1 f n), (f.1.1 (𝔼.inv.g1 f m - 1) < m ∧ m ≤ f.1.1 (𝔼.inv.g1 f m)) ∧ (f.1.1 (𝔼.inv.g1 f n - 1) < n ∧
    n ≤ f.1.1 (𝔼.inv.g1 f n)) ∧ (f.1.1 (𝔼.inv.g1 f (m + n) - 1) < m + n ∧ m + n ≤ f.1.1 (𝔼.inv.g1 f (m + n))),
    intros m n hm h0n hgn,
    have h0m : 0 ≤ m,
      linarith,
    have h0mn : 0 ≤ m + n,
      linarith,
    have hmn : N ≤ m + n,
      linarith,
    use [lemma43 f m h0m (hfN m hm), lemma43 f n h0n hgn, lemma43 f (m + n) h0mn (hfN (m + n) hmn)],
  set f1 : ℤ → ℤ → ℤ := λ m n, f.1.1 (𝔼.inv.g1 f (m + n)) - f.1.1 (𝔼.inv.g1 f m - 1) - f.1.1 (𝔼.inv.g1 f n - 1),
  set f2 : ℤ → ℤ → ℤ := λ m n, f.1.1 (𝔼.inv.g1 f (m + n) - 1) - f.1.1 (𝔼.inv.g1 f m) - f.1.1 (𝔼.inv.g1 f n),
  set f3 : ℤ → ℤ → ℤ := λ m n, f.1.1 (𝔼.inv.g1 f (m + n) - (𝔼.inv.g1 f m) - (𝔼.inv.g1 f n)),
  have h2 : ∀ m n (hm : N ≤ m) (h0n : 0 ≤ n) (hgn : 0 < 𝔼.inv.g1 f n), f1 m n > 0 ∧ f2 m n < 0,
    intros m n hm h0n hgn,
    rcases h1 m n hm h0n hgn with ⟨⟨hm1, hm2⟩, ⟨hn1, hn2⟩, ⟨hmn1, hmn2⟩⟩,
    simp only [sub_lt_zero, gt_iff_lt, sub_pos],
    split,
      linarith,
    linarith,
  have := lemma36 f1 f2 f3 h2 (lemma41 f) (lemma42 f),
  set T := {t | ∃ m n (hm : N ≤ m) (hn : 0 ≤ n) (hgn : 0 < 𝔼.inv.g1 f n), (𝔼.inv.g1 f (m + n) - (𝔼.inv.g1 f m) - (𝔼.inv.g1 f n)) = t},
  have hCT : ∃ C, ∀ x ∈ T, abs (f.1.1 x) < C,
    cases this with E hE,
    use E,
    intros x hxT,
    rcases hxT with ⟨m, n, hm, hn, hgn, h⟩,
    specialize hE m n hm hn hgn,
    rw ← h,
    linarith,
  cases lemma37 f T hCT with C1 hC1,
  have h3 : ∀ m n (hm : N ≤ m) (h0n : 0 ≤ n) (hgn : 0 = 𝔼.inv.g1 f n), (f.1.1 (𝔼.inv.g1 f m - 1) < m ∧ m ≤ f.1.1 (𝔼.inv.g1 f m)) ∧
    (n ≤ f.1.1 (𝔼.inv.g1 f n)) ∧ (f.1.1 (𝔼.inv.g1 f (m + n) - 1) < m + n ∧ m + n ≤ f.1.1 (𝔼.inv.g1 f (m + n))),
    intros m n hm h0n hgn,
    have h0m : 0 ≤ m,
      linarith,
    have h0mn : 0 ≤ m + n,
      linarith,
    have hmn : N ≤ m + n,
      linarith,
    use [lemma43 f m h0m (hfN m hm), lemma35 f n h0n, lemma43 f (m + n) h0mn (hfN (m + n) hmn)],
  set f1' : ℤ → ℤ → ℤ := λ m n, f.1.1 (𝔼.inv.g1 f (m + n)) - f.1.1 (𝔼.inv.g1 f m - 1),
  set f2' : ℤ → ℤ → ℤ := λ m n, f.1.1 (𝔼.inv.g1 f (m + n) - 1) - f.1.1 (𝔼.inv.g1 f m) - f.1.1 (𝔼.inv.g1 f n),
  set f3' : ℤ → ℤ → ℤ := λ m n, f.1.1 (𝔼.inv.g1 f (m + n) - (𝔼.inv.g1 f m) - (𝔼.inv.g1 f n)),
  have h4 : ∀ m n (hm : N ≤ m) (h0n : 0 ≤ n) (hgn : 0 = 𝔼.inv.g1 f n), f1' m n > 0 ∧ f2' m n < 0,
    intros m n hm h0n hgn,
    rcases h3 m n hm h0n hgn with ⟨⟨hm1, hm2⟩, hn1, ⟨hmn1, hmn2⟩⟩,
    simp only [sub_lt_zero, gt_iff_lt, sub_pos],
    split,
      linarith,
    linarith,
  have := lemma45 f1' f2' f3' h4 (lemma44 f) (lemma42 f),
  set T' := {t | ∃ m n (hm : N ≤ m) (hn : 0 ≤ n) (hgn : 0 = 𝔼.inv.g1 f n), (𝔼.inv.g1 f (m + n) - (𝔼.inv.g1 f m) - (𝔼.inv.g1 f n)) = t},
  have hCT' : ∃ C, ∀ x ∈ T', abs (f.1.1 x) < C,
    cases this with E hE,
    use E,
    intros x hxT,
    rcases hxT with ⟨m, n, hm, hn, hgn, h⟩,
    specialize hE m n hm hn hgn,
    rw ← h,
    linarith,
  cases lemma37 f T hCT with C1 hC1,
  cases lemma37 f T' hCT' with C2 hC2,
  use [N, (max C1 C2) + 1],
  intros m n hm hn,
  by_cases hgn : 0 = 𝔼.inv.g1 f n,
  { specialize hC2 (df (λ (p : ℤ), 𝔼.inv.g1 f p) m n),
    have : df (λ (p : ℤ), 𝔼.inv.g1 f p) m n ∈ T',
      simp,
      use [m, hm, n, hn, hgn],
    specialize hC2 this,
    linarith [le_max_right C1 C2], },
  { have hgn' : 0 < 𝔼.inv.g1 f n,
      have := lemma31 f n hn,
      exact lt_of_le_of_ne this hgn,
    specialize hC1 (df (λ (p : ℤ), 𝔼.inv.g1 f p) m n),
    have : df (λ (p : ℤ), 𝔼.inv.g1 f p) m n ∈ T,
      simp,
      use [m, hm, n, hn, hgn'],
    specialize hC1 this,
    linarith [le_max_left C1 C2], },
end

lemma lemma47 (f : P') : ∃ (C : ℤ) , ∀ (m n : ℤ), 0 ≤ m → 0 ≤ n → abs (df (λ (p : ℤ), 𝔼.inv.g1 f p) m n) < C :=
begin
  rcases lemma46 f with ⟨N, C, hfN⟩,
  have hfs1 : set.finite (set.image2 (λ m n, abs (df (λ (p : ℤ), 𝔼.inv.g1 f p) m n)) {m | 0 ≤ m ∧ m < N} {n | 0 ≤ n ∧ n < N}),
    apply set.finite.image2,
      split,
      apply fintype.of_finset (finset.Ico_ℤ 0 N),
      simp,
    split,
    apply fintype.of_finset (finset.Ico_ℤ 0 N),
    simp,
  have hbdd : bdd_above (set.image2 (λ m n, abs (df (λ (p : ℤ), 𝔼.inv.g1 f p) m n)) {m | 0 ≤ m ∧ m < N} {n | 0 ≤ n ∧ n < N}),
    apply set.finite.bdd_above hfs1,
  simp at hbdd,
  cases hbdd with C1 hC1,
  simp at hC1,
  use max C C1 + 1,
  intros m n hm hn,
  have hmN := lt_or_le m N,
  have hnN := lt_or_le n N,
  cases hmN,
  { cases hnN,
      specialize @hC1 (abs (𝔼.inv.g1 f (m + n) - 𝔼.inv.g1 f m - 𝔼.inv.g1 f n)) m hm hmN n hn hnN rfl,
      simp,
      linarith [le_max_right C C1],
    specialize hfN n m hnN hm,
    simp at hfN,
    simp,
    have : 𝔼.inv.g1 f (m + n) - 𝔼.inv.g1 f m - 𝔼.inv.g1 f n = 𝔼.inv.g1 f (n + m) - 𝔼.inv.g1 f n - 𝔼.inv.g1 f m,
      rw [add_comm],
      ring,
    rw this,
    linarith [le_max_left C C1], },
  { specialize hfN m n hmN hn,
    linarith [le_max_left C C1], },
end

noncomputable def 𝔼.inv.g : P' → S := λ f, ⟨λ p, 𝔼.inv.g1 f p,
begin
  apply lemma26,
  { intros p hp,
    simp only [𝔼.inv.g1],
    split_ifs with hp1 hp2,
          exfalso,
          linarith,
        exfalso,
        linarith,
      refl,
    exfalso,
    linarith, },
  exact lemma47 f,
end⟩

lemma lemma48 (f : P') : ∃ (C : ℤ), ∀ n (hn : 0 ≤ n), abs (f.1.1 ((𝔼.inv.g f).1 n) - n) < C :=
begin
  have H : ∃ (N C : ℤ), ∀ n (hn : N ≤ n), abs (f.1.1 ((𝔼.inv.g f).1 n) - n) < C,
    rcases lemma34 f with ⟨N, hN, h⟩,
    have hN' : 0 ≤ N,
      linarith,
    set g := 𝔼.inv.g f with hg,
    choose C hC using f.1.2,
    use [N, C + abs (f.1.1 1)],
    intros n hn,
    specialize h n hn,
    have h0n : 0 ≤ n,
      linarith,
    have key := lemma43 f n h0n h,
    have : g.val = 𝔼.inv.g1 f,
      rw hg,
      refl,
    rw ← this at *,
    specialize hC 1 (g.1 n - 1),
    simp only [add_sub_cancel'_right, df_eq] at hC,
    cases key,
    rw abs_lt at *,
    cases hC,
    split,
      linarith [abs_nonneg (f.1.1 1)],
    linarith [le_abs_self (f.1.1 1)],
  rcases H with ⟨N, C, H⟩,
    have hfin : set.finite ((λ n, abs (f.1.1 ((𝔼.inv.g f).1 n) - n)) '' set.Ico 0 N),
    apply set.finite.image,
    split,
    apply fintype.of_finset (finset.Ico_ℤ 0 N),
    simp,
  have hbdd : bdd_above ((λ n, abs (f.1.1 ((𝔼.inv.g f).1 n) - n)) '' set.Ico 0 N),
    apply set.finite.bdd_above hfin,
  simp at hbdd,
  cases hbdd with C1 hC1,
  simp only [upper_bounds_eq, and_imp, set.mem_Ico, set.mem_image, set.mem_set_of_eq, exists_imp_distrib] at hC1,
  use max C C1 + 1,
  intros n hn,
  have hnN := lt_or_le n N,
  cases hnN,
    specialize @hC1 (abs (f.val.val ((𝔼.inv.g f).val n) - n)) n hn hnN rfl,
    linarith [le_max_right C C1],
  specialize H n hnN,
  linarith [le_max_left C C1],
end

lemma lemma49 : ∀ (a : 𝔼) (ha : a ∈ P), ∃ b, a * b = 1 :=
begin
  rintro a ⟨f, hf, h⟩,
  have hfP' : f ∈ P',
    exact h,
  use ↑(𝔼.inv.g ⟨f, hfP'⟩),
  rw ← hf,
  simp only [𝔼.mul_eq', 𝔼.one_eq'],
  rw [lemma17, quotient_add_group.eq],
  apply lemma4,
  cases lemma48 ⟨f, hfP'⟩ with C hC,
  use C,
  intros p hp,
  specialize hC p hp,
  rw ← abs_neg at hC,
  simp at hC,
  rw [add_comm],
  simp,
  exact hC,
end

lemma lemma50 : ∀ a b, a ∈ P → b ∈ P → a * b ∈ P :=
begin
  intros a b ha hb,
  rcases ha with ⟨u, hu, ha⟩,
  rcases hb with ⟨v, hv, hb⟩,
  rw [← hu, ← hv],
  simp only [𝔼.mul_eq'],
  rw lemma17,
  use [⟨u.val ∘ v.val, lemma14 u v⟩, rfl],
  rw lemma8 at *,
  intros C hC,
  cases ha C hC with M hM,
  have : 0 < max M 1,
    rw lt_max_iff,
    right,
    norm_num,
  cases hb (max M 1) this with N hN,
  use N,
  intros p hNp,
  specialize hN p hNp,
  have hvval : M < v.val p,
    rw max_lt_iff at hN,
    exact hN.1,
  specialize hM (v.val p) hvval,
  exact hM,
end

lemma lemma51 : (1 : 𝔼) ∈ P :=
begin
  use [(⟨(id : ℤ → ℤ), lemma16⟩ : S), rfl],
  intros n hn,
  use n + 1,
  split,
    linarith,
  norm_num,
end

noncomputable def 𝔼.inv : 𝔼 → 𝔼 := λ a,
if ha1 : a ∈ P then begin
  choose b hb using lemma49 a ha1,
  exact b,
end
else if ha2 : a = 0 then (0 : 𝔼) else begin
  choose b hb using lemma49 (-a) (lemma30 ha1 ha2),
  exact -b,
end

noncomputable instance field_𝔼 : field 𝔼 :=
{ inv := 𝔼.inv,
  exists_pair_ne := begin
    use [0, 1],
    have h0P := lemma10,
    have h1P := lemma51,
    intro h01,
    rw h01 at h0P,
    exact h0P h1P,
  end,
  mul_inv_cancel := begin
    intros a ha,
    show a * (𝔼.inv a) = 1,
    simp only [𝔼.inv],
    split_ifs,
      have := classical.some_spec (lemma49 a h),
      exact this,
    have := classical.some_spec (𝔼.inv._proof_2 a h ha),
    have heq : a * -(classical.some (𝔼.inv._proof_2 a h ha)) =
      -a * (classical.some (𝔼.inv._proof_2 a h ha)),
      ring,
    rw heq,
    exact this,
  end,
  inv_zero := begin
    show (𝔼.inv 0) = 0,
    simp only [𝔼.inv],
    split_ifs,
      exfalso,
      exact lemma10 h,
    refl,
  end,
  ..comm_ring_𝔼 }

lemma 𝔼.field.zero_eq : field.zero = (0 : 𝔼) := rfl

lemma 𝔼.field.one_eq : field.one = (1 : 𝔼) := rfl

noncomputable instance linear_ordered_field_𝔼 : linear_ordered_field 𝔼 :=
{ le := λ a b, -a + b ∈ P ∪ {0},
  lt := λ a b, -a + b ∈ P,
  le_refl := begin
    intro a,
    simp,
  end,
  le_trans := begin
    intros a b c hab hbc,
    simp at *,
    cases hab,
    { cases hbc,
      { left,
        rw [neg_add_eq_zero.mp hab, neg_add_eq_zero.mp hbc],
        simp, },
      { rw neg_add_eq_zero.mp hab,
        cc, }, },
    { cases hbc,
      { rw ← (neg_add_eq_zero.mp hbc),
        cc, },
      { right,
        have h : (-a + b) + (-b + c) ∈ P := lemma9 (-a + b) (-b + c) hab hbc,
        have heq : -a + c = (-a + b) + (-b + c),
          abel,
        rw heq,
        exact h, }, },
  end,
  lt_iff_le_not_le := begin
    intros a b,
    split,
    { intro hab,
      simp at hab,
      simp,
      split,
        cc,
      intro hfalse,
      cases hfalse,
      { rw neg_add_eq_zero.mp hfalse at hab,
        simp at hab,
        exact lemma10 hab, },
      { have heq : -b + a = -(-a + b),
          abel,
        rw heq at hfalse,
        exact lemma11 hab hfalse, }, },
    { rintro ⟨hab, hba⟩,
      cases hab,
      { exact hab, },
      { simp at hab,
        simp at hba,
        have : ¬(-b + a = 0),
          finish,
        exfalso,
        apply this,
        rw neg_add_eq_zero at *,
        exact eq.symm hab, }, },
  end,
  le_antisymm := begin
    intros a b hab hba,
    cases hab,
    { cases hba,
      { exfalso,
        have :  -b + a = -(-a + b),
          abel,
        rw this at hba,
        exact lemma11 hab hba, },
      { simp at hba,
        exact eq.symm (neg_add_eq_zero.mp hba), }, },
    { simp at hab,
      exact neg_add_eq_zero.mp hab, },
  end,
  add_le_add_left := begin
    intros a b hab c,
    show -(c + a) + (c + b) ∈ P ∪ {0},
    have : -(c + a) + (c + b) = -a + b,
      abel,
    rw this,
    exact hab,
  end,
  mul_pos := begin
    intros a b ha hb,
    change -(0 : 𝔼) + a ∈ P at ha,
    change -(0 : 𝔼) + b ∈ P at hb,
    change -(0 : 𝔼) + (a * b) ∈ P,
    simp at *,
    exact lemma50 a b ha hb,
  end,
  le_total := begin
    intros a b,
    change  -a + b ∈ P ∪ {0} ∨ -b + a ∈ P ∪ {0},
    simp,
    cases lemma29 (-a + b),
      left,
      right,
      exact h,
    cases h,
      left,
      left,
      exact h,
    simp at h,
    right,
    right,
    exact h,
  end,
  zero_lt_one := begin
    simp only [𝔼.field.zero_eq, 𝔼.field.one_eq],
    change -(0 : 𝔼) + 1 ∈ P,
    ring,
    exact lemma51,
  end,
  ..field_𝔼 }

lemma lemma52 : ∀ n, (λ p, n * p) ∈ S  :=
begin
  intro n,
  use 1,
  intros p q,
  simp,
  ring,
  norm_num,
end

lemma lemma53 : ∀ n : ℕ, (n : 𝔼) =
  @coe ↥S 𝔼 eudoxus_reals_group.has_lift_t ⟨λ p, n * p, lemma52 n⟩ :=
begin
  intro n,
  induction n,
    simp,
    refl,
  simp,
  rw n_ih,
  ring,
  have : @coe ↥S 𝔼 eudoxus_reals_group.has_lift_t ⟨has_mul.mul ↑n_n, lemma52 n_n⟩ + @coe ↥S 𝔼 eudoxus_reals_group.has_lift_t ⟨id, lemma16⟩ =
    @coe ↥S 𝔼 eudoxus_reals_group.has_lift_t (⟨has_mul.mul ↑n_n, lemma52 n_n⟩ + ⟨id, lemma16⟩),
    refl,
  rw this,
  simp,
  have heq : ∀ (z : ℤ), ↑n_n * z + z = (↑n_n + 1) * z,
    intro z,
    ring,
  simp_rw heq,
end

lemma lemma54 (f g : S) (hfg : (↑f : 𝔼) = ↑g) : (∀ (C : ℤ), 0 < C → (∃ (N : ℤ), ∀ (p : ℤ), N < p → C < f.val p))
  → (∀ (C : ℤ), 0 < C → (∃ (N : ℤ), ∀ (p : ℤ), N < p → C < g.val p)) :=
begin
  intro hf,
  intros C hC,
  have hfg' : (0 : 𝔼) = -↑(f : S) + ↑(g : S),
    rw hfg,
    simp,
  change ↑(0 : S) = ↑(-f + g) at hfg',
  rw quotient_add_group.eq at hfg',
  simp at hfg',
  cases hfg' with B hB,
  change ∀ (p : ℤ), abs (-f.val p + g.val p) < B at hB,
  have h0BC : 0 < B + C,
    linarith [hB 0, abs_nonneg (-f.val 0 + g.val 0)],
  cases hf (B + C) h0BC with N hN,
  use N,
  intros p hNp,
  specialize hN p hNp,
  specialize hB p,
  rw abs_lt at hB,
  cases hB,
  linarith,
end

lemma lemma55 {f g : S} (B : ℤ) : (0 : 𝔼) < ↑g → (∀ p, abs (f.1 p) < abs (g.1 p) + B) → (↑f : 𝔼) ≤ ↑g :=
begin
  rintro ⟨v, hvg, hv⟩ habs,
  simp at hvg,
  by_contradiction hfalse,
  simp at hfalse,
  change ↑((-g) + f) ∈ P at hfalse,
  rcases hfalse with ⟨gf, hgf, hfalse⟩,
  rw lemma8 at *,
  have h1 := lemma54 gf (-g + f) hgf hfalse,
  have h2 := lemma54 v g hvg hv,
  have : (0 : ℤ) < max B 1,
    rw lt_max_iff,
    norm_num,
  cases h1 (max B 1) this with N1 h1,
  cases h2 (max B 1) this with N2 h2,
  have hle1 : N1 < max N1 N2 + 1,
    linarith [le_max_left N1 N2],
  have hle2 : N2 < max N1 N2 + 1,
    linarith [le_max_right N1 N2],
  specialize h1 (max N1 N2 + 1) hle1,
  specialize h2 (max N1 N2 + 1) hle2,
  specialize habs (max N1 N2 + 1),
  change max B 1 < -g.val (max N1 N2 + 1) + f.val (max N1 N2 + 1) at h1,
  have heq : abs (g.val (max N1 N2 + 1)) = g.val (max N1 N2 + 1),
    rw abs_of_pos,
    linarith,
  rw [heq, abs_lt] at habs,
  cases habs,
  linarith [le_max_left B 1],
end

instance archimedean_𝔼 : archimedean 𝔼 :=
begin
  rw archimedean_iff_nat_le,
  intro a,
  cases lemma12 a with u hu,
  rcases lemma23 u with ⟨A, B, hA, hAB⟩,
  have := int.eq_coe_of_zero_le (le_of_lt hA),
  cases this with n hAn,
  have hn : 0 < n,
    rw hAn at hA,
    exact int.coe_nat_pos.mp hA,
  use n,
  rw [← hu, lemma53],
  apply lemma55 B,
    rw ← lemma53,
    exact nat.cast_pos.mpr hn,
  rw ← hAn,
  intro p,
  specialize hAB p,
  have :  A * abs p = abs (A * p),
    have heq : abs A * abs p = abs (A * p) := (abs_mul A p).symm,
    rw abs_of_pos hA at heq,
    exact heq,
  rw this at hAB,
  exact hAB,
end

noncomputable instance : floor_ring 𝔼 := archimedean.floor_ring 𝔼

noncomputable instance decidable_linear_order_𝔼 : decidable_linear_order 𝔼 := classical.DLO 𝔼

noncomputable instance lattice_𝔼 : lattice 𝔼 := by apply_instance

lemma lemma56 : ∀ {x y : 𝔼} (hxy : x < y), ∃ (M N : ℤ) (hN : 0 < N), (N : 𝔼) * x < (M : 𝔼) ∧ (M : 𝔼) < (N : 𝔼) * y :=
begin
  intros x y hxy,
  rcases exists_rat_btwn hxy with ⟨q, hq1, hq2⟩,
  rcases q with ⟨M, N, h1, h2⟩,
  use [M, N, int.coe_nat_pos.mpr h1],
  split,
    rw mul_comm,
    rw ← lt_div_iff,
      exact hq1,
      exact int.cast_pos.mpr (int.coe_nat_pos.mpr h1),
  rw mul_comm,
  rw ← div_lt_iff,
    exact hq2,
  exact int.cast_pos.mpr (int.coe_nat_pos.mpr h1),
end

lemma lemma57 : ∃ C, ∀ (a b : 𝔼), abs (floor (a + b) - floor a - floor b) < C :=
begin
  use 2,
  intros a b,
  have ha1 := floor_le a,
  have ha2 := lt_floor_add_one a,
  have hb1 := floor_le b,
  have hb2 := lt_floor_add_one b,
  have : (2 : 𝔼) = (↑2 : 𝔼),
    simp,
  have h1 : ↑⌊a + b⌋ - ↑⌊a⌋ - ↑⌊b⌋ < (↑2 : 𝔼),
    linarith [floor_le (a + b)],
  have h2 : -(↑2 : 𝔼) < ↑⌊a + b⌋ - ↑⌊a⌋ - ↑⌊b⌋,
    linarith [lt_floor_add_one (a + b)],
  have h3 : ↑⌊a + b⌋ - ↑⌊a⌋ - ↑⌊b⌋ = (↑(⌊a + b⌋ - ⌊a⌋ - ⌊b⌋) : 𝔼),
    simp,
  rw h3 at *,
  have h1' : ⌊a + b⌋ - ⌊a⌋ - ⌊b⌋ < 2,
    rw ← @int.cast_lt 𝔼,
    exact h1,
  have h2' : -2 < ⌊a + b⌋ - ⌊a⌋ - ⌊b⌋,
    rw ← @int.cast_lt 𝔼,
    exact h2,
  rw abs_lt,
  split,
    linarith,
  linarith,
end

@[simp] lemma upper_bounds_eq' {S : set 𝔼} : upper_bounds S = {x : 𝔼 | ∀ ⦃a : 𝔼⦄, a ∈ S → a ≤ x} := rfl

lemma lemma58 (K : set ℤ) (hK1 : set.finite K) (hK2 : K.nonempty) :
  ∃ n (hn : n ∈ K), ∀ t ∈ K, t ≤ n :=
begin
  cases set.finite.exists_finset hK1 with K' hK'K,
  have hK' : K'.nonempty,
    cases hK2 with x hx,
    use x,
    rw hK'K,
    exact hx,
  use finset.max' K' hK',
  simp_rw ← hK'K,
  use finset.max'_mem K' hK',
  intros t ht,
  use finset.le_max' K' t ht,
end

lemma lemma59 (K : set ℤ) (hK1 : K.nonempty) (hK2 : bdd_above K) :
  ∃ n (hn : n ∈ K), ∀ t ∈ K, t ≤ n :=
begin
  cases hK2 with M hM,
  simp at hM,
  cases hK1 with m hm,
  set K' := K ∩ set.Icc m M with hK'K,
  have hK'1 : set.finite K',
    have : (set.Icc m M).finite := ⟨fintype.of_finset (finset.Ico_ℤ m (M + 1)) (by {simp [int.lt_add_one_iff]})⟩,
    rw hK'K,
    apply set.finite.subset this,
    exact set.inter_subset_right K (set.Icc m M),
  have hK'2 : K'.nonempty,
    rw hK'K,
    use [m, hm],
    simp,
    apply hM,
    exact hm,
  rcases lemma58 K' hK'1 hK'2 with ⟨n, hn, h⟩,
  rw hK'K at *,
  use [n, hn.1],
  intros t htK,
  have htm := lt_or_le t m,
  cases htm,
    have : m ≤ n,
      rcases hn with ⟨hn1, hn2, hn3⟩,
      exact hn2,
    linarith,
  apply h,
  use [htK, htm, hM htK],
end

lemma lemma60 (p : ℤ) (hp : 0 ≤ p) (T : set 𝔼) (hT1 : T.nonempty) (hT2 : bdd_above T) :
  ∃ n (hn : n ∈ {m | ∃ x ∈ T, m = floor ((p : 𝔼) * x)}), ∀ t ∈ {m | ∃ x ∈ T, m = floor ((p : 𝔼) * x)}, t ≤ n :=
begin
  have h1 : {m | ∃ x ∈ T, m = floor ((p : 𝔼) * x)}.nonempty,
    cases hT1 with x hx,
    use [⌊↑p * x⌋, x, hx],
  have h2 : bdd_above {m | ∃ x ∈ T, m = floor ((p : 𝔼) * x)},
    cases hT2 with M hM,
    use ⌊↑p * M⌋ + 1,
    simp only [set.mem_set_of_eq, exists_imp_distrib, upper_bounds_eq],
    intros a x hxT hapx,
    rw hapx,
    have hpxpM : ↑p * x ≤ ↑p * M,
      apply mul_le_mul_of_nonneg_left,
        simp at hM,
        exact hM hxT,
      exact int.cast_nonneg.mpr hp,
    have : ↑⌊↑p * x⌋ ≤ ↑⌊↑p * M⌋ + (1 : 𝔼),
      linarith [floor_le (↑p * x), lt_floor_add_one (↑p * M)],
    have heq : ↑⌊↑p * M⌋ + 1 = (↑(⌊↑p * M⌋ + 1) : 𝔼),
      simp,
    rw heq at this,
    rw ← @int.cast_le 𝔼,
    exact this,
  exact lemma59 {m | ∃ x ∈ T, m = floor ((p : 𝔼) * x)} h1 h2,
end

noncomputable def T_sup_f1 (T : set 𝔼) (hT1 : T.nonempty) (hT2 : bdd_above T) : ℤ → ℤ := λ p,
if hp : 0 ≤ p then begin
  choose n hn using lemma60 p hp T hT1 hT2,
  exact n,
end
else begin
  simp at hp,
  have hp' : 0 ≤ -p,
    linarith,
  choose n hn using lemma60 (-p) hp' T hT1 hT2,
  exact -n,
end

lemma lemma61 (a p : ℤ) (T : set 𝔼) (hT1 : T.nonempty) (hT2 : bdd_above T) (hp : 0 ≤ p) (m1 m2 : 𝔼) (hm1 : m1 ∈ T) (hm2 : m2 ∈ T) :
  a = T_sup_f1 T hT1 hT2 p → a = ⌊↑p * m1⌋ → a = ⌊↑p * max m1 m2⌋ :=
begin
  intros ha1 ha2,
  simp only [T_sup_f1] at ha1,
  split_ifs at ha1,
  rcases classical.some_spec (lemma60 p hp T hT1 hT2) with ⟨⟨c, hc, hfc1⟩, hfc2⟩,
  set fp := classical.some (lemma60 p hp T hT1 hT2) with hfpeq,
  rw ← hfpeq at *,
  have h1 : ⌊↑p * m1⌋ ≤ ⌊↑p * max m1 m2⌋,
    have : (↑p * m1 : 𝔼) ≤ ↑p * max m1 m2,
      apply mul_le_mul_of_nonneg_left (le_max_left m1 m2),
      exact int.cast_nonneg.mpr hp,
    exact floor_mono this,
  have h2 : ⌊↑p * max m1 m2⌋ ≤ ⌊↑p * m1⌋,
    specialize hfc2 ⌊↑p * max m1 m2⌋,
    rw ha2 at ha1,
    rw ← ha1 at hfc2,
    apply hfc2,
    use max m1 m2,
    split,
      cases max_choice m1 m2,
        rw h,
        exact hm1,
      rw h,
      exact hm2,
    refl,
  linarith,
end

noncomputable def T_sup_f (T : set 𝔼) (hT1 : T.nonempty) (hT2 : bdd_above T) : S := ⟨λ p, T_sup_f1 T hT1 hT2 p,
begin
  apply lemma26,
  { intros p hp,
    simp only [T_sup_f1],
    split_ifs with hp1 hp2,
          exfalso,
          linarith,
        exfalso,
        linarith,
      refl,
    exfalso,
    linarith, },
  cases lemma57 with C hC,
  use C,
  intros m n hm hn,
  have hmn : 0 ≤ m + n,
    linarith,
  rw abs_lt,
  simp,
  simp only [T_sup_f1],
  split_ifs,
  set fm := classical.some (lemma60 m hm T hT1 hT2) with hfmeq,
  set fn := classical.some (lemma60 n hn T hT1 hT2) with hfneq,
  set fmn := classical.some (lemma60 (m + n) hmn T hT1 hT2) with hfmneq,
  rcases classical.some_spec (lemma60 m hm T hT1 hT2) with ⟨⟨xm, hxm, hfm1⟩, hfm2⟩,
  rcases classical.some_spec (lemma60 n hn T hT1 hT2) with ⟨⟨xn, hxn, hfn1⟩, hfn2⟩,
  rcases classical.some_spec (lemma60 (m + n) hmn T hT1 hT2) with ⟨⟨xmn, hxmn, hfmn1⟩, hfmn2⟩,
  rw ← hfmeq at *,
  rw ← hfneq at *,
  rw ← hfmneq at *,
  set x1 := max xm xn with hx1,
  have hx1' : x1 = max xn xm,
    rw hx1,
    exact max_comm xm xn,
  have hx1'' : x1 ∈ T,
    rw hx1,
    cases max_choice xm xn,
      rw h,
      exact hxm,
    rw h,
    exact hxn,
  have hx11 := lemma61 fm m T hT1 hT2 hm xm xn hxm hxn,
  have : fm = T_sup_f1 T hT1 hT2 m,
    simp only [T_sup_f1],
    split_ifs,
    exact hfmeq,
  specialize hx11 this hfm1,
  have hx12 := lemma61 fn n T hT1 hT2 hn xn xm hxn hxm,
  have : fn = T_sup_f1 T hT1 hT2 n,
    simp only [T_sup_f1],
    split_ifs,
    exact hfneq,
  specialize hx12 this hfn1,
  rw ← hx1 at hx11,
  rw ← hx1' at hx12,
  set x := max x1 xmn with hx,
  have hx' : x = max xmn x1,
    rw hx,
    exact max_comm x1 xmn,
  have hx01 := lemma61 fm m T hT1 hT2 hm x1 xmn hx1'' hxmn,
  have : fm = T_sup_f1 T hT1 hT2 m,
    simp only [T_sup_f1],
    split_ifs,
    exact hfmeq,
  specialize hx01 this hx11,
  have hx02 := lemma61 fn n T hT1 hT2 hn x1 xmn hx1'' hxmn,
  have : fn = T_sup_f1 T hT1 hT2 n,
    simp only [T_sup_f1],
    split_ifs,
    exact hfneq,
  specialize hx02 this hx12,
  have hx03 := lemma61 fmn (m + n) T hT1 hT2 hmn xmn x1 hxmn hx1'',
  have : fmn = T_sup_f1 T hT1 hT2 (m + n),
    simp only [T_sup_f1],
    split_ifs,
    exact hfmneq,
  specialize hx03 this hfmn1,
  rw ← hx at hx01,
  rw ← hx at hx02,
  rw ← hx' at hx03,
  have hmxnx : ↑(m + n) * x = ↑m * x + ↑n * x,
    have heq : (↑(m + n) : 𝔼) = ↑m + ↑n,
      simp,
    rw heq,
    ring,
  rw hmxnx at hx03,
  specialize hC (↑m * x) (↑n * x),
  rw abs_lt at hC,
  split,
    linarith,
  linarith,
end⟩

lemma lemma62 : ∀ (x y : 𝔼) (hxy : x < y), ∃ (M N : ℤ) (hN : 0 < N), x < (M : 𝔼) / (N : 𝔼) ∧ (M : 𝔼) / (N : 𝔼) < y :=
begin
  intros x y hxy,
  rcases exists_rat_btwn hxy with ⟨q, hq1, hq2⟩,
  rcases q with ⟨M, N, h1, h2⟩,
  use [M, N, int.coe_nat_pos.mpr h1, hq1, hq2],
end

noncomputable def T_sup (T : set 𝔼) : 𝔼 :=
if hT1 : T.nonempty ∧ bdd_above T then
  if hT2 : ∃ x ∈ T, ∀ y ∈ T, y ≤ x then begin
    choose x hx using hT2,
    exact x,
  end
  else (↑(T_sup_f T hT1.1 hT1.2) : 𝔼)
else 0

lemma lemma63 (f g : S) : (∀ p (hp : 0 ≤ p), f.1 p ≤ g.1 p) → (↑f : 𝔼) ≤ (↑g : 𝔼) :=
begin
  intro h,
  by_contradiction hfalse,
  simp at hfalse,
  change ↑(-g + f) ∈ P at hfalse,
  rcases hfalse with ⟨gf, hgf, hfalse⟩,
  have := lemma54 gf (-g + f) hgf,
  rw lemma8 at hfalse,
  specialize this hfalse,
  have h01 : (0 : ℤ) < 1,
    norm_num,
  cases this 1 h01 with N hN,
  have hN01 : N < max (N + 1) 0,
    linarith [le_max_left (N + 1) 0],
  have hN02 : 0 ≤ max (N + 1) 0,
    exact le_max_right (N + 1) 0,
  specialize hN (max (N + 1) 0) hN01,
  specialize h (max (N + 1) 0) hN02,
  simp only [S.add_eq', S.add_eq, S.neg_eq', lt_neg_add_iff_add_lt, S.neg_eq] at hN,
  linarith,
end

lemma lemma64 : ∀ n : ℤ, (n : 𝔼) =
  @coe ↥S 𝔼 eudoxus_reals_group.has_lift_t ⟨λ p, n * p, lemma52 n⟩ :=
begin
  intro n,
  cases le_or_lt n 0,
    have hn : 0 ≤ -n,
      linarith,
    cases int.eq_coe_of_zero_le hn with n' hn',
    have := lemma53 n',
    have heq1 : (↑n : 𝔼) = -↑(↑n' : ℤ),
      rw ← hn',
      simp,
    have heq2 : (↑n : 𝔼) = -↑(n' : ℕ),
      rw heq1,
      simp,
    have heq3 : (↑(⟨λ (p : ℤ), n * p, lemma52 n⟩ : S) : 𝔼) = -↑(⟨λ (p : ℤ), ↑n' * p, lemma52 ↑n'⟩ : S),
      rw ← hn',
      show ↑(⟨λ (p : ℤ), n * p, lemma52 n⟩ : S) = ↑(-⟨λ (p : ℤ), -n * p, lemma52 (-n)⟩ : S),
      rw quotient_add_group.eq,
      use 1,
      intro p,
      norm_num,
    linarith,
  have hn : 0 ≤ n,
    linarith,
  cases int.eq_coe_of_zero_le hn with n' hn',
  rw hn',
  exact lemma53 n',
end

lemma T_le_cSup : ∀ (s : set 𝔼) (a : 𝔼), bdd_above s → a ∈ s → a ≤ T_sup s :=
begin
  intros T x hT hxT,
  simp only [T_sup],
  split_ifs with hT1 hT3,
  { cases classical.some_spec hT3,
    exact h x hxT, },
  { have hT3' : ∀ (x : 𝔼) (H : x ∈ T), ∃ (y : 𝔼), y ∈ T ∧ x < y,
      rw not_exists at hT3,
      intros x hx,
      specialize hT3 x,
      rw not_exists at hT3,
      specialize hT3 hx,
      rw not_forall at hT3,
      cases hT3 with y hy,
      use y,
      rw not_imp at hy,
      cases hy with hy1 hy2,
      simp at hy2,
      use [hy1, hy2],
    rcases hT3' x hxT with ⟨y, hy, hxy⟩,
    rcases lemma62 x y hxy with ⟨M, N, hN, hMN1, hMN2⟩,
    have : ∀ p (h0p : 0 ≤ p), p * M ≤ T_sup_f1 T hT1.1 hT1.2 (p * N),
      intros p hp,
      have hpN0 : 0 ≤ p * N,
        apply mul_nonneg hp,
        linarith,
      simp only [T_sup_f1],
      split_ifs,
      rcases classical.some_spec (lemma60 (p * N) hpN0 T hT1.1 hT1.2) with ⟨⟨xm, hxmT, hsome1⟩, hsome2⟩,
      rw hsome1 at *,
      specialize hsome2 ⌊↑(p * N) * y⌋,
      rw set.mem_set_of_eq at hsome2,
      have : ∃ (x : 𝔼) (H : x ∈ T), ⌊↑(p * N) * y⌋ = ⌊↑(p * N) * x⌋,
        use [y, hy, rfl],
      specialize hsome2 this,
      have :  ⌊(↑(p * N) : 𝔼) * (↑M : 𝔼) / (↑N : 𝔼)⌋ ≤ ⌊(↑(p * N) : 𝔼) * (y : 𝔼)⌋,
        apply floor_mono,
        rw [div_eq_mul_inv, mul_assoc],
        apply mul_le_mul_of_nonneg_left,
          rw [← div_eq_mul_inv],
          linarith,
        exact int.cast_nonneg.mpr hpN0,
      have heq : (↑(p * N) : 𝔼) * (↑M : 𝔼) / (↑N : 𝔼) = (↑(p * M) : 𝔼),
        have heq1 : ∀ N : ℤ, (↑(p * N) : 𝔼) = ↑p * ↑N,
          intro N,
          simp,
        rw [heq1 N, heq1 M, mul_comm, div_eq_mul_inv, mul_assoc, mul_assoc, mul_inv_cancel],
          ring,
        simp,
        linarith,
        rw heq at this,
      have heq' : ⌊(↑(p * M) : 𝔼)⌋ = p * (M : ℤ),
        rw floor_eq_iff,
        split,
          linarith,
        linarith,
      linarith,
    have H := lemma63 (⟨(λ p, M * p), lemma52 M⟩),
    set fN := (T_sup_f T hT1.1 hT1.2).1 ∘ (⟨(λ p, N * p), lemma52 N⟩ : S).1 with hfN1,
    have hfN2 : fN ∈ S,
      rw hfN1,
      apply lemma14 (T_sup_f T hT1.1 hT1.2) ⟨(λ p, N * p), lemma52 N⟩,
    specialize H (⟨fN, hfN2⟩ : S),
    dsimp at H,
    dsimp at hfN1,
    have : (∀ (p : ℤ), 0 ≤ p → M * p ≤ fN p),
      rw hfN1,
      intros p h0p,
      specialize this p h0p,
      have heq : T_sup_f1 T hT1.1 hT1.2 (p * N) = (↑(T_sup_f T hT1.1 hT1.2) ∘ has_mul.mul N) p,
        simp,
        rw mul_comm,
        simp only [T_sup_f],
        simp,
      rw [← heq, mul_comm],
      exact this,
      specialize H this,
    have heq1 : (M : 𝔼) = (⟨has_mul.mul M, lemma52 M⟩ : S) := lemma64 M,
    have heq2 : ↑(⟨fN, hfN2⟩ : S) = ↑(T_sup_f T hT1.1 hT1.2) * (↑N : 𝔼),
      simp_rw hfN1,
      rw [lemma64 N, 𝔼.mul_eq', lemma17],
      simp,
    rw [← heq1, heq2, mul_comm] at H,
    have := (@div_le_iff' 𝔼 (linear_ordered_field_𝔼) (↑M) (↑N) (↑(T_sup_f T hT1.1 hT1.2)) (int.cast_pos.mpr hN)).mpr H,
    linarith, },
  { exfalso,
    simp at hT1,
    cases set.eq_empty_or_nonempty T,
      rw h at hxT,
      exact hxT,
    exact hT1 h hT, },
end

lemma T_cSup_le : ∀ (s : set 𝔼) (a : 𝔼), s.nonempty → a ∈ upper_bounds s → T_sup s ≤ a :=
begin
  intros T y hT1 hyT,
  have hT2 : bdd_above T,
    use [y, hyT],
  have hT : T.nonempty ∧ bdd_above T := ⟨hT1, hT2⟩,
  simp only [T_sup],
  split_ifs,
  { simp at hyT,
    cases classical.some_spec h with hs1 hs2,
    exact hyT hs1, },
  { by_contradiction hfalse,
    rw not_le at hfalse,
    rcases lemma56 hfalse with ⟨M, N, hN, hMN1, hMN2⟩,
    have heq1 := lemma64 M,
    have hin := lemma14 (T_sup_f T hT1 hT2) ⟨has_mul.mul N, lemma52 N⟩,
    have heq2 : (↑N : 𝔼) * ↑(T_sup_f T hT1 hT2) = ↑(⟨(↑(T_sup_f T hT1 hT2) ∘ has_mul.mul N), hin⟩ : S),
      rw [mul_comm, 𝔼.mul_eq', lemma64 N, lemma17],
      refl,
    rw [heq1, heq2] at hMN2,
    simp only [T_sup_f, subtype.coe_mk, subtype.val_eq_coe] at hMN2,
    rcases hMN2 with ⟨sum, hsumeq, H⟩,
    rw lemma8 at H,
    change ↑sum = ↑(-(⟨has_mul.mul M, lemma52 M⟩ : S) + ⟨T_sup_f1 T hT1 hT2 ∘ has_mul.mul N, hin⟩) at hsumeq,
    have := lemma54 sum (-(⟨has_mul.mul M, lemma52 M⟩ : S) + ⟨T_sup_f1 T hT1 hT2 ∘ has_mul.mul N, hin⟩) hsumeq H,
    rw ← lemma8 at this,
    have h01 : (0 : ℤ) < 1,
      norm_num,
    rcases this 1 h01 with ⟨p, h0p, hfp⟩,
    simp at hfp,
    have hcomm : N * p = p * N := mul_comm N p,
    rw [mul_comm, hcomm] at hfp,
    have hpN : 0 ≤ p * N := le_of_lt (mul_pos h0p hN),
    have hx : ∃ x ∈ T, T_sup_f1 T hT1 hT2 (p * N) = ⌊↑(p * N) * x⌋,
      simp only [T_sup_f1],
      split_ifs,
      cases classical.some_spec (lemma60 (p * N) hpN T hT1 hT2) with hsome1 hsome2,
      exact hsome1,
    rcases hx with ⟨x, hxT, hx⟩,
    specialize hyT hxT,
    have hle1 : ↑(p * N) * x ≤ ↑(p * N) * y := mul_le_mul_of_nonneg_left hyT (int.cast_nonneg.mpr hpN),
    have heq3 : ↑(p * N) * y = ↑p * (↑N * y),
      rw ← mul_assoc,
      simp,
    have hle2 : ↑p * (↑N * y) < ↑p * ↑M,
      rw mul_lt_mul_left,
        exact hMN1,
      exact int.cast_pos.mpr h0p,
    have hle3 : ↑(p * N) * x < ↑p * ↑M,
      linarith,
    rw hx at hfp,
    have hle4 : ⌊(↑(p * N) : 𝔼) * x⌋ ≤ ⌊(↑p : 𝔼) * (↑M : 𝔼)⌋ := floor_mono (le_of_lt hle3),
    have heq4 : ⌊(↑p : 𝔼) * (↑M : 𝔼)⌋ = p * M,
      rw floor_eq_iff,
      split,
        simp,
      have : (↑(p * M) : 𝔼) = ↑p * ↑M,
        simp,
      linarith,
    linarith, },
end

@[simp] lemma lower_bounds_eq' {S : set 𝔼} : lower_bounds S = {x : 𝔼 | ∀ ⦃a : 𝔼⦄, a ∈ S → x ≤ a} := rfl

lemma T_cInf_le : ∀ (s : set 𝔼) (a : 𝔼), bdd_below s → a ∈ s → -T_sup {x : 𝔼 | -x ∈ s} ≤ a :=
begin
  intros T x hT hxT,
  cases hT with y hy,
  simp at hy,
  have h1 : bdd_above {x : 𝔼 | -x ∈ T},
    use -y,
    intros a ha,
    simp at ha,
    specialize hy ha,
    linarith,
  have := T_le_cSup {x : 𝔼 | -x ∈ T} (-x) h1,
  have h2 : -x ∈ {x : 𝔼 | -x ∈ T},
    simp,
    exact hxT,
  specialize this h2,
  linarith,
end

lemma T_le_cInf : ∀ (s : set 𝔼) (a : 𝔼), s.nonempty → a ∈ lower_bounds s → a ≤ -T_sup {x : 𝔼 | -x ∈ s} :=
begin
  intros T x hT hxT,
  cases hT with y hy,
  simp at hxT,
  have h1 : (-x) ∈ upper_bounds {x : 𝔼 | -x ∈ T},
    intros a ha,
    specialize hxT ha,
    linarith,
  have h2 : {x : 𝔼 | -x ∈ T}.nonempty,
    use -y,
    simp,
    exact hy,
  have := T_cSup_le {x : 𝔼 | -x ∈ T} (-x) h2 h1,
  linarith,
end

noncomputable instance : conditionally_complete_linear_order 𝔼 :=
{ Sup := λ T, T_sup T,
  Inf := λ T, -T_sup {x | -x ∈ T},
  le_cSup := T_le_cSup,
  cSup_le := T_cSup_le,
  cInf_le := T_cInf_le,
  le_cInf := T_le_cInf,
  ..decidable_linear_order_𝔼,
  ..lattice_𝔼 }


/-
Copyright (c) 2021 Yury G. Kudryashov. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yury G. Kudryashov
-/
import analysis.calculus.cont_diff

/-!
# Smoothness of `real.sqrt`

In this file we prove that `real.sqrt` is infinitely smooth at all points `x ≠ 0` and provide some
dot-notation lemmas.

## Tags

sqrt, differentiable
-/

open set
open_locale topology

namespace real

/-- Local homeomorph between `(0, +∞)` and `(0, +∞)` with `to_fun = λ x, x ^ 2` and
`inv_fun = sqrt`. -/
noncomputable def sq_local_homeomorph : local_homeomorph ℝ ℝ :=
{ to_fun := λ x, x ^ 2,
  inv_fun := sqrt,
  source := Ioi 0,
  target := Ioi 0,
  map_source' := λ x hx, mem_Ioi.2 (pow_pos hx _),
  map_target' := λ x hx, mem_Ioi.2 (sqrt_pos.2 hx),
  left_inv' := λ x hx, sqrt_sq (le_of_lt hx),
  right_inv' := λ x hx, sq_sqrt (le_of_lt hx),
  open_source := is_open_Ioi,
  open_target := is_open_Ioi,
  continuous_to_fun := (continuous_pow 2).continuous_on,
  continuous_inv_fun := continuous_on_id.sqrt }

lemma deriv_sqrt_aux {x : ℝ} (hx : x ≠ 0) :
  has_strict_deriv_at sqrt (1 / (2 * sqrt x)) x ∧ ∀ n, cont_diff_at ℝ n sqrt x :=
begin
  cases hx.lt_or_lt with hx hx,
  { rw [sqrt_eq_zero_of_nonpos hx.le, mul_zero, div_zero],
    have : sqrt =ᶠ[𝓝 x] (λ _, 0) := (gt_mem_nhds hx).mono (λ x hx, sqrt_eq_zero_of_nonpos hx.le),
    exact ⟨(has_strict_deriv_at_const x (0 : ℝ)).congr_of_eventually_eq this.symm,
      λ n, cont_diff_at_const.congr_of_eventually_eq this⟩ },
  { have : ↑2 * sqrt x ^ (2 - 1) ≠ 0, by simp [(sqrt_pos.2 hx).ne', @two_ne_zero ℝ],
    split,
    { simpa using sq_local_homeomorph.has_strict_deriv_at_symm hx this
        (has_strict_deriv_at_pow 2 _) },
    { exact λ n, sq_local_homeomorph.cont_diff_at_symm_deriv this hx
        (has_deriv_at_pow 2 (sqrt x)) (cont_diff_at_id.pow 2) } }
end

lemma has_strict_deriv_at_sqrt {x : ℝ} (hx : x ≠ 0) :
  has_strict_deriv_at sqrt (1 / (2 * sqrt x)) x :=
(deriv_sqrt_aux hx).1

lemma cont_diff_at_sqrt {x : ℝ} {n : ℕ∞} (hx : x ≠ 0) :
  cont_diff_at ℝ n sqrt x :=
(deriv_sqrt_aux hx).2 n

lemma has_deriv_at_sqrt {x : ℝ} (hx : x ≠ 0) : has_deriv_at sqrt (1 / (2 * sqrt x)) x :=
(has_strict_deriv_at_sqrt hx).has_deriv_at

end real

open real

section deriv

variables {f : ℝ → ℝ} {s : set ℝ} {f' x : ℝ}

lemma has_deriv_within_at.sqrt (hf : has_deriv_within_at f f' s x) (hx : f x ≠ 0) :
  has_deriv_within_at (λ y, sqrt (f y)) (f' / (2 * sqrt (f x))) s x :=
by simpa only [(∘), div_eq_inv_mul, mul_one]
  using (has_deriv_at_sqrt hx).comp_has_deriv_within_at x hf

lemma has_deriv_at.sqrt (hf : has_deriv_at f f' x) (hx : f x ≠ 0) :
  has_deriv_at (λ y, sqrt (f y)) (f' / (2 * sqrt(f x))) x :=
by simpa only [(∘), div_eq_inv_mul, mul_one] using (has_deriv_at_sqrt hx).comp x hf

lemma has_strict_deriv_at.sqrt (hf : has_strict_deriv_at f f' x) (hx : f x ≠ 0) :
  has_strict_deriv_at (λ t, sqrt (f t)) (f' / (2 * sqrt (f x))) x :=
by simpa only [(∘), div_eq_inv_mul, mul_one] using (has_strict_deriv_at_sqrt hx).comp x hf

lemma deriv_within_sqrt (hf : differentiable_within_at ℝ f s x) (hx : f x ≠ 0)
  (hxs : unique_diff_within_at ℝ s x) :
  deriv_within (λx, sqrt (f x)) s x = (deriv_within f s x) / (2 * sqrt (f x)) :=
(hf.has_deriv_within_at.sqrt hx).deriv_within hxs

@[simp] lemma deriv_sqrt (hf : differentiable_at ℝ f x) (hx : f x ≠ 0) :
  deriv (λx, sqrt (f x)) x = (deriv f x) / (2 * sqrt (f x)) :=
(hf.has_deriv_at.sqrt hx).deriv

end deriv

section fderiv

variables {E : Type*} [normed_add_comm_group E] [normed_space ℝ E] {f : E → ℝ} {n : ℕ∞}
  {s : set E} {x : E} {f' : E →L[ℝ] ℝ}

lemma has_fderiv_at.sqrt (hf : has_fderiv_at f f' x) (hx : f x ≠ 0) :
  has_fderiv_at (λ y, sqrt (f y)) ((1 / (2 * sqrt (f x))) • f') x :=
(has_deriv_at_sqrt hx).comp_has_fderiv_at x hf

lemma has_strict_fderiv_at.sqrt (hf : has_strict_fderiv_at f f' x) (hx : f x ≠ 0) :
  has_strict_fderiv_at (λ y, sqrt (f y)) ((1 / (2 * sqrt (f x))) • f') x :=
(has_strict_deriv_at_sqrt hx).comp_has_strict_fderiv_at x hf

lemma has_fderiv_within_at.sqrt (hf : has_fderiv_within_at f f' s x) (hx : f x ≠ 0) :
  has_fderiv_within_at (λ y, sqrt (f y)) ((1 / (2 * sqrt (f x))) • f') s x :=
(has_deriv_at_sqrt hx).comp_has_fderiv_within_at x hf

lemma differentiable_within_at.sqrt (hf : differentiable_within_at ℝ f s x) (hx : f x ≠ 0) :
  differentiable_within_at ℝ (λ y, sqrt (f y)) s x :=
(hf.has_fderiv_within_at.sqrt hx).differentiable_within_at

lemma differentiable_at.sqrt (hf : differentiable_at ℝ f x) (hx : f x ≠ 0) :
  differentiable_at ℝ (λ y, sqrt (f y)) x :=
(hf.has_fderiv_at.sqrt hx).differentiable_at

lemma differentiable_on.sqrt (hf : differentiable_on ℝ f s) (hs : ∀ x ∈ s, f x ≠ 0) :
  differentiable_on ℝ (λ y, sqrt (f y)) s :=
λ x hx, (hf x hx).sqrt (hs x hx)

lemma differentiable.sqrt (hf : differentiable ℝ f) (hs : ∀ x, f x ≠ 0) :
  differentiable ℝ (λ y, sqrt (f y)) :=
λ x, (hf x).sqrt (hs x)

lemma fderiv_within_sqrt (hf : differentiable_within_at ℝ f s x) (hx : f x ≠ 0)
  (hxs : unique_diff_within_at ℝ s x) :
  fderiv_within ℝ (λx, sqrt (f x)) s x = (1 / (2 * sqrt (f x))) • fderiv_within ℝ f s x :=
(hf.has_fderiv_within_at.sqrt hx).fderiv_within hxs

@[simp] lemma fderiv_sqrt (hf : differentiable_at ℝ f x) (hx : f x ≠ 0) :
  fderiv ℝ (λx, sqrt (f x)) x = (1 / (2 * sqrt (f x))) • fderiv ℝ f x :=
(hf.has_fderiv_at.sqrt hx).fderiv

lemma cont_diff_at.sqrt (hf : cont_diff_at ℝ n f x) (hx : f x ≠ 0) :
  cont_diff_at ℝ n (λ y, sqrt (f y)) x :=
(cont_diff_at_sqrt hx).comp x hf

lemma cont_diff_within_at.sqrt (hf : cont_diff_within_at ℝ n f s x) (hx : f x ≠ 0) :
  cont_diff_within_at ℝ n (λ y, sqrt (f y)) s x :=
(cont_diff_at_sqrt hx).comp_cont_diff_within_at x hf

lemma cont_diff_on.sqrt (hf : cont_diff_on ℝ n f s) (hs : ∀ x ∈ s, f x ≠ 0) :
  cont_diff_on ℝ n (λ y, sqrt (f y)) s :=
λ x hx, (hf x hx).sqrt (hs x hx)

lemma cont_diff.sqrt (hf : cont_diff ℝ n f) (h : ∀ x, f x ≠ 0) :
  cont_diff ℝ n (λ y, sqrt (f y)) :=
cont_diff_iff_cont_diff_at.2 $ λ x, (hf.cont_diff_at.sqrt (h x))

end fderiv