def start_coloring(filename, td, cfgfile, output): m = ccalgorithm_factory(cfgfile, False, None) p, fn = os.path.split(filename) graphname, e = os.path.splitext(fn) col = m.start(load_graph(filename), td) # Store results in common folder and, if supplied, in output file save_file(col, 'colorings/' + graphname + str(td), False) if output: save_file(col, output, True)
def start_coloring(filename, td, cfgfile, output): m = ccalgorithm_factory(cfgfile, False) p, fn = os.path.split(filename) graphname, e = os.path.splitext(fn) col = m.start(load_graph(filename), td) # Store results in common folder and, if supplied, in output file save_file(col, 'colorings/' + graphname + str(td), False) if output: save_file(col, output, True)
def get_pattern_from_file(filename): """ Load pattern from a file :param filename: The name of the pattern file :return: A graph object representing the pattern along with its treedepth """ # Argument is a filename try: # Try to load the graph from file H = load_graph(filename) # Return pattern along with lower bound on its treedepth return H, treedepth(H) except Exception: # Invalid file extension pattern_argument_error_msg(filename)
for v in cols: f.write(str(v)+': '+str(cols[v])+'\n') f.close() if __name__=="__main__": parser = argparse.ArgumentParser() parser.add_argument("graph", help="A graph in any supported format " "(see graphformats.py)") parser.add_argument("colors", help="A vertex coloring file") parser.add_argument("p", help="the number of color classes that yield " "low-td components, i.e. the coloring is (p+1)-" "centered coloring", type=int) args = parser.parse_args() graph = load_graph(args.graph) remove_loops(graph) cols = load_coloring(args.colors) p = args.p print "Loaded {0} and coloring {1} ({2} colors)".format(args.graph, args.colors, len(cols)) res = cols.is_proper(graph) and check_tree_depth(graph, graph, cols, p) print "{0}-centered coloring: {1}".format(p+1, res) print "" optcols = merge_colors(graph, cols, p) size = len(optcols) print "Best coloring found has size", size
def parse_pattern_argument(pattern): """ Parses the 'pattern' command line argument. Checks to see if this argument is a filename or a description of the pattern :param pattern: Filename or description of pattern :return: A tuple with the pattern graph and a lower bound on its treedepth """ import os # Get the name of the file and the file extension name, ext = os.path.splitext(pattern) # There is no extension, so argument is a description # of the pattern if ext == "": import re p = re.compile(r'(\d*)') # Parse out the different parts of the argument args = filter(lambda x: x != "" and x != ",", p.split(pattern)) # There are two parts if len(args) == 2 and args[0] not in pattern_gen.bipartite_patterns: try: # Get the generator for the pattern type generator = pattern_gen.get_generator(args[0]) # Get the number of vertices provided pattern_num_vertices = int(args[1]) # Generate the pattern H = generator(pattern_num_vertices) # Return the pattern along with its treedepth return H, treedepth(H, args[0], pattern_num_vertices) except KeyError: pattern_argument_error_msg() # Bipartite pattern type provided elif len(args) == 3 and args[0] in pattern_gen.bipartite_patterns: # Make sure it is a valid bipartite pattern try: generator = pattern_gen.get_generator(args[0]) # Try to get the two set sizes m = int(args[1]) n = int(args[2]) # Generate the pattern H = generator(m, n) # Return the pattern along with its treedepth return H, treedepth(H, args[0], m, n) except (KeyError, ValueError): # Invalid sizes provided pattern_argument_error_msg() else: # Number of vertices not provided in argument pattern_argument_error_msg() else: # Argument is a filename try: # Try to load the graph from file H = load_graph(pattern) # Return pattern along with lower bound on its treedepth return H, treedepth(H) except Exception: # Invalid file extension pattern_argument_error_msg()
def runPipeline(graph, pattern, cfgFile, colorFile, color_no_verify, output, verbose, profile): """Basic running of the pipeline""" if profile: # time profiling readProfile = cProfile.Profile() readProfile.enable() H, td_lower = parse_pattern_argument(pattern) # Read graphs from file G = load_graph(graph) td = len(H) G_path, G_local_name = os.path.split(graph) G_name, G_extension = os.path.splitext(G_local_name) if verbose: print "G has {0} vertices and {1} edges".format(len(G), G.num_edges()) if profile: # time profiling readProfile.disable() printProfileStats("reading graphs", readProfile) colorProfile = cProfile.Profile() colorProfile.enable() # Find p-centered coloring if colorFile is None: coloring = p_centered_coloring(G, td, cfgFile, verbose) save_file(coloring, 'colorings/' + G_name + str(td), False, verbose) else: coloring = coloring_from_file(colorFile, G, td, cfgFile, verbose, not color_no_verify) if profile: # time profiling colorProfile.disable() printProfileStats("coloring", colorProfile) patternProfile = cProfile.Profile() patternProfile.enable() # Get configuration settings for dynamic programming cfgParser = parse_config_safe(cfgFile) kpat_name = cfgParser.get('compute', 'k_pattern') # tab_name = cfgParser.get('dp', 'tab') table_hints = { 'forward': cfgParser.getboolean('compute', 'table_forward'), 'reuse': cfgParser.getboolean('compute', 'table_reuse') } count_name = cfgParser.get('combine', 'count') sweep_name = cfgParser.get('decompose', 'sweep') patternClass = import_modules("lib.pattern_counting.dp."+kpat_name) count_class = import_modules('lib.pattern_counting.double_count.' + count_name) sweep_class = import_modules('lib.decomposition.' + sweep_name) # Count patterns pattern_counter = PatternCounter(G, H, td_lower, coloring, pattern_class=patternClass, table_hints=table_hints, decomp_class=sweep_class, combiner_class=count_class, verbose=verbose) patternCount = pattern_counter.count_patterns() print "Number of occurrences of H in G: {0}".format(patternCount) if profile: # time profiling patternProfile.disable() printProfileStats("pattern counting", patternProfile)
def runPipeline(graph, pattern, cfgFile, colorFile, color_no_verify, output, verbose, profile, multifile, execution_data): """Basic running of the pipeline""" # Check if execution_data flag is set execdata = execution_data is not None if execdata and pattern == "multi": print "CONCUSS does not support outputting execution data while using the multi-motif flag" sys.exit(1) if execdata: # Check if directory exists already if os.path.isdir("./execdata"): # delete it, if it does exist shutil.rmtree("./execdata") # make new directory called "execdata" os.mkdir("./execdata") if profile: # time profiling readProfile = cProfile.Profile() readProfile.enable() # Parse the multifile if counting multiple patterns if pattern == 'multi': multi, td_list = parse_multifile(multifile) # Parse pattern argument else: basic_pattern = is_basic_pattern(pattern) if basic_pattern: H, td_lower = get_pattern_from_generator(pattern) else: H, td_lower = get_pattern_from_file(pattern) multi = [H] td_list = [td_lower] # Read graphs from file G = load_graph(graph) td = len(max(multi, key=len)) G_path, G_local_name = os.path.split(graph) G_name, G_extension = os.path.splitext(G_local_name) if verbose: print "G has {0} vertices and {1} edges".format(len(G), G.num_edges()) if profile: # time profiling readProfile.disable() printProfileStats("reading graphs", readProfile) colorProfile = cProfile.Profile() colorProfile.enable() # Find p-centered coloring if colorFile is None: coloring = p_centered_coloring(G, td, cfgFile, verbose, execdata) save_file(coloring, 'colorings/' + G_name + str(td), False, verbose) else: coloring = coloring_from_file(colorFile, G, td, cfgFile, verbose, not color_no_verify) if profile: # time profiling colorProfile.disable() printProfileStats("coloring", colorProfile) patternProfile = cProfile.Profile() patternProfile.enable() # Get configuration settings for dynamic programming cfgParser = parse_config_safe(cfgFile) kpat_name = cfgParser.get('compute', 'k_pattern') # tab_name = cfgParser.get('dp', 'tab') table_hints = { 'forward': cfgParser.getboolean('compute', 'table_forward'), 'reuse': cfgParser.getboolean('compute', 'table_reuse') } count_name = cfgParser.get('combine', 'count') sweep_name = cfgParser.get('decompose', 'sweep') patternClass = import_modules("lib.pattern_counting.dp." + kpat_name) count_class = import_modules('lib.pattern_counting.double_count.' + count_name) sweep_class = import_modules('lib.decomposition.' + sweep_name) # Output for Count stage if execdata: count_path = 'execdata/count/' if not os.path.exists(count_path): os.makedirs(count_path) big_component_file = open(count_path+'big_component.txt', 'w') tdd_file = open(count_path+'tdd.txt', 'w') dp_table_file = open(count_path+'dp_table.txt', 'w') else: big_component_file = None tdd_file = None dp_table_file = None # Output for Combine stage if execdata: combine_path = 'execdata/combine/' if not os.path.exists(combine_path): os.makedirs(combine_path) # Open the file that needs to be passed to the count combiner colset_count_file = open('execdata/combine/counts_per_colorset.txt', 'w') else: # If execution data is not requested, we don't need to open a file colset_count_file = None if count_name != "InclusionExclusion" and execdata: print "CONCUSS can only output execution data using the", print "InclusionExclusion combiner class." # Check if there is incomplete execution data written if os.path.isdir("./execdata"): # delete it, if it does exist shutil.rmtree("./execdata") # Exit the program with an error code of 1 sys.exit(1) pattern_counter = PatternCounter(G, multi, td_list, coloring, pattern_class=patternClass, table_hints=table_hints, decomp_class=sweep_class, combiner_class=count_class, verbose=verbose, big_component_file=big_component_file, tdd_file=tdd_file, dp_table_file=dp_table_file, colset_count_file=colset_count_file) pattern_count = pattern_counter.count_patterns() # Patterns have been counted, print output if pattern == "multi": with open(multifile[0], 'r') as pattern_file: pattern_names = [pat[:-1] for pat in pattern_file] else: pattern_names = [pattern] for i in range(len(pattern_names)): print "Number of occurrences of {0} in G: {1}".format(pattern_names[i], pattern_count[i]) if execdata: # Close count stage files big_component_file.close() tdd_file.close() dp_table_file.close() # Close the color set file colset_count_file.close() # if execution data flag is set # make and write to visinfo.cfg with open('execdata/visinfo.cfg', 'w') as visinfo: write_visinfo(visinfo, graph, pattern) # write execution data to zip with ZipFile(execution_data, 'w') as exec_zip: # exec_zip.write("execdata/visinfo.cfg", "visinfo.cfg") # Write data from 'execdata' directory to the zip: rootDir = './execdata/' for dir_name, _, file_list in os.walk(rootDir): for f_name in file_list: full_path = dir_name + '/' + f_name exec_zip.write( full_path, '/'.join(full_path.split('/')[2:])) exec_zip.write(cfgFile, os.path.split(cfgFile)[1]) exec_zip.write(graph, os.path.split(graph)[1]) # Check to see if the user specified a basic pattern if basic_pattern: from lib.graph.graphformats import write_edgelist # Write the pattern graph object to a file as an edgelist with open(pattern + '.txt', 'w') as pattern_file: write_edgelist(H, pattern_file) # Write the file to the zip exec_zip.write( pattern + '.txt', os.path.split(pattern + '.txt')[1]) # File written to zip, delete it os.remove(pattern + '.txt') else: exec_zip.write(pattern, os.path.split(pattern)[1]) # delete execution data stored in folder shutil.rmtree('./execdata') if profile: # time profiling patternProfile.disable() printProfileStats("pattern counting", patternProfile)
def parse_pattern_argument(pattern): """ Parses the 'pattern' command line argument. Checks to see if this argument is a filename or a description of the pattern :param pattern: Filename or description of pattern :return: A tuple with the pattern graph and a lower bound on its treedepth """ # Get the name of the file and the file extension name, ext = os.path.splitext(pattern) # There is no extension, so argument is a description # of the pattern if ext == "": import re p = re.compile(r'(\d*)') # Parse out the different parts of the argument args = filter(lambda x: x != "" and x != ",", p.split(pattern)) # There are two parts if len(args) == 2 and args[0] not in pattern_gen.bipartite_patterns: try: # Get the generator for the pattern type generator = pattern_gen.get_generator(args[0]) # Get the number of vertices provided pattern_num_vertices = int(args[1]) # Generate the pattern H = generator(pattern_num_vertices) # Return the pattern along with its treedepth return H, treedepth(H, args[0], pattern_num_vertices) except KeyError: pattern_argument_error_msg(pattern) # Bipartite pattern type provided elif len(args) == 3 and args[0] in pattern_gen.bipartite_patterns: # Make sure it is a valid bipartite pattern try: generator = pattern_gen.get_generator(args[0]) # Try to get the two set sizes m = int(args[1]) n = int(args[2]) # Generate the pattern H = generator(m, n) # Return the pattern along with its treedepth return H, treedepth(H, args[0], m, n) except (KeyError, ValueError): # Invalid sizes provided pattern_argument_error_msg(pattern) else: # Number of vertices not provided in argument pattern_argument_error_msg(pattern) else: # Argument is a filename try: # Try to load the graph from file H = load_graph(pattern) # Return pattern along with lower bound on its treedepth return H, treedepth(H) except Exception: # Invalid file extension pattern_argument_error_msg(pattern)
def cycle(num_vertices): """ Compute the lower bound on treedepth of a cycle. :param num_vertices: Tuple containing number of elements :return: the treedepth """ # return lower bound return int(ceil(log(num_vertices[0], 2))) + 1 def biclique(num_vertices): """ Compute the lower bound on treedepth of a clique. :param num_vertices: 2-Tuple containing number of elements in first and second set :return: the treedepth """ # The treedepth of a biclique is the number of nodes in # the smaller set + 1 return min(num_vertices[0], num_vertices[1]) + 1 if __name__ == "__main__": G = load_graph(sys.argv[1]) print treedepth(G)
def runPipeline( graph, pattern, cfgFile, colorFile, color_no_verify, output, verbose, profile, multifile, execution_data ): """Basic running of the pipeline""" # Check if execution_data flag is set execdata = execution_data is not None if execdata and pattern == "multi": print "CONCUSS does not support outputting execution data while using the multi-motif flag" sys.exit(1) if execdata: # Check if directory exists already if os.path.isdir("./execdata"): # delete it, if it does exist shutil.rmtree("./execdata") # make new directory called "execdata" os.mkdir("./execdata") if profile: # time profiling readProfile = cProfile.Profile() readProfile.enable() # Parse the multifile if counting multiple patterns if pattern == "multi": multi, td_list = parse_multifile(multifile) # Parse pattern argument else: basic_pattern = is_basic_pattern(pattern) if basic_pattern: H, td_lower = get_pattern_from_generator(pattern) else: H, td_lower = get_pattern_from_file(pattern) multi = [H] td_list = [td_lower] # Read graphs from file G = load_graph(graph) td = len(max(multi, key=len)) G_path, G_local_name = os.path.split(graph) G_name, G_extension = os.path.splitext(G_local_name) if verbose: print "G has {0} vertices and {1} edges".format(len(G), G.num_edges()) if profile: # time profiling readProfile.disable() printProfileStats("reading graphs", readProfile) colorProfile = cProfile.Profile() colorProfile.enable() # Find p-centered coloring if colorFile is None: coloring = p_centered_coloring(G, td, cfgFile, verbose, execdata) save_file(coloring, "colorings/" + G_name + str(td), False, verbose) else: coloring = coloring_from_file(colorFile, G, td, cfgFile, verbose, not color_no_verify) if profile: # time profiling colorProfile.disable() printProfileStats("coloring", colorProfile) patternProfile = cProfile.Profile() patternProfile.enable() # Get configuration settings for dynamic programming cfgParser = parse_config_safe(cfgFile) kpat_name = cfgParser.get("compute", "k_pattern") # tab_name = cfgParser.get('dp', 'tab') table_hints = { "forward": cfgParser.getboolean("compute", "table_forward"), "reuse": cfgParser.getboolean("compute", "table_reuse"), } count_name = cfgParser.get("combine", "count") sweep_name = cfgParser.get("decompose", "sweep") patternClass = import_modules("lib.pattern_counting.dp." + kpat_name) count_class = import_modules("lib.pattern_counting.double_count." + count_name) sweep_class = import_modules("lib.decomposition." + sweep_name) # Output for Count stage if execdata: count_path = "execdata/count/" if not os.path.exists(count_path): os.makedirs(count_path) big_component_file = open(count_path + "big_component.txt", "w") tdd_file = open(count_path + "tdd.txt", "w") dp_table_file = open(count_path + "dp_table.txt", "w") else: big_component_file = None tdd_file = None dp_table_file = None # Output for Combine stage if execdata: combine_path = "execdata/combine/" if not os.path.exists(combine_path): os.makedirs(combine_path) # Open the file that needs to be passed to the count combiner colset_count_file = open("execdata/combine/counts_per_colorset.txt", "w") else: # If execution data is not requested, we don't need to open a file colset_count_file = None if count_name != "InclusionExclusion" and execdata: print "CONCUSS can only output execution data using the", print "InclusionExclusion combiner class." # Check if there is incomplete execution data written if os.path.isdir("./execdata"): # delete it, if it does exist shutil.rmtree("./execdata") # Exit the program with an error code of 1 sys.exit(1) pattern_counter = PatternCounter( G, multi, td_list, coloring, pattern_class=patternClass, table_hints=table_hints, decomp_class=sweep_class, combiner_class=count_class, verbose=verbose, big_component_file=big_component_file, tdd_file=tdd_file, dp_table_file=dp_table_file, colset_count_file=colset_count_file, ) pattern_count = pattern_counter.count_patterns() # Patterns have been counted, print output if pattern == "multi": with open(multifile[0], "r") as pattern_file: pattern_names = [pat[:-1] for pat in pattern_file] else: pattern_names = [pattern] for i in range(len(pattern_names)): print "Number of occurrences of {0} in G: {1}".format(pattern_names[i], pattern_count[i]) if execdata: # Close count stage files big_component_file.close() tdd_file.close() dp_table_file.close() # Close the color set file colset_count_file.close() # if execution data flag is set # make and write to visinfo.cfg with open("execdata/visinfo.cfg", "w") as visinfo: write_visinfo(visinfo, graph, pattern) # write execution data to zip with ZipFile(execution_data, "w") as exec_zip: # exec_zip.write("execdata/visinfo.cfg", "visinfo.cfg") # Write data from 'execdata' directory to the zip: rootDir = "./execdata/" for dir_name, _, file_list in os.walk(rootDir): for f_name in file_list: full_path = dir_name + "/" + f_name exec_zip.write(full_path, "/".join(full_path.split("/")[2:])) exec_zip.write(cfgFile, os.path.split(cfgFile)[1]) exec_zip.write(graph, os.path.split(graph)[1]) # Check to see if the user specified a basic pattern if basic_pattern: from lib.graph.graphformats import write_edgelist # Write the pattern graph object to a file as an edgelist with open(pattern + ".txt", "w") as pattern_file: write_edgelist(H, pattern_file) # Write the file to the zip exec_zip.write(pattern + ".txt", os.path.split(pattern + ".txt")[1]) # File written to zip, delete it os.remove(pattern + ".txt") else: exec_zip.write(pattern, os.path.split(pattern)[1]) # delete execution data stored in folder shutil.rmtree("./execdata") if profile: # time profiling patternProfile.disable() printProfileStats("pattern counting", patternProfile)