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

Commit 31e5ae2

Browse files
committed
feat(data/list/cycle): Define the empty cycle (#12967)
Also clean the file up somewhat, and add various `simp` lemmas.
1 parent 0c6f0c2 commit 31e5ae2

File tree

1 file changed

+100
-83
lines changed

1 file changed

+100
-83
lines changed

src/data/list/cycle.lean

Lines changed: 100 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -430,73 +430,91 @@ instance : has_coe (list α) (cycle α) := ⟨quot.mk _⟩
430430
@[simp] lemma coe_eq_coe {l₁ l₂ : list α} : (l₁ : cycle α) = l₂ ↔ (l₁ ~r l₂) :=
431431
@quotient.eq _ (is_rotated.setoid _) _ _
432432

433-
@[simp] lemma mk_eq_coe (l : list α) :
434-
quot.mk _ l = (l : cycle α) := rfl
433+
@[simp] lemma mk_eq_coe (l : list α) : quot.mk _ l = (l : cycle α) :=
434+
rfl
435435

436-
@[simp] lemma mk'_eq_coe (l : list α) :
437-
quotient.mk' l = (l : cycle α) := rfl
436+
@[simp] lemma mk'_eq_coe (l : list α) : quotient.mk' l = (l : cycle α) :=
437+
rfl
438438

439-
instance : inhabited (cycle α) := ⟨(([] : list α) : cycle α)⟩
439+
/-- The unique empty cycle. -/
440+
def nil : cycle α := ↑([] : list α)
440441

441-
/--
442-
For `x : α`, `s : cycle α`, `x ∈ s` indicates that `x` occurs at least once in `s`.
443-
-/
442+
@[simp] lemma coe_nil : ↑([] : list α) = @nil α :=
443+
rfl
444+
445+
@[simp] lemma coe_eq_nil (l : list α) : (l : cycle α) = nil ↔ l = [] :=
446+
coe_eq_coe.trans is_rotated_nil_iff
447+
448+
instance : has_emptyc (cycle α) := ⟨nil⟩
449+
450+
@[simp] lemma empty_eq : ∅ = @nil α :=
451+
rfl
452+
453+
instance : inhabited (cycle α) := ⟨nil⟩
454+
455+
/-- An induction principle for `cycle`. Use as `induction s using cycle.induction_on`. -/
456+
@[elab_as_eliminator] lemma induction_on {C : cycle α → Prop} (s : cycle α) (H0 : C nil)
457+
(HI : ∀ a (l : list α), C ↑l → C ↑(a :: l)) : C s :=
458+
quotient.induction_on' s $ λ l, by { apply list.rec_on l; simp, assumption' }
459+
460+
/-- For `x : α`, `s : cycle α`, `x ∈ s` indicates that `x` occurs at least once in `s`. -/
444461
def mem (a : α) (s : cycle α) : Prop :=
445462
quot.lift_on s (λ l, a ∈ l) (λ l₁ l₂ (e : l₁ ~r l₂), propext $ e.mem_iff)
446463

447464
instance : has_mem α (cycle α) := ⟨mem⟩
448465

449-
@[simp] lemma mem_coe_iff {a : α} {l : list α} :
450-
a ∈ (l : cycle α) ↔ a ∈ l := iff.rfl
466+
@[simp] lemma mem_coe_iff {a : α} {l : list α} : a ∈ (l : cycle α) ↔ a ∈ l :=
467+
iff.rfl
468+
469+
@[simp] lemma not_mem_nil : ∀ a, a ∉ @nil α :=
470+
not_mem_nil
451471

452472
instance [decidable_eq α] : decidable_eq (cycle α) :=
453-
λ s₁ s₂, quotient.rec_on_subsingleton₂' s₁ s₂ (λ l₁ l₂,
454-
decidable_of_iff' _ quotient.eq')
473+
λ s₁ s₂, quotient.rec_on_subsingleton₂' s₁ s₂ (λ l₁ l₂, decidable_of_iff' _ quotient.eq')
455474

456475
instance [decidable_eq α] (x : α) (s : cycle α) : decidable (x ∈ s) :=
457476
quotient.rec_on_subsingleton' s (λ l, list.decidable_mem x l)
458477

459-
/--
460-
Reverse a `s : cycle α` by reversing the underlying `list`.
461-
-/
478+
/-- Reverse a `s : cycle α` by reversing the underlying `list`. -/
462479
def reverse (s : cycle α) : cycle α :=
463480
quot.map reverse (λ l₁ l₂ (e : l₁ ~r l₂), e.reverse) s
464481

465-
@[simp] lemma reverse_coe (l : list α) :
466-
(l : cycle α).reverse = l.reverse := rfl
482+
@[simp] lemma reverse_coe (l : list α) : (l : cycle α).reverse = l.reverse :=
483+
rfl
467484

468-
@[simp] lemma mem_reverse_iff {a : α} {s : cycle α} :
469-
a ∈ s.reverse ↔ a ∈ s :=
485+
@[simp] lemma mem_reverse_iff {a : α} {s : cycle α} : a ∈ s.reverse ↔ a ∈ s :=
470486
quot.induction_on s (λ _, mem_reverse)
471487

472-
@[simp] lemma reverse_reverse (s : cycle α) :
473-
s.reverse.reverse = s :=
488+
@[simp] lemma reverse_reverse (s : cycle α) : s.reverse.reverse = s :=
474489
quot.induction_on s (λ _, by simp)
475490

476-
/--
477-
The length of the `s : cycle α`, which is the number of elements, counting duplicates.
478-
-/
491+
@[simp] lemma reverse_nil : nil.reverse = @nil α :=
492+
rfl
493+
494+
/-- The length of the `s : cycle α`, which is the number of elements, counting duplicates. -/
479495
def length (s : cycle α) : ℕ :=
480496
quot.lift_on s length (λ l₁ l₂ (e : l₁ ~r l₂), e.perm.length_eq)
481497

482-
@[simp] lemma length_coe (l : list α) :
483-
length (l : cycle α) = l.length := rfl
498+
@[simp] lemma length_coe (l : list α) : length (l : cycle α) = l.length :=
499+
rfl
484500

485-
@[simp] lemma length_reverse (s : cycle α) :
486-
s.reverse.length = s.length :=
501+
@[simp] lemma length_nil : length (@nil α) = 0 :=
502+
rfl
503+
504+
@[simp] lemma length_reverse (s : cycle α) : s.reverse.length = s.length :=
487505
quot.induction_on s length_reverse
488506

489-
/--
490-
A `s : cycle α` that is at most one element.
491-
-/
507+
/-- A `s : cycle α` that is at most one element. -/
492508
def subsingleton (s : cycle α) : Prop :=
493509
s.length ≤ 1
494510

495-
lemma length_subsingleton_iff {s : cycle α} :
496-
subsingleton s ↔ length s ≤ 1 := iff.rfl
511+
lemma subsingleton_nil : subsingleton (@nil α) :=
512+
zero_le_one
497513

498-
@[simp] lemma subsingleton_reverse_iff {s : cycle α} :
499-
s.reverse.subsingleton ↔ s.subsingleton :=
514+
lemma length_subsingleton_iff {s : cycle α} : subsingleton s ↔ length s ≤ 1 :=
515+
iff.rfl
516+
517+
@[simp] lemma subsingleton_reverse_iff {s : cycle α} : s.reverse.subsingleton ↔ s.subsingleton :=
500518
by simp [length_subsingleton_iff]
501519

502520
lemma subsingleton.congr {s : cycle α} (h : subsingleton s) :
@@ -509,9 +527,7 @@ begin
509527
simp
510528
end
511529

512-
/--
513-
A `s : cycle α` that is made up of at least two unique elements.
514-
-/
530+
/-- A `s : cycle α` that is made up of at least two unique elements. -/
515531
def nontrivial (s : cycle α) : Prop := ∃ (x y : α) (h : x ≠ y), x ∈ s ∧ y ∈ s
516532

517533
@[simp] lemma nontrivial_coe_nodup_iff {l : list α} (hl : l.nodup) :
@@ -528,12 +544,10 @@ begin
528544
exact hl.left.left }
529545
end
530546

531-
@[simp] lemma nontrivial_reverse_iff {s : cycle α} :
532-
s.reverse.nontrivial ↔ s.nontrivial :=
547+
@[simp] lemma nontrivial_reverse_iff {s : cycle α} : s.reverse.nontrivial ↔ s.nontrivial :=
533548
by simp [nontrivial]
534549

535-
lemma length_nontrivial {s : cycle α} (h : nontrivial s) :
536-
2 ≤ length s :=
550+
lemma length_nontrivial {s : cycle α} (h : nontrivial s) : 2 ≤ length s :=
537551
begin
538552
obtain ⟨x, y, hxy, hx, hy⟩ := h,
539553
induction s using quot.induction_on with l,
@@ -544,21 +558,20 @@ begin
544558
{ simp [bit0] }
545559
end
546560

547-
/--
548-
The `s : cycle α` contains no duplicates.
549-
-/
561+
/-- The `s : cycle α` contains no duplicates. -/
550562
def nodup (s : cycle α) : Prop :=
551563
quot.lift_on s nodup (λ l₁ l₂ (e : l₁ ~r l₂), propext $ e.nodup_iff)
552564

553-
@[simp] lemma nodup_coe_iff {l : list α} :
554-
nodup (l : cycle α) ↔ l.nodup := iff.rfl
565+
@[simp] lemma nodup_nil : nodup (@nil α) :=
566+
nodup_nil
555567

556-
@[simp] lemma nodup_reverse_iff {s : cycle α} :
557-
s.reverse.nodup ↔ s.nodup :=
568+
@[simp] lemma nodup_coe_iff {l : list α} : nodup (l : cycle α) ↔ l.nodup :=
569+
iff.rfl
570+
571+
@[simp] lemma nodup_reverse_iff {s : cycle α} : s.reverse.nodup ↔ s.nodup :=
558572
quot.induction_on s (λ _, nodup_reverse)
559573

560-
lemma subsingleton.nodup {s : cycle α} (h : subsingleton s) :
561-
nodup s :=
574+
lemma subsingleton.nodup {s : cycle α} (h : subsingleton s) : nodup s :=
562575
begin
563576
induction s using quot.induction_on with l,
564577
cases l with hd tl,
@@ -567,8 +580,7 @@ begin
567580
simp [this] }
568581
end
569582

570-
lemma nodup.nontrivial_iff {s : cycle α} (h : nodup s) :
571-
nontrivial s ↔ ¬ subsingleton s :=
583+
lemma nodup.nontrivial_iff {s : cycle α} (h : nodup s) : nontrivial s ↔ ¬ subsingleton s :=
572584
begin
573585
rw length_subsingleton_iff,
574586
induction s using quotient.induction_on',
@@ -582,27 +594,39 @@ The `s : cycle α` as a `multiset α`.
582594
def to_multiset (s : cycle α) : multiset α :=
583595
quotient.lift_on' s (λ l, (l : multiset α)) (λ l₁ l₂ (h : l₁ ~r l₂), multiset.coe_eq_coe.mpr h.perm)
584596

585-
/--
586-
The lift of `list.map`.
587-
-/
597+
@[simp] lemma coe_to_multiset (l : list α) : (l : cycle α).to_multiset = l :=
598+
rfl
599+
600+
@[simp] lemma nil_to_multiset : nil.to_multiset = (∅ : multiset α) :=
601+
rfl
602+
603+
/-- The lift of `list.map`. -/
588604
def map {β : Type*} (f : α → β) : cycle α → cycle β :=
589605
quotient.map' (list.map f) $ λ l₁ l₂ h, h.map _
590606

591-
/--
592-
The `multiset` of lists that can make the cycle.
593-
-/
607+
@[simp] lemma map_nil {β : Type*} (f : α → β) : map f nil = nil :=
608+
rfl
609+
610+
@[simp] lemma map_coe {β : Type*} (f : α → β) (l : list α) : map f ↑l = list.map f l :=
611+
rfl
612+
613+
@[simp] lemma map_eq_nil {β : Type*} (f : α → β) (s : cycle α) : map f s = nil ↔ s = nil :=
614+
quotient.induction_on' s $ λ l, by simp
615+
616+
/-- The `multiset` of lists that can make the cycle. -/
594617
def lists (s : cycle α) : multiset (list α) :=
595618
quotient.lift_on' s
596619
(λ l, (l.cyclic_permutations : multiset (list α))) $
597620
λ l₁ l₂ (h : l₁ ~r l₂), by simpa using h.cyclic_permutations.perm
598621

599-
@[simp] lemma mem_lists_iff_coe_eq {s : cycle α} {l : list α} :
600-
l ∈ s.lists ↔ (l : cycle α) = s :=
601-
begin
602-
induction s using quotient.induction_on',
603-
rw [lists, quotient.lift_on'_mk'],
604-
simp
605-
end
622+
@[simp] lemma lists_coe (l : list α) : lists (l : cycle α) = ↑l.cyclic_permutations :=
623+
rfl
624+
625+
@[simp] lemma mem_lists_iff_coe_eq {s : cycle α} {l : list α} : l ∈ s.lists ↔ (l : cycle α) = s :=
626+
quotient.induction_on' s $ λ l, by { rw [lists, quotient.lift_on'_mk'], simp }
627+
628+
@[simp] lemma lists_nil : lists (@nil α) = [([] : list α)] :=
629+
by rw [nil, lists_coe, cyclic_permutations_nil]
606630

607631
section decidable
608632

@@ -627,24 +651,22 @@ instance {s : cycle α} : decidable (nodup s) :=
627651
quot.rec_on_subsingleton s (λ (l : list α), list.nodup_decidable l)
628652

629653
instance fintype_nodup_cycle [fintype α] : fintype {s : cycle α // s.nodup} :=
630-
fintype.of_surjective (λ (l : {l : list α // l.nodup}), ⟨l.val, by simpa using l.prop⟩) (λ ⟨s, hs⟩,
631-
begin
632-
induction s using quotient.induction_on',
633-
exact ⟨⟨s, hs⟩, by simp⟩
634-
end)
654+
fintype.of_surjective (λ (l : {l : list α // l.nodup}), ⟨l.val, by simpa using l.prop⟩)
655+
(λ ⟨s, hs⟩, by { induction s using quotient.induction_on', exact ⟨⟨s, hs⟩, by simp⟩ })
635656

636657
instance fintype_nodup_nontrivial_cycle [fintype α] :
637658
fintype {s : cycle α // s.nodup ∧ s.nontrivial} :=
638659
fintype.subtype (((finset.univ : finset {s : cycle α // s.nodup}).map
639660
(function.embedding.subtype _)).filter cycle.nontrivial)
640661
(by simp)
641662

642-
/--
643-
The `s : cycle α` as a `finset α`.
644-
-/
663+
/-- The `s : cycle α` as a `finset α`. -/
645664
def to_finset (s : cycle α) : finset α :=
646665
s.to_multiset.to_finset
647666

667+
@[simp] lemma nil_to_finset : (@nil α).to_finset = ∅ :=
668+
rfl
669+
648670
/-- Given a `s : cycle α` such that `nodup s`, retrieve the next element after `x ∈ s`. -/
649671
def next : Π (s : cycle α) (hs : nodup s) (x : α) (hx : x ∈ s), α :=
650672
λ s, quot.hrec_on s (λ l hn x hx, next l x hx)
@@ -669,16 +691,11 @@ def prev : Π (s : cycle α) (hs : nodup s) (x : α) (hx : x ∈ s), α :=
669691
s.reverse.next (nodup_reverse_iff.mpr hs) x (mem_reverse_iff.mpr hx) = s.prev hs x hx :=
670692
by simp [←prev_reverse_eq_next]
671693

672-
@[simp] lemma next_mem (s : cycle α) (hs : nodup s) (x : α) (hx : x ∈ s) :
673-
s.next hs x hx ∈ s :=
674-
begin
675-
induction s using quot.induction_on,
676-
exact next_mem _ _ _
677-
end
694+
@[simp] lemma next_mem (s : cycle α) (hs : nodup s) (x : α) (hx : x ∈ s) : s.next hs x hx ∈ s :=
695+
by { induction s using quot.induction_on, apply next_mem }
678696

679-
lemma prev_mem (s : cycle α) (hs : nodup s) (x : α) (hx : x ∈ s) :
680-
s.prev hs x hx ∈ s :=
681-
by { rw [←next_reverse_eq_prev, ←mem_reverse_iff], exact next_mem _ _ _ _ }
697+
lemma prev_mem (s : cycle α) (hs : nodup s) (x : α) (hx : x ∈ s) : s.prev hs x hx ∈ s :=
698+
by { rw [←next_reverse_eq_prev, ←mem_reverse_iff], apply next_mem }
682699

683700
@[simp] lemma prev_next (s : cycle α) (hs : nodup s) (x : α) (hx : x ∈ s) :
684701
s.prev hs (s.next hs x hx) (next_mem s hs x hx) = x :=

0 commit comments

Comments
 (0)