(* We have to do this by induction on the computation, since it may make an arbitary number of calls to the oracle. *)
induction c; intuition; simpl in *.
eapply (@comp_spec_consequence _ _ (@pair_EqDec B S1 eqdb eqds1) _ (@pair_EqDec B S2 eqdb eqds2)).
eapply H0; intuition.
intuition.
(* OC_Run case *)
assert (EqDec C).
eapply EqDec_pair_l;
eauto.
eapply (@comp_spec_seq _ _ (fun a b => fst a = fst b /\ fst (snd a) = fst (snd b) /\ P (snd (snd a)) (snd (snd b)) ))
; eauto.
intuition.
eapply oc_base_exists; eauto; intuition.
assert (B * S).
eapply oc_base_exists.
eauto.
intuition.
assert (B' * S1).
eapply comp_base_exists.
eauto.
intuition.
intuition.
intuition.
eapply oc_base_exists; eauto; intuition.
assert (B * S).
eapply oc_base_exists.
eauto.
intuition.
assert (B' * S1).
eapply comp_base_exists.
eauto.
intuition.
intuition.
eapply comp_spec_consequence.
eapply (IHc _ _ _ _ _ _ _ _ _ _ (fun p1 p2 => fst p1 = fst p2 /\ P (snd p1) (snd p2))).
simpl; intuition.
intuition.
simpl in *.
subst.
eapply comp_spec_seq.
intuition.
assert (B * S).
eapply oc_base_exists.
eauto.
intuition.
assert (B' * S1).
eapply comp_base_exists.
eapply o1; intuition.
intuition.
intuition.
intuition.
assert (B * S).
eapply oc_base_exists.
eauto.
intuition.
assert (B' * S1).
eapply comp_base_exists.
eapply o1; intuition.
intuition.
intuition.
eapply H.
eauto.
intuition.
intuition.
eapply comp_spec_ret.
simpl in *; intuition.
destruct b2; simpl in *.
destruct p; simpl in *; intuition.
inversion H7; clear H7; subst.
intuition.
destruct b2; simpl in *.
subst.
simpl.
intuition.
intuition.
intuition.
simpl in *.
subst.
eapply comp_spec_ret.
simpl in *.
destruct b; simpl in *.
intuition.
eapply comp_spec_seq_eq; intuition.
eapply comp_base_exists; intuition.
eapply comp_base_exists; intuition.
eapply comp_spec_eq_refl.
eapply comp_spec_ret; simpl; intuition.
assert (EqDec C).
eapply oc_EqDec.
eapply c.
intuition.
intuition.
assert (B * S1).
eapply comp_base_exists.
eauto.
intuition.
intuition.
eapply comp_spec_seq.
intuition.
eapply oc_base_exists.
eapply o.
eapply oc_base_exists.
eauto.
intuition.
assert (B * S1).
eapply comp_base_exists.
eapply o1.
intuition.
trivial.
intuition.
intuition.
assert (B * S1).
eapply comp_base_exists.
eapply o1; intuition.
intuition.
intuition.
eapply oc_base_exists.
eapply o.
eapply oc_base_exists.
eauto.
intuition.
assert (B * S1).
eapply comp_base_exists.
eapply o1.
intuition.
trivial.
intuition.
intuition.
assert (B * S1).
eapply comp_base_exists.
eapply o1; intuition.
intuition.
eapply IHc.
eauto.
intuition.
intuition.
simpl in *.
subst.
destruct b0.
simpl.
eapply H; intuition.
Qed.
Opaque evalDist.

(* Specifications: *)
Theorem oc_comp_wf_inv
: forall (A B C : Set) (c : OracleComp A B C),
well_formed_oc c ->
forall (S : Set) (P : S -> Prop)(eqds : EqDec S) (o : S -> A -> Comp (B * S)) (s : S),
(forall (a : S) (b : A), P a -> well_formed_comp (o a b)) ->
(forall a b s s', P s -> In (b, s') (getSupport (o s a)) -> P s') ->
P s ->
well_formed_comp (c S eqds o s).