Skip to content

Proved sorted permutations are equal #2748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

MatthewDaggitt
Copy link
Contributor

The main result. Would like to try and sneak this into v2.3 for @onestruggler.

Have also added an explanation of the choice of propositional permutation in SortingAlgorithm and a lemma that proves the setoid version.

Comment on lines +1065 to +1088
injective⇒nonStrictlyContractive : (f : Fin n Fin m) Injective _≡_ _≡_ f
i ¬ ( j j ≤ i f j < i)
injective⇒nonStrictlyContractive f f-injective i j≤i⇒fj<i =
ℕ.n≮n (toℕ i) (injective⇒≤ h-injective)
where
h : Fin′ (suc i) Fin′ i
h k = lower (f (inject! k)) (j≤i⇒fj<i _ (ℕ.s≤s⁻¹ (inject!-< k)))

h-injective : Injective _≡_ _≡_ h
h-injective = inject!-injective ∘ f-injective ∘ lower-injective _ _

injective⇒existsPivot : (f : Fin n Fin m) Injective _≡_ _≡_ f
(i : Fin n) λ (j : Fin n) j ≤ i × i ≤ f j
injective⇒existsPivot {n = suc n} f f-injective i with any? (λ j j ≤? i ×-dec i ≤? f j)
... | yes result = result
... | no ¬result = contradiction
strictlyContractive
(injective⇒nonStrictlyContractive f f-injective i)
where
strictlyContractive : j j ≤ i f j < i
strictlyContractive j j≤i with i ≤? f j
... | yes i≤fj = contradiction (j , j≤i , i≤fj) ¬result
... | no i≰fj = ℕ.≰⇒> i≰fj

Copy link
Contributor

@jamesmckinna jamesmckinna Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Downstream, after resolving the issues around #2744, I'd hope that these could be read off from a single appeal to min? to construct a suitable minimal counterexample (for existsPivot) or else rule out the Universal case branch by contradiction with nonStrictlyContractive. See also #2746 for the use of pigeonhole to prove injective⇒≤, so some simplification in the proof of nonStrictlyContractive might also be possible?

inject!-< : (k : Fin′ i) → inject! k < i
lower-injective : lower i i<n ≡ lower j j<n → i ≡ j
injective⇒nonStrictlyContractive : ∀ (f : Fin n → Fin m) → Injective _≡_ _≡_ f → ∀ i → ¬ (∀ j → j ≤ i → f j < i)
injective⇒existsPivot : ∀ (f : Fin n → Fin m) → Injective _≡_ _≡_ f → ∀ (i : Fin n) → ∃ λ (j : Fin n) → j ≤ i × i ≤ f j
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any particular reason (beyond 'redundant' documentation for the sake of the reader) to include the types of i and j here? They're inferrable form the declared type of f, or not?

@@ -121,6 +121,10 @@ lower₁ {zero} zero ne = contradiction refl ne
lower₁ {suc n} zero _ = zero
lower₁ {suc n} (suc i) ne = suc (lower₁ i (ne ∘ cong suc))

lower : (i : Fin m) .(toℕ i ℕ.< n) Fin n
Copy link
Contributor

@jamesmckinna jamesmckinna Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As on previous iterations: suggest deprecating/redefining lower₁ in terms of this new definition, to avoid redundant duplication?

UPDATED: oh, I see... it would involve importing Data.Nat.Properties in order to fix up the precondition, and that might be considered A Bad Thing...

∀ {i j} → toℕ i ≡ toℕ j →
lookup ys j ≤ lookup xs i
↗↭↗⇒≤ {xs} {ys} xs↭ys xs↗ ys↗ {i} {j} i≡j
with Fin.injective⇒existsPivot _ (inverseʳ⇒injective _ (Inverse.inverseʳ (toFin xs↭ys))) i
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
with Fin.injective⇒existsPivot _ (inverseʳ⇒injective _ (Inverse.inverseʳ (toFin xs↭ys))) i
with Fin.injective⇒existsPivot _ (inverseʳ⇒injective _ (Inverse.inverseʳ (onIndices xs↭ys))) i

???

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, there's no need for with here: the pattern is irrefutable, and computable with a pattern-matching let, so...

with Fin.injective⇒existsPivot _ (inverseʳ⇒injective _ (Inverse.inverseʳ (toFin xs↭ys))) i
... | (k , k≤i , i≤π[k]) = begin
lookup ys j ≤⟨ lookup-mono-≤ O ys↗ (P.subst (ℕ._≤ _) i≡j i≤π[k]) ⟩
lookup ys (toFin xs↭ys ⟨$⟩ʳ k) ≈⟨ toFin-lookup xs↭ys k ⟨
Copy link
Contributor

@jamesmckinna jamesmckinna Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

Suggested change
lookup ys (toFin xs↭ys ⟨$⟩ʳ k) ≈⟨ toFin-lookup xs↭ys k ⟨
lookup ys (onIndices xs↭ys ⟨$⟩ʳ k) ≈⟨ onIndices-lookup xs↭ys k ⟨

Copy link
Contributor

@jamesmckinna jamesmckinna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Various nitpicks and bugfixes suggested, but otherwise: good to go!

Comment on lines +125 to +126
lower {suc _} {suc n} zero leq = zero
lower {suc _} {suc n} (suc i) leq = suc (lower i (ℕ.s≤s⁻¹ leq))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
lower {suc _} {suc n} zero leq = zero
lower {suc _} {suc n} (suc i) leq = suc (lower i (ℕ.s≤s⁻¹ leq))
lower {n = suc _} zero leq = zero
lower {n = suc _} (suc i) leq = suc (lower i (ℕ.s≤s⁻¹ leq))

I don't think there's any need to involve the m binding in the definition, and named telescopes are (typically) more robust in the face of modifications to variable declarations etc.

Comment on lines +560 to +561
lower-injective {suc _} {suc n} zero zero eq = refl
lower-injective {suc _} {suc n} (suc i) (suc j) eq =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto re: avoiding the m binding

Suggested change
lower-injective {suc _} {suc n} zero zero eq = refl
lower-injective {suc _} {suc n} (suc i) (suc j) eq =
lower-injective {n = suc n} zero zero eq = refl
lower-injective {n = suc n} (suc i) (suc j) eq =

```

* In `Data.Fin.Permutation`:
```agda
cast-id : .(m ≡ n) → Permutation m n
swap : Permutation m n → Permutation (suc (suc m)) (suc (suc n))
inject!-injective : swap : Permutation m n → Permutation (suc (suc m)) (suc (suc n))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants