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.

(* Specifications: *)
Lemma bool_fun_eq_refl : forall bf : bool_fun, bool_fun_eq bf bf.
Lemma bool_fun_eq_sym : forall bf1 bf2 : bool_fun, bool_fun_eq bf1 bf2 -> bool_fun_eq bf2 bf1.
Lemma bool_fun_eq_trans : forall bf1 bf2 bf3 : bool_fun, bool_fun_eq bf1 bf2 -> bool_fun_eq bf2 bf3 -> bool_fun_eq bf1 bf3.
Lemma bool_fun_neg_preserves_eq : forall bf1 bf2 : bool_fun, bool_fun_eq bf1 bf2 -> bool_fun_eq (bool_fun_neg bf1) (bool_fun_neg bf2).
Lemma bool_fun_or_preserves_eq : forall bf1 bf1' bf2 bf2' : bool_fun, bool_fun_eq bf1 bf1' -> bool_fun_eq bf2 bf2' -> bool_fun_eq (bool_fun_or bf1 bf2) (bool_fun_or bf1' bf2').
Lemma bool_fun_if_preserves_eq : forall (x : BDDvar) (bf1 bf2 bf1' bf2' : bool_fun), bool_fun_eq bf1 bf1' -> bool_fun_eq bf2 bf2' -> bool_fun_eq (bool_fun_if x bf1 bf2) (bool_fun_if x bf1' bf2').
Lemma bool_fun_and_preserves_eq : forall bf1 bf1' bf2 bf2' : bool_fun, bool_fun_eq bf1 bf1' -> bool_fun_eq bf2 bf2' -> bool_fun_eq (bool_fun_and bf1 bf2) (bool_fun_and bf1' bf2').
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').
Lemma bool_fun_iff_preserves_eq : forall bf1 bf1' bf2 bf2' : bool_fun, bool_fun_eq bf1 bf1' -> bool_fun_eq bf2 bf2' -> bool_fun_eq (bool_fun_iff bf1 bf2) (bool_fun_iff bf1' bf2').
Lemma bool_fun_forall_preserves_eq : forall (bf1 bf2 : bool_fun) (x : BDDvar), bool_fun_eq bf1 bf2 -> bool_fun_eq (bool_fun_forall x bf1) (bool_fun_forall x bf2).
Lemma bool_fun_ex_preserves_eq : forall (bf1 bf2 : bool_fun) (x : BDDvar), bool_fun_eq bf1 bf2 -> bool_fun_eq (bool_fun_ex x bf1) (bool_fun_ex x bf2).
Lemma bool_fun_neg_zero : bool_fun_eq (bool_fun_neg bool_fun_zero) bool_fun_one.
Lemma bool_fun_neg_one : bool_fun_eq (bool_fun_neg bool_fun_one) bool_fun_zero.
Lemma bool_fun_and_lemma : forall bf1 bf2 : bool_fun, bool_fun_eq (bool_fun_and bf1 bf2) (bool_fun_neg (bool_fun_or (bool_fun_neg bf1) (bool_fun_neg bf2))).
Lemma bool_fun_impl_lemma : forall bf1 bf2 : bool_fun, bool_fun_eq (bool_fun_impl bf1 bf2) (bool_fun_or (bool_fun_neg bf1) bf2).
Lemma bool_fun_iff_lemma : forall bf1 bf2 : bool_fun, bool_fun_eq (bool_fun_iff bf1 bf2) (bool_fun_impl (bool_fun_or bf1 bf2) (bool_fun_and bf1 bf2)).
Lemma bool_fun_ex_lemma : forall (bf : bool_fun) (x : BDDvar), bool_fun_eq (bool_fun_ex x bf) (bool_fun_neg (bool_fun_forall x (bool_fun_neg bf))).
Lemma bool_fun_var_lemma : forall x : BDDvar, bool_fun_eq (bool_fun_var x) (bool_fun_if x bool_fun_one bool_fun_zero).
Lemma bool_fun_eq_neg_eq : forall bf1 bf2 : bool_fun, bool_fun_eq (bool_fun_neg bf1) (bool_fun_neg bf2) -> bool_fun_eq bf1 bf2.
Lemma bool_fun_neg_orthogonal : forall (x : BDDvar) (bf1 bf2 : bool_fun), bool_fun_eq (bool_fun_neg (bool_fun_if x bf1 bf2)) (bool_fun_if x (bool_fun_neg bf1) (bool_fun_neg bf2)).
Lemma bool_fun_or_zero : forall bf : bool_fun, bool_fun_eq (bool_fun_or bf bool_fun_zero) bf.
Lemma bool_fun_or_one : forall bf : bool_fun, bool_fun_eq (bool_fun_or bf bool_fun_one) bool_fun_one.
Lemma bool_fun_or_comm : forall bf1 bf2 : bool_fun, bool_fun_eq (bool_fun_or bf1 bf2) (bool_fun_or bf2 bf1).
Lemma bool_fun_and_comm : forall bf1 bf2 : bool_fun, bool_fun_eq (bool_fun_and bf1 bf2) (bool_fun_and bf2 bf1).
Lemma bool_fun_and_idempotent : forall bf : bool_fun, bool_fun_eq (bool_fun_and bf bf) bf.
Lemma bool_fun_or_orthogonal : forall (x : BDDvar) (bf1 bf2 bf1' bf2' : bool_fun), bool_fun_eq (bool_fun_or (bool_fun_if x bf1 bf2) (bool_fun_if x bf1' bf2')) (bool_fun_if x (bool_fun_or bf1 bf1') (bool_fun_or bf2 bf2')).
Lemma bool_fun_or_orthogonal_right : forall (x : BDDvar) (bf bf1' bf2' : bool_fun), bool_fun_eq (bool_fun_or bf (bool_fun_if x bf1' bf2')) (bool_fun_if x (bool_fun_or bf bf1') (bool_fun_or bf bf2')).
Lemma bool_fun_or_orthogonal_left : forall (x : BDDvar) (bf1 bf2 bf' : bool_fun), bool_fun_eq (bool_fun_or (bool_fun_if x bf1 bf2) bf') (bool_fun_if x (bool_fun_or bf1 bf') (bool_fun_or bf2 bf')).
Lemma bool_fun_and_orthogonal : forall (x : BDDvar) (bf1 bf2 bf1' bf2' : bool_fun), bool_fun_eq (bool_fun_and (bool_fun_if x bf1 bf2) (bool_fun_if x bf1' bf2')) (bool_fun_if x (bool_fun_and bf1 bf1') (bool_fun_and bf2 bf2')).
Lemma bool_fun_forall_independent : forall (x : BDDvar) (bf : bool_fun), bool_fun_independent bf x -> bool_fun_eq (bool_fun_forall x bf) bf.
Lemma bool_fun_forall_zero : forall x : BDDvar, bool_fun_eq (bool_fun_forall x bool_fun_zero) bool_fun_zero.
Lemma bool_fun_forall_one : forall x : BDDvar, bool_fun_eq (bool_fun_forall x bool_fun_one) bool_fun_one.
Lemma bool_fun_restrict_zero : forall (x : BDDvar) (b : bool), bool_fun_eq (bool_fun_restrict bool_fun_zero x b) bool_fun_zero.
Lemma bool_fun_restrict_one : forall (x : BDDvar) (b : bool), bool_fun_eq (bool_fun_restrict bool_fun_one x b) bool_fun_one.
Lemma bool_fun_restrict_preserves_eq : forall (bf1 bf2 : bool_fun) (x : BDDvar) (b : bool), bool_fun_eq bf1 bf2 -> bool_fun_eq (bool_fun_restrict bf1 x b) (bool_fun_restrict bf2 x b).
Lemma bool_fun_independent_zero : forall x : BDDvar, bool_fun_independent bool_fun_zero x.
Lemma bool_fun_independent_one : forall x : BDDvar, bool_fun_independent bool_fun_one x.
Lemma bool_fun_eq_independent : forall (bf1 bf2 : bool_fun) (x : BDDvar), bool_fun_eq bf1 bf2 -> bool_fun_independent bf1 x -> bool_fun_independent bf2 x.
Lemma bool_fun_if_restrict_true : forall (bf1 bf2 : bool_fun) (x : BDDvar), bool_fun_eq (bool_fun_restrict (bool_fun_if x bf1 bf2) x true) (bool_fun_restrict bf1 x true).
Lemma bool_fun_if_restrict_false : forall (bf1 bf2 : bool_fun) (x : BDDvar), bool_fun_eq (bool_fun_restrict (bool_fun_if x bf1 bf2) x false) (bool_fun_restrict bf2 x false).
Lemma bool_fun_if_restrict : forall (bf1 bf2 : bool_fun) (x y : BDDvar) (b : bool), Neqb x y = false -> bool_fun_eq (bool_fun_restrict (bool_fun_if x bf1 bf2) y b) (bool_fun_if x (bool_fun_restrict bf1 y b) (bool_fun_restrict bf2 y b)).
Lemma bool_fun_if_restrict_true_independent : forall (bf1 bf2 : bool_fun) (x : BDDvar), bool_fun_independent bf1 x -> bool_fun_eq (bool_fun_restrict (bool_fun_if x bf1 bf2) x true) bf1.
Lemma bool_fun_if_restrict_false_independent : forall (bf1 bf2 : bool_fun) (x : BDDvar), bool_fun_independent bf2 x -> bool_fun_eq (bool_fun_restrict (bool_fun_if x bf1 bf2) x false) bf2.
Lemma bool_fun_forall_orthogonal : forall (x u : BDDvar) (bf1 bf2 : bool_fun), Neqb x u = false -> bool_fun_eq (bool_fun_forall u (bool_fun_if x bf1 bf2)) (bool_fun_if x (bool_fun_forall u bf1) (bool_fun_forall u bf2)).
Lemma bool_fun_independent_if : forall (x y : BDDvar) (bf1 bf2 : bool_fun), bool_fun_independent bf1 x -> bool_fun_independent bf2 x -> Neqb x y = false -> bool_fun_independent (bool_fun_if y bf1 bf2) x.
Lemma bool_fun_forall_if_egal : forall (x : BDDvar) (bf1 bf2 : bool_fun), bool_fun_independent bf1 x -> bool_fun_independent bf2 x -> bool_fun_eq (bool_fun_forall x (bool_fun_if x bf1 bf2)) (bool_fun_and bf1 bf2).
Lemma bool_fun_if_eq_1 : forall (bf1 bf2 : bool_fun) (x : BDDvar), bool_fun_eq bf1 bf2 -> bool_fun_eq (bool_fun_if x bf1 bf2) bf1.
Lemma bool_fun_if_eq_2 : forall (bf1 bf2 : bool_fun) (x : BDDvar), bool_fun_eq bf1 bf2 -> bool_fun_eq (bool_fun_if x bf1 bf2) bf2.
Lemma bool_fun_ext_zero : bool_fun_ext bool_fun_zero.
Lemma bool_fun_ext_one : bool_fun_ext bool_fun_one.
Lemma bool_fun_ext_if : forall (bf1 bf2 : bool_fun) (x : BDDvar), bool_fun_ext bf1 -> bool_fun_ext bf2 -> bool_fun_ext (bool_fun_if x bf1 bf2).