def test_max_cuts_negative_fails(): """Tests the circuit-to-ordering conversion.""" qubits = [cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)] size = 4 for x in range(size): qubits.append([cirq.GridQubit(x, y) for y in range(size)]) moments = (cirq.Moment([cirq.CZ(qubits[0], qubits[1])]), cirq.Moment([cirq.CZ(qubits[0], qubits[1])])) circuit = cirq.Circuit(moments) # max_cuts cannot be less than zero. with pytest.raises(ValueError): order_lib.circuit_to_ordering(circuit=circuit, max_cuts=-1)
def test_max_cuts_zero_succeeds(): """Tests the circuit-to-ordering conversion.""" qubits = [cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)] size = 4 for x in range(size): qubits.append([cirq.GridQubit(x, y) for y in range(size)]) moments = (cirq.Moment([cirq.CZ(qubits[0], qubits[1])]), cirq.Moment([cirq.CZ(qubits[0], qubits[1])])) circuit = cirq.Circuit(moments) # max_cuts of zero will generate an ordering. order = order_lib.circuit_to_ordering(circuit=circuit, max_cuts=0) assert len(order) > 1
def test_automatic_ordering(): test_size = 2 test_circuit = generate_circuit(size=test_size) # This is a known order random.seed(0) order = order_lib.circuit_to_ordering(test_circuit) # Now I am creating a QFlexOrder qorder = QFlexOrder(qflex_order_strings=None, cirq_circuit=test_circuit, qubits=list(range(test_size**2))) read_contents = None with open(qorder.order_data, "r") as file: read_contents = "".join(file.readlines()) assert (read_contents.strip() == "\n".join(order).strip())
def __init__(self, qflex_order_strings=None, cirq_circuit=None, qubits=None): if (qflex_order_strings is None) and (cirq_circuit is None): # TODO: More serious checking raise ValueError("No order specified to constructor!") if (cirq_circuit is not None) and (not isinstance(cirq_circuit, cirq.Circuit)): raise ValueError("Order accepts only QFlexCircuits") ord_list = qflex_order_strings if cirq_circuit is not None: if qubits is None: raise ValueError("Qubits have to be specified!") # The device has to be QFlex # qubits = qflex_circuit.device.get_indexed_grid_qubits() # List of ordering commands print("Ordering is being computed from the provided circuit ...") ord_list = auto_order.circuit_to_ordering( cirq_circuit, qubit_names=sorted(qubits)) print("... Done!") # Long string of ordering commands _local_order_string = '\n'.join([x.strip() for x in ord_list]) # Behind the scene, this class creates a temporary file for each object self.temp_file_if = tmpi.DataStorageInterface() with open(self.temp_file_if.fullpath, "w") as f: # I do have the file handle anyway... print(_local_order_string, file=f)
def test_circuit_to_ordering(): """Tests the circuit-to-ordering conversion. This is mostly a change-detecting test, as the heuristic is known to be non-optimal. If this test fails, verify that the new output is an improvement over the old output (either in time or memory cost) and update the test. """ qubits = [] size = 4 for x in range(size): qubits.append([cirq.GridQubit(x, y) for y in range(size)]) random.seed(0) # Build moments with ISWAPs and CZs on each adjacent pair of qubits. # Each bond has a pseudorandom dimension between 2 and 5: # (Dots represent qubits, numbers are bond dimension, and Xs are cuts) # # .3.4.5. Canonical qubit numbering goes in row-major order: # 5 5 2 4 - The top-left qubit, (0, 0), is index 0. # .2.2.2. - The top-right qubit, (0, 3), is index 3. # X 5 4 5 - The bottom-left qubit, (3, 0), is index 12. # .4.2.4. # 4 3 3 4 # .3.X.5. # # ISWAPs add 2 to the bond dimension, and CZs add 1. moments = () for x in range(size - 1): for y in range(size): r = random.randint(2, 5) while r > 1: moments += (cirq.Moment( [cirq.ISWAP(qubits[x][y], qubits[x + 1][y])]), ) r -= 2 while r > 0: moments += (cirq.Moment( [cirq.CZ(qubits[x][y], qubits[x + 1][y])]), ) r -= 1 for y in range(size - 1): for x in range(size): r = random.randint(2, 5) while r > 1: moments += (cirq.Moment( [cirq.ISWAP(qubits[x][y], qubits[x][y + 1])]), ) r -= 2 while r > 0: moments += (cirq.Moment( [cirq.CZ(qubits[x][y], qubits[x][y + 1])]), ) r -= 1 circuit = cirq.Circuit(moments) order = order_lib.circuit_to_ordering(circuit=circuit, max_cuts=2) # Log the ordering file for debugging purposes. print("\n".join(order)) assert len(order) == 39 # The order of these two operations doesn't matter, and cuts may have their # indices Iswapped. # cut bond (cirq.GridQubit(3, 1), cirq.GridQubit(3, 2)) of dim 16 cut1 = set(["cut () 13 14", "cut () 14 13"]) # cut bond (cirq.GridQubit(1, 0), cirq.GridQubit(2, 0)) of dim 4 cut2 = set(["cut () 9 10", "cut () 10 9"]) # approximate fidelity: 1.0 assert cut1.intersection(set([order[1], order[3]])) assert cut2.intersection(set([order[1], order[3]])) # These are the lines with commands. command_indices = [ 6, 7, 9, 10, 12, 13, 15, 17, 19, 21, 23, 25, 27, 29, 30, 32 ] order5_33 = [order[i] for i in command_indices] assert order5_33 == [ # 1: ['ISWAP((3, 2), (3, 3))', 'ISWAP((3, 2), (3, 3))', 'CZ((3, 2), (3, 3))'] "expand A 14", "expand A 15", # 2: ['ISWAP((0, 0), (1, 0))', 'ISWAP((0, 0), (1, 0))', 'CZ((0, 0), (1, 0))'] "expand B 0", "expand B 4", # 3: ['ISWAP((0, 2), (0, 3))', 'ISWAP((0, 2), (0, 3))', 'CZ((0, 2), (0, 3))'] "expand C 2", "expand C 3", # 4: ['ISWAP((2, 3), (3, 3))', 'ISWAP((2, 3), (3, 3))'] "expand A 11", # 5: ['ISWAP((2, 2), (2, 3))', 'ISWAP((2, 2), (2, 3))', 'ISWAP((2, 2), (3, 2))', 'CZ((2, 2), (3, 2))'] "expand A 10", # 6: ['ISWAP((1, 3), (2, 3))', 'ISWAP((1, 3), (2, 3))', 'CZ((1, 3), (2, 3))'] "expand A 7", # 7: ['ISWAP((1, 2), (2, 2))', 'ISWAP((1, 2), (2, 2))', 'ISWAP((1, 2), (1, 3))'] "expand A 6", # 8: ['ISWAP((0, 2), (1, 2))', 'ISWAP((0, 3), (1, 3))', 'ISWAP((0, 3), (1, 3))'] "merge A C", # 9: ['ISWAP((0, 1), (0, 2))', 'ISWAP((0, 1), (0, 2))'] "expand C 1", # 10: ['ISWAP((0, 1), (1, 1))', 'ISWAP((0, 1), (1, 1))', 'CZ((0, 1), (1, 1))', 'ISWAP((1, 1), (1, 2))'] "expand C 5", # 11: ['ISWAP((2, 0), (3, 0))', 'ISWAP((2, 0), (3, 0))'] "expand D 8", "expand D 12", # 12: ['ISWAP((0, 0), (0, 1))', 'CZ((0, 0), (0, 1))', 'ISWAP((1, 0), (1, 1))'] "merge B C" ] # The order of these two operations doesn't matter. # 13: ['ISWAP((1, 0), (2, 0))', 'ISWAP((1, 0), (2, 0))', 'CZ((1, 0), (2, 0))'] # 14: ['ISWAP((1, 1), (2, 1))', 'ISWAP((1, 1), (2, 1))', 'CZ((1, 1), (2, 1))', 'ISWAP((2, 0), (2, 1))', 'ISWAP((2, 0), (2, 1))'] assert (["expand C 9", "merge C D"] == [order[34], order[36]] or ["merge C D", "expand D 9"] == [order[34], order[36]]) # 15: ['ISWAP((2, 1), (3, 1))', 'CZ((2, 1), (3, 1))', 'ISWAP((3, 0), (3, 1))', 'CZ((3, 0), (3, 1))'] assert order[38] == "expand D 13"
expand B 10 expand B 11 expand B 12 expand B 13 expand B 14 expand B 15 merge A B """ # Simulate circuit qubits = utils.GetGridQubits(StringIO(grid_test)) circuit = utils.GetCircuit(StringIO(circuit_test), qubits) circuit_no_h_and_sparse = utils.GetCircuit( StringIO(circuit_no_h_and_sparse_test), qubits) auto_ordering = auto_order.circuit_to_ordering(circuit, qubit_names=sorted(qubits)) results = cirq.Simulator().simulate(circuit) results_no_h_and_sparse = cirq.Simulator().simulate(circuit_no_h_and_sparse) @pytest.mark.parametrize('m', ['1kB', '10B', '1', 1 << 10, 10, 1, '1kMB']) @pytest.mark.xfail def test_memory_limit(m): # Get configuration as a string final_conf = '0' * len(qubits) options = { 'circuit': circuit_test.split('\n'), 'ordering': ordering_test.split('\n'), 'grid': grid_test.split('\n'),