PermutationFun

This module defines a boolean notion of list permutation, assuming a decidable equality on elements. Unlike the standard Permutation from the Rocq standard library (which is a Prop), this version returns a bool and is suitable for computation and reflection.
It is mainly used to prove that iterated sums or products over a list are invariant under permutations of the list, under appropriate algebraic conditions (e.g., associativity and commutativity).


From Stdlib Require Import Utf8 Arith.
From Stdlib Require FinFun.
Import Init.Nat.
Import List.ListNotations.

Require Import Misc Utils.

Definition reflexive {A} (rel : A A bool) :=
   a, rel a a = true.

Fixpoint is_permutation {A} (eqb : A A bool) (la lb : list A) :=
  match la with
  | []match lb with []true | _false end
  | a :: la'
      match List_extract (eqb a) lb with
      | Nonefalse
      | Some (bef, _, aft)is_permutation eqb la' (bef ++ aft)
      end
  end.

Definition permutation {A} (eqb : A _) la lb :=
  is_permutation eqb la lb = true.

Theorem permutation_cons_l_iff : A (eqb : A _) a la lb,
  permutation eqb (a :: la) lb
   match List_extract (eqb a) lb with
     | Some (bef, _, aft)permutation eqb la (bef ++ aft)
     | NoneFalse
     end.


Theorem permutation_cons_inv : {A} {eqb : A _},
  equality eqb
   la lb a,
  permutation eqb (a :: la) (a :: lb) permutation eqb la lb.

Theorem permutation_app_inv_aux : {A} {eqb : A _},
  equality eqb
   la lb lc ld a,
  a la
   a lc
   permutation eqb (la ++ a :: lb) (lc ++ a :: ld)
   permutation eqb (la ++ lb) (lc ++ ld).


Theorem permutation_refl : {A} {eqb : A _},
  equality eqb
   l, permutation eqb l l.

Theorem permutation_in_iff : {A} {eqb : A _},
  equality eqb
   [la lb], permutation eqb la lb a, a la a lb.
Theorem permutation_sym : {A} {eqb : A _},
  equality eqb
   la lb, permutation eqb la lb permutation eqb lb la.

Theorem permutation_nil_l : {A} {eqb : A _} l,
  permutation eqb [] l l = [].

Theorem permutation_nil_r : {A} {eqb : A _} l,
  permutation eqb l [] l = [].

Theorem permutation_trans : {A} {eqb : A _},
  equality eqb
   la lb lc,
  permutation eqb la lb permutation eqb lb lc permutation eqb la lc.


Theorem permutation_nil_nil : {A} {eqb : A _}, permutation eqb [] [].

Theorem permutation_skip : {A} {eqb : A _},
  reflexive eqb
   a la lb, permutation eqb la lb permutation eqb (a :: la) (a :: lb).

Theorem permutation_swap : {A} {eqb : A _},
  equality eqb
   a b la, permutation eqb (b :: a :: la) (a :: b :: la).


Theorem permutation_add_inv : {A} {eqb : A _} (Heqb : equality eqb),
   a la lb,
  permutation eqb la lb
   lc ld,
  permutation eqb (a :: lc) la
   permutation eqb (a :: ld) lb
   permutation eqb lc ld.


Theorem permutation_app_tail : {A} {eqb : A _},
  equality eqb
   l l' tl,
  permutation eqb l l' permutation eqb (l ++ tl) (l' ++ tl).

Theorem permutation_app_head : {A} {eqb : A _},
  equality eqb
   l tl tl',
  permutation eqb tl tl' permutation eqb (l ++ tl) (l ++ tl').

Theorem permutation_app : {A} {eqb : A _},
  equality eqb
   l m l' m',
  permutation eqb l l'
   permutation eqb m m'
   permutation eqb (l ++ m) (l' ++ m').

Theorem permutation_cons_append : {A} {eqb : A _},
  equality eqb
   l x, permutation eqb (x :: l) (l ++ [x]).

Theorem permutation_app_comm : {A} {eqb : A _},
  equality eqb
   l l', permutation eqb (l ++ l') (l' ++ l).

Theorem permutation_cons_app : {A} {eqb : A _},
  equality eqb
   l l1 l2 a,
  permutation eqb l (l1 ++ l2)
   permutation eqb (a :: l) (l1 ++ a :: l2).

Theorem permutation_middle : {A} {eqb : A _},
  equality eqb
   la lb a,
  permutation eqb (a :: la ++ lb) (la ++ a :: lb).

Theorem permutation_elt : {A} {eqb : A _},
  equality eqb
   (la lb lc ld : list A) (a : A),
  permutation eqb (la ++ lb) (lc ++ ld)
   permutation eqb (la ++ a :: lb) (lc ++ a :: ld).

Theorem permutation_rev_l : {A} {eqb : A _},
  equality eqb
   l, permutation eqb (List.rev l) l.

Theorem permutation_rev_r : {A} {eqb : A _},
  equality eqb
   l, permutation eqb l (List.rev l).

Theorem permutation_length : {A} {eqb : A _} {la lb},
  permutation eqb la lb List.length la = List.length lb.

Theorem permutation_app_inv : {A} {eqb : A _},
  equality eqb
   la lb lc ld a,
  permutation eqb (la ++ a :: lb) (lc ++ a :: ld)
   permutation eqb (la ++ lb) (lc ++ ld).
Theorem permutation_app_inv_l : {A} {eqb : A _},
  equality eqb
   l l1 l2,
  permutation eqb (l ++ l1) (l ++ l2) permutation eqb l1 l2.

Theorem permutation_app_inv_r : {A} {eqb : A _},
  equality eqb
   l l1 l2,
  permutation eqb (l1 ++ l) (l2 ++ l) permutation eqb l1 l2.

Theorem permutation_length_1 : {A} {eqb : A _},
  equality eqb
   a b,
  permutation eqb [a] [b] a = b.

Theorem permutation_length_1_inv_l :
   {A} {eqb : A _} (Heqb : equality eqb) a l,
  permutation eqb [a] l l = [a].

Theorem permutation_length_1_inv_r :
   {A} {eqb : A _} (Heqb : equality eqb) a l,
  permutation eqb l [a] l = [a].

Theorem NoDup_permutation : {A} {eqb : A _},
  equality eqb
   la lb,
  List.NoDup la
   List.NoDup lb
   ( x : A, x la x lb)
   permutation eqb la lb.
Theorem NoDup_permutation_bis : {A} {eqb : A _},
  equality eqb
   la lb,
  List.NoDup la
   List.length lb List.length la
   List.incl la lb
   permutation eqb la lb.

Theorem permutation_NoDup : {A} {eqb : A _},
  equality eqb
   [la lb],
  permutation eqb la lb List.NoDup la List.NoDup lb.

Theorem permutation_map : {A B} [eqba : A _] [eqbb : B _],
  equality eqba
  equality eqbb
   (f : A B) (la lb : list A),
  permutation eqba la lb permutation eqbb (List.map f la) (List.map f lb).


Theorem List_rank_loop_extract : A (la : list A) f i,
  List_rank_loop i f la =
  match List_extract f la with
  | Some (bef, _, _)i + List.length bef
  | Nonei + List.length la
  end.

Theorem List_rank_extract : A (la : list A) f,
  List_rank f la =
  match List_extract f la with
  | Some (bef, _, _)List.length bef
  | NoneList.length la
  end.

Theorem List_rank_not_found : n l i,
  permutation Nat.eqb l (List.seq 0 n)
   i < n
   List_rank (Nat.eqb i) l List.length l.


Definition option_eqb {A} (eqb : A A bool) ao bo :=
  match (ao, bo) with
  | (Some a, Some b)eqb a b
  | _false
  end.

Fixpoint permutation_assoc_loop {A} eqb (la : list A) lbo :=
  match la with
  | [][]
  | a :: la'
      match List_extract (λ bo, option_eqb eqb bo (Some a)) lbo with
      | Some (befo, _, afto)
          List.length befo ::
            permutation_assoc_loop eqb la' (befo ++ None :: afto)
      | None[]
      end
  end.

Definition permutation_assoc {A} (eqb : A _) la lb :=
  permutation_assoc_loop eqb la (List.map Some lb).

Definition permutation_fun {A} (eqb : A _) la lb i :=
  let j := List_rank (Nat.eqb i) (permutation_assoc eqb la lb) in
  if j =? List.length la then 0 else j.

Fixpoint filter_Some {A} (lao : list (option A)) :=
  match lao with
  | [][]
  | Some a :: lao'a :: filter_Some lao'
  | None :: lao'filter_Some lao'
  end.

Theorem fold_permutation_assoc : {A} {eqb : A _} la lb,
  permutation_assoc_loop eqb la (List.map Some lb) =
  permutation_assoc eqb la lb.

Theorem filter_Some_inside : A l1 l2 (x : option A),
  filter_Some (l1 ++ x :: l2) =
    filter_Some l1 ++
    match x with
    | Some aa :: filter_Some l2
    | Nonefilter_Some l2
    end.

Theorem filter_Some_map_Some : A (la : list A),
  filter_Some (List.map Some la) = la.

Theorem permutation_assoc_loop_length : {A} {eqb : A _},
  equality eqb
   la lbo,
  permutation eqb la (filter_Some lbo)
   List.length (permutation_assoc_loop eqb la lbo) = List.length la.

Theorem permutation_assoc_length : {A} {eqb : A _},
  equality eqb
   {la lb},
  permutation eqb la lb
   List.length (permutation_assoc eqb la lb) = List.length la.

Theorem permutation_assoc_loop_ub : {A} {eqb : A _},
  equality eqb
   la lbo i,
  permutation eqb la (filter_Some lbo)
   i < List.length la
   List.nth i (permutation_assoc_loop eqb la lbo) 0 < List.length lbo.

Theorem permutation_assoc_loop_None_inside : {A} {eqb : A _},
  equality eqb
   la lbo lco,
  permutation_assoc_loop eqb la (lbo ++ None :: lco) =
  List.map (λ i, if i <? List.length lbo then i else S i)
    (permutation_assoc_loop eqb la (lbo ++ lco)).
Theorem filter_Some_app : A (l1 l2 : list (option A)),
  filter_Some (l1 ++ l2) = filter_Some l1 ++ filter_Some l2.

Theorem permutation_assoc_loop_nth_nth : {A} {eqb : A _},
  equality eqb
   d la lbo i j,
  permutation eqb la (filter_Some lbo)
   i < List.length la
   List.nth i (permutation_assoc_loop eqb la lbo) 0 = j
   List.nth i la d = unsome d (List.nth j lbo None).

Theorem unmap_Some_app_cons : A (a : A) la lbo lco,
  List.map Some la = lbo ++ Some a :: lco
   lbo = List.map Some (filter_Some lbo)
    lco = List.map Some (filter_Some lco)
    la = filter_Some lbo ++ a :: filter_Some lco.

Theorem permutation_permutation_assoc : {A} {eqb : A _},
  equality eqb
   {la lb},
  permutation eqb la lb
   permutation Nat.eqb (permutation_assoc eqb la lb)
      (List.seq 0 (List.length la)).

Theorem map_permutation_assoc : {A} {eqb : A _},
  equality eqb
   d [la lb],
  permutation eqb la lb
   la = List.map (λ i, List.nth i lb d) (permutation_assoc eqb la lb).

Theorem permutation_fun_nth : {A} {eqb : A _},
  equality eqb
   d la lb i,
  permutation eqb la lb
   i < List.length la
   List.nth i lb d = List.nth (permutation_fun eqb la lb i) la d.

Theorem permutation_nth : {A} {eqb : A _},
  equality eqb
   la lb d,
  permutation eqb la lb
   (let n := List.length la in
     List.length lb = n
      f : nat nat,
     FinFun.bFun n f
     FinFun.bInjective n f
     ( x : nat, x < n List.nth x lb d = List.nth (f x) la d)).
Theorem permutation_partition : {A} {eqb : A _},
  equality eqb
   f la lb lc,
  List.partition f la = (lb, lc)
   permutation eqb la (lb ++ lc).
Fixpoint transp_loop {A} (eqb : A A bool) i la lb :=
  match lb with
  | [][]
  | b :: lb'
      match List_extract (eqb b) la with
      | Some ([], _, la2)transp_loop eqb (S i) la2 lb'
      | Some (a :: la1, _, la2)
          (i, S (i + List.length la1)) ::
          transp_loop eqb (S i) (la1 ++ a :: la2) lb'
      | None[]
      end
  end.

Definition transp_list {A} (eqb : A _) la lb := transp_loop eqb 0 la lb.

Definition swap_d {A} d i j (la : list A) :=
   List.map
     (λ k, List.nth (if k =? i then j else if k =? j then i else k) la d)
     (List.seq 0 (List.length la)).

Definition swap {A} i j (la : list A) :=
  match la with
  | [][]
  | d :: _swap_d d i j la
  end.

Definition apply_transp_list {A} trl (la : list A) :=
  List.fold_left (λ lb ij, swap (fst ij) (snd ij) lb) trl la.

Definition shift_transp i trl :=
  List.map (λ ij, (fst ij + i, snd ij + i)) trl.

Theorem fold_apply_transp_list : A trl (la : list A),
  List.fold_left (λ lb ij, swap (fst ij) (snd ij) lb) trl la =
  apply_transp_list trl la.

Theorem transp_loop_shift : {A} {eqb : A _},
  equality eqb
   i la lb,
  transp_loop eqb i la lb = shift_transp i (transp_list eqb la lb).

Theorem swap_length : A (la : list A) i j,
  List.length (swap i j la) = List.length la.

Theorem apply_transp_list_shift_1_cons : A (a : A) la trl,
  ( ij, ij trl fst ij < snd ij < List.length la)
   apply_transp_list (shift_transp 1 trl) (a :: la) =
    a :: apply_transp_list trl la.

Theorem in_transp_loop_length : {A} {eqb : A _},
  equality eqb
   la lb,
  List.length la = List.length lb
   i j k,
  (i, j) transp_loop eqb k la lb
   i < j < k + List.length la.

Theorem in_transp_list_length : {A} {eqb : A _},
  equality eqb
   la lb,
  List.length la = List.length lb
   i j,
  (i, j) transp_list eqb la lb
   i < j < List.length la.

Theorem permutation_transp_list : {A} {eqb : A _},
  equality eqb
   la lb,
  permutation eqb la lb
   apply_transp_list (transp_list eqb la lb) la = lb.

Theorem swap_d_inside : A (d : A) l1 l2 l3 x y,
  swap_d d (List.length l1) (S (List.length (l1 ++ l2)))
    (l1 ++ x :: l2 ++ y :: l3) =
  l1 ++ y :: l2 ++ x :: l3.

Theorem permutation_transp_inside : {A} {eqb : A _},
  equality eqb
   l1 l2 l3 x y,
  permutation eqb (l1 ++ y :: l2 ++ x :: l3) (l1 ++ x :: l2 ++ y :: l3).

Theorem permutation_swap_any : {A} {eqb : A _},
  equality eqb
   i j la,
  i < j < List.length la
   permutation eqb (swap i j la) la.

Theorem iter_list_permut : {A} {eqb : A _},
  equality eqb
   T (d : T) (op : T T T) (l1 l2 : list A) f
  (op_d_l : x, op d x = x)
  (op_d_r : x, op x d = x)
  (op_comm : a b, op a b = op b a)
  (op_assoc : a b c, op a (op b c) = op (op a b) c),
  permutation eqb l1 l2
   iter_list l1 (λ (c : T) i, op c (f i)) d =
    iter_list l2 (λ (c : T) i, op c (f i)) d.

Theorem incl_incl_permutation : {A} {eqb : A _},
  equality eqb
   la lb,
  List.NoDup la
   List.NoDup lb
   la lb
   lb la
   permutation eqb la lb.
Theorem permutation_firstn : {A} {eqb : A _} d,
  equality eqb
   P n la lb,
  ( i, i < n P (List.nth i la d) P (List.nth i lb d))
   ( i,
      n i < List.length la
       ¬ P (List.nth i la d) ¬ P (List.nth i lb d))
   permutation eqb la lb
   permutation eqb (List.firstn n la) (List.firstn n lb).
Theorem permutation_app_permutation_l : {A} {eqb : A _},
  equality eqb
   la lb lc ld,
  permutation eqb (la ++ lb) (lc ++ ld)
   permutation eqb la lc
   permutation eqb lb ld.

Theorem permutation_filter : {A} {eqb : A _},
  equality eqb
   f la lb,
  permutation eqb la lb
   permutation eqb (List.filter f la) (List.filter f lb).

This page has been generated by coqdoc