idris-0.1.5: lib/perm.idr
include "vect.idr";
-- Yes, it's a DSL! One which gives a sequence of operations for converting a
-- list into its permutation.
using (x:A, xs:List A, xs':List A, xs'':List A,
ys:List A, ys':List A,
zs:List A)
{
data Perm : (List A) -> (List A) -> Set where
pnil : {A:Set} -> (Perm {A} Nil Nil)
| pskip : (Perm xs xs') -> (Perm (Cons x xs) (Cons x xs'))
| pswap : (Perm (Cons x (Cons y xs)) (Cons y (Cons x xs)))
| ptrans : (Perm xs xs') -> (Perm xs' xs'') -> (Perm xs xs'');
perm_id: Perm xs xs;
perm_id {xs=Nil} = pnil;
perm_id {xs=Cons x xs} = pskip perm_id;
perm_sym : Perm xs xs' -> Perm xs' xs;
perm_sym pnil = pnil;
perm_sym (pskip p) = pskip (perm_sym p);
perm_sym pswap = pswap;
perm_sym (ptrans p q) = ptrans (perm_sym q) (perm_sym p);
perm_refl : Perm xs xs;
perm_refl {xs=Nil} = pnil;
perm_refl {xs=Cons x xs} = pskip perm_refl;
perm_app_head : (xs:List A) ->
Perm xs' ys' -> Perm (app xs xs') (app xs ys');
perm_app_head Nil p = p;
perm_app_head (Cons x xs) p = pskip (perm_app_head xs p);
perm_add_cons : Perm (Cons x xs) (Cons x ys) -> Perm xs ys;
perm_add_cons (pskip p) = p;
perm_add_cons pswap = pskip perm_id;
perm_app : Perm xs ys -> Perm xs' ys' ->
Perm (app xs xs') (app ys ys');
perm_app {xs=Nil} {ys=Nil} p p' = p';
perm_app {xs=Cons x xs} {ys=Cons y ys} {xs'} {ys'} (ptrans p1 p2) p' =
let r1 = perm_app p1 p' in
let r2 = perm_app p2 p' in ?papp_cons;
perm_rewrite : Perm xs xs' -> Perm xs ys -> Perm xs' ys;
perm_rewrite p1 p2 = ptrans (perm_sym p1) p2;
perm_rewrite_cons : Perm (Cons x xs) xs' -> Perm xs ys ->
Perm (Cons x ys) xs';
perm_rewrite_cons (pskip p1) p2 = pskip (ptrans (perm_sym p2) p1);
perm_rewrite_cons pswap p = ptrans (pskip (perm_sym p)) pswap;
perm_rewrite_cons (ptrans p1 p2) p3 = ptrans (perm_rewrite_cons p1 p3) p2;
perm_rewrite_app : Perm (app xs ys) xs' -> Perm ys zs ->
Perm (app xs zs) xs';
perm_rewrite_app {xs=Nil} p1 p2 = perm_rewrite p2 p1;
perm_rewrite_app {xs=Cons x xs} p1 p2
= perm_rewrite_cons p1 (perm_app perm_id p2);
perm_swapr : Perm xs (Cons x (Cons y ys)) ->
Perm xs (Cons y (Cons x ys));
perm_swapr {xs=Cons a (Cons b xs)} p = ptrans p pswap;
perm_swapl : Perm (Cons x (Cons y ys)) xs ->
Perm (Cons y (Cons x ys)) xs;
perm_swapl {xs=Cons a (Cons b xs)} p = ptrans pswap p;
perm_move_cons : Perm xs (app ys (Cons x zs)) ->
Perm xs (Cons x (app ys zs));
perm_move_cons {ys=Nil} p = p;
perm_move_cons {ys=Cons y ys} p
= perm_swapr (perm_sym
(perm_rewrite_cons (perm_sym p) (perm_move_cons perm_id)));
perm_cons_move : Perm xs (Cons x (app ys zs)) ->
Perm xs (app ys (Cons x zs));
perm_cons_move {ys=Nil} p = p;
perm_cons_move {ys=Cons y ys} p
= perm_sym (perm_rewrite_cons
(perm_swapl (perm_sym p)) (perm_cons_move perm_id));
-- This is by induction on the *list* xs, not the permutation, despite
-- initial appearances.
perm_app_cons : Perm xs (app xs' ys') ->
Perm (Cons x xs) (app xs' (Cons x ys'));
perm_app_cons {xs'=Nil} {ys'=Nil} p = pskip p;
perm_app_cons {x} {xs=Cons x' xs} {xs'=Cons x' xs'}
(pskip p) = let prec = perm_app_cons {x=x} p in
perm_swapl (perm_rewrite_cons perm_id (perm_sym prec));
perm_app_cons {xs=Cons x (Cons y _)} {xs'=Cons y (Cons x _)}
pswap = perm_swapl (perm_swapr (pskip (perm_swapl
(pskip (perm_app_cons perm_id))))); -- list is smaller!
perm_app_cons {xs=Cons x' xs} {xs'=Cons x' xs'}
(ptrans p1 p2) = perm_swapl (pskip (perm_app_cons
(perm_add_cons (ptrans p1 p2)))); -- list is smaller!
-- Again by induction on the list xs. Maybe there are shorter proofs,
-- but it doesn't really matter, we're not going to run them...
perm_app_swap : Perm (app xs ys) zs -> Perm (app ys xs) zs;
perm_app_swap {xs=Nil} p ?= p; [papp_swap_nil]
perm_app_swap {xs=Cons x xs} {zs=Cons x zs}
(pskip p) = perm_sym
(perm_app_cons (perm_sym (perm_app_swap p)));
perm_app_swap {xs=Cons x (Cons y _)}
pswap = perm_swapr (perm_sym
(perm_app_cons
(perm_rewrite_cons
(perm_app_cons perm_id) (perm_app_swap perm_id))));
perm_app_swap {xs=Cons x xs} {zs=Cons z zs}
(ptrans p1 p2) = perm_sym (perm_cons_move
(perm_sym (perm_rewrite_cons
(ptrans p1 p2) (perm_app_swap perm_id))));
}
papp_cons proof {
%intro a;
%intro;
%refine ptrans;
%fill (app X xs');
%refine ptrans;
%fill (app X ys');
%fill r1;
%fill perm_app_head X (perm_sym p');
%fill r2;
%qed;
};
papp_swap_nil proof {
%intro;
%use value;
%fill app_Nil X1;
%qed;
};