diff --git a/.gitignore b/.gitignore
index a90f785ec69810fc99f57bf21c919787316c5c90..21848c58bb32dff0c4f0ec9d598af9a5a439feca 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,9 +17,14 @@ rdbg-session*.ml
 *.save
 *.lus
 *.lut
-*.ml
 flymd.html
 log
+*.sh
+test/**/*.ml
+results
+Makefile.local
+.ocamldebug
+lib/sasacore/sasaVersion.ml
 
 # Created by https://www.gitignore.io/api/vim,code,ocaml,emacs
 # Edit at https://www.gitignore.io/?templates=vim,code,ocaml,emacs
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1cd3fd40c88847eb62b03a8627f75d97af06e8b2..5eb7f3ad2c7bf7ddbbe3f93e6bdc2fe4440ea3e5 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -16,7 +16,7 @@ build:
     - make install
     - make test
 
-test_opam_test:
+simca:
   stage: release
   script:
     - opam repo add verimag-sync-repo "http://www-verimag.imag.fr/DIST-TOOLS/SYNCHRONE/test/opam-repository"
@@ -24,8 +24,24 @@ test_opam_test:
     - opam update -y
     - opam depext -y sasa 
     - opam install -y sasa
+    - cd tools/simca
+    - make
+    - make cmxs
+    - make log
+    - make pdf
   allow_failure: true
 
+  
+test_opam_test:
+  stage: release
+  script:
+    - opam repo add verimag-sync-repo "http://www-verimag.imag.fr/DIST-TOOLS/SYNCHRONE/test/opam-repository"
+    - eval `opam config env`
+    - opam depext -y sasa 
+    - opam install -y sasa
+  allow_failure: true
+
+
 
 # automating version numbering
 release:
diff --git a/test/alea-coloring-alt/Makefile b/test/alea-coloring-alt/Makefile
index f56815721356c84022581342e4d8a62975624f38..1620fe4b82397e2857d2a0dbc5b1a4aea16a6241 100644
--- a/test/alea-coloring-alt/Makefile
+++ b/test/alea-coloring-alt/Makefile
@@ -1,4 +1,4 @@
-# Time-stamp: <modified the 22/04/2020 (at 10:39) by Erwan Jahier>
+# Time-stamp: <modified the 27/04/2020 (at 14:43) by Erwan Jahier>
 
 
 test: ring.cmxs
@@ -22,17 +22,12 @@ grid44.dot:
 	gg grid -w 4 -he 4 -o grid44.dot
 
 
-clique10_%.dot:clique10.dot
-	gg-deco "0-:algo_$*.ml" $< -o  $@
 
 clique10.dot:
 	gg clique -n 10 -o $@
 
 
 # 
-grid44_%.dot: grid44.dot
-	gg-deco "0-:algo_$*.ml" $< -o  $@
-
 
 
 rdbg321: grid44_331.dot grid44_331.ml
diff --git a/tools/readme.org b/tools/readme.org
index 4ce40b460f08e39146f5b3067d9b32bf4297552d..94c86a80521d07d973baca6ccf769b9ec131ae69 100644
--- a/tools/readme.org
+++ b/tools/readme.org
@@ -2,6 +2,7 @@
 Various tools to use with =sasa=
 
 - =rdbgui= is a GUI dedicated to the use of =sasa= with =rdbg=
+- =simca= a set of scripts to perform SIMulation CAmpaigns with =sasa=
 - =gg= is a dot graph generator (*).
 - =gg-deco= decorates graphs generated by =gg= (*) 
 
diff --git a/tools/simca/Makefile b/tools/simca/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..2a2810310b6fcc99765899c4e8f89b9eaeec0d25
--- /dev/null
+++ b/tools/simca/Makefile
@@ -0,0 +1,21 @@
+CAMPAIGN=spanning_tree_campaign.ml
+CAMPAIGN=coloring_campaign.ml
+CAMPAIGN=nonreg_test_campaign.ml
+
+Makefile.expe-rules: $(CAMPAIGN)
+	echo "#use \"$(CAMPAIGN)\";;\n gen_make_rules ();;" | ocaml
+
+-include Makefile.expe-rulesexpe-rules
+# CMXS and LOG are defined in Makefile.expe-rules, which must have been generated!
+cmxs: $(CMXS)
+log: $(LOG)
+pdf:
+	echo "#use \"$(CAMPAIGN)\";;\n gen_pdf ();;" | ocaml
+
+
+-include Makefile.local
+
+clean:
+	rm -rf *.log *.data *.pdf Makefile.expe-rules *~ *.png cmxs_done
+
+
diff --git a/tools/simca/coloring_campaign.ml b/tools/simca/coloring_campaign.ml
new file mode 100644
index 0000000000000000000000000000000000000000..f475018495c06cf26ae6854b0c20517187496e46
--- /dev/null
+++ b/tools/simca/coloring_campaign.ml
@@ -0,0 +1,40 @@
+#use "genExpeMakefiles.ml";;
+precision := 0.01;;
+    (* 0.01 means that we simulate until  the Interval Confidence
+       size of  the 3 complexity  numbers under estimation  is smaller
+       than 1% of their current estimation.
+    *)
+let algos = ["../../test/alea-coloring-alt";
+             "../../test/alea-coloring-unif";
+             "../../test/alea-coloring"]
+let daemons = ["-sd";"-lcd";"-dd"]  
+let cliques = List.init 25 (fun n -> Clique (20*(n+1))) (* [20; 40; ...; 500] *)
+let rings = List.init 25 (fun n -> Ring (400*(n+1)))  (* [100; 500; ...; 10000] *)
+let er = List.init 25 (fun n -> ER (10*(n+1), 0.4)) (* [10; 20; ...; 2500] *)
+    
+let gen_make_rules () = 
+  let fn = "Makefile.expe-rules" in
+  let oc = open_out fn in
+  Printf.fprintf oc "# Generated by coloring_campaign.ml";
+  let compare_neg x y = compare y x in
+  let l = List.sort_uniq compare_neg (cliques @ rings @ er) in 
+  let targets,targets_cmxs = gen_makefile oc daemons algos l [] [] in
+  Printf.fprintf oc "\nCMXS=%s\n"  (String.concat " " targets_cmxs);
+  Printf.fprintf oc "\nLOG=%s\n%!" (String.concat " " targets);
+  Printf.printf "%s has been generated\n%!" fn;
+  close_out oc
+;;
+
+
+
+#use "parseLog.ml";;
+let gen_pdf () =
+  let gl = ["clique"; "ring"; "er"] in 
+  List.iter (fun n -> sh ("rm -f "^n^".data")) gl; 
+  parse_log ["Uniform When Triggered","alea-coloring-unif"] gl daemons;
+  parse_log ["Smallest When Triggered","alea-coloring"] gl daemons;
+  parse_log ["Always the Biggest","alea-coloring-alt"] gl daemons;    
+  List.iter (fun n -> sh ("./gen_pdf.r "^n^".data coloring")) gl;
+  ()
+;;
+
diff --git a/tools/simca/genExpeMakefiles.ml b/tools/simca/genExpeMakefiles.ml
new file mode 100644
index 0000000000000000000000000000000000000000..85efab52baa7c7c8caa67d6077dd9249f1a23f33
--- /dev/null
+++ b/tools/simca/genExpeMakefiles.ml
@@ -0,0 +1,71 @@
+(* [algo_to_deco dir] associates a directory names to 
+   - an argument to provide to gg-deco (to decorate gg generated graphs)
+   - a label that is used to create the dot file names 
+ *)
+let algo_to_deco dir =
+  match Filename.basename dir with
+  | "bfs-spanning-tree" 
+  | "dijkstra-ring"     
+  | "bfs-st-HC92"       
+  | "st-CYH91"          
+  | "st-KK06-algo1"     
+  | "st-KK06-algo2"     
+  | "dfs"               
+  | "dfs-list" -> "1-:p.ml 0:root.ml", "p_root"
+  | "async-unison" 
+  | "coloring"     
+  | "alea-coloring"
+  | "alea-coloring-unif" -> "0-:p.ml","p"
+  | "alea-coloring-alt"  -> "0-:algo_331.ml","algo_331"
+  | "unison"        -> "0-:unison.ml","unison"
+  | s  -> Printf.printf
+            "Error: %s is not handled by GenExpeMakefiles.algo_to_deco\n%!" s;
+    assert false
+
+type dir = string
+type daemon = string
+type graph =
+  | Udg of int  (* size of the graph *)
+  | Qudg of int (* size of the graph *)
+  | ER of int * float (* size of the graph, probability to add an edge *)
+  | Grid of int * int (* width and height of the grid *)
+  | Clique of int  (* size of the graph *)
+  | Ring of int    (* size of the graph *)
+;;
+
+(* The  4 following simulation  parameters are put into  references so
+   that  they can  be modified.   They  could have  been arguments  of
+   gen_makefile, but their values ought to be always the same (this is
+   arguable).  *)
+let precision = ref 0.01
+    (* 0.01 here  means that we simulate until  the Interval Confidence
+       size of  the 3 complexity  numbers under estimation  is smaller
+       than 1% of their current estimation.
+    *)
+let max_simu_nb = ref 10000 (* no more simulations are done once reached *)
+let timeout_in_sec = ref 10000 (* Ditto, once overtaken *)
+let regen_dot = ref true;; (* regenerate the graph before every simulation *)
+#use "genExpeMakefilesUtils.ml";;
+
+(* The Main function (or in other words, the entry point)
+
+   [gen_makefile oc p dl dirl  gl targets targets_cmxs] writes on [oc]
+   |dl| x |dirl| x |gl| Makefile  rules that build .log files. It also
+   generates the  dependencies to  execute those  log rules  (to build
+   .dot and .cmxs files).
+
+   It returns  the list of log  and cmxs targets that  were written on [oc]
+
+   More   precisely,  it   adds  to   the  input   list  [targets_log]
+   [targets_cmxs] the log and cmxs  targets that were written on [oc].
+   *)
+let (gen_makefile : out_channel -> daemon list -> dir list
+     -> graph list -> string list -> string list -> string list * string list) =
+  fun  oc dl dirl gl targets_log targets_cmxs ->
+  let targets_log, targets_cmxs  =
+    List.fold_left (gen_makefile0 oc dl dirl) (targets_log, targets_cmxs) gl
+  in
+  Printf.fprintf oc "\n# ZZZ do not do 'make -j 20 $(CMXS)'! (p.cmxs is regenerated
+# at each target, which causes failures)\n";
+  Printf.fprintf oc "\n# But 'make -j 20 $(LOG)' is fine!\n%!";
+  targets_log, targets_cmxs
diff --git a/tools/simca/genExpeMakefilesUtils.ml b/tools/simca/genExpeMakefilesUtils.ml
new file mode 100644
index 0000000000000000000000000000000000000000..1dccbbd95ca75940f54bcfede7bb2ab06bc2580f
--- /dev/null
+++ b/tools/simca/genExpeMakefilesUtils.ml
@@ -0,0 +1,110 @@
+#use "topfind";;
+#require "unix";;
+#require "str";;
+
+(** Generate a dot file with gg *)
+let gen_dot graph_kind dot dir =
+  let gg_cmd = Printf.sprintf "echo \"gg %s -o %s/%s.dot\" > %s/%s.dot.sh"
+      graph_kind dir dot dir dot in
+  gg_cmd
+
+(** Decorate gg generated  dot files with gg-deco *)
+let deco_dot dir dot =
+  let deco, _label = algo_to_deco dir in
+  let dot = dir^"/"^dot in
+  Printf.sprintf "echo \"gg-deco \\\"%s\\\" %s -o %s\" >> %s.sh " deco dot dot dot
+
+let grid w h label dir =
+  let name = Printf.sprintf "grid%dx%d_%s" w h label in 
+  name, gen_dot (Printf.sprintf "grid -w %d -he %d" w h) name dir
+
+let erdos_renyi n p label dir =
+  let name = Printf.sprintf "er%i_%s" n label in
+  (* The graph is a.c. connected if p> log(n)/n *) 
+  name, gen_dot (Printf.sprintf "ER -n %d -p %f" n p) name dir
+
+let clique n label dir =
+  let name = Printf.sprintf "clique%i_%s" n label in 
+  name, gen_dot (Printf.sprintf "clique -n %d" n) name dir
+
+let ring n label dir =
+  let name = Printf.sprintf "ring%i_%s" n label in 
+  name, gen_dot (Printf.sprintf "ring -n %d" n) name dir
+
+let udg n label dir =
+  let name = Printf.sprintf "udg%i_%s" n label in
+  name, gen_dot (Printf.sprintf "UDG -n %d" n) name dir
+
+let qudg n label dir =
+  let name = Printf.sprintf "qudg%i_%s" n label in 
+  name, gen_dot (Printf.sprintf "QUDG -n %d" n) name dir
+
+let gen_graph label dir = function
+  | Udg i  -> udg i label  dir
+  | Qudg i -> qudg i label  dir
+  | ER  (i,p)  -> erdos_renyi i p label dir
+  | Grid (i,j) -> grid i j label dir
+  | Clique i -> clique i  label dir
+  | Ring i -> ring i  label dir
+  
+let (gen_dot_rule : out_channel -> graph -> daemon list -> dir list ->
+     string list * string list) =
+  fun oc g dl dirl ->
+  List.iter (fun dir -> 
+      if not (Sys.file_exists dir) then failwith ("Error: "^dir^" does not exist\n");)
+    dirl;
+  let regen_dot = match g with
+    | Udg _ | Qudg _ | ER  _  -> !regen_dot
+    | Grid (_,_) | Clique _ | Ring _ -> false (* those are deterministic *)
+  in
+  let targets = 
+    (List.fold_left
+       (fun acc dir ->
+          let _, label = algo_to_deco dir in
+          let name, _ = gen_graph label dir g in
+          let dot = Printf.sprintf "%s.dot" name in
+          let bdir = Filename.basename dir in
+          let log = Printf.sprintf "%s%s-%s.log" name (List.hd dl) bdir in
+          let cwd = Sys.getcwd() in
+          Printf.fprintf oc "\n%s: \n\t[ -f %s/%s.cmxs ] || \\
+(echo \"\\n ===> do a 'make cmxs' before!\\n\\n\"; exit 1)\n\tcd %s \\\n" log dir name dir;
+          List.iter (fun d -> 
+              let log = Printf.sprintf "%s%s-%s.log" name d bdir in
+              Printf.fprintf oc
+                "\t && echo \"#use \\\"%s/runSimus.ml\\\";;\\n \\
+         run_simus %b %f %d %d.0 \\\"sasa -l 20000 %s %s -nd > /dev/null\\\";;\\n\" \\
+         | ocaml  > %s/%s \\
+"
+                cwd regen_dot !precision !max_simu_nb !timeout_in_sec dot d cwd log 
+            )
+          dl;
+          Printf.fprintf oc "\t && echo \"%s done\"\n\n" log; 
+          log::acc
+       )
+       [] dirl
+    )
+  in
+  let targets_cmxs : string list =
+    List.fold_left
+      (fun acc dir ->
+         let _deco, label = algo_to_deco dir in
+         let name, gg_cmd = gen_graph label dir g in
+         let dot = Printf.sprintf "%s.dot" name in
+         let cmxs = Printf.sprintf "%s.cmxs" name in
+         Printf.fprintf oc "%s/%s:\n	%s\n" dir dot gg_cmd;
+         Printf.fprintf oc "	%s\n" (deco_dot dir dot);
+         Printf.fprintf oc "	sh %s/%s.sh\n" dir dot;
+         Printf.fprintf oc "\n\n%s/%s: %s/%s\n" dir cmxs dir dot;
+         Printf.fprintf oc "	cd %s; make %s\n" dir cmxs;
+         (dir^"/"^cmxs)::acc
+      )
+      []
+      dirl
+  in
+  targets,targets_cmxs
+
+let (gen_makefile0 : out_channel -> daemon list -> dir list ->
+     string list * string list -> graph -> string list * string list) =
+  fun oc dl dirl (targets_acc, targets_cmxs_acc) g ->
+  let targets, targets_cmxs = gen_dot_rule oc g dl dirl in
+  targets @ targets_acc, targets_cmxs @ targets_cmxs_acc
diff --git a/tools/simca/gen_pdf.r b/tools/simca/gen_pdf.r
new file mode 100755
index 0000000000000000000000000000000000000000..5057de93dd0d58b855a3e8efd4f4ea76115dc261
--- /dev/null
+++ b/tools/simca/gen_pdf.r
@@ -0,0 +1,84 @@
+#! /usr/bin/env Rscript
+args <- commandArgs(TRUE)
+if (length(args) == 0) {
+    stop("At least one argument is necessary
+usage:
+  gen_pdf.r file.data [a_label [ordinate_label]]
+where the optional arguments
+  a_label is used to build output file names (use current dir by default)
+  ordinate_label is used to label the ordinate axis (use 'Nodes' by default)
+
+example:
+  gen_pdf.r clique.data
+  gen_pdf.r clique.data coloring
+  gen_pdf.r clique.data coloring Diameter
+", call.=FALSE)
+} 
+
+datafilename <- args[1]
+campaign <- ifelse(is.na(args[2]), basename(getwd()), args[2])
+abscissa  <- ifelse(is.na(args[3]),"Nodes",args[3])
+graphname <- tools::file_path_sans_ext(args[1])
+
+# Read the data file 
+data <- data.frame(val=read.table(datafilename))
+
+# Give to columns a name
+names(data) <- c("n", "Daemons", "Algorithms", "complexity_kind", "min", "mean", "max")
+
+# Generate a pdf visualisation of the Data with ggplot2
+library(ggplot2)
+library(dplyr)
+
+gen_pdf <- function(pdffilename, x1, x2){   
+    pdf(pdffilename,onefile=TRUE)
+    mplot <- ggplot(data, aes_string(x="n",y="mean",colour=x1))+ geom_line() +
+        facet_grid(c(paste("complexity_kind"), paste(x2)) , scales='free') +
+        ylab("Move/Step/Round Numbers")+xlab(paste(abscissa,"Number"))+
+        ggtitle(paste("Compare", x1, "on various", x2, "Numbers on",
+                      stringr::str_to_title(graphname), sep = " "))
+    mplot2 <- mplot+geom_ribbon(aes_string(x="n", ymax="max", ymin="min"), alpha=0.2) +
+        ggtitle(paste("Compare", x1, "on various", x2, "Numbers on",
+                      stringr::str_to_title(graphname), "(+ min/max ribbon)", sep = " "))
+    print(mplot)
+    print(mplot2)
+        
+    for (cm in c("moves","steps","rounds")){
+        datax <- filter(data, complexity_kind == cm)
+        
+        plot <- ggplot(datax,aes_string(x="n",y="mean",colour=x1))+ geom_line() +
+            facet_grid(c(paste(x2)), scales='free') +
+            ylab(paste(cm, "Number", sep=" ")) + xlab(paste(abscissa,"Number"))+
+            ggtitle(paste(stringr::str_to_title(cm), "Numbers on",
+                          stringr::str_to_title(graphname), sep = " "))
+        plot1 <- plot + geom_point() 
+        plot2 <- plot+geom_ribbon(aes_string(x="n", ymax="max", ymin="min"), alpha=0.2)+
+            ggtitle(paste(stringr::str_to_title(cm), "Numbers on",
+                          stringr::str_to_title(graphname),
+                          "(+ min/max ribbon)", sep = " "))
+        print(plot1)
+        print(plot2)
+        
+        plot <- ggplot(datax,aes_string(x="n",y="mean",colour=x1,shape=x2))+ geom_line() +
+            ylab(paste(cm, "Number", sep=" ")) + xlab(paste(abscissa,"Number"))+
+            ggtitle(paste(stringr::str_to_title(cm), "Numbers on",
+                          stringr::str_to_title(graphname), sep = " "))
+        plot1 <- plot + geom_point() 
+        plot2 <- plot+geom_ribbon(aes_string(x="n", ymax="max", ymin="min"), alpha=0.2)+
+            ggtitle(paste(stringr::str_to_title(cm), "Numbers on",
+                          stringr::str_to_title(graphname),
+                          "(+ min/max ribbon)", sep = " "))
+        print(plot1)
+        print(plot2)
+    }
+    pngfilename = paste(pdffilename,".png", sep ="")
+    png(pngfilename)
+    print(mplot2)
+    
+}
+
+pdffilename1 = paste(campaign, datafilename,"algos.pdf", sep ="-")
+pdffilename2 = paste(campaign, datafilename,"demons.pdf", sep ="-")
+gen_pdf(pdffilename1, "Algorithms", "Daemons")
+gen_pdf(pdffilename2, "Daemons", "Algorithms")
+
diff --git a/tools/simca/nonreg_test_campaign.ml b/tools/simca/nonreg_test_campaign.ml
new file mode 100644
index 0000000000000000000000000000000000000000..36d0b592072e01ee4da7dd9c40d25355ebf2f5b0
--- /dev/null
+++ b/tools/simca/nonreg_test_campaign.ml
@@ -0,0 +1,43 @@
+#use "genExpeMakefiles.ml";;
+precision := 0.1;;
+(* 0.1  means that we simulate  until the Interval Confidence  size of
+   the 3  complexity numbers under  estimation is smaller than  10% of
+   their current estimation.
+
+   Starting with  10% to  get a  rough idea of  the complexity  in the
+   first place is probably a wise idea.  *)
+max_simu_nb := 1000;; (* by default, it's more *)
+timeout_in_sec := 60;; (* ditto *)
+let algos = ["../../test/alea-coloring-alt";
+             "../../test/alea-coloring-unif";
+             "../../test/alea-coloring"]
+let daemons = ["-sd";"-lcd";"-dd"]  
+let cliques = List.init 5 (fun n -> Clique (10*(n+1))) (* [10; 20; ...; 50] *)
+let rings = List.init 5 (fun n -> Ring (100*(n+1))) (* [100; 200; ...; 500] *)
+let er = List.init 5 (fun n -> ER (20*(n+1), 0.4)) (* [20; 40; ...; 100] *)
+    
+let gen_make_rules () = 
+  let fn = "Makefile.expe-rules" in
+  let oc = open_out fn in
+  Printf.fprintf oc "# Generated by nonreg_test_campaign.ml";
+  (* 5 Cliques and 5 rings (not too big for the CI scripts) *)
+  let compare_neg x y = compare y x in
+  let l = List.sort_uniq compare_neg (cliques @ rings @ er) in
+  let targets,targets_cmxs = gen_makefile oc daemons algos l [] [] in
+  Printf.fprintf oc "\nCMXS=%s\n" (String.concat " " targets_cmxs);
+  Printf.fprintf oc "\nLOG=%s\n%!" (String.concat " " targets);
+  Printf.printf "%s has been generated\n%!" fn;
+  close_out oc
+;;
+
+#use "parseLog.ml";;
+open Printf
+let gen_pdf () =
+  let gl = ["clique"; "ring"; "er"] in
+  List.iter (fun n -> sh ("rm -f "^n^".data")) gl; (* because parse_log appends data *) 
+  parse_log ["Uniform When Triggered", "alea-coloring-unif"] gl daemons;
+  parse_log ["Smallest When Triggered","alea-coloring"] gl daemons;
+  parse_log ["Always the Biggest", "alea-coloring-alt"] gl daemons;
+  List.iter (fun n -> sh ("./gen_pdf.r "^n^".data nonreg")) gl;
+  ()
+;;
diff --git a/tools/simca/parseLog.ml b/tools/simca/parseLog.ml
new file mode 100644
index 0000000000000000000000000000000000000000..e3375eceb3e6350ed4ed37a1cd62ee3d18cd4556
--- /dev/null
+++ b/tools/simca/parseLog.ml
@@ -0,0 +1,18 @@
+#use "parseLogUtils.ml";;
+(*  [parse_log algo_labels  graphs  daemons] generates  as many  .data
+   files as there are graphs  i.e., if graphs=["g1"; "g2"; etc.], then
+   this function  generates "g1.data",  "g2.data", etc.  If  the .data
+   files  do  not  exist,  there are  created.   Otherwise,  data  are
+   appended at the end.  *)
+let parse_log
+    (algo_labels:(string * string) list) (* (algo label, algo directory) *)
+    (graphs: string list) (* graph label (clique, ring, udg) *)
+    (daemons:string list) = (* sasa daemon short option name *)
+  let f l a g d =
+    let log_mask = Printf.sprintf  "%s*%s-*%s.log" g d a in
+    Printf.printf "parse_log \"%s\" \"%s\" \"%s\" \"%s\" mask='%s'\n%!" l a g d log_mask;
+    data_from_log log_mask d l (g^".data")
+  in
+  List.iter (fun (l, a) -> List.iter (fun g -> List.iter (fun d ->
+      f l a g d) daemons) graphs) algo_labels
+;;
diff --git a/tools/simca/parseLogUtils.ml b/tools/simca/parseLogUtils.ml
new file mode 100644
index 0000000000000000000000000000000000000000..ad1ea71ea0c5146095f1e867f3b88e54e8b5f752
--- /dev/null
+++ b/tools/simca/parseLogUtils.ml
@@ -0,0 +1,85 @@
+#use "utils.ml";;
+
+(***********************************************************************)
+(* Append to datafile  information read in log files specified with log_mask.
+log files are expected to contain something like
+"
+ Min.   : 906.0  
+ 1st Qu.: 973.5  
+ Median :1007.5  
+ Mean   :1020.5  
+ 3rd Qu.:1053.5  
+ Max.   :1164.0  
+"
+3 times (for moves, steps, and then rounds)
+*)
+exception Pb
+let data_from_log log_mask demon algolbl datafile  =
+  let demon = match demon with
+    | "-sd" -> "Synchronous"
+    | "-dd" -> "Distributed"
+    | "-lcd" -> "Locally Central"
+    | "-cd" -> "Central"
+    | s -> s
+  in
+  let oc = open_out_gen [Open_wronly; Open_creat; Open_append; Open_binary] 0o666
+      datafile
+  in
+  let ocorg = open_out_gen [Open_wronly; Open_creat; Open_append; Open_binary] 0o666
+      (datafile^".org")
+  in
+  let log_files = run ("ls -1 " ^ log_mask) in
+  List.iter
+    (fun log ->
+       try
+         let _first_int = Str.search_forward (Str.regexp "[0-9]+") log 0 in
+         let size = Str.matched_string log in
+         let min_moves, min_steps, min_rounds =
+           match run ("grep -n \"Min.\" "^ log) with
+           | str1::str2::str3::_ ->
+             List.hd (List.rev(Str.split (Str.regexp ":") str1)),
+             List.hd (List.rev(Str.split (Str.regexp ":") str2)),
+             List.hd (List.rev(Str.split (Str.regexp ":") str3))
+           | _  ->
+             Printf.printf  "W: no Min found in %s\n%!" log;
+             raise Pb
+         in
+         let max_moves, max_steps, max_rounds =
+           match run ("grep -n \"Max.\" "^ log) with
+           | str1::str2::str3::_ ->
+             List.hd (List.rev(Str.split (Str.regexp ":") str1)),
+             List.hd (List.rev(Str.split (Str.regexp ":") str2)),
+             List.hd (List.rev(Str.split (Str.regexp ":") str3))
+           | _  ->
+             Printf.printf  "W: no Max found in %s\n%!" log;
+             raise Pb
+         in
+         let mean_moves, mean_steps, mean_rounds =
+           match run ("grep -n \"Mean\" "^ log) with
+           | str1::str2::str3::_ ->
+             List.hd (List.rev(Str.split (Str.regexp ":") str1)),
+             List.hd (List.rev(Str.split (Str.regexp ":") str2)),
+             List.hd (List.rev(Str.split (Str.regexp ":") str3))
+           | _  ->
+             Printf.printf  "W: no Mean found in %s\n%!" log;
+             raise Pb
+         in
+         Printf.fprintf oc "%s \"%s\" \"%s\" moves %s %s %s\n%!"
+           size demon algolbl min_moves mean_moves max_moves ;
+         Printf.fprintf oc "%s \"%s\" \"%s\" steps %s %s %s\n%!"
+           size demon algolbl min_steps mean_steps max_steps ;
+         Printf.fprintf oc "%s \"%s\" \"%s\" rounds %s %s %s\n%!"
+           size demon algolbl min_rounds mean_rounds max_rounds;
+         Printf.fprintf ocorg "| %s | %s | %s | moves | %s | %s | %s| \n%!"
+           size demon algolbl min_moves mean_moves max_moves ;
+         Printf.fprintf ocorg "| %s | %s | %s | steps | %s | %s | %s| \n%!"
+           size demon algolbl min_steps mean_steps max_steps ;
+         Printf.fprintf ocorg "| %s | %s | %s | rounds | %s | %s | %s| \n%!"
+           size demon algolbl min_rounds mean_rounds max_rounds
+       with
+         Pb -> ()
+    )
+    log_files;
+  close_out oc;
+  close_out ocorg;
+  ()
diff --git a/tools/simca/plot.r b/tools/simca/plot.r
new file mode 100755
index 0000000000000000000000000000000000000000..e2b342542e5963db39626d1215157fb1b79fbae9
--- /dev/null
+++ b/tools/simca/plot.r
@@ -0,0 +1,36 @@
+#! /usr/bin/env Rscript
+# Let's first give to CLI arguments some meaningfull names
+args <- commandArgs(TRUE)
+datafilename <- args[1]
+outfilename <- args[2]
+title <- args[3]
+pdffilename = paste(datafilename,outfilename,"rounds.pdf", sep ="-")
+pdffilename2 = paste(datafilename,outfilename,"moves.pdf", sep ="-")
+pdffilename3 = paste(datafilename,outfilename,"steps.pdf", sep ="-")
+
+# Read the data file 
+data <- data.frame(val=read.table(datafilename))
+
+# Give to columns a name
+names(data) <- c("n", "r", "Daemon", "Algorithm", "complexity_kind")
+
+# Generate a pdf visualisation of the Data with ggplot2
+library(ggplot2)
+pdf(pdffilename)
+ggplot(subset(data,complexity_kind=="rounds"),aes(x=n,y=r,colour=Daemon,shape=Algorithm))+
+    geom_line() + geom_point() +
+#    facet_grid(complexity_kind ~ .)
+    ylab("Rounds Number")+xlab("Nodes Number")+ggtitle(paste(title,"Rounds Numbers"," "))
+
+# Ditto for moves
+pdf(pdffilename2)
+ggplot(subset(data,complexity_kind=="moves"),aes(x=n,y=r,colour=Daemon,shape=Algorithm))+
+    geom_line() +  geom_point() +
+    ylab("Moves Number")+xlab ("Nodes Number")+ggtitle(paste(title,"Moves Numbers"," "))
+
+# Ditto for steps
+pdf(pdffilename3)
+ggplot(subset(data,complexity_kind=="steps"),aes(x=n,y=r,colour=Daemon,shape=Algorithm))+
+    geom_line() + geom_point() +
+    ylab("Steps Number")+xlab("Nodes Number")+ggtitle(paste(title,"Steps Numbers"," "))
+
diff --git a/tools/simca/runSimus.ml b/tools/simca/runSimus.ml
new file mode 100644
index 0000000000000000000000000000000000000000..1cfa8cf519d8e59b94abb46d37f4890a76cda405
--- /dev/null
+++ b/tools/simca/runSimus.ml
@@ -0,0 +1,185 @@
+#use "topfind";;
+#require "unix";;
+#require "str";;
+
+let (run0 : string -> (string -> string option) -> string list) =
+ fun cmd filter -> 
+  let proc = Unix.open_process_in ("("^cmd^" ) 2>&1") in
+  let list = ref [] in
+  try
+    while true do
+      let line = input_line proc in
+        match filter line with
+          | None -> ()
+          | Some str -> list := str::!list
+    done;
+    []
+  with End_of_file ->
+    ignore (Unix.close_process_in proc);
+    List.rev !list
+
+(* Executes a system call and get the printed result in a list *)
+let run str = run0 str (fun s -> Some s)
+
+let run_p str = print_string (String.concat " " (run str))
+let sh = run_p
+
+let time f x =
+  let t = Sys.time() in
+  let fx = f x in
+  Printf.printf "Execution time: %fs\n" (Sys.time() -. t);
+  fx 
+
+
+(**********************************************************************)
+(* Parses a sasa call outputs to get the nb of moves, rounds, and steps. *)
+let get_step str =
+  (*    Printf.printf "get_step '%s'\n%!" str;  *)
+  if
+    Str.string_match (Str.regexp "This algo is silent after \\(.+\\) moves, \\(.+\\) steps, \\(.+\\) rounds.$") str 0
+  then
+    let moves  = int_of_string (Str.matched_group 1 str) in
+    let step   = int_of_string (Str.matched_group 2 str) in
+    let rounds = int_of_string (Str.matched_group 3 str) in
+    Some (moves, step, rounds)
+  else
+    (
+      Printf.printf "runSimu.ml get_step: Fail to parse '%s'\n%!" str;
+      None
+    )
+
+(**********************************************************************)
+let tf = float_of_int
+let stddev m xl =
+  let n = List.length xl in
+  let sum =
+    List.fold_left (fun acc xi -> acc +. (m -. (tf xi)) *. (m -. (tf xi))) 0.0 xl
+  in
+  sqrt (sum /. (tf n))
+
+type t = {  all: int list;  sum: int;  mini: int;  maxi: int }
+let init = { all = []; sum = 0; mini = max_int; maxi = 0 }
+
+let update v x =  {
+  all = v::x.all;
+  sum = v+x.sum;
+  mini = min v x.mini;
+  maxi = max v x.maxi;
+}
+
+let gen_data_file  m il fn n label title =
+  let oc =open_out fn in
+  Printf.fprintf oc "# %s %s \n" label title;
+  List.iter (Printf.fprintf oc "%i\n") il;
+  flush oc;
+  close_out oc;
+  ignore(Sys.command (Printf.sprintf "../expe/distrib.r %s %f %s %s %i"
+                        fn m label title n));
+  ()
+    
+(* run_simus [cmd] several times [*], and generates 3 files:
+   -  f.step.data  
+   -  f.move.data  
+   -  f.round.data  
+   where f is a string made of out of the [cmd] string, and 
+   where data files contain [n] step/move/round numbers (one per simu)
+
+   Also call the R script distrib.r on each data file 
+ 
+   [*] at least 10, and at most 10000 times.  New  simulations are performed 
+   as long  as the size of the Confidence Interval with a confidence level of 
+   95% (CI_95) is higher  than threshold x m, where  is the estimation of one
+   on the complexity measure number.
+
+   Take threshold= 0.01 for 1% of uncertainty 
+*)
+let run_simus regen_dot threshold max_simu_nb timeout cmd = 
+  let t = Unix.time() in
+  let g, d =
+    if Str.string_match (Str.regexp ".* \\(.*\\)\\.dot \\([^ ]*\\) ") cmd 0
+    then Str.matched_group 1 cmd,Str.matched_group 2 cmd
+    else "g",""
+  in
+  let basefn = Printf.sprintf "%s%s" g d in
+  let step = ref init in
+  let move = ref init in
+  let round = ref init in
+  let continue = ref true in
+  let i = ref 0 in
+  while !continue  do
+    if regen_dot then (
+      let gen_dot_cmd = Printf.sprintf "sh ./%s.dot.sh 2>&1" g in
+      Printf.printf "Regenerating the dot graph: %s\n%!" gen_dot_cmd;
+      assert (0 = Sys.command gen_dot_cmd)
+    );
+    let l = run cmd in
+    List.iter
+      (fun x  ->
+         match get_step x with
+         | None -> ()
+         (* can occur if the generated graph is not connected on some algos *)
+         | Some (m,s,r) ->
+           incr i;
+           step := update s !step;
+           move := update m !move;
+           round := update r !round;
+           Printf.printf
+             "\n%i: step = %i round = %i mean(step) = %d mean(round) = %d\n%!"
+             !i  s r
+             (!step.sum / !i) 
+             (!round.sum / !i) ;
+      )
+      l;
+    let step_mean = (tf !step.sum /. (tf !i))
+    and move_mean = (tf !move.sum /. (tf !i))
+    and round_mean= (tf !round.sum /. (tf !i))
+    in
+    let step_dev = stddev step_mean !step.all
+    and move_dev = stddev move_mean !move.all
+    and round_dev = stddev round_mean !round.all
+    in
+    let continue_f m rho =
+      let x = (1.96 *. rho /. (threshold *. m)) ** 2.0 in
+      let y = (1.96 *. rho *. 10.) ** 2.0 in
+      Printf.printf "m=%f rho=%f : %d > %f or %f ? \n%!" m rho !i x y;
+      !i < max_simu_nb && ( (* do at most max_simu_nb simulations *)
+        (Unix.time() -. t < timeout) && 
+        (!i < 10 (* and at least 10 *)
+         ||
+         (!i < (int_of_float x ) (* stop when |ci|< threshold x m *)
+          && !i < (int_of_float y )) (* or stop when |ci|< 0.1 *)
+        ))
+    in
+    continue := continue_f move_mean move_dev ||
+                continue_f step_mean step_dev ||
+                continue_f round_mean round_dev 
+  done;
+  let step_mean = (tf !step.sum /. (tf !i))
+  and move_mean = (tf !move.sum /. (tf !i))
+  and round_mean= (tf !round.sum /. (tf !i))
+  in
+  let step_dev = stddev step_mean !step.all
+  and move_dev = stddev move_mean !move.all
+  and round_dev = stddev round_mean !round.all
+  in
+  let step_delta_ci = 2.0 *.  1.96 *. step_dev /. (sqrt (tf !i))
+  and move_delta_ci = 2.0 *.  1.96 *. move_dev /. (sqrt (tf !i))
+  and round_delta_ci = 2.0 *.  1.96 *. round_dev /. (sqrt (tf !i))
+  in
+  let step_str = Printf.sprintf "\"[%d ... %.2f~%.2f ... %d]   |CI_95|=%.2f n=%d\"%!"
+      !step.mini step_mean step_dev !step.maxi step_delta_ci !i
+  and move_str= Printf.sprintf "\"[%d ... %.2f~%.2f ... %d]   |CI_95|=%.2f n=%d\"%!"
+      !move.mini move_mean move_dev !move.maxi move_delta_ci !i
+  and round_str = Printf.sprintf "\"[%d ... %.2f~%.2f ... %d]   |CI_95|=%.2f n=%d\"%!"
+      !round.mini  round_mean round_dev !round.maxi round_delta_ci !i
+  in    
+  gen_data_file move_mean !move.all (basefn^".move.data") !i "Move" move_str;
+  gen_data_file step_mean !step.all (basefn^".step.data") !i "Step" step_str;
+  gen_data_file round_mean !round.all (basefn^".round.data") !i "Round" round_str;
+  Printf.printf "Moves:%s\nSteps:%s\nRounds:%s\n" move_str step_str round_str ;
+  if !i = max_simu_nb then
+    Printf.printf "ZZZ Maximal number of simulations (%d) reached!\n" max_simu_nb;
+  if Unix.time() -. t > timeout  then
+    Printf.printf "ZZZ Timeout! (%f > %f)\n"  (Unix.time() -. t) timeout ;
+  Printf.printf "Wall-clock Execution time for this file: %fs\n" (Unix.time() -. t);
+  exit 0;;
diff --git a/tools/simca/spanning_tree_campaign.ml b/tools/simca/spanning_tree_campaign.ml
new file mode 100644
index 0000000000000000000000000000000000000000..a58268ba5c756a2a7a1f0e801bfe325a4a7cce91
--- /dev/null
+++ b/tools/simca/spanning_tree_campaign.ml
@@ -0,0 +1,38 @@
+#use "genExpeMakefiles.ml";;
+let algos = ["../../test/bfs-spanning-tree";
+             "../../test/dfs";
+             "../../test/bfs-st-HC92";
+             "../../test/st-CYH91";
+             "../../test/st-KK06-algo1";
+             "../../test/st-KK06-algo2"
+             ]
+let daemons = ["-cd";"-dd"]  
+let cliques = List.init 10 (fun n -> Clique (20*(n+1)))  (* [20; 40; ...; 200] *)
+let er = List.init 10 (fun n -> ER (10*(n+1), 0.4)) (* [10; 20; ...; 100] *)
+
+let gen_make_rules () =
+  precision := 0.5; 
+  let fn = "Makefile.expe-rules" in
+  let oc = open_out fn in
+  Printf.fprintf oc "# Generated by spanning_tree_campaign.ml / gen_make_rules";
+  let compare_neg x y = compare y x in
+  let l = List.sort_uniq compare_neg (cliques @ er) in
+  let targets,targets_cmxs = gen_makefile oc daemons algos l [] [] in
+  Printf.fprintf oc "\nCMXS=%s\n"  (String.concat " " targets_cmxs);
+  Printf.fprintf oc "\nLOG=%s\n%!" (String.concat " " targets);
+  Printf.printf "%s has been generated\n%!" fn;
+  close_out oc
+;;
+#use "parseLog.ml";;
+let gen_pdf () =
+  let gl = ["clique"; "er"] in
+  List.iter (fun n -> sh ("rm -f "^n^".data")) gl;
+  parse_log ["BFS book", "bfs-spanning-tree";
+             "DFS book", "dfs";
+             "HC92", "bfs-st-HC92";
+             "CYH91", "st-CYH91";
+             "KK06-algo1", "st-KK06-algo1";
+             "KK06-algo2", "st-KK06-algo2"]
+    gl daemons;
+  List.iter (fun n -> sh ("./gen_pdf.r "^n^".data Tree")) gl
+;;
diff --git a/tools/simca/utils.ml b/tools/simca/utils.ml
new file mode 100644
index 0000000000000000000000000000000000000000..995eb858b1b54ea12a7fde4329005132264b44ae
--- /dev/null
+++ b/tools/simca/utils.ml
@@ -0,0 +1,33 @@
+#use "topfind";;
+
+#require "str";;
+
+let (run0 : string -> (string -> string option) -> string list) =
+ fun cmd filter -> 
+  let proc = Unix.open_process_in ("("^cmd^" | sed -e 's/^/stdout: /' ) 2>&1") in
+  let list = ref [] in
+  try
+    while true do
+      let line = input_line proc in
+      if String.length line >= 8 && String.sub line 0 8 = "stdout: " then 
+        let str = String.sub line 8 (String.length line - 8) in
+        match filter str with
+          | None -> ()
+          | Some str -> list := str::!list
+    done;
+    []
+  with End_of_file ->
+    ignore (Unix.close_process_in proc);
+    List.rev !list
+
+(* Executes a system call and get the printed result in a list *)
+let run str = run0 str (fun s -> Some s)
+
+let run_p str = print_string (String.concat " " (run str))
+let sh = run_p
+
+let time f x =
+  let t = Sys.time() in
+  let fx = f x in
+  Printf.printf "Execution time: %fs\n" (Sys.time() -. t);
+  fx