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.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.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.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.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.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.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.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.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.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.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.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.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)).