(* This program is free software; you can redistribute it and/or      *)
(* modify it under the terms of the GNU Lesser General Public License *)
(* as published by the Free Software Foundation; either version 2.1   *)
(* of the License, or (at your option) any later version.             *)
(*                                                                    *)
(* This program is distributed in the hope that it will be useful,    *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of     *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *)
(* GNU General Public License for more details.                       *)
(*                                                                    *)
(* You should have received a copy of the GNU Lesser General Public   *)
(* License along with this program; if not, write to the Free         *)
(* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *)
(* 02110-1301 USA                                                     *)
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.

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)).