Zulip Chat Archive

Stream: new members

Topic: perm equal to sorted list indices


Evan Lohn (Mar 29 2022 at 02:32):

Hi all, can someone point me in the right direction for the following proof:

import tactic.linarith

variables (α : Type*)

lemma mergesort_length_preserve (lst: list α) {lt: α  α  Prop} [decidable_rel lt]: (list.merge_sort lt lst).length = lst.length :=
begin
  exact list.perm.length_eq (list.perm_merge_sort lt lst),
end

lemma ind_in_sorted_list (lst: list α) (ind: fin (lst.length)) (lt: α  α  Prop) [ v1, decidable_pred (lt v1)]:
ind < (list.merge_sort lt lst).length :=
begin
  rw mergesort_length_preserve,
  exact fin.is_lt ind,
end

lemma exists_perm_eq_sort (lst: list α) (lt: α  α  Prop) [ v1, decidable_pred (lt v1)]:
 (perm : equiv.perm (fin (lst.length))),  ind: fin (lst.length), lst.nth_le (perm ind) (fin.is_lt _) = (list.merge_sort lt lst).nth_le ind (ind_in_sorted_list _ lst ind lt) :=
begin
  sorry
end

Namely, I'm not sure how to instantiate the ∃ perm. My idea was to sort a modified version of the original list where each element is a pair that also contains the original list index and reconstruct the index permutation from that... is there a better way?

P.S. In case it's relevant, I need something of this form because my proofs for my larger project require me to show that sorting the rows of a matrix is equivalent to some permutation of the matrix's rows.

Patrick Johnson (Mar 29 2022 at 09:22):

Not sure what the best way to prove it is (we probably have something along those lines in mathlib, although I don't know what), but as an answer to your question "How to instantiate the ∃ perm" - you can write a simple function that takes two list and some index i in the first list and returns the index of the same element in the second list. In case there are duplicates, you would subtract the number of equal elements previously encountered. But it would be painful to prove that it is a bijection.

Another way would be to use an inductive data type to represent list permutations:

import tactic.induction

inductive {u} perm {α : Type u} : list α  list α  Type (u+1)
| nil   : perm [] []
| cons  : Π (x : α) {l₁ l₂ : list α}, perm l₁ l₂  perm (x::l₁) (x::l₂)
| swap  : Π (x y : α) (l : list α), perm (y::x::l) (x::y::l)
| trans : Π {l₁ l₂ l₃ : list α}, perm l₁ l₂  perm l₂ l₃  perm l₁ l₃

noncomputable def perm_of_list_perm {α : Type*} {xs ys : list α} (h : xs ~ ys) : perm xs ys :=
begin
  refine (_ : nonempty _).some, induction' h,
  { exact perm.nil },
  { cases ih, exact perm.cons x ih },
  { exact perm.swap x y l },
  { cases ih_h, cases ih_h_1, exact perm.trans ih_h ih_h_1 },
end

Then you can obtain a prop permutation from list.perm_merge_sort and convert it to data using perm_of_list_perm. Then you can implement a function that constructs equiv.perm from perm recursively. Finally, you will need to prove that such permutation satisfies the nth_le relation that you need.

As a side note, when using nth_le in a lemma statement, you don't need to actually prove the requirement in order to invoke nth_le. You can simply assert that a proof exists. Your lemma statement can be simplified to:

lemma exists_perm_eq_sort (lst : list α) (lt : α  α  Prop) [Π (v1 : α), decidable_pred (lt v1)] :
   (perm : equiv.perm (fin lst.length)),  (ind : fin lst.length),  h₁ h₂,
  lst.nth_le (perm ind) h₁ = (list.merge_sort lt lst).nth_le ind h₂ :=
begin
  sorry
end

Kyle Miller (Mar 29 2022 at 16:09):

The module where docs#tuple.sort is might be helpful

Kyle Miller (Mar 29 2022 at 16:11):

You could pass it the fin version of docs#list.nth_le (I forget what that is, if there is one)


Last updated: Dec 20 2023 at 11:08 UTC