Definition unprimed_var := var_lu 0 N.
Definition rel_env := ad -> bool_expr.
Definition Brel_env := Map ad.
Definition trans_env := ad -> bool_expr.
Definition Btrans_env := Map ad.
Definition re_put (re : rel_env) (x : ad) (be : bool_expr) : rel_env :=
fun y => if Neqb x y then be else re y.
Inductive mu_form : Set :=
| mu_0 : mu_form
| mu_1 : mu_form
| mu_ap : ad -> mu_form
| mu_rel_var : ad -> mu_form
| mu_neg : mu_form -> mu_form
| mu_and : mu_form -> mu_form -> mu_form
| mu_or : mu_form -> mu_form -> mu_form
| mu_impl : mu_form -> mu_form -> mu_form
| mu_iff : mu_form -> mu_form -> mu_form
| mu_all : ad -> mu_form -> mu_form
| mu_ex : ad -> mu_form -> mu_form
| mu_mu : ad -> mu_form -> mu_form.
(* (mu_rel_free P f) means that there is a free occurrence of the relational variable P in the formula f *)
Fixpoint mu_rel_free (P : ad) (f : mu_form) {struct f} : bool :=
match f with
| mu_0 => false
| mu_1 => false
| mu_ap _ => false
| mu_rel_var Q => Neqb P Q
| mu_neg g => mu_rel_free P g
| mu_and g h => mu_rel_free P g || mu_rel_free P h
| mu_or g h => mu_rel_free P g || mu_rel_free P h
| mu_impl g h => mu_rel_free P g || mu_rel_free P h
| mu_iff g h => mu_rel_free P g || mu_rel_free P h
| mu_all t g => mu_rel_free P g
| mu_ex t g => mu_rel_free P g
| mu_mu Q g => negb (Neqb P Q) && mu_rel_free P g
end.
(* (mu_t_free t f) means that there is a free occurrence of the transition variable t in the formula f *)
Fixpoint mu_t_free (t : ad) (f : mu_form) {struct f} : bool :=
match f with
| mu_0 => false
| mu_1 => false
| mu_ap _ => false
| mu_rel_var P => false
| mu_neg g => mu_t_free t g
| mu_and g h => mu_t_free t g || mu_t_free t h
| mu_or g h => mu_t_free t g || mu_t_free t h
| mu_impl g h => mu_t_free t g || mu_t_free t h
| mu_iff g h => mu_t_free t g || mu_t_free t h
| mu_all u g => Neqb t u || mu_t_free t g
| mu_ex u g => Neqb t u || mu_t_free t g
| mu_mu Q g => mu_t_free t g
end.
(* Applies the function f n times on argument a *)
Fixpoint iter (A : Type) (A_eq : A -> A -> bool) (f : A -> A)
(a : A) (n : nat) {struct n} : A :=
match n with
| O => a
| S m => if A_eq a (f a) then f a else iter _ A_eq f (f a) m
end.
Definition be_iter (f : bool_expr -> bool_expr) (be : bool_expr)
(n : nat) := iter _ be_eq_dec f be n.
Fixpoint iter2n (A : Set) (A_eq : A -> A -> bool) (f : A -> A)
(a : A) (n : nat) {struct n} : A * bool :=
match n with
| O => (f a, A_eq a (f a))
| S m =>
match iter2n _ A_eq f a m with
| (b, true) => (b, true)
| (b, false) => iter2n _ A_eq f b m
end
end.
Definition be_iter2n := iter2n _ be_eq_dec.

(* Specifications: *)
Lemma be_iter_prop_preserved :
forall (n : nat) (be : bool_expr) (f : bool_expr -> bool_expr)
(pr : bool_expr -> Prop),
pr be ->
(forall be' : bool_expr, pr be' -> pr (f be')) -> pr (be_iter f be n).
Lemma be_iter2n_prop_preserved :
forall (n : nat) (be : bool_expr) (f : bool_expr -> bool_expr)
(pr : bool_expr -> Prop),
pr be ->
(forall be' : bool_expr, pr be' -> pr (f be')) ->
pr (fst (be_iter2n f be n)).
Lemma be_iter_eq_preserved :
forall (n : nat) (be : bool_expr) (f1 f2 : bool_expr -> bool_expr),
(forall be' : bool_expr, f1 be' = f2 be') ->
be_iter f1 be n = be_iter f2 be n.
Lemma be_iter2n_eq_preserved :
forall (n : nat) (be : bool_expr) (f1 f2 : bool_expr -> bool_expr),
(forall be' : bool_expr, f1 be' = f2 be') ->
be_iter2n f1 be n = be_iter2n f2 be n.
Lemma be_iter_eq_1 :
forall (n : nat) (be : bool_expr) (f : bool_expr -> bool_expr),
be_eq (f be) be -> be_eq (be_iter f be n) be.
Lemma be_iter_eq_preserved_1 :
forall (n : nat) (be1 be2 : bool_expr) (f1 f2 : bool_expr -> bool_expr),
be_eq be1 be2 ->
(forall be1' be2' : bool_expr, be_eq be1' be2' -> be_eq (f1 be1') (f1 be2')) ->
(forall be1' be2' : bool_expr, be_eq be1' be2' -> be_eq (f2 be1') (f2 be2')) ->
(forall be1' be2' : bool_expr, be_eq be1' be2' -> be_eq (f1 be1') (f2 be2')) ->
be_eq (be_iter f1 be1 n) (be_iter f2 be2 n).
Lemma be_iter2n_eq_preserved_1 :
forall (n : nat) (be1 be2 : bool_expr) (f1 f2 : bool_expr -> bool_expr),
be_eq be1 be2 ->
(forall be1' be2' : bool_expr, be_eq be1' be2' -> be_eq (f1 be1') (f1 be2')) ->
(forall be1' be2' : bool_expr, be_eq be1' be2' -> be_eq (f2 be1') (f2 be2')) ->
(forall be1' be2' : bool_expr, be_eq be1' be2' -> be_eq (f1 be1') (f2 be2')) ->
be_eq (fst (be_iter2n f1 be1 n)) (fst (be_iter2n f2 be2 n)) /\
snd (be_iter2n f1 be1 n) = snd (be_iter2n f2 be2 n).
Lemma be_iter2n_eq_preserved_2 :
forall (n : nat) (be1 be2 : bool_expr) (f1 f2 : bool_expr -> bool_expr),
be_eq be1 be2 ->
(forall be1' be2' : bool_expr, be_eq be1' be2' -> be_eq (f1 be1') (f1 be2')) ->
(forall be1' be2' : bool_expr, be_eq be1' be2' -> be_eq (f2 be1') (f2 be2')) ->
(forall be1' be2' : bool_expr, be_eq be1' be2' -> be_eq (f1 be1') (f2 be2')) ->
be_eq (fst (be_iter2n f1 be1 n)) (fst (be_iter2n f2 be2 n)).
Lemma be_iter_le_preserved :
forall (n : nat) (be1 be2 : bool_expr) (f1 f2 : bool_expr -> bool_expr),
be_le be1 be2 ->
(forall be1' be2' : bool_expr, be_eq be1' be2' -> be_eq (f1 be1') (f1 be2')) ->
(forall be1' be2' : bool_expr, be_eq be1' be2' -> be_eq (f2 be1') (f2 be2')) ->
(forall be1' be2' : bool_expr, be_le be1' be2' -> be_le (f1 be1') (f2 be2')) ->
be_le (be_iter f1 be1 n) (be_iter f2 be2 n).
Lemma be_iter2n_true :
forall (n : nat) (be : bool_expr) (f : bool_expr -> bool_expr),
(forall be1 be2 : bool_expr, be_eq be1 be2 -> be_eq (f be1) (f be2)) ->
snd (be_iter2n f be n) = true -> fp f (fst (be_iter2n f be n)).
Lemma be_iter2n_0 :
forall (n : nat) (be : bool_expr) (f : bool_expr -> bool_expr),
(forall be1 be2 : bool_expr, be_eq be1 be2 -> be_eq (f be1) (f be2)) ->
fp f be -> be_eq be (fst (be_iter2n f be n)).