Exemple #1
0
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)
Exemple #2
0
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)
Exemple #3
0
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)
Exemple #4
0
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)
Exemple #5
0
    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
Exemple #6
0
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()
Exemple #7
0
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)
Exemple #8
0
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)
Exemple #9
0
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)
Exemple #10
0
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)
Exemple #11
0
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)
Exemple #12
0
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)