Definition BDDsharing_map := Map (Map (Map ad)).(* 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'.