Section expected_poly_time_theory.
Context `{ept : expected_poly_time_predicate}.
intuition.
eapply (@expected_poly_time_compose _ _ _ _ _ _ (fun n a b => (f2 n b))); eauto.
eapply expected_poly_time_const; eauto.
Qed.
intuition.
eapply (@expected_poly_time_compose _ _ _ _ _ _ (fun n a b => f3 n (f1 n a) b)); eauto.
eapply (@expected_poly_time_compose _ _ _ _ _ _ (fun n a b => f3 n b)); eauto.
eapply expected_poly_time_const.
eauto.
Qed.
intuition.
eapply (@expected_poly_time_compose_binary _ _ _ _ _ _ (fun n b c => pair b c)); eauto.
eapply expected_poly_time_pair.
Qed.
intuition.
eapply (@expected_poly_time_compose_binary _ _ _ _ _ _ BVxor); eauto.
eapply expected_poly_time_bvxor.
Qed.
intuition.
eapply (@expected_poly_time_compose_binary _ _ _ _ _ _ (fun n a b => eqb a b)); eauto.
eapply expected_poly_time_eqb_bool.
Qed.
intuition.
eapply (@expected_poly_time_compose_simp _ _ _ _ (fun n a => fst a)); eauto.
eapply expected_poly_time_fst.
Qed.
intuition.
eapply (@expected_poly_time_compose_simp _ _ _ _ (fun n a => snd a)); eauto.
eapply expected_poly_time_snd.
Qed.
intuition.
eapply (@expected_poly_time_compose_0 _ _ _ _ _ (fun n b => f3 n (f1 n) b)); eauto.
eapply (@expected_poly_time_compose_0 _ _ _ _ _ (fun n b => f3 n b)); eauto.
Qed.
intuition.
eapply (@expected_poly_time_compose_0_binary _ _ _ a b (fun n a b => Bind a b)); eauto.
eapply expected_poly_time_bind.
Qed.
intuition.
eapply (@expected_poly_time_compose_binary _ _ _ _ b c (fun n a b => Bind a b)); eauto.
eapply expected_poly_time_bind.
Qed.
intuition.
eapply (@expected_poly_time_compose_simp _ _ _ _ (fun n b => Ret (eqd n) b)); eauto.
eapply expected_poly_time_ret.
Qed.
eapply expected_poly_time_rnd.
exists 1%nat.
exists 1%nat.
exists 0%nat.
intuition.
simpl.
omega.
Qed.
eapply expected_poly_time_bind_0_f.
eapply expected_poly_time_rnd.
exists 0%nat.
exists 1%nat.
exists 0%nat.
intuition.
eapply expected_poly_time_ret_f.
eapply expected_poly_time_vec_hd.
Qed.
intuition.
eapply (@expected_poly_time_compose _ _ _ _ _ _ (fun n a (b : bool) => if b then (f_so n a) else (f_not n a))); eauto.
eapply expected_poly_time_pair_arg.
eapply (@expected_poly_time_compose _ _ _ _ _ _ (fun n (a : A n * bool) b => if (snd a) then b else (f_not n (fst a)))); eauto.
apply (@expected_poly_time_compose_simp _ _ _ _ f_so); eauto.
eapply expected_poly_time_fst.
eapply expected_poly_time_pair_arg.
eapply (@expected_poly_time_compose _ _ _ _ _ _ (fun n (a : A n * bool * B n) b => if (snd (fst a)) then (snd a) else b)); eauto.
apply (@expected_poly_time_compose_simp _ _ _ _ f_not); eauto.
apply (@expected_poly_time_compose_simp _ _ _ _ (fun n a => fst a)); eauto.
eapply expected_poly_time_fst.
eapply expected_poly_time_fst.
eapply expected_poly_time_unpair_arg.
eapply expected_poly_time_unpair_arg.
simpl.
eapply expected_poly_time_const.
eapply expected_poly_time_if.
Qed.

Theorem expected_poly_time_cons_f :
forall A B (f1 : forall n, A n -> B n) (f2 : forall n, A n -> list (B n)),
efficient _ f1 ->
efficient _ f2 ->
efficient _ (fun n (a : A n) => (cons (f1 n a) (f2 n a))).