[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
ha : IsLeast {g | g ∈ H ∧ 0 < g} a
⊢ H = closure {a}
[PROOFSTEP]
obtain ⟨⟨a_in, a_pos⟩, a_min⟩ := ha
[GOAL]
case intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
⊢ H = closure {a}
[PROOFSTEP]
refine' le_antisymm _ (H.closure_le.mpr <| by simp [a_in])
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
⊢ {a} ⊆ ↑H
[PROOFSTEP]
simp [a_in]
[GOAL]
case intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
⊢ H ≤ closure {a}
[PROOFSTEP]
intro g g_in
[GOAL]
case intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
g : G
g_in : g ∈ H
⊢ g ∈ closure {a}
[PROOFSTEP]
obtain ⟨k, ⟨nonneg, lt⟩, _⟩ := existsUnique_zsmul_near_of_pos' a_pos g
[GOAL]
case intro.intro.intro.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
g : G
g_in : g ∈ H
k : ℤ
right✝ : ∀ (y : ℤ), (fun k => 0 ≤ g - k • a ∧ g - k • a < a) y → y = k
nonneg : 0 ≤ g - k • a
lt : g - k • a < a
⊢ g ∈ closure {a}
[PROOFSTEP]
have h_zero : g - k • a = 0 := by
  by_contra h
  have h : a ≤ g - k • a := by
    refine' a_min ⟨_, _⟩
    · exact AddSubgroup.sub_mem H g_in (AddSubgroup.zsmul_mem H a_in k)
    · exact lt_of_le_of_ne nonneg (Ne.symm h)
  have h' : ¬a ≤ g - k • a := not_le.mpr lt
  contradiction
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
g : G
g_in : g ∈ H
k : ℤ
right✝ : ∀ (y : ℤ), (fun k => 0 ≤ g - k • a ∧ g - k • a < a) y → y = k
nonneg : 0 ≤ g - k • a
lt : g - k • a < a
⊢ g - k • a = 0
[PROOFSTEP]
by_contra h
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
g : G
g_in : g ∈ H
k : ℤ
right✝ : ∀ (y : ℤ), (fun k => 0 ≤ g - k • a ∧ g - k • a < a) y → y = k
nonneg : 0 ≤ g - k • a
lt : g - k • a < a
h : ¬g - k • a = 0
⊢ False
[PROOFSTEP]
have h : a ≤ g - k • a := by
  refine' a_min ⟨_, _⟩
  · exact AddSubgroup.sub_mem H g_in (AddSubgroup.zsmul_mem H a_in k)
  · exact lt_of_le_of_ne nonneg (Ne.symm h)
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
g : G
g_in : g ∈ H
k : ℤ
right✝ : ∀ (y : ℤ), (fun k => 0 ≤ g - k • a ∧ g - k • a < a) y → y = k
nonneg : 0 ≤ g - k • a
lt : g - k • a < a
h : ¬g - k • a = 0
⊢ a ≤ g - k • a
[PROOFSTEP]
refine' a_min ⟨_, _⟩
[GOAL]
case refine'_1
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
g : G
g_in : g ∈ H
k : ℤ
right✝ : ∀ (y : ℤ), (fun k => 0 ≤ g - k • a ∧ g - k • a < a) y → y = k
nonneg : 0 ≤ g - k • a
lt : g - k • a < a
h : ¬g - k • a = 0
⊢ g - k • a ∈ H
[PROOFSTEP]
exact AddSubgroup.sub_mem H g_in (AddSubgroup.zsmul_mem H a_in k)
[GOAL]
case refine'_2
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
g : G
g_in : g ∈ H
k : ℤ
right✝ : ∀ (y : ℤ), (fun k => 0 ≤ g - k • a ∧ g - k • a < a) y → y = k
nonneg : 0 ≤ g - k • a
lt : g - k • a < a
h : ¬g - k • a = 0
⊢ 0 < g - k • a
[PROOFSTEP]
exact lt_of_le_of_ne nonneg (Ne.symm h)
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
g : G
g_in : g ∈ H
k : ℤ
right✝ : ∀ (y : ℤ), (fun k => 0 ≤ g - k • a ∧ g - k • a < a) y → y = k
nonneg : 0 ≤ g - k • a
lt : g - k • a < a
h✝ : ¬g - k • a = 0
h : a ≤ g - k • a
⊢ False
[PROOFSTEP]
have h' : ¬a ≤ g - k • a := not_le.mpr lt
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
g : G
g_in : g ∈ H
k : ℤ
right✝ : ∀ (y : ℤ), (fun k => 0 ≤ g - k • a ∧ g - k • a < a) y → y = k
nonneg : 0 ≤ g - k • a
lt : g - k • a < a
h✝ : ¬g - k • a = 0
h : a ≤ g - k • a
h' : ¬a ≤ g - k • a
⊢ False
[PROOFSTEP]
contradiction
[GOAL]
case intro.intro.intro.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
a_min : a ∈ lowerBounds {g | g ∈ H ∧ 0 < g}
a_in : a ∈ H
a_pos : 0 < a
g : G
g_in : g ∈ H
k : ℤ
right✝ : ∀ (y : ℤ), (fun k => 0 ≤ g - k • a ∧ g - k • a < a) y → y = k
nonneg : 0 ≤ g - k • a
lt : g - k • a < a
h_zero : g - k • a = 0
⊢ g ∈ closure {a}
[PROOFSTEP]
simp [sub_eq_zero.mp h_zero, AddSubgroup.mem_closure_singleton]
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
⊢ ∃ b, IsLeast {g | g ∈ H ∧ 0 < g} b
[PROOFSTEP]
have hex : ∀ g > 0, ∃ n : ℕ, g ∈ Ioc (n • a) ((n + 1) • a) := fun g hg =>
  by
  rcases existsUnique_add_zsmul_mem_Ico h₀ 0 (g - a) with ⟨m, ⟨hm, hm'⟩, -⟩
  simp only [zero_add, sub_le_iff_le_add, sub_add_cancel, ← add_one_zsmul] at hm hm'
  lift m to ℕ
  · rw [← Int.lt_add_one_iff, ← zsmul_lt_zsmul_iff h₀, zero_zsmul]
    exact hg.trans_le hm
  · simp only [← Nat.cast_succ, coe_nat_zsmul] at hm hm'
    exact ⟨m, hm', hm⟩
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
g : G
hg : g > 0
⊢ ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
[PROOFSTEP]
rcases existsUnique_add_zsmul_mem_Ico h₀ 0 (g - a) with ⟨m, ⟨hm, hm'⟩, -⟩
[GOAL]
case intro.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
g : G
hg : g > 0
m : ℤ
hm : g - a ≤ 0 + m • a
hm' : 0 + m • a < g - a + a
⊢ ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
[PROOFSTEP]
simp only [zero_add, sub_le_iff_le_add, sub_add_cancel, ← add_one_zsmul] at hm hm'
[GOAL]
case intro.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
g : G
hg : g > 0
m : ℤ
hm : g ≤ (m + 1) • a
hm' : m • a < g
⊢ ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
[PROOFSTEP]
lift m to ℕ
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
g : G
hg : g > 0
m : ℤ
hm : g ≤ (m + 1) • a
hm' : m • a < g
⊢ 0 ≤ m
[PROOFSTEP]
rw [← Int.lt_add_one_iff, ← zsmul_lt_zsmul_iff h₀, zero_zsmul]
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
g : G
hg : g > 0
m : ℤ
hm : g ≤ (m + 1) • a
hm' : m • a < g
⊢ 0 < (m + 1) • a
[PROOFSTEP]
exact hg.trans_le hm
[GOAL]
case intro.intro.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
g : G
hg : g > 0
m : ℕ
hm : g ≤ (↑m + 1) • a
hm' : ↑m • a < g
⊢ ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
[PROOFSTEP]
simp only [← Nat.cast_succ, coe_nat_zsmul] at hm hm'
[GOAL]
case intro.intro.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
g : G
hg : g > 0
m : ℕ
hm : g ≤ Nat.succ m • a
hm' : m • a < g
⊢ ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
[PROOFSTEP]
exact ⟨m, hm', hm⟩
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
⊢ ∃ b, IsLeast {g | g ∈ H ∧ 0 < g} b
[PROOFSTEP]
have : ∃ n : ℕ, Set.Nonempty (H ∩ Ioc (n • a) ((n + 1) • a))
[GOAL]
case this
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
⊢ ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
[PROOFSTEP]
rcases(bot_or_exists_ne_zero H).resolve_left hbot with ⟨g, hgH, hg₀⟩
[GOAL]
case this.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
g : G
hgH : g ∈ H
hg₀ : g ≠ 0
⊢ ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
[PROOFSTEP]
rcases hex |g| (abs_pos.2 hg₀) with ⟨n, hn⟩
[GOAL]
case this.intro.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
g : G
hgH : g ∈ H
hg₀ : g ≠ 0
n : ℕ
hn : |g| ∈ Ioc (n • a) ((n + 1) • a)
⊢ ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
[PROOFSTEP]
exact ⟨n, _, (@abs_mem_iff (AddSubgroup G) G _ _).2 hgH, hn⟩
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
this : ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
⊢ ∃ b, IsLeast {g | g ∈ H ∧ 0 < g} b
[PROOFSTEP]
classical rcases Nat.findX this with ⟨n, ⟨x, hxH, hnx, hxn⟩, hmin⟩
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
this : ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
⊢ ∃ b, IsLeast {g | g ∈ H ∧ 0 < g} b
[PROOFSTEP]
rcases Nat.findX this with ⟨n, ⟨x, hxH, hnx, hxn⟩, hmin⟩
[GOAL]
case mk.intro.intro.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
this : ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
n : ℕ
hmin : ∀ (m : ℕ), m < n → ¬Set.Nonempty (↑H ∩ Ioc (m • a) ((m + 1) • a))
x : G
hxH : x ∈ ↑H
hnx : n • a < x
hxn : x ≤ (n + 1) • a
⊢ ∃ b, IsLeast {g | g ∈ H ∧ 0 < g} b
[PROOFSTEP]
by_contra hxmin
[GOAL]
case mk.intro.intro.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
this : ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
n : ℕ
hmin : ∀ (m : ℕ), m < n → ¬Set.Nonempty (↑H ∩ Ioc (m • a) ((m + 1) • a))
x : G
hxH : x ∈ ↑H
hnx : n • a < x
hxn : x ≤ (n + 1) • a
hxmin : ¬∃ b, IsLeast {g | g ∈ H ∧ 0 < g} b
⊢ False
[PROOFSTEP]
simp only [IsLeast, not_and, mem_setOf_eq, mem_lowerBounds, not_exists, not_forall, not_le] at hxmin
[GOAL]
case mk.intro.intro.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
this : ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
n : ℕ
hmin : ∀ (m : ℕ), m < n → ¬Set.Nonempty (↑H ∩ Ioc (m • a) ((m + 1) • a))
x : G
hxH : x ∈ ↑H
hnx : n • a < x
hxn : x ≤ (n + 1) • a
hxmin : ∀ (x : G), x ∈ H ∧ 0 < x → ∃ x_1 h, x_1 < x
⊢ False
[PROOFSTEP]
rcases hxmin x ⟨hxH, (nsmul_nonneg h₀.le _).trans_lt hnx⟩ with ⟨y, ⟨hyH, hy₀⟩, hxy⟩
[GOAL]
case mk.intro.intro.intro.intro.intro.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
this : ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
n : ℕ
hmin : ∀ (m : ℕ), m < n → ¬Set.Nonempty (↑H ∩ Ioc (m • a) ((m + 1) • a))
x : G
hxH : x ∈ ↑H
hnx : n • a < x
hxn : x ≤ (n + 1) • a
hxmin : ∀ (x : G), x ∈ H ∧ 0 < x → ∃ x_1 h, x_1 < x
y : G
hxy : y < x
hyH : y ∈ H
hy₀ : 0 < y
⊢ False
[PROOFSTEP]
rcases hex y hy₀ with ⟨m, hm⟩
[GOAL]
case mk.intro.intro.intro.intro.intro.intro.intro.intro
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
this : ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
n : ℕ
hmin : ∀ (m : ℕ), m < n → ¬Set.Nonempty (↑H ∩ Ioc (m • a) ((m + 1) • a))
x : G
hxH : x ∈ ↑H
hnx : n • a < x
hxn : x ≤ (n + 1) • a
hxmin : ∀ (x : G), x ∈ H ∧ 0 < x → ∃ x_1 h, x_1 < x
y : G
hxy : y < x
hyH : y ∈ H
hy₀ : 0 < y
m : ℕ
hm : y ∈ Ioc (m • a) ((m + 1) • a)
⊢ False
[PROOFSTEP]
cases' lt_or_le m n with hmn hnm
[GOAL]
case mk.intro.intro.intro.intro.intro.intro.intro.intro.inl
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
this : ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
n : ℕ
hmin : ∀ (m : ℕ), m < n → ¬Set.Nonempty (↑H ∩ Ioc (m • a) ((m + 1) • a))
x : G
hxH : x ∈ ↑H
hnx : n • a < x
hxn : x ≤ (n + 1) • a
hxmin : ∀ (x : G), x ∈ H ∧ 0 < x → ∃ x_1 h, x_1 < x
y : G
hxy : y < x
hyH : y ∈ H
hy₀ : 0 < y
m : ℕ
hm : y ∈ Ioc (m • a) ((m + 1) • a)
hmn : m < n
⊢ False
[PROOFSTEP]
exact hmin m hmn ⟨y, hyH, hm⟩
[GOAL]
case mk.intro.intro.intro.intro.intro.intro.intro.intro.inr
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
this : ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
n : ℕ
hmin : ∀ (m : ℕ), m < n → ¬Set.Nonempty (↑H ∩ Ioc (m • a) ((m + 1) • a))
x : G
hxH : x ∈ ↑H
hnx : n • a < x
hxn : x ≤ (n + 1) • a
hxmin : ∀ (x : G), x ∈ H ∧ 0 < x → ∃ x_1 h, x_1 < x
y : G
hxy : y < x
hyH : y ∈ H
hy₀ : 0 < y
m : ℕ
hm : y ∈ Ioc (m • a) ((m + 1) • a)
hnm : n ≤ m
⊢ False
[PROOFSTEP]
refine disjoint_left.1 hd (sub_mem hxH hyH) ⟨sub_pos.2 hxy, sub_lt_iff_lt_add'.2 ?_⟩
[GOAL]
case mk.intro.intro.intro.intro.intro.intro.intro.intro.inr
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
hbot : H ≠ ⊥
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hex : ∀ (g : G), g > 0 → ∃ n, g ∈ Ioc (n • a) ((n + 1) • a)
this : ∃ n, Set.Nonempty (↑H ∩ Ioc (n • a) ((n + 1) • a))
n : ℕ
hmin : ∀ (m : ℕ), m < n → ¬Set.Nonempty (↑H ∩ Ioc (m • a) ((m + 1) • a))
x : G
hxH : x ∈ ↑H
hnx : n • a < x
hxn : x ≤ (n + 1) • a
hxmin : ∀ (x : G), x ∈ H ∧ 0 < x → ∃ x_1 h, x_1 < x
y : G
hxy : y < x
hyH : y ∈ H
hy₀ : 0 < y
m : ℕ
hm : y ∈ Ioc (m • a) ((m + 1) • a)
hnm : n ≤ m
⊢ x < y + a
[PROOFSTEP]
calc
  x ≤ (n + 1) • a := hxn
  _ ≤ (m + 1) • a := (nsmul_le_nsmul h₀.le (add_le_add_right hnm _))
  _ = m • a + a := (succ_nsmul' _ _)
  _ < y + a := add_lt_add_right hm.1 _
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
⊢ ∃ b, H = closure {b}
[PROOFSTEP]
rcases eq_or_ne H ⊥ with rfl | hbot
[GOAL]
case inl
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
a : G
h₀ : 0 < a
hd : Disjoint (↑⊥) (Ioo 0 a)
⊢ ∃ b, ⊥ = closure {b}
[PROOFSTEP]
exact ⟨0, closure_singleton_zero.symm⟩
[GOAL]
case inr
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup G
a : G
h₀ : 0 < a
hd : Disjoint (↑H) (Ioo 0 a)
hbot : H ≠ ⊥
⊢ ∃ b, H = closure {b}
[PROOFSTEP]
exact (exists_isLeast_pos hbot h₀ hd).imp fun _ => cyclic_of_min
[GOAL]
G : Type u_1
inst✝¹ : LinearOrderedAddCommGroup G
inst✝ : Archimedean G
H : AddSubgroup ℤ
this : Ioo 0 1 = ∅
⊢ Disjoint (↑H) (Ioo 0 1)
[PROOFSTEP]
simp [this]


[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
⊢ Irreducible (factor f)
[PROOFSTEP]
rw [factor]
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
⊢ Irreducible (if H : ∃ g, Irreducible g ∧ g ∣ f then Classical.choose H else X)
[PROOFSTEP]
split_ifs with H
[GOAL]
case pos
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
H : ∃ g, Irreducible g ∧ g ∣ f
⊢ Irreducible (Classical.choose H)
[PROOFSTEP]
exact (Classical.choose_spec H).1
[GOAL]
case neg
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
H : ¬∃ g, Irreducible g ∧ g ∣ f
⊢ Irreducible X
[PROOFSTEP]
exact irreducible_X
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf1 : ¬IsUnit f
⊢ factor f ∣ f
[PROOFSTEP]
by_cases hf2 : f = 0
[GOAL]
case pos
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf1 : ¬IsUnit f
hf2 : f = 0
⊢ factor f ∣ f
[PROOFSTEP]
rw [hf2]
[GOAL]
case pos
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf1 : ¬IsUnit f
hf2 : f = 0
⊢ factor 0 ∣ 0
[PROOFSTEP]
exact dvd_zero _
[GOAL]
case neg
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf1 : ¬IsUnit f
hf2 : ¬f = 0
⊢ factor f ∣ f
[PROOFSTEP]
rw [factor, dif_pos (WfDvdMonoid.exists_irreducible_factor hf1 hf2)]
[GOAL]
case neg
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf1 : ¬IsUnit f
hf2 : ¬f = 0
⊢ Classical.choose (_ : ∃ i, Irreducible i ∧ i ∣ f) ∣ f
[PROOFSTEP]
exact (Classical.choose_spec <| WfDvdMonoid.exists_irreducible_factor hf1 hf2).2
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf : natDegree f ≠ 0
⊢ (X - ↑C (AdjoinRoot.root (factor f))) * removeFactor f = map (AdjoinRoot.of (factor f)) f
[PROOFSTEP]
let ⟨g, hg⟩ := factor_dvd_of_natDegree_ne_zero hf
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf : natDegree f ≠ 0
g : K[X]
hg : f = factor f * g
⊢ (X - ↑C (AdjoinRoot.root (factor f))) * removeFactor f = map (AdjoinRoot.of (factor f)) f
[PROOFSTEP]
apply (mul_divByMonic_eq_iff_isRoot (R := AdjoinRoot f.factor) (a := AdjoinRoot.root f.factor)).mpr
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf : natDegree f ≠ 0
g : K[X]
hg : f = factor f * g
⊢ IsRoot (map (AdjoinRoot.of (factor f)) f) (AdjoinRoot.root (factor f))
[PROOFSTEP]
rw [IsRoot.def, eval_map, hg, eval₂_mul, ← hg, AdjoinRoot.eval₂_root, zero_mul]
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
⊢ natDegree (removeFactor f) = natDegree f - 1
[PROOFSTEP]
rw [removeFactor, natDegree_divByMonic (map (AdjoinRoot.of f.factor) f) (monic_X_sub_C _), natDegree_map,
  natDegree_X_sub_C]
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
n : ℕ
hfn : natDegree f = n + 1
⊢ natDegree (removeFactor f) = n
[PROOFSTEP]
rw [natDegree_removeFactor, hfn, n.add_sub_cancel]
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]), natDegree f = n → Splits (algebraMap K (SplittingFieldAux n f)) f)
    n
K : Type u
x✝ : Field K
f : K[X]
hf : natDegree f = Nat.succ n
⊢ Splits (algebraMap K (SplittingFieldAux (Nat.succ n) f)) f
[PROOFSTEP]
rw [← splits_id_iff_splits, algebraMap_succ, ← map_map, splits_id_iff_splits, ←
  X_sub_C_mul_removeFactor f fun h => by rw [h] at hf ; cases hf]
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]), natDegree f = n → Splits (algebraMap K (SplittingFieldAux n f)) f)
    n
K : Type u
x✝ : Field K
f : K[X]
hf : natDegree f = Nat.succ n
h : natDegree f = 0
⊢ False
[PROOFSTEP]
rw [h] at hf
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]), natDegree f = n → Splits (algebraMap K (SplittingFieldAux n f)) f)
    n
K : Type u
x✝ : Field K
f : K[X]
hf : 0 = Nat.succ n
h : natDegree f = 0
⊢ False
[PROOFSTEP]
cases hf
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]), natDegree f = n → Splits (algebraMap K (SplittingFieldAux n f)) f)
    n
K : Type u
x✝ : Field K
f : K[X]
hf : natDegree f = Nat.succ n
⊢ Splits (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f)))
    ((X - ↑C (AdjoinRoot.root (factor f))) * removeFactor f)
[PROOFSTEP]
exact splits_mul _ (splits_X_sub_C _) (ih _ (natDegree_removeFactor' hf))
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
⊢ Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux (Nat.succ n) f)) f))) = ⊤
[PROOFSTEP]
have hndf : f.natDegree ≠ 0 := by intro h; rw [h] at hfn ; cases hfn
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
⊢ natDegree f ≠ 0
[PROOFSTEP]
intro h
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
h : natDegree f = 0
⊢ False
[PROOFSTEP]
rw [h] at hfn
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : 0 = Nat.succ n
h : natDegree f = 0
⊢ False
[PROOFSTEP]
cases hfn
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
hndf : natDegree f ≠ 0
⊢ Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux (Nat.succ n) f)) f))) = ⊤
[PROOFSTEP]
have hfn0 : f ≠ 0 := by intro h; rw [h] at hndf ; exact hndf rfl
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
hndf : natDegree f ≠ 0
⊢ f ≠ 0
[PROOFSTEP]
intro h
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
hndf : natDegree f ≠ 0
h : f = 0
⊢ False
[PROOFSTEP]
rw [h] at hndf
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
hndf : natDegree 0 ≠ 0
h : f = 0
⊢ False
[PROOFSTEP]
exact hndf rfl
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
hndf : natDegree f ≠ 0
hfn0 : f ≠ 0
⊢ Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux (Nat.succ n) f)) f))) = ⊤
[PROOFSTEP]
have hmf0 : map (algebraMap K (SplittingFieldAux n.succ f)) f ≠ 0 := map_ne_zero hfn0
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
hndf : natDegree f ≠ 0
hfn0 : f ≠ 0
hmf0 : map (algebraMap K (SplittingFieldAux (Nat.succ n) f)) f ≠ 0
⊢ Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux (Nat.succ n) f)) f))) = ⊤
[PROOFSTEP]
rw [algebraMap_succ, ← map_map, ← X_sub_C_mul_removeFactor _ hndf, Polynomial.map_mul] at hmf0 ⊢
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
hndf : natDegree f ≠ 0
hfn0 : f ≠ 0
hmf0 :
  map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f)))
        (X - ↑C (AdjoinRoot.root (factor f))) *
      map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) (removeFactor f) ≠
    0
⊢ Algebra.adjoin K
      ↑(Multiset.toFinset
          (roots
            (map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f)))
                (X - ↑C (AdjoinRoot.root (factor f))) *
              map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) (removeFactor f)))) =
    ⊤
[PROOFSTEP]
rw [roots_mul hmf0, Polynomial.map_sub, map_X, map_C, roots_X_sub_C, Multiset.toFinset_add, Finset.coe_union,
  Multiset.toFinset_singleton, Finset.coe_singleton, Algebra.adjoin_union_eq_adjoin_adjoin, ← Set.image_singleton,
  Algebra.adjoin_algebraMap K (AdjoinRoot f.factor) (SplittingFieldAux n f.removeFactor), AdjoinRoot.adjoinRoot_eq_top,
  Algebra.map_top]
  /- Porting note: was `rw [IsScalarTower.adjoin_range_toAlgHom K (AdjoinRoot f.factor)
          (SplittingFieldAux n f.removeFactor)]` -/
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
hndf : natDegree f ≠ 0
hfn0 : f ≠ 0
hmf0 :
  map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f)))
        (X - ↑C (AdjoinRoot.root (factor f))) *
      map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) (removeFactor f) ≠
    0
⊢ Subalgebra.restrictScalars K
      (Algebra.adjoin
        { x //
          x ∈ AlgHom.range (IsScalarTower.toAlgHom K (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) }
        ↑(Multiset.toFinset
            (roots
              (map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) (removeFactor f))))) =
    ⊤
[PROOFSTEP]
have :=
  IsScalarTower.adjoin_range_toAlgHom K (AdjoinRoot f.factor) (SplittingFieldAux n f.removeFactor)
    (↑(f.removeFactor.map <| algebraMap (AdjoinRoot f.factor) <| SplittingFieldAux n f.removeFactor).roots.toFinset :
      Set (SplittingFieldAux n f.removeFactor))
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
hndf : natDegree f ≠ 0
hfn0 : f ≠ 0
hmf0 :
  map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f)))
        (X - ↑C (AdjoinRoot.root (factor f))) *
      map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) (removeFactor f) ≠
    0
this :
  Subalgebra.restrictScalars K
      (Algebra.adjoin
        { x //
          x ∈ AlgHom.range (IsScalarTower.toAlgHom K (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) }
        ↑(Multiset.toFinset
            (roots
              (map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) (removeFactor f))))) =
    Subalgebra.restrictScalars K
      (Algebra.adjoin (AdjoinRoot (factor f))
        ↑(Multiset.toFinset
            (roots (map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) (removeFactor f)))))
⊢ Subalgebra.restrictScalars K
      (Algebra.adjoin
        { x //
          x ∈ AlgHom.range (IsScalarTower.toAlgHom K (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) }
        ↑(Multiset.toFinset
            (roots
              (map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) (removeFactor f))))) =
    ⊤
[PROOFSTEP]
refine this.trans ?_
[GOAL]
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n →
          Algebra.adjoin K ↑(Multiset.toFinset (roots (map (algebraMap K (SplittingFieldAux n f)) f))) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
hndf : natDegree f ≠ 0
hfn0 : f ≠ 0
hmf0 :
  map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f)))
        (X - ↑C (AdjoinRoot.root (factor f))) *
      map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) (removeFactor f) ≠
    0
this :
  Subalgebra.restrictScalars K
      (Algebra.adjoin
        { x //
          x ∈ AlgHom.range (IsScalarTower.toAlgHom K (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) }
        ↑(Multiset.toFinset
            (roots
              (map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) (removeFactor f))))) =
    Subalgebra.restrictScalars K
      (Algebra.adjoin (AdjoinRoot (factor f))
        ↑(Multiset.toFinset
            (roots (map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) (removeFactor f)))))
⊢ Subalgebra.restrictScalars K
      (Algebra.adjoin (AdjoinRoot (factor f))
        ↑(Multiset.toFinset
            (roots
              (map (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f))) (removeFactor f))))) =
    ⊤
[PROOFSTEP]
rw [ih _ (natDegree_removeFactor' hfn), Subalgebra.restrictScalars_top]
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
⊢ Function.Surjective ↑(ofMvPolynomial f)
[PROOFSTEP]
suffices AlgHom.range (ofMvPolynomial f) = ⊤ by rw [← Set.range_iff_surjective]; rwa [SetLike.ext'_iff] at this
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
this : AlgHom.range (ofMvPolynomial f) = ⊤
⊢ Function.Surjective ↑(ofMvPolynomial f)
[PROOFSTEP]
rw [← Set.range_iff_surjective]
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
this : AlgHom.range (ofMvPolynomial f) = ⊤
⊢ Set.range ↑(ofMvPolynomial f) = Set.univ
[PROOFSTEP]
rwa [SetLike.ext'_iff] at this
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
⊢ AlgHom.range (ofMvPolynomial f) = ⊤
[PROOFSTEP]
rw [ofMvPolynomial, ← Algebra.adjoin_range_eq_range_aeval K, eq_top_iff, ← adjoin_rootSet _ _ rfl]
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
⊢ Algebra.adjoin K (rootSet f (SplittingFieldAux (natDegree f) f)) ≤ Algebra.adjoin K (Set.range fun i => ↑i)
[PROOFSTEP]
apply Algebra.adjoin_le
[GOAL]
case H
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
⊢ rootSet f (SplittingFieldAux (natDegree f) f) ⊆ ↑(Algebra.adjoin K (Set.range fun i => ↑i))
[PROOFSTEP]
intro α hα
[GOAL]
case H
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
α : SplittingFieldAux (natDegree f) f
hα : α ∈ rootSet f (SplittingFieldAux (natDegree f) f)
⊢ α ∈ ↑(Algebra.adjoin K (Set.range fun i => ↑i))
[PROOFSTEP]
apply Algebra.subset_adjoin
[GOAL]
case H.a
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
α : SplittingFieldAux (natDegree f) f
hα : α ∈ rootSet f (SplittingFieldAux (natDegree f) f)
⊢ α ∈ Set.range fun i => ↑i
[PROOFSTEP]
exact ⟨⟨α, hα⟩, rfl⟩
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : SplittingField f
w : a ≠ 0
⊢ a * a⁻¹ = 1
[PROOFSTEP]
apply_fun e
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : SplittingField f
w : a ≠ 0
⊢ ↑e (a * a⁻¹) = ↑e 1
[PROOFSTEP]
have : e a ≠ 0 := fun w' => by
  apply w
  simp at w'
  exact w'
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : SplittingField f
w : a ≠ 0
w' : ↑e a = 0
⊢ False
[PROOFSTEP]
apply w
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : SplittingField f
w : a ≠ 0
w' : ↑e a = 0
⊢ a = 0
[PROOFSTEP]
simp at w'
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : SplittingField f
w : a ≠ 0
w' : a = 0
⊢ a = 0
[PROOFSTEP]
exact w'
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : SplittingField f
w : a ≠ 0
this : ↑e a ≠ 0
⊢ ↑e (a * a⁻¹) = ↑e 1
[PROOFSTEP]
simp only [map_mul, AlgEquiv.apply_symm_apply, ne_eq, AddEquivClass.map_eq_zero_iff, map_one]
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : SplittingField f
w : a ≠ 0
this : ↑e a ≠ 0
⊢ ↑(algEquivSplittingFieldAux f) a * (↑(algEquivSplittingFieldAux f) a)⁻¹ = 1
[PROOFSTEP]
rw [mul_inv_cancel]
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : SplittingField f
w : a ≠ 0
this : ↑e a ≠ 0
⊢ ↑(algEquivSplittingFieldAux f) a ≠ 0
[PROOFSTEP]
assumption
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
⊢ 0⁻¹ = 0
[PROOFSTEP]
simp
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : ℤ
b : ℕ
h1 : b ≠ 0
h2 : Nat.coprime (Int.natAbs a) b
⊢ ↑(Rat.mk' a b) = ↑a * (↑b)⁻¹
[PROOFSTEP]
apply_fun e
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : ℤ
b : ℕ
h1 : b ≠ 0
h2 : Nat.coprime (Int.natAbs a) b
⊢ ↑e ↑(Rat.mk' a b) = ↑e (↑a * (↑b)⁻¹)
[PROOFSTEP]
change e (algebraMap K _ _) = _
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : ℤ
b : ℕ
h1 : b ≠ 0
h2 : Nat.coprime (Int.natAbs a) b
⊢ ↑e (↑(algebraMap K (SplittingField f)) ↑(Rat.mk' a b)) = ↑e (↑a * (↑b)⁻¹)
[PROOFSTEP]
simp only [map_ratCast, map_natCast, map_mul, map_intCast, AlgEquiv.commutes, AlgEquiv.apply_symm_apply]
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : ℤ
b : ℕ
h1 : b ≠ 0
h2 : Nat.coprime (Int.natAbs a) b
⊢ ↑(Rat.mk' a b) = ↑a * (↑b)⁻¹
[PROOFSTEP]
apply Field.ratCast_mk
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : ℚ
x : SplittingField f
p : MvPolynomial (↑(rootSet f (SplittingFieldAux (natDegree f) f))) K
⊢ (fun x x_1 => x • x_1) a p =
    (fun x x_1 => x * x_1) (↑(algebraMap K (MvPolynomial (↑(rootSet f (SplittingFieldAux (natDegree f) f))) K)) ↑a) p
[PROOFSTEP]
ext
[GOAL]
case a
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
e : SplittingField f ≃ₐ[K] SplittingFieldAux (natDegree f) f := algEquivSplittingFieldAux f
a : ℚ
x : SplittingField f
p : MvPolynomial (↑(rootSet f (SplittingFieldAux (natDegree f) f))) K
m✝ : ↑(rootSet f (SplittingFieldAux (natDegree f) f)) →₀ ℕ
⊢ MvPolynomial.coeff m✝ ((fun x x_1 => x • x_1) a p) =
    MvPolynomial.coeff m✝
      ((fun x x_1 => x * x_1) (↑(algebraMap K (MvPolynomial (↑(rootSet f (SplittingFieldAux (natDegree f) f))) K)) ↑a)
        p)
[PROOFSTEP]
simp [MvPolynomial.algebraMap_eq, Rat.smul_def]
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
inst✝¹ : Algebra K L
f : K[X]
inst✝ : IsSplittingField K L f
⊢ L ≃ₐ[K] SplittingField f
[PROOFSTEP]
refine'
  AlgEquiv.ofBijective (lift L f <| splits (SplittingField f) f)
    ⟨RingHom.injective (lift L f <| splits (SplittingField f) f).toRingHom, _⟩
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
inst✝¹ : Algebra K L
f : K[X]
inst✝ : IsSplittingField K L f
⊢ Function.Surjective ↑(lift L f (_ : Splits (algebraMap K (SplittingField f)) f))
[PROOFSTEP]
haveI := finiteDimensional (SplittingField f) f
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
inst✝¹ : Algebra K L
f : K[X]
inst✝ : IsSplittingField K L f
this : FiniteDimensional K (SplittingField f)
⊢ Function.Surjective ↑(lift L f (_ : Splits (algebraMap K (SplittingField f)) f))
[PROOFSTEP]
haveI := finiteDimensional L f
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
inst✝¹ : Algebra K L
f : K[X]
inst✝ : IsSplittingField K L f
this✝ : FiniteDimensional K (SplittingField f)
this : FiniteDimensional K L
⊢ Function.Surjective ↑(lift L f (_ : Splits (algebraMap K (SplittingField f)) f))
[PROOFSTEP]
have : FiniteDimensional.finrank K L = FiniteDimensional.finrank K (SplittingField f) :=
  le_antisymm
    (LinearMap.finrank_le_finrank_of_injective
      (show Function.Injective (lift L f <| splits (SplittingField f) f).toLinearMap from
        RingHom.injective (lift L f <| splits (SplittingField f) f : L →+* f.SplittingField)))
    (LinearMap.finrank_le_finrank_of_injective
      (show Function.Injective (lift (SplittingField f) f <| splits L f).toLinearMap from
        RingHom.injective (lift (SplittingField f) f <| splits L f : f.SplittingField →+* L)))
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
inst✝¹ : Algebra K L
f : K[X]
inst✝ : IsSplittingField K L f
this✝¹ : FiniteDimensional K (SplittingField f)
this✝ : FiniteDimensional K L
this : FiniteDimensional.finrank K L = FiniteDimensional.finrank K (SplittingField f)
⊢ Function.Surjective ↑(lift L f (_ : Splits (algebraMap K (SplittingField f)) f))
[PROOFSTEP]
change Function.Surjective (lift L f <| splits (SplittingField f) f).toLinearMap
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
inst✝¹ : Algebra K L
f : K[X]
inst✝ : IsSplittingField K L f
this✝¹ : FiniteDimensional K (SplittingField f)
this✝ : FiniteDimensional K L
this : FiniteDimensional.finrank K L = FiniteDimensional.finrank K (SplittingField f)
⊢ Function.Surjective ↑(AlgHom.toLinearMap (lift L f (_ : Splits (algebraMap K (SplittingField f)) f)))
[PROOFSTEP]
refine' (LinearMap.injective_iff_surjective_of_finrank_eq_finrank this).1 _
[GOAL]
F : Type u
K : Type v
L : Type w
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
inst✝¹ : Algebra K L
f : K[X]
inst✝ : IsSplittingField K L f
this✝¹ : FiniteDimensional K (SplittingField f)
this✝ : FiniteDimensional K L
this : FiniteDimensional.finrank K L = FiniteDimensional.finrank K (SplittingField f)
⊢ Function.Injective ↑(AlgHom.toLinearMap (lift L f (_ : Splits (algebraMap K (SplittingField f)) f)))
[PROOFSTEP]
exact RingHom.injective (lift L f <| splits (SplittingField f) f : L →+* f.SplittingField)


[GOAL]
α β : Type u
m : Type u → Type v
x : OptionT m α
inst✝¹ : Monad m
f : α → β
inst✝ : LawfulMonad m
⊢ run (f <$> x) = Option.map f <$> run x
[PROOFSTEP]
rw [← bind_pure_comp _ x.run]
[GOAL]
α β : Type u
m : Type u → Type v
x : OptionT m α
inst✝¹ : Monad m
f : α → β
inst✝ : LawfulMonad m
⊢ run (f <$> x) = do
    let a ← run x
    pure (Option.map f a)
[PROOFSTEP]
change
  x.run >>=
      (fun
        | some a => OptionT.run (pure (f a))
        | none => pure none) =
    _
[GOAL]
α β : Type u
m : Type u → Type v
x : OptionT m α
inst✝¹ : Monad m
f : α → β
inst✝ : LawfulMonad m
⊢ (do
      let x ← run x
      match x with
        | some a => run (pure (f a))
        | none => pure none) =
    do
    let a ← run x
    pure (Option.map f a)
[PROOFSTEP]
apply bind_congr
[GOAL]
case h
α β : Type u
m : Type u → Type v
x : OptionT m α
inst✝¹ : Monad m
f : α → β
inst✝ : LawfulMonad m
⊢ ∀ (a : Option α),
    (match a with
      | some a => run (pure (f a))
      | none => pure none) =
      pure (Option.map f a)
[PROOFSTEP]
intro a
[GOAL]
case h
α β : Type u
m : Type u → Type v
x : OptionT m α
inst✝¹ : Monad m
f : α → β
inst✝ : LawfulMonad m
a : Option α
⊢ (match a with
    | some a => run (pure (f a))
    | none => pure none) =
    pure (Option.map f a)
[PROOFSTEP]
cases a
[GOAL]
case h.none
α β : Type u
m : Type u → Type v
x : OptionT m α
inst✝¹ : Monad m
f : α → β
inst✝ : LawfulMonad m
⊢ (match none with
    | some a => run (pure (f a))
    | none => pure none) =
    pure (Option.map f none)
[PROOFSTEP]
simp [Option.map, Option.bind]
[GOAL]
case h.some
α β : Type u
m : Type u → Type v
x : OptionT m α
inst✝¹ : Monad m
f : α → β
inst✝ : LawfulMonad m
val✝ : α
⊢ (match some val✝ with
    | some a => run (pure (f a))
    | none => pure none) =
    pure (Option.map f (some val✝))
[PROOFSTEP]
simp [Option.map, Option.bind]
[GOAL]
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
⊢ ∀ {α : Type u} (x : OptionT m α), id <$> x = x
[PROOFSTEP]
intros
[GOAL]
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ : Type u
x✝ : OptionT m α✝
⊢ id <$> x✝ = x✝
[PROOFSTEP]
apply OptionT.ext
[GOAL]
case h
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ : Type u
x✝ : OptionT m α✝
⊢ OptionT.run (id <$> x✝) = OptionT.run x✝
[PROOFSTEP]
simp only [OptionT.run_map]
[GOAL]
case h
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ : Type u
x✝ : OptionT m α✝
⊢ Option.map id <$> OptionT.run x✝ = OptionT.run x✝
[PROOFSTEP]
rw [map_congr, id_map]
[GOAL]
case h
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ : Type u
x✝ : OptionT m α✝
⊢ ∀ (a : Option α✝), Option.map id a = id a
[PROOFSTEP]
intro a
[GOAL]
case h
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ : Type u
x✝ : OptionT m α✝
a : Option α✝
⊢ Option.map id a = id a
[PROOFSTEP]
cases a
[GOAL]
case h.none
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ : Type u
x✝ : OptionT m α✝
⊢ Option.map id none = id none
[PROOFSTEP]
rfl
[GOAL]
case h.some
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ : Type u
x✝ : OptionT m α✝
val✝ : α✝
⊢ Option.map id (some val✝) = id (some val✝)
[PROOFSTEP]
rfl
[GOAL]
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
⊢ ∀ {α β : Type u} (x : α) (f : α → OptionT m β), pure x >>= f = f x
[PROOFSTEP]
intros
[GOAL]
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ β✝ : Type u
x✝ : α✝
f✝ : α✝ → OptionT m β✝
⊢ pure x✝ >>= f✝ = f✝ x✝
[PROOFSTEP]
apply OptionT.ext
[GOAL]
case h
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ β✝ : Type u
x✝ : α✝
f✝ : α✝ → OptionT m β✝
⊢ OptionT.run (pure x✝ >>= f✝) = OptionT.run (f✝ x✝)
[PROOFSTEP]
simp
[GOAL]
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
⊢ ∀ {α β γ : Type u} (x : OptionT m α) (f : α → OptionT m β) (g : β → OptionT m γ),
    x >>= f >>= g = x >>= fun x => f x >>= g
[PROOFSTEP]
intros
[GOAL]
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ β✝ γ✝ : Type u
x✝ : OptionT m α✝
f✝ : α✝ → OptionT m β✝
g✝ : β✝ → OptionT m γ✝
⊢ x✝ >>= f✝ >>= g✝ = x✝ >>= fun x => f✝ x >>= g✝
[PROOFSTEP]
apply OptionT.ext
[GOAL]
case h
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ β✝ γ✝ : Type u
x✝ : OptionT m α✝
f✝ : α✝ → OptionT m β✝
g✝ : β✝ → OptionT m γ✝
⊢ OptionT.run (x✝ >>= f✝ >>= g✝) = OptionT.run (x✝ >>= fun x => f✝ x >>= g✝)
[PROOFSTEP]
simp only [OptionT.run_bind, bind_assoc]
[GOAL]
case h
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ β✝ γ✝ : Type u
x✝ : OptionT m α✝
f✝ : α✝ → OptionT m β✝
g✝ : β✝ → OptionT m γ✝
⊢ (do
      let x ← OptionT.run x✝
      let x ←
        match x with
          | some a => OptionT.run (f✝ a)
          | none => pure none
      match x with
        | some a => OptionT.run (g✝ a)
        | none => pure none) =
    do
    let x ← OptionT.run x✝
    match x with
      | some a => do
        let x ← OptionT.run (f✝ a)
        match x with
          | some a => OptionT.run (g✝ a)
          | none => pure none
      | none => pure none
[PROOFSTEP]
rw [bind_congr]
[GOAL]
case h
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ β✝ γ✝ : Type u
x✝ : OptionT m α✝
f✝ : α✝ → OptionT m β✝
g✝ : β✝ → OptionT m γ✝
⊢ ∀ (a : Option α✝),
    (do
        let x ←
          match a with
            | some a => OptionT.run (f✝ a)
            | none => pure none
        match x with
          | some a => OptionT.run (g✝ a)
          | none => pure none) =
      match a with
      | some a => do
        let x ← OptionT.run (f✝ a)
        match x with
          | some a => OptionT.run (g✝ a)
          | none => pure none
      | none => pure none
[PROOFSTEP]
intro a
[GOAL]
case h
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ β✝ γ✝ : Type u
x✝ : OptionT m α✝
f✝ : α✝ → OptionT m β✝
g✝ : β✝ → OptionT m γ✝
a : Option α✝
⊢ (do
      let x ←
        match a with
          | some a => OptionT.run (f✝ a)
          | none => pure none
      match x with
        | some a => OptionT.run (g✝ a)
        | none => pure none) =
    match a with
    | some a => do
      let x ← OptionT.run (f✝ a)
      match x with
        | some a => OptionT.run (g✝ a)
        | none => pure none
    | none => pure none
[PROOFSTEP]
cases a
[GOAL]
case h.none
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ β✝ γ✝ : Type u
x✝ : OptionT m α✝
f✝ : α✝ → OptionT m β✝
g✝ : β✝ → OptionT m γ✝
⊢ (do
      let x ←
        match none with
          | some a => OptionT.run (f✝ a)
          | none => pure none
      match x with
        | some a => OptionT.run (g✝ a)
        | none => pure none) =
    match none with
    | some a => do
      let x ← OptionT.run (f✝ a)
      match x with
        | some a => OptionT.run (g✝ a)
        | none => pure none
    | none => pure none
[PROOFSTEP]
simp
[GOAL]
case h.some
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α✝ β✝ γ✝ : Type u
x✝ : OptionT m α✝
f✝ : α✝ → OptionT m β✝
g✝ : β✝ → OptionT m γ✝
val✝ : α✝
⊢ (do
      let x ←
        match some val✝ with
          | some a => OptionT.run (f✝ a)
          | none => pure none
      match x with
        | some a => OptionT.run (g✝ a)
        | none => pure none) =
    match some val✝ with
    | some a => do
      let x ← OptionT.run (f✝ a)
      match x with
        | some a => OptionT.run (g✝ a)
        | none => pure none
    | none => pure none
[PROOFSTEP]
simp


[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ g✝ : Ultrafilter α
s t : Set α
p q : α → Prop
f : Filter α
h₁ : NeBot f
h₂ : ∀ (g : Filter α), NeBot g → g ≤ f → f ≤ g
g : Filter α
neBot'✝ : NeBot g
le_of_le✝ : ∀ (g_1 : Filter α), NeBot g_1 → g_1 ≤ g → g ≤ g_1
x✝ : ↑{ toFilter := f, neBot' := h₁, le_of_le := h₂ } = ↑{ toFilter := g, neBot' := neBot'✝, le_of_le := le_of_le✝ }
⊢ { toFilter := f, neBot' := h₁, le_of_le := h₂ } = { toFilter := g, neBot' := neBot'✝, le_of_le := le_of_le✝ }
[PROOFSTEP]
congr
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ g✝ : Ultrafilter α
s t : Set α
p q : α → Prop
f : Ultrafilter α
g : Filter α
hg : NeBot (g ⊓ ↑f)
⊢ NeBot (↑f ⊓ g)
[PROOFSTEP]
rwa [inf_comm]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ g✝ : Ultrafilter α
s t : Set α
p q : α → Prop
f : Ultrafilter α
g : Filter α
⊢ Disjoint (↑f) g ↔ ¬↑f ≤ g
[PROOFSTEP]
rw [← inf_neBot_iff, neBot_iff, Ne.def, not_not, disjoint_iff]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f g : Ultrafilter α
s t : Set α
p q : α → Prop
hsc : ¬sᶜ ∈ f
h : ↑f ⊓ 𝓟 s = ⊥
⊢ ↑f ⊓ 𝓟 sᶜᶜ = ⊥
[PROOFSTEP]
rwa [compl_compl]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f g : Ultrafilter α
s t : Set α
p q : α → Prop
⊢ sᶜ ∈ f ↔ ¬s ∈ f
[PROOFSTEP]
rw [← compl_not_mem_iff, compl_compl]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ g : Ultrafilter α
s t : Set α
p q : α → Prop
f : Filter α
h : ∀ (s : Set α), ¬sᶜ ∈ f ↔ s ∈ f
hf : f = ⊥
⊢ False
[PROOFSTEP]
simp [hf] at h
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ g✝ : Ultrafilter α
s t : Set α
p q : α → Prop
u : Ultrafilter α
f g : Filter α
⊢ ¬↑u ≤ f ⊔ g ↔ ¬(↑u ≤ f ∨ ↑u ≤ g)
[PROOFSTEP]
simp only [← disjoint_iff_not_le, not_or, disjoint_sup_right]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f g : Ultrafilter α
s t : Set α
p q : α → Prop
⊢ s ∪ t ∈ f ↔ s ∈ f ∨ t ∈ f
[PROOFSTEP]
simp only [← mem_coe, ← le_principal_iff, ← sup_principal, le_sup_iff]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f g : Ultrafilter α
s t : Set α
p q : α → Prop
⊢ (∀ᶠ (x : α) in ↑f, p x → q x) ↔ (∀ᶠ (x : α) in ↑f, p x) → ∀ᶠ (x : α) in ↑f, q x
[PROOFSTEP]
simp only [imp_iff_not_or, eventually_or, eventually_not]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f g : Ultrafilter α
s✝ t : Set α
p q : α → Prop
s : Set (Set α)
hs : Set.Finite s
⊢ ⋃₀ ∅ ∈ f ↔ ∃ t, t ∈ ∅ ∧ t ∈ f
[PROOFSTEP]
simp
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f g : Ultrafilter α
s✝¹ t : Set α
p q : α → Prop
s : Set (Set α)
hs : Set.Finite s
a✝ : Set α
s✝ : Set (Set α)
x✝¹ : ¬a✝ ∈ s✝
x✝ : Set.Finite s✝
his : ⋃₀ s✝ ∈ f ↔ ∃ t, t ∈ s✝ ∧ t ∈ f
⊢ ⋃₀ insert a✝ s✝ ∈ f ↔ ∃ t, t ∈ insert a✝ s✝ ∧ t ∈ f
[PROOFSTEP]
simp [union_mem_iff, his, or_and_right, exists_or]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f g : Ultrafilter α
s✝ t : Set α
p q : α → Prop
is : Set β
s : β → Set α
his : Set.Finite is
⊢ ⋃ (i : β) (_ : i ∈ is), s i ∈ f ↔ ∃ i, i ∈ is ∧ s i ∈ f
[PROOFSTEP]
simp only [← sUnion_image, finite_sUnion_mem_iff (his.image s), bex_image_iff]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f g✝ : Ultrafilter α
s t : Set α
p q : α → Prop
m : α → β
u : Ultrafilter β
inj : Injective m
large : range m ∈ u
g : Filter α
hg : NeBot g
hgu : g ≤ Filter.comap m ↑u
⊢ Filter.comap m ↑u ≤ g
[PROOFSTEP]
simp only [← u.unique (map_le_iff_le_comap.2 hgu), comap_map inj, le_rfl]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ g : Ultrafilter α
s t : Set α
p q : α → Prop
f : Ultrafilter α
h₀ : optParam (Injective id) (_ : Injective id)
⊢ range id ∈ f
[PROOFSTEP]
rw [range_id]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ g : Ultrafilter α
s t : Set α
p q : α → Prop
f : Ultrafilter α
h₀ : optParam (Injective id) (_ : Injective id)
⊢ univ ∈ f
[PROOFSTEP]
exact univ_mem
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ g : Ultrafilter α
s t : Set α
p q : α → Prop
f : Ultrafilter γ
m : α → β
n : β → γ
inj₀ : Injective n
large₀ : range n ∈ f
inj₁ : Injective m
large₁ : range m ∈ comap f inj₀ large₀
inj₂ : optParam (Injective (n ∘ m)) (_ : Injective (n ∘ m))
⊢ range (n ∘ m) ∈ f
[PROOFSTEP]
rw [range_comp]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ g : Ultrafilter α
s t : Set α
p q : α → Prop
f : Ultrafilter γ
m : α → β
n : β → γ
inj₀ : Injective n
large₀ : range n ∈ f
inj₁ : Injective m
large₁ : range m ∈ comap f inj₀ large₀
inj₂ : optParam (Injective (n ∘ m)) (_ : Injective (n ∘ m))
⊢ n '' range m ∈ f
[PROOFSTEP]
exact image_mem_of_mem_comap large₀ large₁
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f g : Ultrafilter α
s✝ t : Set α
p q : α → Prop
α✝ : Type ?u.19487
a : α✝
s : Set α✝
⊢ ¬sᶜ ∈ pure a ↔ s ∈ pure a
[PROOFSTEP]
simp
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f g : Ultrafilter α
s t : Set α
p q : α → Prop
m : α → β
a : α
inj : Injective m
large : range m ∈ pure (m a)
⊢ 𝓟 (m ⁻¹' {m a}) = ↑(pure a)
[PROOFSTEP]
rw [coe_pure, ← principal_singleton, ← image_singleton, preimage_image_eq _ inj]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f g : Ultrafilter α
s t : Set α
p q : α → Prop
h : Set.Finite s
h' : s ∈ f
⊢ ∃ x, x ∈ s ∧ f = pure x
[PROOFSTEP]
rw [← biUnion_of_singleton s] at h'
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f g : Ultrafilter α
s t : Set α
p q : α → Prop
h : Set.Finite s
h' : ⋃ (x : α) (_ : x ∈ s), {x} ∈ f
⊢ ∃ x, x ∈ s ∧ f = pure x
[PROOFSTEP]
rcases(Ultrafilter.finite_biUnion_mem_iff h).mp h' with ⟨a, has, haf⟩
[GOAL]
case intro.intro
α : Type u
β : Type v
γ : Type u_1
f g : Ultrafilter α
s t : Set α
p q : α → Prop
h : Set.Finite s
h' : ⋃ (x : α) (_ : x ∈ s), {x} ∈ f
a : α
has : a ∈ s
haf : {a} ∈ f
⊢ ∃ x, x ∈ s ∧ f = pure x
[PROOFSTEP]
exact ⟨a, has, eq_of_le (Filter.le_pure_iff.2 haf)⟩
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ g : Ultrafilter α
s✝ t : Set α
p q : α → Prop
f : Ultrafilter α
m : α → Ultrafilter β
s : Set β
⊢ (¬sᶜ ∈ Filter.bind ↑f fun x => ↑(m x)) ↔ s ∈ Filter.bind ↑f fun x => ↑(m x)
[PROOFSTEP]
simp only [mem_bind', mem_coe, ← compl_mem_iff_not_mem, compl_setOf, compl_compl]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f : Filter α
s : Set α
a : α
⊢ s ∈ f ↔ ∀ (g : Ultrafilter α), ↑g ≤ f → s ∈ g
[PROOFSTEP]
refine' ⟨fun hf g hg => hg hf, fun H => by_contra fun hf => _⟩
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f : Filter α
s : Set α
a : α
H : ∀ (g : Ultrafilter α), ↑g ≤ f → s ∈ g
hf : ¬s ∈ f
⊢ False
[PROOFSTEP]
set g : Filter (sᶜ : Set α) := comap (↑) f
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f : Filter α
s : Set α
a : α
H : ∀ (g : Ultrafilter α), ↑g ≤ f → s ∈ g
hf : ¬s ∈ f
g : Filter ↑sᶜ := comap Subtype.val f
⊢ False
[PROOFSTEP]
haveI : NeBot g := comap_neBot_iff_compl_range.2 (by simpa [compl_setOf])
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f : Filter α
s : Set α
a : α
H : ∀ (g : Ultrafilter α), ↑g ≤ f → s ∈ g
hf : ¬s ∈ f
g : Filter ↑sᶜ := comap Subtype.val f
⊢ ¬(range Subtype.val)ᶜ ∈ f
[PROOFSTEP]
simpa [compl_setOf]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f : Filter α
s : Set α
a : α
H : ∀ (g : Ultrafilter α), ↑g ≤ f → s ∈ g
hf : ¬s ∈ f
g : Filter ↑sᶜ := comap Subtype.val f
this : NeBot g
⊢ False
[PROOFSTEP]
simpa using H ((of g).map (↑)) (map_le_iff_le_comap.mpr (of_le g))
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ : Filter α
s : Set α
a : α
f f' : Filter α
⊢ ⨆ (g : Ultrafilter α) (_ : ↑g ≤ f), ↑g ≤ f' ↔ f ≤ f'
[PROOFSTEP]
simp only [iSup_le_iff, ← le_iff_ultrafilter]
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ : Filter α
s : Set α
a : α
f : α → β
l₁ : Filter α
l₂ : Filter β
⊢ Tendsto f l₁ l₂ ↔ ∀ (g : Ultrafilter α), ↑g ≤ l₁ → Tendsto f (↑g) l₂
[PROOFSTEP]
simpa only [tendsto_iff_comap] using le_iff_ultrafilter
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f : Filter α
s : Set α
a : α
g : Filter α
p : Filter α → Prop
hp : Monotone p
⊢ (∀ (f : Filter α), NeBot f → f ≤ g → p f) ↔ ∀ (f : Ultrafilter α), ↑f ≤ g → p ↑f
[PROOFSTEP]
refine' ⟨fun H f hf => H f f.neBot hf, _⟩
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f : Filter α
s : Set α
a : α
g : Filter α
p : Filter α → Prop
hp : Monotone p
⊢ (∀ (f : Ultrafilter α), ↑f ≤ g → p ↑f) → ∀ (f : Filter α), NeBot f → f ≤ g → p f
[PROOFSTEP]
intro H f hf hfg
[GOAL]
α : Type u
β : Type v
γ : Type u_1
f✝ : Filter α
s : Set α
a : α
g : Filter α
p : Filter α → Prop
hp : Monotone p
H : ∀ (f : Ultrafilter α), ↑f ≤ g → p ↑f
f : Filter α
hf : NeBot f
hfg : f ≤ g
⊢ p f
[PROOFSTEP]
exact hp (of_le f) (H _ ((of_le f).trans hfg))
[GOAL]
α : Type u
β : Type v
γ : Type u_1
m : α → β
s : Set α
g : Ultrafilter β
h : m '' s ∈ g
⊢ s ∈ ofComapInfPrincipal h
[PROOFSTEP]
let f := Filter.comap m g ⊓ 𝓟 s
[GOAL]
α : Type u
β : Type v
γ : Type u_1
m : α → β
s : Set α
g : Ultrafilter β
h : m '' s ∈ g
f : Filter α := Filter.comap m ↑g ⊓ 𝓟 s
⊢ s ∈ ofComapInfPrincipal h
[PROOFSTEP]
haveI : f.NeBot := comap_inf_principal_neBot_of_image_mem h
[GOAL]
α : Type u
β : Type v
γ : Type u_1
m : α → β
s : Set α
g : Ultrafilter β
h : m '' s ∈ g
f : Filter α := Filter.comap m ↑g ⊓ 𝓟 s
this : NeBot f
⊢ s ∈ ofComapInfPrincipal h
[PROOFSTEP]
have : s ∈ f := mem_inf_of_right (mem_principal_self s)
[GOAL]
α : Type u
β : Type v
γ : Type u_1
m : α → β
s : Set α
g : Ultrafilter β
h : m '' s ∈ g
f : Filter α := Filter.comap m ↑g ⊓ 𝓟 s
this✝ : NeBot f
this : s ∈ f
⊢ s ∈ ofComapInfPrincipal h
[PROOFSTEP]
exact le_def.mp (of_le _) s this
[GOAL]
α : Type u
β : Type v
γ : Type u_1
m : α → β
s : Set α
g : Ultrafilter β
h : m '' s ∈ g
⊢ map m (ofComapInfPrincipal h) = g
[PROOFSTEP]
let f := Filter.comap m g ⊓ 𝓟 s
[GOAL]
α : Type u
β : Type v
γ : Type u_1
m : α → β
s : Set α
g : Ultrafilter β
h : m '' s ∈ g
f : Filter α := Filter.comap m ↑g ⊓ 𝓟 s
⊢ map m (ofComapInfPrincipal h) = g
[PROOFSTEP]
haveI : f.NeBot := comap_inf_principal_neBot_of_image_mem h
[GOAL]
α : Type u
β : Type v
γ : Type u_1
m : α → β
s : Set α
g : Ultrafilter β
h : m '' s ∈ g
f : Filter α := Filter.comap m ↑g ⊓ 𝓟 s
this : NeBot f
⊢ map m (ofComapInfPrincipal h) = g
[PROOFSTEP]
apply eq_of_le
[GOAL]
case h
α : Type u
β : Type v
γ : Type u_1
m : α → β
s : Set α
g : Ultrafilter β
h : m '' s ∈ g
f : Filter α := Filter.comap m ↑g ⊓ 𝓟 s
this : NeBot f
⊢ ↑(map m (ofComapInfPrincipal h)) ≤ ↑g
[PROOFSTEP]
calc
  Filter.map m (of f) ≤ Filter.map m f := map_mono (of_le _)
  _ ≤ (Filter.map m <| Filter.comap m g) ⊓ Filter.map m (𝓟 s) := map_inf_le
  _ = (Filter.map m <| Filter.comap m g) ⊓ (𝓟 <| m '' s) := by rw [map_principal]
  _ ≤ ↑g ⊓ (𝓟 <| m '' s) := (inf_le_inf_right _ map_comap_le)
  _ = ↑g := inf_of_le_left (le_principal_iff.mpr h)
[GOAL]
α : Type u
β : Type v
γ : Type u_1
m : α → β
s : Set α
g : Ultrafilter β
h : m '' s ∈ g
f : Filter α := Filter.comap m ↑g ⊓ 𝓟 s
this : NeBot f
⊢ Filter.map m (Filter.comap m ↑g) ⊓ Filter.map m (𝓟 s) = Filter.map m (Filter.comap m ↑g) ⊓ 𝓟 (m '' s)
[PROOFSTEP]
rw [map_principal]