(* These are maps from left-hand sides l to maps from right-hand sides r to maps from BDD variables x to the address of the unique node in the given BDDstate that contains (x, (l, r)). *)
Definition initBDDsharing_map := newMap (Map (Map ad)).
Definition BDDshare_lookup (share : BDDsharing_map)
(x : BDDvar) (l r : ad) : option ad :=
match MapGet _ share l with
| None => None
| Some m1 =>
match MapGet _ m1 r with
| None => None
| Some m2 =>
match MapGet _ m2 x with
| None => None
| Some y => Some y
end
end
end.
Definition BDDshare_put (share : BDDsharing_map)
(x : BDDvar) (l r counter : ad) : BDDsharing_map :=
let m1 :=
match MapGet _ share l with
| Some y => y
| None => newMap (Map ad)
end in
let m2 :=
match MapGet _ m1 r with
| Some y => y
| None => newMap ad
end in
let m2' := MapPut _ m2 x counter in
let m1' := MapPut _ m1 r m2' in MapPut _ share l m1'.

(* Specifications: *)
Lemma BDDshare_put_puts :
forall (share : BDDsharing_map) (x : BDDvar) (l r counter : ad),
BDDshare_lookup (BDDshare_put share x l r counter) x l r = Some counter.
Lemma BDDshare_put_no_new_node :
forall (share : BDDsharing_map) (x x' : BDDvar)
(l l' r r' counter counter' : ad),
BDDshare_lookup (BDDshare_put share x l r counter) x' l' r' =
Some counter' ->
BDDshare_lookup share x' l' r' = Some counter' \/
(x, (l, r)) = (x', (l', r')).
Lemma BDDshare_put_preserves_nodes :
forall (share : BDDsharing_map) (x x' : BDDvar)
(l l' r r' counter counter' : ad),
BDDshare_lookup share x' l' r' = Some counter' ->
(x, (l, r)) <> (x', (l', r')) ->
BDDshare_lookup (BDDshare_put share x l r counter) x' l' r' =
Some counter'.