Definition var_env := BDDvar -> bool.Definition bool_fun := var_env -> bool.Definition bool_fun_eq (bf1 bf2 : bool_fun) :=
  forall vb : var_env, bf1 vb = bf2 vb.Definition bool_fun_zero (vb : var_env) := false.Definition bool_fun_one (vb : var_env) := true.Definition bool_fun_neg (bf : bool_fun) : bool_fun :=
  fun vb : var_env => negb (bf vb).Definition bool_fun_or (bf1 bf2 : bool_fun) : bool_fun :=
  fun vb : var_env => bf1 vb || bf2 vb.Definition bool_fun_and (bf1 bf2 : bool_fun) : bool_fun :=
  fun vb : var_env => bf1 vb && bf2 vb.Definition bool_fun_impl (bf1 bf2 : bool_fun) : bool_fun :=
  fun vb : var_env => implb (bf1 vb) (bf2 vb).Definition bool_fun_iff (bf1 bf2 : bool_fun) : bool_fun :=
  fun vb : var_env => eqb (bf1 vb) (bf2 vb).Definition bool_fun_if (x : BDDvar) (bf1 bf2 : bool_fun) : bool_fun :=
  fun vb : var_env => ifb (vb x) (bf1 vb) (bf2 vb).Definition bool_fun_var (x : BDDvar) : bool_fun := fun vb : var_env => vb x.Definition augment (vb : var_env) (x : BDDvar) (b : bool) : var_env :=
  fun y : BDDvar => if Neqb x y then b else vb y.Definition bool_fun_restrict (bf : bool_fun) (x : BDDvar) 
  (b : bool) : bool_fun := fun vb : var_env => bf (augment vb x b).Definition bool_fun_independent (bf : bool_fun) (x : BDDvar) :=
  forall b : bool, bool_fun_eq (bool_fun_restrict bf x b) bf.Definition bool_fun_forall (x : BDDvar) (bf : bool_fun) :=
  bool_fun_and (bool_fun_restrict bf x true) (bool_fun_restrict bf x false).Definition bool_fun_ex (x : BDDvar) (bf : bool_fun) :=
  bool_fun_or (bool_fun_restrict bf x true) (bool_fun_restrict bf x false).Definition bool_fun_ext (bf : bool_fun) :=
  forall vb vb' : var_env,
  (forall x : BDDvar, vb x = vb' x) -> bf vb = bf vb'.Inductive bool_expr : Set :=
  | Zero : bool_expr
  | One : bool_expr
  | Var : BDDvar -> bool_expr
  | Neg : bool_expr -> bool_expr
  | Or : bool_expr -> bool_expr -> bool_expr
  | ANd : bool_expr -> bool_expr -> bool_expr
  | Impl : bool_expr -> bool_expr -> bool_expr
  | Iff : bool_expr -> bool_expr -> bool_expr.Inductive bool_expr : Set :=
  | Zero : bool_expr
  | One : bool_expr
  | Var : BDDvar -> bool_expr
  | Neg : bool_expr -> bool_expr
  | Or : bool_expr -> bool_expr -> bool_expr
  | ANd : bool_expr -> bool_expr -> bool_expr
  | Impl : bool_expr -> bool_expr -> bool_expr
  | Iff : bool_expr -> bool_expr -> bool_expr.Inductive bool_expr : Set :=
  | Zero : bool_expr
  | One : bool_expr
  | Var : BDDvar -> bool_expr
  | Neg : bool_expr -> bool_expr
  | Or : bool_expr -> bool_expr -> bool_expr
  | ANd : bool_expr -> bool_expr -> bool_expr
  | Impl : bool_expr -> bool_expr -> bool_expr
  | Iff : bool_expr -> bool_expr -> bool_expr.Inductive bool_expr : Set :=
  | Zero : bool_expr
  | One : bool_expr
  | Var : BDDvar -> bool_expr
  | Neg : bool_expr -> bool_expr
  | Or : bool_expr -> bool_expr -> bool_expr
  | ANd : bool_expr -> bool_expr -> bool_expr
  | Impl : bool_expr -> bool_expr -> bool_expr
  | Iff : bool_expr -> bool_expr -> bool_expr.Inductive bool_expr : Set :=
  | Zero : bool_expr
  | One : bool_expr
  | Var : BDDvar -> bool_expr
  | Neg : bool_expr -> bool_expr
  | Or : bool_expr -> bool_expr -> bool_expr
  | ANd : bool_expr -> bool_expr -> bool_expr
  | Impl : bool_expr -> bool_expr -> bool_expr
  | Iff : bool_expr -> bool_expr -> bool_expr.Inductive bool_expr : Set :=
  | Zero : bool_expr
  | One : bool_expr
  | Var : BDDvar -> bool_expr
  | Neg : bool_expr -> bool_expr
  | Or : bool_expr -> bool_expr -> bool_expr
  | ANd : bool_expr -> bool_expr -> bool_expr
  | Impl : bool_expr -> bool_expr -> bool_expr
  | Iff : bool_expr -> bool_expr -> bool_expr.Inductive bool_expr : Set :=
  | Zero : bool_expr
  | One : bool_expr
  | Var : BDDvar -> bool_expr
  | Neg : bool_expr -> bool_expr
  | Or : bool_expr -> bool_expr -> bool_expr
  | ANd : bool_expr -> bool_expr -> bool_expr
  | Impl : bool_expr -> bool_expr -> bool_expr
  | Iff : bool_expr -> bool_expr -> bool_expr.Inductive bool_expr : Set :=
  | Zero : bool_expr
  | One : bool_expr
  | Var : BDDvar -> bool_expr
  | Neg : bool_expr -> bool_expr
  | Or : bool_expr -> bool_expr -> bool_expr
  | ANd : bool_expr -> bool_expr -> bool_expr
  | Impl : bool_expr -> bool_expr -> bool_expr
  | Iff : bool_expr -> bool_expr -> bool_expr.Inductive bool_expr : Set :=
  | Zero : bool_expr
  | One : bool_expr
  | Var : BDDvar -> bool_expr
  | Neg : bool_expr -> bool_expr
  | Or : bool_expr -> bool_expr -> bool_expr
  | ANd : bool_expr -> bool_expr -> bool_expr
  | Impl : bool_expr -> bool_expr -> bool_expr
  | Iff : bool_expr -> bool_expr -> bool_expr.Fixpoint bool_fun_of_bool_expr (be : bool_expr) : bool_fun :=
  match be with
  | Zero => bool_fun_zero
  | One => bool_fun_one
  | Var x => bool_fun_var x
  | Neg be' => bool_fun_neg (bool_fun_of_bool_expr be')
  | Or be1 be2 =>
      bool_fun_or (bool_fun_of_bool_expr be1) (bool_fun_of_bool_expr be2)
  | ANd be1 be2 =>
      bool_fun_and (bool_fun_of_bool_expr be1) (bool_fun_of_bool_expr be2)
  | Impl be1 be2 =>
      bool_fun_impl (bool_fun_of_bool_expr be1) (bool_fun_of_bool_expr be2)
  | Iff be1 be2 =>
      bool_fun_iff (bool_fun_of_bool_expr be1) (bool_fun_of_bool_expr be2)
  end.

Lemma bool_fun_impl_preserves_eq : forall bf1 bf1' bf2 bf2' : bool_fun, bool_fun_eq bf1 bf1' -> bool_fun_eq bf2 bf2' -> bool_fun_eq (bool_fun_impl bf1 bf2) (bool_fun_impl bf1' bf2').