(* Copyright 2012-2015 by Adam Petcher.				* * Use of this source code is governed by the license described	* * in the LICENSE file at the root of the source tree.		*)
Set Implicit Arguments.
Local Open Scope nat_scope.
Class function_cost_model(cost: FunctionCostModel) :={
cost_ident :
forall (A : Type),
cost _ _ (fun (a : A) => a) 0;
cost_ext :
forall (A B : Type)(f1 f2 : A -> B) n,
(forall a, f1 a = f2 a) ->
cost _ _ f2 n ->
cost _ _ f1 n;
cost_const :
forall (A B : Type)(b : B),
cost _ _ (fun (_ : A) => b) 0;
cost_le :
forall A B (f : A -> B) c1 c2,
cost _ _ f c1 ->
c1 <= c2  ->
cost _ _ f c2;
cost_compose :
forall (A B C : Type)
(f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
cost _ _ f1 c1 ->
cost _ _ f2 c2 ->
(forall a, cost _ _ (f2 a) c3) ->
cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);
cost_uncurry_1 :
forall (A B C : Type)(f : A -> B -> C) n,
cost _ _ (fun a => f (fst a) (snd a)) n ->
cost _ _ f n;
cost_uncurry_2 :
forall (A B C : Type)(f : A -> B -> C) n,
cost _ _ (fun a => f (fst a) (snd a)) n ->
forall a, cost _ _ (f a) n;
cost_curry :
forall (A B C : Type)(f : A -> B -> C) c1 c2,
cost _ _ f c1 ->
(forall a, cost _ _ (f a) c2) ->
cost _ _ (fun p => f (fst p) (snd p)) (c1 + c2);
cost_fst :
forall (A B : Type),
cost _ _ (@fst A B) 0;
cost_snd :
forall (A B : Type),
cost _ _ (@snd A B) 0;
cost_BVxor :
forall n,
cost _ _ (fun p => @BVxor n (fst p) (snd p)) n;
cost_vec_head :
forall (A : Type) n,
cost _ _ (@Vector.hd A n) 0;
cost_eqb_bool :
cost _ _ (fun (p : bool * bool) => eqb (fst p) (snd p)) 1;
cost_if_bool :
forall (A B : Type) (f : A -> bool) (f_so f_not : A -> B) c1 c2 c3,
cost _ _ f c1 ->
cost _ _ f_so c2 ->
cost _ _ f_not c3 ->
cost _ _ (fun p => if (f p) then (f_so p) else (f_not p)) (c1 + c2 + c3);
cost_Ret :
forall (A : Set)(eqd : eq_dec A),
cost _ _ (Ret eqd) 0;
cost_OC_Ret :
forall (A B C: Set),
cost _ _ (@OC_Ret A B C) 0;
cost_OC_Bind :
forall (A B C C' : Set),
cost _ _ (fun p => (@OC_Bind A B C C' (fst p) (snd p))) 0;
cost_OC_Query :
forall (A B : Set),
cost _ _ (@OC_Query A B) 0;
cost_OC_Run_1 :
forall (A B C A' B' S : Set)(eqds : EqDec S)(eqda : EqDec A)(eqdb : EqDec B),
cost _ _
(@OC_Run A B C A' B' S eqds eqdb eqda)
0;
cost_OC_Run_2 :
forall (A B C A' B' S : Set)(eqds : EqDec S)(eqda : EqDec A)(eqdb : EqDec B) c,
cost _ _
(@OC_Run A B C A' B' S eqds eqdb eqda c)
0;
cost_OC_Run_3 :
forall (A B C A' B' S : Set)(eqds : EqDec S)(eqda : EqDec A)(eqdb : EqDec B) c o,
cost _ _
(@OC_Run A B C A' B' S eqds eqdb eqda c o)
0
}.
Inductive comp_cost(fm : FunctionCostModel) : CompCostModel :=
| comp_cost_Ret :
forall (A : Set)(eqd : eq_dec A)(a : A),
comp_cost fm (Ret eqd a) 0
| comp_cost_Bind :
forall (A B : Set)(c : Comp A)(f : A -> Comp B) x1 x2 x3,
comp_cost fm c x1 ->
fm _ _ f x2 ->
(forall a, comp_cost fm (f a) x3) ->
comp_cost fm (Bind c f) (x1 + x2 + x3)
| comp_cost_Rnd :
forall n,
comp_cost fm (Rnd n) n.
Inductive oc_cost(fm : FunctionCostModel)(cm : CompCostModel) : OC_CostModel :=
| oc_cost_Query :
forall (A B : Set)(a : A),
oc_cost fm cm (OC_Query B a) (fun n => n)
| oc_cost_Run :
forall (A B C : Set)(c : OracleComp A B C) f1,
oc_cost fm cm c f1 ->
forall (A' B' S : Set)(eqds : EqDec S)(eqdb : EqDec B)(eqda : EqDec A)
(o : S -> A -> OracleComp A' B' (B * S)) x1 x2 f2,
fm _ _ o x1 ->
(forall x, fm _ _ (o x) x2) ->
(forall x y, oc_cost fm cm (o x y) f2) ->
forall s,
oc_cost fm cm (OC_Run _ _ _ c o s) (fun n => f1 (x1 + x2 + (f2 n)))
| oc_cost_Ret :
forall (A B C : Set)(c : Comp C) n,
cm _ c n ->
oc_cost fm cm (OC_Ret A B c) (fun _ => n)
| oc_cost_Bind :
forall (A B C C' : Set)(c : OracleComp A B C)(f : C -> OracleComp A B C') f1 x f2,
oc_cost fm cm c f1 ->
fm _ _ f x->
(forall y, oc_cost fm cm (f y) f2) ->
oc_cost fm cm (OC_Bind c f) (fun n => (f1 n) + x + (f2 n))
| oc_cost_le :
forall (A B C : Set)(c : OracleComp A B C) f1 f2,
oc_cost fm cm c f1 ->
(forall x, f1 x <= f2 x) ->
oc_cost fm cm c f2.
Section CostTheory.
Context `{function_cost_model}.

(* Specifications: *)
Theorem cost_compose_unary :
forall (A B C: Type)
(f1 : A -> B)(f2 : B ->C) c1 c2,
cost f1 c1 ->
cost f2 c2 ->
cost (fun a => f2 (f1 a)) (c1 + c2).