def test_qobj_to_circuits_multiple_no_qasm(self): """Check that qobj_to_circuits's result with multiple circuits""" backend = BasicAer.get_backend('qasm_simulator') qreg1 = QuantumRegister(2) qreg2 = QuantumRegister(3) creg1 = ClassicalRegister(2) creg2 = ClassicalRegister(2) circuit_b = QuantumCircuit(qreg1, qreg2, creg1, creg2) circuit_b.x(qreg1) circuit_b.h(qreg2) circuit_b.measure(qreg1, creg1) circuit_b.measure(qreg2[0], creg2[1]) qobj = compile([self.circuit, circuit_b], backend, pass_manager=PassManager()) for i in qobj.experiments: del i.header.compiled_circuit_qasm dag_list = [circuit_to_dag(x) for x in qobj_to_circuits(qobj)] self.assertEqual(dag_list, [self.dag, circuit_to_dag(circuit_b)])
def test_optimize_u_to_p_sx_p(self): """U(pi/2, 0, pi/4) -> p(-pi/4)-sx-p(p/2). Basis [p, sx].""" qr = QuantumRegister(2, "qr") circuit = QuantumCircuit(qr) circuit.append(UGate(np.pi / 2, 0, np.pi / 4), [qr[0]]) expected = QuantumCircuit(qr, global_phase=-np.pi / 4) expected.append(PhaseGate(-np.pi / 4), [qr[0]]) expected.append(SXGate(), [qr[0]]) expected.append(PhaseGate(np.pi / 2), [qr[0]]) basis = ["p", "sx"] passmanager = PassManager() passmanager.append(BasisTranslator(sel, basis)) passmanager.append(Optimize1qGatesDecomposition(basis)) result = passmanager.run(circuit) msg = f"expected:\n{expected}\nresult:\n{result}" self.assertEqual(expected, result, msg=msg)
def test_callback(self): """Test the callback parameter.""" qr = QuantumRegister(1, 'qr') circuit = QuantumCircuit(qr, name='MyCircuit') circuit.h(qr[0]) circuit.h(qr[0]) circuit.h(qr[0]) expected_start = QuantumCircuit(qr) expected_start.u2(0, np.pi, qr[0]) expected_start.u2(0, np.pi, qr[0]) expected_start.u2(0, np.pi, qr[0]) expected_start_dag = circuit_to_dag(expected_start) expected_end = QuantumCircuit(qr) expected_end.u2(0, np.pi, qr[0]) expected_end_dag = circuit_to_dag(expected_end) calls = [] def callback(**kwargs): out_dict = kwargs out_dict['dag'] = copy.deepcopy(kwargs['dag']) calls.append(out_dict) passmanager = PassManager() passmanager.append(Unroller(['u2'])) passmanager.append(Optimize1qGates()) passmanager.run(circuit, callback=callback) self.assertEqual(len(calls), 2) self.assertEqual(len(calls[0]), 5) self.assertEqual(calls[0]['count'], 0) self.assertEqual(calls[0]['pass_'].name(), 'Unroller') self.assertEqual(expected_start_dag, calls[0]['dag']) self.assertIsInstance(calls[0]['time'], float) self.assertEqual(calls[0]['property_set'], PropertySet()) self.assertEqual('MyCircuit', calls[0]['dag'].name) self.assertEqual(len(calls[1]), 5) self.assertEqual(calls[1]['count'], 1) self.assertEqual(calls[1]['pass_'].name(), 'Optimize1qGates') self.assertEqual(expected_end_dag, calls[1]['dag']) self.assertIsInstance(calls[0]['time'], float) self.assertEqual(calls[0]['property_set'], PropertySet()) self.assertEqual('MyCircuit', calls[1]['dag'].name)
def test_optimize_h_gates_pass_manager(self): """Transpile: qr:--[H]-[H]-[H]-- == qr:--[u2]-- """ qr = QuantumRegister(1, 'qr') circuit = QuantumCircuit(qr) circuit.h(qr[0]) circuit.h(qr[0]) circuit.h(qr[0]) expected = QuantumCircuit(qr) expected.u2(0, np.pi, qr[0]) passmanager = PassManager() passmanager.append(Unroller(['u2'])) passmanager.append(Optimize1qGates()) result = transpile(circuit, FakeRueschlikon(), pass_manager=passmanager) self.assertEqual(expected, result)
def test_passes_in_linear(self): """Dump passes in the same FlowControllerLinear""" passmanager = PassManager(passes=[ PassC_TP_RA_PA(), PassB_TP_RA_PA(), PassD_TP_NR_NP(argument1=[1, 2]), PassB_TP_RA_PA() ]) expected = [{ 'flow_controllers': {}, 'passes': [ PassC_TP_RA_PA(), PassB_TP_RA_PA(), PassD_TP_NR_NP(argument1=[1, 2]), PassB_TP_RA_PA() ] }] self.assertEqual(expected, passmanager.passes())
def test_all_gates(self): """Test all gates on 1 and 2 qubits q0:-[H]-[H]--[x]-[x]--[y]-[y]--[rz]-[rz]--[u1]-[u1]-[rx]-[rx]---.--.--.--.--.--.- | | | | | | q1:-------------------------------------------------------------X--X--Y--Y--.--.- = qr0:---[u1]--- qr1:---------- """ qr = QuantumRegister(2, 'q') circuit = QuantumCircuit(qr) circuit.h(qr[0]) circuit.h(qr[0]) circuit.x(qr[0]) circuit.x(qr[0]) circuit.y(qr[0]) circuit.y(qr[0]) circuit.rz(0.5, qr[0]) circuit.rz(0.5, qr[0]) circuit.u1(0.5, qr[0]) circuit.u1(0.5, qr[0]) circuit.rx(0.5, qr[0]) circuit.rx(0.5, qr[0]) circuit.cx(qr[0], qr[1]) circuit.cx(qr[0], qr[1]) circuit.cy(qr[0], qr[1]) circuit.cy(qr[0], qr[1]) circuit.cz(qr[0], qr[1]) circuit.cz(qr[0], qr[1]) passmanager = PassManager() passmanager.append(CommutativeCancellation()) new_circuit = passmanager.run(circuit) expected = QuantumCircuit(qr) expected.u1(2.0, qr[0]) expected.rx(1.0, qr[0]) self.assertEqual(expected, new_circuit)
def test_do_not_merge_conditioned_gates(self): """Validate that classically conditioned gates are never considered for inclusion in a block. Note that there are cases where gates conditioned on the same (register, value) pair could be correctly merged, but this is not yet implemented. ┌─────────┐┌─────────┐┌─────────┐ ┌───┐ qr_0: |0>┤ U1(0.1) ├┤ U1(0.2) ├┤ U1(0.3) ├──■───┤ X ├────■─── └─────────┘└────┬────┘└────┬────┘┌─┴─┐ └─┬─┘ ┌─┴─┐ qr_1: |0>────────────────┼──────────┼─────┤ X ├───■────┤ X ├─ │ │ └───┘ │ └─┬─┘ qr_2: |0>────────────────┼──────────┼─────────────┼──────┼─── ┌──┴──┐ ┌──┴──┐ ┌──┴──┐┌──┴──┐ cr_0: 0 ═════════════╡ ╞════╡ ╞═══════╡ ╞╡ ╞ │ = 0 │ │ = 0 │ │ = 0 ││ = 1 │ cr_1: 0 ═════════════╡ ╞════╡ ╞═══════╡ ╞╡ ╞ └─────┘ └─────┘ └─────┘└─────┘ Previously the blocks collected were : [['u1', 'u1', 'u1', 'cx', 'cx', 'cx']] This is now corrected to : [['cx']] """ # ref: https://github.com/Qiskit/qiskit-terra/issues/3215 print("BEGIN MERGE CONDITION ") qr = QuantumRegister(3, "qr") cr = ClassicalRegister(2, "cr") qc = QuantumCircuit(qr, cr) qc.u1(0.1, 0) qc.u1(0.2, 0).c_if(cr, 0) qc.u1(0.3, 0).c_if(cr, 0) qc.cx(0, 1) qc.cx(1, 0).c_if(cr, 0) qc.cx(0, 1).c_if(cr, 1) pass_manager = PassManager() pass_manager.append(CollectMultiQBlocks()) pass_manager.run(qc) for block in pass_manager.property_set["block_list"]: self.assertTrue(len(block) <= 1)
def test_unbound_parameters(self): """ Test that partial matches with parameters will not raise errors. This tests that if parameters are still in the temporary template after _attempt_bind then they will not be used. """ class PhaseSwap(Gate): """CZ gates used for the test.""" def __init__(self, num_qubits, params): super().__init__("p", num_qubits, params) def inverse(self): inverse = UnitaryGate( np.diag( [1.0, 1.0, np.exp(-1.0j * self.params[0]), np.exp(-1.0j * self.params[0])] ) ) inverse.name = "p" return inverse def template(): beta = Parameter("β") qc = QuantumCircuit(2) qc.cx(1, 0) qc.cx(1, 0) qc.p(beta, 1) qc.append(PhaseSwap(2, [beta]), [0, 1]) return qc circuit_in = QuantumCircuit(2) circuit_in.cx(1, 0) circuit_in.cx(1, 0) pass_ = TemplateOptimization(template_list=[template()]) circuit_out = PassManager(pass_).run(circuit_in) # This template will not fully match as long as gates with parameters do not # commute with any other gates in the DAG dependency. self.assertEqual(circuit_out.count_ops().get("cx", 0), 2)
def run(self, quantum_circuit): dag_circuit = circuit_to_dag(quantum_circuit) init_time = time.time() self.parameters["TIME_START"] = init_time initial_mapping = [] if self.parameters["initial_map"] == K7MInitialMapping.RANDOM: # Only the first positions which correspond to the circuit qubits initial_mapping = numpy.random.permutation( self.parameters["nisq_qubits"]) initial_mapping = initial_mapping[:dag_circuit.num_qubits()] elif self.parameters["initial_map"] == K7MInitialMapping.LINEAR: initial_mapping = list(range(dag_circuit.num_qubits())) elif self.parameters["initial_map"] == K7MInitialMapping.HEURISTIC: initial_mapping = cuthill_order(dag_circuit, self.coupling_obj, self.parameters) init_time = time.time() - init_time if initial_mapping is None: return None, init_time, None # print(initial_mapping) # # return quantum_circuit print(" .......") original_pm = PassManager() optimal_layout = Layout() for c_idx, p_idx in enumerate(initial_mapping): optimal_layout.add(quantum_circuit.qregs[0][c_idx], p_idx) original_pm.append([ SetLayout(optimal_layout), ApplyLayout(), StochasticSwap(self.coupling_obj.coupling, seed=0), Decompose(gate=qiskit.extensions.SwapGate) ]) return original_pm.run(quantum_circuit), init_time, initial_mapping
def test_cnot_cascade(self): """ A cascade of CNOTs that equals identity. """ qr = QuantumRegister(10, "qr") circuit = QuantumCircuit(qr) circuit.cx(qr[0], qr[1]) circuit.cx(qr[1], qr[2]) circuit.cx(qr[2], qr[3]) circuit.cx(qr[3], qr[4]) circuit.cx(qr[4], qr[5]) circuit.cx(qr[5], qr[6]) circuit.cx(qr[6], qr[7]) circuit.cx(qr[7], qr[8]) circuit.cx(qr[8], qr[9]) circuit.cx(qr[8], qr[9]) circuit.cx(qr[7], qr[8]) circuit.cx(qr[6], qr[7]) circuit.cx(qr[5], qr[6]) circuit.cx(qr[4], qr[5]) circuit.cx(qr[3], qr[4]) circuit.cx(qr[2], qr[3]) circuit.cx(qr[1], qr[2]) circuit.cx(qr[0], qr[1]) passmanager = PassManager() # passmanager.append(CommutativeCancellation()) passmanager.append( [ CommutationAnalysis(), CommutativeCancellation(), Size(), FixedPoint("size") ], do_while=lambda property_set: not property_set["size_fixed_point"], ) new_circuit = passmanager.run(circuit) expected = QuantumCircuit(qr) self.assertEqual(expected, new_circuit)
def test_pass_cx_cancellation_chained_cx(self): """Include a test were not all operations can be cancelled.""" # ┌───┐ # q0_0: ┤ H ├──■─────────■─────── # ├───┤┌─┴─┐ ┌─┴─┐ # q0_1: ┤ H ├┤ X ├──■──┤ X ├───── # └───┘└───┘┌─┴─┐└───┘ # q0_2: ──────────┤ X ├──■────■── # └───┘┌─┴─┐┌─┴─┐ # q0_3: ───────────────┤ X ├┤ X ├ # └───┘└───┘ qr = QuantumRegister(4) circuit = QuantumCircuit(qr) circuit.h(qr[0]) circuit.h(qr[1]) circuit.cx(qr[0], qr[1]) circuit.cx(qr[1], qr[2]) circuit.cx(qr[0], qr[1]) circuit.cx(qr[2], qr[3]) circuit.cx(qr[2], qr[3]) pass_manager = PassManager() pass_manager.append(CXCancellation()) out_circuit = pass_manager.run(circuit) # ┌───┐ # q0_0: ┤ H ├──■─────────■── # ├───┤┌─┴─┐ ┌─┴─┐ # q0_1: ┤ H ├┤ X ├──■──┤ X ├ # └───┘└───┘┌─┴─┐└───┘ # q0_2: ──────────┤ X ├───── # └───┘ # q0_3: ──────────────────── expected = QuantumCircuit(qr) expected.h(qr[0]) expected.h(qr[1]) expected.cx(qr[0], qr[1]) expected.cx(qr[1], qr[2]) expected.cx(qr[0], qr[1]) self.assertEqual(out_circuit, expected)
def test_callback_with_pass_requires(self): """Test the callback with a pass with another pass requirement.""" qr = QuantumRegister(3, 'qr') circuit = QuantumCircuit(qr, name='MyCircuit') circuit.z(qr[0]) circuit.cx(qr[0], qr[2]) circuit.z(qr[0]) expected_start = QuantumCircuit(qr) expected_start.z(qr[0]) expected_start.cx(qr[0], qr[2]) expected_start.z(qr[0]) expected_start_dag = circuit_to_dag(expected_start) expected_end = QuantumCircuit(qr) expected_end.cx(qr[0], qr[2]) expected_end_dag = circuit_to_dag(expected_end) calls = [] def callback(**kwargs): out_dict = kwargs out_dict['dag'] = copy.deepcopy(kwargs['dag']) calls.append(out_dict) passmanager = PassManager(callback=callback) passmanager.append(CommutativeCancellation()) passmanager.run(circuit) self.assertEqual(len(calls), 2) self.assertEqual(len(calls[0]), 5) self.assertEqual(calls[0]['count'], 0) self.assertEqual(calls[0]['pass_'].name(), 'CommutationAnalysis') self.assertEqual(expected_start_dag, calls[0]['dag']) self.assertIsInstance(calls[0]['time'], float) self.assertIsInstance(calls[0]['property_set'], PropertySet) self.assertEqual('MyCircuit', calls[0]['dag'].name) self.assertEqual(len(calls[1]), 5) self.assertEqual(calls[1]['count'], 1) self.assertEqual(calls[1]['pass_'].name(), 'CommutativeCancellation') self.assertEqual(expected_end_dag, calls[1]['dag']) self.assertIsInstance(calls[0]['time'], float) self.assertIsInstance(calls[0]['property_set'], PropertySet) self.assertEqual('MyCircuit', calls[1]['dag'].name)
def test_compile_pass_manager(self): """Test compile with and without an empty pass manager.""" qr = QuantumRegister(2) cr = ClassicalRegister(2) qc = QuantumCircuit(qr, cr) qc.u1(3.14, qr[0]) qc.u2(3.14, 1.57, qr[0]) qc.barrier(qr) qc.measure(qr, cr) backend = BasicAer.get_backend('qasm_simulator') qrtrue = assemble(transpile(qc, backend, seed_transpiler=8), seed_simulator=42) rtrue = backend.run(qrtrue).result() qrfalse = assemble(transpile(qc, backend, seed_transpiler=8, pass_manager=PassManager()), seed_simulator=42) rfalse = backend.run(qrfalse).result() self.assertEqual(rtrue.get_counts(), rfalse.get_counts())
def test_passes(self): """Dump passes in different FlowControllerLinear""" passmanager = PassManager() passmanager.append(PassC_TP_RA_PA()) passmanager.append(PassB_TP_RA_PA()) expected = [{ 'options': { 'max_iteration': 1000 }, 'passes': [PassC_TP_RA_PA()], 'type': FlowControllerLinear }, { 'options': { 'max_iteration': 1000 }, 'passes': [PassB_TP_RA_PA()], 'type': FlowControllerLinear }] self.assertEqual(expected, passmanager.passes())
def test_control_bit_of_cnot3(self): """A simple circuit where the two cnots shoule be cancelled. qr0:----.------[Rz]------.-- qr0:---[Rz]--- | | qr1:---(+)-------- -----(+)- = qr1:---------- """ qr = QuantumRegister(2, 'qr') circuit = QuantumCircuit(qr) circuit.cx(qr[0], qr[1]) circuit.rz(sympy.pi / 3, qr[0]) circuit.cx(qr[0], qr[1]) new_pm = PassManager(CommutativeCancellation()) new_circuit = transpile(circuit, pass_manager=new_pm) expected = QuantumCircuit(qr) expected.rz(sympy.pi / 3, qr[0]) self.assertEqual(expected, new_circuit)
def test_two_resets(self): """Remove two initial resets qr0:--|0>-|0>-- ==> qr0:---- """ qr = QuantumRegister(1, "qr") circuit = QuantumCircuit(qr) circuit.reset(qr[0]) circuit.reset(qr[0]) expected = QuantumCircuit(qr) pass_manager = PassManager() pass_manager.append( [RemoveResetInZeroState(), DAGFixedPoint()], do_while=lambda property_set: not property_set["dag_fixed_point"], ) after = pass_manager.run(circuit) self.assertEqual(expected, after)
def test_control_bit_of_cnot4(self): """A simple circuit where the two cnots should be cancelled. 0:----.------[T]------.-- 0:---[T]--- | | 1:---(+)-------------(+)- = 1:--------- """ circuit = QuantumCircuit(2) circuit.cx(0, 1) circuit.t(0) circuit.cx(0, 1) passmanager = PassManager(CommutativeInverseCancellation()) new_circuit = passmanager.run(circuit) expected = QuantumCircuit(2) expected.t(0) self.assertEqual(expected, new_circuit)
def test_conditional_and_loop(self): """Dump passes with a conditional and a loop.""" passmanager = PassManager() passmanager.append(PassE_AP_NR_NP(True)) passmanager.append( [PassK_check_fixed_point_property(), PassA_TP_NR_NP(), PassF_reduce_dag_property()], do_while=lambda property_set: not property_set['property_fixed_point'], condition=lambda property_set: property_set['property_fixed_point']) expected = [{'options': {'max_iteration': 1000}, 'passes': [PassE_AP_NR_NP(True)], 'type': FlowControllerLinear}, {'options': {'max_iteration': 1000}, 'passes': [PassK_check_fixed_point_property(), PassA_TP_NR_NP(), PassF_reduce_dag_property()], 'type': ConditionalController}] self.assertEqual(expected, passmanager.passes())
def test_all_gates_in_basis_after_translation(self): """Test circuit with gates in basis after conditional translation.""" basis_gates = ["cx", "u"] property_set = {} analysis_pass = GatesInBasis(basis_gates) circuit = QuantumCircuit(2) circuit.h(0) circuit.cx(0, 1) circuit.measure_all() analysis_pass(circuit, property_set=property_set) self.assertFalse(property_set["all_gates_in_basis"]) pm = PassManager() pm.append(analysis_pass) pm.append( BasisTranslator(SessionEquivalenceLibrary, basis_gates), condition=lambda property_set: not property_set["all_gates_in_basis"], ) pm.append(analysis_pass) pm.run(circuit) self.assertTrue(pm.property_set["all_gates_in_basis"])
def test_single_parameterized_circuit(self, basis): """Parameters should be treated as opaque gates.""" qr = QuantumRegister(1) qc = QuantumCircuit(qr) theta = Parameter("theta") qc.p(0.3, qr) qc.p(0.4, qr) qc.p(theta, qr) qc.p(0.1, qr) qc.p(0.2, qr) passmanager = PassManager() passmanager.append(BasisTranslator(sel, basis)) passmanager.append(Optimize1qGatesDecomposition(basis)) result = passmanager.run(qc) self.assertTrue( Operator(qc.bind_parameters({theta: 3.14})).equiv( Operator(result.bind_parameters({theta: 3.14}))))
def test_lookahead_swap_should_add_a_single_swap(self): """Test that LookaheadSwap will insert a SWAP to match layout. For a single cx gate which is not available in the current layout, test that the mapper inserts a single swap to enable the gate. """ qr = QuantumRegister(3) circuit = QuantumCircuit(qr) circuit.cx(qr[0], qr[2]) dag_circuit = circuit_to_dag(circuit) coupling_map = CouplingMap(couplinglist=[(0, 1), (1, 2)]) pass_manager = PassManager() pass_manager.append([LookaheadSwap(coupling_map)]) mapped_dag = transpile_dag(dag_circuit, pass_manager=pass_manager) self.assertEqual(mapped_dag.count_ops().get('swap', 0), dag_circuit.count_ops().get('swap', 0) + 1)
def test_two_resets(self): """ Remove two initial resets qr0:--|0>-|0>-- ==> qr0:---- """ qr = QuantumRegister(1, 'qr') circuit = QuantumCircuit(qr) circuit.reset(qr[0]) circuit.reset(qr[0]) dag = circuit_to_dag(circuit) expected = QuantumCircuit(qr) pass_manager = PassManager() pass_manager.append( [RemoveResetInZeroState(), DAGFixedPoint()], do_while=lambda property_set: not property_set['dag_fixed_point']) after = transpile_dag(dag, pass_manager=pass_manager) self.assertEqual(circuit_to_dag(expected), after)
def test_control_bit_of_cnot4(self): """A simple circuit where the two cnots shoule be cancelled. qr0:----.------[T]------.-- qr0:---[T]--- | | qr1:---(+)-------------(+)- = qr1:--------- """ qr = QuantumRegister(2, "qr") circuit = QuantumCircuit(qr) circuit.cx(qr[0], qr[1]) circuit.t(qr[0]) circuit.cx(qr[0], qr[1]) new_pm = PassManager(CommutativeCancellation()) new_circuit = new_pm.run(circuit) expected = QuantumCircuit(qr) expected.t(qr[0]) self.assertEqual(expected, new_circuit)
def test_pass_cx_cancellation_intermixed_ops(self): """Cancellation shouldn't be affected by the order of ops on different qubits.""" qr = QuantumRegister(4) circuit = QuantumCircuit(qr) circuit.h(qr[0]) circuit.h(qr[1]) circuit.cx(qr[0], qr[1]) circuit.cx(qr[2], qr[3]) circuit.cx(qr[0], qr[1]) circuit.cx(qr[2], qr[3]) pass_manager = PassManager() pass_manager.append(CXCancellation()) out_circuit = pass_manager.run(circuit) expected = QuantumCircuit(qr) expected.h(qr[0]) expected.h(qr[1]) self.assertEqual(out_circuit, expected)
def test_consecutive_cnots2(self): """ Two CNOTs that equals identity, with rotation gates inserted. """ qr = QuantumRegister(2, 'qr') circuit = QuantumCircuit(qr) circuit.rx(np.pi, qr[0]) circuit.cx(qr[0], qr[1]) circuit.cx(qr[0], qr[1]) circuit.rx(np.pi, qr[0]) passmanager = PassManager() passmanager.append([CommutationAnalysis(), CommutativeCancellation(), Size(), FixedPoint('size')], do_while=lambda property_set: not property_set['size_fixed_point']) new_circuit = passmanager.run(circuit) expected = QuantumCircuit(qr) self.assertEqual(expected, new_circuit)
def test_ignore_preserves_pm(self): """ A pass manager that ignores preserves does not record the passes decleared in the 'preserves' field of the passes as valid passes.""" passmanager = PassManager(ignore_preserves=True) passmanager.append( PassC_TP_RA_PA()) # Request: PassA / Preserves: PassA passmanager.append( PassB_TP_RA_PA()) # Request: PassA / Preserves: PassA passmanager.append( PassD_TP_NR_NP(argument1=[1, 2])) # Requires: {} / Preserves: {} passmanager.append(PassB_TP_RA_PA()) self.assertScheduler(self.dag, passmanager, [ 'run transformation pass PassA_TP_NR_NP', 'run transformation pass PassC_TP_RA_PA', 'run transformation pass PassA_TP_NR_NP', 'run transformation pass PassB_TP_RA_PA', 'run transformation pass PassD_TP_NR_NP', 'argument [1, 2]', 'run transformation pass PassA_TP_NR_NP', 'run transformation pass PassB_TP_RA_PA' ])
def test_pass_manager_empty(self): """Test passing an empty PassManager() to the transpiler. It should perform no transformations on the circuit. """ qr = QuantumRegister(2) circuit = QuantumCircuit(qr) circuit.h(qr[0]) circuit.h(qr[0]) circuit.cx(qr[0], qr[1]) circuit.cx(qr[0], qr[1]) circuit.cx(qr[0], qr[1]) circuit.cx(qr[0], qr[1]) resources_before = circuit.count_ops() pass_manager = PassManager() out_circuit = transpile(circuit, pass_manager=pass_manager) resources_after = out_circuit.count_ops() self.assertDictEqual(resources_before, resources_after)
def test_objective_function(self): """Test if ``objective`` functions priorities metrics correctly.""" # ┌──────┐┌──────┐ ┌──────┐ # q_0: ┤0 ├┤0 ├─────┤0 ├ # │ Dcx ││ │ │ Dcx │ # q_1: ┤1 ├┤ Dcx ├──■──┤1 ├ # └──────┘│ │ │ └──────┘ # q_2: ───■────┤1 ├──┼─────■──── # ┌─┴─┐ └──────┘┌─┴─┐ ┌─┴─┐ # q_3: ─┤ X ├──────────┤ X ├─┤ X ├── # └───┘ └───┘ └───┘ qc = QuantumCircuit(4) qc.dcx(0, 1) qc.cx(2, 3) qc.dcx(0, 2) qc.cx(1, 3) qc.dcx(0, 1) qc.cx(2, 3) coupling = CouplingMap(FakeLima().configuration().coupling_map) dep_opt = BIPMapping(coupling, objective="depth", qubit_subset=[0, 1, 3, 4])(qc) err_opt = BIPMapping( coupling, objective="gate_error", qubit_subset=[0, 1, 3, 4], backend_prop=FakeLima().properties(), )(qc) # depth = number of su4 layers (mirrored gates have to be consolidated as single su4 gates) pm_ = PassManager( [Collect2qBlocks(), ConsolidateBlocks(basis_gates=["cx"])]) dep_opt = pm_.run(dep_opt) err_opt = pm_.run(err_opt) self.assertLessEqual(dep_opt.depth(), err_opt.depth()) # count CNOTs after synthesized dep_opt = UnitarySynthesis(basis_gates=["cx"])(dep_opt) err_opt = UnitarySynthesis(basis_gates=["cx"])(err_opt) self.assertGreater(dep_opt.count_ops()["cx"], err_opt.count_ops()["cx"])
def test_block_with_classical_register(self): """Test that only blocks that share quantum wires are added to the block. It was the case that gates which shared a classical wire could be added to the same block, despite not sharing the same qubits. This was fixed in #2956. ┌─────────────────────┐ q_0: |0>────────────────────┤ U2(0.25*pi,0.25*pi) ├ ┌─────────────┐└──────────┬──────────┘ q_1: |0>──■──┤ U1(0.25*pi) ├───────────┼─────────── ┌─┴─┐└──────┬──────┘ │ q_2: |0>┤ X ├───────┼──────────────────┼─────────── └───┘ ┌──┴──┐ ┌──┴──┐ c0_0: 0 ═════════╡ = 0 ╞════════════╡ = 0 ╞════════ └─────┘ └─────┘ Previously the blocks collected were : [['cx', 'u1', 'u2']] This is now corrected to : [['cx', 'u1']] """ qasmstr = """ OPENQASM 2.0; include "qelib1.inc"; qreg q[3]; creg c0[1]; cx q[1],q[2]; if(c0==0) u1(0.25*pi) q[1]; if(c0==0) u2(0.25*pi, 0.25*pi) q[0]; """ qc = QuantumCircuit.from_qasm_str(qasmstr) backend = FakeMelbourne() pass_manager = PassManager() pass_manager.append(Collect2qBlocks()) transpile(qc, backend, pass_manager=pass_manager) self.assertEqual( [['cx', 'u1']], [[n.name for n in block] for block in pass_manager.property_set['block_list']])
def test_do_not_merge_conditioned_gates(self): """Validate that classically conditioned gates are never considered for inclusion in a block. Note that there are cases where gates conditioned on the same (register, value) pair could be correctly merged, but this is not yet implemented. ┌─────────┐┌─────────┐┌─────────┐ ┌───┐ qr_0: |0>┤ U1(0.1) ├┤ U1(0.2) ├┤ U1(0.3) ├──■───┤ X ├────■─── └─────────┘└────┬────┘└────┬────┘┌─┴─┐ └─┬─┘ ┌─┴─┐ qr_1: |0>────────────────┼──────────┼─────┤ X ├───■────┤ X ├─ │ │ └───┘ │ └─┬─┘ qr_2: |0>────────────────┼──────────┼─────────────┼──────┼─── ┌──┴──┐ ┌──┴──┐ ┌──┴──┐┌──┴──┐ cr_0: 0 ═════════════╡ ╞════╡ ╞═══════╡ ╞╡ ╞ │ = 0 │ │ = 0 │ │ = 0 ││ = 1 │ cr_1: 0 ═════════════╡ ╞════╡ ╞═══════╡ ╞╡ ╞ └─────┘ └─────┘ └─────┘└─────┘ Previously the blocks collected were : [['u1', 'u1', 'u1', 'cx', 'cx', 'cx']] This is now corrected to : [['cx']] """ # ref: https://github.com/Qiskit/qiskit-terra/issues/3215 qr = QuantumRegister(3, 'qr') cr = ClassicalRegister(2, 'cr') qc = QuantumCircuit(qr, cr) qc.u1(0.1, 0) qc.u1(0.2, 0).c_if(cr, 0) qc.u1(0.3, 0).c_if(cr, 0) qc.cx(0, 1) qc.cx(1, 0).c_if(cr, 0) qc.cx(0, 1).c_if(cr, 1) pass_manager = PassManager() pass_manager.append(Collect2qBlocks()) transpile(qc, pass_manager=pass_manager) self.assertEqual( [['cx']], [[n.name for n in block] for block in pass_manager.property_set['block_list']])