Definition map_empty_def {A} (m1: PMap.t (Z -> option A)):=
m1.1 = fun _ => None.
Definition fun_leq' {A B} (f1: Z -> option A) (f2: Z -> option B): Prop :=
forall p, f1 p -> f2 p.
Definition fun_leq {A B} (o1: option (Z -> option A)) (o2: option (Z -> option B)): Prop :=
match o1, o2 with
| Some f1, Some f2 => fun_leq' f1 f2
| None, None => True
| _, _ => False
end.
Definition option_eq {A B} (a:option A) (b: option B): Prop :=
match a, b with
| Some _ , Some _ => True
| None, None => True
| _, _ => False
end.
Definition bounded_nat_func_aux {A} (f: nat -> option A) hi: Prop :=
(forall p, (p >= hi )%nat -> f p = None).
Definition bounded_nat_func' {A} (f: nat -> option A) hi: Prop :=
(forall p, (p > hi )%nat -> f p = None).
Definition bounded_func' {A} (f: Z -> option A) hi lo: Prop :=
(forall p, (p > hi )%Z -> f p = None) /\
(forall p, (p < lo)%Z -> f p = None).
Definition bounded_func_op {A} (f: option (Z -> option A)) hi lo: Prop :=
match f with
| Some f' => bounded_func' f' hi lo
| None => True
end.
Definition bounded_func {A} (f: Z -> option A): Prop :=
exists hi lo,
bounded_func' f hi lo.
Definition bounded_map {A} (m: PTree.t (Z -> option A)):=
forall p f, m ! p = Some f -> bounded_func f.
Fixpoint strong_tree_leq {A B}
(t1: PTree.t A) (t2: PTree.t B)
(leq: option A -> option B -> Prop):=
match t1, t2 with
| PTree.Leaf, PTree.Leaf => True
| PTree.Node l1 o1 r1, PTree.Node l2 o2 r2 =>
leq o1 o2 /\
strong_tree_leq l1 l2 leq /\
strong_tree_leq r1 r2 leq
| _, _ => False
end.
Definition same_shape {A B} (m1: PTree.t (Z -> option A))(m2: PTree.t (Z -> option B)):=
strong_tree_leq m1 m2 option_eq.
Definition sub_map' {A B} (m1: PTree.t (Z -> option A))(m2: PTree.t (Z -> option B)):=
forall p f1, m1 ! p = Some f1 ->
exists f2, m2 ! p = Some f2 /\ fun_leq' f1 f2.
Definition sub_map {A B} (m1: PTree.t (Z -> option A))(m2: PTree.t (Z -> option B)):=
strong_tree_leq m1 m2 fun_leq.

(* Specifications: *)
Lemma sub_map_and_shape:
forall { A B} m1 m2,
@same_shape A B m1 m2 ->
sub_map' m1 m2 ->
sub_map m1 m2.
Lemma sub_map_and_shape:
forall { A B} m1 m2,
@same_shape A B m1 m2 ->
sub_map' m1 m2 ->
sub_map m1 m2.