def test_crazy_linear_graph_builder():
    """ Tests a 10-node crazy linear graph correctly built """
    l, n = 5, 3
    g = linear_graph(l)
    cg = make_crazy(g, n)
    cg_nodes, cg_edges = process_graph_nodes_edges(cg)
    nodes = {(i, 0): [((i, 0), j) for j in range(n)] for i in range(l)}
    edges = [((i, 0), (i + 1, 0)) for i in range(l - 1)]
    edges = sorted(flatten([it.product(nodes[u], nodes[v])
                            for u, v in edges]))
    nodes = sorted(flatten(nodes.values()))
    assert cg_nodes == nodes
    assert cg_edges == edges
Beispiel #2
0
def make_crazy(graph, n):
    """ Converts a graph into it's crazily encoded version """
    # Defines groupings of crazy nodes and edges between them
    crazy_nodes = {node: [(node, i) for i in range(n)]
                   for node in graph.nodes()}
    crazy_edges = flatten([it.product(crazy_nodes[u], crazy_nodes[v])
                           for u, v in graph.edges()])
    # Creates graph and adds edges and nodes
    crazy_graph = nx.Graph()
    crazy_graph.add_nodes_from(flatten(crazy_nodes.values()))
    crazy_graph.add_edges_from(crazy_edges)
    # Assigns encoded attribute for to_GraphState
    crazy_graph.encoded = True
    return crazy_graph
Beispiel #3
0
def square_lattice(n, m, boundary=True):
    """ Creates a square lattice with 2D coordinates """
    mod_n = n + 1 if boundary else n
    mod_m = m + 1 if boundary else m
    g = nx.Graph()
    nodes = list(it.product(range(n), range(m)))
    edges = flatten([[((i, j), ((i + 1) % mod_n, j)),
                      ((i, j), (i, (j + 1) % mod_m))] for i, j in nodes])
    edges = [((u_x, u_y), (v_x, v_y)) for (u_x, u_y), (v_x, v_y) in edges
             if max([u_x, v_x]) < n and max([u_y, v_y]) < m]
    g.add_edges_from(edges)
    return g
Beispiel #4
0
def make_ghz_like(graph, n):
    """ Converts a graph into it's GHZ-encoded version """
    # Defines groupings of GHZ-like nodes and edges between them
    ghz_nodes = {node: [(node, i) for i in range(n)] for node in graph.nodes()}
    ghz_edges = [((u, 0), (v, 0)) for u, v in graph.edges()] + \
        [((node, 0), (node, i)) for node in graph.nodes() for i in range(1, n)]
    # Creates graph and adds edges and nodes
    ghz_graph = nx.Graph()
    ghz_graph.add_nodes_from(flatten(ghz_nodes.values()))
    ghz_graph.add_edges_from(ghz_edges)
    # Assigns encoded attribute for to_GraphState
    ghz_graph.encoded = True
    return ghz_graph
Beispiel #5
0
def are_lc_equiv(g1, g2):
    """
        Tests whether two graphs are equivalent up to local complementation.
        If True, also returns every unitary such that |g2> = U|g1>.
    """
    # Gets adjacency matrices and returns false if differing bases
    am1, k1 = get_adjacency_matrix(g1)
    am2, k2 = get_adjacency_matrix(g2)
    dim1, dim2 = len(k1), len(k2)
    if k1 != k2 or am1.shape != (dim1, dim1) or am2.shape != (dim2, dim2):
        return False, None
    # Defines binary matrices
    Id = sp.eye(dim1)
    S1 = sp.Matrix(am1).col_join(Id)
    S2 = sp.Matrix(am2).col_join(Id)
    # Defines symbolic variables
    A = sp.symbols('a:' + str(dim1), bool=True)
    B = sp.symbols('b:' + str(dim1), bool=True)
    C = sp.symbols('c:' + str(dim1), bool=True)
    D = sp.symbols('d:' + str(dim1), bool=True)
    # Defines solution matrix basis
    abcd = flatten(list(zip(A, B, C, D)))
    no_vars = len(abcd)
    no_qubits = no_vars // 4
    # Creates symbolic binary matrix
    A, B, C, D = sp.diag(*A), sp.diag(*B), sp.diag(*C), sp.diag(*D)
    Q = A.row_join(B).col_join(C.row_join(D))
    P = sp.zeros(dim1).row_join(Id).col_join(Id.row_join(sp.zeros(dim1)))
    # Constructs matrix to solve
    X = [i for i in S1.T * Q.T * P * S2]
    X = np.array([[x.coeff(v) for v in abcd] for x in X], dtype=int)
    # Removes any duplicated and all-zero rows
    X = np.unique(X, axis=0)
    X = X[~(X == 0).all(1)]
    # Finds the solutions (the nullspace of X)
    V = list(GF2nullspace(X))
    if len(V) > 4:
        V = [(v1 + v2) % 2 for v1, v2 in it.combinations(V, 2)]
    else:
        V = [sum(vs) % 2 for vs in powerset(V)]
    V = [np.reshape(v, (no_qubits, 4)) for v in V]
    V = [v for v in V if all((a * d + b * c) % 2 == 1 for a, b, c, d in v)]
    if V:
        V = [[bin2gate[tuple(r)] for r in v] for v in V]
        return True, V
    else:
        return False, None