Definition BDDsubst (cfg : BDDconfig) (ul : list ad) 
  (node1 : ad) (x : BDDvar) (node2 : ad) :=
  match BDDvar_make gc cfg ul x with
  | (cfg1, nodex) =>
      match BDDiff gc cfg1 (nodex :: ul) nodex node2 with
      | (cfg2, node3) =>
          match BDDimpl gc cfg2 (node3 :: ul) node3 node1 with
          | (cfg3, node4) => BDDuniv cfg3 (node4 :: ul) x node4
          end
      end
  end.

(* Specifications: *)
Lemma BDDsubst_lemma : forall (cfg : BDDconfig) (ul : list ad) (node1 : ad) (x : BDDvar) (node2 : ad), BDDconfig_OK cfg -> used_list_OK cfg ul -> used_node' cfg ul node1 -> used_node' cfg ul node2 -> BDDconfig_OK (fst (BDDsubst cfg ul node1 x node2)) /\ config_node_OK (fst (BDDsubst cfg ul node1 x node2)) (snd (BDDsubst cfg ul node1 x node2)) /\ used_nodes_preserved cfg (fst (BDDsubst cfg ul node1 x node2)) ul /\ bool_fun_eq (bool_fun_of_BDD (fst (BDDsubst cfg ul node1 x node2)) (snd (BDDsubst cfg ul node1 x node2))) (bool_fun_subst1 x (bool_fun_of_BDD cfg node2) (bool_fun_of_BDD cfg node1)).
Lemma BDDsubst_config_OK : BDDconfig_OK (fst (BDDsubst cfg ul node1 x node2)).
Lemma BDDsubst_node_OK : config_node_OK (fst (BDDsubst cfg ul node1 x node2)) (snd (BDDsubst cfg ul node1 x node2)).
Lemma BDDsubst_used_nodes_preserved : used_nodes_preserved cfg (fst (BDDsubst cfg ul node1 x node2)) ul.
Lemma BDDsubst_list_OK : used_list_OK (fst (BDDsubst cfg ul node1 x node2)) ul.
Lemma BDDsubst_list_OK_cons : used_list_OK (fst (BDDsubst cfg ul node1 x node2)) (snd (BDDsubst cfg ul node1 x node2) :: ul).
Lemma BDDsubst_is_subst1 : bool_fun_eq (bool_fun_of_BDD (fst (BDDsubst cfg ul node1 x node2)) (snd (BDDsubst cfg ul node1 x node2))) (bool_fun_subst1 x (bool_fun_of_BDD cfg node2) (bool_fun_of_BDD cfg node1)).
Lemma BDDsubst_is_subst : bool_fun_eq (bool_fun_of_BDD (fst (BDDsubst cfg ul node1 x node2)) (snd (BDDsubst cfg ul node1 x node2))) (bool_fun_subst x (bool_fun_of_BDD cfg node2) (bool_fun_of_BDD cfg node1)).