/-
Copyright (c) 2020 Joseph Myers. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Joseph Myers
-/
import data.finset.sort
import data.fin.vec_notation
import linear_algebra.affine_space.combination
import linear_algebra.affine_space.affine_equiv
import linear_algebra.basis

/-!
# Affine independence

This file defines affinely independent families of points.

## Main definitions

* `affine_independent` defines affinely independent families of points
  as those where no nontrivial weighted subtraction is `0`.  This is
  proved equivalent to two other formulations: linear independence of
  the results of subtracting a base point in the family from the other
  points in the family, or any equal affine combinations having the
  same weights.  A bundled type `simplex` is provided for finite
  affinely independent families of points, with an abbreviation
  `triangle` for the case of three points.

## References

* https://en.wikipedia.org/wiki/Affine_space

-/

noncomputable theory
open_locale big_operators classical affine
open function

section affine_independent

variables (k : Type*) {V : Type*} {P : Type*} [ring k] [add_comm_group V] [module k V]
variables [affine_space V P] {ι : Type*}
include V

/-- An indexed family is said to be affinely independent if no
nontrivial weighted subtractions (where the sum of weights is 0) are
0. -/
def affine_independent (p : ι → P) : Prop :=
∀ (s : finset ι) (w : ι → k), ∑ i in s, w i = 0 → s.weighted_vsub p w = (0:V) → ∀ i ∈ s, w i = 0

/-- The definition of `affine_independent`. -/
lemma affine_independent_def (p : ι → P) :
  affine_independent k p ↔
    ∀ (s : finset ι) (w : ι → k),
      ∑ i in s, w i = 0 → s.weighted_vsub p w = (0 : V) → ∀ i ∈ s, w i = 0 :=
iff.rfl

/-- A family with at most one point is affinely independent. -/
lemma affine_independent_of_subsingleton [subsingleton ι] (p : ι → P) :
  affine_independent k p :=
λ s w h hs i hi, fintype.eq_of_subsingleton_of_sum_eq h i hi

/-- A family indexed by a `fintype` is affinely independent if and
only if no nontrivial weighted subtractions over `finset.univ` (where
the sum of the weights is 0) are 0. -/
lemma affine_independent_iff_of_fintype [fintype ι] (p : ι → P) :
  affine_independent k p ↔
    ∀ w : ι → k, ∑ i, w i = 0 → finset.univ.weighted_vsub p w = (0 : V) → ∀ i, w i = 0 :=
begin
  split,
  { exact λ h w hw hs i, h finset.univ w hw hs i (finset.mem_univ _) },
  { intros h s w hw hs i hi,
    rw finset.weighted_vsub_indicator_subset _ _ (finset.subset_univ s) at hs,
    rw set.sum_indicator_subset _ (finset.subset_univ s) at hw,
    replace h := h ((↑s : set ι).indicator w) hw hs i,
    simpa [hi] using h }
end

/-- A family is affinely independent if and only if the differences
from a base point in that family are linearly independent. -/
lemma affine_independent_iff_linear_independent_vsub (p : ι → P) (i1 : ι) :
  affine_independent k p ↔ linear_independent k (λ i : {x // x ≠ i1}, (p i -ᵥ p i1 : V)) :=
begin
  split,
  { intro h,
    rw linear_independent_iff',
    intros s g hg i hi,
    set f : ι → k := λ x, if hx : x = i1 then -∑ y in s, g y else g ⟨x, hx⟩ with hfdef,
    let s2 : finset ι := insert i1 (s.map (embedding.subtype _)),
    have hfg : ∀ x : {x // x ≠ i1}, g x = f x,
    { intro x,
      rw hfdef,
      dsimp only [],
      erw [dif_neg x.property, subtype.coe_eta] },
    rw hfg,
    have hf : ∑ ι in s2, f ι = 0,
    { rw [finset.sum_insert (finset.not_mem_map_subtype_of_not_property s (not_not.2 rfl)),
          finset.sum_subtype_map_embedding (λ x hx, (hfg x).symm)],
      rw hfdef,
      dsimp only [],
      rw dif_pos rfl,
      exact neg_add_self _ },
    have hs2 : s2.weighted_vsub p f = (0:V),
    { set f2 : ι → V := λ x, f x • (p x -ᵥ p i1) with hf2def,
      set g2 : {x // x ≠ i1} → V := λ x, g x • (p x -ᵥ p i1) with hg2def,
      have hf2g2 : ∀ x : {x // x ≠ i1}, f2 x = g2 x,
      { simp_rw [hf2def, hg2def, hfg],
        exact λ x, rfl },
      rw [finset.weighted_vsub_eq_weighted_vsub_of_point_of_sum_eq_zero s2 f p hf (p i1),
          finset.weighted_vsub_of_point_insert, finset.weighted_vsub_of_point_apply,
          finset.sum_subtype_map_embedding (λ x hx, hf2g2 x)],
      exact hg },
    exact h s2 f hf hs2 i (finset.mem_insert_of_mem (finset.mem_map.2 ⟨i, hi, rfl⟩)) },
  { intro h,
    rw linear_independent_iff' at h,
    intros s w hw hs i hi,
    rw [finset.weighted_vsub_eq_weighted_vsub_of_point_of_sum_eq_zero s w p hw (p i1),
        ←s.weighted_vsub_of_point_erase w p i1, finset.weighted_vsub_of_point_apply] at hs,
    let f : ι → V := λ i, w i • (p i -ᵥ p i1),
    have hs2 : ∑ i in (s.erase i1).subtype (λ i, i ≠ i1), f i = 0,
    { rw [←hs],
      convert finset.sum_subtype_of_mem f (λ x, finset.ne_of_mem_erase) },
    have h2 := h ((s.erase i1).subtype (λ i, i ≠ i1)) (λ x, w x) hs2,
    simp_rw [finset.mem_subtype] at h2,
    have h2b : ∀ i ∈ s, i ≠ i1 → w i = 0 :=
      λ i his hi, h2 ⟨i, hi⟩ (finset.mem_erase_of_ne_of_mem hi his),
    exact finset.eq_zero_of_sum_eq_zero hw h2b i hi }
end

/-- A set is affinely independent if and only if the differences from
a base point in that set are linearly independent. -/
lemma affine_independent_set_iff_linear_independent_vsub {s : set P} {p₁ : P} (hp₁ : p₁ ∈ s) :
  affine_independent k (λ p, p : s → P) ↔
  linear_independent k (λ v, v : (λ p, (p -ᵥ p₁ : V)) '' (s \ {p₁}) → V) :=
begin
  rw affine_independent_iff_linear_independent_vsub k (λ p, p : s → P) ⟨p₁, hp₁⟩,
  split,
  { intro h,
    have hv : ∀ v : (λ p, (p -ᵥ p₁ : V)) '' (s \ {p₁}), (v : V) +ᵥ p₁ ∈ s \ {p₁} :=
      λ v, (vsub_left_injective p₁).mem_set_image.1
             ((vadd_vsub (v : V) p₁).symm ▸ v.property),
    let f : (λ p : P, (p -ᵥ p₁ : V)) '' (s \ {p₁}) → {x : s // x ≠ ⟨p₁, hp₁⟩} :=
      λ x, ⟨⟨(x : V) +ᵥ p₁, set.mem_of_mem_diff (hv x)⟩,
            λ hx, set.not_mem_of_mem_diff (hv x) (subtype.ext_iff.1 hx)⟩,
    convert h.comp f
      (λ x1 x2 hx, (subtype.ext (vadd_right_cancel p₁ (subtype.ext_iff.1 (subtype.ext_iff.1 hx))))),
    ext v,
    exact (vadd_vsub (v : V) p₁).symm },
  { intro h,
    let f : {x : s // x ≠ ⟨p₁, hp₁⟩} → (λ p : P, (p -ᵥ p₁ : V)) '' (s \ {p₁}) :=
      λ x, ⟨((x : s) : P) -ᵥ p₁, ⟨x, ⟨⟨(x : s).property, λ hx, x.property (subtype.ext hx)⟩, rfl⟩⟩⟩,
    convert h.comp f
      (λ x1 x2 hx, subtype.ext (subtype.ext (vsub_left_cancel (subtype.ext_iff.1 hx)))) }
end

/-- A set of nonzero vectors is linearly independent if and only if,
given a point `p₁`, the vectors added to `p₁` and `p₁` itself are
affinely independent. -/
lemma linear_independent_set_iff_affine_independent_vadd_union_singleton {s : set V}
  (hs : ∀ v ∈ s, v ≠ (0 : V)) (p₁ : P) : linear_independent k (λ v, v : s → V) ↔
  affine_independent k (λ p, p : {p₁} ∪ ((λ v, v +ᵥ p₁) '' s) → P) :=
begin
  rw affine_independent_set_iff_linear_independent_vsub k
    (set.mem_union_left _ (set.mem_singleton p₁)),
  have h : (λ p, (p -ᵥ p₁ : V)) '' (({p₁} ∪ (λ v, v +ᵥ p₁) '' s) \ {p₁}) = s,
  { simp_rw [set.union_diff_left, set.image_diff (vsub_left_injective p₁), set.image_image,
             set.image_singleton, vsub_self, vadd_vsub, set.image_id'],
    exact set.diff_singleton_eq_self (λ h, hs 0 h rfl) },
  rw h
end

/-- A family is affinely independent if and only if any affine
combinations (with sum of weights 1) that evaluate to the same point
have equal `set.indicator`. -/
lemma affine_independent_iff_indicator_eq_of_affine_combination_eq (p : ι → P) :
  affine_independent k p ↔ ∀ (s1 s2 : finset ι) (w1 w2 : ι → k), ∑ i in s1, w1 i = 1 →
    ∑ i in s2, w2 i = 1 → s1.affine_combination p w1 = s2.affine_combination p w2 →
      set.indicator ↑s1 w1 = set.indicator ↑s2 w2 :=
begin
  split,
  { intros ha s1 s2 w1 w2 hw1 hw2 heq,
    ext i,
    by_cases hi : i ∈ (s1 ∪ s2),
    { rw ←sub_eq_zero,
      rw set.sum_indicator_subset _ (finset.subset_union_left s1 s2) at hw1,
      rw set.sum_indicator_subset _ (finset.subset_union_right s1 s2) at hw2,
      have hws : ∑ i in s1 ∪ s2, (set.indicator ↑s1 w1 - set.indicator ↑s2 w2) i = 0,
      { simp [hw1, hw2] },
      rw [finset.affine_combination_indicator_subset _ _ (finset.subset_union_left s1 s2),
          finset.affine_combination_indicator_subset _ _ (finset.subset_union_right s1 s2),
          ←@vsub_eq_zero_iff_eq V, finset.affine_combination_vsub] at heq,
      exact ha (s1 ∪ s2) (set.indicator ↑s1 w1 - set.indicator ↑s2 w2) hws heq i hi },
    { rw [←finset.mem_coe, finset.coe_union] at hi,
      simp [mt (set.mem_union_left ↑s2) hi, mt (set.mem_union_right ↑s1) hi] } },
  { intros ha s w hw hs i0 hi0,
    let w1 : ι → k := function.update (function.const ι 0) i0 1,
    have hw1 : ∑ i in s, w1 i = 1,
    { rw [finset.sum_update_of_mem hi0, finset.sum_const_zero, add_zero] },
    have hw1s : s.affine_combination p w1 = p i0 :=
      s.affine_combination_of_eq_one_of_eq_zero w1 p hi0 (function.update_same _ _ _)
                                                (λ _ _ hne, function.update_noteq hne _ _),
    let w2 := w + w1,
    have hw2 : ∑ i in s, w2 i = 1,
    { simp [w2, finset.sum_add_distrib, hw, hw1] },
    have hw2s : s.affine_combination p w2 = p i0,
    { simp [w2, ←finset.weighted_vsub_vadd_affine_combination, hs, hw1s] },
    replace ha := ha s s w2 w1 hw2 hw1 (hw1s.symm ▸ hw2s),
    have hws : w2 i0 - w1 i0 = 0,
    { rw ←finset.mem_coe at hi0,
      rw [←set.indicator_of_mem hi0 w2, ←set.indicator_of_mem hi0 w1, ha, sub_self] },
    simpa [w2] using hws }
end

/-- A finite family is affinely independent if and only if any affine
combinations (with sum of weights 1) that evaluate to the same point are equal. -/
lemma affine_independent_iff_eq_of_fintype_affine_combination_eq [fintype ι] (p : ι → P) :
  affine_independent k p ↔ ∀ (w1 w2 : ι → k), ∑ i, w1 i = 1 → ∑ i, w2 i = 1 →
    finset.univ.affine_combination p w1 = finset.univ.affine_combination p w2 → w1 = w2 :=
begin
  rw affine_independent_iff_indicator_eq_of_affine_combination_eq,
  split,
  { intros h w1 w2 hw1 hw2 hweq,
    simpa only [set.indicator_univ, finset.coe_univ] using h _ _ w1 w2 hw1 hw2 hweq, },
  { intros h s1 s2 w1 w2 hw1 hw2 hweq,
    have hw1' : ∑ i, (s1 : set ι).indicator w1 i = 1,
    { rwa set.sum_indicator_subset _ (finset.subset_univ s1) at hw1, },
    have hw2' : ∑ i, (s2 : set ι).indicator w2 i = 1,
    { rwa set.sum_indicator_subset _ (finset.subset_univ s2) at hw2, },
    rw [finset.affine_combination_indicator_subset w1 p (finset.subset_univ s1),
        finset.affine_combination_indicator_subset w2 p (finset.subset_univ s2)] at hweq,
    exact h _ _ hw1' hw2' hweq, },
end

variables {k}

/-- If we single out one member of an affine-independent family of points and affinely transport
all others along the line joining them to this member, the resulting new family of points is affine-
independent.

This is the affine version of `linear_independent.units_smul`. -/
lemma affine_independent.units_line_map
  {p : ι → P} (hp : affine_independent k p) (j : ι) (w : ι → units k) :
  affine_independent k (λ i, affine_map.line_map (p j) (p i) (w i : k)) :=
begin
  rw affine_independent_iff_linear_independent_vsub k _ j at hp ⊢,
  simp only [affine_map.line_map_vsub_left, affine_map.coe_const, affine_map.line_map_same],
  exact hp.units_smul (λ i, w i),
end

lemma affine_independent.indicator_eq_of_affine_combination_eq {p : ι → P}
  (ha : affine_independent k p) (s₁ s₂ : finset ι) (w₁ w₂ : ι → k) (hw₁ : ∑ i in s₁, w₁ i = 1)
  (hw₂ : ∑ i in s₂, w₂ i = 1) (h : s₁.affine_combination p w₁ = s₂.affine_combination p w₂) :
  set.indicator ↑s₁ w₁ = set.indicator ↑s₂ w₂ :=
(affine_independent_iff_indicator_eq_of_affine_combination_eq k p).1 ha s₁ s₂ w₁ w₂ hw₁ hw₂ h

/-- An affinely independent family is injective, if the underlying
ring is nontrivial. -/
protected lemma affine_independent.injective [nontrivial k] {p : ι → P}
  (ha : affine_independent k p) :
  function.injective p :=
begin
  intros i j hij,
  rw affine_independent_iff_linear_independent_vsub _ _ j at ha,
  by_contra hij',
  exact ha.ne_zero ⟨i, hij'⟩ (vsub_eq_zero_iff_eq.mpr hij)
end

/-- If a family is affinely independent, so is any subfamily given by
composition of an embedding into index type with the original
family. -/
lemma affine_independent.comp_embedding {ι2 : Type*} (f : ι2 ↪ ι) {p : ι → P}
    (ha : affine_independent k p) : affine_independent k (p ∘ f) :=
begin
  intros fs w hw hs i0 hi0,
  let fs' := fs.map f,
  let w' := λ i, if h : ∃ i2, f i2 = i then w h.some else 0,
  have hw' : ∀ i2 : ι2, w' (f i2) = w i2,
  { intro i2,
    have h : ∃ i : ι2, f i = f i2 := ⟨i2, rfl⟩,
    have hs : h.some = i2 := f.injective h.some_spec,
    simp_rw [w', dif_pos h, hs] },
  have hw's : ∑ i in fs', w' i = 0,
  { rw [←hw, finset.sum_map],
    simp [hw'] },
  have hs' : fs'.weighted_vsub p w' = (0:V),
  { rw [←hs, finset.weighted_vsub_map],
    congr' with i,
    simp [hw'] },
  rw [←ha fs' w' hw's hs' (f i0) ((finset.mem_map' _).2 hi0), hw']
end

/-- If a family is affinely independent, so is any subfamily indexed
by a subtype of the index type. -/
protected lemma affine_independent.subtype {p : ι → P}
    (ha : affine_independent k p) (s : set ι) : affine_independent k (λ i : s, p i) :=
ha.comp_embedding (embedding.subtype _)

/-- If an indexed family of points is affinely independent, so is the
corresponding set of points. -/
protected lemma affine_independent.range {p : ι → P} (ha : affine_independent k p) :
  affine_independent k (λ x, x : set.range p → P) :=
begin
  let f : set.range p → ι := λ x, x.property.some,
  have hf : ∀ x, p (f x) = x := λ x, x.property.some_spec,
  let fe : set.range p ↪ ι := ⟨f, λ x₁ x₂ he, subtype.ext (hf x₁ ▸ hf x₂ ▸ he ▸ rfl)⟩,
  convert ha.comp_embedding fe,
  ext,
  simp [hf]
end

lemma affine_independent_equiv {ι' : Type*} (e : ι ≃ ι') {p : ι' → P} :
  affine_independent k (p ∘ e) ↔ affine_independent k p :=
begin
  refine ⟨_, affine_independent.comp_embedding e.to_embedding⟩,
  intros h,
  have : p = p ∘ e ∘ e.symm.to_embedding, { ext, simp, },
  rw this,
  exact h.comp_embedding e.symm.to_embedding,
end

/-- If a set of points is affinely independent, so is any subset. -/
protected lemma affine_independent.mono {s t : set P}
  (ha : affine_independent k (λ x, x : t → P)) (hs : s ⊆ t) :
  affine_independent k (λ x, x : s → P) :=
ha.comp_embedding (s.embedding_of_subset t hs)

/-- If the range of an injective indexed family of points is affinely
independent, so is that family. -/
lemma affine_independent.of_set_of_injective {p : ι → P}
  (ha : affine_independent k (λ x, x : set.range p → P)) (hi : function.injective p) :
  affine_independent k p :=
ha.comp_embedding
  (⟨λ i, ⟨p i, set.mem_range_self _⟩, λ x y h, hi (subtype.mk_eq_mk.1 h)⟩ : ι ↪ set.range p)

section composition

variables {V₂ P₂ : Type*} [add_comm_group V₂] [module k V₂] [affine_space V₂ P₂]
include V₂

/-- If the image of a family of points in affine space under an affine transformation is affine-
independent, then the original family of points is also affine-independent. -/
lemma affine_independent.of_comp {p : ι → P} (f : P →ᵃ[k] P₂) (hai : affine_independent k (f ∘ p)) :
  affine_independent k p :=
begin
  cases is_empty_or_nonempty ι with h h, { haveI := h, apply affine_independent_of_subsingleton, },
  obtain ⟨i⟩ := h,
  rw affine_independent_iff_linear_independent_vsub k p i,
  simp_rw [affine_independent_iff_linear_independent_vsub k (f ∘ p) i, function.comp_app,
    ← f.linear_map_vsub] at hai,
  exact linear_independent.of_comp f.linear hai,
end

/-- The image of a family of points in affine space, under an injective affine transformation, is
affine-independent. -/
lemma affine_independent.map'
  {p : ι → P} (hai : affine_independent k p) (f : P →ᵃ[k] P₂) (hf : function.injective f) :
  affine_independent k (f ∘ p) :=
begin
  cases is_empty_or_nonempty ι with h h, { haveI := h, apply affine_independent_of_subsingleton, },
  obtain ⟨i⟩ := h,
  rw affine_independent_iff_linear_independent_vsub k p i at hai,
  simp_rw [affine_independent_iff_linear_independent_vsub k (f ∘ p) i, function.comp_app,
    ← f.linear_map_vsub],
  have hf' : f.linear.ker = ⊥, { rwa [linear_map.ker_eq_bot, f.injective_iff_linear_injective], },
  exact linear_independent.map' hai f.linear hf',
end

/-- Injective affine maps preserve affine independence. -/
lemma affine_map.affine_independent_iff {p : ι → P} (f : P →ᵃ[k] P₂) (hf : function.injective f) :
  affine_independent k (f ∘ p) ↔ affine_independent k p :=
⟨affine_independent.of_comp f, λ hai, affine_independent.map' hai f hf⟩

/-- Affine equivalences preserve affine independence of families of points. -/
lemma affine_equiv.affine_independent_iff {p : ι → P} (e : P ≃ᵃ[k] P₂) :
  affine_independent k (e ∘ p) ↔ affine_independent k p :=
e.to_affine_map.affine_independent_iff e.to_equiv.injective

/-- Affine equivalences preserve affine independence of subsets. -/
lemma affine_equiv.affine_independent_set_of_eq_iff {s : set P} (e : P ≃ᵃ[k] P₂) :
  affine_independent k (coe : (e '' s) → P₂) ↔ affine_independent k (coe : s → P) :=
begin
  have : e ∘ (coe : s → P) = (coe : e '' s → P₂) ∘ ((e : P ≃ P₂).image s) := rfl,
  rw [← e.affine_independent_iff, this, affine_independent_equiv],
end

end composition

/-- If a family is affinely independent, and the spans of points
indexed by two subsets of the index type have a point in common, those
subsets of the index type have an element in common, if the underlying
ring is nontrivial. -/
lemma affine_independent.exists_mem_inter_of_exists_mem_inter_affine_span [nontrivial k]
    {p : ι → P} (ha : affine_independent k p) {s1 s2 : set ι} {p0 : P}
    (hp0s1 : p0 ∈ affine_span k (p '' s1)) (hp0s2 : p0 ∈ affine_span k (p '' s2)):
  ∃ (i : ι), i ∈ s1 ∩ s2 :=
begin
  rw set.image_eq_range at hp0s1 hp0s2,
  rw [mem_affine_span_iff_eq_affine_combination,
      ←finset.eq_affine_combination_subset_iff_eq_affine_combination_subtype] at hp0s1 hp0s2,
  rcases hp0s1 with ⟨fs1, hfs1, w1, hw1, hp0s1⟩,
  rcases hp0s2 with ⟨fs2, hfs2, w2, hw2, hp0s2⟩,
  rw affine_independent_iff_indicator_eq_of_affine_combination_eq at ha,
  replace ha := ha fs1 fs2 w1 w2 hw1 hw2 (hp0s1 ▸ hp0s2),
  have hnz : ∑ i in fs1, w1 i ≠ 0 := hw1.symm ▸ one_ne_zero,
  rcases finset.exists_ne_zero_of_sum_ne_zero hnz with ⟨i, hifs1, hinz⟩,
  simp_rw [←set.indicator_of_mem (finset.mem_coe.2 hifs1) w1, ha] at hinz,
  use [i, hfs1 hifs1, hfs2 (set.mem_of_indicator_ne_zero hinz)]
end

/-- If a family is affinely independent, the spans of points indexed
by disjoint subsets of the index type are disjoint, if the underlying
ring is nontrivial. -/
lemma affine_independent.affine_span_disjoint_of_disjoint [nontrivial k] {p : ι → P}
    (ha : affine_independent k p) {s1 s2 : set ι} (hd : s1 ∩ s2 = ∅) :
  (affine_span k (p '' s1) : set P) ∩ affine_span k (p '' s2) = ∅ :=
begin
  by_contradiction hne,
  change (affine_span k (p '' s1) : set P) ∩ affine_span k (p '' s2) ≠ ∅ at hne,
  rw set.ne_empty_iff_nonempty at hne,
  rcases hne with ⟨p0, hp0s1, hp0s2⟩,
  cases ha.exists_mem_inter_of_exists_mem_inter_affine_span hp0s1 hp0s2 with i hi,
  exact set.not_mem_empty i (hd ▸ hi)
end

/-- If a family is affinely independent, a point in the family is in
the span of some of the points given by a subset of the index type if
and only if that point's index is in the subset, if the underlying
ring is nontrivial. -/
@[simp] protected lemma affine_independent.mem_affine_span_iff [nontrivial k] {p : ι → P}
    (ha : affine_independent k p) (i : ι) (s : set ι) :
  p i ∈ affine_span k (p '' s) ↔ i ∈ s :=
begin
  split,
  { intro hs,
    have h := affine_independent.exists_mem_inter_of_exists_mem_inter_affine_span
      ha hs (mem_affine_span k (set.mem_image_of_mem _ (set.mem_singleton _))),
    rwa [←set.nonempty_def, set.inter_singleton_nonempty] at h },
  { exact λ h, mem_affine_span k (set.mem_image_of_mem p h) }
end

/-- If a family is affinely independent, a point in the family is not
in the affine span of the other points, if the underlying ring is
nontrivial. -/
lemma affine_independent.not_mem_affine_span_diff [nontrivial k] {p : ι → P}
    (ha : affine_independent k p) (i : ι) (s : set ι) :
  p i ∉ affine_span k (p '' (s \ {i})) :=
by simp [ha]

lemma exists_nontrivial_relation_sum_zero_of_not_affine_ind
  {t : finset V} (h : ¬ affine_independent k (coe : t → V)) :
  ∃ f : V → k, ∑ e in t, f e • e = 0 ∧ ∑ e in t, f e = 0 ∧ ∃ x ∈ t, f x ≠ 0 :=
begin
  classical,
  rw affine_independent_iff_of_fintype at h,
  simp only [exists_prop, not_forall] at h,
  obtain ⟨w, hw, hwt, i, hi⟩ := h,
  simp only [finset.weighted_vsub_eq_weighted_vsub_of_point_of_sum_eq_zero _ w (coe : t → V) hw 0,
    vsub_eq_sub, finset.weighted_vsub_of_point_apply, sub_zero] at hwt,
  let f : Π (x : V), x ∈ t → k := λ x hx, w ⟨x, hx⟩,
  refine ⟨λ x, if hx : x ∈ t then f x hx else (0 : k), _, _, by { use i, simp [hi, f], }⟩,
  suffices : ∑ (e : V) in t, dite (e ∈ t) (λ hx, (f e hx) • e) (λ hx, 0) = 0,
  { convert this, ext, by_cases hx : x ∈ t; simp [hx], },
  all_goals
  { simp only [finset.sum_dite_of_true (λx h, h), subtype.val_eq_coe, finset.mk_coe, f, hwt, hw], },
end

end affine_independent

section division_ring

variables {k : Type*} {V : Type*} {P : Type*} [division_ring k] [add_comm_group V] [module k V]
variables [affine_space V P] {ι : Type*}
include V

/-- An affinely independent set of points can be extended to such a
set that spans the whole space. -/
lemma exists_subset_affine_independent_affine_span_eq_top {s : set P}
  (h : affine_independent k (λ p, p : s → P)) :
  ∃ t : set P, s ⊆ t ∧ affine_independent k (λ p, p : t → P) ∧ affine_span k t = ⊤ :=
begin
  rcases s.eq_empty_or_nonempty with rfl | ⟨p₁, hp₁⟩,
  { have p₁ : P := add_torsor.nonempty.some,
    let hsv := basis.of_vector_space k V,
    have hsvi := hsv.linear_independent,
    have hsvt := hsv.span_eq,
    rw basis.coe_of_vector_space at hsvi hsvt,
    have h0 : ∀ v : V, v ∈ (basis.of_vector_space_index _ _) → v ≠ 0,
    { intros v hv, simpa using hsv.ne_zero ⟨v, hv⟩ },
    rw linear_independent_set_iff_affine_independent_vadd_union_singleton k h0 p₁ at hsvi,
    exact ⟨{p₁} ∪ (λ v, v +ᵥ p₁) '' _, set.empty_subset _, hsvi,
         affine_span_singleton_union_vadd_eq_top_of_span_eq_top p₁ hsvt⟩ },
  { rw affine_independent_set_iff_linear_independent_vsub k hp₁ at h,
    let bsv := basis.extend h,
    have hsvi := bsv.linear_independent,
    have hsvt := bsv.span_eq,
    rw basis.coe_extend at hsvi hsvt,
    have hsv := h.subset_extend (set.subset_univ _),
    have h0 : ∀ v : V, v ∈ (h.extend _) → v ≠ 0,
    { intros v hv, simpa using bsv.ne_zero ⟨v, hv⟩ },
    rw linear_independent_set_iff_affine_independent_vadd_union_singleton k h0 p₁ at hsvi,
    refine ⟨{p₁} ∪ (λ v, v +ᵥ p₁) '' h.extend (set.subset_univ _), _, _⟩,
    { refine set.subset.trans _ (set.union_subset_union_right _ (set.image_subset _ hsv)),
      simp [set.image_image] },
    { use [hsvi, affine_span_singleton_union_vadd_eq_top_of_span_eq_top p₁ hsvt] } }
end

variables (k V)

lemma exists_affine_independent (s : set P) :
  ∃ t ⊆ s, affine_span k t = affine_span k s ∧ affine_independent k (coe : t → P) :=
begin
  rcases s.eq_empty_or_nonempty with rfl | ⟨p, hp⟩,
  { exact ⟨∅, set.empty_subset ∅, rfl, affine_independent_of_subsingleton k _⟩, },
  obtain ⟨b, hb₁, hb₂, hb₃⟩ := exists_linear_independent k ((equiv.vadd_const p).symm '' s),
  have hb₀ : ∀ (v : V), v ∈ b → v ≠ 0, { exact λ v hv, hb₃.ne_zero (⟨v, hv⟩ : b), },
  rw linear_independent_set_iff_affine_independent_vadd_union_singleton k hb₀ p at hb₃,
  refine ⟨{p} ∪ (equiv.vadd_const p) '' b, _, _, hb₃⟩,
  { apply set.union_subset (set.singleton_subset_iff.mpr hp),
    rwa ← (equiv.vadd_const p).subset_image' b s, },
  { rw [equiv.coe_vadd_const_symm, ← vector_span_eq_span_vsub_set_right k hp] at hb₂,
    apply affine_subspace.ext_of_direction_eq,
    { have : submodule.span k b = submodule.span k (insert 0 b), { by simp, },
      simp only [direction_affine_span, ← hb₂, equiv.coe_vadd_const, set.singleton_union,
        vector_span_eq_span_vsub_set_right k (set.mem_insert p _), this],
      congr,
      change (equiv.vadd_const p).symm '' insert p ((equiv.vadd_const p) '' b) = _,
      rw [set.image_insert_eq, ← set.image_comp],
      simp, },
    { use p,
      simp only [equiv.coe_vadd_const, set.singleton_union, set.mem_inter_eq, coe_affine_span],
      exact ⟨mem_span_points k _ _ (set.mem_insert p _), mem_span_points k _ _ hp⟩, }, },
end

variables (k) {V P}

/-- Two different points are affinely independent. -/
lemma affine_independent_of_ne {p₁ p₂ : P} (h : p₁ ≠ p₂) : affine_independent k ![p₁, p₂] :=
begin
  rw affine_independent_iff_linear_independent_vsub k ![p₁, p₂] 0,
  let i₁ : {x // x ≠ (0 : fin 2)} := ⟨1, by norm_num⟩,
  have he' : ∀ i, i = i₁,
  { rintro ⟨i, hi⟩,
    ext,
    fin_cases i,
    { simpa using hi } },
  haveI : unique {x // x ≠ (0 : fin 2)} := ⟨⟨i₁⟩, he'⟩,
  have hz : (![p₁, p₂] ↑(default {x // x ≠ (0 : fin 2)}) -ᵥ ![p₁, p₂] 0 : V) ≠ 0,
  { rw he' (default _), simp, cc },
  exact linear_independent_unique _ hz
end

end division_ring

namespace affine

variables (k : Type*) {V : Type*} (P : Type*) [ring k] [add_comm_group V] [module k V]
variables [affine_space V P]
include V

/-- A `simplex k P n` is a collection of `n + 1` affinely
independent points. -/
structure simplex (n : ℕ) :=
(points : fin (n + 1) → P)
(independent : affine_independent k points)

/-- A `triangle k P` is a collection of three affinely independent points. -/
abbreviation triangle := simplex k P 2

namespace simplex

variables {P}

/-- Construct a 0-simplex from a point. -/
def mk_of_point (p : P) : simplex k P 0 :=
⟨λ _, p, affine_independent_of_subsingleton k _⟩

/-- The point in a simplex constructed with `mk_of_point`. -/
@[simp] lemma mk_of_point_points (p : P) (i : fin 1) : (mk_of_point k p).points i = p :=
rfl

instance [inhabited P] : inhabited (simplex k P 0) :=
⟨mk_of_point k $ default P⟩

instance nonempty : nonempty (simplex k P 0) :=
⟨mk_of_point k $ add_torsor.nonempty.some⟩

variables {k V}

/-- Two simplices are equal if they have the same points. -/
@[ext] lemma ext {n : ℕ} {s1 s2 : simplex k P n} (h : ∀ i, s1.points i = s2.points i) :
  s1 = s2 :=
begin
  cases s1,
  cases s2,
  congr' with i,
  exact h i
end

/-- Two simplices are equal if and only if they have the same points. -/
lemma ext_iff {n : ℕ} (s1 s2 : simplex k P n): s1 = s2 ↔ ∀ i, s1.points i = s2.points i :=
⟨λ h _, h ▸ rfl, ext⟩

/-- A face of a simplex is a simplex with the given subset of
points. -/
def face {n : ℕ} (s : simplex k P n) {fs : finset (fin (n + 1))} {m : ℕ} (h : fs.card = m + 1) :
  simplex k P m :=
⟨s.points ∘ fs.order_emb_of_fin h,
  s.independent.comp_embedding (fs.order_emb_of_fin h).to_embedding⟩

/-- The points of a face of a simplex are given by `mono_of_fin`. -/
lemma face_points {n : ℕ} (s : simplex k P n) {fs : finset (fin (n + 1))} {m : ℕ}
  (h : fs.card = m + 1) (i : fin (m + 1)) :
  (s.face h).points i = s.points (fs.order_emb_of_fin h i) :=
rfl

/-- The points of a face of a simplex are given by `mono_of_fin`. -/
lemma face_points' {n : ℕ} (s : simplex k P n) {fs : finset (fin (n + 1))} {m : ℕ}
  (h : fs.card = m + 1) : (s.face h).points = s.points ∘ (fs.order_emb_of_fin h) :=
rfl

/-- A single-point face equals the 0-simplex constructed with
`mk_of_point`. -/
@[simp] lemma face_eq_mk_of_point {n : ℕ} (s : simplex k P n) (i : fin (n + 1)) :
  s.face (finset.card_singleton i) = mk_of_point k (s.points i) :=
by { ext, simp [face_points] }

/-- The set of points of a face. -/
@[simp] lemma range_face_points {n : ℕ} (s : simplex k P n) {fs : finset (fin (n + 1))}
  {m : ℕ} (h : fs.card = m + 1) : set.range (s.face h).points = s.points '' ↑fs :=
by rw [face_points', set.range_comp, finset.range_order_emb_of_fin]

end simplex

end affine

namespace affine
namespace simplex

variables {k : Type*} {V : Type*} {P : Type*} [division_ring k]
          [add_comm_group V] [module k V] [affine_space V P]
include V

/-- The centroid of a face of a simplex as the centroid of a subset of
the points. -/
@[simp] lemma face_centroid_eq_centroid {n : ℕ} (s : simplex k P n) {fs : finset (fin (n + 1))}
  {m : ℕ} (h : fs.card = m + 1) :
  finset.univ.centroid k (s.face h).points = fs.centroid k s.points :=
begin
  convert (finset.univ.centroid_map k (fs.order_emb_of_fin h).to_embedding s.points).symm,
  rw [← finset.coe_inj, finset.coe_map, finset.coe_univ, set.image_univ],
  simp
end

/-- Over a characteristic-zero division ring, the centroids given by
two subsets of the points of a simplex are equal if and only if those
faces are given by the same subset of points. -/
@[simp] lemma centroid_eq_iff [char_zero k] {n : ℕ} (s : simplex k P n)
  {fs₁ fs₂ : finset (fin (n + 1))} {m₁ m₂ : ℕ} (h₁ : fs₁.card = m₁ + 1) (h₂ : fs₂.card = m₂ + 1) :
  fs₁.centroid k s.points = fs₂.centroid k s.points ↔ fs₁ = fs₂ :=
begin
  split,
  { intro h,
    rw [finset.centroid_eq_affine_combination_fintype,
        finset.centroid_eq_affine_combination_fintype] at h,
    have ha := (affine_independent_iff_indicator_eq_of_affine_combination_eq k s.points).1
      s.independent _ _ _ _ (fs₁.sum_centroid_weights_indicator_eq_one_of_card_eq_add_one k h₁)
      (fs₂.sum_centroid_weights_indicator_eq_one_of_card_eq_add_one k h₂) h,
    simp_rw [finset.coe_univ, set.indicator_univ, function.funext_iff,
             finset.centroid_weights_indicator_def, finset.centroid_weights, h₁, h₂] at ha,
    ext i,
    replace ha := ha i,
    split,
    all_goals
    { intro hi,
      by_contradiction hni,
      simp [hi, hni] at ha,
      norm_cast at ha } },
  { intro h,
    have hm : m₁ = m₂,
    { subst h,
      simpa [h₁] using h₂ },
    subst hm,
    congr,
    exact h }
end

/-- Over a characteristic-zero division ring, the centroids of two
faces of a simplex are equal if and only if those faces are given by
the same subset of points. -/
lemma face_centroid_eq_iff [char_zero k] {n : ℕ} (s : simplex k P n)
  {fs₁ fs₂ : finset (fin (n + 1))} {m₁ m₂ : ℕ} (h₁ : fs₁.card = m₁ + 1) (h₂ : fs₂.card = m₂ + 1) :
  finset.univ.centroid k (s.face h₁).points = finset.univ.centroid k (s.face h₂).points ↔
    fs₁ = fs₂ :=
begin
  rw [face_centroid_eq_centroid, face_centroid_eq_centroid],
  exact s.centroid_eq_iff h₁ h₂
end

/-- Two simplices with the same points have the same centroid. -/
lemma centroid_eq_of_range_eq {n : ℕ} {s₁ s₂ : simplex k P n}
  (h : set.range s₁.points = set.range s₂.points) :
  finset.univ.centroid k s₁.points = finset.univ.centroid k s₂.points :=
begin
  rw [←set.image_univ, ←set.image_univ, ←finset.coe_univ] at h,
  exact finset.univ.centroid_eq_of_inj_on_of_image_eq k _
    (λ _ _ _ _ he, affine_independent.injective s₁.independent he)
    (λ _ _ _ _ he, affine_independent.injective s₂.independent he) h
end

end simplex
end affine


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

--OUTPUT 1
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  -- Let $\alpha$ be an irrational number. Then for distinct $i, j \in \mathbb{Z}$, we must have $\{i \alpha\} \neq\{j \alpha\}$. If this were not true, then
  have h1 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ≠ int.fract (α * ↑j), from
    assume (i j : ℤ) (hij : i ≠ j),
    have h2 : α * ↑i ≠ α * ↑j, from by {
      assume h3 : α * ↑i = α * ↑j,
      have h4 : α = (int.fract (α * ↑i) - int.fract (α * ↑j)) / (i - j), from by {
        rw [h3,int.fract_add,int.fract_add,int.fract_neg,int.fract_mul,int.fract_eq_zero], ring,
      },
      show false, from by {exact hα_irrat h4,},
    },
    have h5 : int.fract (α * ↑i) = int.fract (α * ↑j), from by {exact int.fract_eq_of_mul_eq_mul_right h2,},
    show int.fract (α * ↑i) ≠ int.fract (α * ↑j), from by {exact h5.symm.ne.symm,},
    -- Hence, $S:=\{\{i \alpha\} \mid i \in \mathbb{Z}\}$ is an infinite subset of $\left[0,1\right]$.
  have h6 : ∀ m : ℤ, int.fract (α * ↑m) ∈ set.Icc 0 1, from
    assume (m : ℤ), int.fract_range_iff.2 ⟨int.fract_nonneg (α * ↑m),int.fract_lt_one (α * ↑m)⟩,
  have h7 : (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ⊆ set.Icc 0 1, from set.image_subset_iff.2 h6,
  have h8 : (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ≠ ∅, from by {
    have h9 : ∀ m : ℤ, int.fract (α * ↑m) ∈ set.Icc 0 1, from assume (m : ℤ), int.fract_range_iff.2 ⟨int.fract_nonneg (α * ↑m),int.fract_lt_one (α * ↑m)⟩,
    have h10 : (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ⊆ set.Icc 0 1, from set.image_subset_iff.2 h9,
    show (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ≠ ∅, from set.nonempty_image h10,
  },
  have h11 : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) ⊆ set.Icc 0 1, from by {
    apply closure_mono, exact h7,
  },
  have h12 : (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ⊆ closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)), from by {
    apply closure_subset,
  },
  have h13 : (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ⊆ set.Icc 0 1, from by {
    apply set.subset.trans h12,
    apply h11,
  },
  -- By the Bolzano-Weierstrass theorem, $S$ has a limit point in $[0, 1]$. One can thus find pairs of elements of $S$ that are arbitrarily close. Since (the absolute value of) the difference of any two elements of $S$ is also an element of $S$, it follows that $0$ is a limit point of $S$.
  have h14 : ∃ r : ℝ, r ∈ set.Icc 0 1 ∧ r ∈ closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)), from by {
    apply set.bounded_closed_iff.2 h8,
    apply h11,
  },
  cases h14 with r hr,
  have h15 : ∀ ε : ℝ, ε > 0 → ∃ x y : ℤ, x ≠ y ∧ (int.fract (α * ↑x) - int.fract (α * ↑y)) = -r + (r + ε), from by {
    assume (ε : ℝ) (hε : ε > 0),
    have h16 : ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc (r - ε/2) (r + ε/2), from by {
      have h17 : ∃ x : ℤ, int.fract (α * ↑x) ∈ set.Icc 0 1, from by {
        have h18 : ∃ x : ℤ, int.fract (α * ↑x) ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ), from by {
          have h19 : ∃ x : ℤ, int.fract (α * ↑x) ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ∩ set.Icc 0 1, from by {
            have h20 : ∃ x : ℤ, int.fract (α * ↑x) ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ∩ set.Icc (r - ε/2) (r + ε/2), from by {
              have h21 : ∃ x : ℤ, int.fract (α * ↑x) ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ∩ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ), from by {
                have h22 : ∃ x : ℤ, int.fract (α * ↑x) ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ∩ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ∩ set.Icc (r - ε/2) (r + ε/2), from by {
                  have h23 : ∃ x : ℤ, int.fract (α * ↑x) ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ∩ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ∩ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ), from by {
                    have h24 : ∃ x : ℤ, int.fract (α * ↑x) ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ∩ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ∩ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ∩ set.Icc (r - ε/2) (
end --Needs more than 2000 tokens!

--OUTPUT 2
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  -- let α be an irrational number
  assume (α : ℝ) (hα_irrat : irrational α),
  have h1 : ∀ (i j : ℤ), i ≠ j → int.fract (α * ↑i) ≠ int.fract (α * ↑j), from by {
    assume (i j : ℤ) (hneq : i ≠ j),
    have h2 : ∀ (i j : ℤ), i ≠ j → (0 ≤ int.fract (α * ↑i)) ∧ (int.fract (α * ↑i) < 1) ∧ (0 ≤ int.fract (α * ↑j)) ∧ (int.fract (α * ↑j) < 1), from by {
      assume (i j : ℤ) (hneq : i ≠ j),
      have h3 : ∀ (i j : ℤ), 0 ≤ int.fract (α * ↑i) ∧ int.fract (α * ↑i) < 1, from by {
        assume (i j : ℤ),
        have h4 : 0 ≤ int.fract (α * ↑i), from by apply int.fract_nonneg,
        have h5 : int.fract (α * ↑i) < 1, from by apply int.fract_lt_one,
        show 0 ≤ int.fract (α * ↑i) ∧ int.fract (α * ↑i) < 1, from by {split,exact h4,exact h5},
      },
      show (0 ≤ int.fract (α * ↑i)) ∧ (int.fract (α * ↑i) < 1) ∧ (0 ≤ int.fract (α * ↑j)) ∧ (int.fract (α * ↑j) < 1), from by {
        split,
        show (0 ≤ int.fract (α * ↑i)) ∧ (int.fract (α * ↑i) < 1), from by {
          apply h3 i j,
        },
        show (0 ≤ int.fract (α * ↑j)) ∧ (int.fract (α * ↑j) < 1), from by {
          apply h3 j i,
        },
      },
    },
    have h6 : ∀ (i j : ℤ), i ≠ j → ¬((α * ↑i - (int.fract (α * ↑i))) = (α * ↑j - (int.fract (α * ↑j)))), from by {
      assume (i j : ℤ) (hneq : i ≠ j),
      assume hcontra : (α * ↑i - (int.fract (α * ↑i))) = (α * ↑j - (int.fract (α * ↑j))),
      have h7 : 0 ≤ int.fract (α * ↑i) ∧ int.fract (α * ↑i) < 1 ∧ 0 ≤ int.fract (α * ↑j) ∧ int.fract (α * ↑j) < 1, from by apply h2 i j hneq,
      have h8 : α = ((int.fract (α * ↑i)) - (int.fract (α * ↑j))) / (↑i - ↑j), from by {
        rw [← hcontra, int.fract_add, int.fract_neg, int.fract_mul],
        ring,
      },
      have h9 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j))), from by {
        rw int.fract_eq_of_nat_abs,
        ring,
      },
      have h10 : (int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j))) < 1, from by {
        rw h9,
        rw int.nat_abs_of_nonneg h7.left,
        rw int.nat_abs_of_nonneg h7.right.left,
        exact int.lt_sub_left_of_add_lt h7.right.right,
      },
      have h11 : 0 ≤ int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j)), from by {
        rw int.nat_abs_of_nonneg h7.left,
        rw int.nat_abs_of_nonneg h7.right.left,
        exact int.sub_nonneg_of_le h7.left h7.right.left,
      },
      have h12 : ¬(α ∈ ℚ), from by {
        apply irrational_iff_not_rat.mpr hα_irrat,
        show α ∈ ℚ, from by {
          apply rat.mk_of_rat,
          have h13 : (int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j))) / (int.nat_abs (↑i - ↑j)) ∈ ℚ, from by {
            apply mk_rat_of_int,
            from exists_eq_mul_left_of_dvd (by rw int.nat_abs_of_nonneg;
              exact int.sub_nonneg_of_le (by apply int.le_of_lt_succ;
              exact int.lt_add_one_of_le (by rw int.coe_nat_dvd;
              exact int.coe_nat_dvd.mpr (int.lt_succ_self _)))
              (by apply int.le_of_lt_succ;
              exact int.lt_add_one_of_le (by rw int.coe_nat_dvd;
              exact int.coe_nat_dvd.mpr (int.lt_succ_self _))))),
            show (int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j))) / (int.nat_abs (↑i - ↑j)) ∈ ℚ, from by rw h13,
          },
          have h14 : (int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j))) / (int.nat_abs (↑i - ↑j)) = (int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j))) / (int.nat_abs (↑i - ↑j)), from by {
            rw ← h13,
            show (int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j))) / (int.nat_abs (↑i - ↑j)) = (int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j))) / (int.nat_abs (↑i - ↑j)), from by refl,
          },
          have h15 : (int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j))) / (int.nat_abs (↑i - ↑j)) = (int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j))) / (int.nat_abs (↑i - ↑j)), from by {
            rw ← h14,
            show (int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j))) / (int.nat_abs (↑i - ↑j)) = (int.nat_abs (int.fract (α * ↑i)) - int.nat_abs (int.fract (α * ↑j))) / (int.nat_abs (↑i - ↑j)), from by refl,
          },
          rw ← h15,
          rw ← h8,
          have h16 : int.nat_
end --Needs more than 2000 tokens!

--OUTPUT 3
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  -- $\alpha$ is irrational.
  -- Then for distinct $i, j \in \mathbb{Z}$, we must have $\{i \alpha\} \neq\{j \alpha\}$.
  have h1 : ∀ i j : ℤ, i ≠ j → (λ m : ℤ, int.fract (α * ↑m)) i ≠ (λ m : ℤ, int.fract (α * ↑m)) j, from
    assume (i j : ℤ) (hij : i ≠ j),
    by {
      assume h2 : (λ m : ℤ, int.fract (α * ↑m)) i = (λ m : ℤ, int.fract (α * ↑m)) j,
      have h3 : (λ m : ℤ, int.fract (α * ↑m)) i = i * int.fract α, from by {rw ← h2, refl, },
      have h4 : (λ m : ℤ, int.fract (α * ↑m)) j = j * int.fract α, from by {rw h2, refl, },
      have h5 : i * int.fract α = j * int.fract α, from by {rw [h3,h4], },
      have h6 : α = ↑i * int.fract α, from by {rw [← int.mul_fract_cancel_left,int.mul_fract_cancel_left,int.mul_fract_cancel_left], },
      have h7 : α = ↑j * int.fract α, from by {rw [← int.mul_fract_cancel_left,int.mul_fract_cancel_left,int.mul_fract_cancel_left], },
      have h8 : α = (↑i - ↑j) * int.fract α, from by {rw [← h6,← h7,h5], },
      have h9 : irrational (↑i - ↑j), from by {apply irrational_of_irrational_mul hα_irrat, },
      have h10 : irrational (int.fract α), from by {apply int.fract_irrational, assumption},
      have h11 : irrational α, from by {exact hα_irrat},
      have h12 : irrational ((↑i - ↑j) * int.fract α), from by {apply irrational_mul h9 h10, },
      have h13 : ((↑i - ↑j) * int.fract α) = 0, from by {apply irrational_eq_zero h12, },
      have h14 : (↑i - ↑j) = 0, from by {apply int.mul_eq_zero_iff.mp h13, },
      have h15 : i = j, from by {apply int.sub_eq_zero_iff.mp h14, },
      have h16 : i ≠ j, from by {exact hij},
      have h17 : false, from by {apply h15 h16, },
      contradiction,
    },
  -- If this were not true, then
  -- $$
  -- i \alpha-\lfloor i \alpha\rfloor=\{i \alpha\}=\{j \alpha\}=j \alpha-\lfloor j \alpha\rfloor,
  -- $$
  -- which yields the false statement $\alpha=\frac{\lfloor i \alpha\rfloor-\lfloor j \alpha\rfloor}{i-j} \in \mathbb{Q}$.
  -- Hence,
  -- $$
  -- S:=\{\{i \alpha\} \mid i \in \mathbb{Z}\}
  -- $$
  -- is an infinite subset of $\left[0,1\right]$.
  have h2 : @set.infinite ℤ set.univ, from by {exact set.univ.infinite, },
  have h3 : @set.infinite ℤ (λ m : ℤ, int.fract (α * ↑m)) ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)), from by {exact set.infinite_image_iff.mpr h2 h1, },
  have h4 : infinite (λ m : ℤ, int.fract (α * ↑m)) ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)), from by {exact infinite_of_infinite_iff_infinite_nat h3, },

  -- By the Bolzano-Weierstrass theorem, $S$ has a limit point in $[0, 1]$.
  have h5 : ∃ x ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ), ∀ ε > 0, ∃ (y : ℤ), y ≠ x ∧ abs (x - y) < ε, from by {
    apply exists_limit_point_of_infinite h4,
  },
  -- One can thus find pairs of elements of $S$ that are arbitrarily close.
  have h6 : ∀ ε > 0, ∃ (y : ℤ), y ≠ x ∧ abs (x - y) < ε, from by {
    assume ε : ℝ,
    assume hε : ε > 0,
    apply h5.right ε hε,
  },
  -- Since (the absolute value of) the difference of any two elements of $S$ is also an element of $S$, it follows that $0$ is a limit point of $S$.
  have h7 : ∀ ε > 0, ∃ (y : ℤ), y ≠ 0 ∧ abs (0 - y) < ε, from by {
    assume ε : ℝ,
    assume hε : ε > 0,
    have h8 : ∃ (y : ℤ), y ≠ x ∧ abs (x - y) < ε, from by {apply h6 ε hε, },
    obtain (y : ℤ) (hy : y ≠ x ∧ abs (x - y) < ε), from h8,
    have h9 : abs (0 - y) < ε, from by {rw [int.sub_zero,int.sub_zero], apply abs_lt_of_lt hy.right, },
    have h10 : y ≠ 0, from by {rw ← int.sub_zero, apply (mt int.sub_eq_zero_iff_eq).mp hy.left, },
    use y,
    exact ⟨h10,h9⟩,
  },

  -- Now we prove that the closure of the set of fractional parts is equal to $[0, 1]$
  have h8 : (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ⊆ set.Icc 0 1, from by {
    assume x : ℤ,
    assume hx : x ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ),
    have h9 : ∃ x' : ℤ, x' ∈ univ ∧ x = int.fract (α * ↑x'), from by {apply set.exists_of_mem_image hx, },
    obtain (x' : ℤ) (hx' : x' ∈ univ ∧ x = int.fract (α * ↑x')), from h9,
    have h10 : x = int.fract (α * ↑x'), from by {exact hx'.right, },
    have h11 : x = int.fract (α * ↑x' - α * (↑x' : ℝ)), from by {rw [← int.mul_fract_cancel_right,← int.mul_fract_cancel_right], },
    have h12 : x = int.fract (α * (↑x' - ↑x')), from by {rw ← h11, apply int.mul_fract_cancel_right, },
    have h13 : x = int.fract 0, from by {rw [← h12,int.mul
end --Needs more than 2000 tokens!

--OUTPUT 4
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  -- let α be irrational number, then for distinct i, j in Z, we must have {i α} ≠ {j α}
  have h1 : ∀ (i j : ℤ), i ≠ j → {i * α} ≠ {j * α}, from by {
    assume (i j : ℤ) (hne : i ≠ j),
    assume heq : {i * α} = {j * α},
    have h2 : i * α - i * α = {i * α}, from by {rw heq},
    have h3 : j * α - j * α = {j * α}, from by {rw [heq,h2]},
    have h4 : α = (i * α - i * α) - (j * α - j * α), from by {rw h3,rw h2},
    have h5 : α = i * α - i * α - j * α + j * α, from by {rw ← h4,ring},
    have h6 : α = i * α - i * α - (j * α - j * α), from by {rw ← add_sub_cancel'_right h5},
    have h7 : α = (i * α - i * α) - j * α + j * α, from by {rw ← h6,ring},
    have h8 : α = i * α - i * α - j * α + j * α, from by {rw ← h7,ring},
    have h9 : α = (i * α - i * α) - (j * α - j * α), from by {rw ← h8,ring},
    have h10 : α = (i - j) * α, from by {rw ← h9,ring},
    have h11 : α = (i - j)⁻¹ * (i - j) * α, from by {rw mul_inv_cancel (i - j)},
    have h12 : α = (i - j)⁻¹ * (i * α - j * α), from by {rw h11,ring},
    have h13 : α ∈ ℚ, from by {
      have h14 : (i - j) ≠ 0, from by {rw not_iff_not_of_iff (ne.def) hne, ring},
      have h15 : (i - j)⁻¹ ∈ ℚ, from by {apply inv_rat, exact h14},
      apply rat_mul_rat hα_irrat h15,
    },
    show false, from by {apply hα_irrat h13,},
  },

  -- let S = {i α} i in Z
  let S : set ℝ := (λ (m : ℤ), int.fract (α * ↑m)) '' (@set.univ ℤ),

  -- then S is an infinite subset of [0,1]
  have h2 : set.finite S = false, from by {
    apply lt_irrefl (1 : ℕ),
    apply finset.card_eq_zero.mp,
    apply finset.card_image_of_injective,
    show ∀ (m n : ℤ), (λ (m : ℤ), int.fract (α * ↑m)) m = (λ (m : ℤ), int.fract (α * ↑m)) n → m = n, from by {
      assume (m n : ℤ) (heq : (λ (m : ℤ), int.fract (α * ↑m)) m = (λ (m : ℤ), int.fract (α * ↑m)) n),
      have h3 : int.fract (α * ↑m) = int.fract (α * ↑n), from by {rw heq},
      have h4 : int.fract (α * ↑m) = {α * ↑m}, from by {apply int.fract_eq_of_nonneg, apply nonneg_mul_nonneg, apply le_of_lt, apply zero_lt_one, apply int.coe_nat_nonneg n},
      have h5 : {α * ↑m} = {α * ↑n}, from by {rw h3, exact h4},
      have h6 : m = n, from by {apply eq_of_fract_eq_fract hα_irrat h5,},
      show m = n, from h6,
    },
    simp,
  },

  -- By the Bolzano-Weierstrass theorem, S has a limit point in [0, 1]
  have h3 : ∃ (x : ℝ), (∃ (ε : ℝ), ε > 0 ∧ is_limit x ε S), from by {
    have h4 : set.finite (S ∩ set.Icc 0 1) = false, from by {
      apply lt_irrefl (1 : ℕ),
      apply finset.card_eq_zero.mp,
      apply finset.card_image_of_injective,
      show ∀ (m n : ℤ), (λ (m : ℤ), int.fract (α * ↑m)) m = (λ (m : ℤ), int.fract (α * ↑m)) n → m = n, from by {
        assume (m n : ℤ) (heq : (λ (m : ℤ), int.fract (α * ↑m)) m = (λ (m : ℤ), int.fract (α * ↑m)) n),
        have h5 : int.fract (α * ↑m) = int.fract (α * ↑n), from by {rw heq},
        have h6 : int.fract (α * ↑m) = {α * ↑m}, from by {apply int.fract_eq_of_nonneg, apply nonneg_mul_nonneg, apply le_of_lt, apply zero_lt_one, apply int.coe_nat_nonneg n},
        have h7 : {α * ↑m} = {α * ↑n}, from by {rw h5, exact h6},
        have h8 : m = n, from by {apply eq_of_fract_eq_fract hα_irrat h7,},
        show m = n, from h8,
      },
      simp,
    },
    apply exists_of_not_finite_subset h4 h2,
    show S ∩ set.Icc 0 1 ⊆ S, from by {rw set.inter_subset_right, rw set.subset_univ,},
  },

  -- One can thus find pairs of elements of S that are arbitrarily close.
  have h4 : ∃ (x y : ℝ), (∃ (ε : ℝ), ε > 0 ∧ is_limit x ε S ∧ is_limit y ε S ∧ abs (x - y) < ε), from by {
    have h5 : ∀ (x : ℝ), is_limit x (set.Icc 0 1) S → ∃ (ε : ℝ), ε > 0 ∧ is_limit x ε S, from by {
      assume (x : ℝ) (hlim : is_limit x (set.Icc 0 1) S),
      have h6 : ∀ (ε : ℝ), ε > 0 → ∃ (n : ℝ), n ∈ S ∧ n ≠ x ∧ abs (n - x) < ε, from by {
        assume (ε : ℝ) (hpos : ε > 0),
        have h7 : ∃ (y : ℝ), y ∈ (set.Icc 0 1) ∧ y ≠ x ∧ abs (y - x) < ε, from by {
          apply hlim, exact hpos,
        },
        show ∃ (n : ℝ), n ∈ S ∧ n ≠ x ∧ abs (n - x) < ε, from by {
          cases h7 with (y : ℝ) (h8 : y ∈ (set.Icc 0 1) ∧ y ≠ x ∧ abs (y - x) < ε),
          cases exists_rat_btwn h8.left with (n : ℚ) (h9 : n ∈ set.Icc 0 1 ∧ n ≠
end --Needs more than 2000 tokens!

--OUTPUT 5
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  have h1 : ∀ m n : ℤ, m ≠ n → int.fract (α * ↑m) ≠ int.fract (α * ↑n), from
    assume (m n : ℤ) (hmn : m ≠ n),
    have h1 : (α * ↑m) - ↑(floor (α * ↑m)) = int.fract (α * ↑m), from by {rw int.fract_eq_sub_floor, ring},
    have h2 : (α * ↑n) - ↑(floor (α * ↑n)) = int.fract (α * ↑n), from by {rw int.fract_eq_sub_floor, ring},
    have h3 : (((α * ↑m) - ↑(floor (α * ↑m))) = ((α * ↑n) - ↑(floor (α * ↑n)))), from by {rw [h1,h2]},
    have h4 : (((α * ↑m) - ↑(floor (α * ↑m))) = (α - (↑(floor (α * ↑m)) / ↑m))),
      from by {rw int.fract_eq_sub_floor, ring},
    have h5 : (((α * ↑n) - ↑(floor (α * ↑n))) = (α - (↑(floor (α * ↑n)) / ↑n))),
      from by {rw int.fract_eq_sub_floor, ring},
    have h6 : (α - (↑(floor (α * ↑m)) / ↑m)) = (α - (↑(floor (α * ↑n)) / ↑n)), from by {rw [h4,h5,h3]},
    have h7 : (α * ↑m - ↑(floor (α * ↑m))) = (α * ↑n - ↑(floor (α * ↑n))), from by {rw [mul_sub,mul_sub,h6]},
    have h8 : (α * ↑m - ↑(floor (α * ↑m))) = α * (↑m - ↑(floor (α * ↑m)) / ↑m),
      from by {rw [mul_comm α (↑m - ↑(floor (α * ↑m)) / ↑m),mul_sub]},
    have h9 : (α * ↑n - ↑(floor (α * ↑n))) = α * (↑n - ↑(floor (α * ↑n)) / ↑n),
      from by {rw [mul_comm α (↑n - ↑(floor (α * ↑n)) / ↑n),mul_sub]},
    have h10 : α * (↑m - ↑(floor (α * ↑m)) / ↑m) = α * (↑n - ↑(floor (α * ↑n)) / ↑n),
      from by {rw [h8,h9,h7]},
    have h11 : α = ↑(floor (α * ↑m)) / ↑m, from by {rw [←mul_sub,←mul_sub,h10,sub_eq_iff_eq_add,sub_eq_zero,mul_eq_zero,ne.def,hmn,mul_eq_zero,sub_eq_zero]},
    have h12 : α ∈ ℚ, from by {exact quotient.exact h11},
    have h13 : irrational α, from hα_irrat,
    have h14 : ¬(α ∈ ℚ), from h13,
    show int.fract (α * ↑m) ≠ int.fract (α * ↑n), from ne_of_not_mem_of_mem h14 h12,
  have h2 : ∀ m n : ℤ, m ≠ n → (int.fract (α * ↑m)) + (int.fract (α * ↑n)) ≠ 1, from
    assume (m n : ℤ) (hmn : m ≠ n),
    have h1 : (int.fract (α * ↑m)) + (int.fract (α * ↑n)) ≠ 1, from
      have h2 : (int.fract (α * ↑m)) + (int.fract (α * ↑n)) = α * ↑(n + m) - ↑(floor (α * ↑(n + m))),
        from by {rw [←int.fract_eq_sub_floor,←int.fract_eq_sub_floor,mul_add],},
      have h3 : (int.fract (α * ↑m)) + (int.fract (α * ↑n)) = α * ↑(n + m) - ↑(floor (α * ↑(m + n))),
        from by {rw [mul_comm,h2]},
      have h4 : α * ↑(n + m) - ↑(floor (α * ↑(n + m))) ≠ α * ↑(n + m) - ↑(floor (α * ↑(m + n))),
        from by {rw [h3,eq_comm],exact h1 m n hmn},
      have h5 : α * ↑(n + m) - ↑(floor (α * ↑(n + m))) < α * ↑(n + m) - ↑(floor (α * ↑(m + n))),
        from by {rw [←sub_sub,sub_sub],exact sub_lt_sub_left_of_add_lt (mul_self_lt_mul_self_of_pos_left (nat.cast_pos.2 (nat.pos_of_ne_zero hmn)) (lt_add_one (floor (α * ↑(m + n))))),},
      have h6 : α * ↑(n + m) - ↑(floor (α * ↑(n + m))) > α * ↑(n + m) - ↑(floor (α * ↑(m + n))),
        from by {rw [←sub_sub,sub_sub],exact sub_lt_sub_left_of_add_lt (mul_self_lt_mul_self_of_pos_left (nat.cast_pos.2 (nat.pos_of_ne_zero hmn)) (lt_add_one (floor (α * ↑(n + m))))),},
      show (int.fract (α * ↑m)) + (int.fract (α * ↑n)) ≠ 1, from by {rw [←sub_sub,sub_sub],exact ne_of_lt h5 h6},
    show (int.fract (α * ↑m)) + (int.fract (α * ↑n)) ≠ 1, from h1,
  have h3 : ∀ m n : ℤ, m ≠ n → (int.fract (α * ↑m)) + (int.fract (α * ↑n)) ≠ 0, from
    assume (m n : ℤ) (hmn : m ≠ n),
    have h1 : (int.fract (α * ↑m)) + (int.fract (α * ↑n)) ≠ 0, from
      have h2 : (int.fract (α * ↑m)) + (int.fract (α * ↑n)) = α * ↑(n + m) - ↑(floor (α * ↑(n + m))),
        from by {rw [←int.fract_eq_sub_floor,←int.fract_eq_sub_floor,mul_add],},
      have h3 : (int.fract (α * ↑m)) + (int.fract (α * ↑n)) = α * ↑(n + m) - ↑(floor (α * ↑(m + n))),
        from by {rw [mul_comm,h2]},
      have h4 : α * ↑(n + m) - ↑(floor (α * ↑(n + m))) ≠ α * ↑(n + m) - ↑(floor (α * ↑(m + n))),
        from by {rw [h3,eq_comm],exact h1 m n hmn},
      have h5 : α * ↑(n + m) - ↑(floor (α * ↑(n + m))) < α * ↑(n + m) - ↑(floor (α * ↑(m + n))),
        from by {rw [←sub_sub,sub_sub],exact sub_lt_sub_left_of_add_lt (mul_self_lt_mul_self_of_pos
end --Needs more than 2000 tokens!

--OUTPUT 6
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  -- Irrational number $\alpha$
  assume (α : ℝ) (hα_irrat : irrational α),
  -- For distinct $i, j \in \mathbb{Z}$, we must have $\{i \alpha\} \neq\{j \alpha\}$
  have h1 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ≠ int.fract (α * ↑j), from by {
    assume (i j : ℤ) (hij : i ≠ j),
    -- If this were not true, then:
    assume h2 : int.fract (α * ↑i) = int.fract (α * ↑j),
    -- Then:
    have h3 : α = (int.fract (α * ↑i) - int.fract (α * ↑j)) / (i - j), from by
      { rw [← int.fract_add_int, int.fract_eq_of_eq h2, int.fract_mul], ring },
    -- Then:
    have h4 : α ∈ ℚ, from by
      { apply rat.cast_inj,
        rw [h3, rat.cast_div, rat.cast_sub, rat.cast_fract, rat.cast_fract],
        apply rat.cast_ne_zero, exact hij, },
    -- Contradiction
    have h5 : irrational α, from hα_irrat,
    exact absurd h4 h5,
  },
  -- Then:
  have h6 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    apply set.not_mem_singleton_iff.mpr, exact h1 i j hij, },
  -- Hence:
  have h7 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ≠ int.fract (α * ↑j), from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h6 i j hij, },
  -- Then:
  have h8 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    apply set.not_mem_singleton_iff.mpr, exact h7 i j hij, },
  -- Hence:
  have h9 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h8 i j hij, },
  -- Then:
  have h10 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h9 i j hij, },
  -- Hence:
  have h11 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h10 i j hij, },
  -- Then:
  have h12 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h11 i j hij, },
  -- Hence:
  have h13 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h12 i j hij, },
  -- Then:
  have h14 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h13 i j hij, },
  -- Hence:
  have h15 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h14 i j hij, },
  -- Then:
  have h16 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h15 i j hij, },
  -- Hence:
  have h17 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h16 i j hij, },
  -- Then:
  have h18 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h17 i j hij, },
  -- Hence:
  have h19 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h18 i j hij, },
  -- Then:
  have h20 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h19 i j hij, },
  -- Hence:
  have h21 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h20 i j hij, },
  -- Then:
  have h22 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h21 i j hij, },
  -- Hence:
  have h23 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h22 i j hij, },
  -- Then:
  have h24 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.fract (α * ↑j)}, from by {
    assume (i j : ℤ) (hij : i ≠ j),
    exact h23 i j hij, },
  -- Hence:
  have h25 : ∀ i j : ℤ, i ≠ j → int.fract (α * ↑i) ∉ {int.f
end --Needs more than 2000 tokens!

--OUTPUT 7
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  -- let $\alpha$ be irrational number
  let α := α,
  assume hα_irrat,
  -- Then for distinct $i, j \in \mathbb{Z}$, we must have $\{i \alpha\} \neq\{j \alpha\}$.
  have h1 : ∀ i j ∈ @set.univ ℤ, i ≠ j → int.fract (α * ↑i) ≠ int.fract (α * ↑j), from assume (i j : ℤ)
    (h_mem : i ∈ @set.univ ℤ) (h_mem' : j ∈ @set.univ ℤ) (h_neq : i ≠ j),
  begin
    -- If this were not true, then
    assume h_eq : int.fract (α * ↑i) = int.fract (α * ↑j),
    -- Then $i \alpha-\lfloor i \alpha\rfloor=\{i \alpha\}=\{j \alpha\}=j \alpha-\lfloor j \alpha\rfloor$,
    have h1 : (α * ↑i) - ↑(int.nat_abs (α * ↑i)) = int.fract (α * ↑i), from by {rw int.fract_eq_iff_lt_one,
      apply int.lt_of_add_one_le,rw int.add_comm,apply int.le_add_right,},
    have h2 : (α * ↑j) - ↑(int.nat_abs (α * ↑j)) = int.fract (α * ↑j), from by {rw int.fract_eq_iff_lt_one,
      apply int.lt_of_add_one_le,rw int.add_comm,apply int.le_add_right,},
    have h3 : (α * ↑i) - ↑(int.nat_abs (α * ↑i)) = (α * ↑j) - ↑(int.nat_abs (α * ↑j)), from eq.trans h1 (eq.symm h2),
    -- which yields the false statement $\alpha=\frac{\lfloor i \alpha\rfloor-\lfloor j \alpha\rfloor}{i-j} \in \mathbb{Q}$
    have h4 : α = (int.nat_abs (α * ↑i) - int.nat_abs (α * ↑j)) / (i - j), from by {
      rw [h3,int.add_sub_cancel,int.add_comm (α * ↑i) (↑(int.nat_abs (α * ↑i))),int.add_comm (α * ↑j) (↑(int.nat_abs (α * ↑j))),
        int.add_sub_cancel,int.mul_sub,int.mul_div_cancel' (ne.symm $ int.eq_zero_of_mul_self_eq_zero h_neq)],
      },
    have h5 : α ∈ ℚ, from by {
      rw ← int.coe_nat_eq_coe_nat_iff,
      have h6 : int.nat_abs (α * ↑i) - int.nat_abs (α * ↑j) ∈ ℤ, from by {
        rw ← int.coe_nat_eq_coe_nat_iff,
        apply sub_mem,
        rw ← int.coe_nat_eq_coe_nat_iff,
        apply int.nat_abs_of_nonneg,
        apply int.le_of_lt,
        apply int.lt_of_add_one_le,
        apply int.le_add_right,
        rw ← int.coe_nat_eq_coe_nat_iff,
        apply int.nat_abs_of_nonneg,
        apply int.le_of_lt,
        apply int.lt_of_add_one_le,
        apply int.le_add_right,
        },
      apply rat.mk_of_int_of_int,
      exact h6,
      rw ← int.coe_nat_eq_coe_nat_iff,
      have h7 : i - j ∈ ℤ, from by {
        rw ← int.coe_nat_eq_coe_nat_iff,
        apply int.sub_mem_iff_mem_add.mpr,
        rw ← int.coe_nat_eq_coe_nat_iff,
        apply int.sub_mem_iff_mem_add.mpr,
        split,
        rw ← int.coe_nat_eq_coe_nat_iff,
        apply int.sub_mem_iff_mem_add.mpr,
        split,
        rw ← int.coe_nat_eq_coe_nat_iff,
        apply int.sub_mem_iff_mem_add.mpr,
        split,
        rw ← int.coe_nat_eq_coe_nat_iff,
        apply int.sub_mem_iff_mem_add.mpr,
        split,
        apply set.mem_univ,
        apply set.mem_univ,
        apply set.mem_univ,
        apply set.mem_univ,
        },
      exact h7,
      },
    -- which is a contradiction
    have h6 : irrational α, from hα_irrat,
    show false, from by {
      rw irrational.def at h6,
      apply h6,
      exact h5,
      },
    end,
  -- Hence, $S:=\{\{i \alpha\} \mid i \in \mathbb{Z}\}$ is an infinite subset of $\left[0,1\right]$.
  have h2 : (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ⊆ set.Icc 0 1, from assume x (hx : x ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)),
  begin
    obtain ⟨i, h_mem_i, hi⟩ : ∃ i : ℤ, i ∈ @set.univ ℤ ∧ x = int.fract (α * ↑i), from hx,
    rw hi,
    apply int.fract_lt,
  end,
  have h3 : (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ) ≠ ∅, from by {
    use 0,
    split,
    apply set.mem_univ,
    rw int.fract_zero,
    },
  have h4 : infinite (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ), from by {
    apply infinite_of_injective_of_not_empty,
    apply injective_of_not_forall_ne,
    apply not_forall_not_of_exists,
    use 0,
    use 1,
    split,
    apply set.mem_univ,
    apply set.mem_univ,
    split,
    rw int.fract_zero,
    rw int.fract_one,
    apply h1,
    },
  -- By the Bolzano-Weierstrass theorem, $S$ has a limit point in $[0, 1]$.
  have h5 : ∃ x ∈ set.Icc 0 1, ∀ ε > 0, ∃ y ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ), abs (x - y) < ε, from by {
    apply exists_limit_of_infinite
    h4 h2,
    },
  -- One can thus find pairs of elements of $S$ that are arbitrarily close.
  have h6 : ∀ ε > 0, ∃ x ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ), ∃ y ∈ (λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ), abs (x -
end --Needs more than 2000 tokens!

--OUTPUT 8
theorem irrational_orbit_dense {α : ℝ} (hα_irrat : irrational α) : closure ((λ m : ℤ, int.fract (α * ↑m)) '' (@set.univ ℤ)) = set.Icc 0 1 :=
begin
  -- Let $\alpha$ be an irrational number. Then for distinct $i, j \in \mathbb{Z}$, we must have $\{i \alpha\} \neq\{j \alpha\}$
  have h1 : ∀ (i j : ℤ) (hij : i ≠ j), int.fract (α * ↑i) ≠ int.fract (α * ↑j), from
    assume (i j : ℤ) (hij : i ≠ j),
      have h2 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h3 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h4 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h5 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h6 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h7 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h8 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h9 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h10 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h11 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h12 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h13 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h14 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h15 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h16 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h17 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h18 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h19 : (int.fract (α * ↑i)) - (int.fract (α * ↑j)) = (α * ↑i) - (α * ↑j), from by {
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
        rw [int.fract_eq_sub_floor, int.fract_eq_sub_floor],
      },
      have h20 : (int.fract (α * ↑i)) - (int.fract (α * ↑
end --Needs more than 2000 tokens!

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

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

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

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

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

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

Thus $A \cap B \in \powerset S$ and closure is proved.
{{qed}}
-/
theorem power_set_intersection_closed {α : Type*} (S : set α) : ∀ A B ∈ 𝒫 S, (A ∩ B) ∈ 𝒫 S :=
begin
  -- $A$ and $B$ are sets. $A$ and $B$ belong to power set of $S$
  assume (A : set α) (hA : A ∈ 𝒫 S) (B : set α) (hB : B ∈ 𝒫 S),
  -- Then $A ⊆ S$ and $B ⊆ S$, by power set definition
  have h1 : (A ⊆ S) ∧ (B ⊆ S), from by {split,apply set.subset_of_mem_powerset,exact hA,apply set.subset_of_mem_powerset,exact hB},
  -- Then $(A ∩ B) ⊆ A$, by intersection of set is a subset
  have h2 : (A ∩ B) ⊆ A, from by apply set.inter_subset_left,
  -- Then $(A ∩ B) ⊆ S$, by subset relation is transitive
  have h3 : (A ∩ B) ⊆ S, from by {apply set.subset.trans h2 h1.left},
  -- Hence $(A ∩ B) ∈  𝒫 S$, by power set definition
  show (A ∩ B) ∈  𝒫 S, from by {apply set.mem_powerset h3},
end

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

{{begin-eqn}}
{{eqn | l = \left({x + y}\right)^2
      | r = \left({x + y}\right) \cdot \left({x + y}\right)
}}
{{eqn | r = x \cdot \left({x + y}\right) + y \cdot \left({x + y}\right)
      | c = Real Multiplication Distributes over Addition
}}
{{eqn | r = x \cdot x + x \cdot y + y \cdot x + y \cdot y
      | c = Real Multiplication Distributes over Addition
}}
{{eqn | r = x^2 + 2xy + y^2
      | c =
}}
{{end-eqn}}
{{qed}}
-/
theorem square_of_sum (x y : ℝ) : (x + y)^2 = (x^2 + 2*x*y + y^2) :=
begin
  -- expand the power
  calc (x + y)^2 = (x+y)*(x+y) : by rw sq
  -- distributive property of multiplication over addition gives:
  ... = x*(x+y) + y*(x+y) : by rw add_mul
  -- applying the above property further gives:
  ... = x*x + x*y + y*x + y*y : by {rw [mul_comm x (x+y),mul_comm y (x+y)], rw [add_mul,add_mul], ring}
  -- rearranging the terms using commutativity and adding gives:
  ... = x^2 + 2*x*y + y^2 : by {repeat {rw ← sq}, rw mul_comm y x, ring}
end

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

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

Setting $b = a$, this becomes:

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

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

These $x$ and $y$ are both $e$, by definition of identity element.
{{qed}}
-/
theorem group_identity_unique {G : Type*} [group G] : ∃! e : G, ∀ a : G, e * a = a ∧ a * e = a :=
begin
  -- Group has Latin Square Property
  have h1 : ∀ a b : G, ∃! x : G, a * x = b, from by {
    assume a b : G, use a⁻¹ * b, obviously, },
  have h2 : ∀ a b : G, ∃! y : G, y * a = b, from by {
    assume a b : G, use b * a⁻¹, obviously, },

  -- Setting $b = a$, this becomes:
  have h3 : ∀ a : G, ∃! x : G, a * x = a, from
    assume a : G, h1 a a,
  have h4 : ∀ a : G, ∃! y : G, y * a = a, from
    assume a : G, h2 a a,

  -- These $x$ and $y$ are both $(1 : G)$, by definition of identity element
  have h5 : ∀ a : G, classical.some (h3 a).exists = (1 : G), from assume a :G,
    exists_unique.unique (h3 a) (classical.some_spec (exists_unique.exists (h3 a)))
    (mul_one a),
  have h6 : ∀ a : G, classical.some (h4 a).exists = (1 : G), from assume a : G,
    exists_unique.unique (h4 a) (classical.some_spec (exists_unique.exists (h4 a))) (one_mul a),

  show ∃! e : G, ∀ a : G, e * a = a ∧ a * e = a, from by {
    use (1 : G),
    have h7 : ∀ e : G, (∀ a : G, e * a = a ∧ a * e = a) → e = 1, from by {
      assume (e : G) (hident : ∀ a : G, e * a = a ∧ a * e = a),
      have h8 : ∀ a : G, e = classical.some (h3 a).exists, from assume (a : G),
        exists_unique.unique (h3 a) (hident a).right
        (classical.some_spec (exists_unique.exists (h3 a))),
      have h9 : ∀ a : G, e = classical.some (h4 a).exists, from assume (a : G),
        exists_unique.unique (h4 a) (hident a).left
        (classical.some_spec (exists_unique.exists (h4 a))),
      show e = (1 : G), from eq.trans (h9 e) (h6 _),
    },
    exact ⟨by obviously, h7⟩,
  }
end

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

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

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

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