Example #1
0
def test_prime_power_hash_examples():
    # Tests that two C-shaped prime power graphs are equivalent
    prime, power = 2, 2
    e1 = [((0, 1), (1, 1), 1), ((1, 0), (0, 0), 1), ((0, 0), (0, 1), 1)]
    e2 = [((0, 1), (1, 1), 1), ((1, 0), (0, 0), 1), ((1, 0), (1, 1), 1)]
    g1 = create_prime_power_graph(e1, prime, power)
    g2 = create_prime_power_graph(e2, prime, power)
    assert hash_graph(g1) == hash_graph(g2)

    # Tests upper ququart bar and lower ququart bar inequivalent
    e1 = [((1, 0), (0, 0), 1)]
    e2 = [((0, 1), (1, 1), 1)]
    g1 = create_prime_power_graph(e1, prime, power)
    g2 = create_prime_power_graph(e2, prime, power)
    assert hash_graph(g1) == hash_graph(g2)

    # Tests both ququart zigzags are equivalent
    e1 = [((0, 1), (1, 1), 1), ((1, 0), (0, 0), 1), ((0, 0), (1, 1), 1)]
    e2 = [((0, 1), (1, 1), 1), ((1, 0), (0, 0), 1), ((0, 1), (1, 0), 1)]
    g1 = create_prime_power_graph(e1, prime, power)
    g2 = create_prime_power_graph(e2, prime, power)
    assert hash_graph(g1) == hash_graph(g2)

    # Checks two-bar and rotated two-bar ququarts are inequivalent
    e1 = [((0, 1), (1, 1), 1), ((0, 0), (1, 0), 1)]
    e2 = [((0, 0), (0, 1), 1), ((1, 0), (1, 1), 1)]
    g1 = create_prime_power_graph(e1, prime, power)
    g2 = create_prime_power_graph(e2, prime, power)
    assert hash_graph(g1) == hash_graph(g2)
Example #2
0
def queued_orbit_search(init_graph, local_ops, save_edges, verbose):
    # Initialises class graph with init_graph
    init_edges = list(init_graph.edges())
    init_hash = hash_graph(init_graph)
    class_graph = nx.Graph()
    class_graph.add_node(0,
                         nx_graph=init_graph,
                         edges=init_edges,
                         hash=init_hash)
    class_graph.member_hash_table = {init_hash: 0}
    # Loops over queue members until empty
    queue = [0]
    visited = 0
    while queue:
        # Prints live count of explored/known
        if verbose:
            out = \
                str(visited) + '/' + str(len(queue) + visited) + ' visited (' \
                + str(int(100 * float(visited)/(len(queue) + visited))) + '%)'
            sys.stdout.write('%s\r' % out)
            sys.stdout.flush()
        visited += 1
        # Gets next graph on queue and finds representative nodes
        graph_label = queue.pop()
        graph = class_graph.node[graph_label]['nx_graph']
        node_equivs = find_rep_nodes(graph)
        # Applies set of local ops to each representative node
        for rep_node, equiv_nodes in node_equivs.iteritems():
            for op_label, local_op in local_ops:
                new_graph = local_op(graph, rep_node)
                new_edges = list(new_graph.edges())
                new_hash = hash_graph(new_graph)
                # Checks new graph is difference to original
                if sorted(new_graph.edges(data='weight')) == \
                        sorted(graph.edges(data='weight')):
                    continue
                # If different, tries to find new graph in class
                try:
                    old_label = class_graph.member_hash_table[new_hash]
                    if save_edges:
                        # If new edge adds new edge between members
                        if not class_graph.has_edge(graph_label, old_label):
                            class_graph.add_edge(graph_label,
                                                 old_label,
                                                 equivs=[equiv_nodes],
                                                 ops=[op_label])
                        # Else adds any new local ops to edge label
                        elif op_label not in \
                                class_graph[graph_label][old_label]['ops']:
                            class_graph[graph_label][old_label]['ops']\
                                .append(op_label)
                            class_graph[graph_label][old_label]['equivs']\
                                .append(equiv_nodes)
                    continue
                # If not in class, creates new class graph node
                except KeyError:
                    new_label = max(class_graph.nodes()) + 1
                    class_graph.add_node(new_label,
                                         nx_graph=new_graph,
                                         edges=new_edges,
                                         hash=new_hash)
                    if save_edges:
                        class_graph.add_edge(graph_label,
                                             new_label,
                                             equivs=[equiv_nodes],
                                             ops=[op_label])
                    class_graph.member_hash_table.update({new_hash: new_label})
                    queue.append(new_label)
    return class_graph
Example #3
0
def test_hash_graph():
    for _ in range(100):
        g = gen_random_connected_graph(10)
        relab_g = random_relabel(g)
        assert hash_graph(g) == hash_graph(relab_g)
Example #4
0
def find_all_classes(directory, power, prime):
    """ Finds all members of all classes """
    # Gets edge indices and state params and generates edge map
    filename = directory + '/edge_index.csv'
    with open(filename, 'r') as file:
        reader = csv.reader(file)
        edge_index = [tuple(map(int, edge)) for edge in reader]
    filename = directory + '/state_params.csv'
    with open(filename, 'r') as file:
        reader = csv.reader(file)
        p, m, n = map(int, next(reader))
    c_map = gen_psuedo_graph_edge_map(p, m)
    # Creates function to produce config isomorphs
    isomorph_configs = make_isomorph_func(edge_index, n)
    pprint(c_map)
    pprint(edge_index)
    # Initialises progress bar
    rg_file = directory + '/remaining_graphs.csv'
    rem_graphs_size = os.path.getsize(rg_file)
    pbar = tqdm(total=rem_graphs_size)
    while True:
        rem_update = rem_graphs_size - os.path.getsize(rg_file)
        if rem_update >= 0:
            pbar.update(rem_update)
        rem_graphs_size = os.path.getsize(rg_file)
        # Waits until a graph is available to process
        edge_config = get_next_graph(directory)
        if not edge_config:
            break
        tqdm.write("Psuedo edge config: %s" % (edge_config, ))
        # Create initial graph
        c_edges = [(u, v, w) for (u, v), w in zip(edge_index, edge_config)]
        init_graph = create_psuedo_graph(c_edges, p, m, c_map)
        # Checks if graph is connected
        if not nx.is_connected(init_graph.to_undirected()):
            tqdm.write("Disconnected. Removing isomorphs... ")
            # Removes any isomorphic graphs from remaining
            remove_disconnected_configs(directory, edge_config,
                                        isomorph_configs)
            tqdm.write("Done")
            continue
        init_graph = psuedo_to_real(init_graph)
        # Check if graph has already been found for hash test
        graph_hash = hash_graph(init_graph)
        if found_hash(directory, graph_hash):
            tqdm.write("Already found %d" % graph_hash)
            iso_configs = isomorph_configs(edge_config)
            remove_found_graphs(directory, iso_configs)
            continue
        # Explore class graph
        tqdm.write("Exploring class...")
        class_graph = explore_lc_orbit(init_graph, False, False)
        class_register = [[
            node, attrs['edges'], attrs['hash'], attrs['nx_graph']
        ] for node, attrs in class_graph.node.iteritems()]
        nodes, edges, hashes, graphs = zip(*class_register)
        # Formats edge list based on state parameters
        if power == 1:
            edges = [[(u, v, c) for (u, i), (v, j), c in edge_set]
                     for edge_set in edges]
        if prime == 2:
            edges = [[(u, v) for u, v, c in edge_set] for edge_set in edges]
        # Exports class_register to file
        tqdm.write("Writing register to file...")
        class_register = zip(nodes, edges, hashes)
        config_label = '_'.join(map(str, edge_config))
        filename = directory + '/classes/' + config_label + '.csv'
        with open(filename, 'w') as csvfile:
            writer = csv.writer(csvfile)
            writer.writerows(class_register)
        # Finds and removes any isomorphs
        tqdm.write("Removing isomorphs...")
        psu_edges = [
            real_graph_to_psu_edges(graph, c_map, edge_index)
            for graph in graphs
        ]
        edge_configs = [[c for u, v, c in w_edges] for w_edges in psu_edges]
        iso_configs = [
            iso_config for config in edge_configs
            for iso_config in isomorph_configs(config)
        ]
        remove_found_graphs(directory, iso_configs)
        # Adds hashes to found hash directory
        write_hashes(directory, hashes)
        tqdm.write("Done")
    pbar.close()