(*****************************************************************************)
(*                                                                           *)
(*                     Translation respects PPO                              *)
(*                                                                           *)
(*****************************************************************************)
Ltac ppo := Ordering.ppo Nat.eq_dec Nat.eq_dec constructor_eq_dec.

(* Specifications: *)
(* replacing the rank function by a locally equivalent one *)
Lemma same_rank_same_ppo_iff s t rk rk':   (* => Ordering *)
(∀ f, f ∈ functions_of_term t → rk f = rk' f) →
(∀ f, f ∈ functions_of_term s → rk f = rk' f) →
PPO rk t s ↔ PPO rk' t s.
Lemma same_rank_same_ppo_rule_iff r rk rk': (* replace same_rank_same_ppo_rule in Ordering *)
(rk (lhs_func r) = rk' (lhs_func r)) →
(∀ f : function, f ∈ (rhs_funcs r) → rk f = rk' f) →
PPO_rule rk r ↔ PPO_rule rk' r.
Lemma BC_to_TRS_same_rank_same_ppo_rule_iff bc st r rk rk':
let trs := snd (BC_to_TRS bc st) in
(∀ ru, ru ∈ trs.(rules) → rk (lhs_func ru) = rk' (lhs_func ru)) →
r ∈ trs.(rules) → PPO_rule rk r ↔ PPO_rule rk' r.
Lemma map_BC_to_TRS_same_rank_same_ppo_rule bcl st r rk rk':
let trsl := snd ((lm_to_ml (map BC_to_TRS bcl)) st) in
(∀ ru, ru ∈ get_rules trsl → rk (lhs_func ru) = rk' (lhs_func ru)) →
r ∈ get_rules trsl → PPO_rule rk r → PPO_rule rk' r.
(* ordering the mk_call of rec and comp *)
Lemma ppo_rec_calls f g rk (Suc:constructor) n s:
rk g < rk f →
PPO rk
(fapply g (mk_args_h (S n) s (mk_call (S (n + s)) f)))
(fapply f (capply Suc [var 0] :: map term_from_pattern (mk_pvl 1 (S (n + s))))).
Lemma ppo_comp_calls trsl f rk n m t:
n ≤ m → (∀ g : function, g ∈ map main trsl → rk g < rk f) →
t ∈ map (mk_call_trs n) trsl → PPO rk t (fapply f (mk_tvl 0 m)).
(* from ordering of elements to ordering of the list *)
Lemma map_BC_to_TRS_ppo_rule bcl st: (* maybe also prove the other direction and make a _iff maybe not needed. *)
let rk := λ f : nat, rank (get_info_l (snd (lm_to_ml (map BC_to_TRS bcl) st)) f) in
(∀ (bc : BC) (st0 : state), bc ∈ bcl →
Forall (PPO_rule (get_rank (snd (BC_to_TRS bc st0)))) (rules (snd (BC_to_TRS bc st0)))) →
Forall (PPO_rule rk) (get_rules (snd (lm_to_ml (map BC_to_TRS bcl) st))).
(* Translation produced an ordered TRS *)
Theorem BC_to_TRS_PPO bc st n s:
let trs := snd (BC_to_TRS bc st) in
arities bc = ok_arities n s →
PPO_prog trs.(rules) (get_rank trs).