From 9bb45f3e10c15c3409b646bc52ce797d5ea2de65 Mon Sep 17 00:00:00 2001 From: Gwennan Eliezer <gwennan.eliezer@etu.univ-grenoble-alpes.fr> Date: Fri, 5 Jul 2019 15:34:39 +0200 Subject: [PATCH] Debugged, renamed CommomGraph ClassicGraph, placed all the UDG utils from RandomGraph into a new module, enhanced "gg <command> -s" such that is has effect on warnings, removed "rand" function --- .../{commonGraph.ml => classicGraph.ml} | 23 +++--- .../{commonGraph.mli => classicGraph.mli} | 0 tools/graphgen/ggcore.ml | 15 ++-- tools/graphgen/ggcore.mli | 3 - tools/graphgen/graphGen.ml | 78 ++++++++++--------- tools/graphgen/graphGen_arg.ml | 42 +++++----- tools/graphgen/graphGen_arg.mli | 2 +- tools/graphgen/randomGraph.ml | 67 ---------------- tools/graphgen/randomGraph.mli | 35 --------- tools/graphgen/udgUtils.ml | 70 +++++++++++++++++ tools/graphgen/udgUtils.mli | 42 ++++++++++ 11 files changed, 196 insertions(+), 181 deletions(-) rename tools/graphgen/{commonGraph.ml => classicGraph.ml} (90%) rename tools/graphgen/{commonGraph.mli => classicGraph.mli} (100%) create mode 100644 tools/graphgen/udgUtils.ml create mode 100644 tools/graphgen/udgUtils.mli diff --git a/tools/graphgen/commonGraph.ml b/tools/graphgen/classicGraph.ml similarity index 90% rename from tools/graphgen/commonGraph.ml rename to tools/graphgen/classicGraph.ml index 39e077c1..6001554e 100644 --- a/tools/graphgen/commonGraph.ml +++ b/tools/graphgen/classicGraph.ml @@ -33,16 +33,19 @@ let add_weight (li : node_id list) : (int option * node_id) list = map (fun elem let neighbours_ring : (node_id list -> (node_id -> (int option * node_id) list)) = fun li -> let node_succ:node_succ_t = Hashtbl.create (length li) in - let (_,ret) = fold_right (fun elem ((first,prev),accu) -> (* have to change it, to use a fold_left *) - if first = "" then - ((elem,elem),[[""; prev]]) - else - ( - match accu with - | [_;x]::tl -> ((first,elem),[first;prev]::([elem;x]::tl)) - | _ -> assert false - ) - ) li (("",(hd li)),[]) in + let ((_,last),ret) = fold_left (fun ((first,prev),accu) elem -> + if first = "" then + ((elem,elem),[[""; ""]]) + else + ( + match accu with + | [x;_]::tl -> ((first,elem),[prev;first]::([x;elem]::tl)) + | _ -> assert false + ) + ) (("",""),[]) li in let ret = rev ret in + let ret = (match ret with + | ["";x]::tail -> [last;x]::tail + | _ -> assert false) in iter2 (fun neighbours elem -> Hashtbl.replace node_succ elem (add_weight neighbours)) ret li ; (fun n -> try Hashtbl.find node_succ n with Not_found -> []) diff --git a/tools/graphgen/commonGraph.mli b/tools/graphgen/classicGraph.mli similarity index 100% rename from tools/graphgen/commonGraph.mli rename to tools/graphgen/classicGraph.mli diff --git a/tools/graphgen/ggcore.ml b/tools/graphgen/ggcore.ml index 143837fa..e3fb5611 100644 --- a/tools/graphgen/ggcore.ml +++ b/tools/graphgen/ggcore.ml @@ -6,10 +6,6 @@ type topology = { succ: node_id -> (int option * node_id) list } -let rand : (int -> int -> int) = - (* Makes a random number between the two arguments *) - fun min max -> min + Random.int (max-min) - let rec create_nodes : (string -> int*int -> node_id list) = (* Create names from a generic name *) fun name (start,finish) -> @@ -51,10 +47,13 @@ let make_dot : (topology -> string -> unit) = let name = ref "graph0" in let f = (if file_name = "" then stdout else ( - name := Filename.remove_extension file_name; - (*if Filename.extension file_name <> ".dot" then - (open_out (file_name ^".dot")) - else*) open_out file_name + name := file_name; + (try ( (* remove all extensions. So if name = ref "tt.dot.dot" at the beginning, at the end name = ref "tt". *) + while true do + name := Filename.chop_extension !name; + done; + ) with Invalid_argument _ -> ()); + open_out file_name ) ) in let dot = (Printf.sprintf "graph %s {\n\n" !name) ^ (make_nodes_dot t.nodes) ^ "\n" ^ (make_links_dot t) ^ "\n}\n" in diff --git a/tools/graphgen/ggcore.mli b/tools/graphgen/ggcore.mli index 0178c099..a6cdc4b3 100644 --- a/tools/graphgen/ggcore.mli +++ b/tools/graphgen/ggcore.mli @@ -6,9 +6,6 @@ type topology = { succ: node_id -> (int option * node_id) list } -(** Gives a random int between the two arguments. Useful to have a random nodes number *) -val rand : (int -> int -> int) - (** Create a name (i.d. node ID) list from a generic name *) val create_nodes : (string -> int*int -> node_id list) diff --git a/tools/graphgen/graphGen.ml b/tools/graphgen/graphGen.ml index 81494a17..b297095a 100644 --- a/tools/graphgen/graphGen.ml +++ b/tools/graphgen/graphGen.ml @@ -1,26 +1,28 @@ open Ggcore -open CommonGraph +open ClassicGraph open RandomGraph open GraphGen_arg +open UdgUtils let () = ( let t = parse Sys.argv in if (t.n < 0) then ( - match t.action with - | "void" | "grid" -> () + let msg = match t.action with + | "void" | "grid" -> "" | "HC" -> ( t.n <- 3; - Printf.fprintf stderr "=========================================================================\n"; - Printf.fprintf stderr "Caution : the dimension is not defined or negative. It has been set to 3.\n"; - Printf.fprintf stderr "=========================================================================\n" + "=========================================================================\n"^ + "Caution : the dimension is not defined or negative. It has been set to 3.\n"^ + "=========================================================================\n" ) | _ -> ( t.n <- 10; - Printf.fprintf stderr "=============================================================================\n"; - Printf.fprintf stderr "Caution : the nodes number is not defined or negative. It has been set to 10.\n"; - Printf.fprintf stderr "=============================================================================\n" - ) + "=============================================================================\n"^ + "Caution : the nodes number is not defined or negative. It has been set to 10.\n"^ + "=============================================================================\n" + ) in + if (not t.silent) then Printf.fprintf stderr "%s" msg ); let args_msg = ref "" in let g = ( match t.action with @@ -28,36 +30,42 @@ let () = ( | "clique" -> (gen_clique t.n) | "star" -> (gen_star t.n) | "ring" -> (gen_ring t.n) - | "grid" -> (args_msg := Printf.sprintf" with l=%d w=%d" t.grid.height t.grid.width; gen_grid t.grid.height t.grid.width) + | "grid" -> (args_msg := Printf.sprintf" with l=%d w=%d" t.grid.height t.grid.width; + gen_grid t.grid.height t.grid.width) | "HC" -> (gen_hyper_cube t.n) | "ER" -> (args_msg := Printf.sprintf" with p=%f" t.er; gen_ER t.n t.er) | "BA" -> (args_msg := Printf.sprintf" with m=%d" t.ba; gen_BA t.n t.ba) | "tree" -> (rand_tree t.n) | "UDG" -> ( - args_msg := Printf.sprintf " with w=%f l=%f r=%f" t.udg.width t.udg.height t.udg.radius; - let prob_func = (match t.udg.proba with - | ConstP c -> (args_msg := Printf.sprintf "%s and p=%f" !args_msg c; (proba_from_constant c)) - | LstP l -> (args_msg := Printf.sprintf "%s and a list of probabilities" !args_msg; (proba_from_list l t.udg.radius)) - | LinearP -> ( - args_msg := Printf.sprintf "%s and a probability proportionnal to to the distance" !args_msg; - (linear_prob t.udg.radius) - ) - ) in - let (graph,plan) = gen_udg ~p:(prob_func) t.n t.udg.width t.udg.height t.udg.radius in - if (t.dotUDG <> "") then ( - make_dot_udg graph plan (t.udg.width,t.udg.height) (t.dotUDG^".dot"); - ignore (Sys.command (Printf.sprintf "neato -Tpdf %s.dot -o %s.pdf" t.dotUDG t.dotUDG )) - ); - if (t.dotUDGrad <> "") then ( - make_dot_udg graph plan (t.udg.width,t.udg.height) ~r:(t.udg.radius) (t.dotUDGrad^".dot"); - ignore (Sys.command (Printf.sprintf "neato -Tpdf %s.dot -o %s.pdf" t.dotUDGrad t.dotUDGrad )) - ); - graph - ) - | _ -> (Printf.fprintf stderr "Unexpected outcome. Command line : %s\n" (String.concat " " (Array.to_list Sys.argv)); - assert false) + args_msg := Printf.sprintf " with w=%f l=%f r=%f" + t.udg.width t.udg.height t.udg.radius; + let prob_func = (match t.udg.proba with + | ConstP c -> (args_msg := Printf.sprintf "%s and p=%f" !args_msg c; + (prob_from_constant c)) + | LstP l -> (args_msg := Printf.sprintf "%s and a list of probabilities" !args_msg; + (prob_from_list l t.udg.radius)) + | LinearP -> ( + args_msg := Printf.sprintf "%s and a linear edge probability" !args_msg; + (linear_prob t.udg.radius) + ) + ) in + let (graph,plan) = gen_udg ~p:(prob_func) t.n t.udg.width t.udg.height t.udg.radius in + if (t.dotUDG <> "") then ( + make_dot_udg graph plan (t.udg.width,t.udg.height) (t.dotUDG^".dot"); + ignore (Sys.command (Printf.sprintf "neato -Tpdf %s.dot -o %s.pdf" t.dotUDG t.dotUDG)) + ); + if (t.dotUDGrad <> "") then ( + make_dot_udg graph plan (t.udg.width,t.udg.height) ~r:(t.udg.radius) (t.dotUDGrad^".dot"); + ignore (Sys.command (Printf.sprintf "neato -Tpdf %s.dot -o %s.pdf" t.dotUDGrad t.dotUDGrad )) + ); + graph + ) + | _ -> (Printf.fprintf stderr "Unexpected outcome. Command line : %s\n" + (String.concat " " (Array.to_list Sys.argv)); assert false) ) in - if (t.outputFile <> "" && not t.silent) then Printf.printf "Generating a %s graph%s...\n" t.action !args_msg; + if (t.outputFile <> "" && not t.silent) + then Printf.printf "Generating a %s graph%s...\n" t.action !args_msg; make_dot g t.outputFile; - if (t.outputFile <> "" && not t.silent) then Printf.printf "Done.\nOutput file : '%s'\n" t.outputFile + if (t.outputFile <> "" && not t.silent) + then Printf.printf "Done.\nOutput file : '%s'\n" t.outputFile ) diff --git a/tools/graphgen/graphGen_arg.ml b/tools/graphgen/graphGen_arg.ml index 1805a413..6fc6f13e 100644 --- a/tools/graphgen/graphGen_arg.ml +++ b/tools/graphgen/graphGen_arg.ml @@ -4,7 +4,7 @@ type action = string type udg_proba = | ConstP of float | LstP of float list - | ProgP + | LinearP type grid_arg = { mutable width: int; @@ -73,9 +73,9 @@ let (make_args : unit -> t) = er = 0.3; ba = 2; udg = { - width = 0.; - height = 0.; - radius = 0.; + width = 10.; + height = 10.; + radius = 2.; proba = ConstP 1.; }; @@ -207,7 +207,7 @@ let (mkoptab : string array -> t -> unit) = | "UDG" -> args.udg.width <- w | _ -> unexpected "-w" )) [(["Set the grid's width to the value (integer)\n"],"grid"); - (["Set the UDG's terrain width to the value (float)\n"],"UDG")]; + (["Set the UDG's terrain width to the value (float)";"10 by default.\n"],"UDG")]; mkopt args ["--height";"-he"] ~arg:" <float>" (Arg.Float (fun h -> match args.action with @@ -215,7 +215,7 @@ let (mkoptab : string array -> t -> unit) = | "UDG" -> args.udg.height <- h | _ -> unexpected "-he")) [(["Set the grid's height to the value (integer)\n"],"grid"); - (["Set the UDG's terrain height to the value (float)\n"],"UDG")]; + (["Set the UDG's terrain height to the value (float)";"10 by default.\n"],"UDG")]; mkopt args ["--edge-probability";"-p"]~arg:" <float>" @@ -237,7 +237,7 @@ let (mkoptab : string array -> t -> unit) = (Arg.Float (fun r -> match args.action with | "UDG" -> args.udg.radius <- r | _ -> unexpected "-r")) - [(["Set the Unit Disc's radius around a node to the given value.\n"],"UDG")]; + [(["Set the Unit Disc's radius around a node to the given value.";"3 by default.\n"],"UDG")]; mkopt args ["--prob-from-constant";"-pc"] ~arg:" <float>" (Arg.Float (fun i -> args.udg.proba <- ConstP i)) @@ -256,28 +256,26 @@ let (mkoptab : string array -> t -> unit) = ], "UDG")]; mkopt args ["--progressive-prob";"-pp"] - (Arg.Unit (fun () -> args.udg.proba <- ProgP)) + (Arg.Unit (fun () -> args.udg.proba <- LinearP)) [(["...";"...";"...\n"], "UDG")]; - mkopt args ["--proba_from_couple_list";"-pcl"] - (Arg.Unit (fun () -> args.udg.proba <- CplLstP [])) - [(["...";"...";"...\n"], "UDG")]; - - mkopt args ["--dot_udg";"-du"]~arg:" <file>" + mkopt args ["--dot_udg";"-du"]~arg:" <file-base-name>" (Arg.String (fun f -> match args.action with | "UDG" -> args.dotUDG <- f | _ -> unexpected "-mdudg")) - [(["Create a DOT file to visualize the UDG plan.\n"],"UDG")]; + [(["Create a DOT file to visualize the UDG plan."; + "The extension .dot will be added to the file base-name.\n"],"UDG")]; - mkopt args ["--dot_udg_radius";"-dur"]~arg:" <file>" + mkopt args ["--dot_udg_radius";"-dur"]~arg:" <file-base-name>" (Arg.String (fun f -> match args.action with | "UDG" -> args.dotUDGrad <- f | _ -> unexpected "-mdudg")) - [(["Create a DOT file to visualize the UDG plan.\n"],"UDG")]; + [(["Create a DOT file to visualize the UDG plan."; + "The extension .dot will be added to the file base-name.\n"],"UDG")]; -(* mkopt args ["--silent";"-s"] + mkopt args ["--silent";"-s"] (Arg.Unit (fun () -> args.silent <- true)) - [(["Remove all outputs, except ones made by other options.\n"],"all")];*) + [(["Remove all outputs, except ones made by other options.\n"],"all")]; mkopt args ["--help";"-h"] (Arg.Unit (fun () -> help args ((argv.(0))^(if args.action = "void" then "" @@ -295,6 +293,7 @@ let current = ref 1;; let parse argv = ( let save_current = !current in let args = make_args () in + mkoptab argv args; try ( (if (Array.length argv) = 1 then help args (argv.(0))); let possible_actions = ["clique";"star";"ring";"grid";"HC";"ER";"BA";"tree";"UDG"] in @@ -305,23 +304,22 @@ let parse argv = ( (Printf.fprintf stderr "*** Error when calling '%s %s': No such command\n\n" (argv.(0)) (argv.(1)); (print_usage stderr true argv.(0)); exit 2) ); - mkoptab argv args; Arg.parse_argv ~current:current argv args._args (add_other args) (usage_msg false (argv.(0)^argv.(1))); current := save_current; (List.iter (fun f -> - if (String.sub f 0 1 = "-") then + if (String.sub f 0 1 = "-") then ( unexpected f - else + ) else ( match args.action with | "UDG" -> ( match args.udg.proba with | LstP l -> args.udg.proba <- LstP ((float_of_string f)::l) | _ -> unexpected f ) - ) | _ -> unexpected f + ) ) (List.rev args._others) ); args diff --git a/tools/graphgen/graphGen_arg.mli b/tools/graphgen/graphGen_arg.mli index bf12aeed..70d476ef 100644 --- a/tools/graphgen/graphGen_arg.mli +++ b/tools/graphgen/graphGen_arg.mli @@ -1,6 +1,6 @@ type action = string -type udg_proba = |ConstP of float | LstP of float list | CplLstP of (float*float) list +type udg_proba = | ConstP of float | LstP of float list | LinearP type grid_arg = { mutable width: int; mutable height: int; diff --git a/tools/graphgen/randomGraph.ml b/tools/graphgen/randomGraph.ml index 28dca952..8e0a45e5 100644 --- a/tools/graphgen/randomGraph.ml +++ b/tools/graphgen/randomGraph.ml @@ -109,37 +109,6 @@ type node_udg = node_id*float*float type plan_udg = node_udg list type prob_udg = (float -> float) -(* utils for UDG : *) - -let prob_from_list : (float list -> float -> prob_udg) = - fun l r d -> (List.nth l (int_of_float (((float_of_int (List.length l))/.r)*.d))) - -let linear_prob : (float -> prob_udg) = - fun r -> (fun d -> d/r) - - - ) cpl (d,0)) in let (_,p) = (List.nth cpl tmp) in p - -let prob_from_constant : (float -> prob_udg) = - fun x _ -> x - -let recommend_radius : (int -> float -> (float * float) -> float) = - fun mean_deg nb_node (h,w) -> - if(mean_deg > nb_node) then - failwith "Error : the number of node should be greater or equal than mean degree" - else - sqrt ((h*.w)*.mean_deg/.(Float.pi*.(float_of_int nb_node))) - -let reccomend_nb_node : (float -> float -> (float * float) -> int) = - fun radius mean_deg (h,w) -> - (int_of_float ((mean_deg*.h*.w)/.((radius**2.)*.Float.pi)))+1 - -let compute_mean_degree : (int -> float -> (float * float) -> float) = - fun radius nb_node (h,w) -> - ((radius**2.)*.Float.pi*.(float_of_int nb_node))/.(h*.w) - -(* UDG implementation : *) - let (make_plan_udg: node_id list -> float -> float -> plan_udg) = fun nodes x y -> List.map (fun elem -> (elem,(Random.float x),(Random.float y))) (nodes) @@ -176,39 +145,3 @@ let (gen_udg: ?p:prob_udg -> int -> float -> float -> float -> (topology * plan_ nodes = nodes ; succ =(fun n -> (try Hashtbl.find node_succ n with Not_found -> [])); },pl - -(***************************************************************) - -let rec make_nodes_dot_udg : (node_udg list -> float -> string) = - (*Create a string in the dot syntax from a node list*) - fun nudg r -> - match nudg with - | [] -> "" - | head::tail -> - let (node,x,y) = head in - (*(Printf.sprintf "%s [algo=\"%s\",pos=\"%f,%f!\"]\n" node.id node.file x y )^*) - (Printf.sprintf "%s [pos=\"%f,%f!\"]\n" node x y )^ - let draw_rad = if(r <> -1.) then - (Printf.sprintf "%srad [pos=\"%f,%f!\",width=%f, length=%f,shape = circle,label=\"\",color=\"red\"]\n" node x y (2.*.r) (2.*.r) ) else "" in - draw_rad^(make_nodes_dot_udg tail r) - -let make_dot_udg : (topology -> plan_udg -> (float*float) -> ?r:float -> string -> unit) = - (*Create a dot file from a graph*) - fun t plan dim ?(r = -1.) file_name -> - let name = ref "graph0" in - let f = (if file_name = "" then stdout else - ( - name := Filename.remove_extension file_name; - open_out file_name - ) - ) in - let (w,l) = dim in - let mpos = if(r <> -1.) then (Printf.sprintf "size = \"%f,%f!\"\ntopLeft [pos=\"%f,%f!\",style=invis]\nlowRight [pos=\"0,0!\",style = invis]\nnode [fixedsize=false,shape=circle]\n" w l w l) else "" in - let dot = (Printf.sprintf "graph %s {\n\n"!name )^mpos - - - ^(make_nodes_dot_udg plan r) ^ "\n" ^ (make_links_dot t) ^ "\n}\n" in - Printf.fprintf f "%s" dot; - flush f; - close_out f - (*ignore (Sys.command (Printf.sprintf "echo \"%s\" > \"%s.dot\"" dot file_name)); ()*) diff --git a/tools/graphgen/randomGraph.mli b/tools/graphgen/randomGraph.mli index 4cd31460..140c7acb 100644 --- a/tools/graphgen/randomGraph.mli +++ b/tools/graphgen/randomGraph.mli @@ -29,38 +29,3 @@ val rand_tree: (int -> topology) p will be run to obtain the probability of an edge appearing between these nodes. p is (fun _ -> 1) by default, which means that the edge will appear if the Unit Discs of two nodes touch themselves.*) val gen_udg: (?p:prob_udg -> int -> float -> float -> float -> (topology * plan_udg)) - -(** create a probability function for UDG that always return the same probability *) -val prob_from_constant: (float -> prob_udg) - -(** [proba_from_list fl r] create a probability function for UDG that changes the probability according to the distance. - It cuts r into (length fl), and attribute the first element of fl to the first slice (closest to the center), and so on. - For example, [proba_from_list [1.;0.5;0.3;0.1] 10 d] will return 1. if 0 <= d < 2.5, 0.5 if 2.5 <= d < 5, and so on. - Note that r must be equal to the radius of the Unit Disc *) -val prob_from_list: (float list -> float -> prob_udg) - -(** [linear_proba r] gives a function that, for an input d (distance) outputs d/r. - If r is the Unit Disc radius and d the distance between two points, - it outputs a probability that is higher for a low d and lower for a high d. *) -val linear_prob: (float -> prob_udg) - -(** [recommend_radius n mean_deg h w] returns the recommended radius to give to UDG - in order to get a mean degree approximately equal to mean_deg, - knowing there's n nodes and the UDG is applied in an area of height h and width w. *) -val recommend_radius : (int -> float -> float -> float -> float) - -(** [reccomend_nb_node r mean_deg h w] returns the recommended number of nodes - to give to UDG in order to get a mean degree approximately equal to mean_deg, - knowing the radius is r and the UDG is applied in an area of height h and width w. *) -val reccomend_nb_node : (float -> float -> float -> float -> int) - -(** [compute_mean_degree n r h w] computes and return the approximative mean degree of - an UDG graph with the same arguments. *) -val compute_mean_degree : (int -> float -> float -> float -> float) - -(** [make_dot_udg ~r=r g p (h,w) f] Creates a DOT file to represent the UDG area, - r being the radius, g being the graph, p being the UDG area, - and (h,w) being the dimensions of the plan. - If no radius is given, they won't appear on the pdf. - If you have Grahviz, we advice using 'twopi -Tpdf f' to obtain a pdf. *) -val make_dot_udg : (topology -> plan_udg -> (float*float) -> ?r:float -> string -> unit) diff --git a/tools/graphgen/udgUtils.ml b/tools/graphgen/udgUtils.ml new file mode 100644 index 00000000..ea769743 --- /dev/null +++ b/tools/graphgen/udgUtils.ml @@ -0,0 +1,70 @@ +open Ggcore +type probability = float (*between 0 and 1*) +type prob_udg = (float -> probability) + +type node_udg = node_id*float*float +type plan_udg = node_udg list + +let prob_from_list : (float list -> float -> prob_udg) = + fun l r d -> (List.nth l (int_of_float (((float_of_int (List.length l))/.r)*.d))) + +let linear_prob : (float -> prob_udg) = + fun r -> (fun d -> d/.r) + +let prob_from_constant : (float -> prob_udg) = + fun x _ -> x + +let recommend_radius : (int -> float -> float -> float -> float) = + fun nb_node mean_deg h w -> + if(mean_deg > float_of_int nb_node) then + failwith "Error : the number of node should be greater or equal than mean degree" + else + sqrt ((h*.w)*.mean_deg/.(Float.pi*.(float_of_int nb_node))) + +let recommend_nb_node : (float -> float -> float -> float -> int) = + fun radius mean_deg h w -> + (int_of_float ((mean_deg*.h*.w)/.((radius**2.)*.Float.pi)))+1 + +let compute_mean_degree : (int -> float -> float -> float -> float) = + fun nb_node radius h w -> + ((radius**2.)*.Float.pi*.(float_of_int nb_node))/.(h*.w) + +(******************************************************************************) + +let rec make_nodes_dot_udg : (node_udg list -> float -> string) = + (*Create a string in the dot syntax from a node list*) + fun nudg r -> + match nudg with + | [] -> "" + | head::tail -> + let (node,x,y) = head in + (Printf.sprintf "%s [pos=\"%f,%f!\"]\n" node x y )^ + let draw_rad = if(r <> -1.) then + (Printf.sprintf "%srad [pos=\"%f,%f!\",width=%f, length=%f,shape = circle,label=\"\",color=\"red\"]\n" node x y (2.*.r) (2.*.r) ) else "" in + draw_rad^(make_nodes_dot_udg tail r) + +let make_dot_udg : (topology -> plan_udg -> (float*float) -> ?r:float -> string -> unit) = + (*Create a dot file from a graph*) + fun t plan dim ?(r = -1.) file_name -> + let name = ref "graph0" in (* default name *) + let f = (if file_name = "" then stdout else + ( + name := file_name; + (try ( (* remove all extensions. So if name = ref "tt.dot.dot" at the beginning, at the end name = ref "tt". *) + while true do + name := Filename.chop_extension !name; + done; + ) with Invalid_argument _ -> ()); + open_out file_name + ) + ) in + let (w,l) = dim in + let mpos = if(r <> -1.) then (Printf.sprintf "size = \"%f,%f!\"\ntopLeft [pos=\"%f,%f!\",style=invis]\nlowRight [pos=\"0,0!\",style = invis]\nnode [fixedsize=false,shape=circle]\n" w l w l) else "" in + let dot = (Printf.sprintf "graph %s {\n\n"!name )^mpos + + + ^(make_nodes_dot_udg plan r) ^ "\n" ^ (make_links_dot t) ^ "\n}\n" in + Printf.fprintf f "%s" dot; + flush f; + close_out f + (*ignore (Sys.command (Printf.sprintf "echo \"%s\" > \"%s.dot\"" dot file_name)); ()*) diff --git a/tools/graphgen/udgUtils.mli b/tools/graphgen/udgUtils.mli new file mode 100644 index 00000000..aad176e2 --- /dev/null +++ b/tools/graphgen/udgUtils.mli @@ -0,0 +1,42 @@ +open Ggcore +type probability = float (*between 0 and 1*) +type prob_udg = (float -> probability) + +type node_udg = node_id*float*float +type plan_udg = node_udg list + + +(** create a probability function for UDG that always return the same probability *) +val prob_from_constant: (float -> prob_udg) + +(** [proba_from_list fl r] create a probability function for UDG that changes the probability according to the distance. + It cuts r into (length fl), and attribute the first element of fl to the first slice (closest to the center), and so on. + For example, [proba_from_list [1.;0.5;0.3;0.1] 10 d] will return 1. if 0 <= d < 2.5, 0.5 if 2.5 <= d < 5, and so on. + Note that r must be equal to the radius of the Unit Disc *) +val prob_from_list: (float list -> float -> prob_udg) + +(** [linear_proba r] gives a function that, for an input d (distance) outputs d/r. + If r is the Unit Disc radius and d the distance between two points, + it outputs a probability that is higher for a low d and lower for a high d. *) +val linear_prob: (float -> prob_udg) + +(** [recommend_radius n mean_deg h w] returns the recommended radius to give to UDG + in order to get a mean degree approximately equal to mean_deg, + knowing there's n nodes and the UDG is applied in an area of height h and width w. *) +val recommend_radius : (int -> float -> float -> float -> float) + +(** [reccomend_nb_node r mean_deg h w] returns the recommended number of nodes + to give to UDG in order to get a mean degree approximately equal to mean_deg, + knowing the radius is r and the UDG is applied in an area of height h and width w. *) +val recommend_nb_node : (float -> float -> float -> float -> int) + +(** [compute_mean_degree n r h w] computes and return the approximative mean degree of + an UDG graph with the same arguments. *) +val compute_mean_degree : (int -> float -> float -> float -> float) + +(** [make_dot_udg g p (h,w) ~r=r f] Creates a DOT file to represent the UDG area, + r being the radius, g being the graph, p being the UDG area, + and (h,w) being the dimensions of the plan. + If no radius is given, they won't appear on the pdf. + If you have Grahviz, we advice using 'twopi -Tpdf f' to obtain a pdf. *) +val make_dot_udg : (topology -> plan_udg -> (float*float) -> ?r:float -> string -> unit) \ No newline at end of file -- GitLab