Fixpoint BDDor_1 (cfg : BDDconfig) (memo : BDDor_memo) 
 (node1 node2 : ad) (bound : nat) {struct bound} :
 BDDconfig * (ad * BDDor_memo) :=
  match BDDor_memo_lookup memo node1 node2 with
  | Some node => (cfg, (node, memo))
  | None =>
      if Neqb node1 BDDzero
      then (cfg, (node2, BDDor_memo_put memo BDDzero node2 node2))
      else
       if Neqb node1 BDDone
       then (cfg, (BDDone, BDDor_memo_put memo BDDone node2 BDDone))
       else
        if Neqb node2 BDDzero
        then (cfg, (node1, BDDor_memo_put memo node1 BDDzero node1))
        else
         if Neqb node2 BDDone
         then (cfg, (BDDone, BDDor_memo_put memo node1 BDDone BDDone))
         else
          match bound with
          | O => (initBDDconfig, (BDDzero, initBDDor_memo))
          | S bound' =>
              match BDDcompare (var cfg node1) (var cfg node2) with
              | Datatypes.Eq =>
                  (fst
                     (BDDmake
                        (fst
                           (BDDor_1
                              (fst
                                 (BDDor_1 cfg memo 
                                    (low cfg node1) 
                                    (low cfg node2) bound'))
                              (snd
                                 (snd
                                    (BDDor_1 cfg memo 
                                       (low cfg node1) 
                                       (low cfg node2) bound')))
                              (high cfg node1) (high cfg node2) bound'))
                        (var cfg node1)
                        (fst
                           (snd
                              (BDDor_1 cfg memo (low cfg node1)
                                 (low cfg node2) bound')))
                        (fst
                           (snd
                              (BDDor_1
                                 (fst
                                    (BDDor_1 cfg memo 
                                       (low cfg node1) 
                                       (low cfg node2) bound'))
                                 (snd
                                    (snd
                                       (BDDor_1 cfg memo 
                                          (low cfg node1) 
                                          (low cfg node2) bound')))
                                 (high cfg node1) (high cfg node2) bound')))),
                  (snd
                     (BDDmake
                        (fst
                           (BDDor_1
                              (fst
                                 (BDDor_1 cfg memo 
                                    (low cfg node1) 
                                    (low cfg node2) bound'))
                              (snd
                                 (snd
                                    (BDDor_1 cfg memo 
                                       (low cfg node1) 
                                       (low cfg node2) bound')))
                              (high cfg node1) (high cfg node2) bound'))
                        (var cfg node1)
                        (fst
                           (snd
                              (BDDor_1 cfg memo (low cfg node1)
                                 (low cfg node2) bound')))
                        (fst
                           (snd
                              (BDDor_1
                                 (fst
                                    (BDDor_1 cfg memo 
                                       (low cfg node1) 
                                       (low cfg node2) bound'))
                                 (snd
                                    (snd
                                       (BDDor_1 cfg memo 
                                          (low cfg node1) 
                                          (low cfg node2) bound')))
                                 (high cfg node1) (high cfg node2) bound')))),
                  BDDor_memo_put
                    (snd
                       (snd
                          (BDDor_1
                             (fst
                                (BDDor_1 cfg memo (low cfg node1)
                                   (low cfg node2) bound'))
                             (snd
                                (snd
                                   (BDDor_1 cfg memo 
                                      (low cfg node1) 
                                      (low cfg node2) bound')))
                             (high cfg node1) (high cfg node2) bound')))
                    node1 node2
                    (snd
                       (BDDmake
                          (fst
                             (BDDor_1
                                (fst
                                   (BDDor_1 cfg memo 
                                      (low cfg node1) 
                                      (low cfg node2) bound'))
                                (snd
                                   (snd
                                      (BDDor_1 cfg memo 
                                         (low cfg node1) 
                                         (low cfg node2) bound')))
                                (high cfg node1) (high cfg node2) bound'))
                          (var cfg node1)
                          (fst
                             (snd
                                (BDDor_1 cfg memo (low cfg node1)
                                   (low cfg node2) bound')))
                          (fst
                             (snd
                                (BDDor_1
                                   (fst
                                      (BDDor_1 cfg memo 
                                         (low cfg node1) 
                                         (low cfg node2) bound'))
                                   (snd
                                      (snd
                                         (BDDor_1 cfg memo 
                                            (low cfg node1) 
                                            (low cfg node2) bound')))
                                   (high cfg node1) 
                                   (high cfg node2) bound')))))))
              | Datatypes.Lt =>
                  (fst
                     (BDDmake
                        (fst
                           (BDDor_1
                              (fst
                                 (BDDor_1 cfg memo node1 
                                    (low cfg node2) bound'))
                              (snd
                                 (snd
                                    (BDDor_1 cfg memo node1 
                                       (low cfg node2) bound'))) node1
                              (high cfg node2) bound')) 
                        (var cfg node2)
                        (fst
                           (snd
                              (BDDor_1 cfg memo node1 (low cfg node2) bound')))
                        (fst
                           (snd
                              (BDDor_1
                                 (fst
                                    (BDDor_1 cfg memo node1 
                                       (low cfg node2) bound'))
                                 (snd
                                    (snd
                                       (BDDor_1 cfg memo node1
                                          (low cfg node2) bound'))) node1
                                 (high cfg node2) bound')))),
                  (snd
                     (BDDmake
                        (fst
                           (BDDor_1
                              (fst
                                 (BDDor_1 cfg memo node1 
                                    (low cfg node2) bound'))
                              (snd
                                 (snd
                                    (BDDor_1 cfg memo node1 
                                       (low cfg node2) bound'))) node1
                              (high cfg node2) bound')) 
                        (var cfg node2)
                        (fst
                           (snd
                              (BDDor_1 cfg memo node1 (low cfg node2) bound')))
                        (fst
                           (snd
                              (BDDor_1
                                 (fst
                                    (BDDor_1 cfg memo node1 
                                       (low cfg node2) bound'))
                                 (snd
                                    (snd
                                       (BDDor_1 cfg memo node1
                                          (low cfg node2) bound'))) node1
                                 (high cfg node2) bound')))),
                  BDDor_memo_put
                    (snd
                       (snd
                          (BDDor_1
                             (fst
                                (BDDor_1 cfg memo node1 
                                   (low cfg node2) bound'))
                             (snd
                                (snd
                                   (BDDor_1 cfg memo node1 
                                      (low cfg node2) bound'))) node1
                             (high cfg node2) bound'))) node1 node2
                    (snd
                       (BDDmake
                          (fst
                             (BDDor_1
                                (fst
                                   (BDDor_1 cfg memo node1 
                                      (low cfg node2) bound'))
                                (snd
                                   (snd
                                      (BDDor_1 cfg memo node1 
                                         (low cfg node2) bound'))) node1
                                (high cfg node2) bound')) 
                          (var cfg node2)
                          (fst
                             (snd
                                (BDDor_1 cfg memo node1 
                                   (low cfg node2) bound')))
                          (fst
                             (snd
                                (BDDor_1
                                   (fst
                                      (BDDor_1 cfg memo node1 
                                         (low cfg node2) bound'))
                                   (snd
                                      (snd
                                         (BDDor_1 cfg memo node1
                                            (low cfg node2) bound'))) node1
                                   (high cfg node2) bound')))))))
              | Datatypes.Gt =>
                  (fst
                     (BDDmake
                        (fst
                           (BDDor_1
                              (fst
                                 (BDDor_1 cfg memo 
                                    (low cfg node1) node2 bound'))
                              (snd
                                 (snd
                                    (BDDor_1 cfg memo 
                                       (low cfg node1) node2 bound')))
                              (high cfg node1) node2 bound')) 
                        (var cfg node1)
                        (fst
                           (snd
                              (BDDor_1 cfg memo (low cfg node1) node2 bound')))
                        (fst
                           (snd
                              (BDDor_1
                                 (fst
                                    (BDDor_1 cfg memo 
                                       (low cfg node1) node2 bound'))
                                 (snd
                                    (snd
                                       (BDDor_1 cfg memo 
                                          (low cfg node1) node2 bound')))
                                 (high cfg node1) node2 bound')))),
                  (snd
                     (BDDmake
                        (fst
                           (BDDor_1
                              (fst
                                 (BDDor_1 cfg memo 
                                    (low cfg node1) node2 bound'))
                              (snd
                                 (snd
                                    (BDDor_1 cfg memo 
                                       (low cfg node1) node2 bound')))
                              (high cfg node1) node2 bound')) 
                        (var cfg node1)
                        (fst
                           (snd
                              (BDDor_1 cfg memo (low cfg node1) node2 bound')))
                        (fst
                           (snd
                              (BDDor_1
                                 (fst
                                    (BDDor_1 cfg memo 
                                       (low cfg node1) node2 bound'))
                                 (snd
                                    (snd
                                       (BDDor_1 cfg memo 
                                          (low cfg node1) node2 bound')))
                                 (high cfg node1) node2 bound')))),
                  BDDor_memo_put
                    (snd
                       (snd
                          (BDDor_1
                             (fst
                                (BDDor_1 cfg memo (low cfg node1) node2
                                   bound'))
                             (snd
                                (snd
                                   (BDDor_1 cfg memo 
                                      (low cfg node1) node2 bound')))
                             (high cfg node1) node2 bound'))) node1 node2
                    (snd
                       (BDDmake
                          (fst
                             (BDDor_1
                                (fst
                                   (BDDor_1 cfg memo 
                                      (low cfg node1) node2 bound'))
                                (snd
                                   (snd
                                      (BDDor_1 cfg memo 
                                         (low cfg node1) node2 bound')))
                                (high cfg node1) node2 bound'))
                          (var cfg node1)
                          (fst
                             (snd
                                (BDDor_1 cfg memo (low cfg node1) node2
                                   bound')))
                          (fst
                             (snd
                                (BDDor_1
                                   (fst
                                      (BDDor_1 cfg memo 
                                         (low cfg node1) node2 bound'))
                                   (snd
                                      (snd
                                         (BDDor_1 cfg memo 
                                            (low cfg node1) node2 bound')))
                                   (high cfg node1) node2 bound')))))))
              end
          end
  end.

(* Specifications: *)
Lemma BDDor_1_lemma_1 : forall (cfg : BDDconfig) (memo : BDDor_memo) (node1 node2 node : ad) (bound : nat), BDDor_memo_lookup memo node1 node2 = Some node -> BDDor_1 cfg memo node1 node2 bound = (cfg, (node, memo)).
Lemma BDDor_1_lemma_zero_1 : forall (cfg : BDDconfig) (memo : BDDor_memo) (node1 : ad) (bound : nat), BDDor_memo_lookup memo node1 BDDzero = None -> BDDor_1 cfg memo node1 BDDzero bound = (cfg, (node1, BDDor_memo_put memo node1 BDDzero node1)).
Lemma BDDor_1_lemma_one_1 : forall (cfg : BDDconfig) (memo : BDDor_memo) (node1 : ad) (bound : nat), BDDor_memo_lookup memo node1 BDDone = None -> BDDor_1 cfg memo node1 BDDone bound = (cfg, (BDDone, BDDor_memo_put memo node1 BDDone BDDone)).
Lemma BDDor_1_lemma_zero_2 : forall (cfg : BDDconfig) (memo : BDDor_memo) (node2 : ad) (bound : nat), BDDor_memo_lookup memo BDDzero node2 = None -> BDDor_1 cfg memo BDDzero node2 bound = (cfg, (node2, BDDor_memo_put memo BDDzero node2 node2)).
Lemma BDDor_1_lemma_one_2 : forall (cfg : BDDconfig) (memo : BDDor_memo) (node2 : ad) (bound : nat), BDDor_memo_lookup memo BDDone node2 = None -> BDDor_1 cfg memo BDDone node2 bound = (cfg, (BDDone, BDDor_memo_put memo BDDone node2 BDDone)).
Lemma BDDor_1_lemma_internal_1 : forall (cfg : BDDconfig) (memo : BDDor_memo) (node1 node2 : ad) (bound bound' : nat), BDDor_memo_lookup memo node1 node2 = None -> BDDconfig_OK cfg -> is_internal_node cfg node1 -> is_internal_node cfg node2 -> max (nat_of_N (var cfg node1)) (nat_of_N (var cfg node2)) < bound -> bound = S bound' -> BDDcompare (var cfg node1) (var cfg node2) = Datatypes.Eq -> BDDor_1 cfg memo node1 node2 bound = (fst (BDDmake (fst (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound'))) (high cfg node1) (high cfg node2) bound')) (var cfg node1) (fst (snd (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound'))) (fst (snd (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound'))) (high cfg node1) (high cfg node2) bound')))), (snd (BDDmake (fst (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound'))) (high cfg node1) (high cfg node2) bound')) (var cfg node1) (fst (snd (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound'))) (fst (snd (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound'))) (high cfg node1) (high cfg node2) bound')))), BDDor_memo_put (snd (snd (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound'))) (high cfg node1) (high cfg node2) bound'))) node1 node2 (snd (BDDmake (fst (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound'))) (high cfg node1) (high cfg node2) bound')) (var cfg node1) (fst (snd (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound'))) (fst (snd (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) (low cfg node2) bound'))) (high cfg node1) (high cfg node2) bound'))))))).
Lemma BDDor_1_lemma_internal_2 : forall (cfg : BDDconfig) (memo : BDDor_memo) (node1 node2 : ad) (bound bound' : nat), BDDor_memo_lookup memo node1 node2 = None -> BDDconfig_OK cfg -> is_internal_node cfg node1 -> is_internal_node cfg node2 -> max (nat_of_N (var cfg node1)) (nat_of_N (var cfg node2)) < bound -> bound = S bound' -> BDDcompare (var cfg node1) (var cfg node2) = Datatypes.Lt -> BDDor_1 cfg memo node1 node2 bound = (fst (BDDmake (fst (BDDor_1 (fst (BDDor_1 cfg memo node1 (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo node1 (low cfg node2) bound'))) node1 (high cfg node2) bound')) (var cfg node2) (fst (snd (BDDor_1 cfg memo node1 (low cfg node2) bound'))) (fst (snd (BDDor_1 (fst (BDDor_1 cfg memo node1 (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo node1 (low cfg node2) bound'))) node1 (high cfg node2) bound')))), (snd (BDDmake (fst (BDDor_1 (fst (BDDor_1 cfg memo node1 (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo node1 (low cfg node2) bound'))) node1 (high cfg node2) bound')) (var cfg node2) (fst (snd (BDDor_1 cfg memo node1 (low cfg node2) bound'))) (fst (snd (BDDor_1 (fst (BDDor_1 cfg memo node1 (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo node1 (low cfg node2) bound'))) node1 (high cfg node2) bound')))), BDDor_memo_put (snd (snd (BDDor_1 (fst (BDDor_1 cfg memo node1 (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo node1 (low cfg node2) bound'))) node1 (high cfg node2) bound'))) node1 node2 (snd (BDDmake (fst (BDDor_1 (fst (BDDor_1 cfg memo node1 (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo node1 (low cfg node2) bound'))) node1 (high cfg node2) bound')) (var cfg node2) (fst (snd (BDDor_1 cfg memo node1 (low cfg node2) bound'))) (fst (snd (BDDor_1 (fst (BDDor_1 cfg memo node1 (low cfg node2) bound')) (snd (snd (BDDor_1 cfg memo node1 (low cfg node2) bound'))) node1 (high cfg node2) bound'))))))).
Lemma BDDor_1_lemma_internal_3 : forall (cfg : BDDconfig) (memo : BDDor_memo) (node1 node2 : ad) (bound bound' : nat), BDDor_memo_lookup memo node1 node2 = None -> BDDconfig_OK cfg -> is_internal_node cfg node1 -> is_internal_node cfg node2 -> max (nat_of_N (var cfg node1)) (nat_of_N (var cfg node2)) < bound -> bound = S bound' -> BDDcompare (var cfg node1) (var cfg node2) = Datatypes.Gt -> BDDor_1 cfg memo node1 node2 bound = (fst (BDDmake (fst (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) node2 bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) node2 bound'))) (high cfg node1) node2 bound')) (var cfg node1) (fst (snd (BDDor_1 cfg memo (low cfg node1) node2 bound'))) (fst (snd (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) node2 bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) node2 bound'))) (high cfg node1) node2 bound')))), (snd (BDDmake (fst (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) node2 bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) node2 bound'))) (high cfg node1) node2 bound')) (var cfg node1) (fst (snd (BDDor_1 cfg memo (low cfg node1) node2 bound'))) (fst (snd (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) node2 bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) node2 bound'))) (high cfg node1) node2 bound')))), BDDor_memo_put (snd (snd (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) node2 bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) node2 bound'))) (high cfg node1) node2 bound'))) node1 node2 (snd (BDDmake (fst (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) node2 bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) node2 bound'))) (high cfg node1) node2 bound')) (var cfg node1) (fst (snd (BDDor_1 cfg memo (low cfg node1) node2 bound'))) (fst (snd (BDDor_1 (fst (BDDor_1 cfg memo (low cfg node1) node2 bound')) (snd (snd (BDDor_1 cfg memo (low cfg node1) node2 bound'))) (high cfg node1) node2 bound'))))))).
Lemma BDDvar_le_max_2 : forall x y : BDDvar, BDDvar_le x (BDDvar_max y x) = true.
Lemma BDDvar_le_max_1 : forall x y : BDDvar, BDDvar_le x (BDDvar_max x y) = true.
Lemma BDDor_1_internal : forall (cfg : BDDconfig) (memo : BDDor_memo) (node1 node2 : ad) (bound : nat), BDDconfig_OK cfg -> config_node_OK cfg node1 -> config_node_OK cfg node2 -> BDDor_memo_OK cfg memo -> is_internal_node (fst (BDDor_1 cfg memo node1 node2 bound)) (fst (snd (BDDor_1 cfg memo node1 node2 bound))) -> is_internal_node cfg node1 \/ is_internal_node cfg node2.