Module rs_admissible

Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq div choice fintype.
Require Import finset zmodp ssralg rs_definitions aux_lemmas rs_dvf advf_type.

Set Implicit Arguments.
Unset Strict Implicit.
Import Prenex Implicits.






Section admissible.


Section rs_adm_prop5.

Section sequences_norep.

Fixpoint subseq (T:eqType) (s1 s2 : seq T) :=
if s2 is y :: s2' then if s1 is x :: s1' then if (x \in s2) then subseq s1' s2 else false else true
else s1 == [::].


Lemma subseqtail (s2 r2:seq (seq nat)) :
   r2!= [::] -> subseq s2 (behead r2) -> subseq s2 r2.
Proof.
elim H: s2=>[|s21 s22 HI]; first by case H1: r2.
rewrite {1}/subseq -/subseq => H1.
case H2: r2 =>[|r21 r22]; first by move: H1; rewrite H2.
case H3: (behead (r21 :: r22))=>[|r3 r4]; first by done.
case H4: (s21 \in r3 :: r4); last by done.
rewrite /subseq -/subseq -H3 -H2 => H5; move: (HI H1 H5)=> ->.
have ->: (s21 \in r2); last by done.
by move: H4; rewrite -H3 /behead H2 inE => ->; rewrite Bool.orb_true_r.
Qed.


Lemma last_last (k a1:nat)(a2:seq nat): a2!=[::] -> last k a2 = last k (a1::a2).
Proof.
by elim: a2.
Qed.


Lemma last_in (k i:nat)(a:seq nat): (a!=[::]) -> ((last k a)= i) -> (i \in a).
Proof.
elim H: a=>[|a1 a2 H3]; first by done.
move=> H5.
case H2: a2=>[|a21 a22]; first by rewrite inE /= => ->.
have H6: (a2!=nil); first by rewrite H2.
rewrite -H2 -(last_last k a1 H6) => H7.
rewrite inE; apply/orP; right; apply:(H3 H6 H7).
Qed.

Lemma in_concat (s1 k:nat)(s2:seq nat): (s1 \in s2 ++ [:: k]) = ((s1 \in s2) || (s1 == k)).
Proof.
elim H: s2 =>[|s21 s22 HH]; first by rewrite inE.
by rewrite mem_cat !inE.
Qed.


Lemma uniq_last (n i:nat)(s:seq nat): (s!=[::]) -> (n= last i s) -> uniq (n::s)=false.
Proof.
elim H: s=>[|s1 s2 H1]; first by done.
case H2: s2=>[|s21 s22].
  move => _ -> /=.
  by rewrite inE Bool.andb_true_r /=; apply/eqP.
rewrite -H2 => H3 H4.
have H5: (s2!=[::]); first by rewrite H2.
move: (@last_last i s1 s2)=>H6.
move: (H6 H5)=> H7; rewrite -H7 in H4.
move: (H1 H5 H4)=>H8.
rewrite /uniq.
have ->: (n \notin (s1::s2)) = false; last first.
  by rewrite Bool.andb_false_l.
rewrite inE.
have ->: (n \in s2); last first.
  by rewrite Bool.orb_true_r.
move:H4; move/eqP; rewrite eq_sym; move/eqP=> H4.
by rewrite (last_in H5 H4).
Qed.



Lemma subseq_norep_seq (s:seq nat)(rest: seq (seq nat)):
  subseq [::s] rest -> norep rest -> uniq s.
Proof.
elim H: rest=>[|r1 r2 HI]; first by done.
move=> H1 H2.
have H3: (norep r2).
  case H3: r2=>[|r21 r22]; first by done.
  move:H2; rewrite /norep /=.
  by move/andP=> [_ H4]; move:H4; rewrite H3 /=.
move: H1; rewrite /=.
case H4:(s \in r1 :: r2); last by done.
move:H4; rewrite inE; move/orP =>[H5|H6] _.
  move: (eqP H5)=> ->.
  move:H2; rewrite /=. by move/andP=> [-> _].
have H7: (subseq [:: s] r2).
  rewrite /=.
  case H7: r2=>[|r21 r22]; first by move:H6; rewrite H7.
  by rewrite -H7 H6.
by apply:(HI H7 H3).
Qed.


Lemma norepik (i k:nat):
  i != k -> norep [:: [:: i, k & [::]]].
Proof.
by rewrite /= inE=> ->.
Qed.


Lemma noreprev (k:nat)(s:seq nat): norep [::s] -> (k\in s)=false ->
   norep ([::s ++ [::k]]) = norep ((k::s)::[::]).
Proof.
elim H: s =>[|s1 s2 HH]; first by done.
move=> H1 H2; rewrite /=.
case H3: s2=>[|s21 s22]; first rewrite /=.
  case H4: (s1==k).
    by move:(eqP H4) => ->.
  rewrite !inE.
  move:H4; move/eqP; move/eqP => H4.
  rewrite H4. by move: H4; rewrite eq_sym => ->.
have H4: (norep [::s2]).
  move: H1; rewrite /=; case: (uniq s2); first by done.
  by rewrite Bool.andb_true_r Bool.andb_false_r.
have H5: (k \in s2) =false.
  move:H2; rewrite inE=> H5.
  by move: (@Bool.orb_false_elim (k==s1)(k\in s2) H5) => [H6 H7].
move: (HH H4 H5)=> H6.
have H7: (k==s1)= false.
  move:H2; rewrite inE => H7.
  by move: (@Bool.orb_false_elim (k==s1)(k\in s2) H7) => [H9 H8].
rewrite -H3.

rewrite inE H7 H5 /=.
rewrite in_concat eq_sym H7; apply/orP; rewrite Bool.orb_false_r Bool.andb_true_r.
case H8:((s1 \notin s2) && uniq s2).
rewrite cat_uniq /= H5 /=.
by move:H8; rewrite Bool.andb_true_r => ->; apply/orP.
rewrite cat_uniq /= H5 /= Bool.andb_true_r.
by apply/orP; rewrite Bool.orb_false_r H8.
Qed.


Lemma norep_cat (r1 r2:seq (seq nat)): norep (r1 ++ r2) = norep r1 && norep r2.
Proof.
 elim H: r1=>[|t s]; first by rewrite /=.
 elim : r2 => [|r21 r22].
   move=> H1.
   by rewrite !cats0 /= Bool.andb_true_r.
move=> H1 H2.
  rewrite /norep /=.
by rewrite all_cat /= Bool.andb_assoc.
Qed.


Lemma norephead (s1:seq nat)(s2:seq (seq nat)): norep(s1::s2) -> norep [::s1].
Proof.
by rewrite /=; case H: (uniq s1).
Qed.


Lemma getfirstE_in (k:nat)(s2:seq nat)(rest:seq(seq nat)):
  s2 \in rest -> head 0 s2 = k -> s2 \in getfirstE k rest.
Proof.
elim H: rest => [|r1 r2 HI]; first by done.
rewrite inE; move/orP=> [H1 |H2] H3.
  move:(eqP H1) => <- /=.
  move: H3; move/eqP=>H3; rewrite H3 inE.
  by have H4: ((s2 == s2)); last by rewrite H4.
move: (HI H2 H3)=>H4 /=.
by case: (head 0 r1 == k ); first by rewrite inE H4 Bool.orb_true_r.
Qed.


End sequences_norep.



Section getfirst_last.

Lemma getfirstE_headtail (k:nat)(t:seq nat)(s:seq (seq nat)):
  getfirstE k (t::s) = ((getfirstE k (t::nil))++ (getfirstE k s)).
Proof.
rewrite /getfirstE /=.
case H: (head 0 t == k); first by rewrite cat1s.
by rewrite cat0s.
Qed.



Lemma getlastE_headtail (k:nat)(t:seq nat)(s:seq (seq nat)):
  getlastE k (t::s) = ((getlastE k (t::nil))++ (getlastE k s)).
Proof.
rewrite /getlastE /=.
case H: (last 0 t == k); first by rewrite cat1s.
by rewrite cat0s.
Qed.


Lemma getfirstEnil (k:nat)(t:seq nat)(s:seq (seq nat)):
  getfirstE k (t::s) = [::] -> ((getfirstE k s)=[::]).
Proof.
elim H:t=>[|t1 s1]; first by rewrite /=; case: (last 0 [::]==k).
by rewrite /=; case: (head 0 (t1 :: s1) == k).
Qed.


Lemma getlastEnil (k:nat)(t:seq nat)(s:seq (seq nat)):
  getlastE k (t::s) = [::] -> ((getlastE k s)=[::]) .
Proof.
elim H:t=>[|t1 s1]; first by rewrite /=; case: (last 0 [::]==k).
by rewrite /=; case: (last 0 (t1 :: s1) == k).
Qed.


Lemma in_getfirstE (k:nat)(s1:seq nat)(s:seq (seq nat)):
  s1 \in s -> head 0 s1 = k -> getfirstE k s!= [::].
Proof.
elim H: s=>[|s2 s3 HI]; first by done.
rewrite inE.
move/orP=>[H1|H1].
  move/eqP=> H2.
  move: (eqP H1) => <-.
  by rewrite /getfirstE -/getfirstE /= H2.
move=>H2.
move:(HI H1 H2); rewrite getfirstE_headtail => H3.
by case H4:(getfirstE k [:: s2])=>[|l1 l2]; first by rewrite H3.
Qed.

Lemma in_getlastE (k:nat)(s1:seq nat)(s:seq (seq nat)):
  s1 \in s -> last 0 s1 = k -> getlastE k s!= [::].
Proof.
elim H: s=>[|s2 s3 HI]; first by done.
rewrite inE.
move/orP=>[H1|H1].
  move:(eqP H1) => ->.
  rewrite /getlastE -/getlastE /=.
  by move/eqP => ->.
move=>H2.
move:(HI H1 H2); rewrite getlastE_headtail => H3.
by case H4:(getlastE k [:: s2])=>[|l1 l2]; first by rewrite H3.
Qed.


Lemma ingetlastE_last (i:nat)(x:seq nat)(rest:seq (seq nat)):
    x \in getlastE i rest -> last 0 x = i.
Proof.
elim H: rest =>[|r1 r2 HI]; first by done.
rewrite /=.
case H1: (last 0 r1 == i); last by apply: HI.
rewrite inE; move/orP=>[H2 |H2]; last by apply: HI.
by move: (eqP H2) => ->; apply/eqP; rewrite H1.
Qed.


Lemma ingetfirst (i:nat)(x:seq nat)(rest:seq (seq nat)):
    x \in getfirstE i rest -> head 0 x = i.
Proof.
elim H: rest =>[|r1 r2 HI]; first by done.
rewrite /=.
case H1: (head 0 r1 == i); last by apply: HI.
rewrite inE; move/orP=>[H2 |H2]; last by apply: HI.
by move: (eqP H2) => ->; apply/eqP; rewrite H1.
Qed.


Lemma subseq_subseqgetfirstE (k:nat)(s2 rest : seq (seq nat)):
  (subseq s2 rest) -> subseq (getfirstE k s2) (getfirstE k rest).
Proof.
elim H: s2=>[|s21 s22 HI].
  by rewrite /=; case H1: (getfirstE k rest).
rewrite {1}/subseq -/subseq.
case H1: rest=>[|r1 r2]; first by move/eqP.
case H2: (s21 \in r1 :: r2); last by done.
rewrite -H1=> H3; move:(HI H3)=>H4.
rewrite /getfirstE -/getfirstE /=.
case H5:(head 0 s21 == k); last by done.
case H6:((filter [pred s | head 0 s == k] rest)) =>[|c1 c2]; last first.
  rewrite /subseq -/subseq.
  move:(eqP H5)=>H51.
  move: (getfirstE_in H2 H51). rewrite /getfirstE -H1 H6 => ->.
  by move:H4; rewrite /getfirstE H6.
rewrite -H1 in H2.
by move:(eqP H5) => H51; move: (in_getfirstE H2 H51); rewrite /getfirstE H6; move/eqP.
Qed.


Lemma ingetlastE (k:nat)(s2:seq nat)(rest:seq(seq nat)):
  s2 \in rest -> last 0 s2 = k -> s2 \in getlastE k rest.
Proof.
elim H: rest => [|r1 r2 HI]; first by done.
rewrite inE; move/orP=> [H1 |H2] H3.
  move:(eqP H1) => <- /=.
  move: H3; move/eqP=>->; rewrite inE.
  by have ->: ((s2 == s2)).
move: (HI H2 H3)=>H4 /=.
by case: (last 0 r1 == k); first by rewrite inE H4 Bool.orb_true_r.
Qed.



Lemma subseq_subseqgetlastE (k:nat)(s2 rest : seq (seq nat)):
  (subseq s2 rest) -> subseq (getlastE k s2) (getlastE k rest).
Proof.
elim H: s2=>[|s21 s22 HI]; first by rewrite /=; first case: (getlastE k rest).
rewrite {1}/subseq -/subseq.
case H1: rest=>[|r1 r2]; first by move/eqP.
case H2: (s21 \in r1 :: r2); last by done.
rewrite -H1=> H3; move:(HI H3)=>H4; rewrite /getlastE -/getlastE /=.

case H5:(last 0 s21 == k); last by done.
case H6:((filter [pred s | last 0 s == k] rest)) =>[|c1 c2]; last first.
  rewrite /subseq -/subseq.
  move:(eqP H5)=>H51.
  move: (ingetlastE H2 H51). rewrite /getlastE -H1 H6 => ->.
  by move:H4; rewrite /getlastE H6.
rewrite -H1 in H2.
by move:(eqP H5) => H51; move: (in_getlastE H2 H51); rewrite /getlastE H6; move/eqP.
Qed.


Lemma subseq_concat (a b rest:seq (seq nat)):
  subseq (a++b) rest = subseq a rest && subseq b rest.
Proof.
case H: rest =>[|r1 r2]; first by elim: a.
elim H1: a=>[|a1 a2 HI]; first by done.
rewrite /=.
by case H2:(a1 \in r1 :: r2); first by rewrite HI.
Qed.


Lemma inseq (i a1: seq nat)(a2:seq (seq nat)): i \in a2 -> i \in (a1::a2).
Proof.
by move=> H; rewrite inE H Bool.orb_true_r.
Qed.


Lemma insubseq (s:seq nat)(r:seq (seq nat)):
  s \in r -> subseq [::s] r.
Proof.
elim H: r=>[|r1 r2 HI]; first by done.
rewrite inE; move/orP=>[H1|H1].
  move:(eqP H1) => <- /=.
  by have ->: (s \in s :: r2); first by rewrite inE; apply/orP; left.
move: (HI H1)=> H3.
by have H4: (r1::r2!=[::]); last by apply: (subseqtail H4 H3).
Qed.


Lemma subseq_behead (r:seq (seq nat)):
  subseq (behead r) r.
Proof.
elim H: r=>[|r1 r2 HI]; first by done.
case H1: r2=>[|r21 r22]; first by done.
rewrite /=.
have ->: (r21 \in [:: r1, r21 & r22]); first by rewrite !inE; apply/orP; right; apply/orP; left.
rewrite H1 /behead in HI.
by have H2: ([:: r1, r21 & r22]!=[::]); last by apply:(subseqtail H2 HI).
Qed.


Lemma subseq_getfirstE (k:nat)(rest:seq (seq nat)):
 (subseq (getfirstE k rest)rest).
Proof.
elim H: rest =>[|r1 r2 HI]; first by done.
rewrite /getfirstE -/getfirstE.
have H2: (r1::r2!=[::]); first by done.
move: (subseqtail H2 HI)=>H3 /=.
case H1: (head 0 r1 == k); last by rewrite H3.
rewrite /subseq -/subseq inE //=.
have -> : r1 == r1; first by done.
by move:H3; rewrite /= /getfirstE.
Qed.


Lemma subseq_getlastE (i:nat)(rest:seq (seq nat)): (subseq (getlastE i rest)rest).
Proof.
elim H: rest =>[|r1 r2 HI]; first by done.
rewrite /getlastE -/getlastE.
have H2: (r1::r2!=[::]); first by done.
move: (subseqtail H2 HI)=>H3 /=.
case H1: (last 0 r1 == i); last by rewrite H3.
rewrite /subseq -/subseq inE //=.
have -> : r1 == r1; first by done.
by move:H3; rewrite /= /getlastE.
Qed.

End getfirst_last.





Section canAddOrder.


Lemma norepAddOrders (i k:nat)(s:seqZ2): i!=k -> s!= [::]
 ->((head false s) != false) -> canAddOrders i k s [::] ->
 norep (addOrders i k s [::]) = norep (addOrders i (k+1) (behead s) ((i::k::nil)::nil)).
Proof.
move=> H2.
elim H8: s=>[|s21 s22 HH]; first by done.
move=> H3 H4 H5 /=.
case H6: s22=>[|s3 s4]; last by rewrite /head in H4; rewrite H2 H4.
by rewrite /head in H4; rewrite H2 H4 /addOrders /=.
Qed.



Lemma canAddOrder_tail (i k:nat)(a:seq nat)(rest: seq (seq nat)):
 (i!=k) -> uniq a ->
     (canAddOrder i k (a ::rest)) -> (canAddOrder i k rest).
Proof.
move=> H H4 /=.
elim H5: rest=>[|r1 r2 HH]; first by rewrite /= H.
by case H6: r2; case:(nocycles_order i k a == true); rewrite H.
Qed.



Lemma last_possize (s:seq nat):
uniq s -> s!=[::] -> ((index (last 0 s) s) = (size s) - 1).
Proof.
elim H: s=>[|s1 s2]; first by done.
move=> HI H1 H2.
have H3: (uniq s2).
  by move: H1; rewrite /uniq -/uniq; move/andP=>[_ ->].
case H4: (s2==[::]).
  rewrite (eqP H4) /=.
  by have ->: (s1 == s1).
move: H4; move/eqP; move/eqP.
move=> H6; move: (HI H3 H6) => H7.
rewrite /=.
case H8:(s1 == last s1 s2).
  move: H8; move/eqP; case H9: s2=>[|s21 s22]; first by done.
  rewrite -H9 => H10.
  by move: H1; rewrite (uniq_last H6 H10).
move: H6 H7; case H9: s2=>[|s21 s22]; first by done.
move=> H6;
rewrite /= => ->.
by rewrite !subn1 /=.
Qed.



Lemma norepAddOrder_order_head (i k:nat)(d1:seq nat)(d2:seq (seq nat)):
i != k -> norep (d1::d2) ->
canAddOrder i k (d1::d2) -> norep (addOrder_order i k d1) = true.
Proof.
move => H2 H4.
rewrite /= H2.
case H6: (nocycles_order i k d1 == true); last by move: H4.
rewrite /addOrder_order => _.
case H9:d1=>[|d11 d12]; first by done.
move:H6; rewrite /nocycles_order H9.
have ik: (i==k)=false; first by apply/eqP; apply/eqP.
case H10: d12=>[|d31 d32].
  case H11: (i == last 0 [:: d11]).
    case H12:(k == head 0 [:: d11]); first by done.
    move: H11; rewrite /=; move/eqP => <-.
    by rewrite !inE /= (eq_sym k _) ik.
  case H12: (k == head 0 [:: d11]); last by done.
  move:H12; rewrite /=; move/eqP => <-.
  by rewrite !inE /= (eq_sym k _) ik.
case H13:((i \in [:: d11, d31 & d32]) == false).
  case H14:(i == last 0 [:: d11, d31 & d32]).
    have H15: ([:: d11, d31 & d32]!=[::]); first by done.
    have H16: (last 0 [:: d11, d31 & d32] = i); first by move:H14; move/eqP => ->.
    move: (last_in H15 H16).
    by have ->: (i \in [:: d11, d31 & d32])=false; first by move:H13; move/eqP.
  case H15:(k == head 0 [:: d11, d31 & d32]); last by done.
  rewrite /norep.
  have: (all uniq ([:: [:: i] ++ [:: d11, d31 & d32]])); last by move=> ->.
  move: (eqP H15) => /= H151.
  have H16: (i == d11)=false; first by rewrite -H151; apply/eqP; apply/eqP.
  rewrite inE H16.
  have H17: (i==d31)=false.
    move:(eqP H13); rewrite !inE H16.
    move: (@Bool.orb_false_elim (i == d31)(i \in d32)) => H17 H18.
    by move: (H17 H18); move=>[H19 H20].
  rewrite !inE H17.
  have H18: (d11 == d31)=false; last first.
    move: H13; rewrite H18 inE H16 Bool.orb_false_l inE H17 Bool.orb_false_l; move/eqP => H19.
    case H20: d32=>[|d221 d222]; first by rewrite /=.
    rewrite -H20.
    rewrite H19 /=.
    move: H4; rewrite H9 H10 /norep.
    case H23: (all uniq ([:: d11, d31 & d32] :: d2)); last by done.
    move:H23; rewrite /=.
    rewrite !inE. move/andP =>[H21 H22].
    move:H21; move/andP=> [H21 H23]; move:H23; move/andP=> [H23 H24].
    move:H21; rewrite Bool.negb_orb; move/andP=> [_ ->].
    by rewrite H23 H24.
  move:H4; rewrite H9 H10 /=.
  case H18:(d11 \notin d31 :: d32); last by done.
  move: H18; rewrite inE Bool.negb_orb. move/andP=>[H18 _] _.
  by apply/eqP; apply/eqP.
case H14:((k \in [:: d11, d31 & d32]) == false).
  case H15:(i == last 0 [:: d11, d31 & d32]).
    case H16:(k == head 0 [:: d11, d31 & d32]).
      move: (eqP H16); rewrite /head => H161.
      move: H14; rewrite H161 inE; move/eqP.
      move: (@Bool.orb_false_elim (d11 == d11)(d11 \in d31 :: d32)) => H17 H18.
      by move:(H17 H18) => [H19 H20].
    rewrite -H10 -H9 noreprev /norep.
        have ->: (all uniq [:: k :: d1]); last by done.
        rewrite /=; move: (eqP H14); rewrite -H10 -H9 =>H141.
        move: H4; rewrite /norep /=; move/andP=>[-> _].
        rewrite !Bool.andb_true_r.
        by move:H141; rewrite H9 inE => ->.
      apply:(norephead H4).
    case H17:(k == head 0 [:: d11, d31 & d32]); first by move:H16; rewrite H17.
    by move: (eqP H14); rewrite -H10 -H9.
  case H16:(k == head 0 [:: d11, d31 & d32]); last by done.
  move: (eqP H16); rewrite /head => H161.
  move: (eqP H14); rewrite H161 inE => H17.
  move: (@Bool.orb_false_elim (d11 == d11)(d11 \in d31 :: d32) H17) => [H18 H19].
  by move:H18; move/eqP.
case H15: (index i [:: d11, d31 & d32] < index k [:: d11, d31 & d32]); last by done.
case H16:(i == last 0 [:: d11, d31 & d32]).
  have H17: (uniq [:: d11, d31 & d32]).
    by move: H4; rewrite H9 H10 /norep /=; move/andP=>[-> _].
  have H25: ([:: d11, d31 & d32]!=[::]); first by done.
  move: (last_possize H17 H25) => hh.
  move: H13; case H13: ((i \in [:: d11, d31 & d32])); last by done.
  move: H14; case H14: ((k \in [:: d11, d31 & d32])); last by done.
  move: (index_mem i [:: d11, d31 & d32])=> h15.
  move: (index_mem k [:: d11, d31 & d32])=> h16.
  rewrite -h16 in H14; rewrite -h15 in H13.
  move: H15; rewrite (eqP H16) hh; move:H14.
  case hh1 :( size [:: d11, d31 & d32])=> [|n]; first by done.
  rewrite subn1 ltnS.
  have -> : (n.+1.-1 = n); first by done.
  move=> H15 H161.
  by move: (leq_ltn_trans H15 H161); rewrite ltnn.
case H17:(k == head 0 [:: d11, d31 & d32]); last by done.
have H22: ([:: d11, d31 & d32] !=[::]); first by done.
move: H17; move/eqP; rewrite /head=> H23.
move: H15; rewrite H23 /=.
have -> : (d11 == d11); first by done.
case H24: (index i [:: d11, d31 & d32]) =>[|n]; last first.
  by case H25: n; first by done.
have H21: (i \in [:: d11, d31 & d32]); first by move:H13; move/eqP; case:((i \in [:: d11, d31 & d32])).
have H25: (uniq [:: d11, d31 & d32]).
  move: H4; rewrite -H10 -H9.
  by rewrite /norep /=; move /andP =>[-> _].
case H26:(d11== i); first by done.
by case h27: (d31==i); first by done.
Qed.



Lemma canAddOrder_norep (i k:nat)(d:seq (seq nat)):
 i != k -> norep d->
 canAddOrder i k d -> norep (addOrder_orders i k d).
Proof.
move=> H2.
elim H3: d=>[|d1 d2 H4]; first by done.
rewrite /addOrder_orders -/addOrder_orders H2 => H5 H6.
case H7: d2=>[|d21 d22].
  have H8: norep(addOrder_order i k d1); first by apply: (norepAddOrder_order_head H2 H5 H6).
  by rewrite H7 in H5; rewrite !norep_cat H5 H8 /=.
rewrite norep_cat (norephead H5) norep_cat -H7.
have H8: (norep d2); first by move:H5; rewrite /norep /= H7; move/andP=> [_ ->].
have ->: (norep(addOrder_order i k d1)= true); first by apply:(norepAddOrder_order_head H2 H5 H6).
move: H6; rewrite /= H2 H7.
by case: (nocycles_order i k d1 == true); first by rewrite -H7; move=> H10; apply:(H4 H8 H10).
Qed.


Lemma canAddOrder_nocycles (i k:nat)(s1:seq nat)(rest: seq (seq nat)):
  i!=k -> rest !=[::] -> s1 \in rest -> canAddOrder i k rest -> nocycles_order i k s1.
Proof.
move=> H4.
elim H: rest =>[|r1 r2 HI]; first by done.
case H1: r2=>[|r21 r22].
  move=> H2; rewrite inE /= H4; move/eqP=> ->.
  by case:(nocycles_order i k r1).
move=> H2 H3 H5.
have H6: (r2!=[::]); first by rewrite H1.
move: H3; rewrite inE; move/orP=>[H71 |H72].
  move: H71 H5; move/eqP => <-. rewrite /= H4.
  by case H8:(nocycles_order i k s1 == true); first by move: (eqP H8).
rewrite -H1 in H72.
have H8: (canAddOrder i k r2); last by apply: (HI H6 H72 H8).
move: H5; rewrite /= H4.
case H8:(nocycles_order i k r1 == true); last by done.
case H9: r22=>[|r3 r4]; first by rewrite H1 H9 /= H4.
case H10:(nocycles_order i k r21 == true); last by done.
by rewrite -H9 H1 /= H4 H10.
Qed.


Lemma subseq_canAddOrder (i k:nat)(s2 rest:seq (seq nat)):
  i!=k -> norep rest -> subseq s2 rest -> canAddOrder i k rest -> canAddOrder i k s2.
Proof.
move=> H.
elim H1: s2=> [|s21 s22 HI]; first by rewrite /= H.
move=> H2 H3 H4.
case H5: (subseq s22 rest); last first.
  move: H3=> /=.
  case H6: rest =>[|r1 r2]; first by done.
  case H7:(s21 \in r1 :: r2); last by done.
  by rewrite -H6 H5.
move:(HI H2 H5 H4) => H6.
rewrite /= H6 H.
have ->: (nocycles_order i k s21 == true); last by done.
move: H3 => /=.
case H7: rest=>[|r1 r2]; first by done.
case H8:(s21 \in r1 :: r2); last by done.
move=>H9; rewrite H7 in H4.
by have H10: (r1 :: r2)!=[::]; last by move: (canAddOrder_nocycles H H10 H8 H4)=> ->.
Qed.


End canAddOrder.


Section canAOrder.


Lemma in_nocycles_concat (s:seq nat) (rest lasts:seq (seq nat)):
  s \in rest -> nocycles_concat_orders rest lasts -> nocycles_concat_order s lasts.
Proof.
elim H: rest =>[|r1 r2 HI]; first by done.
rewrite inE; move/orP=>[H1|H1].
  move:(eqP H1)=> <-; rewrite {1}/nocycles_concat_orders -/nocycles_concat_orders.
  case H3: lasts =>[|l1 l2]; first by rewrite /=; case s.
  by case (nocycles_concat_order s (l1 :: l2)).
rewrite /nocycles_concat_orders -/nocycles_concat_orders.
case H2: r2=>[|r21 r22]; first by move:H1; rewrite H2.
case H3: lasts =>[|l1 l2]; first by rewrite /=; case s.
by case: (nocycles_concat_order r1 (l1 :: l2)); first by rewrite -H2 -H3 => H5; apply: (HI H1 H5).
Qed.


Lemma subseq_nocycles (s rest lasts:seq (seq nat)):
  subseq s rest -> nocycles_concat_orders rest lasts -> nocycles_concat_orders s lasts.
Proof.
elim H: s=>[|s1 s2 HI]; first by rewrite /=.
rewrite /subseq -/subseq.
case H1: rest =>[|r1 r2]; first by rewrite /=.
case H2: (s1 \in r1 :: r2); last by done.
rewrite -H1=> H3 H4; move: (HI H3 H4)=>H5.
rewrite /nocycles_concat_orders -/nocycles_concat_orders.
case H7: lasts =>[|l1 l2]; first by done.
rewrite -H7 H5; rewrite -H1 in H2.
by move:(in_nocycles_concat H2 H4) => ->.
Qed.


Lemma nocycles_headtail (s1:seq nat)(firsts s2:seq (seq nat)):
   nocycles_concat_orders firsts (s1::s2) = nocycles_concat_orders firsts [::s1] && nocycles_concat_orders firsts s2.
Proof.
elim H: firsts =>[|f1 f2 HI]; first by done.
rewrite {1}/nocycles_concat_orders -/nocycles_concat_orders.
case H1: f2=>[|f21 f22].
  case H2: s2=>[|s21 s22]; first by rewrite Bool.andb_true_r.
  rewrite /=.
  by case H3: f1=>[|f11 f12]; last by case: (uniq (s1 ++ f11 :: f12)).
case H2: (nocycles_concat_order f1 (s1 :: s2) == true).
  rewrite -H1 HI H1 {2}/nocycles_concat_orders -/nocycles_concat_orders.
  case H3: f22=>[|f221 f222].
    case H4: s2=>[|s21 s22]; first by rewrite /nocycles_concat_orders !Bool.andb_true_r .
    rewrite {2 3}/nocycles_concat_orders -/nocycles_concat_orders.
    move: (eqP H2); rewrite {1}/nocycles_concat_order -/nocycles_concat_order.
    case H5: f1 =>[|f11 f12]; first by case HH:s2; by case H6: f21; last by rewrite -H6.
    rewrite H4.
    case H6: (uniq (s1 ++ f11 :: f12)); last by done.
    move=> H7.
    case H8:(nocycles_concat_order (f11 :: f12) [:: s1, s21 & s22]).
      have H9:(nocycles_concat_order (f11 :: f12) [:: s1]).
        by move:H8; rewrite /=; case:(uniq (s1 ++ f11 :: f12)).
      by rewrite H9 !/nocycles_concat_orders H7.
    have ->: (nocycles_concat_order (f11 :: f12) [:: s1])= false; last by done.
    move: H8; rewrite /= H6.
    by move:H7 => /= ->.
  rewrite -H3.
  case H4: s2=>[|s21 s22]; first by rewrite !Bool.andb_true_r.
  case H5:(nocycles_concat_order f21 (s21 :: s22)).
    rewrite {3}/nocycles_concat_orders -/nocycles_concat_orders; move: (eqP H2); rewrite H4=> H6.
    rewrite H6.
    have ->: (nocycles_concat_order f1 [:: s1]).
      move:H6 => /=.
      by case H6: f1=>[|f11 f12]; last by case:(uniq (s1 ++ f11 :: f12)).
    rewrite {1}/nocycles_concat_orders -/nocycles_concat_orders H3.
    case H7:((if nocycles_concat_order f21 [:: s1] then nocycles_concat_orders (f221 :: f222) [:: s1] else false)); last by done.
    rewrite !Bool.andb_true_l -H3 {2}/nocycles_concat_orders -/nocycles_concat_orders.
    have ->: (nocycles_concat_order f1 (s21 :: s22)); last by rewrite H3 H5.
    move: H6; rewrite /=; by case H8: f1=>[|f11 f12]; last by case:(uniq (s1 ++ f11 :: f12)).
  move:(eqP H2);rewrite -H4 => ->; rewrite Bool.andb_false_r {2}/nocycles_concat_orders -/nocycles_concat_orders H4 H5 H3.
  by case: (nocycles_concat_order f1 (s21 :: s22)); rewrite Bool.andb_false_r.
have H3: (nocycles_concat_order f1 (s1 :: s2) = false); first by move:H2; move/eqP; case H2:(nocycles_concat_order f1 (s1 :: s2)).
rewrite H3.
move:H3; rewrite /nocycles_concat_order -/nocycles_concat_order.
case H3: f1=>[|f11 f12]; first by done.
rewrite -H3.
case H4: s2=>[|s21 s22].
  case H5: (uniq (s1 ++ f1)); first by rewrite /= H3.
  by rewrite /= H3 -H3 H5.
case H5:(uniq (s1 ++ f1)); last by rewrite /= H3 -H3 H5.
by move=>H6; rewrite {2}/nocycles_concat_orders -/nocycles_concat_orders H6 Bool.andb_false_r.
Qed.


Lemma in_nocycles (s1:seq nat)(firsts rest : seq (seq nat)):
  s1 \in rest -> nocycles_concat_orders firsts rest -> nocycles_concat_orders firsts [::s1].
Proof.
elim H: rest =>[|r1 r2 HI]; first by done.
rewrite inE; move/orP=>[H1|H1]; last by rewrite nocycles_headtail; move/andP=>[H2 H3];apply: (HI H1 H3).
move: H1; move/eqP=>H1; rewrite -H1.
case H2: firsts =>[|f1 f2]; first by done.
rewrite {1}/nocycles_concat_orders -/nocycles_concat_orders.
case H3: f2=>[|f21 f22].
  rewrite /nocycles_concat_orders {1}/nocycles_concat_order -/nocycles_concat_order.
  case H4:f1=>[|f11 f12]; first by done.
  case H5: r2=>[|r21 r22]; first by done.
  by case H6: (uniq (s1 ++ f11 :: f12)); first by rewrite /= H6.
case H4: (nocycles_concat_order f1 (s1 :: r2)); last by done.
rewrite {2}/nocycles_concat_orders -/nocycles_concat_orders.
move:H4; rewrite {1}/nocycles_concat_order -/nocycles_concat_order.
case H6: f1=>[|f11 f12].
  case H7: f22=>[|f221 f222].
    rewrite {1}/nocycles_concat_order /nocycles_concat_orders -/nocycles_concat_orders.
    rewrite {1}/nocycles_concat_order -/nocycles_concat_order.
    case H8: f21=>[|f211 f212]; first by done.
    case H9: r2=>[|r21 r22]; first by done.
    case H10:(uniq (s1 ++ f211 :: f212)); last by done.
  by rewrite /= H10.
  rewrite {1}/nocycles_concat_orders -/nocycles_concat_orders.
  case H8:(nocycles_concat_order f21 (s1 :: r2)); last by done.
  case H9: f222=>[|f3 f4].
    have H11: (nocycles_concat_order f21 [:: s1]).
      move: H8; move/eqP; rewrite /nocycles_concat_order -/nocycles_concat_order.
      case H11:f21; first by done.
      rewrite -H11.
      by case :(uniq (s1 ++ f21)).
    rewrite {1}/nocycles_concat_order -/nocycles_concat_order.
    case H12: f221=>[|n2 n]; first by rewrite H11 /=.
    rewrite -H12.
    case H13: r2=>[|r21 r22].
      by case H14:(uniq (s1 ++ f221)); first by move:H14; rewrite H11 /= H12 => ->.
    case H14:(uniq (s1 ++ f221)); last by done.
    rewrite H1 /= H12.
    case H16: f21 =>[|f211 f212]; first by move:H14; rewrite -H1 -H12 =>->.
    move:H14; rewrite -H12 -H1 => ->.
    by move:H11; rewrite /nocycles_concat_order -H16 H16 => ->.
  case H10:(nocycles_concat_order f221 (s1 :: r2)); last by done.
  move=> HH H11.
  have H12: (nocycles_concat_order f21 [::s1]).
    move:H8; move/eqP; rewrite /nocycles_concat_order -/nocycles_concat_order.
    case H12: f21=>[|f211 f212]; first by done.
    case H13: r2=>[|r21 r22]; first by move/eqP=> ->.
    by case H14: (uniq (s1 ++ f211 :: f212)).
  rewrite -H9 /nocycles_concat_orders -/nocycles_concat_orders H12 H9.
  move: H10; move/eqP=>H10; move: H11; rewrite nocycles_headtail; move/andP=>[H11 H13].
  have H14: (nocycles_concat_order f221 [:: s1]).
    move: H10; rewrite /nocycles_concat_order -/nocycles_concat_order.
    case H14: f221=>[|f2211 f2212]; first by done.
    case H15: r2=>[|r21 r22]; first by move/eqP => ->.
    by case H16:(uniq (s1 ++ f2211 :: f2212)).
  by rewrite H14 H11 /=.
case H7: r2=>[|r21 r22].
  case H8:(uniq (s1 ++ f11 :: f12)); last by done.
  move=> hh; rewrite /= H8.
  by case H9: f22=>[|f221 f222]; rewrite /= => ->.
case H8: (uniq (s1 ++ f11 :: f12)); last by done.
move=> H9 H10; rewrite /= H8.
by move:H10; rewrite nocycles_headtail; move/andP=>[H10 H12]; move: H10.
Qed.




Lemma subseq_nocycles2 (s rest firsts:seq (seq nat)):
  subseq s rest -> nocycles_concat_orders firsts rest -> nocycles_concat_orders firsts s.
Proof.
elim H: s=>[|s1 s2 HI]; first by case H1: firsts =>[|l1 l2]; last by case l2.
rewrite /subseq -/subseq.
case H1: rest =>[|r1 r2]; first by done.
case H2: (s1 \in r1 :: r2); last by done.
rewrite -H1=> H3 H4; move: (HI H3 H4)=>H5.
case H6: firsts =>[|f1 f2]; first by done.
rewrite nocycles_headtail -H6 H5 Bool.andb_true_r; rewrite -H1 in H2.
apply:(in_nocycles H2 H4).
Qed.


Lemma nocycles_subseq (i k: nat)(s2 rest:seq (seq nat)):
  (i!=k) -> subseq s2 rest ->(nocycles_concat_orders (getfirstE k rest) (getlastE i rest)) ->
(nocycles_concat_orders (getfirstE k s2) (getlastE i s2)).
Proof.
move=> H.
elim H1: s2=>[|s21 s22 HI]; first by done.
have H2: (s21::s22!=[::]); first by done.
rewrite /subseq -/subseq.
case H3: rest=>[|r1 r2]; first by move/eqP => ->.
case H4: (s21 \in r1 :: r2); last by done.
rewrite -H3 => H5 H6; move: (HI H5 H6)=> H7.
rewrite /getfirstE -/getfirstE.
have H10: (subseq (s21::s22) rest); first by rewrite /= H3 H4 -H3 H5.
case H8:(head 0 s21 == k); last first.
  rewrite /getlastE -/getlastE /= H8.
  case H9: (last 0 s21 == i); last by rewrite H7.
  have ->: (s21 :: filter [pred s | last 0 s == i] s22) = getlastE i (s21::s22); first by rewrite /getlastE /= H9.
  move: (subseq_subseqgetfirstE k H5)(subseq_subseqgetlastE i H10)=> H12 H13.
  move: (subseq_nocycles H12 H6) => H17.
  apply: (subseq_nocycles2 H13 H17).
rewrite /getlastE -/getlastE.
case H9:(last 0 s21 == i).
  move: (subseq_subseqgetfirstE k H10) (subseq_subseqgetlastE i H10)=> H11 H12 /=.
  rewrite H8 H9.
  have ->: ((s21 :: filter [pred s | head 0 s == k] s22) = getfirstE k (s21::s22)); first by rewrite /= H8.
  have ->: ((s21 :: filter [pred s | last 0 s == i] s22) = getlastE i (s21::s22)); first by rewrite /= H9.
  move: (subseq_nocycles H11 H6)=>H15.
  apply: (subseq_nocycles2 H12 H15).
rewrite /= H8 H9.
have ->: ((s21 :: filter [pred s | head 0 s == k] s22) = getfirstE k (s21::s22)); first by rewrite /= H8.
have ->: ((filter [pred s | last 0 s == i] s22) = getlastE i (s21::s22)); first by rewrite /= H9.
move: (subseq_subseqgetfirstE k H10) (subseq_subseqgetlastE i H10)=> H11 H12.
move: (subseq_nocycles H11 H6)=>H15.
apply: (subseq_nocycles2 H12 H15).
Qed.


Lemma norep_seq_canAOrder (i k:nat)(a:seq nat)(rest: seq (seq nat)):
 (i!=k) -> uniq a ->
     (canAOrder i k (rest)) -> (canAOrder i k (behead rest)).
Proof.
move=> H H3.
elim H4: rest =>[|r1 r2 HI]; first by done.
rewrite /canAOrder /behead.
case H5: r2=>[|r21 r22]; first by done.
case H6:((getfirstE k [:: r1, r21 & r22] == [::]) || (getlastE i [:: r1, r21 & r22] == [::])).
  move:(orP H6) =>[H7|H7].
    by move: (eqP H7) =>H71; move: (getfirstEnil H71); move/eqP => ->.
  by move:(eqP H7) =>H71; move: (getlastEnil H71); move/eqP => ->; rewrite Bool.orb_true_r.
move=> H8.
case H7:((getfirstE k (r21 :: r22) == [::]) || (getlastE i (r21 :: r22) == [::])); first by done.
move: (subseq_behead [:: r1, r21 & r22])=> H9.
apply: (nocycles_subseq H H9 H8).
Qed.


Lemma canAcanAdd_norep (i k:nat)(a c:seq nat)(r:seq (seq nat)):
 i!=k -> norep r -> head 0 a = k -> last 0 c = i -> subseq [::a] r -> subseq [::c] r ->
 canAOrder i k r -> canAddOrder i k r -> norep [::c ++ a].
Proof.
move=> H2 H3 H4 H5 H6 H7 H8 H9.
have H17: (c==a)= false.
  case H17:((c == a)); last by done.
  move: (eqP H17) => H171; rewrite H171 in H5.
  move: (subseq_canAddOrder H2 H3 H6 H9).
  rewrite /canAddOrder H2 /nocycles_order.
  case H18: a=>[|a11 a12].
    move: H4 H5; rewrite H18 /==> H4 H5.
    by move: H2; rewrite -H4 -H5; move/eqP.
  case H19: a12; first by rewrite H19 in H18; rewrite H18 in H4 H5; move: H5 H4 H2; rewrite /= => -> ->; move/eqP.
  rewrite -H19 -H18.
  have H20: a!=[::]; first by rewrite H18.
  move: (last_in H20 H5)=>H22.
  have H21: (k \in a); first by move: H4; rewrite H18 /= => ->; rewrite inE; apply/orP; left.
  rewrite H21 H22 /=.

  have H151: (i = last 0 a); first by rewrite H5.
  case H15: (index i a < index k a); last by done.
  have H1711: (uniq a); first by apply:(subseq_norep_seq H6 H3).
  move: (last_possize H1711 H20) => hh.
  move: (index_mem i a)=> h15.
  move: (index_mem k a)=> h16.
  rewrite -h16 in H21; rewrite -h15 in H22.
  move: H15; rewrite H151 hh.
  move:H21.
  case hh1 :( size a)=> [|n]; first by done.
  rewrite subn1 ltnS.
  have -> : (n.+1.-1 = n); first by done.
  move=> H15 H161.
  by move: (leq_ltn_trans H15 H161); rewrite ltnn.
move:H3 H6 H7 H8 H9.
elim H10: r=>[|r1 r2 HI]; first by done.
rewrite /subseq => HH.
case H3:(a \in r1 :: r2); last by done.
move: H3; rewrite inE; move/orP=>[H41 |H41] _.
  case H51:(c \in r1 :: r2); last by done.
  move:H51; rewrite inE; move/orP=>[H6|H7].
    by move:H4; move/eqP=>H4; move: (eqP H41)=>H411;move: H17; rewrite H411 H6; move/eqP.
  move: (eqP H41) => <-; rewrite /canAOrder.
  have ->:((getfirstE k (a :: r2) == [::]) || (getlastE i (a :: r2) == [::])=false); last first.
    have: (a \in (getfirstE k (a :: r2))); first by rewrite /= H4; have ->:(k==k); last by rewrite inE; apply/orP; left.
    move=> H8 _ H9.
    move: (in_nocycles_concat H8 H9).
    have H71: c\in (a::r2); first by apply: (inseq a H7).
    move: (ingetlastE H71 H5)=> H11 H12 H13; move: (insubseq H11) =>H14.
    move: (subseq_nocycles2 H14 H9)=> H91.
    have H81: (a \in (getfirstE k (a :: r2))); first by rewrite /= H4; have ->:(k==k); last by rewrite inE; apply/orP; left.
    move: (in_nocycles_concat H81 H91)=> /=.
    case H15: a=>[|a1 a2].
      rewrite cats0.
      have hh: (norep r2).
        by move: HH; rewrite /=; move/andP=>[_ H16]; move:H16; case ff :r2.
      move: (insubseq H7)=> H6.
      by rewrite (subseq_norep_seq H6 hh).
    rewrite -H15 /norep.
    by case : (uniq (c ++ a)).
  rewrite /= H4 -/getfirstE.
  have ->: (k==k); first by rewrite /=.
  have ->: ((getlastE i (a :: r2) == [::]) = false); last by done.
  have H71: c\in (a::r2); first by apply: (inseq a H7).
  move: (ingetlastE H71 H5).
  by case H11:(getlastE i (a :: r2)).
case H51:(c \in r1 :: r2); last by done.
move:H51; rewrite inE; move/orP=>[H6|H7] _; last first.
  move: (insubseq H7)(insubseq H41)=>H9 H8 H12 H13.
  have H11: (norep r2).
   case H:r2=>[|r21 r22]; first by done.
   move:HH; rewrite /= /norep H /= Bool.andb_comm.
   by move/andP=>[-> _].
  have H14: (uniq r1).
    by move: HH; rewrite /=; move/andP=>[-> _].
  move: (canAddOrder_tail H2 H14 H13)=>H18.
  move: (norep_seq_canAOrder H2 H14 H12)=>H19.
  apply: (HI H11 H8 H9 H19 H18).
move: (eqP H6) => <-; rewrite /canAOrder /canAddOrder -/canAddOrder.
have ->:((getfirstE k (c :: r2) == [::]) || (getlastE i (c :: r2) == [::])=false); last first.
  have H8: (c \in (getlastE i (c :: r2))); first by rewrite /= H5; have ->:(i==i); last by rewrite inE; apply/orP; left.
  move: (insubseq H8) => H14 H9 _.
  move: (subseq_nocycles2 H14 H9).
  have H71: a\in (c::r2); first by apply: (inseq c H41).
  move: (getfirstE_in H71 H4)=>H12.
  move: (insubseq H12) =>H15 H16.
  move: (subseq_nocycles H15 H16); rewrite /=.
  case H151: a=>[|a1 a2].
   rewrite cats0.
   by have ->: (uniq c); first by move: HH; rewrite /= -(eqP H6); move/andP=>[-> _].
  by case:(uniq (c ++ a1 :: a2)).
rewrite /= H5.
have ->: (i==i); first by done.
have ->: ((getfirstE k (c :: r2) == [::]) = false); last by done.
have H71: a\in (c::r2); first by apply: (inseq c H41).
move: (getfirstE_in H71 H4).
by case H11:(getfirstE k (c :: r2)).
Qed.



Lemma norep_addOrder_concat (i k: nat)(r:orders)(rest: orders * orders):
 (i != k) -> norep r ->
 (forall x:seq nat, x \in (fst rest) -> head 0 x = k) ->
 (forall x:seq nat, x \in (snd rest) -> last 0 x = i) ->
  subseq (fst rest) r -> subseq (snd rest) r ->
  canAddOrder i k r -> canAOrder i k r ->
  norep (addOrder_concat rest).
move=> H3.
functional induction addOrder_concat rest.
 by done.
 by done.
 rewrite /fst /snd in IHo.
  rewrite e e0 => H5 H6 H7 H11.
  have H10: (forall x : seq nat, x \in d -> last 0 x = i).
    by move=> x H; move: (H7 x); rewrite inE H Bool.orb_true_r => ->.
  rewrite /subseq -/subseq.
  case H12: r=> [|r1 r2]; first by done.
  rewrite H12 in IHo H5 H11.
  case H13:(c \in (r1::r2)); last by done.
  rewrite norep_cat => H14 H15 H16.
  move: (IHo H5 H6 H10 H11 H14 H15 H16) => ->.
  have HH2: (a \in [::a]); first by rewrite inE.
  have HH3: (c \in c::d); first by rewrite inE; apply/orP; left.
  move: (H7 c HH3) => H17.
  move: (H6 a HH2)=>H18.
  have H19: (subseq [::c] (r1::r2)); first by rewrite /subseq H13.
  by rewrite (canAcanAdd_norep H3 H5 H18 H17 H11 H19 H16 H15).
 rewrite /fst /snd in IHo.
  rewrite e e0 {1}/subseq -/subseq norep_cat => H5 H6 H7.
  case H12: r=> [|r1 r2]; first by done.
  case H13: (a \in r1 :: r2); last by done.
  rewrite H12 in IHo H5 => H11 H14 H15 H16.
  have H10:(forall x : seq nat, x \in b -> head 0 x = k).
    by move=> x H; move: (H6 x); rewrite inE H Bool.orb_true_r => ->.
  move: (IHo H5 H10 H7 H11 H14 H15 H16) => ->.
  have HH3: (c \in [::c]); first by rewrite inE.
  have HH2: (a \in a::b); first by rewrite inE; apply/orP; left.
  move: (H7 c HH3) => H17.
  move: (H6 a HH2)=>H18.
  have H19: (subseq [::a] (r1::r2)); first by rewrite /subseq H13.
  by rewrite (canAcanAdd_norep H3 H5 H18 H17 H19 H14 H16 H15).
 rewrite /fst /snd in IHo IHo0.
  rewrite e e0 {1}/subseq -/subseq !norep_cat => H5 H6 H7.
  case H12: r=> [|r1 r2]; first by done.
  case H13: (a \in r1 :: r2); last by done.
  rewrite H12 in IHo H5 IHo0 => H15 H16 H17 H18.
  have H10:(forall x : seq nat, x \in b -> head 0 x = k).
    by move=> x H; move: (H6 x); rewrite inE H Bool.orb_true_r => ->.
  move: (IHo0 H5 H10 H7 H15 H16 H17 H18) => ->.
  have H19:(forall x : seq nat, x \in [:: a] -> head 0 x = k).
    by move=> x; rewrite inE => H; move: (H6 x); rewrite inE H Bool.orb_true_l => ->.
  have H20:(forall x : seq nat, x \in d -> last 0 x = i).
    by move=> x H; move: (H7 x); rewrite inE H Bool.orb_true_r => ->.
  have H21: (subseq [::a] (r1::r2)); first by rewrite /subseq H13.
  move: H16; rewrite /subseq -/subseq.
  case H22:(c \in r1 :: r2); last by done.
  move=> H23.
  move: (IHo H5 H19 H20 H21 H23 H17 H18) => ->.
  have HH2: (a \in a::b); first by rewrite inE; apply/orP; left.
  have HH3: (c \in c::d); first by rewrite inE; apply/orP; left.
  move: (H7 c HH3) => H24.
  move: (H6 a HH2)=> H25.
  have H26: (subseq [::c] (r1::r2)); first by rewrite /subseq H22.
  by rewrite (canAcanAdd_norep H3 H5 H25 H24 H21 H26 H18 H17).
Qed.


End canAOrder.



Section canAddOrders.

Lemma canAddOrders_tail (i k :nat) (a: bool)(x: seqZ2)(s: orders):
  (i != k) && (a != false) = false -> x!=[::] -> canAddOrders i k (a::x) s =
  canAddOrders i (k+1) x s.
Proof.
rewrite /= => -> H1.
case H2: x; first by move:H1; rewrite H2.
by case: s.
Qed.


Lemma canAddOrders_tailnil (i k:nat)(s:seqZ2):
 i != k -> (head false s) != false -> s!=[::] ->
 canAddOrders i k s [::] -> canAddOrders i (k + 1) (behead s) ((i::k::nil)::nil).
Proof.
elim H3: s=>[|s1 s2 HH]; first by done.
move=> H2 H4 H5.
rewrite /head in H4; rewrite /= H2 H4.
by case H6: s2.
Qed.



Lemma canAddOrders_addOrders (i j:nat)(col: seqZ2) (d: orders):
 norep d -> canAddOrders i j col d -> norep (addOrders i j col d) = true.
Proof.
move=> H2 H3.
functional induction (addOrders i j col d); try by move => //=.
 by move:(andP e2)=>[H4 H5]; apply:norepik.
 move: (andP e2) => [H5 H6]; rewrite norep_cat.
  move: (norepik H6)=> ->.
  move:H3; rewrite /canAddOrders H5 H6.
  case H7: (canAddOrder i k (_x :: _x0) && canAOrder i k (_x :: _x0)); last by done.
  move: (andP H7) =>[H31 H32] => _.
  by apply: (canAddOrder_norep H6 H2 H31).
 move: (andP e2) => [H5 H6]; rewrite norep_cat.
  move: (norepik H6)=> ->.
  move:H3; rewrite /canAddOrders H5 H6; move/andP=>[H31 _]; move: (andP H31)=>[H311 H32].
  rewrite norep_cat (canAddOrder_norep H6 H2 H311).
  move: (subseq_getfirstE k (_x :: _x0))(subseq_getlastE i (_x :: _x0))=>HH1 HH2.
  have H7:(forall x : seq nat, x \in ((getfirstE k (_x :: _x0), getlastE i (_x :: _x0)).1) -> head 0 x = k).
    by rewrite /fst => x H4; apply: (ingetfirst H4).
  have H8:(forall x : seq nat, x \in ((getfirstE k (_x :: _x0), getlastE i (_x :: _x0)).2) -> last 0 x = i).
    by rewrite /snd => x H4; apply: (ingetlastE_last H4).
  by move: (norep_addOrder_concat H6 H2 H7 H8 HH1 HH2 H311 H32).
 have H4: (k + 1 == 0) = false; first by rewrite addn1.
  move:(andP e2) =>[H7 H8]; move: (norepik H8)=> H5.
  have H6: (_x::_x0) != [::]; first by done.
  have H9: ([:: a, _x & _x0] != [::]); first by done.
  have H10: (head false [:: a, _x & _x0] != false); first by done.
  move: (@norepAddOrders i k [:: a, _x & _x0] H8 H9 H10 H3)=> H11.
  rewrite /behead in H11; rewrite -H11.
  have H12: (canAddOrders i (k + 1) (_x :: _x0) [:: [:: i, k & [::]]]); last by rewrite H11; apply: (IHo H5 H12).
  by apply: (canAddOrders_tailnil H8 H10 H9 H3).
 move: H3; rewrite /canAddOrders -/canAddOrders Bool.andb_comm e2.
  case H4: (_x0)=>[|x1 x2].
    case H5:((_x != false) && (i != k + 1)).
      move: (andP H5)=>[H51 H52]; rewrite /= H51 H52 /=.
      have H6:(i == k + 1)= false; first by apply/eqP; apply/eqP.
      by rewrite inE H6.
    case H6: (_x != false); last by rewrite /= H5.
    rewrite H6 Bool.andb_true_l in H5; rewrite H5 => H9.
    have H7: (canAddOrders i (k + 1) (_x :: _x0) [::]); last first.
      have H8: (k+1 == 0)=false; first by rewrite addn1.
      rewrite H4 in IHo H7; apply: (IHo H2 H7).
    by rewrite /= H5 H4.
  case H5: ((i != k + 1) && (_x != false)); last first.
    rewrite -H4 => H10.
    have H8: ((k + 1 == 0) = false); first by rewrite addn1.
    have H9:(canAddOrders i (k + 1) (_x :: _x0) [::]); first by rewrite /= H4 H5 -H4.
    apply: (IHo H2 H9).
  have H8: (k+1 == 0)=false; first by rewrite addn1.
  move=> H9; rewrite -H4.
  have H10: (canAddOrders i (k + 1) (_x :: _x0) [::]); first by rewrite /= H4 H5.
  apply: (IHo H2 H10).
 have H6: (k + 1 == 0) = false; first by rewrite addn1.
  have H7:(norep ([:: [:: i; k]] ++ addOrder_orders i k (_x1 :: _x2) ++addOrder_concat
           ((getfirstE k (_x1 :: _x2)), (getlastE i (_x1 :: _x2))))); last first.
  have H8: (canAddOrders i (k + 1) (_x :: _x0)([:: [:: i; k]] ++
         addOrder_orders i k (_x1 :: _x2) ++ addOrder_concat
           ((getfirstE k (_x1 :: _x2)), (getlastE i (_x1 :: _x2))))); last first.
  apply:(IHo H7 H8).
  set x:= (_x::_x0).
  move:H3; rewrite -/x /=.
  rewrite Bool.andb_comm in e2; rewrite e2.
  by case:(canAddOrder i k (_x1 :: _x2) && canAOrder i k (_x1 :: _x2)).
  rewrite norep_cat; move: (andP e2) => [H10 H9].
  rewrite (norepik H9) norep_cat.
  have H11: (canAddOrder i k (_x1 :: _x2) && canAOrder i k (_x1 :: _x2)).
    move: H3; rewrite /canAddOrders -/canAddOrders H9 H10.
    by case H12: (canAddOrder i k (_x1 :: _x2) && canAOrder i k (_x1 :: _x2)).
  move:(andP H11)=> [H111 H12].
  move: (canAddOrder_norep H9 H2 H111) => ->.
  move: (subseq_getfirstE k (_x1 :: _x2))(subseq_getlastE i (_x1 :: _x2)) => HH1 HH2.
  have H7:(forall x : seq nat, x \in ((getfirstE k (_x1 :: _x2), getlastE i (_x1 :: _x2)).1) -> head 0 x = k).
    by rewrite /fst => x H4; apply: (ingetfirst H4).
  have H8:(forall x : seq nat, x \in ((getfirstE k (_x1 :: _x2), getlastE i (_x1 :: _x2)).2) -> last 0 x = i).
    by rewrite /snd => x H4; apply: (ingetlastE_last H4).
  by move: (norep_addOrder_concat H9 H2 H7 H8 HH1 HH2 H111 H12).
 have H4: ((_x1 :: _x2)!=[::]); first by done.
  have H5: (head false [:: a, _x & _x0] != false) && (i!=k)=false; first by done.
  have H6: (canAddOrders i (k + 1) (_x :: _x0)(_x1::_x2)); last first.
    have H7: (k + 1 == 0) = false; first by rewrite addn1.
    apply: (IHo H2 H6).
  rewrite Bool.andb_comm in e2.
  have H6: ((_x :: _x0)!=[::]); first by done.
  by rewrite -(canAddOrders_tail (_x1 :: _x2) e2 H6).
Qed.


End canAddOrders.


Section proofAdm.


Lemma admis_aux ss (a:seqZ2) m2 m1:
norep (genDvfOrders (size ss * size a).+1 m2 m2 ss m1 [::] [::]).2.
Proof.
functional induction (genDvfOrders (((size ss)*(size a)).+1) m2 m2 ss m1 nil nil); last first; try by done.
 by move:(andP e0)=> [H3 H4]; move:(andP H3)=>[H31 H5]; move:(andP H31)=>[H32 H6];move:(andP H32).
 move:(andP e0) =>[H32 H6];move:(andP H32)=>[H33 H7];
  move:(andP H33) =>[H34 H8];move:(andP H34)=>[H35 H9] ;move:(andP H35)=>[H36 H10].
  apply: (@canAddOrders_addOrders i 0 (getcol (firstElem1 j a0) mm) (e3 :: f) H7).
  by move:(eqP e7) => ->.
 move:(andP e0) =>[H32 H6];move:(andP H32)=>[H33 H7];
  move:(andP H33) =>[H34 H8];move:(andP H34)=>[H35 H9] ;move:(andP H35)=>[H36 H10].
  apply:(@canAddOrders_addOrders i 0 (getcol (firstElem1 j a0) mm) [::] H7).
  by move:(eqP e6).
 by move:(andP e0)=> [H1 H3]; move:(andP H1) =>[H5 H4]; move: (andP H5)=>[_ H6].
Qed.



Lemma admis (ss: matZ2): norep (genOrders ss).
Proof.
elim H: ss=> [|a b HI]; first by done.
rewrite /genOrders !addn1 -H.
have H2: (a::b = a::b); first by done.
set m1:= ss.
rewrite {-6}/m1.
case HH:(prop_cat (genDvfOrders (size ss * size a).+1 0 0 ss m1 [::] [::]).2); last by done.
by apply : admis_aux.
Qed.


End proofAdm.


End rs_adm_prop5.




Section rs_adm_prop6.



Functional Scheme addOrder_orders_ind := Induction for addOrder_orders Sort Prop.

Lemma invf_inaddOrder_orders a i j ords: i!= j ->
  a \in ords -> a \in addOrder_orders i j ords.
Proof.
functional induction (addOrder_orders i j ords); try by done.
 move=> H; rewrite inE; move/orP=>[H1|H1]; first by rewrite (eqP H1) inE; by have -> //: (a0 == a0).
  move: (IHl H H1) => H2.
  by rewrite !mem_cat; apply/orP; right; apply/orP; right.
 by rewrite e0.
Qed.
  


Lemma invf_inaddO a i j c ords:
  a \in ords -> a \in addOrders i j c ords.
Proof.
functional induction (addOrders i j c ords); try by done.
+ move=> H; rewrite mem_cat; apply/orP; right.
  rewrite /addOrder_orders -/addOrder_orders.
  move:H; rewrite inE; move/orP =>[H2|H2]; first by rewrite (eqP H2) inE; by have -> //: (_x == _x).
  move: (andP e2)=>[e21 e22].
  rewrite mem_cat; apply/orP; right; rewrite e22 mem_cat; apply/orP; right.
  apply:(invf_inaddOrder_orders e22 H2).
+ move=> H1; rewrite mem_cat; apply/orP; right; rewrite mem_cat; apply/orP; left.
  move: (andP e2) =>[_ e22].
  apply: (invf_inaddOrder_orders e22 H1).
+ move=> H1.
  have H2: ( a \in [:: [:: i; k]] ++ addOrder_orders i k (_x1 :: _x2) ++
    addOrder_concat (getfirstE k (_x1 :: _x2), getlastE i (_x1 :: _x2))); last apply: (IHo H2).
  rewrite mem_cat; apply/orP; right; rewrite mem_cat; apply/orP; left; move: (andP e2) =>[_ e22].
  apply: (invf_inaddOrder_orders e22 H1).
Qed.
  


Fixpoint schemaaddOrders (i k:nat)(s:seqZ2)(ords: orders)(im:nat):=
match s, ords with
|nil, _ => ords
|a::nil, nil => if (im == 0)
                   then if ((a!= false) && (i!=k))
                        then (i::k::nil)::nil
                        else nil
                   else nil
|a::nil, _ => let getf := (getfirstE k ords) in
                 let getl := (getlastE i ords) in
                 if (im == 0)
                 then if ((a!=false) && (i!=k))
                      then if ((getf == nil) || (getl == nil))
                             then ((i::k::nil)::nil ) ++ (addOrder_orders i k ords)
                             else ((i::k::nil)::nil ) ++(addOrder_orders i k ords)++(addOrder_concat (getf, getl))
                      else ords
                 else nil
|a::b, nil => if ((a != false) && (i != k))
   then schemaaddOrders i (k+1) b ((i::k::nil)::nil)(im-1)
  else schemaaddOrders i (k+1) b nil (im-1)
|a::b, _ => let getf := (getfirstE k ords) in
                 let getl := (getlastE i ords) in
                 if ((a != false) && (i != k))
                      then (schemaaddOrders i (k+1) b (((i::k::nil)::nil) ++ (addOrder_orders i k ords) ++ (addOrder_concat (getf, getl))) (im-1))
    else schemaaddOrders i (k+1) b ords (im-1)
end.

Functional Scheme schemaaddOrders_ind := Induction for schemaaddOrders Sort Prop.



Lemma compij_in_addOrders (im k i:nat) l ords:
  nth false l im!= false -> uniq (i::(im+ k)::nil) ->
   (i :: (im + k) ::nil) \in addOrders i k l ords.
Proof.
functional induction (schemaaddOrders i k l ords im); first by rewrite nth_nil.
 move: (eqP e2)=> -> H2 H3.
  by rewrite /= e3 add0n inE.
 rewrite (eqP e2)=> H2; rewrite /addOrders e3 add0n.
  move: H2; rewrite /= inE Bool.andb_true_r => H3 H4.
  by move: e3; rewrite H3 H4.
 case H2: im=>[|im1]; first by move:e2; rewrite H2.
  by move:e2; rewrite H2 /= => _; move/eqP; rewrite nth_nil.
 rewrite /addOrders e3 e4 (eqP e2)=> H2 H3.
  by rewrite add0n /= inE; apply/orP; left.
 rewrite /addOrders e3 e4 (eqP e2)=> H2 H3.
  by rewrite add0n /= inE; apply/orP; left.
 rewrite (eqP e2)=> H2; rewrite /addOrders e3 add0n.
  move: H2; rewrite /= inE => H3.
  by move: e3; rewrite H3 Bool.andb_true_l => ->.
 case H2: im=>[|im1]; first by move:e2; rewrite H2.
  by move:e2; rewrite H2 /= => _; move/eqP; rewrite nth_nil.
 set x:= (_x :: _x0).
  case H1: (im) =>[|n1].
    rewrite add0n /nth=> H4 H5.
    rewrite /= -/addOrders e2 /x.
    have H7: ([:: i; k] \in [:: [:: i; k]]); first by rewrite inE.
    apply: (@invf_inaddO [:: i; k] i (k+1) (_x::_x0)[:: [:: i; k]] H7).
  move: (ltn0Sn k); rewrite -(addn1 k) => H2 H4 H5.
  have H3: (0 < im); first by rewrite H1.
  rewrite -H1.
  have H8:nth false (_x :: _x0) (im - 1) != false.
    by move: H4; rewrite subn1 /x H1 /=.
  have H9: (im - 1 + (k + 1)) = im + k.
    by rewrite H1 addn1 -H1 !subn1 H1 /= addnS addSn.
  rewrite -H1 -H9 in H5; rewrite -H9 /= -/addOrders e2 /x.
  apply: (IHo H8 H5).
 set x:= (_x :: _x0).
  rewrite /addOrders -/addOrders e2 /x.
  case H1: (im) =>[|n1].
    rewrite add0n /nth.
    move=> H5; move:e2; rewrite H5 Bool.andb_true_l; move/eqP => ->.
    by rewrite /uniq /= inE Bool.andb_true_r; move/eqP.
  move: (ltn0Sn k); rewrite -(addn1 k) => H2 H4 H5.
  have H3: (0 < im); first by rewrite H1.
  have H8: nth false (_x :: _x0) (im - 1) != false; first by move: H4; rewrite H1 subn1.
  have H9: (im - 1 + (k + 1)) = im + k.
    by rewrite H1 addn1 -H1 !subn1 H1 /= addnS addSn.
  move:H5; rewrite -H1 -H9; apply: (IHo H8).
 set x:= (_x :: _x0).
  case H1: (im) =>[|n1].
    rewrite add0n /nth.
    move=> H5 H6.
    rewrite /addOrders -/addOrders e2 /x.
    have H7: ([:: i; k] \in ([:: [:: i; k]] ++ addOrder_orders i k (_x1 :: _x2) ++
      addOrder_concat (getfirstE k (_x1 :: _x2), getlastE i (_x1 :: _x2)))); first
      by rewrite mem_cat inE; apply/orP; left.
    apply: (@invf_inaddO [:: i; k] i (k+1) (_x::_x0)([:: [:: i; k]] ++
      addOrder_orders i k (_x1 :: _x2) ++
      addOrder_concat (getfirstE k (_x1 :: _x2), getlastE i (_x1 :: _x2))) H7).
  move: (ltn0Sn k); rewrite -(addn1 k) => H5 H6 H7.
  have H3: (0 < im); first by rewrite H1.
  have H8: nth false (_x :: _x0) (im - 1) != false; first by move: H6; rewrite H1 subn1.
  have H9: (im - 1 + (k + 1)) = im + k.
    by rewrite H1 addn1 -H1 !subn1 H1 /= addnS addSn.
  rewrite /= -/addOrders e2 /x.
  move:H7; rewrite -H1 -H9 => H7; apply: (IHo H8 H7).
 set x:= (_x :: _x0).
  rewrite /addOrders -/addOrders e2 /x.
  case H1: (im) =>[|n1].
    rewrite add0n /nth.
    move=> H5; move:e2; rewrite H5 Bool.andb_true_l; move/eqP => ->.
    by rewrite /uniq /= inE Bool.andb_true_r; move/eqP.
  move: (ltn0Sn k); rewrite -(addn1 k) => H2 H4 H5.
  have H3: (0 < im); first by rewrite H1.
  have H8: nth false (_x :: _x0) (im - 1) != false; first by move: H4; rewrite H1 subn1.
  have H9: (im - 1 + (k + 1)) = im + k.
    by rewrite H1 addn1 -H1 !subn1 H1 /= addnS addSn.
  move:H5; rewrite -H1 -H9; apply: (IHo H8).
Qed.


Lemma compijsub (k1 k2:nat)(a:seqZ2)(s: matZ2):
  k1 > 0 -> compij k1 k2 (a::s) = compij k1.-1 k2 s.
Proof.
move=> H; rewrite /compij.
have ->: ((nth [::] (a :: s) (k1)) =(nth [::] s (k1.-1))); last by done.
case H1: k1=>[|k]; first by move:H; rewrite H1.
by rewrite /=.
Qed.


Fixpoint schemagetcol1 (c:nat)(s: matZ2)(i:nat):seqZ2 :=
match s with
|nil => nil
|a::b => (schemagetcol1 c b (i -1))
end.

Functional Scheme schemagetcol1_ind := Induction for schemagetcol1 Sort Prop.


Lemma compij_nth im jk M:
compij im jk M = nth false (getcol jk M) im.
Proof.
functional induction (schemagetcol1 jk M im); first by rewrite /compij !nth_nil.
case H1: i => [|i1]; first by rewrite /compij.
have H3: 0 < i; first by rewrite H1.
by rewrite -H1 (compijsub jk _x b H3) -subn1 IHs /getcol -/getcol cat1s H1 !subn1.
Qed.


Lemma pairs (i j i0 j0:nat): (i,j)== (i0,j0) -> (i==i0)/\ (j ==j0).
Proof.
by move=> H; rewrite (pair_eq1 H) (pair_eq2 H).
Qed.


Lemma indif0_order ik jk im p i j M M1 ords vf :
 ((ik, jk) \in vf -> compij im jk M != false -> (ik::im::nil) \in ords) ->
  ik!= im -> (ik,jk)\in (genDvfOrders p i j M M1 vf ords).1 ->
  compij im jk M != false -> (ik::im::nil) \in (genDvfOrders p i j M M1 vf ords).2.
Proof.
functional induction (genDvfOrders p i j M M1 vf ords); try by done; try by apply:IHp0.
+ rewrite /= => H1 HH.
  rewrite (mem_cat (ik, jk) vf [:: (i, firstElem1 j a)]).
  move/orP=>[H2| H3] H4; first by move: (H1 H2 H4).
  move: H3; rewrite inE => H5; move: (pairs H5) =>[H6 H7]; rewrite (eqP H6) -(eqP H7).
  rewrite compij_nth in H4.
  have H8:(0 < 1); first by done.
  have H9:(uniq [::i;im]); first by move:(eqP H6) HH => -> /=; rewrite inE => ->.
  move: (@compij_in_addOrders im 0 i (getcol jk mm)[::]); rewrite addn0=> H10.
  by apply: (H10 H4 H9).
+ rewrite /= => H1 HH.
  rewrite (mem_cat (ik, jk) vf [:: (i, firstElem1 j a)]).
  move/orP=>[H2| H3] H4; first by move: (H1 H2 H4); apply:(invf_inaddO i 0 ((getcol (firstElem1 j a) mm))).
  move: H3; rewrite inE => H5; move: (pairs H5) =>[H6 H7]; rewrite (eqP H6) -(eqP H7).
  rewrite compij_nth in H4.
  have H8:(0 < 1); first by done.
  have H9:(uniq [::i;im]); first by move:(eqP H6) HH => -> /=; rewrite inE => ->.
  move: (@compij_in_addOrders im 0 i (getcol jk mm)(e3::f)); rewrite addn0=> H10.
  by apply: (H10 H4 H9).
+ move=> H1 H2 H3.
  have H4: (((ik, jk) \in addcvd i (firstElem1 j a) vf -> compij im jk mm != false ->
    [:: ik; im] \in addOrders i 0 (getcol (firstElem1 j a) mm) [::])); last by apply: (IHp0 H4 H2 H3).
  rewrite /addcvd mem_cat; move/orP=>[H4|H4] hh; last by move: (H1 H4 hh).
  move:H4; rewrite inE => H5.
  move: (pairs H5)=>[H61 H62]; move:(eqP H61)(eqP H62)=> -> <-.
  rewrite compij_nth in hh.
  have H8:(0 < 1); first by done.
  have H9:(uniq [::i;im]); first by move:(eqP H61) H2 => -> /=; rewrite inE /= => ->.
  move: (@compij_in_addOrders im 0 i (getcol jk mm)[::]); rewrite addn0=> H10.
  by apply: (H10 hh H9).
+ move=> H1 H2 H3.
  have H4: (((ik, jk) \in addcvd i (firstElem1 j a) vf -> compij im jk mm != false ->
    [:: ik; im] \in addOrders i 0 (getcol (firstElem1 j a) mm) (e3::f))); last by apply: (IHp0 H4 H2 H3).
  rewrite /addcvd mem_cat; move/orP=>[H4|H4] hh; last first.
    move: (H1 H4 hh)=> H5; by rewrite (invf_inaddO i 0 ((getcol (firstElem1 j a) mm)) H5).
  move:H4; rewrite inE => H5.
  move: (pairs H5)=>[H61 H62]; move:(eqP H61)(eqP H62)=> -> <-.
  rewrite compij_nth in hh.
  have H8:(0 < 1); first by done.
  have H9:(uniq [::i;im]); first by move:(eqP H61) H2 => -> /=; rewrite inE /= => ->.
  move: (@compij_in_addOrders im 0 i (getcol jk mm)(e3::f)); rewrite addn0=> H10.
  by apply: (H10 hh H9).
Qed.



Lemma indif0_order1 M : forall ik jk im,
  (ik,jk)\in (dvford M) -> ik!= im ->
 compij im jk M != false -> (ik::im::nil) \in genOrders M.
Proof.
move=> ik jk im H; move:(indvford_genDvf H).
rewrite /genDvf /genOrders.
case H1: M => [|a b]; first by done.
case HH: (prop_cat (genDvfOrders (size (a :: b) * size a + 1) 0 0 (a :: b) (a :: b) [::] [::]).2); last by rewrite in_nil.
move: HH => _.
rewrite -H1 => H4 H6 H7.
have H3:((ik, jk) \in [::] -> compij im jk M != false -> (ik::im::nil) \in [::]); first by done.
apply: (indif0_order H3 H6 H4 H7).
Qed.

End rs_adm_prop6.






End admissible.
Section rs_adm_prop7.


Lemma propcat_in_in_cat M: prop_cat (genOrders M).
Proof.
elim H: M => [|a b HI]; first by done.
rewrite /genOrders !addn1 -H.
by case HH: (prop_cat (genDvfOrders (size M * size a).+1 0 0 M M [::] [::]).2).
Qed.





Lemma in_in_cat (M:matZ2):
  let ords:= (genOrders M) in
  (forall a b s p, (a::s) \in ords -> (last 0 s = b) -> (b::p) \in ords -> ((a::s)++p) \in ords).
Proof.
apply:(prop_cat_prop_cat2 ( propcat_in_in_cat M)).
Qed.



End rs_adm_prop7.



Section dvfordgenOrder_is_Vecfieldadmord.

Variable M: matZ2.
Variable m n: nat.
Hypotheses ismatrix: is_matrix m n M.

Lemma dvfordisVecfieldadm:
  Vecfieldadm M (dvford M)(genOrders M).
Proof.
case H1: M=>[|s1 s2]; first by done.
have HH: (M!=[::]); first by rewrite H1.
rewrite -H1 /Vecfieldadm.
rewrite (propSizef_ord M) (@propSizes_ord m n M HH ismatrix)
(norepfst_ord M)(norepsnd_ord M)(admis M).
split; split; split; split; split.
apply: v_in_genDvf_Mv1_ord.
split; first by done.
split; first by apply: ordered_dvfg.
split; first by apply : indif0_order1.
apply: in_in_cat.
Qed.

End dvfordgenOrder_is_Vecfieldadmord.