Example #1
0
 def test_basic_gate_inverse(self):
     """Test that a basic pair of gate inverse can be cancelled."""
     qc = QuantumCircuit(2, 2)
     qc.rx(np.pi / 4, 0)
     qc.rx(-np.pi / 4, 0)
     pass_ = InverseCancellation([(RXGate(np.pi / 4), RXGate(-np.pi / 4))])
     pm = PassManager(pass_)
     new_circ = pm.run(qc)
     gates_after = new_circ.count_ops()
     self.assertNotIn("rx", gates_after)
Example #2
0
 def test_get_instruction_from_name(self):
     with self.assertRaises(KeyError):
         self.empty_target.operation_from_name("measure")
     self.assertEqual(self.ibm_target.operation_from_name("measure"), Measure())
     self.assertEqual(self.fake_backend_target.operation_from_name("rx_30"), RXGate(math.pi / 6))
     self.assertEqual(
         self.fake_backend_target.operation_from_name("rx"),
         RXGate(self.fake_backend._theta),
     )
     self.assertEqual(self.ideal_sim_target.operation_from_name("ccx"), CCXGate())
Example #3
0
 def test_non_inverse_do_not_cancel(self):
     """Test that non-inverse gate pairs do not cancel."""
     qc = QuantumCircuit(2, 2)
     qc.rx(np.pi / 4, 0)
     qc.rx(np.pi / 4, 0)
     pass_ = InverseCancellation([(RXGate(np.pi / 4), RXGate(-np.pi / 4))])
     pm = PassManager(pass_)
     new_circ = pm.run(qc)
     gates_after = new_circ.count_ops()
     self.assertIn("rx", gates_after)
     self.assertEqual(gates_after["rx"], 2)
    def test_insert_midmeas_hahn_asap(self):
        """Test a single X gate as Hahn echo can absorb in the upstream circuit.

                               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ยป
        q_0: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ– โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค U(3ฯ€/4,-ฯ€/2,ฯ€/2) โ”œโ”€โ”ค Delay(600[dt]) โ”œโ”ค Rx(ฯ€/4) โ”œยป
                   โ”Œโ”€โ”ดโ”€โ”       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”Œโ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ยป
        q_1: โ”€โ”€โ”€โ”€โ”€โ”€โ”ค X โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ– โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค Delay(1000[dt]) โ”œโ”€โ”€โ”€โ”€โ”€โ– โ”€โ”€โ”€โ”€โ”€ยป
             โ”Œโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”Œโ”€โ”ดโ”€โ”        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”Œโ”€โ”ดโ”€โ”   ยป
        q_2: โ”ค Delay(700[dt]) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค X โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คMโ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค X โ”œโ”€โ”€โ”€ยป
             โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ””โ”€โ”€โ”€โ”˜                โ””โ•ฅโ”˜           โ””โ”€โ”€โ”€โ”˜   ยป
        c: 1/โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฉโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ยป
                                                            0                    ยป
        ยซ     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        ยซq_0: โ”ค Delay(600[dt]) โ”œโ”€โ”€โ– โ”€โ”€
        ยซ     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”Œโ”€โ”ดโ”€โ”
        ยซq_1: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค X โ”œ
        ยซ     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ””โ”€โ”€โ”€โ”˜
        ยซq_2: โ”ค Delay(700[dt]) โ”œโ”€โ”€โ”€โ”€โ”€
        ยซ     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        ยซc: 1/โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
        ยซ
        """
        dd_sequence = [RXGate(pi / 4)]
        pm = PassManager([
            ASAPScheduleAnalysis(self.durations),
            PadDynamicalDecoupling(self.durations, dd_sequence),
        ])

        midmeas_dd = pm.run(self.midmeas)

        combined_u = UGate(3 * pi / 4, -pi / 2, pi / 2)

        expected = QuantumCircuit(3, 1)
        expected.cx(0, 1)
        expected.compose(combined_u, [0], inplace=True)
        expected.delay(600, 0)
        expected.rx(pi / 4, 0)
        expected.delay(600, 0)
        expected.delay(700, 2)
        expected.cx(1, 2)
        expected.delay(1000, 1)
        expected.measure(2, 0)
        expected.cx(1, 2)
        expected.cx(0, 1)
        expected.delay(700, 2)

        self.assertEqual(midmeas_dd, expected)
        # check the absorption into U was done correctly
        self.assertTrue(
            Operator(XGate()).equiv(
                Operator(UGate(3 * pi / 4, -pi / 2, pi / 2))
                & Operator(RXGate(pi / 4))))
    def test_for_loop_invalid_params_setter(self):
        """Verify we catch invalid param settings for ForLoopOp."""
        body = QuantumCircuit(3, 1)
        loop_parameter = Parameter("foo")
        indexset = range(0, 10, 2)

        body.rx(loop_parameter, 0)

        op = ForLoopOp(indexset, loop_parameter, body)

        with self.assertWarnsRegex(UserWarning,
                                   r"loop_parameter was not found"):
            op.params = [indexset, Parameter("foo"), body]

        with self.assertRaisesRegex(CircuitError,
                                    r"to be of type QuantumCircuit"):
            op.params = [indexset, loop_parameter, RXGate(loop_parameter)]

        bad_body = QuantumCircuit(2, 1)
        with self.assertRaisesRegex(
                CircuitError,
                r"num_clbits different than that of the ForLoopOp"):
            op.params = [indexset, loop_parameter, bad_body]

        with self.assertRaisesRegex(CircuitError,
                                    r"to be either of type Parameter or None"):
            _ = ForLoopOp(indexset, "foo", body)
Example #6
0
    def exp_i(self) -> OperatorBase:
        """ Return a ``CircuitOp`` equivalent to e^-iH for this operator H. """
        # if only one qubit is significant, we can perform the evolution
        corrected_x = self.primitive.x[::-1]  # type: ignore
        corrected_z = self.primitive.z[::-1]  # type: ignore
        # pylint: disable=import-outside-toplevel,no-member
        sig_qubits = np.logical_or(corrected_x, corrected_z)
        if np.sum(sig_qubits) == 0:
            # e^I is just a global phase, but we can keep track of it! Should we?
            # For now, just return identity
            return PauliOp(self.primitive)
        if np.sum(sig_qubits) == 1:
            sig_qubit_index = sig_qubits.tolist().index(True)
            coeff = np.real(self.coeff) \
                if not isinstance(self.coeff, ParameterExpression) \
                else self.coeff
            # Y rotation
            if corrected_x[sig_qubit_index] and corrected_z[sig_qubit_index]:
                rot_op = PrimitiveOp(RYGate(coeff))
            # Z rotation
            elif corrected_z[sig_qubit_index]:
                rot_op = PrimitiveOp(RZGate(coeff))
            # X rotation
            elif corrected_x[sig_qubit_index]:
                rot_op = PrimitiveOp(RXGate(coeff))

            from ..operator_globals import I
            left_pad = I.tensorpower(sig_qubit_index)
            right_pad = I.tensorpower(self.num_qubits - sig_qubit_index - 1)
            # Need to use overloaded operators here in case left_pad == I^0
            return left_pad ^ rot_op ^ right_pad
        else:
            from ..evolutions.evolved_op import EvolvedOp
            return EvolvedOp(self)
Example #7
0
 def test_get_instructions_for_qargs(self):
     with self.assertRaises(KeyError):
         self.empty_target.operations_for_qargs((0, ))
     expected = [RZGate(self.theta), IGate(), SXGate(), XGate(), Measure()]
     res = self.ibm_target.operations_for_qargs((0, ))
     for gate in expected:
         self.assertIn(gate, res)
     expected = [ECRGate()]
     res = self.fake_backend_target.operations_for_qargs((1, 0))
     for gate in expected:
         self.assertIn(gate, res)
     expected = [CXGate()]
     res = self.fake_backend_target.operations_for_qargs((0, 1))
     self.assertEqual(expected, res)
     ideal_sim_expected = [
         UGate(self.theta, self.phi, self.lam),
         RXGate(self.theta),
         RYGate(self.theta),
         RZGate(self.theta),
         CXGate(),
         ECRGate(),
         CCXGate(),
         Measure(),
     ]
     for gate in ideal_sim_expected:
         self.assertIn(gate,
                       self.ideal_sim_target.operations_for_qargs(None))
Example #8
0
 def test_non_gate_inverse_raise_error(self):
     """Test that non-inverse gate inputs raise an error."""
     qc = QuantumCircuit(2, 2)
     qc.rx(np.pi / 4, 0)
     qc.rx(np.pi / 4, 0)
     with self.assertRaises(TranspilerError):
         InverseCancellation([(RXGate(np.pi / 4))])
    def test_calibrations_basis_gates(self):
        """Check if the calibrations for basis gates provided are added correctly."""
        circ = QuantumCircuit(2)

        with pulse.build() as q0_x180:
            pulse.play(pulse.library.Gaussian(20, 1.0, 3.0),
                       pulse.DriveChannel(0))
        with pulse.build() as q1_y90:
            pulse.play(pulse.library.Gaussian(20, -1.0, 3.0),
                       pulse.DriveChannel(1))

        # Add calibration
        circ.add_calibration(RXGate(3.14), [0], q0_x180)
        circ.add_calibration(RYGate(1.57), [1], q1_y90)

        self.assertEqual(set(circ.calibrations.keys()), {"rx", "ry"})
        self.assertEqual(set(circ.calibrations["rx"].keys()),
                         {((0, ), (3.14, ))})
        self.assertEqual(set(circ.calibrations["ry"].keys()),
                         {((1, ), (1.57, ))})
        self.assertEqual(
            circ.calibrations["rx"][((0, ), (3.14, ))].instructions,
            q0_x180.instructions)
        self.assertEqual(
            circ.calibrations["ry"][((1, ), (1.57, ))].instructions,
            q1_y90.instructions)
Example #10
0
 def test_operations(self):
     self.assertEqual(self.empty_target.operations, [])
     ibm_expected = [
         RZGate(self.theta),
         IGate(),
         SXGate(),
         XGate(),
         CXGate(),
         Measure()
     ]
     for gate in ibm_expected:
         self.assertIn(gate, self.ibm_target.operations)
     aqt_expected = [
         RZGate(self.theta),
         RXGate(self.theta),
         RYGate(self.theta),
         RGate(self.theta, self.phi),
         RXXGate(self.theta),
     ]
     for gate in aqt_expected:
         self.assertIn(gate, self.aqt_target.operations)
     fake_expected = [
         UGate(self.fake_backend._theta, self.fake_backend._phi,
               self.fake_backend._lam),
         CXGate(),
         Measure(),
         ECRGate(),
         RXGate(math.pi / 6),
         RXGate(self.fake_backend._theta),
     ]
     for gate in fake_expected:
         self.assertIn(gate, self.fake_backend_target.operations)
     ideal_sim_expected = [
         UGate(self.theta, self.phi, self.lam),
         RXGate(self.theta),
         RYGate(self.theta),
         RZGate(self.theta),
         CXGate(),
         ECRGate(),
         CCXGate(),
         Measure(),
     ]
     for gate in ideal_sim_expected:
         self.assertIn(gate, self.ideal_sim_target.operations)
Example #11
0
    def test_multi_circuit_uncommon_calibrations(self):
        """Test that disassembler parses uncommon calibrations (stored at QOBJ experiment-level)."""
        with pulse.build() as sched:
            pulse.play(pulse.library.Drag(50, 0.15, 4, 2), pulse.DriveChannel(0))

        qc_0 = QuantumCircuit(2)
        qc_0.h(0)
        qc_0.append(RXGate(np.pi), [1])
        qc_0.add_calibration("h", [0], sched)
        qc_0.add_calibration(RXGate(np.pi), [1], sched)

        qc_1 = QuantumCircuit(2)
        qc_1.h(0)

        circuits = [qc_0, qc_1]
        qobj = assemble(circuits, FakeOpenPulse2Q())
        output_circuits, _, _ = disassemble(qobj)

        self.assertCircuitCalibrationsEqual(circuits, output_circuits)
Example #12
0
def rx_matrix(phi: float) -> np.ndarray:
    """
    Computes an RX rotation by the angle of ``phi``.

    Args:
        phi: rotation angle.

    Returns:
        an RX rotation matrix.
    """
    return RXGate(phi).to_matrix()
    def test_multi_controlled_rotation_gate_matrices(self, num_controls,
                                                     base_gate_name,
                                                     use_basis_gates):
        """Test the multi controlled rotation gates without ancillas.

        Based on the test moved here from Aqua:
        https://github.com/Qiskit/qiskit-aqua/blob/769ca8f/test/aqua/test_mcr.py
        """
        q_controls = QuantumRegister(num_controls)
        q_target = QuantumRegister(1)

        # iterate over all possible combinations of control qubits
        for ctrl_state in range(2**num_controls):
            bitstr = bin(ctrl_state)[2:].zfill(num_controls)[::-1]
            theta = 0.871236 * pi
            qc = QuantumCircuit(q_controls, q_target)
            for idx, bit in enumerate(bitstr):
                if bit == '0':
                    qc.x(q_controls[idx])

            # call mcrx/mcry/mcrz
            if base_gate_name == 'y':
                qc.mcry(theta,
                        q_controls,
                        q_target[0],
                        None,
                        mode='noancilla',
                        use_basis_gates=use_basis_gates)
            else:  # case 'x' or 'z' only support the noancilla mode and do not have this keyword
                getattr(qc, 'mcr' + base_gate_name)(
                    theta,
                    q_controls,
                    q_target[0],
                    use_basis_gates=use_basis_gates)

            for idx, bit in enumerate(bitstr):
                if bit == '0':
                    qc.x(q_controls[idx])

            backend = BasicAer.get_backend('unitary_simulator')
            simulated = execute(qc, backend).result().get_unitary(qc)

            if base_gate_name == 'x':
                rot_mat = RXGate(theta).to_matrix()
            elif base_gate_name == 'y':
                rot_mat = RYGate(theta).to_matrix()
            else:  # case 'z'
                rot_mat = U1Gate(theta).to_matrix()

            expected = _compute_control_matrix(rot_mat,
                                               num_controls,
                                               ctrl_state=ctrl_state)
            with self.subTest(msg='control state = {}'.format(ctrl_state)):
                self.assertTrue(matrix_equal(simulated, expected))
 def test_param_gate_instance(self):
     """Verify that the same Parameter gate instance is not being used in
     multiple circuits."""
     a, b = Parameter("a"), Parameter("b")
     rx = RXGate(a)
     qc0, qc1 = QuantumCircuit(1), QuantumCircuit(1)
     qc0.append(rx, [0])
     qc1.append(rx, [0])
     qc0.assign_parameters({a: b}, inplace=True)
     qc0_instance = next(iter(qc0._parameter_table[b]))[0]
     qc1_instance = next(iter(qc1._parameter_table[a]))[0]
     self.assertNotEqual(qc0_instance, qc1_instance)
    def test_hadamard_to_rot_gates(self):
        """Test a transpilation from H to Rx, Ry gates"""
        qr = QuantumRegister(1)
        qc = QuantumCircuit(qr)
        qc.h(0)

        expected = QuantumCircuit(qr, global_phase=np.pi / 2)
        expected.append(RYGate(theta=np.pi / 2), [0])
        expected.append(RXGate(theta=np.pi), [0])

        circuit = transpile(qc, basis_gates=['rx', 'ry'], optimization_level=0)
        self.assertEqual(circuit, expected)
class TestParameterCtrlState(QiskitTestCase):
    """Test gate equality with ctrl_state parameter."""
    @data((RXGate(0.5), CRXGate(0.5)), (RYGate(0.5), CRYGate(0.5)),
          (RZGate(0.5), CRZGate(0.5)), (XGate(), CXGate()),
          (YGate(), CYGate()), (ZGate(), CZGate()),
          (U1Gate(0.5), CU1Gate(0.5)), (SwapGate(), CSwapGate()),
          (HGate(), CHGate()), (U3Gate(0.1, 0.2, 0.3), CU3Gate(0.1, 0.2, 0.3)))
    @unpack
    def test_ctrl_state_one(self, gate, controlled_gate):
        """Test controlled gates with ctrl_state
        See https://github.com/Qiskit/qiskit-terra/pull/4025
        """
        self.assertEqual(gate.control(1, ctrl_state='1'), controlled_gate)
Example #17
0
 def test_instructions(self):
     self.assertEqual(self.empty_target.instructions, [])
     ibm_expected = [
         (IGate(), (0, )),
         (IGate(), (1, )),
         (IGate(), (2, )),
         (IGate(), (3, )),
         (IGate(), (4, )),
         (RZGate(self.theta), (0, )),
         (RZGate(self.theta), (1, )),
         (RZGate(self.theta), (2, )),
         (RZGate(self.theta), (3, )),
         (RZGate(self.theta), (4, )),
         (SXGate(), (0, )),
         (SXGate(), (1, )),
         (SXGate(), (2, )),
         (SXGate(), (3, )),
         (SXGate(), (4, )),
         (XGate(), (0, )),
         (XGate(), (1, )),
         (XGate(), (2, )),
         (XGate(), (3, )),
         (XGate(), (4, )),
         (CXGate(), (3, 4)),
         (CXGate(), (4, 3)),
         (CXGate(), (3, 1)),
         (CXGate(), (1, 3)),
         (CXGate(), (1, 2)),
         (CXGate(), (2, 1)),
         (CXGate(), (0, 1)),
         (CXGate(), (1, 0)),
         (Measure(), (0, )),
         (Measure(), (1, )),
         (Measure(), (2, )),
         (Measure(), (3, )),
         (Measure(), (4, )),
     ]
     self.assertEqual(ibm_expected, self.ibm_target.instructions)
     ideal_sim_expected = [
         (UGate(self.theta, self.phi, self.lam), None),
         (RXGate(self.theta), None),
         (RYGate(self.theta), None),
         (RZGate(self.theta), None),
         (CXGate(), None),
         (ECRGate(), None),
         (CCXGate(), None),
         (Measure(), None),
     ]
     self.assertEqual(ideal_sim_expected,
                      self.ideal_sim_target.instructions)
    def test_for_loop_invalid_instantiation(self):
        """Verify we catch invalid instantiations of ForLoopOp."""
        body = QuantumCircuit(3, 1)
        loop_parameter = Parameter("foo")
        indexset = range(0, 10, 2)

        body.rx(loop_parameter, 0)

        with self.assertWarnsRegex(UserWarning,
                                   r"loop_parameter was not found"):
            _ = ForLoopOp(indexset, Parameter("foo"), body)

        with self.assertRaisesRegex(CircuitError,
                                    r"to be of type QuantumCircuit"):
            _ = ForLoopOp(indexset, loop_parameter, RXGate(loop_parameter))
Example #19
0
 def test_instruction_schedule_map_ideal_sim_backend(self):
     ideal_sim_target = Target(num_qubits=3)
     theta = Parameter("theta")
     phi = Parameter("phi")
     lam = Parameter("lambda")
     for inst in [
             UGate(theta, phi, lam),
             RXGate(theta),
             RYGate(theta),
             RZGate(theta),
             CXGate(),
             ECRGate(),
             CCXGate(),
             Measure(),
     ]:
         ideal_sim_target.add_instruction(inst, {None: None})
     inst_map = ideal_sim_target.instruction_schedule_map()
     self.assertEqual(InstructionScheduleMap(), inst_map)
def RXDataset(angle_step=10, probability_step=10, shots=1024, save_dir=None):
    # define constants
    basis_gates = ['u3']
    simulator = QasmSimulator()
    df = pd.DataFrame()

    # generate circuits
    for angle in np.linspace(0, np.pi, angle_step, endpoint=True):
        # define circuit
        circ = QuantumCircuit(1, 1)
        rotate = RXGate(angle)
        circ.append(rotate, [0])
        circ.measure(0, 0)
        new_circ = qiskit.compiler.transpile(circ,
                                             basis_gates=basis_gates,
                                             optimization_level=0)
        print(new_circ)

        # generate noise models:
        for probability in np.linspace(0, 1, probability_step, endpoint=True):
            # add noise
            noise_model = NoiseModel()
            error = depolarizing_error(probability, 1)
            noise_model.add_all_qubit_quantum_error(error,
                                                    ['x', 'u1', 'u2', 'u3'])

            # execution - Noisy
            job = execute(new_circ,
                          simulator,
                          shots=shots,
                          noise_model=noise_model)
            result = job.result()

            # add to Pandas DF
            data = {
                'rx_theta': angle,
                'p': probability,
                'E': result.get_counts(0).get('0', 0) / shots
            }
            df = df.append(data, ignore_index=True)
    df = df[['rx_theta', 'E', 'p']]
    df.to_csv(save_dir + "/dataframe_RX.csv")
    return df
Example #21
0
    def test_single_circuit_calibrations(self):
        """Test that disassembler parses single circuit QOBJ calibrations (from QOBJ-level)."""
        theta = Parameter("theta")
        qc = QuantumCircuit(2)
        qc.h(0)
        qc.rx(np.pi, 0)
        qc.rx(theta, 1)
        qc = qc.assign_parameters({theta: np.pi})

        with pulse.build() as h_sched:
            pulse.play(pulse.library.Drag(1, 0.15, 4, 2), pulse.DriveChannel(0))

        with pulse.build() as x180:
            pulse.play(pulse.library.Gaussian(1, 0.2, 5), pulse.DriveChannel(0))

        qc.add_calibration("h", [0], h_sched)
        qc.add_calibration(RXGate(np.pi), [0], x180)

        qobj = assemble(qc, FakeOpenPulse2Q())
        output_circuits, _, _ = disassemble(qobj)

        self.assertCircuitCalibrationsEqual([qc], output_circuits)
Example #22
0
class TestCollect2qBlocks(QiskitTestCase):
    """
    Tests to verify that blocks of 2q interactions are found correctly.
    """
    def test_blocks_in_topological_order(self):
        """the pass returns blocks in correct topological order
                                                    ______
        q0:--[p]-------.----      q0:-------------|      |--
                       |                 ______   |  U2  |
        q1:--[u]--(+)-(+)---   =  q1:---|      |--|______|--
                   |                    |  U1  |
        q2:--------.--------      q2:---|______|------------
        """
        qr = QuantumRegister(3, "qr")
        qc = QuantumCircuit(qr)
        qc.p(0.5, qr[0])
        qc.u(0.0, 0.2, 0.6, qr[1])
        qc.cx(qr[2], qr[1])
        qc.cx(qr[0], qr[1])
        dag = circuit_to_dag(qc)

        topo_ops = list(dag.topological_op_nodes())
        block_1 = [topo_ops[1], topo_ops[2]]
        block_2 = [topo_ops[0], topo_ops[3]]

        pass_ = Collect2qBlocks()
        pass_.run(dag)
        self.assertTrue(pass_.property_set["block_list"], [block_1, block_2])

    def test_block_interrupted_by_gate(self):
        """Test that blocks interrupted by a gate that can't be added
        to the block can be collected correctly

        This was raised in #2775 where a measure in the middle of a block
        stopped the block collection from working properly. This was because
        the pass didn't expect to have measures in the middle of the circuit.

        blocks : [['cx', 'id', 'id', 'id'], ['id', 'cx']]

                โ”Œโ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”โ”Œโ”€โ”     โ”Œโ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”
        q_0: |0>โ”ค X โ”œโ”ค I โ”œโ”คMโ”œโ”€โ”€โ”€โ”€โ”€โ”ค I โ”œโ”ค X โ”œ
                โ””โ”€โ”ฌโ”€โ”˜โ”œโ”€โ”€โ”€โ”คโ””โ•ฅโ”˜โ”Œโ”€โ”€โ”€โ”โ””โ”€โ”€โ”€โ”˜โ””โ”€โ”ฌโ”€โ”˜
        q_1: |0>โ”€โ”€โ– โ”€โ”€โ”ค I โ”œโ”€โ•ซโ”€โ”ค I โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ– โ”€โ”€
                     โ””โ”€โ”€โ”€โ”˜ โ•‘ โ””โ”€โ”€โ”€โ”˜
         c_0: 0 โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฉโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

        """
        qc = QuantumCircuit(2, 1)
        qc.cx(1, 0)
        qc.i(0)
        qc.i(1)
        qc.measure(0, 0)
        qc.i(0)
        qc.i(1)
        qc.cx(1, 0)

        dag = circuit_to_dag(qc)
        pass_ = Collect2qBlocks()
        pass_.run(dag)

        # list from Collect2QBlocks of nodes that it should have put into blocks
        good_names = ["cx", "u1", "u2", "u3", "id"]
        dag_nodes = [
            node for node in dag.topological_op_nodes()
            if node.name in good_names
        ]

        # we have to convert them to sets as the ordering can be different
        # but equivalent between python 3.5 and 3.7
        # there is no implied topology in a block, so this isn't an issue
        dag_nodes = [set(dag_nodes[:4]), set(dag_nodes[4:])]
        pass_nodes = [set(bl) for bl in pass_.property_set["block_list"]]

        self.assertEqual(dag_nodes, pass_nodes)

    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)

        pass_manager = PassManager()
        pass_manager.append(Collect2qBlocks())

        pass_manager.run(qc)

        self.assertEqual(
            [["cx"]], [[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>โ”ค P(0.1) โ”œโ”ค P(0.2) โ”œโ”ค P(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 : [['p', 'p', 'p', '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.p(0.1, 0)
        qc.p(0.2, 0).c_if(cr, 0)
        qc.p(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())

        pass_manager.run(qc)
        self.assertEqual(
            [["cx"]], [[n.name for n in block]
                       for block in pass_manager.property_set["block_list"]])

    @unpack
    @data(
        (CXGate(), U1Gate(0.1), U2Gate(0.2, 0.3)),
        (RXXGate(pi / 2), RZGate(0.1), RXGate(pi / 2)),
        (
            Gate("custom2qgate", 2, []),
            Gate("custom1qgate1", 1, []),
            Gate("custom1qgate2", 1, []),
        ),
    )
    def test_collect_arbitrary_gates(self, twoQ_gate, oneQ_gate1, oneQ_gate2):
        """Validate we can collect blocks irrespective of gate types in the circuit."""

        qc = QuantumCircuit(3)

        # Block 1 - q[0] and q[1]
        qc.append(oneQ_gate1, [0])
        qc.append(oneQ_gate2, [1])
        qc.append(twoQ_gate, [0, 1])
        qc.append(oneQ_gate1, [0])
        qc.append(oneQ_gate2, [1])

        # Block 2 - q[1] and q[2]
        qc.append(oneQ_gate1, [1])
        qc.append(oneQ_gate2, [2])
        qc.append(twoQ_gate, [1, 2])
        qc.append(oneQ_gate1, [1])
        qc.append(oneQ_gate2, [2])

        # Block 3 - q[0] and q[1]
        qc.append(oneQ_gate1, [0])
        qc.append(oneQ_gate2, [1])
        qc.append(twoQ_gate, [0, 1])
        qc.append(oneQ_gate1, [0])
        qc.append(oneQ_gate2, [1])

        pass_manager = PassManager()
        pass_manager.append(Collect2qBlocks())

        pass_manager.run(qc)
        self.assertEqual(len(pass_manager.property_set["block_list"]), 3)
Example #23
0
class TestTwoLocal(QiskitTestCase):
    """Tests for the TwoLocal circuit."""

    def assertCircuitEqual(self, qc1, qc2, visual=False, transpiled=True):
        """An equality test specialized to circuits."""
        if transpiled:
            basis_gates = ['id', 'u1', 'u3', 'cx']
            qc1_transpiled = transpile(qc1, basis_gates=basis_gates, optimization_level=0)
            qc2_transpiled = transpile(qc2, basis_gates=basis_gates, optimization_level=0)
            qc1, qc2 = qc1_transpiled, qc2_transpiled

        if visual:
            self.assertEqual(qc1.draw(), qc2.draw())
        else:
            self.assertEqual(qc1, qc2)

    def test_skip_final_rotation_layer(self):
        """Test skipping the final rotation layer works."""
        two = TwoLocal(3, ['ry', 'h'], ['cz', 'cx'], reps=2, skip_final_rotation_layer=True)
        self.assertEqual(two.num_parameters, 6)  # would be 9 with a final rotation layer

    @data((5, 'rx', 'cx', 'full', 2, 15),
          (3, 'x', 'z', 'linear', 1, 0),
          (3, ['rx', 'ry'], ['cry', 'cx'], 'circular', 2, 24),
          )
    @unpack
    def test_num_parameters(self, num_qubits, rot, ent, ent_mode, reps, expected):
        """Test the number of parameters."""
        two = TwoLocal(num_qubits, rotation_blocks=rot, entanglement_blocks=ent,
                       entanglement=ent_mode, reps=reps)

        with self.subTest(msg='num_parameters_settable'):
            self.assertEqual(two.num_parameters_settable, expected)

        with self.subTest(msg='num_parameters'):
            self.assertEqual(two.num_parameters, expected)

    def test_empty_two_local(self):
        """Test the setup of an empty two-local circuit."""
        two = TwoLocal()

        with self.subTest(msg='0 qubits'):
            self.assertEqual(two.num_qubits, 0)

        with self.subTest(msg='no blocks are set'):
            self.assertListEqual(two.rotation_blocks, [])
            self.assertListEqual(two.entanglement_blocks, [])

        with self.subTest(msg='equal to empty circuit'):
            self.assertEqual(two, QuantumCircuit())

    @data('rx', RXGate(Parameter('p')), RXGate, 'circuit')
    def test_various_block_types(self, rot):
        """Test setting the rotation blocks to various type and assert the output type is RX."""
        if rot == 'circuit':
            rot = QuantumCircuit(1)
            rot.rx(Parameter('angle'), 0)

        two = TwoLocal(3, rot, 'cz', reps=1)
        self.assertEqual(len(two.rotation_blocks), 1)
        rotation = two.rotation_blocks[0]

        # decompose
        self.assertIsInstance(rotation.data[0][0], RXGate)

    def test_parameter_setters(self):
        """Test different possibilities to set parameters."""
        two = TwoLocal(3, rotation_blocks='rx', entanglement='cz', reps=2)
        params = [0, 1, 2, Parameter('x'), Parameter('y'), Parameter('z'), 6, 7, 0]
        params_set = set(param for param in params if isinstance(param, Parameter))

        with self.subTest(msg='dict assign and copy'):
            ordered = two.ordered_parameters
            bound = two.assign_parameters(dict(zip(ordered, params)), inplace=False)
            self.assertEqual(bound.parameters, params_set)
            self.assertEqual(two.num_parameters, 9)

        with self.subTest(msg='list assign and copy'):
            ordered = two.ordered_parameters
            bound = two.assign_parameters(params, inplace=False)
            self.assertEqual(bound.parameters, params_set)
            self.assertEqual(two.num_parameters, 9)

        with self.subTest(msg='list assign inplace'):
            ordered = two.ordered_parameters
            two.assign_parameters(params, inplace=True)
            self.assertEqual(two.parameters, params_set)
            self.assertEqual(two.num_parameters, 3)
            self.assertEqual(two.num_parameters_settable, 9)

    def test_parameters_settable_is_constant(self):
        """Test the attribute num_parameters_settable does not change on parameter change."""
        two = TwoLocal(3, rotation_blocks='rx', entanglement='cz', reps=2)
        ordered_params = two.ordered_parameters

        x = Parameter('x')
        two.assign_parameters(dict(zip(ordered_params, [x] * two.num_parameters)), inplace=True)

        with self.subTest(msg='num_parameters collapsed to 1'):
            self.assertEqual(two.num_parameters, 1)

        with self.subTest(msg='num_parameters_settable remained constant'):
            self.assertEqual(two.num_parameters_settable, len(ordered_params))

    def test_compose_inplace_to_circuit(self):
        """Test adding a two-local to an existing circuit."""
        two = TwoLocal(3, ['ry', 'rz'], 'cz', 'full', reps=1, insert_barriers=True)
        circuit = QuantumCircuit(3)
        circuit.compose(two, inplace=True)

        reference = QuantumCircuit(3)
        param_iter = iter(two.ordered_parameters)
        for i in range(3):
            reference.ry(next(param_iter), i)
        for i in range(3):
            reference.rz(next(param_iter), i)
        reference.barrier()
        reference.cz(0, 1)
        reference.cz(0, 2)
        reference.cz(1, 2)
        reference.barrier()
        for i in range(3):
            reference.ry(next(param_iter), i)
        for i in range(3):
            reference.rz(next(param_iter), i)

        self.assertCircuitEqual(circuit, reference)

    def test_composing_two(self):
        """Test adding two two-local circuits."""
        entangler_map = [[0, 3], [0, 2]]
        two = TwoLocal(4, [], 'cry', entangler_map, reps=1)
        circuit = two.compose(two)

        reference = QuantumCircuit(4)
        params = two.ordered_parameters
        for _ in range(2):
            reference.cry(params[0], 0, 3)
            reference.cry(params[1], 0, 2)

        self.assertCircuitEqual(reference, circuit)

    def test_ry_blocks(self):
        """Test that the RealAmplitudes circuit is instantiated correctly."""
        two = RealAmplitudes(4)
        with self.subTest(msg='test rotation gate'):
            self.assertEqual(len(two.rotation_blocks), 1)
            self.assertIsInstance(two.rotation_blocks[0].data[0][0], RYGate)

        with self.subTest(msg='test parameter bounds'):
            expected = [(-np.pi, np.pi)] * two.num_parameters
            np.testing.assert_almost_equal(two.parameter_bounds, expected)

    def test_ry_circuit(self):
        """Test an RealAmplitudes circuit."""
        num_qubits = 3
        reps = 2
        entanglement = 'full'
        parameters = ParameterVector('theta', num_qubits * (reps + 1))
        param_iter = iter(parameters)

        expected = QuantumCircuit(3)
        for _ in range(reps):
            for i in range(num_qubits):
                expected.ry(next(param_iter), i)
            expected.cx(0, 1)
            expected.cx(0, 2)
            expected.cx(1, 2)
        for i in range(num_qubits):
            expected.ry(next(param_iter), i)

        library = RealAmplitudes(num_qubits, reps=reps,
                                 entanglement=entanglement).assign_parameters(parameters)

        self.assertCircuitEqual(library, expected)

    def test_ryrz_blocks(self):
        """Test that the EfficientSU2 circuit is instantiated correctly."""
        two = EfficientSU2(3)
        with self.subTest(msg='test rotation gate'):
            self.assertEqual(len(two.rotation_blocks), 2)
            self.assertIsInstance(two.rotation_blocks[0].data[0][0], RYGate)
            self.assertIsInstance(two.rotation_blocks[1].data[0][0], RZGate)

        with self.subTest(msg='test parameter bounds'):
            expected = [(-np.pi, np.pi)] * two.num_parameters
            np.testing.assert_almost_equal(two.parameter_bounds, expected)

    def test_ryrz_circuit(self):
        """Test an EfficientSU2 circuit."""
        num_qubits = 3
        reps = 2
        entanglement = 'circular'
        parameters = ParameterVector('theta', 2 * num_qubits * (reps + 1))
        param_iter = iter(parameters)

        expected = QuantumCircuit(3)
        for _ in range(reps):
            for i in range(num_qubits):
                expected.ry(next(param_iter), i)
            for i in range(num_qubits):
                expected.rz(next(param_iter), i)
            expected.cx(2, 0)
            expected.cx(0, 1)
            expected.cx(1, 2)
        for i in range(num_qubits):
            expected.ry(next(param_iter), i)
        for i in range(num_qubits):
            expected.rz(next(param_iter), i)

        library = EfficientSU2(num_qubits, reps=reps, entanglement=entanglement).assign_parameters(
            parameters
        )

        self.assertCircuitEqual(library, expected)

    def test_swaprz_blocks(self):
        """Test that the ExcitationPreserving circuit is instantiated correctly."""
        two = ExcitationPreserving(5)
        with self.subTest(msg='test rotation gate'):
            self.assertEqual(len(two.rotation_blocks), 1)
            self.assertIsInstance(two.rotation_blocks[0].data[0][0], RZGate)

        with self.subTest(msg='test entanglement gate'):
            self.assertEqual(len(two.entanglement_blocks), 1)
            block = two.entanglement_blocks[0]
            self.assertEqual(len(block.data), 2)
            self.assertIsInstance(block.data[0][0], RXXGate)
            self.assertIsInstance(block.data[1][0], RYYGate)

        with self.subTest(msg='test parameter bounds'):
            expected = [(-np.pi, np.pi)] * two.num_parameters
            np.testing.assert_almost_equal(two.parameter_bounds, expected)

    def test_swaprz_circuit(self):
        """Test a ExcitationPreserving circuit in iswap mode."""
        num_qubits = 3
        reps = 2
        entanglement = 'linear'
        parameters = ParameterVector('theta', num_qubits * (reps + 1) + reps * (num_qubits - 1))
        param_iter = iter(parameters)

        expected = QuantumCircuit(3)
        for _ in range(reps):
            for i in range(num_qubits):
                expected.rz(next(param_iter), i)
            shared_param = next(param_iter)
            expected.rxx(shared_param, 0, 1)
            expected.ryy(shared_param, 0, 1)
            shared_param = next(param_iter)
            expected.rxx(shared_param, 1, 2)
            expected.ryy(shared_param, 1, 2)
        for i in range(num_qubits):
            expected.rz(next(param_iter), i)

        library = ExcitationPreserving(num_qubits, reps=reps,
                                       entanglement=entanglement).assign_parameters(parameters)

        self.assertCircuitEqual(library, expected)

    def test_fsim_circuit(self):
        """Test a ExcitationPreserving circuit in fsim mode."""
        num_qubits = 3
        reps = 2
        entanglement = 'linear'
        # need the parameters in the entanglement blocks to be the same because the order
        # can get mixed up in ExcitationPreserving (since parameters are not ordered in circuits)
        parameters = [1] * (num_qubits * (reps + 1) + reps * (1 + num_qubits))
        param_iter = iter(parameters)

        expected = QuantumCircuit(3)
        for _ in range(reps):
            for i in range(num_qubits):
                expected.rz(next(param_iter), i)
            shared_param = next(param_iter)
            expected.rxx(shared_param, 0, 1)
            expected.ryy(shared_param, 0, 1)
            expected.cp(next(param_iter), 0, 1)
            shared_param = next(param_iter)
            expected.rxx(shared_param, 1, 2)
            expected.ryy(shared_param, 1, 2)
            expected.cp(next(param_iter), 1, 2)
        for i in range(num_qubits):
            expected.rz(next(param_iter), i)

        library = ExcitationPreserving(num_qubits, reps=reps, mode='fsim',
                                       entanglement=entanglement).assign_parameters(parameters)

        self.assertCircuitEqual(library, expected)

    def test_circular_on_same_block_and_circuit_size(self):
        """Test circular entanglement works correctly if the circuit and block sizes match."""

        two = TwoLocal(2, 'ry', 'cx', entanglement='circular', reps=1)
        parameters = np.arange(two.num_parameters)

        ref = QuantumCircuit(2)
        ref.ry(parameters[0], 0)
        ref.ry(parameters[1], 1)
        ref.cx(0, 1)
        ref.ry(parameters[2], 0)
        ref.ry(parameters[3], 1)

        self.assertCircuitEqual(two.assign_parameters(parameters), ref)
Example #24
0
class TestTwoLocal(QiskitTestCase):
    """Tests for the TwoLocal circuit."""
    def assertCircuitEqual(self, qc1, qc2, visual=False, transpiled=True):
        """An equality test specialized to circuits."""
        if transpiled:
            basis_gates = ["id", "u1", "u3", "cx"]
            qc1_transpiled = transpile(qc1,
                                       basis_gates=basis_gates,
                                       optimization_level=0)
            qc2_transpiled = transpile(qc2,
                                       basis_gates=basis_gates,
                                       optimization_level=0)
            qc1, qc2 = qc1_transpiled, qc2_transpiled

        if visual:
            self.assertEqual(qc1.draw(), qc2.draw())
        else:
            self.assertEqual(qc1, qc2)

    def test_skip_final_rotation_layer(self):
        """Test skipping the final rotation layer works."""
        two = TwoLocal(3, ["ry", "h"], ["cz", "cx"],
                       reps=2,
                       skip_final_rotation_layer=True)
        self.assertEqual(two.num_parameters,
                         6)  # would be 9 with a final rotation layer

    @data(
        (5, "rx", "cx", "full", 2, 15),
        (3, "x", "z", "linear", 1, 0),
        (3, "rx", "cz", "linear", 0, 3),
        (3, ["rx", "ry"], ["cry", "cx"], "circular", 2, 24),
    )
    @unpack
    def test_num_parameters(self, num_qubits, rot, ent, ent_mode, reps,
                            expected):
        """Test the number of parameters."""
        two = TwoLocal(
            num_qubits,
            rotation_blocks=rot,
            entanglement_blocks=ent,
            entanglement=ent_mode,
            reps=reps,
        )

        with self.subTest(msg="num_parameters_settable"):
            self.assertEqual(two.num_parameters_settable, expected)

        with self.subTest(msg="num_parameters"):
            self.assertEqual(two.num_parameters, expected)

    def test_empty_two_local(self):
        """Test the setup of an empty two-local circuit."""
        two = TwoLocal()

        with self.subTest(msg="0 qubits"):
            self.assertEqual(two.num_qubits, 0)

        with self.subTest(msg="no blocks are set"):
            self.assertListEqual(two.rotation_blocks, [])
            self.assertListEqual(two.entanglement_blocks, [])

        with self.subTest(msg="equal to empty circuit"):
            self.assertEqual(two, QuantumCircuit())

    @data("rx", RXGate(Parameter("p")), RXGate, "circuit")
    def test_various_block_types(self, rot):
        """Test setting the rotation blocks to various type and assert the output type is RX."""
        if rot == "circuit":
            rot = QuantumCircuit(1)
            rot.rx(Parameter("angle"), 0)

        two = TwoLocal(3, rot, reps=0)
        self.assertEqual(len(two.rotation_blocks), 1)
        rotation = two.rotation_blocks[0]

        # decompose
        self.assertIsInstance(rotation.data[0].operation, RXGate)

    def test_parameter_setters(self):
        """Test different possibilities to set parameters."""
        two = TwoLocal(3, rotation_blocks="rx", entanglement="cz", reps=2)
        params = [
            0, 1, 2,
            Parameter("x"),
            Parameter("y"),
            Parameter("z"), 6, 7, 0
        ]
        params_set = {
            param
            for param in params if isinstance(param, Parameter)
        }

        with self.subTest(msg="dict assign and copy"):
            ordered = two.ordered_parameters
            bound = two.assign_parameters(dict(zip(ordered, params)),
                                          inplace=False)
            self.assertEqual(bound.parameters, params_set)
            self.assertEqual(two.num_parameters, 9)

        with self.subTest(msg="list assign and copy"):
            ordered = two.ordered_parameters
            bound = two.assign_parameters(params, inplace=False)
            self.assertEqual(bound.parameters, params_set)
            self.assertEqual(two.num_parameters, 9)

        with self.subTest(msg="list assign inplace"):
            ordered = two.ordered_parameters
            two.assign_parameters(params, inplace=True)
            self.assertEqual(two.parameters, params_set)
            self.assertEqual(two.num_parameters, 3)
            self.assertEqual(two.num_parameters_settable, 9)

    def test_parameters_settable_is_constant(self):
        """Test the attribute num_parameters_settable does not change on parameter change."""
        two = TwoLocal(3, rotation_blocks="rx", entanglement="cz", reps=2)
        ordered_params = two.ordered_parameters

        x = Parameter("x")
        two.assign_parameters(dict(
            zip(ordered_params, [x] * two.num_parameters)),
                              inplace=True)

        with self.subTest(msg="num_parameters collapsed to 1"):
            self.assertEqual(two.num_parameters, 1)

        with self.subTest(msg="num_parameters_settable remained constant"):
            self.assertEqual(two.num_parameters_settable, len(ordered_params))

    def test_compose_inplace_to_circuit(self):
        """Test adding a two-local to an existing circuit."""
        two = TwoLocal(3, ["ry", "rz"],
                       "cz",
                       "full",
                       reps=1,
                       insert_barriers=True)
        circuit = QuantumCircuit(3)
        circuit.compose(two, inplace=True)

        #      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ–‘           โ–‘ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        # q_0: โ”ค Ry(ฮธ[0]) โ”œโ”ค Rz(ฮธ[3]) โ”œโ”€โ–‘โ”€โ”€โ– โ”€โ”€โ– โ”€โ”€โ”€โ”€โ”€โ–‘โ”€โ”ค Ry(ฮธ[6]) โ”œโ”€โ”ค Rz(ฮธ[9]) โ”œ
        #      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ–‘  โ”‚  โ”‚     โ–‘ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”Œโ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
        # q_1: โ”ค Ry(ฮธ[1]) โ”œโ”ค Rz(ฮธ[4]) โ”œโ”€โ–‘โ”€โ”€โ– โ”€โ”€โ”ผโ”€โ”€โ– โ”€โ”€โ–‘โ”€โ”ค Ry(ฮธ[7]) โ”œโ”ค Rz(ฮธ[10]) โ”œ
        #      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ–‘     โ”‚  โ”‚  โ–‘ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
        # q_2: โ”ค Ry(ฮธ[2]) โ”œโ”ค Rz(ฮธ[5]) โ”œโ”€โ–‘โ”€โ”€โ”€โ”€โ”€โ– โ”€โ”€โ– โ”€โ”€โ–‘โ”€โ”ค Ry(ฮธ[8]) โ”œโ”ค Rz(ฮธ[11]) โ”œ
        #      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ–‘           โ–‘ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        reference = QuantumCircuit(3)
        param_iter = iter(two.ordered_parameters)
        for i in range(3):
            reference.ry(next(param_iter), i)
        for i in range(3):
            reference.rz(next(param_iter), i)
        reference.barrier()
        reference.cz(0, 1)
        reference.cz(0, 2)
        reference.cz(1, 2)
        reference.barrier()
        for i in range(3):
            reference.ry(next(param_iter), i)
        for i in range(3):
            reference.rz(next(param_iter), i)

        self.assertCircuitEqual(circuit.decompose(), reference)

    def test_composing_two(self):
        """Test adding two two-local circuits."""
        entangler_map = [[0, 3], [0, 2]]
        two = TwoLocal(4, [], "cry", entangler_map, reps=1)
        circuit = two.compose(two)

        reference = QuantumCircuit(4)
        params = two.ordered_parameters
        for _ in range(2):
            reference.cry(params[0], 0, 3)
            reference.cry(params[1], 0, 2)

        self.assertCircuitEqual(reference, circuit)

    def test_ry_blocks(self):
        """Test that the RealAmplitudes circuit is instantiated correctly."""
        two = RealAmplitudes(4)
        with self.subTest(msg="test rotation gate"):
            self.assertEqual(len(two.rotation_blocks), 1)
            self.assertIsInstance(two.rotation_blocks[0].data[0].operation,
                                  RYGate)

        with self.subTest(msg="test parameter bounds"):
            expected = [(-np.pi, np.pi)] * two.num_parameters
            np.testing.assert_almost_equal(two.parameter_bounds, expected)

    def test_ry_circuit_reverse_linear(self):
        """Test a RealAmplitudes circuit with entanglement = "reverse_linear"."""
        num_qubits = 3
        reps = 2
        entanglement = "reverse_linear"
        parameters = ParameterVector("theta", num_qubits * (reps + 1))
        param_iter = iter(parameters)

        expected = QuantumCircuit(3)
        for _ in range(reps):
            for i in range(num_qubits):
                expected.ry(next(param_iter), i)
            expected.cx(1, 2)
            expected.cx(0, 1)
        for i in range(num_qubits):
            expected.ry(next(param_iter), i)

        library = RealAmplitudes(
            num_qubits, reps=reps,
            entanglement=entanglement).assign_parameters(parameters)
        self.assertCircuitEqual(library, expected)

    def test_ry_circuit_full(self):
        """Test a RealAmplitudes circuit with entanglement = "full"."""
        num_qubits = 3
        reps = 2
        entanglement = "full"
        parameters = ParameterVector("theta", num_qubits * (reps + 1))
        param_iter = iter(parameters)

        #      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        # q_0: โ”ค Ry(ฮธ[0]) โ”œโ”€โ”€โ– โ”€โ”€โ”€โ”€โ– โ”€โ”€โ”ค Ry(ฮธ[3]) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ– โ”€โ”€โ”€โ”€โ– โ”€โ”€โ”ค Ry(ฮธ[6]) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
        #      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”Œโ”€โ”ดโ”€โ”  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”ดโ”€โ”  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        # q_1: โ”ค Ry(ฮธ[1]) โ”œโ”ค X โ”œโ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ– โ”€โ”€โ”€โ”€โ”ค Ry(ฮธ[4]) โ”œโ”ค X โ”œโ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ– โ”€โ”€โ”€โ”€โ”ค Ry(ฮธ[7]) โ”œ
        #      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ””โ”€โ”€โ”€โ”˜โ”Œโ”€โ”ดโ”€โ”     โ”Œโ”€โ”ดโ”€โ”  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ””โ”€โ”€โ”€โ”˜โ”Œโ”€โ”ดโ”€โ”     โ”Œโ”€โ”ดโ”€โ”  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
        # q_2: โ”ค Ry(ฮธ[2]) โ”œโ”€โ”€โ”€โ”€โ”€โ”ค X โ”œโ”€โ”€โ”€โ”€โ”€โ”ค X โ”œโ”€โ”€โ”ค Ry(ฮธ[5]) โ”œโ”€โ”€โ”€โ”€โ”€โ”ค X โ”œโ”€โ”€โ”€โ”€โ”€โ”ค X โ”œโ”€โ”€โ”ค Ry(ฮธ[8]) โ”œ
        #      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        expected = QuantumCircuit(3)
        for _ in range(reps):
            for i in range(num_qubits):
                expected.ry(next(param_iter), i)
            expected.cx(0, 1)
            expected.cx(0, 2)
            expected.cx(1, 2)
        for i in range(num_qubits):
            expected.ry(next(param_iter), i)

        library = RealAmplitudes(
            num_qubits, reps=reps,
            entanglement=entanglement).assign_parameters(parameters)
        self.assertCircuitEqual(library, expected)

    def test_ryrz_blocks(self):
        """Test that the EfficientSU2 circuit is instantiated correctly."""
        two = EfficientSU2(3)
        with self.subTest(msg="test rotation gate"):
            self.assertEqual(len(two.rotation_blocks), 2)
            self.assertIsInstance(two.rotation_blocks[0].data[0].operation,
                                  RYGate)
            self.assertIsInstance(two.rotation_blocks[1].data[0].operation,
                                  RZGate)

        with self.subTest(msg="test parameter bounds"):
            expected = [(-np.pi, np.pi)] * two.num_parameters
            np.testing.assert_almost_equal(two.parameter_bounds, expected)

    def test_ryrz_circuit(self):
        """Test an EfficientSU2 circuit."""
        num_qubits = 3
        reps = 2
        entanglement = "circular"
        parameters = ParameterVector("theta", 2 * num_qubits * (reps + 1))
        param_iter = iter(parameters)

        #      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”             ยป
        # q_0: โ”ค Ry(ฮธ[0]) โ”œโ”ค Rz(ฮธ[3]) โ”œโ”ค X โ”œโ”€โ”€โ– โ”€โ”€โ”ค Ry(ฮธ[6]) โ”œโ”ค Rz(ฮธ[9]) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ยป
        #      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ””โ”€โ”ฌโ”€โ”˜โ”Œโ”€โ”ดโ”€โ”โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ยป
        # q_1: โ”ค Ry(ฮธ[1]) โ”œโ”ค Rz(ฮธ[4]) โ”œโ”€โ”€โ”ผโ”€โ”€โ”ค X โ”œโ”€โ”€โ”€โ”€โ”€โ– โ”€โ”€โ”€โ”€โ”€โ”€โ”ค Ry(ฮธ[7]) โ”œโ”ค Rz(ฮธ[10]) โ”œยป
        #      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค  โ”‚  โ””โ”€โ”€โ”€โ”˜   โ”Œโ”€โ”ดโ”€โ”    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คยป
        # q_2: โ”ค Ry(ฮธ[2]) โ”œโ”ค Rz(ฮธ[5]) โ”œโ”€โ”€โ– โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค X โ”œโ”€โ”€โ”€โ”€โ”ค Ry(ฮธ[8]) โ”œโ”ค Rz(ฮธ[11]) โ”œยป
        #      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜             โ””โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ยป
        # ยซ     โ”Œโ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        # ยซq_0: โ”ค X โ”œโ”€โ”€โ– โ”€โ”€โ”ค Ry(ฮธ[12]) โ”œโ”ค Rz(ฮธ[15]) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
        # ยซ     โ””โ”€โ”ฌโ”€โ”˜โ”Œโ”€โ”ดโ”€โ”โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        # ยซq_1: โ”€โ”€โ”ผโ”€โ”€โ”ค X โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ– โ”€โ”€โ”€โ”€โ”€โ”€โ”ค Ry(ฮธ[13]) โ”œโ”ค Rz(ฮธ[16]) โ”œ
        # ยซ       โ”‚  โ””โ”€โ”€โ”€โ”˜    โ”Œโ”€โ”ดโ”€โ”    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
        # ยซq_2: โ”€โ”€โ– โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค X โ”œโ”€โ”€โ”€โ”€โ”ค Ry(ฮธ[14]) โ”œโ”ค Rz(ฮธ[17]) โ”œ
        # ยซ                   โ””โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        expected = QuantumCircuit(3)
        for _ in range(reps):
            for i in range(num_qubits):
                expected.ry(next(param_iter), i)
            for i in range(num_qubits):
                expected.rz(next(param_iter), i)
            expected.cx(2, 0)
            expected.cx(0, 1)
            expected.cx(1, 2)
        for i in range(num_qubits):
            expected.ry(next(param_iter), i)
        for i in range(num_qubits):
            expected.rz(next(param_iter), i)

        library = EfficientSU2(
            num_qubits, reps=reps,
            entanglement=entanglement).assign_parameters(parameters)

        self.assertCircuitEqual(library, expected)

    def test_swaprz_blocks(self):
        """Test that the ExcitationPreserving circuit is instantiated correctly."""
        two = ExcitationPreserving(5)
        with self.subTest(msg="test rotation gate"):
            self.assertEqual(len(two.rotation_blocks), 1)
            self.assertIsInstance(two.rotation_blocks[0].data[0].operation,
                                  RZGate)

        with self.subTest(msg="test entanglement gate"):
            self.assertEqual(len(two.entanglement_blocks), 1)
            block = two.entanglement_blocks[0]
            self.assertEqual(len(block.data), 2)
            self.assertIsInstance(block.data[0].operation, RXXGate)
            self.assertIsInstance(block.data[1].operation, RYYGate)

        with self.subTest(msg="test parameter bounds"):
            expected = [(-np.pi, np.pi)] * two.num_parameters
            np.testing.assert_almost_equal(two.parameter_bounds, expected)

    def test_swaprz_circuit(self):
        """Test a ExcitationPreserving circuit in iswap mode."""
        num_qubits = 3
        reps = 2
        entanglement = "linear"
        parameters = ParameterVector(
            "theta",
            num_qubits * (reps + 1) + reps * (num_qubits - 1))
        param_iter = iter(parameters)

        #      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”               ยป
        # q_0: โ”ค Rz(ฮธ[0]) โ”œโ”ค0           โ”œโ”ค0           โ”œโ”€โ”ค Rz(ฮธ[5]) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ยป
        #      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”‚  Rxx(ฮธ[3]) โ”‚โ”‚  Ryy(ฮธ[3]) โ”‚โ”Œโ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ยป
        # q_1: โ”ค Rz(ฮธ[1]) โ”œโ”ค1           โ”œโ”ค1           โ”œโ”ค0           โ”œโ”ค0           โ”œยป
        #      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚  Rxx(ฮธ[4]) โ”‚โ”‚  Ryy(ฮธ[4]) โ”‚ยป
        # q_2: โ”ค Rz(ฮธ[2]) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค1           โ”œโ”ค1           โ”œยป
        #      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ยป
        # ยซ                 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”               ยป
        # ยซq_0: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค0           โ”œโ”ค0           โ”œโ”ค Rz(ฮธ[10]) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ยป
        # ยซ     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚  Rxx(ฮธ[8]) โ”‚โ”‚  Ryy(ฮธ[8]) โ”‚โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ยป
        # ยซq_1: โ”ค Rz(ฮธ[6]) โ”œโ”ค1           โ”œโ”ค1           โ”œโ”ค0           โ”œโ”ค0           โ”œยป
        # ยซ     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚  Rxx(ฮธ[9]) โ”‚โ”‚  Ryy(ฮธ[9]) โ”‚ยป
        # ยซq_2: โ”ค Rz(ฮธ[7]) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค1           โ”œโ”ค1           โ”œยป
        # ยซ     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ยป
        # ยซ
        # ยซq_0: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
        # ยซ     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        # ยซq_1: โ”ค Rz(ฮธ[11]) โ”œ
        # ยซ     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
        # ยซq_2: โ”ค Rz(ฮธ[12]) โ”œ
        # ยซ     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        expected = QuantumCircuit(3)
        for _ in range(reps):
            for i in range(num_qubits):
                expected.rz(next(param_iter), i)
            shared_param = next(param_iter)
            expected.rxx(shared_param, 0, 1)
            expected.ryy(shared_param, 0, 1)
            shared_param = next(param_iter)
            expected.rxx(shared_param, 1, 2)
            expected.ryy(shared_param, 1, 2)
        for i in range(num_qubits):
            expected.rz(next(param_iter), i)

        library = ExcitationPreserving(
            num_qubits, reps=reps,
            entanglement=entanglement).assign_parameters(parameters)

        self.assertCircuitEqual(library, expected)

    def test_fsim_circuit(self):
        """Test a ExcitationPreserving circuit in fsim mode."""
        num_qubits = 3
        reps = 2
        entanglement = "linear"
        # need the parameters in the entanglement blocks to be the same because the order
        # can get mixed up in ExcitationPreserving (since parameters are not ordered in circuits)
        parameters = [1] * (num_qubits * (reps + 1) + reps * (1 + num_qubits))
        param_iter = iter(parameters)

        #      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                   ยป
        # q_0: โ”ค Rz(1) โ”œโ”ค0        โ”œโ”ค0        โ”œโ”€โ– โ”€โ”€โ”€โ”€โ”€โ”€โ”ค Rz(1) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ยป
        #      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”‚  Rxx(1) โ”‚โ”‚  Ryy(1) โ”‚ โ”‚P(1) โ”Œโ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       ยป
        # q_1: โ”ค Rz(1) โ”œโ”ค1        โ”œโ”ค1        โ”œโ”€โ– โ”€โ”€โ”€โ”€โ”€โ”ค0        โ”œโ”ค0        โ”œโ”€โ– โ”€โ”€โ”€โ”€โ”€ยป
        #      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ”‚  Rxx(1) โ”‚โ”‚  Ryy(1) โ”‚ โ”‚P(1) ยป
        # q_2: โ”ค Rz(1) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค1        โ”œโ”ค1        โ”œโ”€โ– โ”€โ”€โ”€โ”€โ”€ยป
        #      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                             โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       ยป
        # ยซ              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                   ยป
        # ยซq_0: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค0        โ”œโ”ค0        โ”œโ”€โ– โ”€โ”€โ”€โ”€โ”€โ”€โ”ค Rz(1) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ยป
        # ยซ     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚  Rxx(1) โ”‚โ”‚  Ryy(1) โ”‚ โ”‚P(1) โ”Œโ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       ยป
        # ยซq_1: โ”ค Rz(1) โ”œโ”ค1        โ”œโ”ค1        โ”œโ”€โ– โ”€โ”€โ”€โ”€โ”€โ”ค0        โ”œโ”ค0        โ”œโ”€โ– โ”€โ”€โ”€โ”€โ”€ยป
        # ยซ     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ”‚  Rxx(1) โ”‚โ”‚  Ryy(1) โ”‚ โ”‚P(1) ยป
        # ยซq_2: โ”ค Rz(1) โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค1        โ”œโ”ค1        โ”œโ”€โ– โ”€โ”€โ”€โ”€โ”€ยป
        # ยซ     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                             โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       ยป
        # ยซ
        # ยซq_0: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
        # ยซ     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        # ยซq_1: โ”ค Rz(1) โ”œ
        # ยซ     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
        # ยซq_2: โ”ค Rz(1) โ”œ
        # ยซ     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        expected = QuantumCircuit(3)
        for _ in range(reps):
            for i in range(num_qubits):
                expected.rz(next(param_iter), i)
            shared_param = next(param_iter)
            expected.rxx(shared_param, 0, 1)
            expected.ryy(shared_param, 0, 1)
            expected.cp(next(param_iter), 0, 1)
            shared_param = next(param_iter)
            expected.rxx(shared_param, 1, 2)
            expected.ryy(shared_param, 1, 2)
            expected.cp(next(param_iter), 1, 2)
        for i in range(num_qubits):
            expected.rz(next(param_iter), i)

        library = ExcitationPreserving(
            num_qubits, reps=reps, mode="fsim",
            entanglement=entanglement).assign_parameters(parameters)

        self.assertCircuitEqual(library, expected)

    def test_circular_on_same_block_and_circuit_size(self):
        """Test circular entanglement works correctly if the circuit and block sizes match."""

        two = TwoLocal(2, "ry", "cx", entanglement="circular", reps=1)
        parameters = np.arange(two.num_parameters)

        #      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        # q_0: โ”ค Ry(0) โ”œโ”€โ”€โ– โ”€โ”€โ”ค Ry(2) โ”œ
        #      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”Œโ”€โ”ดโ”€โ”โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
        # q_1: โ”ค Ry(1) โ”œโ”ค X โ”œโ”ค Ry(3) โ”œ
        #      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        ref = QuantumCircuit(2)
        ref.ry(parameters[0], 0)
        ref.ry(parameters[1], 1)
        ref.cx(0, 1)
        ref.ry(parameters[2], 0)
        ref.ry(parameters[3], 1)

        self.assertCircuitEqual(two.assign_parameters(parameters), ref)

    def test_circuit_with_numpy_integers(self):
        """Test if TwoLocal can be made from numpy integers"""
        num_qubits = 6
        reps = 3
        expected_np32 = [(i, j) for i in np.arange(num_qubits, dtype=np.int32)
                         for j in np.arange(num_qubits, dtype=np.int32)
                         if i < j]
        expected_np64 = [(i, j) for i in np.arange(num_qubits, dtype=np.int64)
                         for j in np.arange(num_qubits, dtype=np.int64)
                         if i < j]

        two_np32 = TwoLocal(num_qubits,
                            "ry",
                            "cx",
                            entanglement=expected_np32,
                            reps=reps)
        two_np64 = TwoLocal(num_qubits,
                            "ry",
                            "cx",
                            entanglement=expected_np64,
                            reps=reps)

        expected_cx = reps * num_qubits * (num_qubits - 1) / 2

        self.assertEqual(two_np32.decompose().count_ops()["cx"], expected_cx)
        self.assertEqual(two_np64.decompose().count_ops()["cx"], expected_cx)

    @combine(num_qubits=[4, 5])
    def test_full_vs_reverse_linear(self, num_qubits):
        """Test that 'full' and 'reverse_linear' provide the same unitary element."""
        reps = 2
        full = RealAmplitudes(num_qubits=num_qubits,
                              entanglement="full",
                              reps=reps)
        num_params = (reps + 1) * num_qubits
        np.random.seed(num_qubits)
        params = np.random.rand(num_params)
        reverse = RealAmplitudes(num_qubits=num_qubits,
                                 entanglement="reverse_linear",
                                 reps=reps)
        full.assign_parameters(params, inplace=True)
        reverse.assign_parameters(params, inplace=True)
        assert Operator(full) == Operator(reverse)
import qiskit
from qiskit import QuantumCircuit
from qiskit.circuit.library import RXGate
import numpy as np

basis_gates = ['u3']
circ = QuantumCircuit(1, 1)
RX = RXGate(0)
# circ.append(RX, [0])
circ.h(0)
circ.measure(0, 0)
print("Before Transpiling:")
print(circ)
new_circ = qiskit.compiler.transpile(circ,
                                     basis_gates=basis_gates,
                                     optimization_level=0)
print("After Transpiling:")
print(new_circ)
Example #26
0
    def setUp(self):
        super().setUp()
        self.fake_backend = FakeBackendV2()
        self.fake_backend_target = self.fake_backend.target
        self.theta = Parameter("theta")
        self.phi = Parameter("phi")
        self.ibm_target = Target()
        i_props = {
            (0, ): InstructionProperties(duration=35.5e-9, error=0.000413),
            (1, ): InstructionProperties(duration=35.5e-9, error=0.000502),
            (2, ): InstructionProperties(duration=35.5e-9, error=0.0004003),
            (3, ): InstructionProperties(duration=35.5e-9, error=0.000614),
            (4, ): InstructionProperties(duration=35.5e-9, error=0.006149),
        }
        self.ibm_target.add_instruction(IGate(), i_props)
        rz_props = {
            (0, ): InstructionProperties(duration=0, error=0),
            (1, ): InstructionProperties(duration=0, error=0),
            (2, ): InstructionProperties(duration=0, error=0),
            (3, ): InstructionProperties(duration=0, error=0),
            (4, ): InstructionProperties(duration=0, error=0),
        }
        self.ibm_target.add_instruction(RZGate(self.theta), rz_props)
        sx_props = {
            (0, ): InstructionProperties(duration=35.5e-9, error=0.000413),
            (1, ): InstructionProperties(duration=35.5e-9, error=0.000502),
            (2, ): InstructionProperties(duration=35.5e-9, error=0.0004003),
            (3, ): InstructionProperties(duration=35.5e-9, error=0.000614),
            (4, ): InstructionProperties(duration=35.5e-9, error=0.006149),
        }
        self.ibm_target.add_instruction(SXGate(), sx_props)
        x_props = {
            (0, ): InstructionProperties(duration=35.5e-9, error=0.000413),
            (1, ): InstructionProperties(duration=35.5e-9, error=0.000502),
            (2, ): InstructionProperties(duration=35.5e-9, error=0.0004003),
            (3, ): InstructionProperties(duration=35.5e-9, error=0.000614),
            (4, ): InstructionProperties(duration=35.5e-9, error=0.006149),
        }
        self.ibm_target.add_instruction(XGate(), x_props)
        cx_props = {
            (3, 4): InstructionProperties(duration=270.22e-9, error=0.00713),
            (4, 3): InstructionProperties(duration=305.77e-9, error=0.00713),
            (3, 1): InstructionProperties(duration=462.22e-9, error=0.00929),
            (1, 3): InstructionProperties(duration=497.77e-9, error=0.00929),
            (1, 2): InstructionProperties(duration=227.55e-9, error=0.00659),
            (2, 1): InstructionProperties(duration=263.11e-9, error=0.00659),
            (0, 1): InstructionProperties(duration=519.11e-9, error=0.01201),
            (1, 0): InstructionProperties(duration=554.66e-9, error=0.01201),
        }
        self.ibm_target.add_instruction(CXGate(), cx_props)
        measure_props = {
            (0, ): InstructionProperties(duration=5.813e-6, error=0.0751),
            (1, ): InstructionProperties(duration=5.813e-6, error=0.0225),
            (2, ): InstructionProperties(duration=5.813e-6, error=0.0146),
            (3, ): InstructionProperties(duration=5.813e-6, error=0.0215),
            (4, ): InstructionProperties(duration=5.813e-6, error=0.0333),
        }
        self.ibm_target.add_instruction(Measure(), measure_props)

        self.aqt_target = Target(description="AQT Target")
        rx_props = {
            (0, ): None,
            (1, ): None,
            (2, ): None,
            (3, ): None,
            (4, ): None,
        }
        self.aqt_target.add_instruction(RXGate(self.theta), rx_props)
        ry_props = {
            (0, ): None,
            (1, ): None,
            (2, ): None,
            (3, ): None,
            (4, ): None,
        }
        self.aqt_target.add_instruction(RYGate(self.theta), ry_props)
        rz_props = {
            (0, ): None,
            (1, ): None,
            (2, ): None,
            (3, ): None,
            (4, ): None,
        }
        self.aqt_target.add_instruction(RZGate(self.theta), rz_props)
        r_props = {
            (0, ): None,
            (1, ): None,
            (2, ): None,
            (3, ): None,
            (4, ): None,
        }
        self.aqt_target.add_instruction(RGate(self.theta, self.phi), r_props)
        rxx_props = {
            (0, 1): None,
            (0, 2): None,
            (0, 3): None,
            (0, 4): None,
            (1, 0): None,
            (2, 0): None,
            (3, 0): None,
            (4, 0): None,
            (1, 2): None,
            (1, 3): None,
            (1, 4): None,
            (2, 1): None,
            (3, 1): None,
            (4, 1): None,
            (2, 3): None,
            (2, 4): None,
            (3, 2): None,
            (4, 2): None,
            (3, 4): None,
            (4, 3): None,
        }
        self.aqt_target.add_instruction(RXXGate(self.theta), rxx_props)
        measure_props = {
            (0, ): None,
            (1, ): None,
            (2, ): None,
            (3, ): None,
            (4, ): None,
        }
        self.aqt_target.add_instruction(Measure(), measure_props)
        self.empty_target = Target()
        self.ideal_sim_target = Target(num_qubits=3,
                                       description="Ideal Simulator")
        self.lam = Parameter("lam")
        for inst in [
                UGate(self.theta, self.phi, self.lam),
                RXGate(self.theta),
                RYGate(self.theta),
                RZGate(self.theta),
                CXGate(),
                ECRGate(),
                CCXGate(),
                Measure(),
        ]:
            self.ideal_sim_target.add_instruction(inst, {None: None})
 def test_controlled_rx(self):
     """Test the creation of a controlled RX gate."""
     theta = 0.5
     self.assertEqual(RXGate(theta).control(), CRXGate(theta))
    def convert(
        self,
        operator: CircuitStateFn,
        params: Optional[Union[ParameterExpression, ParameterVector,
                               List[ParameterExpression]]] = None,
    ) -> ListOp:
        r"""
        Args:
            operator: The operator corresponding to the quantum state :math:`|\psi(\omega)\rangle`
                for which we compute the QFI.
            params: The parameters :math:`\omega` with respect to which we are computing the QFI.

        Returns:
            A ``ListOp[ListOp]`` where the operator at position ``[k][l]`` corresponds to the matrix
            element :math:`k, l` of the QFI.

        Raises:
            AquaError: If one of the circuits could not be constructed.
            TypeError: If ``operator`` is an unsupported type.
        """

        # QFI & phase fix observable
        qfi_observable = ~StateFn(4 * Z ^ (I ^ operator.num_qubits))
        phase_fix_observable = ~StateFn((X + 1j * Y)
                                        ^ (I ^ operator.num_qubits))
        # see https://arxiv.org/pdf/quant-ph/0108146.pdf

        # Check if the given operator corresponds to a quantum state given as a circuit.
        if not isinstance(operator, CircuitStateFn):
            raise TypeError(
                'LinCombFull is only compatible with states that are given as CircuitStateFn'
            )

        # If a single parameter is given wrap it into a list.
        if not isinstance(params, (list, np.ndarray)):
            params = [params]
        state_qc = operator.primitive

        # First, the operators are computed which can compensate for a potential phase-mismatch
        # between target and trained state, i.e.ใ€ˆฯˆ|โˆ‚lฯˆใ€‰
        phase_fix_states = None
        # Add working qubit
        qr_work = QuantumRegister(1, 'work_qubit')
        work_q = qr_work[0]
        additional_qubits: Tuple[List[Qubit], List[Qubit]] = ([work_q], [])
        for param in params:
            # Get the gates of the given quantum state which are parameterized by param
            param_gates = state_qc._parameter_table[param]
            # Loop through the occurrences of param in the quantum state
            for m, param_occurence in enumerate(param_gates):
                # Get the coefficients and gates for the linear combination gradient for each
                # occurrence, see e.g. https://arxiv.org/abs/2006.06004
                coeffs_i, gates_i = LinComb._gate_gradient_dict(
                    param_occurence[0])[param_occurence[1]]
                # Construct the quantum states which are then evaluated for the respective QFI
                # element.
                for k, gate_to_insert_i in enumerate(gates_i):
                    grad_state = state_qc.copy()
                    grad_state.add_register(qr_work)

                    # apply Hadamard on work_q
                    LinComb.insert_gate(grad_state,
                                        param_occurence[0],
                                        HGate(),
                                        qubits=[work_q])
                    # Fix work_q phase such that the gradient is correct.
                    coeff_i = coeffs_i[k]
                    sign = np.sign(coeff_i)
                    is_complex = np.iscomplex(coeff_i)
                    if sign == -1:
                        if is_complex:
                            LinComb.insert_gate(grad_state,
                                                param_occurence[0],
                                                SdgGate(),
                                                qubits=[work_q])
                        else:
                            LinComb.insert_gate(grad_state,
                                                param_occurence[0],
                                                ZGate(),
                                                qubits=[work_q])
                    else:
                        if is_complex:
                            LinComb.insert_gate(grad_state,
                                                param_occurence[0],
                                                SGate(),
                                                qubits=[work_q])

                    # Insert controlled, intercepting gate - controlled by |0>

                    if isinstance(param_occurence[0], UGate):
                        if param_occurence[1] == 0:
                            LinComb.insert_gate(
                                grad_state, param_occurence[0],
                                RZGate(param_occurence[0].params[2]))
                            LinComb.insert_gate(grad_state, param_occurence[0],
                                                RXGate(np.pi / 2))
                            LinComb.insert_gate(
                                grad_state,
                                param_occurence[0],
                                gate_to_insert_i,
                                additional_qubits=additional_qubits)
                            LinComb.insert_gate(grad_state, param_occurence[0],
                                                RXGate(-np.pi / 2))
                            LinComb.insert_gate(
                                grad_state, param_occurence[0],
                                RZGate(-param_occurence[0].params[2]))

                        elif param_occurence[1] == 1:
                            LinComb.insert_gate(
                                grad_state,
                                param_occurence[0],
                                gate_to_insert_i,
                                after=True,
                                additional_qubits=additional_qubits)
                        else:
                            LinComb.insert_gate(
                                grad_state,
                                param_occurence[0],
                                gate_to_insert_i,
                                additional_qubits=additional_qubits)
                    else:
                        LinComb.insert_gate(
                            grad_state,
                            param_occurence[0],
                            gate_to_insert_i,
                            additional_qubits=additional_qubits)

                    # Remove unnecessary gates.
                    grad_state = self.trim_circuit(grad_state,
                                                   param_occurence[0])
                    # Apply the final Hadamard on the working qubit.
                    grad_state.h(work_q)
                    # Add the coefficient needed for the gradient as well as the original
                    # coefficient of the given quantum state.
                    state = np.sqrt(np.abs(
                        coeff_i)) * operator.coeff * CircuitStateFn(grad_state)

                    # Check if the gate parameter corresponding to param is a parameter expression
                    gate_param = param_occurence[0].params[param_occurence[1]]
                    if gate_param == param:
                        state = phase_fix_observable @ state
                    else:
                        # If the gate parameter is a parameter expressions the chain rule needs
                        # to be taken into account.
                        if isinstance(gate_param, ParameterExpression):
                            expr_grad = DerivativeBase.parameter_expression_grad(
                                gate_param, param)
                            state = (expr_grad * phase_fix_observable) @ state
                        else:
                            state *= 0

                    if m == 0 and k == 0:
                        phase_fix_state = state
                    else:
                        # Take the product rule into account
                        phase_fix_state += state
            # Create a list for the phase fix states
            if not phase_fix_states:
                phase_fix_states = [phase_fix_state]
            else:
                phase_fix_states += [phase_fix_state]

        # Get  4 * Re[ใ€ˆโˆ‚kฯˆ|โˆ‚lฯˆ]
        qfi_operators = []
        # Add a working qubit
        qr_work_qubit = QuantumRegister(1, 'work_qubit')
        work_qubit = qr_work_qubit[0]
        additional_qubits = ([work_qubit], [])
        # create a copy of the original circuit with an additional work_qubit register
        circuit = state_qc.copy()
        circuit.add_register(qr_work_qubit)
        # Apply a Hadamard on the working qubit
        LinComb.insert_gate(circuit,
                            state_qc._parameter_table[params[0]][0][0],
                            HGate(),
                            qubits=[work_qubit])

        # Get the circuits needed to computeใ€ˆโˆ‚iฯˆ|โˆ‚jฯˆใ€‰
        for i, param_i in enumerate(params):  # loop over parameters
            qfi_ops = None
            for j, param_j in enumerate(params):
                # Get the gates of the quantum state which are parameterized by param_i
                param_gates_i = state_qc._parameter_table[param_i]
                for m_i, param_occurence_i in enumerate(param_gates_i):
                    coeffs_i, gates_i = LinComb._gate_gradient_dict(
                        param_occurence_i[0])[param_occurence_i[1]]

                    for k_i, gate_to_insert_i in enumerate(gates_i):
                        coeff_i = coeffs_i[k_i]
                        # Get the gates of the quantum state which are parameterized by param_j
                        param_gates_j = state_qc._parameter_table[param_j]
                        for m_j, param_occurence_j in enumerate(param_gates_j):
                            coeffs_j, gates_j = \
                                LinComb._gate_gradient_dict(param_occurence_j[0])[
                                    param_occurence_j[1]]
                            for k_j, gate_to_insert_j in enumerate(gates_j):
                                coeff_j = coeffs_j[k_j]

                                # create a copy of the original circuit with the same registers
                                qfi_circuit = QuantumCircuit(*circuit.qregs)
                                qfi_circuit.data = circuit.data

                                # Correct the phase of the working qubit according to coefficient i
                                # and coefficient j
                                sign = np.sign(np.conj(coeff_i) * coeff_j)
                                is_complex = np.iscomplex(
                                    np.conj(coeff_i) * coeff_j)
                                if sign == -1:
                                    if is_complex:
                                        LinComb.insert_gate(
                                            qfi_circuit,
                                            param_occurence_i[0],
                                            SdgGate(),
                                            qubits=[work_qubit])
                                    else:
                                        LinComb.insert_gate(
                                            qfi_circuit,
                                            param_occurence_i[0],
                                            ZGate(),
                                            qubits=[work_qubit])
                                else:
                                    if is_complex:
                                        LinComb.insert_gate(
                                            qfi_circuit,
                                            param_occurence_i[0],
                                            SGate(),
                                            qubits=[work_qubit])

                                LinComb.insert_gate(qfi_circuit,
                                                    param_occurence_i[0],
                                                    XGate(),
                                                    qubits=[work_qubit])

                                # Insert controlled, intercepting gate i - controlled by |1>
                                if isinstance(param_occurence_i[0], UGate):
                                    if param_occurence_i[1] == 0:
                                        LinComb.insert_gate(
                                            qfi_circuit, param_occurence_i[0],
                                            RZGate(param_occurence_i[0].
                                                   params[2]))
                                        LinComb.insert_gate(
                                            qfi_circuit, param_occurence_i[0],
                                            RXGate(np.pi / 2))
                                        LinComb.insert_gate(
                                            qfi_circuit,
                                            param_occurence_i[0],
                                            gate_to_insert_i,
                                            additional_qubits=additional_qubits
                                        )
                                        LinComb.insert_gate(
                                            qfi_circuit, param_occurence_i[0],
                                            RXGate(-np.pi / 2))
                                        LinComb.insert_gate(
                                            qfi_circuit, param_occurence_i[0],
                                            RZGate(-param_occurence_i[0].
                                                   params[2]))

                                    elif param_occurence_i[1] == 1:
                                        LinComb.insert_gate(
                                            qfi_circuit,
                                            param_occurence_i[0],
                                            gate_to_insert_i,
                                            after=True,
                                            additional_qubits=additional_qubits
                                        )
                                    else:
                                        LinComb.insert_gate(
                                            qfi_circuit,
                                            param_occurence_i[0],
                                            gate_to_insert_i,
                                            additional_qubits=additional_qubits
                                        )
                                else:
                                    LinComb.insert_gate(
                                        qfi_circuit,
                                        param_occurence_i[0],
                                        gate_to_insert_i,
                                        additional_qubits=additional_qubits)

                                LinComb.insert_gate(qfi_circuit,
                                                    gate_to_insert_i,
                                                    XGate(),
                                                    qubits=[work_qubit],
                                                    after=True)

                                # Insert controlled, intercepting gate j - controlled by |0>
                                if isinstance(param_occurence_j[0], UGate):
                                    if param_occurence_j[1] == 0:
                                        LinComb.insert_gate(
                                            qfi_circuit, param_occurence_j[0],
                                            RZGate(param_occurence_j[0].
                                                   params[2]))
                                        LinComb.insert_gate(
                                            qfi_circuit, param_occurence_j[0],
                                            RXGate(np.pi / 2))
                                        LinComb.insert_gate(
                                            qfi_circuit,
                                            param_occurence_j[0],
                                            gate_to_insert_j,
                                            additional_qubits=additional_qubits
                                        )
                                        LinComb.insert_gate(
                                            qfi_circuit, param_occurence_j[0],
                                            RXGate(-np.pi / 2))
                                        LinComb.insert_gate(
                                            qfi_circuit, param_occurence_j[0],
                                            RZGate(-param_occurence_j[0].
                                                   params[2]))

                                    elif param_occurence_j[1] == 1:
                                        LinComb.insert_gate(
                                            qfi_circuit,
                                            param_occurence_j[0],
                                            gate_to_insert_j,
                                            after=True,
                                            additional_qubits=additional_qubits
                                        )
                                    else:
                                        LinComb.insert_gate(
                                            qfi_circuit,
                                            param_occurence_j[0],
                                            gate_to_insert_j,
                                            additional_qubits=additional_qubits
                                        )
                                else:
                                    LinComb.insert_gate(
                                        qfi_circuit,
                                        param_occurence_j[0],
                                        gate_to_insert_j,
                                        additional_qubits=additional_qubits)

                                # Remove redundant gates

                                if j <= i:
                                    qfi_circuit = self.trim_circuit(
                                        qfi_circuit, param_occurence_i[0])
                                else:
                                    qfi_circuit = self.trim_circuit(
                                        qfi_circuit, param_occurence_j[0])
                                # Apply final Hadamard gate
                                qfi_circuit.h(work_qubit)
                                # Convert the quantum circuit into a CircuitStateFn and add the
                                # coefficients i, j and the original operator coefficient
                                term = np.sqrt(
                                    np.abs(coeff_i) *
                                    np.abs(coeff_j)) * operator.coeff
                                term = term * CircuitStateFn(qfi_circuit)

                                # Check if the gate parameters i and j are parameter expressions
                                gate_param_i = param_occurence_i[0].params[
                                    param_occurence_i[1]]
                                gate_param_j = param_occurence_j[0].params[
                                    param_occurence_j[1]]

                                meas = deepcopy(qfi_observable)
                                # If the gate parameter i is a parameter expression use the chain
                                # rule.
                                if isinstance(gate_param_i,
                                              ParameterExpression):
                                    expr_grad = DerivativeBase.parameter_expression_grad(
                                        gate_param_i, param_i)
                                    meas *= expr_grad
                                # If the gate parameter j is a parameter expression use the chain
                                # rule.
                                if isinstance(gate_param_j,
                                              ParameterExpression):
                                    expr_grad = DerivativeBase.parameter_expression_grad(
                                        gate_param_j, param_j)
                                    meas *= expr_grad
                                term = meas @ term

                                if m_i == 0 and k_i == 0 and m_j == 0 and k_j == 0:
                                    qfi_op = term
                                else:
                                    # Product Rule
                                    qfi_op += term

                # Compute โˆ’4 * Re(ใ€ˆโˆ‚kฯˆ|ฯˆใ€‰ใ€ˆฯˆ|โˆ‚lฯˆใ€‰)
                def phase_fix_combo_fn(x):
                    return 4 * (-0.5) * (x[0] * np.conjugate(x[1]) +
                                         x[1] * np.conjugate(x[0]))

                phase_fix = ListOp([phase_fix_states[i], phase_fix_states[j]],
                                   combo_fn=phase_fix_combo_fn)
                # Add the phase fix quantities to the entries of the QFI
                # Get 4 * Re[ใ€ˆโˆ‚kฯˆ|โˆ‚lฯˆใ€‰โˆ’ใ€ˆโˆ‚kฯˆ|ฯˆใ€‰ใ€ˆฯˆ|โˆ‚lฯˆใ€‰]
                if not qfi_ops:
                    qfi_ops = [qfi_op + phase_fix]
                else:
                    qfi_ops += [qfi_op + phase_fix]
            qfi_operators.append(ListOp(qfi_ops))
        # Return the full QFI
        return ListOp(qfi_operators)