Inductive perm (s1 s2 : seq A) : Prop :=
| permutation_nil of s1 = [::] & s2 = [::]
| permutation_skip x t1 t2 of s1 = x :: t1 & s2 = x :: t2 & perm t1 t2
| permutation_swap x y t of s1 = x :: y :: t & s2 = y :: x :: t
| permutation_trans t of perm s1 t & perm t s2.

(* Specifications: *)
Lemma perm_nil (s : seq A) : perm [::] s <-> s = [::].
Lemma perm_refl (s : seq A) : perm s s.
Hint Resolve perm_refl : core.
Lemma perm_sym s1 s2 : perm s1 s2 <-> perm s2 s1.
Lemma perm_trans s2 s1 s3 : perm s1 s2 -> perm s2 s3 -> perm s1 s3.
Lemma perm_cat2lL s s1 s2 : perm s1 s2 -> perm (s ++ s1) (s ++ s2).
Lemma perm_catL s1 t1 s2 t2 :
perm s1 s2 -> perm t1 t2 -> perm (s1 ++ t1) (s2 ++ t2).
Lemma perm_cat_consL s1 t1 s2 t2 x :
perm s1 s2 -> perm t1 t2 -> perm (s1 ++ x :: t1) (s2 ++ x :: t2).
Lemma perm_catC s1 s2 : perm (s1 ++ s2) (s2 ++ s1).
Hint Resolve perm_catC : core.
Lemma perm_cons_catCA s1 s2 x : perm (x :: s1 ++ s2) (s1 ++ x :: s2).
Lemma perm_cons_catAC s1 s2 x : perm (s1 ++ x :: s2) (x :: s1 ++ s2).
(* a somewhat generalized induction principle *)
Lemma perm_ind2 (P : seq A -> seq A -> Prop) :
P [::] [::] ->
(forall x s1 s2, perm s1 s2 -> P s1 s2 ->
P (x :: s1) (x :: s2)) ->
(forall x y s1 s2, perm s1 s2 -> P s1 s2 ->
P (y :: x :: s1) (x :: y :: s2)) ->
(forall s2 s1 s3, perm s1 s2 -> P s1 s2 ->
perm s2 s3 -> P s2 s3 -> P s1 s3) ->
forall s1 s2, perm s1 s2 -> P s1 s2.
(* Now the hard part; the opposite implications *)
Lemma perm_cat_consR s1 t1 s2 t2 x :
perm (s1 ++ x :: t1) (s2 ++ x :: t2) -> perm (s1 ++ t1) (s2 ++ t2).
Lemma perm_cons x s1 s2 : perm (x :: s1) (x :: s2) <-> perm s1 s2.
Lemma perm_cons_cat_cons x s1 s2 s :
perm (x :: s) (s1 ++ x :: s2) <-> perm s (s1 ++ s2).
Lemma perm_cat_cons x s1 s2 t1 t2 :
perm (s1 ++ x :: t1) (s2 ++ x :: t2) <-> perm (s1 ++ t1) (s2 ++ t2).
Lemma perm_cat2l s1 s2 s3: perm (s1 ++ s2) (s1 ++ s3) <-> perm s2 s3.
Lemma perm_cat2r s1 s2 s3 : perm (s2 ++ s1) (s3 ++ s1) <-> perm s2 s3.
Lemma perm_catAC s1 s2 s3 : perm ((s1 ++ s2) ++ s3) ((s1 ++ s3) ++ s2).