Skip to content
Snippets Groups Projects
demon.ml 3.02 KiB
Newer Older
(* Time-stamp: <modified the 13/03/2019 (at 17:44) by Erwan Jahier> *)
erwan's avatar
erwan committed

type t =
  | Synchronous (* select all actions *) 
  | Central (* select 1 action *)
  | LocallyCentral (* never activates two neighbors actions in the same step *)
  | Distributed (* select at least one action *)
  | Custom
erwan's avatar
erwan committed

let (random_list : 'a list -> 'a) = fun l ->
  assert (l <> []);
  List.nth l (Random.int (List.length l))

let (random1: 'a list list -> 'a list) =
  fun all -> 
   let al = List.map random_list all in
   let a = random_list al in
   [a]

let rec (random: 'a list list -> 'a list) =
  fun all ->
    assert (all <> []);
    let al = List.map random_list all in
    let al = List.filter (fun _ -> Random.bool ()) al in
    if al = [] then random all else al
   
let (synchrone: 'a list list -> 'a list) = fun all -> 
  let al = List.map random_list all in
  al


type pna = Process.t * Topology.neighbor list * Algo.action
(* From a list of enabled actions (pna) returns:
   - a string containing the values (in RIF) of activing_variables
   - the list of activated actions

As a side-effect, read on stdin which actions should be activated.

nb: it is possible that we read on stdin that an action should be
   activated even if it is not enabled (which would be a demon
   "error").  For the time being, we ignore the demon "error" and
   inhibit the activation.
*)
let rec map3 f l1 l2 l3 =
  match (l1, l2, l3) with
    ([], [], []) -> []
  | (a1::l1, a2::l2, a3::l3) -> let r = f a1 a2 a3 in r :: map3 f l1 l2 l3
  | ([], _, _) -> invalid_arg "map3 (1st arg too short)"
  | (_, [], _) -> invalid_arg "map3 (2nd arg too short)"
  | (_, _, []) -> invalid_arg "map3 (3rd arg too short)"

let (custom: bool -> pna list list -> Process.t list -> bool list list
     -> string * pna list) =
  fun verbose_mode pnall pl enab_ll -> 
    let f p pnal enab_l =
      let actions = p.Process.actions in
      let trigger_l = List.map (fun a -> RifRead.bool verbose_mode p a) actions in
      let acti_l_al =
        map3
          (fun trig enab a ->
             let acti = trig && enab in
             acti, if acti then
               let pna = List.find (fun (_,_,a') -> a=a') pnal in 
               [pna]
             else []
          ) trigger_l enab_l actions
      in
      acti_l_al
    in    
    let acti_l_all = map3 f pl pnall enab_ll in
    let acti_l_al = List.flatten acti_l_all in
    let acti_l,al = List.split acti_l_al in
    let acti = String.concat " " (List.map (fun b -> if b then "t" else "f") acti_l) in
    acti, List.flatten al

let (remove_empty_list: 'a list list -> 'a list list) =
  fun ll ->
    List.filter (fun l -> l<>[]) ll
erwan's avatar
erwan committed
      
let (f: bool -> t -> Process.t list -> pna list list -> bool list list ->
     string * pna list) =
  fun verbose_mode demon pl all enab ->
    | Synchronous  -> "", synchrone (remove_empty_list all)
    | Central -> "", random1 (remove_empty_list all)
    | LocallyCentral -> assert false
    | Distributed -> "", random (remove_empty_list all)
    | Custom -> custom verbose_mode all pl enab