Definition BDDstate := Map (BDDvar * (ad * ad)).(* BDDstates are maps from (node) addresses to actual nodes.
	These nodes contain a variable, the address of the left subBDD,
	and the address of the right subBDD.
	BDDstates should obey a few invariants: *)

  Definition initBDDstate := newMap (BDDvar * (ad * ad)).Inductive BDDbounded (bs : BDDstate) : ad -> BDDvar -> Prop :=
    | BDDbounded_0 : forall n : BDDvar, BDDbounded bs BDDzero n
    | BDDbounded_1 : forall n : BDDvar, BDDbounded bs BDDone n
    | BDDbounded_2 :
        forall (node : ad) (n x : BDDvar) (l r : ad),
        MapGet _ bs node = Some (x, (l, r)) ->
        BDDcompare x n = Datatypes.Lt ->
        Neqb l r = false ->
        BDDbounded bs l x -> BDDbounded bs r x -> BDDbounded bs node n.Inductive BDDbounded (bs : BDDstate) : ad -> BDDvar -> Prop :=
    | BDDbounded_0 : forall n : BDDvar, BDDbounded bs BDDzero n
    | BDDbounded_1 : forall n : BDDvar, BDDbounded bs BDDone n
    | BDDbounded_2 :
        forall (node : ad) (n x : BDDvar) (l r : ad),
        MapGet _ bs node = Some (x, (l, r)) ->
        BDDcompare x n = Datatypes.Lt ->
        Neqb l r = false ->
        BDDbounded bs l x -> BDDbounded bs r x -> BDDbounded bs node n.Inductive BDDbounded (bs : BDDstate) : ad -> BDDvar -> Prop :=
    | BDDbounded_0 : forall n : BDDvar, BDDbounded bs BDDzero n
    | BDDbounded_1 : forall n : BDDvar, BDDbounded bs BDDone n
    | BDDbounded_2 :
        forall (node : ad) (n x : BDDvar) (l r : ad),
        MapGet _ bs node = Some (x, (l, r)) ->
        BDDcompare x n = Datatypes.Lt ->
        Neqb l r = false ->
        BDDbounded bs l x -> BDDbounded bs r x -> BDDbounded bs node n.Inductive BDDbounded (bs : BDDstate) : ad -> BDDvar -> Prop :=
    | BDDbounded_0 : forall n : BDDvar, BDDbounded bs BDDzero n
    | BDDbounded_1 : forall n : BDDvar, BDDbounded bs BDDone n
    | BDDbounded_2 :
        forall (node : ad) (n x : BDDvar) (l r : ad),
        MapGet _ bs node = Some (x, (l, r)) ->
        BDDcompare x n = Datatypes.Lt ->
        Neqb l r = false ->
        BDDbounded bs l x -> BDDbounded bs r x -> BDDbounded bs node n.

(* Specifications: *)
Lemma BDDbounded_lemma : forall (bs : BDDstate) (node : ad) (n : BDDvar), BDDbounded bs node n -> node = BDDzero \/ node = BDDone \/ (exists x : BDDvar, (exists l : BDDvar, (exists r : BDDvar, MapGet _ bs node = Some (x, (l, r)) /\ BDDcompare x n = Datatypes.Lt /\ Neqb l r = false /\ BDDbounded bs l x /\ BDDbounded bs r x))).
Lemma increase_bound : forall (bs : BDDstate) (n n' : BDDvar) (node : ad), BDDbounded bs node n -> BDDcompare n n' = Datatypes.Lt -> BDDbounded bs node n'.
Lemma boundedness_preservation : forall bs bs' : BDDstate, (forall (a l r : ad) (x : BDDvar), MapGet _ bs a = Some (x, (l, r)) -> MapGet _ bs' a = Some (x, (l, r))) -> forall (n : BDDvar) (node : ad), BDDbounded bs node n -> BDDbounded bs' node n.