Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 213b0cf

Browse files
eric-wieserYaelDilliescollares
committed
feat(algebra/order/to_interval_mod): add circular_order instance for add_circle (#17743)
This also provides us with the same instance for `real.angle`. Co-authored-by: Yaël Dillies <yael.dillies@gmail.com> Co-authored-by: Mauricio Collares <mauricio@collares.org>
1 parent 28b2a92 commit 213b0cf

4 files changed

Lines changed: 209 additions & 4 deletions

File tree

src/algebra/order/to_interval_mod.lean

Lines changed: 202 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import algebra.order.archimedean
99
import algebra.periodic
1010
import data.int.succ_pred
1111
import group_theory.quotient_group
12+
import order.circular
1213

1314
/-!
1415
# Reducing to an interval modulo its length
@@ -32,8 +33,6 @@ interval.
3233

3334
noncomputable theory
3435

35-
open add_comm_group
36-
3736
section linear_ordered_add_comm_group
3837

3938
variables {α : Type*} [linear_ordered_add_comm_group α] [hα : archimedean α] {p : α} (hp : 0 < p)
@@ -562,6 +561,8 @@ end
562561

563562
end Ico_Ioc
564563

564+
open add_comm_group
565+
565566
lemma to_Ico_mod_eq_self : to_Ico_mod hp a b = b ↔ b ∈ set.Ico a (a + p) :=
566567
by { rw [to_Ico_mod_eq_iff, and_iff_left], exact ⟨0, by simp⟩ }
567568

@@ -590,6 +591,37 @@ to_Ico_mod_add_right hp a
590591
lemma to_Ioc_mod_periodic (a : α) : function.periodic (to_Ioc_mod hp a) p :=
591592
to_Ioc_mod_add_right hp a
592593

594+
-- helper lemmas for when `a = 0`
595+
section zero
596+
597+
lemma to_Ico_mod_zero_sub_comm (a b : α) : to_Ico_mod hp 0 (a - b) = p - to_Ioc_mod hp 0 (b - a) :=
598+
by rw [←neg_sub, to_Ico_mod_neg, neg_zero]
599+
600+
lemma to_Ioc_mod_zero_sub_comm (a b : α) : to_Ioc_mod hp 0 (a - b) = p - to_Ico_mod hp 0 (b - a) :=
601+
by rw [←neg_sub, to_Ioc_mod_neg, neg_zero]
602+
603+
lemma to_Ico_div_eq_sub (a b : α) : to_Ico_div hp a b = to_Ico_div hp 0 (b - a) :=
604+
by rw [to_Ico_div_sub_eq_to_Ico_div_add, zero_add]
605+
606+
lemma to_Ioc_div_eq_sub (a b : α) : to_Ioc_div hp a b = to_Ioc_div hp 0 (b - a) :=
607+
by rw [to_Ioc_div_sub_eq_to_Ioc_div_add, zero_add]
608+
609+
lemma to_Ico_mod_eq_sub (a b : α) : to_Ico_mod hp a b = to_Ico_mod hp 0 (b - a) + a :=
610+
by rw [to_Ico_mod_sub_eq_sub, zero_add, sub_add_cancel]
611+
612+
lemma to_Ioc_mod_eq_sub (a b : α) : to_Ioc_mod hp a b = to_Ioc_mod hp 0 (b - a) + a :=
613+
by rw [to_Ioc_mod_sub_eq_sub, zero_add, sub_add_cancel]
614+
615+
lemma to_Ico_mod_add_to_Ioc_mod_zero (a b : α) :
616+
to_Ico_mod hp 0 (a - b) + to_Ioc_mod hp 0 (b - a) = p :=
617+
by rw [to_Ico_mod_zero_sub_comm, sub_add_cancel]
618+
619+
lemma to_Ioc_mod_add_to_Ico_mod_zero (a b : α) :
620+
to_Ioc_mod hp 0 (a - b) + to_Ico_mod hp 0 (b - a) = p :=
621+
by rw [add_comm, to_Ico_mod_add_to_Ioc_mod_zero]
622+
623+
end zero
624+
593625
/-- `to_Ico_mod` as an equiv from the quotient. -/
594626
@[simps symm_apply]
595627
def quotient_add_group.equiv_Ico_mod (a : α) :
@@ -610,7 +642,12 @@ lemma quotient_add_group.equiv_Ico_mod_coe (a b : α) :
610642
quotient_add_group.equiv_Ico_mod hp a ↑b = ⟨to_Ico_mod hp a b, to_Ico_mod_mem_Ico hp a _⟩ :=
611643
rfl
612644

613-
/-- `to_Ioc_mod` as an equiv from the quotient. -/
645+
@[simp]
646+
lemma quotient_add_group.equiv_Ico_mod_zero (a : α) :
647+
quotient_add_group.equiv_Ico_mod hp a 0 = ⟨to_Ico_mod hp a 0, to_Ico_mod_mem_Ico hp a _⟩ :=
648+
rfl
649+
650+
/-- `to_Ioc_mod` as an equiv from the quotient. -/
614651
@[simps symm_apply]
615652
def quotient_add_group.equiv_Ioc_mod (a : α) :
616653
(α ⧸ add_subgroup.zmultiples p) ≃ set.Ioc a (a + p) :=
@@ -630,8 +667,170 @@ lemma quotient_add_group.equiv_Ioc_mod_coe (a b : α) :
630667
quotient_add_group.equiv_Ioc_mod hp a ↑b = ⟨to_Ioc_mod hp a b, to_Ioc_mod_mem_Ioc hp a _⟩ :=
631668
rfl
632669

670+
@[simp]
671+
lemma quotient_add_group.equiv_Ioc_mod_zero (a : α) :
672+
quotient_add_group.equiv_Ioc_mod hp a 0 = ⟨to_Ioc_mod hp a 0, to_Ioc_mod_mem_Ioc hp a _⟩ :=
673+
rfl
674+
675+
/-!
676+
### The circular order structure on `α ⧸ add_subgroup.zmultiples p`
677+
-/
678+
679+
section circular
680+
681+
private lemma to_Ixx_mod_iff (x₁ x₂ x₃ : α) :
682+
to_Ico_mod hp x₁ x₂ ≤ to_Ioc_mod hp x₁ x₃ ↔
683+
to_Ico_mod hp 0 (x₂ - x₁) + to_Ico_mod hp 0 (x₁ - x₃) ≤ p :=
684+
by rw [to_Ico_mod_eq_sub, to_Ioc_mod_eq_sub _ x₁, add_le_add_iff_right, ←neg_sub x₁ x₃,
685+
to_Ioc_mod_neg, neg_zero, le_sub_iff_add_le]
686+
687+
private lemma to_Ixx_mod_cyclic_left {x₁ x₂ x₃ : α}
688+
(h : to_Ico_mod hp x₁ x₂ ≤ to_Ioc_mod hp x₁ x₃) :
689+
to_Ico_mod hp x₂ x₃ ≤ to_Ioc_mod hp x₂ x₁ :=
690+
begin
691+
let x₂' := to_Ico_mod hp x₁ x₂,
692+
let x₃' := to_Ico_mod hp x₂' x₃,
693+
have h : x₂' ≤ to_Ioc_mod hp x₁ x₃' := by simpa,
694+
have h₂₁ : x₂' < x₁ + p := to_Ico_mod_lt_right _ _ _,
695+
have h₃₂ : x₃' - p < x₂' := sub_lt_iff_lt_add.2 (to_Ico_mod_lt_right _ _ _),
696+
697+
suffices hequiv : x₃' ≤ to_Ioc_mod hp x₂' x₁,
698+
{ obtain ⟨z, hd⟩ : ∃ (z : ℤ), x₂ = x₂' + z • p := ((to_Ico_mod_eq_iff hp).1 rfl).2,
699+
simpa [hd] },
700+
701+
cases le_or_lt x₃' (x₁ + p) with h₃₁ h₁₃,
702+
{ suffices hIoc₂₁ : to_Ioc_mod hp x₂' x₁ = x₁ + p,
703+
{ exact hIoc₂₁.symm.trans_ge h₃₁ },
704+
apply (to_Ioc_mod_eq_iff hp).2,
705+
exact ⟨⟨h₂₁, by simp [left_le_to_Ico_mod]⟩, -1, by simp⟩ },
706+
707+
have hIoc₁₃ : to_Ioc_mod hp x₁ x₃' = x₃' - p,
708+
{ apply (to_Ioc_mod_eq_iff hp).2,
709+
exact ⟨⟨lt_sub_iff_add_lt.2 h₁₃, le_of_lt (h₃₂.trans h₂₁)⟩, 1, by simp⟩ },
710+
have not_h₃₂ := (h.trans hIoc₁₃.le).not_lt,
711+
contradiction
712+
end
713+
714+
private lemma to_Ixx_mod_antisymm (h₁₂₃ : to_Ico_mod hp a b ≤ to_Ioc_mod hp a c)
715+
(h₁₃₂ : to_Ico_mod hp a c ≤ to_Ioc_mod hp a b) :
716+
b ≡ a [PMOD p] ∨ c ≡ b [PMOD p] ∨ a ≡ c [PMOD p] :=
717+
begin
718+
by_contra' h,
719+
rw modeq_comm at h,
720+
rw ←(not_modeq_iff_to_Ico_mod_eq_to_Ioc_mod hp).mp h.2.2 at h₁₂₃,
721+
rw ←(not_modeq_iff_to_Ico_mod_eq_to_Ioc_mod hp).mp h.1 at h₁₃₂,
722+
exact h.2.1 ((to_Ico_mod_inj _).1 $ h₁₃₂.antisymm h₁₂₃),
723+
end
724+
725+
private lemma to_Ixx_mod_total' (a b c : α) :
726+
to_Ico_mod hp b a ≤ to_Ioc_mod hp b c ∨ to_Ico_mod hp b c ≤ to_Ioc_mod hp b a :=
727+
begin
728+
/- an essential ingredient is the lemma sabing {a-b} + {b-a} = period if a ≠ b (and = 0 if a = b).
729+
Thus if a ≠ b and b ≠ c then ({a-b} + {b-c}) + ({c-b} + {b-a}) = 2 * period, so one of
730+
`{a-b} + {b-c}` and `{c-b} + {b-a}` must be `≤ period` -/
731+
have := congr_arg2 (+)
732+
(to_Ico_mod_add_to_Ioc_mod_zero hp a b) (to_Ico_mod_add_to_Ioc_mod_zero hp c b),
733+
rw [add_add_add_comm, add_comm (to_Ioc_mod _ _ _), add_add_add_comm, ←two_nsmul] at this,
734+
replace := min_le_of_add_le_two_nsmul this.le,
735+
rw min_le_iff at this,
736+
rw [to_Ixx_mod_iff, to_Ixx_mod_iff],
737+
refine this.imp (le_trans $ add_le_add_left _ _) (le_trans $ add_le_add_left _ _),
738+
{ apply to_Ico_mod_le_to_Ioc_mod },
739+
{ apply to_Ico_mod_le_to_Ioc_mod }
740+
end
741+
742+
private lemma to_Ixx_mod_total (a b c : α) :
743+
to_Ico_mod hp a b ≤ to_Ioc_mod hp a c ∨ to_Ico_mod hp c b ≤ to_Ioc_mod hp c a :=
744+
(to_Ixx_mod_total' _ _ _ _).imp_right $ to_Ixx_mod_cyclic_left _
745+
746+
private lemma to_Ixx_mod_trans {x₁ x₂ x₃ x₄ : α}
747+
(h₁₂₃ : to_Ico_mod hp x₁ x₂ ≤ to_Ioc_mod hp x₁ x₃
748+
∧ ¬to_Ico_mod hp x₃ x₂ ≤ to_Ioc_mod hp x₃ x₁)
749+
(h₂₃₄ : to_Ico_mod hp x₂ x₄ ≤ to_Ioc_mod hp x₂ x₃
750+
∧ ¬to_Ico_mod hp x₃ x₄ ≤ to_Ioc_mod hp x₃ x₂) :
751+
to_Ico_mod hp x₁ x₄ ≤ to_Ioc_mod hp x₁ x₃
752+
∧ ¬to_Ico_mod hp x₃ x₄ ≤ to_Ioc_mod hp x₃ x₁ :=
753+
begin
754+
split,
755+
{ suffices h : ¬x₃ ≡ x₂ [PMOD p],
756+
{ have h₁₂₃' := to_Ixx_mod_cyclic_left _ (to_Ixx_mod_cyclic_left _ h₁₂₃.1),
757+
have h₂₃₄' := to_Ixx_mod_cyclic_left _ (to_Ixx_mod_cyclic_left _ h₂₃₄.1),
758+
rw [(not_modeq_iff_to_Ico_mod_eq_to_Ioc_mod hp).1 h] at h₂₃₄',
759+
exact to_Ixx_mod_cyclic_left _ (h₁₂₃'.trans h₂₃₄') },
760+
by_contra,
761+
rw [(modeq_iff_to_Ico_mod_eq_left hp).1 h] at h₁₂₃,
762+
exact h₁₂₃.2 (left_lt_to_Ioc_mod _ _ _).le },
763+
{ rw [not_le] at h₁₂₃ h₂₃₄ ⊢,
764+
exact (h₁₂₃.2.trans_le (to_Ico_mod_le_to_Ioc_mod _ x₃ x₂)).trans h₂₃₄.2 },
765+
end
766+
767+
namespace quotient_add_group
768+
variables [hp' : fact (0 < p)]
769+
include hp'
770+
771+
instance : has_btw (α ⧸ add_subgroup.zmultiples p) :=
772+
{ btw := λ x₁ x₂ x₃, (equiv_Ico_mod hp'.out 0 (x₂ - x₁) : α) ≤ equiv_Ioc_mod hp'.out 0 (x₃ - x₁) }
773+
774+
lemma btw_coe_iff' {x₁ x₂ x₃ : α} :
775+
has_btw.btw (x₁ : α ⧸ add_subgroup.zmultiples p) x₂ x₃ ↔
776+
to_Ico_mod hp'.out 0 (x₂ - x₁) ≤ to_Ioc_mod hp'.out 0 (x₃ - x₁) :=
777+
iff.rfl
778+
779+
-- maybe harder to use than the primed one?
780+
lemma btw_coe_iff {x₁ x₂ x₃ : α} :
781+
has_btw.btw (x₁ : α ⧸ add_subgroup.zmultiples p) x₂ x₃ ↔
782+
to_Ico_mod hp'.out x₁ x₂ ≤ to_Ioc_mod hp'.out x₁ x₃ :=
783+
by rw [btw_coe_iff', to_Ioc_mod_sub_eq_sub, to_Ico_mod_sub_eq_sub, zero_add, sub_le_sub_iff_right]
784+
785+
instance circular_preorder : circular_preorder (α ⧸ add_subgroup.zmultiples p) :=
786+
{ btw_refl := λ x, show _ ≤ _, by simp [sub_self, hp'.out.le],
787+
btw_cyclic_left := λ x₁ x₂ x₃ h, begin
788+
induction x₁ using quotient_add_group.induction_on',
789+
induction x₂ using quotient_add_group.induction_on',
790+
induction x₃ using quotient_add_group.induction_on',
791+
simp_rw [btw_coe_iff] at h ⊢,
792+
apply to_Ixx_mod_cyclic_left _ h,
793+
end,
794+
sbtw := _,
795+
sbtw_iff_btw_not_btw := λ _ _ _, iff.rfl,
796+
sbtw_trans_left := λ x₁ x₂ x₃ x₄ (h₁₂₃ : _ ∧ _) (h₂₃₄ : _ ∧ _), show _ ∧ _, begin
797+
induction x₁ using quotient_add_group.induction_on',
798+
induction x₂ using quotient_add_group.induction_on',
799+
induction x₃ using quotient_add_group.induction_on',
800+
induction x₄ using quotient_add_group.induction_on',
801+
simp_rw [btw_coe_iff] at h₁₂₃ h₂₃₄ ⊢,
802+
apply to_Ixx_mod_trans _ h₁₂₃ h₂₃₄,
803+
end }
804+
805+
instance circular_order : circular_order (α ⧸ add_subgroup.zmultiples p) :=
806+
{ btw_antisymm := λ x₁ x₂ x₃ h₁₂₃ h₃₂₁, begin
807+
induction x₁ using quotient_add_group.induction_on',
808+
induction x₂ using quotient_add_group.induction_on',
809+
induction x₃ using quotient_add_group.induction_on',
810+
rw btw_cyclic at h₃₂₁,
811+
simp_rw [btw_coe_iff] at h₁₂₃ h₃₂₁,
812+
simp_rw ←modeq_iff_eq_mod_zmultiples,
813+
exact to_Ixx_mod_antisymm _ h₁₂₃ h₃₂₁,
814+
end,
815+
btw_total := λ x₁ x₂ x₃, begin
816+
induction x₁ using quotient_add_group.induction_on',
817+
induction x₂ using quotient_add_group.induction_on',
818+
induction x₃ using quotient_add_group.induction_on',
819+
simp_rw [btw_coe_iff] at ⊢,
820+
apply to_Ixx_mod_total,
821+
end,
822+
..quotient_add_group.circular_preorder }
823+
824+
end quotient_add_group
825+
826+
end circular
827+
633828
end linear_ordered_add_comm_group
634829

830+
/-!
831+
### Connections to `int.floor` and `int.fract`
832+
-/
833+
635834
section linear_ordered_field
636835

637836
variables {α : Type*} [linear_ordered_field α] [floor_ring α] {p : α} (hp : 0 < p)

src/analysis/special_functions/trigonometric/angle.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ def angle : Type := add_circle (2 * π)
2727

2828
namespace angle
2929

30+
instance : circular_order real.angle :=
31+
@add_circle.circular_order _ _ _ _ _ ⟨by norm_num [pi_pos]⟩ _
32+
3033
@[continuity] lemma continuous_coe : continuous (coe : ℝ → angle) :=
3134
continuous_quotient_mk
3235

src/order/circular.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ What is the correct generality of "rolling the necklace" open? At least, this wo
7070
`β × α` where `α` is a circular order and `β` is a linear order.
7171
7272
What's next is to define circular groups and provide instances for `zmod n`, the usual circle group
73-
`circle`, `real.angle`, and `roots_of_unity M`. What conditions do we need on `M` for this last one
73+
`circle`, and `roots_of_unity M`. What conditions do we need on `M` for this last one
7474
to work?
7575
7676
We should have circular order homomorphisms. The typical example is

src/topology/instances/add_circle.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ include hp
154154

155155
variables (a : 𝕜) [archimedean 𝕜]
156156

157+
instance : circular_order (add_circle p) :=
158+
quotient_add_group.circular_order
159+
157160
/-- The equivalence between `add_circle p` and the half-open interval `[a, a + p)`, whose inverse
158161
is the natural quotient map. -/
159162
def equiv_Ico : add_circle p ≃ Ico a (a + p) := quotient_add_group.equiv_Ico_mod hp.out a

0 commit comments

Comments
 (0)