Library mathcomp_eulerian.psi_cdindex_defs


From mathcomp Require Import all_ssreflect.
Require Import mmtree psi_core psi_comm psi_descent_v2 psi_descent_thms.

Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.



Definition is_internal (i : nat) (w : seq nat) : bool :=
  (i < size w) && (1 < window_size i w).

Definition apply_psis (ops : seq nat) (w : seq nat) : seq nat :=
  foldl (fun w' ipsi i w') w ops.

Definition char_mono (w : seq nat) : seq bool :=
  [seq is_descent_seq w k | k <- iota 0 (size w).-1].

Inductive cde := C_letter | D_letter | E_letter.

Definition classify_vertex_cde (i : nat) (w : seq nat) : cde :=
  if ~~ is_internal i w then E_letter
  else if has_left_child i w then D_letter
  else C_letter.

Definition phi'_w (w : seq nat) : seq cde :=
  [seq classify_vertex_cde i w | i <- iota 0 (size w)].

Definition phi_w (w : seq nat) : seq cde :=
  [seq x <- phi'_w w | match x with E_letterfalse | _true end].

Definition internal_vertices (w : seq nat) : seq nat :=
  [seq i <- iota 0 (size w) | is_internal i w].

Fixpoint expand_cde (letters : seq cde) : seq (seq bool) :=
  match letters with
  | [::][:: [::]]
| C_letter :: rest
      let tails := expand_cde rest in
      [seq false :: t | t <- tails] ++ [seq true :: t | t <- tails]
  | D_letter :: rest
      let tails := expand_cde rest in
      [seq false :: true :: t | t <- tails] ++ [seq true :: false :: t | t <- tails]
  | E_letter :: restexpand_cde rest
  end.

Definition powerset_internal (w : seq nat) : seq (seq nat) :=
  let ivs := internal_vertices w in
  foldl (fun acc iacc ++ [seq s ++ [:: i] | s <- acc]) [:: [::]] ivs.

Fixpoint leq_seqb (s1 s2 : seq bool) : bool :=
  match s1, s2 with
  | [::], _true
  | _ :: _, [::]false
  | b1 :: s1', b2 :: s2'
    if b1 == b2 then leq_seqb s1' s2'
    else ~~ b1
  end.


Lemma apply_psis_nil w : apply_psis [::] w = w.
Proof. by []. Qed.

Lemma apply_psis_cons i ops w :
  apply_psis (i :: ops) w = apply_psis ops (psi i w).
Proof. by []. Qed.

Lemma size_apply_psis ops w : size (apply_psis ops w) = size w.
Proof.
elim: ops w ⇒ [// | i ops IH] w /=.
by rewrite IH size_psi.
Qed.

Lemma uniq_apply_psis ops w : uniq w uniq (apply_psis ops w).
Proof.
elim: ops w ⇒ [// | i ops IH] w /= Hu.
by apply: IH; apply: uniq_psi.
Qed.

Lemma perm_eq_apply_psis ops w : perm_eq (apply_psis ops w) w.
Proof.
elim: ops w ⇒ [| i ops IH] w /=; first exact: perm_refl.
exact: perm_trans (IH _) (psi_perm_eq _ _).
Qed.

Lemma apply_psis_cat ops1 ops2 w :
  apply_psis (ops1 ++ ops2) w = apply_psis ops2 (apply_psis ops1 w).
Proof. by rewrite /apply_psis foldl_cat. Qed.

Lemma apply_psis_rcons ops i w :
  apply_psis (rcons ops i) w = psi i (apply_psis ops w).
Proof. by rewrite -cats1 apply_psis_cat. Qed.