Commit 18afcd02 authored by Benoît Barbot's avatar Benoît Barbot
Browse files

bug on exact evaluation with smp

parent 467b72e9
type output_style = Void | Timestamp | Timeword |TimewordState | StateList | StateListFull| Debug
type output_style = Void | Word| Timestamp | Timeword |TimewordState | StateList | StateListFull| Debug
let style_list = ["timestamp"; "timeword";"timeword_state"; "state_list"; "state_list_full"; "debug";"void"]
let style_list = ["timestamp"; "timeword";"word";"timeword_state"; "state_list"; "state_list_full"; "debug";"void"]
let style_of_string = function
| "void" -> Void
| "timestamp" -> Timestamp
| "timeword" -> Timeword
| "word" -> Word
| "timeword_state" -> TimewordState
| "state_list" -> StateList
| "state_list_full" -> StateListFull
......@@ -39,7 +40,7 @@ module Make(Sem:Semantic.S) = struct
else
fprintf f " [%c]-[%g;%g] " tr.ZoneGraph.action low up;
) l) rgpoly.ZoneGraph.statelist.(get_loc st).ZoneGraph.transition
| Void | Timestamp | Timeword -> () in
| Void | Word | Timestamp | Timeword -> () in
let up_state_elapsed st i = match ost with
StateListFull -> fprintf outfile "%a" print_state st
| _ -> () in
......@@ -52,6 +53,7 @@ module Make(Sem:Semantic.S) = struct
fprintf outfile "((%a)/(%a))->%f[%c]\n" P.print cdf P.print weight time tr.ZoneGraph.action
| Debug -> fprintf outfile "->%f[%c]\n" time tr.ZoneGraph.action
| Timestamp -> fprintf outfile "%f\t" time
| Word -> fprintf outfile "%c" tr.ZoneGraph.action
| Timeword | TimewordState -> fprintf outfile "%f[%c] " time tr.ZoneGraph.action
| StateListFull -> fprintf outfile "\t%i@." (int_of_char tr.ZoneGraph.action)
| StateList | Void-> () in
......
......@@ -43,11 +43,11 @@ module type WeightStructure = sig
val diff: t-> var -> t
val map_var : t -> (var -> var) -> t
val elapse_time : t -> var -> t
val apply_const : t -> var -> fl -> t
val apply_const : ?smp:float -> t -> var -> fl -> t
val to_float : ?smp:float -> t -> float option
val apply_all : ?smp:float -> t -> float array -> float
val fully_apply : ?smp:float -> t -> var -> fl -> fl
val fully_apply_float : t -> var -> float -> float
val fully_apply_float : ?smp:float -> t -> var -> float -> float
end
type 'a transChoice = Label of 'a | Rand of float | Fixed
......@@ -63,9 +63,10 @@ sig
?update:(unit -> unit) ->
('a,Bt.t) ZoneGraph.t -> int -> P.t array * (P.t,Bt.t) ZoneGraph.t
val find_root :
?factor:float ->
?max_iter:int ->
?bound:float * float -> P.t -> ?diffp:P.t -> P.var -> float -> float
?smp:float ->
?factor:float ->
?max_iter:int ->
?bound:float * float -> P.t -> ?diffp:P.t -> P.var -> float -> float
type state = Bt.state (*= int * float array*)
......@@ -74,7 +75,7 @@ sig
val state_of_float : state -> int * P.F.t array
val init : (int,Bt.t) ZoneGraph.t -> state
val print_state : Format.formatter -> state -> unit
val eval_poly_state : state -> P.t -> P.t
val eval_poly_state : ?smp:float -> state -> P.t -> P.t
val eval_poly_state_full : ?smp:float -> state -> P.t -> float
val elapse_time : state -> float -> state
val fire : state -> ('b,Bt.t) ZoneGraph.transition -> state
......@@ -104,7 +105,6 @@ sig
samplers:(int -> float) * (int -> float) -> unit
end
exception Zero_derivative
module Make (Bt: ZoneGraphInput.BoundType) (P: WeightStructure) = struct
module P=P
module Bt=Bt
......@@ -157,81 +157,14 @@ module Make (Bt: ZoneGraphInput.BoundType) (P: WeightStructure) = struct
done;
!stateweight,rgp
(* Copy from Boost/math/tools/roots.hpp *)
let newton_raphson_iterate ?factor:(factor= 1e-10) ?max_iter:(max_iter=20) ?bound p ?diffp x guess_p =
let find_root ?smp ?factor ?max_iter ?bound p ?diffp x guess_p =
let pp = match diffp with
None -> diff p x
| Some pp -> pp in
let (min,max) = match bound with
None -> ref min_float, ref max_float
| Some (x,y) -> ref x, ref y in
let guess = ref guess_p in
let result = ref (if guess_p= infinity then 1.0 else guess_p) in
let delta = ref max_float
and delta1 = ref max_float
and delta2 = ref max_float in
try for i =0 to max_iter do
delta2 := !delta1;
delta1 := !delta;
let f0 = fully_apply_float p x !result
and f1 = fully_apply_float pp x !result in
if f0 = 0.0 then raise Exit;
if f1 = 0.0 then raise Zero_derivative;
delta := f0 /. f1;
if abs_float (!delta*.2.0) > abs_float !delta2 then (
let shift = if !delta>0.0 then (!result -. !min)/. 2.0 else (!result -. !max)/. 2.0 in
if !result <>0.0 && (abs_float shift > abs_float !result) then
delta := copysign (0.9*.(abs_float !result)) !delta
else delta := shift;
delta1:= 3.0*. !delta;
delta2 := 3.0 *. !delta
);
guess := !result;
result := !result -. !delta;
if !result <= !min then (
delta := 0.5 *. (!guess -. !min);
result := !guess -. !delta;
if !result = !min || !result = !max then raise Exit
) else if !result >= !max then (
delta := 0.5 *. (!guess -. !max);
result := !guess -. !delta;
if !result = !min || !result = !max then raise Exit
);
if !delta >0.0 then max := !guess
else min := !guess;
if abs_float (!result *. factor) >= abs_float !delta then raise Exit
done;
Format.eprintf "Alert Not converging %a --> %g@." P.print p !result;
!result
with
Exit -> !result
let rec find_root_old ?factor:(factor= 1e-10) ?max_iter:(max_iter=20) ?bound p ?diffp x guess =
let pp = match diffp with
None -> diff p x
| Some pp -> pp in
if max_iter =0 then (
Format.eprintf "Alert Not converging %a --> %g@." P.print p guess;
guess
) else
let pv = fully_apply_float p x guess
and ppv = fully_apply_float pp x guess in
if pv = 0.0 then guess
else if ppv = 0.0 then raise Zero_derivative
else let delta = pv /. ppv in
let r1 = guess -. delta in
let result = match bound with
None -> r1
| Some (low,up) -> min (max low r1) up in
if abs_float (result*.factor) < abs_float delta then
find_root_old ~factor ~max_iter:(max_iter -1) ?bound p ~diffp:pp x result
else result
let find_root = newton_raphson_iterate
let f v =
let f0 = fully_apply_float ?smp p x v
and f1 = fully_apply_float ?smp pp x v in (f0,f1) in
newton_raphson_iterate ?factor ?max_iter ?bound f guess_p
(* State instantiation for simulation
......@@ -246,10 +179,10 @@ module Make (Bt: ZoneGraphInput.BoundType) (P: WeightStructure) = struct
Format.fprintf f "@[%i @ @[%a@]@]" id
(fun _ -> Array.iter (fun x -> Format.fprintf f "%f @ " x)) tab
let eval_poly_state (id,tab) p=
let eval_poly_state ?smp (id,tab) p=
let j,p = Array.fold_left
(fun (i,pit) v ->
i+1,apply_const pit (var_of_int i) (F.of_float v))
i+1,apply_const ?smp pit (var_of_int i) (F.of_float v))
(1, p) tab in
p(*apply_const p (var_of_int j) (1.0/.smp)*)
let eval_poly_state_full ?smp (_,tab) p=
......@@ -284,12 +217,12 @@ module Make (Bt: ZoneGraphInput.BoundType) (P: WeightStructure) = struct
else if u=1.0 then up
else
let _,cdf,pdf = trans.weight.(i) in
let cdfap = eval_poly_state state cdf
and pdfap = eval_poly_state state pdf in
let invweight = 1.0/. (P.fully_apply_float cdfap t up) in
let cdfap = eval_poly_state ?smp state cdf
and pdfap = eval_poly_state ?smp state pdf in
let invweight = 1.0/. (P.fully_apply_float ?smp cdfap t up) in
let pb = ((F.of_float invweight) **. cdfap) -.. (const @@ F.of_float u) in
let diffcdf = (F.of_float invweight **. pdfap) in
let time = find_root ~max_iter pb ~diffp:diffcdf ~bound:(low,up) t (0.5 *.(low+.up)) in
let time = find_root ?smp ~max_iter pb ~diffp:diffcdf ~bound:(low,up) t (0.5 *.(low+.up)) in
if (time < low || time > up) then (
Format.eprintf "Error: fail to compute time : (%i->[%c]) cdf:%a; diff:%a -> %g [%g,%g]@."
(fst state) trans.action P.print pb P.print diffcdf time low up;
......
......@@ -21,14 +21,13 @@ module type WeightStructure =
val diff : t -> var -> t
val map_var : t -> (var -> var) -> t
val elapse_time : t -> var -> t
val apply_const : t -> var -> fl -> t
val apply_const : ?smp:float -> t -> var -> fl -> t
val to_float : ?smp:float -> t -> float option
val apply_all : ?smp:float -> t -> float array -> float
val fully_apply : ?smp:float -> t -> var -> fl -> fl
val fully_apply_float : t -> var -> float -> float
val fully_apply_float : ?smp:float -> t -> var -> float -> float
end
type 'a transChoice = Label of 'a | Rand of float | Fixed
exception Zero_derivative
module type S =
sig
......@@ -40,9 +39,10 @@ sig
?update:(unit -> unit) ->
('a,Bt.t) ZoneGraph.t -> int -> P.t array * (P.t,Bt.t) ZoneGraph.t
val find_root :
?factor:float ->
?max_iter:int ->
?bound:float * float -> P.t -> ?diffp:P.t -> P.var -> float -> float
?smp:float ->
?factor:float ->
?max_iter:int ->
?bound:float * float -> P.t -> ?diffp:P.t -> P.var -> float -> float
type state = int * float array
......@@ -51,7 +51,7 @@ sig
val state_of_float : state -> int * P.F.t array
val init : (int,Bt.t) ZoneGraph.t -> state
val print_state : Format.formatter -> state -> unit
val eval_poly_state : state -> P.t -> P.t
val eval_poly_state : ?smp:float -> state -> P.t -> P.t
val eval_poly_state_full : ?smp:float -> state -> P.t -> float
val elapse_time : state -> float -> state
val fire : state -> ('b,Bt.t) ZoneGraph.transition -> state
......
......@@ -60,10 +60,10 @@ let precomputation_exists ?debug filename frequency npoly exact_rational =
let save_precomputation file rg frequency npoly exact_rational =
let fd = open_out ((Filename.remove_extension file)^".pcmp") in
let hashmod = Digest.file file in
output_value fd hashmod;
output_value fd frequency;
output_value fd npoly;
output_value fd exact_rational;
output_value fd (hashmod: Digest.t);
output_value fd (frequency: float option);
output_value fd (npoly: int);
output_value fd (exact_rational:bool);
Marshal.to_channel fd rg [Marshal.Closures];
close_out fd
......
......@@ -87,3 +87,51 @@ let eval (_,clocks) = function
| Finite (a,b) -> (float a) -. clocks.(VarSet.int_of_var b-1)
end
(* Copy from Boost/math/tools/roots.hpp *)
exception Zero_derivative
let newton_raphson_iterate ?factor:(factor= 1e-10) ?max_iter:(max_iter=20) ?bound f guess_p =
let (min,max) = match bound with
None -> ref min_float, ref max_float
| Some (x,y) -> ref x, ref y in
let guess = ref guess_p in
let result = ref (if guess_p= infinity then 1.0 else guess_p) in
let delta = ref max_float
and delta1 = ref max_float
and delta2 = ref max_float in
try for i =0 to max_iter do
delta2 := !delta1;
delta1 := !delta;
let f0,f1 = f !result in
if f0 = 0.0 then raise Exit;
if f1 = 0.0 then raise Zero_derivative;
delta := f0 /. f1;
if abs_float (!delta*.2.0) > abs_float !delta2 then (
let shift = if !delta>0.0 then (!result -. !min)/. 2.0 else (!result -. !max)/. 2.0 in
if !result <>0.0 && (abs_float shift > abs_float !result) then
delta := copysign (0.9*.(abs_float !result)) !delta
else delta := shift;
delta1:= 3.0*. !delta;
delta2 := 3.0 *. !delta
);
guess := !result;
result := !result -. !delta;
if !result <= !min then (
delta := 0.5 *. (!guess -. !min);
result := !guess -. !delta;
if !result = !min || !result = !max then raise Exit
) else if !result >= !max then (
delta := 0.5 *. (!guess -. !max);
result := !guess -. !delta;
if !result = !min || !result = !max then raise Exit
);
if !delta >0.0 then max := !guess
else min := !guess;
if abs_float (!result *. factor) >= abs_float !delta then raise Exit
done;
Format.eprintf "Alert Not converging --> %g@." !result;
!result
with
Exit -> !result
......@@ -43,4 +43,8 @@ module SBound : sig
val print : VarSet.varset -> Format.formatter -> bound -> unit
val eval: 'a * float array -> bound -> float
end
val newton_raphson_iterate:
?factor:float ->
?max_iter:int ->
?bound:float * float ->
(float -> float * float) -> float -> float
......@@ -46,7 +46,7 @@ module type S = sig
val elapse_time : t -> var -> t
val fully_apply : ?smp:float -> t -> var -> fl -> fl
val fully_apply_float : t -> var -> float -> float
val apply_const : t -> var -> fl -> t
val apply_const : ?smp:float -> t -> var -> fl -> t
val apply_bound: t-> var -> bound -> t
val apply_all : ?smp:float -> t -> float array -> float
val primitive: t-> var -> t
......@@ -293,34 +293,35 @@ module Make (P:Polynome.S) (Param:sig val smp:float option val tvar:P.var val sv
)
ep Poly.empty
let apply_const ep var c =
let elapse_time ep t =
map (fun p -> P.elapse_time p t ) ep
let smpv ?smp () =
match smp,Param.smp with
None,Some x -> x
| Some x,None -> x
| Some a, Some b when a= b -> a
| Some _, Some _ -> failwith "Conflicting value for s parameter"
| None,None -> failwith "No value for s parameter"
let apply_const ?smp ep var c =
let s = match Param.smp,smp with
None,None -> raise Polynome.Not_fully_evaluated
| _,Some s -> s
| Some s,_ -> assert (not F.is_exact); s in
Poly.fold (fun k v acc ->
let v2 = P.apply v var (P.const c) in
let v2 = P.apply_const ?smp v var c in
match k with
Infinite -> assert false
| Const _ -> add_mon k v2 acc
| Finite (_,var2) when var2<> var -> add_mon k v2 acc
| Finite (a,_) ->
let isvart = if var = Param.tvar then -1.0 else 1.0 in
match Param.smp with
None -> raise Polynome.Not_fully_evaluated
| Some s ->
assert (not F.is_exact);
let v3 = P.( **.) (F.of_float @@ exp (s *. isvart *. (F.to_float c))) v2 in
add_mon (Const (0)) v3 acc
)
ep Poly.empty
let elapse_time ep t =
map (fun p -> P.elapse_time p t ) ep
let smpv ?smp () =
match smp,Param.smp with
None,Some x -> x
| Some x,None -> x
| Some a, Some b when a= b -> a
| Some _, Some _ -> failwith "Conflicting value for s parameter"
| None,None -> failwith "No value for s parameter"
let to_float ?smp p =
let open ZoneGraph in
......@@ -340,7 +341,7 @@ module Make (P:Polynome.S) (Param:sig val smp:float option val tvar:P.var val sv
let apply_all ?smp p tab =
let _,p = Array.fold_left
(fun (i,pit) v ->
i+1,apply_const pit (var_of_int i) (F.of_float v))
i+1,apply_const ?smp pit (var_of_int i) (F.of_float v))
(1, p) tab in
match to_float ?smp p with
Some x -> x
......@@ -348,14 +349,14 @@ module Make (P:Polynome.S) (Param:sig val smp:float option val tvar:P.var val sv
let fully_apply ?smp p x f =
assert (not F.is_exact);
let p2 = apply_const p x f in
(*assert (not F.is_exact);*)
let p2 = apply_const ?smp p x f in
match to_float ?smp p2 with
Some x -> F.of_float x
| None -> raise Polynome.Not_fully_evaluated
let fully_apply_float p x f =
F.to_float (fully_apply p x (F.of_float f))
let fully_apply_float ?smp p x f =
F.to_float (fully_apply ?smp p x (F.of_float f))
end
......
......@@ -38,16 +38,12 @@ let halton base index =
done;
!r
module PX = Polynome.Make (Fl.Float) (struct let var_string=[|"x",false|] end)
module SX = Semantic.Make (ZoneGraphInput.LinearBound) (PX)
let phi =1.61803398874989484820458683436563
let phi2=1.32471795724474602596090885447809
let phin n =
let n2 = max 2 n in
let open PX in
let x = var @@ var_of_int 0 in
SX.find_root ~factor:1e-15 ~max_iter:1000 ((pow x n2) -.. x -.. const PX.F.one) (var_of_int 0) 1.0
Common.newton_raphson_iterate ~factor:1e-15 ~max_iter:1000 (fun v -> let nm = float (n2-1) in
(v ** (float n2) -. v -.1.0), nm*.(v** nm)-.1.0) 1.0
let kronecker_state = ref phi
......
......@@ -49,7 +49,7 @@ module type S = sig
val vector_space : (t * (t -> t -> t) * (float -> t -> t))
val pow : t -> int -> t
val apply : t -> var -> t -> t
val apply_const : t -> var -> fl -> t
val apply_const : ?smp:float -> t -> var -> fl -> t
val to_float : ?smp:float -> t -> float option
val to_float_poly : t -> ftp
......@@ -60,7 +60,7 @@ module type S = sig
val integral : t -> var -> t -> t -> t
val iter_on_var : (var -> 'a -> 'a) -> 'a -> 'a
val fully_apply : ?smp:float -> t -> var -> fl -> fl
val fully_apply_float : t -> var -> float -> float
val fully_apply_float : ?smp:float -> t -> var -> float -> float
val apply_bound: t-> var -> bound -> t
val apply_all : ?smp:float -> t -> float array -> float
val laplace : t -> t -> var -> t
......@@ -219,7 +219,7 @@ module Make (F: Fl.FSIG)(K:sig val var_string:VarSet.varset end) = struct
add_mon k2 (F.mul v (F.powi f expo)) acc
else add_mon k v acc
let apply_const p x c =
let apply_const ?smp p x c =
Poly.fold (fun k v pacc ->
add_apply_monome_const k v x c pacc) p Poly.empty
......@@ -298,7 +298,7 @@ module Make (F: Fl.FSIG)(K:sig val var_string:VarSet.varset end) = struct
p
let fully_apply ?smp p x f =
match to_const @@ apply_const p x f with
match to_const @@ apply_const ?smp p x f with
Some x -> x
| None -> raise Not_fully_evaluated
......@@ -308,8 +308,8 @@ module Make (F: Fl.FSIG)(K:sig val var_string:VarSet.varset end) = struct
None -> raise Not_fully_evaluated
| Some x -> x*)
let fully_apply_float p x f =
F.to_float (fully_apply p x (F.of_float f))
let fully_apply_float ?smp p x f =
F.to_float (fully_apply ?smp p x (F.of_float f))
let eval_key tab key =
snd @@ Array.fold_left (fun (i,acc) tv ->
......
......@@ -46,7 +46,7 @@ module type S = sig
val vector_space : (t * (t -> t -> t) * (float -> t -> t))
val pow : t -> int -> t
val apply : t -> var -> t -> t
val apply_const : t -> var -> fl -> t
val apply_const : ?smp:float -> t -> var -> fl -> t
val to_float : ?smp:float -> t -> float option
val to_float_poly : t -> ftp
val of_float_poly : ftp -> t
......@@ -55,7 +55,7 @@ module type S = sig
val integral : t -> var -> t -> t -> t
val iter_on_var : (var -> 'a -> 'a) -> 'a -> 'a
val fully_apply : ?smp:float -> t -> var -> fl -> fl
val fully_apply_float : t -> var -> float -> float
val fully_apply_float : ?smp:float -> t -> var -> float -> float
val apply_bound: t-> var -> Common.bound -> t
val apply_all : ?smp:float -> t -> float array -> float
val laplace : t -> t -> var -> t
......
......@@ -43,6 +43,7 @@ let _ =
(* Main *)
let _ =
(* check if precomputation exists *)
let precomp_exists =
if !print_rg then None else ZoneGraphInput.precomputation_exists
~debug:(fun b -> if !verbose>0 then
......@@ -51,7 +52,7 @@ let _ =
else printf "Precomputation file found but file have change discard !@.")
!infile !frequency !npoly !rational_impl in
(* Use splitted or general bound general only for isotropic sampling *)
(* Use splitted or general bound, general only for isotropic sampling *)
let module Bound = (val if !npoly<0 then (module ZoneGraphInput.GeneralBound:ZoneGraphInput.BoundType )
else (module ZoneGraphInput.LinearBound )) in
let module ZGI = ZoneGraphInput.Make (Bound) in
......@@ -65,15 +66,19 @@ let _ =
else None in
(* Build the polynomial ring with exact or approximated rationnal and with or without Exppolynomials *)
(* Rationnal implementation either floating point or exact *)
let module R = (val if !rational_impl then (module Flq.Q :Fl.FSIG) else (module Fl.Float:Fl.FSIG)) in
(* Polynomials over the clocks*)
let module P = Polynome.Make (R) (struct let var_string= match rgopt,precomp_exists with
Some a,_ -> a.ZoneGraph.var_string
| _,Some b -> b.ZoneGraph.var_string
| None,None -> assert false end) in
(* either P or exp-polynomials *)
(* If exact computation or no s parameter given s is symbolic, otherwise it is inlined during computation *)
let module Weight = (val if !frequency = None && !expected_duration = None then (module P:Semantic.WeightStructure)
else (module ExpPoly.Make(P)(struct
let smp = if P.F.is_exact || !expected_duration <> None
then None else !frequency
let smp = if P.F.is_exact then None
else !frequency
let tvar = P.var_of_int 0
let svar= P.var_of_int (P.nb_var-1)
end))) in
......@@ -82,7 +87,7 @@ let _ =
let module FunIt = Semantic.Make (Bound) (Weight) in
(* Compute Weight and distribution as polynomials *)
let rgpoly =
let weights,rgpoly =
match precomp_exists, rgopt, !npoly>=0 with
| Some rg,_,_ -> rg
| _, Some rg, true ->
......@@ -90,14 +95,15 @@ let _ =
printf "Computing Distribution -> %i: [" !npoly; flush stdout;
print_flush ()
);
let _,rgp = FunIt.iterate_functionnal ~update:(fun () ->printf "|"; print_flush ())
let rgp = FunIt.iterate_functionnal ~update:(fun () ->printf "|"; print_flush ())
rg !npoly in
if !verbose>0 then printf "] [%.2fs]@." (check_time ());
rgp
| _, Some rg, false -> snd @@ FunIt.iterate_functionnal rg 0
| _, Some rg, false -> FunIt.iterate_functionnal rg 0
| None,None,_ -> assert false in
ZoneGraphInput.save_precomputation !infile rgpoly !frequency !npoly !rational_impl;
(*Save computation*)
(*ZoneGraphInput.save_precomputation !infile rgpoly !frequency !npoly !rational_impl;*)
if !print_rg then
begin
printf "%a@." (ZoneGraph.print Bound.print) rgpoly;
......@@ -106,7 +112,28 @@ let _ =
close_out fdot
end;
let module M = MainLoop.Make(FunIt) (struct let smp = Some 1.0 end) in
(* Compute s from expected_duration *)
let smp = match !expected_duration with
None -> !frequency
| Some target ->
if !verbose>0 then (
printf "Computing laplace parameters s : %g -> " target; flush stdout;
print_flush ();
);
let w = weights.(rgpoly.init) in
let svar = Weight.var_of_int (Weight.nb_var-1) in
let dw = Weight.diff w svar in
let ddw = Weight.diff dw svar in
let compv s =
match Weight.to_float ~smp:s w ,Weight.to_float ~smp:s dw, Weight.to_float ~smp:s ddw with
Some v,Some dv,Some ddv -> -. dv /. v -.target , -.ddv /. v +. dv*.dv /. (v*.v)
| _ -> failwith "fail to evaluate" in
let x = Common.newton_raphson_iterate compv 1.0 in
if !verbose>0 then printf "%g [%.2fs]@." x (check_time ());
Some x
in
let module M = MainLoop.Make(FunIt) (struct let smp = smp end) in
(* Sampling *)
(* Compute template if not provided *)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment