Fixpoint BDDmu_eval (f : mu_form) :
 BDDconfig -> list ad -> Brel_env -> BDDconfig * ad :=
  fun cfg ul bre =>
  match f with
  | mu_0 => (cfg, BDDzero)
  | mu_1 => (cfg, BDDone)
  | mu_ap p => BDDvar_make gc cfg ul p
  | mu_rel_var P =>
      match MapGet _ bre P with
      | None => (cfg, BDDzero)
      | Some node => (cfg, node)
      end
  | mu_neg g =>
      match BDDmu_eval g cfg ul bre with
      | (cfgg, nodeg) => BDDneg gc cfgg (nodeg :: ul) nodeg
      end
  | mu_and g h =>
      match BDDmu_eval g cfg ul bre with
      | (cfgg, nodeg) =>
          match BDDmu_eval h cfgg (nodeg :: ul) bre with
          | (cfgh, nodeh) =>
              BDDand gc cfgh (nodeh :: nodeg :: ul) nodeg nodeh
          end
      end
  | mu_or g h =>
      match BDDmu_eval g cfg ul bre with
      | (cfgg, nodeg) =>
          match BDDmu_eval h cfgg (nodeg :: ul) bre with
          | (cfgh, nodeh) => BDDor gc cfgh (nodeh :: nodeg :: ul) nodeg nodeh
          end
      end
  | mu_impl g h =>
      match BDDmu_eval g cfg ul bre with
      | (cfgg, nodeg) =>
          match BDDmu_eval h cfgg (nodeg :: ul) bre with
          | (cfgh, nodeh) =>
              BDDimpl gc cfgh (nodeh :: nodeg :: ul) nodeg nodeh
          end
      end
  | mu_iff g h =>
      match BDDmu_eval g cfg ul bre with
      | (cfgg, nodeg) =>
          match BDDmu_eval h cfgg (nodeg :: ul) bre with
          | (cfgh, nodeh) =>
              BDDiff gc cfgh (nodeh :: nodeg :: ul) nodeg nodeh
          end
      end
  | mu_all t g =>
      match MapGet _ bte t with
      | None => (cfg, BDDzero)
      | Some nodet =>
          match BDDmu_eval g cfg ul bre with
          | (cfgg, nodeg) => BDDmu_all N gc cfgg (nodeg :: ul) nodet nodeg
          end
      end
  | mu_ex t g =>
      match MapGet _ bte t with
      | None => (cfg, BDDzero)
      | Some nodet =>
          match BDDmu_eval g cfg ul bre with
          | (cfgg, nodeg) => BDDmu_ex N gc cfgg (nodeg :: ul) nodet nodeg
          end
      end
  | mu_mu P g =>
      fst
        (BDDiter2n
           (fun cfg node =>
            BDDmu_eval g cfg (node :: ul) (MapPut _ bre P node)) cfg BDDzero
           N)
  end.

(* Specifications: *)
Lemma BDDmu_eval_ok : forall (f : mu_form) (cfg : BDDconfig) (ul : list ad) (re : rel_env) (bre : Brel_env), BDDconfig_OK cfg -> used_list_OK cfg ul -> cfg_ul_bre_ok cfg ul bre -> cfg_re_bre_ok cfg re bre -> cfg_ul_bte_ok cfg ul bte -> cfg_te_bte_ok cfg te bte -> f_bre_ok f bre -> f_bte_ok f bte -> BDDconfig_OK (fst (BDDmu_eval f cfg ul bre)) /\ config_node_OK (fst (BDDmu_eval f cfg ul bre)) (snd (BDDmu_eval f cfg ul bre)) /\ used_nodes_preserved cfg (fst (BDDmu_eval f cfg ul bre)) ul /\ bool_fun_eq (bool_fun_of_BDD (fst (BDDmu_eval f cfg ul bre)) (snd (BDDmu_eval f cfg ul bre))) (bool_fun_of_bool_expr (mu_eval f re)).