open SimulTypes open SimulGraphes type trace_event = Peers of int | Days of int * int | Peer of int * float * string | Round of int | On of int | Off of int | Dead of int | End | Exponential let trace_output oc trace_event = output_string oc (match trace_event with Peers npeers -> Printf.sprintf "Peers %d\n" npeers | Days (ndays, day) -> Printf.sprintf "Days %d %d\n" ndays day | Peer (i,avail,s) -> Printf.sprintf "Peer %d %.3f %s\n" i avail s | Round round -> Printf.sprintf "Round %d\n" round | On i -> Printf.sprintf "On %d\n" i | Off i -> Printf.sprintf "Off %d\n" i | Dead i -> Printf.sprintf "Dead %d\n" i | End -> "End\n" | Exponential -> "Exponential\n" ) let trace_input ic = let line = input_line ic in match String2.split line ' ' with ["Peers"; npeers] -> Peers (int_of_string npeers) | ["Days"; ndays] -> Days (int_of_string ndays, 24 * 60) | ["Days"; ndays; day] -> Days (int_of_string ndays, int_of_string day) | "Peer" :: i :: avail :: tail -> Peer (int_of_string i, float_of_string avail, String2.unsplit tail ' ') | ["End"] -> End | ["Exponential"] -> Exponential | ["Round"; round] -> Round (int_of_string round) | ["On"; i] -> On (int_of_string i) | ["Dead"; i] -> Dead (int_of_string i) | ["Off"; i] -> Off (int_of_string i) | _ -> failwith (Printf.sprintf "Bad line [%s]" (String.escaped line)) let print_distribution = ref false (* gnuplot> plot exp(1-log(2+65*x)), 1.0/12 *) let exponential = ref false let distribution = ref [] let availability = ref [] let trace_read filename = let ic = open_in filename in let npeers = match trace_input ic with Peers npeers -> npeers | _ -> assert false in let (ndays, day) = match trace_input ic with Days (ndays, day) -> ndays, day | _ -> assert false in let rec read_peer ii = match trace_input ic with Exponential -> exponential := true; read_peer ii | Peer (i, avail, s) -> assert (i=ii); (* let x = float_of_int avail /. 900000. in let avail = (if !exponential then max 0.02 (min 1. (exp(1. -. log(2. +. 65. *. x)))) else 0.02 +. 0.98 *. x ) in if !print_distribution then begin distribution := x :: !distribution; availability := avail :: !availability; end; let lambda = float_of_int decs /. (60. *. 24.) in let mu = avail *. lambda /. (1. -. avail) in *) let p = { i = i; avail = avail; descr = s; session = 0; day = true; state = OFF; real_avail = 0; real_decs = 0; } in p | _ -> assert false in let peers = Array.init npeers read_peer in let event = ref None in let get_event () = let ev = trace_input ic in event := Some ev in let next_day = ref 0 in let begin_time = (Int64.of_float (Unix.gettimeofday ())) in let rec iter_round round = match !event with None -> next_event round | Some ev -> match ev with Round rr -> if rr = round then begin if !next_day = round then begin let time = Unix.gettimeofday () in let time = Int64.of_float time in Printf.printf "Day %d (%Ld)\n%!" (round / day) (Int64.sub time begin_time); next_day := !next_day + day end; next_event round end else assert (rr > round) | On i -> event := None; let p = peers.(i) in p.state <- ON; next_event round | Off i -> event := None; let p = peers.(i) in p.state <- OFF; p.real_decs <- p.real_decs + 1; next_event round | Dead i -> event := None; let p = peers.(i) in p.state <- DEAD; peers.(i) <- { p with state = OFF; }; next_event round | End -> () | _ -> assert false and next_event round = get_event (); iter_round round in if !print_distribution then begin cdf_of_list string_of_float "dist_random" !distribution "set yrange [0:1]" "CDF of peers" "Distribution" " title 'random'"; cdf_of_list string_of_float "dist_availability" !availability "set yrange [0:1]" "CDF of peers" "Distribution" " title 'avail'"; distribution := []; availability := []; end; peers, ndays * day, iter_round