diff --git a/tools/ggDeco/ggDeco.ml b/tools/ggDeco/ggDeco.ml index 8758f29b6e16b7c187627e37fbc427c5c878e745..7803c51822e7a94e7d841be449da12da33881782 100644 --- a/tools/ggDeco/ggDeco.ml +++ b/tools/ggDeco/ggDeco.ml @@ -55,5 +55,5 @@ let () = ( let args = parse Sys.argv in let g = read args.dot_file in let new_g = deco g args.files_spec in - make_dot new_g args.output + make_dot new_g args.output attr ) diff --git a/tools/graphgen/graphGen.ml b/tools/graphgen/graphGen.ml index 5eb5240e4393b04756a65b8b981a81791103c86a..ae66f1543baa3da7fef0abc16578874df4080761 100644 --- a/tools/graphgen/graphGen.ml +++ b/tools/graphgen/graphGen.ml @@ -1,10 +1,18 @@ -open Sasacore.Topology +open Sasacore +open Topology +open GraphProp open ClassicGraph open RandomGraph open GraphGen_arg open UdgUtils +exception Incorrect_attribute + +let min_max = ref None +let connected_cyclic = ref None +let height = ref None + let generate_du_dur graph plan_udg t : unit = if (t.dotUDG <> "") then ( @@ -15,6 +23,35 @@ let generate_du_dur graph plan_udg t : unit = ); () +let compute_attr : (Topology.t -> string list -> (string*string) list) = + fun g -> List.map (fun attr -> + attr,match attr with + | "min_deg" -> string_of_int (match !min_max with + | None -> (let x = get_degree g in min_max := Some x; fst x) + | Some x -> fst x) + | "mean_deg" -> string_of_float (get_mean_degree g) + | "max_deg" -> string_of_int (match !min_max with + | None -> (let x = get_degree g in min_max := Some x; snd x) + | Some x -> snd x) + | "is_connected" -> string_of_bool (match !connected_cyclic with + | None -> (let x = is_connected_and_cyclic g in connected_cyclic := Some x; fst x) + | Some x -> fst x ) + | "is_cyclic" -> string_of_bool (match !connected_cyclic with + | None -> (let x = is_connected_and_cyclic g in connected_cyclic := Some x; snd x) + | Some x -> snd x ) + | "is_tree" -> string_of_bool (match !connected_cyclic with + | None -> (let x = is_connected_and_cyclic g in connected_cyclic := Some x; (fst x) && (snd x)) + | Some x -> (fst x) && (snd x) ) + | "links_number" -> string_of_int (get_nb_link g false) + | "diameter" -> string_of_int (get_diameter g) + | s -> string_of_int (let s = String.split_on_char ' ' s in + if List.hd s = "height" && List.length s = 2 then + get_height g (List.hd (List.tl s)) + else raise Incorrect_attribute) + ) + + + let () = ( let t = parse Sys.argv in @@ -54,7 +91,7 @@ let () = ( | _ -> (Printf.fprintf stderr "Unexpected outcome. Command line : %s\n" (String.concat " " (Array.to_list Sys.argv)); assert false) ) in - make_dot g t.outputFile; + make_dot g t.outputFile (compute_attr g t.attr); 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 e55b17c6ace511f30e6d991b838c56f651bbc8dd..215579a4ebc7065bfcad706e6347668d2f7b7477 100644 --- a/tools/graphgen/graphGen_arg.ml +++ b/tools/graphgen/graphGen_arg.ml @@ -30,6 +30,8 @@ type t = { mutable ba : ba_m; mutable qudg : qudg_arg; + mutable attr : string list; + mutable silent : bool; mutable _args : (string * Arg.spec * string) list; @@ -77,6 +79,8 @@ let (make_args : unit -> t) = p = 0.5; }; + attr = []; + silent = false; _args = []; @@ -280,6 +284,13 @@ let (mkoptab : string array -> t -> unit) = [(["Remove all outputs, except the dot output if it is on stdout,"; "and the error if one occurred.\n"],"void")]; + args._man <- ("--attributes, -atr <attributes>...", [([ + "Specify the given attributes of the graph to his DOT file."; + "the possible attributes are :"; + "min_deg, mean_deg, max_deg, is_connected, is_cyclic, is_tree, links_number, + diameter, height i (with i being the index of a node)" + ],"void")])::args._man; + mkopt args ["--help";"-h"] (Arg.Unit (fun () -> help args ((argv.(0))^(if args.action = "void" then "" else " "^args.action)))) @@ -310,7 +321,21 @@ let parse argv = ( Arg.parse_argv ~current:current argv args._args (add_other args) (usage_msg false (argv.(0)^argv.(1))); current := save_current; - if (List.length args._others) <> 0 then unexpected (List.hd args._others); + args._others <- List.rev args._others; + let have_atr = ref false in + (List.iter (fun o -> + if !have_atr then ( + if (String.sub o 0 1) = "-" then + unexpected o + else + args.attr <- o::args.attr + ) else ( + if List.mem o ["--attributes";"-atr"] then + have_atr := true + else + unexpected o + ) + ) args._others); args ) with diff --git a/tools/graphgen/graphGen_arg.mli b/tools/graphgen/graphGen_arg.mli index ec4612aac4e38a8267a1b93133af127c7780160b..70eda6d08b2c1ac7142cf488f2038518bc71acf3 100644 --- a/tools/graphgen/graphGen_arg.mli +++ b/tools/graphgen/graphGen_arg.mli @@ -28,6 +28,8 @@ type t = { mutable ba : ba_m; mutable qudg : qudg_arg; + mutable attr : string list; + mutable silent : bool; mutable _args : (string * Arg.spec * string) list; diff --git a/tools/scriptEnv.py b/tools/scriptEnv.py index 1e435bf75b5ef3c90152f9a1f3adb41e42a9b32f..c3028dbe26a7b69300a55caabb7dd4d5ef532c58 100644 --- a/tools/scriptEnv.py +++ b/tools/scriptEnv.py @@ -1,4 +1,4 @@ -import subprocess, os, datetime +import subprocess, os, datetime, math def call(command, log = None, verb = 2, options = {}): """Calls the shell command given in argument, and give its output in stdout as return value @@ -67,7 +67,7 @@ def genGraph(graphType, outputFile, options, is_silent = False, log = None, verb Args: graphType (str): The first argument given to 'gg', corresponding to the command in 'gg <command>'. - Use 'gg -h' in console to view the avaible commands (corresponding to avaible graphTypes). + Use 'gg -h' in console to view the available commands (corresponding to available graphTypes). outputFile (str): The output file given to 'gg' with the option '-o'. We strongly advice to give it a '.dot' extension graphProperties (dict): options given to 'call' function. @@ -250,49 +250,57 @@ def column(i, matrix, names = None): if names != None : i = names.index(i) return [x[i] for x in matrix] -class Project: +class FileManager: """Manage files of a project, to keep traces of a test battery. Inside a project directory, there will be a directory for each version (i.e. for each creation of a Project object). + + Proprieties : + path (str) : the path to the current version """ - def __init__(self, projectName = "sasaProject", date = True, time = True): + def __init__(self, projectName = "sasaProject", version_name = "", date = True, time = True, add_index = True): """Initialize a version of the project. Args : projectName (str) : The name of the project, in which a new version will be created. - date (bool, optional) : indicates if the version's name will contain the date - time (bool, optional) : indicates if the version's name will contain the time - - Note : if an old version has the same name as the new one, a number will be added to the new - version's name. + version_name (str, optional) : indicates the version's name base name + date (bool, optional) : indicates if the version's name will contain the date after the base name + time (bool, optional) : indicates if the version's name will contain the time after the date or base name + add_index (bool, optional) : indicates if the version's name will contain an index if a version of the same + name already exists (to ensure not to mix an old version with the new one). """ - self.name = projectName - identifyer = "" + self.name = projectName # the name of the project + version = version_name now = str(datetime.datetime.now()).split() + if version_name == "" and date: + version += "_" if date: - identifyer += now[0] + version += now[0] if date and time: - identifyer += "_" + version += "_" if time: - identifyer += now[1].split(".")[0] + version += now[1].split(".")[0] try: os.makedirs(projectName) except FileExistsError: pass - if os.path.exists(projectName+"/"+identifyer) : + if os.path.exists(projectName+"/"+version) and add_index : i = 0 - while os.path.exists(projectName+"/"+identifyer+"_"+str(i)):i += 1 - identifyer += "_"+str(i) + while os.path.exists(projectName+"/"+version+"_"+str(i)):i += 1 + version += "_"+str(i) - os.makedirs(projectName+"/"+identifyer) - self.identifyer = identifyer - self.path = projectName+"/"+identifyer+"/" - self.folders = [] + try : + os.makedirs(projectName+"/"+version) + except FileExistsError: + if add_index : raise + + self.version = version # the name of the version + self.path = projectName+"/"+version+"/" # the path to the version def createDir (self, dir): """Creates the directory dir in the current version if it doesn't exist. @@ -309,8 +317,8 @@ class Project: except FileExistsError: return False - def open(self, dir, name, ext): - """Opens a new file in the directory dir of the current version. + def open(self, dir, name, ext, openType = 'w+', add_index = True): + """Use the built-in function open() to open a file in the directory 'dir' of the current version. The actual name of the file is 'name_i.ext', with name and ext being the arguments of the same name, and i being the lower number such as no other file has the same name. @@ -319,9 +327,15 @@ class Project: dir (str) : the name of the directory in which the file will be created. Creates it if it doesn't exists. name (str) : the name of the file, without extension. ext (str) : the extension of the file. If it doesn't start by a point ('.'), it will be added. + openType (str, optional) : the second argument given to the built-in function open(). + Note that if add_index is set to False and the file already exists, + 'w'/'w+' will overwrite the file, whereas 'a'/'a+' and 'r' will not. + add_index (bool, optional) : indicates if an index will be given to the file's name. + Set it to True if you want to ensure that the opened file is a new file. + Return value : - The opened file (same as "open(path)") if getIndex is False + The opened file (same as "open(path)") """ @@ -337,7 +351,7 @@ class Project: return f - def add_file(self, dir, name, ext, content = ""): + def add_file(self, dir, name, ext, content = "", add_index = True): """Creates a new file in the directory dir of the current version. The actual name of the file is 'name_i.ext', with name and ext being the arguments of the same name, @@ -346,8 +360,11 @@ class Project: Args : dir (str) : the name of the directory in which the file will be created. Creates it if it doesn't exists. name (str) : the name of the file, without extension. - ext (str) : the extension of the file. If it doesn't start by a point ('.'), it will be added. + ext (str) : the extension of the file. content (str, optional) : a string that will be added automatically to the file on creation. + add_index (bool, optional) : indicates if an index will be given to the file's name. + Set it to True if you want to ensure that no file of the same name + is overwritten on creation. Return value : The path to the created file @@ -356,7 +373,7 @@ class Project: self.createDir(dir) i = 0 path = self.path + dir + "/" + name - if ext != "" and ext[0] != ".": ext = "."+ext + #if ext != "" and ext[0] != ".": ext = "."+ext while os.path.exists(path + "_" + str(i) + ext):i += 1 path += "_"+str(i)+ ext @@ -369,7 +386,8 @@ class Project: return path def open_i(self, i, dir, name, ext, openType = 'a'): - """Opens a file in dir with the name 'name_i.ext'. + """Opens a file in dir with the name 'name_i.ext'. + (The point between 'i' and 'ext' is for readability, and is not added by the method.) Note : Use it to modify a file created previously, not to create a file at index i unless you are sure of what you are doing @@ -384,8 +402,13 @@ class Project: self.createDir(dir) return open(self.path + dir + "/" + name + "_" + str(i) + ext, openType) + def read_i(self, i, dir, name, ext): + f = open_i(self, i, dir, name, ext, "r") + return f.read() + def exist_i(self, i, dir, name, ext): - """Checks if the file 'name_i.ext' exists in dir.""" + """Checks if the file 'name_i.ext' exists in dir. + (The point between 'i' and 'ext' is for readability, and is not added by the method.)""" return os.path.exists(self.path + dir + "/" + name + "_" + str(i) + ext) @@ -405,3 +428,12 @@ class Project: i = 0 while os.path.exists(self.path + dir + "/" + name + "_" + str(i) + ext): i += 1 return i - 1 + +class UDGtools(object): + """A set of tools to use UDG""" + @property # so that UDGtools() gives an error + def __init__(self):pass + + @staticmethod + def getRadius(n, h, w, md): + math.sqrt(h * w * md / (math.pi * n))