(* 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.

(* 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.