l3lab/ntp-mathlib huggingface dataset:
theorem unitLattice_span_eq_top :
    Submodule.span ℝ (unitLattice K : Set ({w : InfinitePlace K // w ≠ w₀} → ℝ)) = ⊤ := by
  refine le_antisymm (le_top) ?_
  -- The standard basis
  let B := Pi.basisFun ℝ {w : InfinitePlace K // w ≠ w₀}
  -- The image by log_embedding of the family of units constructed above
  let v := fun w : { w : InfinitePlace K // w ≠ w₀ } => logEmbedding K (exists_unit K w).choose
  -- To prove the result, it is enough to prove that the family `v` is linearly independent
  suffices B.det v ≠ 0 by
    rw [← isUnit_iff_ne_zero, ← is_basis_iff_det] at this
    rw [← this.2]
    exact Submodule.span_monotone (fun _ ⟨w, hw⟩ =>
      ⟨(exists_unit K w).choose, trivial, by rw [← hw]⟩)
  rw [Basis.det_apply]
  -- We use a specific lemma to prove that this determinant is nonzero
  refine det_ne_zero_of_sum_col_lt_diag (fun w => ?_)
  simp_rw [Real.norm_eq_abs, Basis.coePiBasisFun.toMatrix_eq_transpose, Matrix.transpose_apply]
  rw [← sub_pos, sum_congr rfl (fun x hx => abs_of_neg ?_), sum_neg_distrib, sub_neg_eq_add,
    sum_erase_eq_sub (mem_univ _), ← add_comm_sub]
  refine add_pos_of_nonneg_of_pos ?_ ?_
  · rw [sub_nonneg]
    exact le_abs_self _
  · rw [sum_logEmbedding_component (exists_unit K w).choose]
    refine mul_pos_of_neg_of_neg ?_ ((exists_unit K w).choose_spec _ w.prop.symm)
    rw [mult]; split_ifs <;> norm_num
  · 

Proof state:
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
w₁ : InfinitePlace K
B✝ : ℕ
hB : minkowskiBound K < convexBodyLTFactor K * ↑B✝
B : Basis { w // w ≠ w₀ } ℝ ({ w // w ≠ w₀ } → ℝ) := Pi.basisFun ℝ { w // w ≠ w₀ }
v : { w // w ≠ w₀ } → { w // w ≠ w₀ } → ℝ :=
  fun w => (logEmbedding K) (Exists.choose (_ : ∃ u, ∀ (w_1 : InfinitePlace K), w_1 ≠ ↑w → Real.log (w_1 ↑↑u) < 0))
w x : { w // w ≠ w₀ }
hx : x ∈ erase univ w
⊢ (logEmbedding K) (Exists.choose (_ : ∃ u, ∀ (w_1 : InfinitePlace K), w_1 ≠ ↑w → Real.log (w_1 ↑↑u) < 0)) x < 0

Next tactic:
refine mul_neg_of_pos_of_neg ?_ ((exists_unit K w).choose_spec x ?_)
theorem unitLattice_span_eq_top :
    Submodule.span ℝ (unitLattice K : Set ({w : InfinitePlace K // w ≠ w₀} → ℝ)) = ⊤ := by
  refine le_antisymm (le_top) ?_
  -- The standard basis
  let B := Pi.basisFun ℝ {w : InfinitePlace K // w ≠ w₀}
  -- The image by log_embedding of the family of units constructed above
  let v := fun w : { w : InfinitePlace K // w ≠ w₀ } => logEmbedding K (exists_unit K w).choose
  -- To prove the result, it is enough to prove that the family `v` is linearly independent
  suffices B.det v ≠ 0 by
    rw [← isUnit_iff_ne_zero, ← is_basis_iff_det] at this
    rw [← this.2]
    exact Submodule.span_monotone (fun _ ⟨w, hw⟩ =>
      ⟨(exists_unit K w).choose, trivial, by rw [← hw]⟩)
  rw [Basis.det_apply]
  -- We use a specific lemma to prove that this determinant is nonzero
  refine det_ne_zero_of_sum_col_lt_diag (fun w => ?_)
  simp_rw [Real.norm_eq_abs, Basis.coePiBasisFun.toMatrix_eq_transpose, Matrix.transpose_apply]
  rw [← sub_pos, sum_congr rfl (fun x hx => abs_of_neg ?_), sum_neg_distrib, sub_neg_eq_add,
    sum_erase_eq_sub (mem_univ _), ← add_comm_sub]
  refine add_pos_of_nonneg_of_pos ?_ ?_
  · rw [sub_nonneg]
    exact le_abs_self _
  · rw [sum_logEmbedding_component (exists_unit K w).choose]
    refine mul_pos_of_neg_of_neg ?_ ((exists_unit K w).choose_spec _ w.prop.symm)
    rw [mult]; split_ifs <;> norm_num
  · refine mul_neg_of_pos_of_neg ?_ ((exists_unit K w).choose_spec x ?_)
    · 

Proof state:
case refine_1
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
w₁ : InfinitePlace K
B✝ : ℕ
hB : minkowskiBound K < convexBodyLTFactor K * ↑B✝
B : Basis { w // w ≠ w₀ } ℝ ({ w // w ≠ w₀ } → ℝ) := Pi.basisFun ℝ { w // w ≠ w₀ }
v : { w // w ≠ w₀ } → { w // w ≠ w₀ } → ℝ :=
  fun w => (logEmbedding K) (Exists.choose (_ : ∃ u, ∀ (w_1 : InfinitePlace K), w_1 ≠ ↑w → Real.log (w_1 ↑↑u) < 0))
w x : { w // w ≠ w₀ }
hx : x ∈ erase univ w
⊢ 0 < ↑(mult ↑x)

Next tactic:
rw [mult]
theorem unitLattice_span_eq_top :
    Submodule.span ℝ (unitLattice K : Set ({w : InfinitePlace K // w ≠ w₀} → ℝ)) = ⊤ := by
  refine le_antisymm (le_top) ?_
  -- The standard basis
  let B := Pi.basisFun ℝ {w : InfinitePlace K // w ≠ w₀}
  -- The image by log_embedding of the family of units constructed above
  let v := fun w : { w : InfinitePlace K // w ≠ w₀ } => logEmbedding K (exists_unit K w).choose
  -- To prove the result, it is enough to prove that the family `v` is linearly independent
  suffices B.det v ≠ 0 by
    rw [← isUnit_iff_ne_zero, ← is_basis_iff_det] at this
    rw [← this.2]
    exact Submodule.span_monotone (fun _ ⟨w, hw⟩ =>
      ⟨(exists_unit K w).choose, trivial, by rw [← hw]⟩)
  rw [Basis.det_apply]
  -- We use a specific lemma to prove that this determinant is nonzero
  refine det_ne_zero_of_sum_col_lt_diag (fun w => ?_)
  simp_rw [Real.norm_eq_abs, Basis.coePiBasisFun.toMatrix_eq_transpose, Matrix.transpose_apply]
  rw [← sub_pos, sum_congr rfl (fun x hx => abs_of_neg ?_), sum_neg_distrib, sub_neg_eq_add,
    sum_erase_eq_sub (mem_univ _), ← add_comm_sub]
  refine add_pos_of_nonneg_of_pos ?_ ?_
  · rw [sub_nonneg]
    exact le_abs_self _
  · rw [sum_logEmbedding_component (exists_unit K w).choose]
    refine mul_pos_of_neg_of_neg ?_ ((exists_unit K w).choose_spec _ w.prop.symm)
    rw [mult]; split_ifs <;> norm_num
  · refine mul_neg_of_pos_of_neg ?_ ((exists_unit K w).choose_spec x ?_)
    · rw [mult]; 

Proof state:
case refine_1
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
w₁ : InfinitePlace K
B✝ : ℕ
hB : minkowskiBound K < convexBodyLTFactor K * ↑B✝
B : Basis { w // w ≠ w₀ } ℝ ({ w // w ≠ w₀ } → ℝ) := Pi.basisFun ℝ { w // w ≠ w₀ }
v : { w // w ≠ w₀ } → { w // w ≠ w₀ } → ℝ :=
  fun w => (logEmbedding K) (Exists.choose (_ : ∃ u, ∀ (w_1 : InfinitePlace K), w_1 ≠ ↑w → Real.log (w_1 ↑↑u) < 0))
w x : { w // w ≠ w₀ }
hx : x ∈ erase univ w
⊢ 0 < ↑(if IsReal ↑x then 1 else 2)

Next tactic:
split_ifs
theorem unitLattice_span_eq_top :
    Submodule.span ℝ (unitLattice K : Set ({w : InfinitePlace K // w ≠ w₀} → ℝ)) = ⊤ := by
  refine le_antisymm (le_top) ?_
  -- The standard basis
  let B := Pi.basisFun ℝ {w : InfinitePlace K // w ≠ w₀}
  -- The image by log_embedding of the family of units constructed above
  let v := fun w : { w : InfinitePlace K // w ≠ w₀ } => logEmbedding K (exists_unit K w).choose
  -- To prove the result, it is enough to prove that the family `v` is linearly independent
  suffices B.det v ≠ 0 by
    rw [← isUnit_iff_ne_zero, ← is_basis_iff_det] at this
    rw [← this.2]
    exact Submodule.span_monotone (fun _ ⟨w, hw⟩ =>
      ⟨(exists_unit K w).choose, trivial, by rw [← hw]⟩)
  rw [Basis.det_apply]
  -- We use a specific lemma to prove that this determinant is nonzero
  refine det_ne_zero_of_sum_col_lt_diag (fun w => ?_)
  simp_rw [Real.norm_eq_abs, Basis.coePiBasisFun.toMatrix_eq_transpose, Matrix.transpose_apply]
  rw [← sub_pos, sum_congr rfl (fun x hx => abs_of_neg ?_), sum_neg_distrib, sub_neg_eq_add,
    sum_erase_eq_sub (mem_univ _), ← add_comm_sub]
  refine add_pos_of_nonneg_of_pos ?_ ?_
  · rw [sub_nonneg]
    exact le_abs_self _
  · rw [sum_logEmbedding_component (exists_unit K w).choose]
    refine mul_pos_of_neg_of_neg ?_ ((exists_unit K w).choose_spec _ w.prop.symm)
    rw [mult]; split_ifs <;> norm_num
  · refine mul_neg_of_pos_of_neg ?_ ((exists_unit K w).choose_spec x ?_)
    · rw [mult]; split_ifs <;> 

Proof state:
case pos
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
w₁ : InfinitePlace K
B✝ : ℕ
hB : minkowskiBound K < convexBodyLTFactor K * ↑B✝
B : Basis { w // w ≠ w₀ } ℝ ({ w // w ≠ w₀ } → ℝ) := Pi.basisFun ℝ { w // w ≠ w₀ }
v : { w // w ≠ w₀ } → { w // w ≠ w₀ } → ℝ :=
  fun w => (logEmbedding K) (Exists.choose (_ : ∃ u, ∀ (w_1 : InfinitePlace K), w_1 ≠ ↑w → Real.log (w_1 ↑↑u) < 0))
w x : { w // w ≠ w₀ }
hx : x ∈ erase univ w
h✝ : IsReal ↑x
⊢ 0 < ↑1

Next tactic:
norm_num
theorem unitLattice_span_eq_top :
    Submodule.span ℝ (unitLattice K : Set ({w : InfinitePlace K // w ≠ w₀} → ℝ)) = ⊤ := by
  refine le_antisymm (le_top) ?_
  -- The standard basis
  let B := Pi.basisFun ℝ {w : InfinitePlace K // w ≠ w₀}
  -- The image by log_embedding of the family of units constructed above
  let v := fun w : { w : InfinitePlace K // w ≠ w₀ } => logEmbedding K (exists_unit K w).choose
  -- To prove the result, it is enough to prove that the family `v` is linearly independent
  suffices B.det v ≠ 0 by
    rw [← isUnit_iff_ne_zero, ← is_basis_iff_det] at this
    rw [← this.2]
    exact Submodule.span_monotone (fun _ ⟨w, hw⟩ =>
      ⟨(exists_unit K w).choose, trivial, by rw [← hw]⟩)
  rw [Basis.det_apply]
  -- We use a specific lemma to prove that this determinant is nonzero
  refine det_ne_zero_of_sum_col_lt_diag (fun w => ?_)
  simp_rw [Real.norm_eq_abs, Basis.coePiBasisFun.toMatrix_eq_transpose, Matrix.transpose_apply]
  rw [← sub_pos, sum_congr rfl (fun x hx => abs_of_neg ?_), sum_neg_distrib, sub_neg_eq_add,
    sum_erase_eq_sub (mem_univ _), ← add_comm_sub]
  refine add_pos_of_nonneg_of_pos ?_ ?_
  · rw [sub_nonneg]
    exact le_abs_self _
  · rw [sum_logEmbedding_component (exists_unit K w).choose]
    refine mul_pos_of_neg_of_neg ?_ ((exists_unit K w).choose_spec _ w.prop.symm)
    rw [mult]; split_ifs <;> norm_num
  · refine mul_neg_of_pos_of_neg ?_ ((exists_unit K w).choose_spec x ?_)
    · rw [mult]; split_ifs <;> 

Proof state:
case neg
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
w₁ : InfinitePlace K
B✝ : ℕ
hB : minkowskiBound K < convexBodyLTFactor K * ↑B✝
B : Basis { w // w ≠ w₀ } ℝ ({ w // w ≠ w₀ } → ℝ) := Pi.basisFun ℝ { w // w ≠ w₀ }
v : { w // w ≠ w₀ } → { w // w ≠ w₀ } → ℝ :=
  fun w => (logEmbedding K) (Exists.choose (_ : ∃ u, ∀ (w_1 : InfinitePlace K), w_1 ≠ ↑w → Real.log (w_1 ↑↑u) < 0))
w x : { w // w ≠ w₀ }
hx : x ∈ erase univ w
h✝ : ¬IsReal ↑x
⊢ 0 < ↑2

Next tactic:
norm_num
theorem unitLattice_span_eq_top :
    Submodule.span ℝ (unitLattice K : Set ({w : InfinitePlace K // w ≠ w₀} → ℝ)) = ⊤ := by
  refine le_antisymm (le_top) ?_
  -- The standard basis
  let B := Pi.basisFun ℝ {w : InfinitePlace K // w ≠ w₀}
  -- The image by log_embedding of the family of units constructed above
  let v := fun w : { w : InfinitePlace K // w ≠ w₀ } => logEmbedding K (exists_unit K w).choose
  -- To prove the result, it is enough to prove that the family `v` is linearly independent
  suffices B.det v ≠ 0 by
    rw [← isUnit_iff_ne_zero, ← is_basis_iff_det] at this
    rw [← this.2]
    exact Submodule.span_monotone (fun _ ⟨w, hw⟩ =>
      ⟨(exists_unit K w).choose, trivial, by rw [← hw]⟩)
  rw [Basis.det_apply]
  -- We use a specific lemma to prove that this determinant is nonzero
  refine det_ne_zero_of_sum_col_lt_diag (fun w => ?_)
  simp_rw [Real.norm_eq_abs, Basis.coePiBasisFun.toMatrix_eq_transpose, Matrix.transpose_apply]
  rw [← sub_pos, sum_congr rfl (fun x hx => abs_of_neg ?_), sum_neg_distrib, sub_neg_eq_add,
    sum_erase_eq_sub (mem_univ _), ← add_comm_sub]
  refine add_pos_of_nonneg_of_pos ?_ ?_
  · rw [sub_nonneg]
    exact le_abs_self _
  · rw [sum_logEmbedding_component (exists_unit K w).choose]
    refine mul_pos_of_neg_of_neg ?_ ((exists_unit K w).choose_spec _ w.prop.symm)
    rw [mult]; split_ifs <;> norm_num
  · refine mul_neg_of_pos_of_neg ?_ ((exists_unit K w).choose_spec x ?_)
    · rw [mult]; split_ifs <;> norm_num
    · 

Proof state:
case refine_2
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
w₁ : InfinitePlace K
B✝ : ℕ
hB : minkowskiBound K < convexBodyLTFactor K * ↑B✝
B : Basis { w // w ≠ w₀ } ℝ ({ w // w ≠ w₀ } → ℝ) := Pi.basisFun ℝ { w // w ≠ w₀ }
v : { w // w ≠ w₀ } → { w // w ≠ w₀ } → ℝ :=
  fun w => (logEmbedding K) (Exists.choose (_ : ∃ u, ∀ (w_1 : InfinitePlace K), w_1 ≠ ↑w → Real.log (w_1 ↑↑u) < 0))
w x : { w // w ≠ w₀ }
hx : x ∈ erase univ w
⊢ ↑x ≠ ↑w

Next tactic:
exact Subtype.ext_iff_val.not.mp (ne_of_mem_erase hx)
instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
  

Proof state:
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ DiscreteTopology ↥(unitLattice K)

Next tactic:
refine discreteTopology_of_isOpen_singleton_zero ?_
instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
  refine discreteTopology_of_isOpen_singleton_zero ?_
  

Proof state:
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ IsOpen {0}

Next tactic:
refine isOpen_singleton_of_finite_mem_nhds 0 (s := Metric.closedBall 0 1) ?_ ?_
instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
  refine discreteTopology_of_isOpen_singleton_zero ?_
  refine isOpen_singleton_of_finite_mem_nhds 0 (s := Metric.closedBall 0 1) ?_ ?_
  · 

Proof state:
case refine_1
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ Metric.closedBall 0 1 ∈ nhds 0

Next tactic:
exact Metric.closedBall_mem_nhds _ (by norm_num)
instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
  refine discreteTopology_of_isOpen_singleton_zero ?_
  refine isOpen_singleton_of_finite_mem_nhds 0 (s := Metric.closedBall 0 1) ?_ ?_
  · exact Metric.closedBall_mem_nhds _ (by 

Proof state:
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ 0 < 1

Next tactic:
norm_num
instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
  refine discreteTopology_of_isOpen_singleton_zero ?_
  refine isOpen_singleton_of_finite_mem_nhds 0 (s := Metric.closedBall 0 1) ?_ ?_
  · exact Metric.closedBall_mem_nhds _ (by norm_num)
  · 

Proof state:
case refine_2
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ Set.Finite (Metric.closedBall 0 1)

Next tactic:
refine Set.Finite.of_finite_image ?_ (Set.injOn_of_injective Subtype.val_injective _)
instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
  refine discreteTopology_of_isOpen_singleton_zero ?_
  refine isOpen_singleton_of_finite_mem_nhds 0 (s := Metric.closedBall 0 1) ?_ ?_
  · exact Metric.closedBall_mem_nhds _ (by norm_num)
  · refine Set.Finite.of_finite_image ?_ (Set.injOn_of_injective Subtype.val_injective _)
    

Proof state:
case refine_2
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ Set.Finite (Subtype.val '' Metric.closedBall 0 1)

Next tactic:
convert unitLattice_inter_ball_finite K 1
instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
  refine discreteTopology_of_isOpen_singleton_zero ?_
  refine isOpen_singleton_of_finite_mem_nhds 0 (s := Metric.closedBall 0 1) ?_ ?_
  · exact Metric.closedBall_mem_nhds _ (by norm_num)
  · refine Set.Finite.of_finite_image ?_ (Set.injOn_of_injective Subtype.val_injective _)
    convert unitLattice_inter_ball_finite K 1
    

Proof state:
case h.e'_2
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ Subtype.val '' Metric.closedBall 0 1 = ↑(unitLattice K) ∩ Metric.closedBall 0 1

Next tactic:
ext x
instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
  refine discreteTopology_of_isOpen_singleton_zero ?_
  refine isOpen_singleton_of_finite_mem_nhds 0 (s := Metric.closedBall 0 1) ?_ ?_
  · exact Metric.closedBall_mem_nhds _ (by norm_num)
  · refine Set.Finite.of_finite_image ?_ (Set.injOn_of_injective Subtype.val_injective _)
    convert unitLattice_inter_ball_finite K 1
    ext x
    

Proof state:
case h.e'_2.h
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
x : { w // w ≠ w₀ } → ℝ
⊢ x ∈ Subtype.val '' Metric.closedBall 0 1 ↔ x ∈ ↑(unitLattice K) ∩ Metric.closedBall 0 1

Next tactic:
refine ⟨?_, fun ⟨hx1, hx2⟩ => ⟨⟨x, hx1⟩, hx2, rfl⟩⟩
instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
  refine discreteTopology_of_isOpen_singleton_zero ?_
  refine isOpen_singleton_of_finite_mem_nhds 0 (s := Metric.closedBall 0 1) ?_ ?_
  · exact Metric.closedBall_mem_nhds _ (by norm_num)
  · refine Set.Finite.of_finite_image ?_ (Set.injOn_of_injective Subtype.val_injective _)
    convert unitLattice_inter_ball_finite K 1
    ext x
    refine ⟨?_, fun ⟨hx1, hx2⟩ => ⟨⟨x, hx1⟩, hx2, rfl⟩⟩
    

Proof state:
case h.e'_2.h
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
x : { w // w ≠ w₀ } → ℝ
⊢ x ∈ Subtype.val '' Metric.closedBall 0 1 → x ∈ ↑(unitLattice K) ∩ Metric.closedBall 0 1

Next tactic:
rintro ⟨x, hx, rfl⟩
instance instDiscrete_unitLattice : DiscreteTopology (unitLattice K) := by
  refine discreteTopology_of_isOpen_singleton_zero ?_
  refine isOpen_singleton_of_finite_mem_nhds 0 (s := Metric.closedBall 0 1) ?_ ?_
  · exact Metric.closedBall_mem_nhds _ (by norm_num)
  · refine Set.Finite.of_finite_image ?_ (Set.injOn_of_injective Subtype.val_injective _)
    convert unitLattice_inter_ball_finite K 1
    ext x
    refine ⟨?_, fun ⟨hx1, hx2⟩ => ⟨⟨x, hx1⟩, hx2, rfl⟩⟩
    rintro ⟨x, hx, rfl⟩
    

Proof state:
case h.e'_2.h.intro.intro
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
x : ↥(unitLattice K)
hx : x ∈ Metric.closedBall 0 1
⊢ ↑x ∈ ↑(unitLattice K) ∩ Metric.closedBall 0 1

Next tactic:
exact ⟨Subtype.mem x, hx⟩
protected theorem finrank_eq_rank :
    finrank ℝ ({w : InfinitePlace K // w ≠ w₀} → ℝ) = Units.rank K := by
  

Proof state:
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ finrank ℝ ({ w // w ≠ w₀ } → ℝ) = rank K

Next tactic:
simp only [finrank_fintype_fun_eq_card, Fintype.card_subtype_compl,
    Fintype.card_ofSubsingleton, rank]
@[simp]
theorem unitLattice_rank :
    finrank ℤ (unitLattice K) = Units.rank K := by
  

Proof state:
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ finrank ℤ ↥(unitLattice K) = rank K

Next tactic:
rw [← Units.finrank_eq_rank]
@[simp]
theorem unitLattice_rank :
    finrank ℤ (unitLattice K) = Units.rank K := by
  rw [← Units.finrank_eq_rank]
  

Proof state:
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ finrank ℤ ↥(unitLattice K) = finrank ℝ ({ w // w ≠ w₀ } → ℝ)

Next tactic:
exact Zlattice.rank ℝ (unitLattice_span_eq_top K)
set_option synthInstance.maxHeartbeats 27000 in
/-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive
`ℤ`-module. -/
def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := by
  

Proof state:
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ ↥(unitLattice K) ≃ₗ[ℤ] Additive ((↥(𝓞 K))ˣ ⧸ torsion K)

Next tactic:
refine AddEquiv.toIntLinearEquiv ?_
set_option synthInstance.maxHeartbeats 27000 in
/-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive
`ℤ`-module. -/
def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := by
  refine AddEquiv.toIntLinearEquiv ?_
  

Proof state:
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ ↥(unitLattice K) ≃+ Additive ((↥(𝓞 K))ˣ ⧸ torsion K)

Next tactic:
rw [unitLattice, ← AddMonoidHom.range_eq_map (logEmbedding K)]
set_option synthInstance.maxHeartbeats 27000 in
/-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive
`ℤ`-module. -/
def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := by
  refine AddEquiv.toIntLinearEquiv ?_
  rw [unitLattice, ← AddMonoidHom.range_eq_map (logEmbedding K)]
  

Proof state:
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ ↥(AddMonoidHom.range (logEmbedding K)) ≃+ Additive ((↥(𝓞 K))ˣ ⧸ torsion K)

Next tactic:
refine (QuotientAddGroup.quotientKerEquivRange (logEmbedding K)).symm.trans ?_
set_option synthInstance.maxHeartbeats 27000 in
/-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive
`ℤ`-module. -/
def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := by
  refine AddEquiv.toIntLinearEquiv ?_
  rw [unitLattice, ← AddMonoidHom.range_eq_map (logEmbedding K)]
  refine (QuotientAddGroup.quotientKerEquivRange (logEmbedding K)).symm.trans ?_
  

Proof state:
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ Additive (↥(𝓞 K))ˣ ⧸ AddMonoidHom.ker (logEmbedding K) ≃+ Additive ((↥(𝓞 K))ˣ ⧸ torsion K)

Next tactic:
refine (QuotientAddGroup.quotientAddEquivOfEq ?_).trans
    (QuotientAddGroup.quotientKerEquivOfSurjective
      (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K))) (fun x => ?_))
set_option synthInstance.maxHeartbeats 27000 in
/-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive
`ℤ`-module. -/
def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := by
  refine AddEquiv.toIntLinearEquiv ?_
  rw [unitLattice, ← AddMonoidHom.range_eq_map (logEmbedding K)]
  refine (QuotientAddGroup.quotientKerEquivRange (logEmbedding K)).symm.trans ?_
  refine (QuotientAddGroup.quotientAddEquivOfEq ?_).trans
    (QuotientAddGroup.quotientKerEquivOfSurjective
      (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K))) (fun x => ?_))
  · 

Proof state:
case refine_1
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
⊢ AddMonoidHom.ker (logEmbedding K) = AddMonoidHom.ker (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K)))

Next tactic:
ext
set_option synthInstance.maxHeartbeats 27000 in
/-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive
`ℤ`-module. -/
def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := by
  refine AddEquiv.toIntLinearEquiv ?_
  rw [unitLattice, ← AddMonoidHom.range_eq_map (logEmbedding K)]
  refine (QuotientAddGroup.quotientKerEquivRange (logEmbedding K)).symm.trans ?_
  refine (QuotientAddGroup.quotientAddEquivOfEq ?_).trans
    (QuotientAddGroup.quotientKerEquivOfSurjective
      (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K))) (fun x => ?_))
  · ext
    

Proof state:
case refine_1.h
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
x✝ : Additive (↥(𝓞 K))ˣ
⊢ x✝ ∈ AddMonoidHom.ker (logEmbedding K) ↔ x✝ ∈ AddMonoidHom.ker (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K)))

Next tactic:
rw [MonoidHom.coe_toAdditive_ker, QuotientGroup.ker_mk', AddMonoidHom.mem_ker,
      logEmbedding_eq_zero_iff]
set_option synthInstance.maxHeartbeats 27000 in
/-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive
`ℤ`-module. -/
def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := by
  refine AddEquiv.toIntLinearEquiv ?_
  rw [unitLattice, ← AddMonoidHom.range_eq_map (logEmbedding K)]
  refine (QuotientAddGroup.quotientKerEquivRange (logEmbedding K)).symm.trans ?_
  refine (QuotientAddGroup.quotientAddEquivOfEq ?_).trans
    (QuotientAddGroup.quotientKerEquivOfSurjective
      (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K))) (fun x => ?_))
  · ext
    rw [MonoidHom.coe_toAdditive_ker, QuotientGroup.ker_mk', AddMonoidHom.mem_ker,
      logEmbedding_eq_zero_iff]
    

Proof state:
case refine_1.h
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
x✝ : Additive (↥(𝓞 K))ˣ
⊢ x✝ ∈ torsion K ↔ x✝ ∈ Subgroup.toAddSubgroup (torsion K)

Next tactic:
rfl
set_option synthInstance.maxHeartbeats 27000 in
/-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive
`ℤ`-module. -/
def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := by
  refine AddEquiv.toIntLinearEquiv ?_
  rw [unitLattice, ← AddMonoidHom.range_eq_map (logEmbedding K)]
  refine (QuotientAddGroup.quotientKerEquivRange (logEmbedding K)).symm.trans ?_
  refine (QuotientAddGroup.quotientAddEquivOfEq ?_).trans
    (QuotientAddGroup.quotientKerEquivOfSurjective
      (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K))) (fun x => ?_))
  · ext
    rw [MonoidHom.coe_toAdditive_ker, QuotientGroup.ker_mk', AddMonoidHom.mem_ker,
      logEmbedding_eq_zero_iff]
    rfl
  · 

Proof state:
case refine_2
K : Type u_1
inst✝¹ : Field K
inst✝ : NumberField K
x : Additive ((↥(𝓞 K))ˣ ⧸ torsion K)
⊢ ∃ a, (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K))) a = x

Next tactic:
refine ⟨Additive.ofMul x.out', ?_⟩