def test_wires_to_edges(self): """Test that wires_to_edges returns the correct mapping""" g = nx.lollipop_graph(4, 1) r = wires_to_edges(g) assert r == { 0: (0, 1), 1: (0, 2), 2: (0, 3), 3: (1, 2), 4: (1, 3), 5: (2, 3), 6: (3, 4) }
def test_wires_to_edges_directed(self): """Test that wires_to_edges returns the correct mapping on a directed graph""" g = nx.lollipop_graph(4, 1).to_directed() r = wires_to_edges(g) assert r == { 0: (0, 1), 1: (0, 2), 2: (0, 3), 3: (1, 0), 4: (1, 2), 5: (1, 3), 6: (2, 0), 7: (2, 1), 8: (2, 3), 9: (3, 0), 10: (3, 1), 11: (3, 2), 12: (3, 4), 13: (4, 3), }
def test_cycle_mixer(self): """Test if the cycle_mixer Hamiltonian maps valid cycles to valid cycles""" n_nodes = 3 g = nx.complete_graph(n_nodes).to_directed() m = wires_to_edges(g) n_wires = len(g.edges) # Find Hamiltonian and its matrix representation h = cycle_mixer(g) h_matrix = np.real_if_close(matrix(h, n_wires).toarray()) # Decide which bitstrings are valid and which are invalid valid_bitstrings_indx = [] invalid_bitstrings_indx = [] for indx, bitstring in enumerate( itertools.product([0, 1], repeat=n_wires)): wires = [i for i, bit in enumerate(bitstring) if bit == 1] edges = [m[wire] for wire in wires] flows = [0 for i in range(n_nodes)] for start, end in edges: flows[start] += 1 flows[end] -= 1 # A bitstring is valid if the net flow is zero and we aren't the empty set or the set of all # edges. Note that the max out-flow constraint is not imposed, which means we can pass # through nodes more than once if sum(np.abs(flows)) == 0 and 0 < len(edges) < n_wires: valid_bitstrings_indx.append(indx) else: invalid_bitstrings_indx.append(indx) # Check that valid bitstrings map to a subset of the valid bitstrings for indx in valid_bitstrings_indx: column = h_matrix[:, indx] destination_indxs = set(np.argwhere(column != 0).flatten()) assert destination_indxs.issubset(valid_bitstrings_indx) # Check that invalid bitstrings map to a subset of the invalid bitstrings for indx in invalid_bitstrings_indx: column = h_matrix[:, indx] destination_indxs = set(np.argwhere(column != 0).flatten()) assert destination_indxs.issubset(invalid_bitstrings_indx) # Now consider a unitary generated by the Hamiltonian h_matrix_e = expm(1j * h_matrix) # We expect non-zero transitions among the set of valid bitstrings, and no transitions outside for indx in valid_bitstrings_indx: column = h_matrix_e[:, indx] destination_indxs = np.argwhere(column != 0).flatten().tolist() assert destination_indxs == valid_bitstrings_indx # Check that invalid bitstrings transition within the set of invalid bitstrings for indx in invalid_bitstrings_indx: column = h_matrix_e[:, indx] destination_indxs = set( np.argwhere(column != 0).flatten().tolist()) assert destination_indxs.issubset(invalid_bitstrings_indx)