l3lab/ntp-mathlib huggingface dataset:
theorem finite_of_linearIndependent [Nontrivial R] {s : Set M}
    (hs : LinearIndependent R ((↑) : s → M)) : s.Finite := by
  refine'
    by_contradiction fun hf =>
      (RelEmbedding.wellFounded_iff_no_descending_seq.1 (wellFounded_submodule_gt R M)).elim' _
  have f : ℕ ↪ s := Set.Infinite.natEmbedding s hf
  have : ∀ n, (↑) ∘ f '' { m | m ≤ n } ⊆ s := by
    rintro n x ⟨y, _, rfl⟩
    exact (f y).2
  let coe' : s → M := (↑)
  have : ∀ a b : ℕ, a ≤ b ↔
    span R (coe' ∘ f '' { m | m ≤ a }) ≤ span R ((↑) ∘ f '' { m | m ≤ b }) := by
    intro a b
    rw [span_le_span_iff hs (this a) (this b),
      Set.image_subset_image_iff (Subtype.coe_injective.comp f.injective), Set.subset_def]
    exact ⟨fun hab x (hxa : x ≤ a) => le_trans hxa hab, fun hx => hx a (le_refl a)⟩
  exact
    ⟨⟨fun n => span R (coe' ∘ f '' { m | m ≤ n }), fun x y => by
        rw [le_antisymm_iff, (this x y).symm, (this y x).symm, ← le_antisymm_iff, imp_self]
        trivial⟩,
      by 

Proof state:
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁸ : Ring R
inst✝⁷ : AddCommGroup M
inst✝⁶ : Module R M
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
inst✝³ : AddCommGroup P
inst✝² : Module R P
inst✝¹ : IsNoetherian R M
inst✝ : Nontrivial R
s : Set M
hs : LinearIndependent (ι := { x // x ∈ s }) R Subtype.val
hf : ¬Set.Finite s
f : ℕ ↪ ↑s
this✝ : ∀ (n : ℕ), Subtype.val ∘ ⇑f '' {m | m ≤ n} ⊆ s
coe' : ↑s → M := Subtype.val
this : ∀ (a b : ℕ), a ≤ b ↔ span R (coe' ∘ ⇑f '' {m | m ≤ a}) ≤ span R (Subtype.val ∘ ⇑f '' {m | m ≤ b})
⊢ ∀ {a b : ℕ},
    { toFun := fun n => span R (coe' ∘ ⇑f '' {m | m ≤ n}),
            inj' :=
              (_ :
                ∀ (x y : ℕ),
                  (fun n => span R (coe' ∘ ⇑f '' {m | m ≤ n})) x = (fun n => span R (coe' ∘ ⇑f '' {m | m ≤ n})) y →
                    x = y) }
          a >
        { toFun := fun n => span R (coe' ∘ ⇑f '' {m | m ≤ n}),
            inj' :=
              (_ :
                ∀ (x y : ℕ),
                  (fun n => span R (coe' ∘ ⇑f '' {m | m ≤ n})) x = (fun n => span R (coe' ∘ ⇑f '' {m | m ≤ n})) y →
                    x = y) }
          b ↔
      a > b

Next tactic:
dsimp [GT.gt]
theorem finite_of_linearIndependent [Nontrivial R] {s : Set M}
    (hs : LinearIndependent R ((↑) : s → M)) : s.Finite := by
  refine'
    by_contradiction fun hf =>
      (RelEmbedding.wellFounded_iff_no_descending_seq.1 (wellFounded_submodule_gt R M)).elim' _
  have f : ℕ ↪ s := Set.Infinite.natEmbedding s hf
  have : ∀ n, (↑) ∘ f '' { m | m ≤ n } ⊆ s := by
    rintro n x ⟨y, _, rfl⟩
    exact (f y).2
  let coe' : s → M := (↑)
  have : ∀ a b : ℕ, a ≤ b ↔
    span R (coe' ∘ f '' { m | m ≤ a }) ≤ span R ((↑) ∘ f '' { m | m ≤ b }) := by
    intro a b
    rw [span_le_span_iff hs (this a) (this b),
      Set.image_subset_image_iff (Subtype.coe_injective.comp f.injective), Set.subset_def]
    exact ⟨fun hab x (hxa : x ≤ a) => le_trans hxa hab, fun hx => hx a (le_refl a)⟩
  exact
    ⟨⟨fun n => span R (coe' ∘ f '' { m | m ≤ n }), fun x y => by
        rw [le_antisymm_iff, (this x y).symm, (this y x).symm, ← le_antisymm_iff, imp_self]
        trivial⟩,
      by dsimp [GT.gt]; 

Proof state:
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁸ : Ring R
inst✝⁷ : AddCommGroup M
inst✝⁶ : Module R M
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
inst✝³ : AddCommGroup P
inst✝² : Module R P
inst✝¹ : IsNoetherian R M
inst✝ : Nontrivial R
s : Set M
hs : LinearIndependent (ι := { x // x ∈ s }) R Subtype.val
hf : ¬Set.Finite s
f : ℕ ↪ ↑s
this✝ : ∀ (n : ℕ), Subtype.val ∘ ⇑f '' {m | m ≤ n} ⊆ s
coe' : ↑s → M := Subtype.val
this : ∀ (a b : ℕ), a ≤ b ↔ span R (coe' ∘ ⇑f '' {m | m ≤ a}) ≤ span R (Subtype.val ∘ ⇑f '' {m | m ≤ b})
⊢ ∀ {a b : ℕ}, span R (Subtype.val ∘ ⇑f '' {m | m ≤ b}) < span R (Subtype.val ∘ ⇑f '' {m | m ≤ a}) ↔ b < a

Next tactic:
simp only [lt_iff_le_not_le, (this _ _).symm]
theorem finite_of_linearIndependent [Nontrivial R] {s : Set M}
    (hs : LinearIndependent R ((↑) : s → M)) : s.Finite := by
  refine'
    by_contradiction fun hf =>
      (RelEmbedding.wellFounded_iff_no_descending_seq.1 (wellFounded_submodule_gt R M)).elim' _
  have f : ℕ ↪ s := Set.Infinite.natEmbedding s hf
  have : ∀ n, (↑) ∘ f '' { m | m ≤ n } ⊆ s := by
    rintro n x ⟨y, _, rfl⟩
    exact (f y).2
  let coe' : s → M := (↑)
  have : ∀ a b : ℕ, a ≤ b ↔
    span R (coe' ∘ f '' { m | m ≤ a }) ≤ span R ((↑) ∘ f '' { m | m ≤ b }) := by
    intro a b
    rw [span_le_span_iff hs (this a) (this b),
      Set.image_subset_image_iff (Subtype.coe_injective.comp f.injective), Set.subset_def]
    exact ⟨fun hab x (hxa : x ≤ a) => le_trans hxa hab, fun hx => hx a (le_refl a)⟩
  exact
    ⟨⟨fun n => span R (coe' ∘ f '' { m | m ≤ n }), fun x y => by
        rw [le_antisymm_iff, (this x y).symm, (this y x).symm, ← le_antisymm_iff, imp_self]
        trivial⟩,
      by dsimp [GT.gt]; simp only [lt_iff_le_not_le, (this _ _).symm]; 

Proof state:
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁸ : Ring R
inst✝⁷ : AddCommGroup M
inst✝⁶ : Module R M
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
inst✝³ : AddCommGroup P
inst✝² : Module R P
inst✝¹ : IsNoetherian R M
inst✝ : Nontrivial R
s : Set M
hs : LinearIndependent (ι := { x // x ∈ s }) R Subtype.val
hf : ¬Set.Finite s
f : ℕ ↪ ↑s
this✝ : ∀ (n : ℕ), Subtype.val ∘ ⇑f '' {m | m ≤ n} ⊆ s
coe' : ↑s → M := Subtype.val
this : ∀ (a b : ℕ), a ≤ b ↔ span R (coe' ∘ ⇑f '' {m | m ≤ a}) ≤ span R (Subtype.val ∘ ⇑f '' {m | m ≤ b})
⊢ ∀ {a b : ℕ}, True

Next tactic:
tauto
/-- If the first and final modules in a short exact sequence are Noetherian,
  then the middle module is also Noetherian. -/
theorem isNoetherian_of_range_eq_ker [IsNoetherian R P] (f : M →ₗ[R] N)
    (g : N →ₗ[R] P) (hf : Function.Injective f) (hg : Function.Surjective g)
    (h : LinearMap.range f = LinearMap.ker g) :
    IsNoetherian R N :=
  isNoetherian_iff_wellFounded.2 <|
    wellFounded_gt_exact_sequence (wellFounded_submodule_gt R M) (wellFounded_submodule_gt R P)
      (LinearMap.range f) (Submodule.map f) (Submodule.comap f) (Submodule.comap g)
      (Submodule.map g) (Submodule.gciMapComap hf) (Submodule.giMapComap hg)
      (by 

Proof state:
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁸ : Ring R
inst✝⁷ : AddCommGroup M
inst✝⁶ : Module R M
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
inst✝³ : AddCommGroup P
inst✝² : Module R P
inst✝¹ : IsNoetherian R M
inst✝ : IsNoetherian R P
f : M →ₗ[R] N
g : N →ₗ[R] P
hf : Injective ⇑f
hg : Surjective ⇑g
h : LinearMap.range f = LinearMap.ker g
⊢ ∀ (a : Submodule R N), Submodule.map f (Submodule.comap f a) = a ⊓ LinearMap.range f

Next tactic:
simp [Submodule.map_comap_eq, inf_comm]
/-- If the first and final modules in a short exact sequence are Noetherian,
  then the middle module is also Noetherian. -/
theorem isNoetherian_of_range_eq_ker [IsNoetherian R P] (f : M →ₗ[R] N)
    (g : N →ₗ[R] P) (hf : Function.Injective f) (hg : Function.Surjective g)
    (h : LinearMap.range f = LinearMap.ker g) :
    IsNoetherian R N :=
  isNoetherian_iff_wellFounded.2 <|
    wellFounded_gt_exact_sequence (wellFounded_submodule_gt R M) (wellFounded_submodule_gt R P)
      (LinearMap.range f) (Submodule.map f) (Submodule.comap f) (Submodule.comap g)
      (Submodule.map g) (Submodule.gciMapComap hf) (Submodule.giMapComap hg)
      (by simp [Submodule.map_comap_eq, inf_comm]) (by 

Proof state:
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁸ : Ring R
inst✝⁷ : AddCommGroup M
inst✝⁶ : Module R M
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
inst✝³ : AddCommGroup P
inst✝² : Module R P
inst✝¹ : IsNoetherian R M
inst✝ : IsNoetherian R P
f : M →ₗ[R] N
g : N →ₗ[R] P
hf : Injective ⇑f
hg : Surjective ⇑g
h : LinearMap.range f = LinearMap.ker g
⊢ ∀ (a : Submodule R N), Submodule.comap g (Submodule.map g a) = a ⊔ LinearMap.range f

Next tactic:
simp [Submodule.comap_map_eq, h]
/-- For an endomorphism of a Noetherian module, any sufficiently large iterate has disjoint kernel
and range. -/
theorem LinearMap.eventually_disjoint_ker_pow_range_pow (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, Disjoint (LinearMap.ker (f ^ n)) (LinearMap.range (f ^ n)) := by
  

Proof state:
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
⊢ ∀ᶠ (n : ℕ) in atTop, Disjoint (ker (f ^ n)) (range (f ^ n))

Next tactic:
obtain ⟨n, hn : ∀ m, n ≤ m → LinearMap.ker (f ^ n) = LinearMap.ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
/-- For an endomorphism of a Noetherian module, any sufficiently large iterate has disjoint kernel
and range. -/
theorem LinearMap.eventually_disjoint_ker_pow_range_pow (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, Disjoint (LinearMap.ker (f ^ n)) (LinearMap.range (f ^ n)) := by
  obtain ⟨n, hn : ∀ m, n ≤ m → LinearMap.ker (f ^ n) = LinearMap.ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
  

Proof state:
case intro
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → ker (f ^ n) = ker (f ^ m)
⊢ ∀ᶠ (n : ℕ) in atTop, Disjoint (ker (f ^ n)) (range (f ^ n))

Next tactic:
refine eventually_atTop.mpr ⟨n, fun m hm ↦ disjoint_iff.mpr ?_⟩
/-- For an endomorphism of a Noetherian module, any sufficiently large iterate has disjoint kernel
and range. -/
theorem LinearMap.eventually_disjoint_ker_pow_range_pow (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, Disjoint (LinearMap.ker (f ^ n)) (LinearMap.range (f ^ n)) := by
  obtain ⟨n, hn : ∀ m, n ≤ m → LinearMap.ker (f ^ n) = LinearMap.ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
  refine eventually_atTop.mpr ⟨n, fun m hm ↦ disjoint_iff.mpr ?_⟩
  

Proof state:
case intro
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → ker (f ^ n) = ker (f ^ m)
m : ℕ
hm : m ≥ n
⊢ ker (f ^ m) ⊓ range (f ^ m) = ⊥

Next tactic:
rw [← hn _ hm, Submodule.eq_bot_iff]
/-- For an endomorphism of a Noetherian module, any sufficiently large iterate has disjoint kernel
and range. -/
theorem LinearMap.eventually_disjoint_ker_pow_range_pow (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, Disjoint (LinearMap.ker (f ^ n)) (LinearMap.range (f ^ n)) := by
  obtain ⟨n, hn : ∀ m, n ≤ m → LinearMap.ker (f ^ n) = LinearMap.ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
  refine eventually_atTop.mpr ⟨n, fun m hm ↦ disjoint_iff.mpr ?_⟩
  rw [← hn _ hm, Submodule.eq_bot_iff]
  

Proof state:
case intro
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → ker (f ^ n) = ker (f ^ m)
m : ℕ
hm : m ≥ n
⊢ ∀ x ∈ ker (f ^ n) ⊓ range (f ^ m), x = 0

Next tactic:
rintro - ⟨hx, ⟨x, rfl⟩⟩
/-- For an endomorphism of a Noetherian module, any sufficiently large iterate has disjoint kernel
and range. -/
theorem LinearMap.eventually_disjoint_ker_pow_range_pow (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, Disjoint (LinearMap.ker (f ^ n)) (LinearMap.range (f ^ n)) := by
  obtain ⟨n, hn : ∀ m, n ≤ m → LinearMap.ker (f ^ n) = LinearMap.ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
  refine eventually_atTop.mpr ⟨n, fun m hm ↦ disjoint_iff.mpr ?_⟩
  rw [← hn _ hm, Submodule.eq_bot_iff]
  rintro - ⟨hx, ⟨x, rfl⟩⟩
  

Proof state:
case intro.intro.intro
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → ker (f ^ n) = ker (f ^ m)
m : ℕ
hm : m ≥ n
x : M
hx : (f ^ m) x ∈ ↑(ker (f ^ n))
⊢ (f ^ m) x = 0

Next tactic:
apply LinearMap.pow_map_zero_of_le hm
/-- For an endomorphism of a Noetherian module, any sufficiently large iterate has disjoint kernel
and range. -/
theorem LinearMap.eventually_disjoint_ker_pow_range_pow (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, Disjoint (LinearMap.ker (f ^ n)) (LinearMap.range (f ^ n)) := by
  obtain ⟨n, hn : ∀ m, n ≤ m → LinearMap.ker (f ^ n) = LinearMap.ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
  refine eventually_atTop.mpr ⟨n, fun m hm ↦ disjoint_iff.mpr ?_⟩
  rw [← hn _ hm, Submodule.eq_bot_iff]
  rintro - ⟨hx, ⟨x, rfl⟩⟩
  apply LinearMap.pow_map_zero_of_le hm
  

Proof state:
case intro.intro.intro
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → ker (f ^ n) = ker (f ^ m)
m : ℕ
hm : m ≥ n
x : M
hx : (f ^ m) x ∈ ↑(ker (f ^ n))
⊢ (f ^ n) x = 0

Next tactic:
replace hx : x ∈ LinearMap.ker (f ^ (n + m)) := by
    simpa [f.pow_apply n, f.pow_apply m, ← f.pow_apply (n + m), ← iterate_add_apply] using hx
/-- For an endomorphism of a Noetherian module, any sufficiently large iterate has disjoint kernel
and range. -/
theorem LinearMap.eventually_disjoint_ker_pow_range_pow (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, Disjoint (LinearMap.ker (f ^ n)) (LinearMap.range (f ^ n)) := by
  obtain ⟨n, hn : ∀ m, n ≤ m → LinearMap.ker (f ^ n) = LinearMap.ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
  refine eventually_atTop.mpr ⟨n, fun m hm ↦ disjoint_iff.mpr ?_⟩
  rw [← hn _ hm, Submodule.eq_bot_iff]
  rintro - ⟨hx, ⟨x, rfl⟩⟩
  apply LinearMap.pow_map_zero_of_le hm
  replace hx : x ∈ LinearMap.ker (f ^ (n + m)) := by
    

Proof state:
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → ker (f ^ n) = ker (f ^ m)
m : ℕ
hm : m ≥ n
x : M
hx : (f ^ m) x ∈ ↑(ker (f ^ n))
⊢ x ∈ ker (f ^ (n + m))

Next tactic:
simpa [f.pow_apply n, f.pow_apply m, ← f.pow_apply (n + m), ← iterate_add_apply] using hx
/-- For an endomorphism of a Noetherian module, any sufficiently large iterate has disjoint kernel
and range. -/
theorem LinearMap.eventually_disjoint_ker_pow_range_pow (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, Disjoint (LinearMap.ker (f ^ n)) (LinearMap.range (f ^ n)) := by
  obtain ⟨n, hn : ∀ m, n ≤ m → LinearMap.ker (f ^ n) = LinearMap.ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
  refine eventually_atTop.mpr ⟨n, fun m hm ↦ disjoint_iff.mpr ?_⟩
  rw [← hn _ hm, Submodule.eq_bot_iff]
  rintro - ⟨hx, ⟨x, rfl⟩⟩
  apply LinearMap.pow_map_zero_of_le hm
  replace hx : x ∈ LinearMap.ker (f ^ (n + m)) := by
    simpa [f.pow_apply n, f.pow_apply m, ← f.pow_apply (n + m), ← iterate_add_apply] using hx
  

Proof state:
case intro.intro.intro
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → ker (f ^ n) = ker (f ^ m)
m : ℕ
hm : m ≥ n
x : M
hx : x ∈ ker (f ^ (n + m))
⊢ (f ^ n) x = 0

Next tactic:
rwa [← hn _ (n.le_add_right m)] at hx
lemma LinearMap.eventually_iSup_ker_pow_eq (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, ⨆ m, LinearMap.ker (f ^ m) = LinearMap.ker (f ^ n) := by
  

Proof state:
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
⊢ ∀ᶠ (n : ℕ) in atTop, ⨆ m, ker (f ^ m) = ker (f ^ n)

Next tactic:
obtain ⟨n, hn : ∀ m, n ≤ m → ker (f ^ n) = ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
lemma LinearMap.eventually_iSup_ker_pow_eq (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, ⨆ m, LinearMap.ker (f ^ m) = LinearMap.ker (f ^ n) := by
  obtain ⟨n, hn : ∀ m, n ≤ m → ker (f ^ n) = ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
  

Proof state:
case intro
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → ker (f ^ n) = ker (f ^ m)
⊢ ∀ᶠ (n : ℕ) in atTop, ⨆ m, ker (f ^ m) = ker (f ^ n)

Next tactic:
refine eventually_atTop.mpr ⟨n, fun m hm ↦ ?_⟩
lemma LinearMap.eventually_iSup_ker_pow_eq (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, ⨆ m, LinearMap.ker (f ^ m) = LinearMap.ker (f ^ n) := by
  obtain ⟨n, hn : ∀ m, n ≤ m → ker (f ^ n) = ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
  refine eventually_atTop.mpr ⟨n, fun m hm ↦ ?_⟩
  

Proof state:
case intro
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → ker (f ^ n) = ker (f ^ m)
m : ℕ
hm : m ≥ n
⊢ ⨆ m, ker (f ^ m) = ker (f ^ m)

Next tactic:
refine le_antisymm (iSup_le fun l ↦ ?_) (le_iSup (fun i ↦ LinearMap.ker (f ^ i)) m)
lemma LinearMap.eventually_iSup_ker_pow_eq (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, ⨆ m, LinearMap.ker (f ^ m) = LinearMap.ker (f ^ n) := by
  obtain ⟨n, hn : ∀ m, n ≤ m → ker (f ^ n) = ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
  refine eventually_atTop.mpr ⟨n, fun m hm ↦ ?_⟩
  refine le_antisymm (iSup_le fun l ↦ ?_) (le_iSup (fun i ↦ LinearMap.ker (f ^ i)) m)
  

Proof state:
case intro
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → ker (f ^ n) = ker (f ^ m)
m : ℕ
hm : m ≥ n
l : ℕ
⊢ ker (f ^ l) ≤ ker (f ^ m)

Next tactic:
rcases le_or_lt m l with h | h
lemma LinearMap.eventually_iSup_ker_pow_eq (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, ⨆ m, LinearMap.ker (f ^ m) = LinearMap.ker (f ^ n) := by
  obtain ⟨n, hn : ∀ m, n ≤ m → ker (f ^ n) = ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
  refine eventually_atTop.mpr ⟨n, fun m hm ↦ ?_⟩
  refine le_antisymm (iSup_le fun l ↦ ?_) (le_iSup (fun i ↦ LinearMap.ker (f ^ i)) m)
  rcases le_or_lt m l with h | h
  · 

Proof state:
case intro.inl
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → ker (f ^ n) = ker (f ^ m)
m : ℕ
hm : m ≥ n
l : ℕ
h : m ≤ l
⊢ ker (f ^ l) ≤ ker (f ^ m)

Next tactic:
rw [← hn _ (hm.trans h), hn _ hm]
lemma LinearMap.eventually_iSup_ker_pow_eq (f : M →ₗ[R] M) :
    ∀ᶠ n in atTop, ⨆ m, LinearMap.ker (f ^ m) = LinearMap.ker (f ^ n) := by
  obtain ⟨n, hn : ∀ m, n ≤ m → ker (f ^ n) = ker (f ^ m)⟩ :=
    monotone_stabilizes_iff_noetherian.mpr inferInstance f.iterateKer
  refine eventually_atTop.mpr ⟨n, fun m hm ↦ ?_⟩
  refine le_antisymm (iSup_le fun l ↦ ?_) (le_iSup (fun i ↦ LinearMap.ker (f ^ i)) m)
  rcases le_or_lt m l with h | h
  · rw [← hn _ (hm.trans h), hn _ hm]
  · 

Proof state:
case intro.inr
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → ker (f ^ n) = ker (f ^ m)
m : ℕ
hm : m ≥ n
l : ℕ
h : l < m
⊢ ker (f ^ l) ≤ ker (f ^ m)

Next tactic:
exact f.iterateKer.monotone h.le
/-- Any surjective endomorphism of a Noetherian module is injective. -/
theorem IsNoetherian.injective_of_surjective_endomorphism (f : M →ₗ[R] M)
    (s : Surjective f) : Injective f := by
  

Proof state:
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
s : Surjective ⇑f
⊢ Injective ⇑f

Next tactic:
obtain ⟨n, hn⟩ := eventually_atTop.mp f.eventually_disjoint_ker_pow_range_pow
/-- Any surjective endomorphism of a Noetherian module is injective. -/
theorem IsNoetherian.injective_of_surjective_endomorphism (f : M →ₗ[R] M)
    (s : Surjective f) : Injective f := by
  obtain ⟨n, hn⟩ := eventually_atTop.mp f.eventually_disjoint_ker_pow_range_pow
  

Proof state:
case intro
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
s : Surjective ⇑f
n : ℕ
hn : ∀ b ≥ n, Disjoint (LinearMap.ker (f ^ b)) (LinearMap.range (f ^ b))
⊢ Injective ⇑f

Next tactic:
specialize hn (n + 1) (n.le_add_right 1)
/-- Any surjective endomorphism of a Noetherian module is injective. -/
theorem IsNoetherian.injective_of_surjective_endomorphism (f : M →ₗ[R] M)
    (s : Surjective f) : Injective f := by
  obtain ⟨n, hn⟩ := eventually_atTop.mp f.eventually_disjoint_ker_pow_range_pow
  specialize hn (n + 1) (n.le_add_right 1)
  

Proof state:
case intro
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
s : Surjective ⇑f
n : ℕ
hn : Disjoint (LinearMap.ker (f ^ (n + 1))) (LinearMap.range (f ^ (n + 1)))
⊢ Injective ⇑f

Next tactic:
rw [disjoint_iff, LinearMap.range_eq_top.mpr (LinearMap.iterate_surjective s _), inf_top_eq,
    LinearMap.ker_eq_bot] at hn
/-- Any surjective endomorphism of a Noetherian module is injective. -/
theorem IsNoetherian.injective_of_surjective_endomorphism (f : M →ₗ[R] M)
    (s : Surjective f) : Injective f := by
  obtain ⟨n, hn⟩ := eventually_atTop.mp f.eventually_disjoint_ker_pow_range_pow
  specialize hn (n + 1) (n.le_add_right 1)
  rw [disjoint_iff, LinearMap.range_eq_top.mpr (LinearMap.iterate_surjective s _), inf_top_eq,
    LinearMap.ker_eq_bot] at hn
  

Proof state:
case intro
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : M →ₗ[R] M
s : Surjective ⇑f
n : ℕ
hn : Injective ⇑(f ^ (n + 1))
⊢ Injective ⇑f

Next tactic:
exact LinearMap.injective_of_iterate_injective n.succ_ne_zero hn
/-- A sequence `f` of submodules of a noetherian module,
with `f (n+1)` disjoint from the supremum of `f 0`, ..., `f n`,
is eventually zero.
-/
theorem IsNoetherian.disjoint_partialSups_eventually_bot
    (f : ℕ → Submodule R M) (h : ∀ n, Disjoint (partialSups f n) (f (n + 1))) :
    ∃ n : ℕ, ∀ m, n ≤ m → f m = ⊥ := by
  -- A little off-by-one cleanup first:
  

Proof state:
R : Type u_1
M : Type u_2
P : Type u_3
N : Type w
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
inst✝⁴ : AddCommGroup N
inst✝³ : Module R N
inst✝² : AddCommGroup P
inst✝¹ : Module R P
inst✝ : IsNoetherian R M
f : ℕ → Submodule R M
h : ∀ (n : ℕ), Disjoint ((partialSups f) n) (f (n + 1))
⊢ ∃ n, ∀ (m : ℕ), n ≤ m → f m = ⊥

Next tactic:
suffices t : ∃ n : ℕ, ∀ m, n ≤ m → f (m + 1) = ⊥