コード例 #1
0
    def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None):
        r"""Return controlled version of gate

        Args:
            num_ctrl_qubits (int): number of controls to add to gate (default=1)
            label (str): optional gate label
            ctrl_state (int or str or None): The control state in decimal or as a
                bit string (e.g. '1011'). If None, use 2**num_ctrl_qubits-1.

        Returns:
            UnitaryGate: controlled version of gate.

        Raises:
            QiskitError: Invalid ctrl_state.
            ExtensionError: Non-unitary controlled unitary.
        """
        cmat = _compute_control_matrix(self.to_matrix(),
                                       num_ctrl_qubits,
                                       ctrl_state=None)
        iso = isometry.Isometry(cmat, 0, 0)
        cunitary = ControlledGate('c-unitary',
                                  num_qubits=self.num_qubits + num_ctrl_qubits,
                                  params=[cmat],
                                  label=label,
                                  num_ctrl_qubits=num_ctrl_qubits,
                                  definition=iso.definition,
                                  ctrl_state=ctrl_state)

        from qiskit.quantum_info import Operator
        # hack to correct global phase; should fix to prevent need for correction here
        pmat = (Operator(iso.inverse()).data @ cmat)
        diag = numpy.diag(pmat)
        if not numpy.allclose(diag, diag[0]):
            raise ExtensionError('controlled unitary generation failed')
        phase = numpy.angle(diag[0])
        if phase:
            # need to apply to _definition since open controls creates temporary definition
            cunitary._definition.global_phase = phase
        cunitary.base_gate = self.copy()
        cunitary.base_gate.label = self.label
        return cunitary
コード例 #2
0
 def test_base_gate_setting(self):
     """
     Test all gates in standard extensions which are of type ControlledGate
     have a base gate setting.
     """
     params = [0.1 * i for i in range(10)]
     for gate_class in ControlledGate.__subclasses__():
         sig = signature(gate_class.__init__)
         free_params = len(sig.parameters) - 1  # subtract "self"
         base_gate = gate_class(*params[0:free_params])
         cgate = base_gate.control()
         self.assertEqual(base_gate.base_gate, cgate.base_gate)
コード例 #3
0
 def setUpClass(cls):
     class_list = Gate.__subclasses__() + ControlledGate.__subclasses__()
     exclude = {
         'ControlledGate', 'DiagonalGate', 'UCGate', 'MCGupDiag',
         'MCU1Gate', 'UnitaryGate', 'HamiltonianGate', 'MCPhaseGate',
         'UCPauliRotGate', 'SingleQubitUnitary', 'MCXGate',
         'VariadicZeroParamGate', 'ClassicalFunction'
     }
     cls._gate_classes = []
     for aclass in class_list:
         if aclass.__name__ not in exclude:
             cls._gate_classes.append(aclass)
コード例 #4
0
 def test_base_gate_setting(self):
     """
     Test all gates in standard extensions which are of type ControlledGate and have a base gate
     setting.
     """
     params = [0.1 * i for i in range(10)]
     for gate_class in ControlledGate.__subclasses__():
         num_free_params = len(
             _get_free_params(gate_class.__init__, ignore=['self']))
         free_params = params[:num_free_params]
         if gate_class in [allGates.MCU1Gate]:
             free_params[1] = 3
         base_gate = gate_class(*free_params)
         cgate = base_gate.control()
         self.assertEqual(base_gate.base_gate, cgate.base_gate)
コード例 #5
0
    def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None):
        r"""Return controlled version of gate

        Args:
            num_ctrl_qubits (int): number of controls to add to gate (default=1)
            label (str): optional gate label
            ctrl_state (int or str or None): The control state in decimal or as a
                bit string (e.g. '1011'). If None, use 2**num_ctrl_qubits-1.

        Returns:
            UnitaryGate: controlled version of gate.

        Raises:
            QiskitError: invalid ctrl_state
        """
        cmat = _compute_control_matrix(self.to_matrix(), num_ctrl_qubits)
        iso = isometry.Isometry(cmat, 0, 0)
        return ControlledGate('c-unitary', self.num_qubits + num_ctrl_qubits, cmat,
                              definition=iso.definition, label=label)
コード例 #6
0
 def setUpClass(cls):
     class_list = Gate.__subclasses__() + ControlledGate.__subclasses__()
     exclude = {
         "ControlledGate",
         "DiagonalGate",
         "UCGate",
         "MCGupDiag",
         "MCU1Gate",
         "UnitaryGate",
         "HamiltonianGate",
         "MCPhaseGate",
         "UCPauliRotGate",
         "SingleQubitUnitary",
         "MCXGate",
         "VariadicZeroParamGate",
         "ClassicalFunction",
         "ClassicalElement",
     }
     cls._gate_classes = []
     for aclass in class_list:
         if aclass.__name__ not in exclude:
             cls._gate_classes.append(aclass)
コード例 #7
0
class TestOpenControlledToMatrix(QiskitTestCase):
    """Test controlled_gates implementing to_matrix work with ctrl_state"""
    @combine(gate_class=ControlledGate.__subclasses__(), ctrl_state=[0, None])
    def test_open_controlled_to_matrix(self, gate_class, ctrl_state):
        """Test open controlled to_matrix."""
        num_free_params = len(
            _get_free_params(gate_class.__init__, ignore=['self']))
        free_params = [0.1 * i for i in range(1, num_free_params + 1)]
        if gate_class in [MCU1Gate]:
            free_params[1] = 3
        elif gate_class in [MCXGate]:
            free_params[0] = 3
        cgate = gate_class(*free_params)
        cgate.ctrl_state = ctrl_state
        base_mat = Operator(cgate.base_gate).data
        target = _compute_control_matrix(base_mat,
                                         cgate.num_ctrl_qubits,
                                         ctrl_state=ctrl_state)
        try:
            actual = cgate.to_matrix()
        except CircuitError as cerr:
            self.skipTest(cerr)
        self.assertTrue(np.allclose(actual, target))
コード例 #8
0
class TestControlledGate(QiskitTestCase):
    """Tests for controlled gates and the ControlledGate class."""
    def test_controlled_x(self):
        """Test creation of controlled x gate"""
        self.assertEqual(XGate().control(), CXGate())

    def test_controlled_y(self):
        """Test creation of controlled y gate"""
        self.assertEqual(YGate().control(), CYGate())

    def test_controlled_z(self):
        """Test creation of controlled z gate"""
        self.assertEqual(ZGate().control(), CZGate())

    def test_controlled_h(self):
        """Test the creation of a controlled H gate."""
        self.assertEqual(HGate().control(), CHGate())

    def test_controlled_u1(self):
        """Test the creation of a controlled U1 gate."""
        theta = 0.5
        self.assertEqual(U1Gate(theta).control(), CU1Gate(theta))

    def test_controlled_rz(self):
        """Test the creation of a controlled RZ gate."""
        theta = 0.5
        self.assertEqual(RZGate(theta).control(), CRZGate(theta))

    def test_controlled_ry(self):
        """Test the creation of a controlled RY gate."""
        theta = 0.5
        self.assertEqual(RYGate(theta).control(), CRYGate(theta))

    def test_controlled_rx(self):
        """Test the creation of a controlled RX gate."""
        theta = 0.5
        self.assertEqual(RXGate(theta).control(), CRXGate(theta))

    def test_controlled_u3(self):
        """Test the creation of a controlled U3 gate."""
        theta, phi, lamb = 0.1, 0.2, 0.3
        self.assertEqual(
            U3Gate(theta, phi, lamb).control(), CU3Gate(theta, phi, lamb))

    def test_controlled_cx(self):
        """Test creation of controlled cx gate"""
        self.assertEqual(CXGate().control(), CCXGate())

    def test_controlled_swap(self):
        """Test creation of controlled swap gate"""
        self.assertEqual(SwapGate().control(), CSwapGate())

    def test_circuit_append(self):
        """Test appending a controlled gate to a quantum circuit."""
        circ = QuantumCircuit(5)
        inst = CXGate()
        circ.append(inst.control(), qargs=[0, 2, 1])
        circ.append(inst.control(2), qargs=[0, 3, 1, 2])
        circ.append(inst.control().control(),
                    qargs=[0, 3, 1, 2])  # should be same as above
        self.assertEqual(circ[1][0], circ[2][0])
        self.assertEqual(circ.depth(), 3)
        self.assertEqual(circ[0][0].num_ctrl_qubits, 2)
        self.assertEqual(circ[1][0].num_ctrl_qubits, 3)
        self.assertEqual(circ[2][0].num_ctrl_qubits, 3)
        self.assertEqual(circ[0][0].num_qubits, 3)
        self.assertEqual(circ[1][0].num_qubits, 4)
        self.assertEqual(circ[2][0].num_qubits, 4)
        for instr in circ:
            gate = instr[0]
            self.assertTrue(isinstance(gate, ControlledGate))

    def test_swap_definition_specification(self):
        """Test the instantiation of a controlled swap gate with explicit definition."""
        swap = SwapGate()
        cswap = ControlledGate('cswap',
                               3, [],
                               num_ctrl_qubits=1,
                               definition=swap.definition)
        self.assertEqual(swap.definition, cswap.definition)

    def test_multi_controlled_composite_gate(self):
        """Test a multi controlled composite gate. """
        num_ctrl = 3
        # create composite gate
        sub_q = QuantumRegister(2)
        cgate = QuantumCircuit(sub_q, name='cgate')
        cgate.h(sub_q[0])
        cgate.crz(pi / 2, sub_q[0], sub_q[1])
        cgate.swap(sub_q[0], sub_q[1])
        cgate.u3(0.1, 0.2, 0.3, sub_q[1])
        cgate.t(sub_q[0])
        num_target = cgate.width()
        gate = cgate.to_gate()
        cont_gate = gate.control(num_ctrl_qubits=num_ctrl)
        control = QuantumRegister(num_ctrl)
        target = QuantumRegister(num_target)
        qc = QuantumCircuit(control, target)
        qc.append(cont_gate, control[:] + target[:])
        simulator = BasicAer.get_backend('unitary_simulator')
        op_mat = execute(cgate, simulator).result().get_unitary(0)
        cop_mat = _compute_control_matrix(op_mat, num_ctrl)
        ref_mat = execute(qc, simulator).result().get_unitary(0)
        self.assertTrue(matrix_equal(cop_mat, ref_mat, ignore_phase=True))

    def test_single_controlled_composite_gate(self):
        """Test a singly controlled composite gate."""
        num_ctrl = 1
        # create composite gate
        sub_q = QuantumRegister(2)
        cgate = QuantumCircuit(sub_q, name='cgate')
        cgate.h(sub_q[0])
        cgate.cx(sub_q[0], sub_q[1])
        num_target = cgate.width()
        gate = cgate.to_gate()
        cont_gate = gate.control(num_ctrl_qubits=num_ctrl)
        control = QuantumRegister(num_ctrl, 'control')
        target = QuantumRegister(num_target, 'target')
        qc = QuantumCircuit(control, target)
        qc.append(cont_gate, control[:] + target[:])
        simulator = BasicAer.get_backend('unitary_simulator')
        op_mat = execute(cgate, simulator).result().get_unitary(0)
        cop_mat = _compute_control_matrix(op_mat, num_ctrl)
        ref_mat = execute(qc, simulator).result().get_unitary(0)
        self.assertTrue(matrix_equal(cop_mat, ref_mat, ignore_phase=True))

    def test_multi_control_u3(self):
        """Test the matrix representation of the controlled and controlled-controlled U3 gate."""
        import qiskit.extensions.standard.u3 as u3

        num_ctrl = 3
        # U3 gate params
        alpha, beta, gamma = 0.2, 0.3, 0.4

        # cnu3 gate
        u3gate = u3.U3Gate(alpha, beta, gamma)
        cnu3 = u3gate.control(num_ctrl)
        width = cnu3.num_qubits
        qr = QuantumRegister(width)
        qcnu3 = QuantumCircuit(qr)
        qcnu3.append(cnu3, qr, [])

        # U3 gate
        qu3 = QuantumCircuit(1)
        qu3.u3(alpha, beta, gamma, 0)

        # CU3 gate
        qcu3 = QuantumCircuit(2)
        qcu3.cu3(alpha, beta, gamma, 0, 1)

        # c-cu3 gate
        width = 3
        qr = QuantumRegister(width)
        qc_cu3 = QuantumCircuit(qr)
        cu3gate = u3.CU3Gate(alpha, beta, gamma)

        c_cu3 = cu3gate.control(1)
        qc_cu3.append(c_cu3, qr, [])

        job = execute([qcnu3, qu3, qcu3, qc_cu3],
                      BasicAer.get_backend('unitary_simulator'),
                      basis_gates=['u1', 'u2', 'u3', 'id', 'cx'])
        result = job.result()

        # Circuit unitaries
        mat_cnu3 = result.get_unitary(0)

        mat_u3 = result.get_unitary(1)
        mat_cu3 = result.get_unitary(2)
        mat_c_cu3 = result.get_unitary(3)

        # Target Controlled-U3 unitary
        target_cnu3 = _compute_control_matrix(mat_u3, num_ctrl)
        target_cu3 = np.kron(mat_u3, np.diag([0, 1])) + np.kron(
            np.eye(2), np.diag([1, 0]))
        target_c_cu3 = np.kron(mat_cu3, np.diag([0, 1])) + np.kron(
            np.eye(4), np.diag([1, 0]))

        tests = [
            ('check unitary of u3.control against tensored unitary of u3',
             target_cu3, mat_cu3),
            ('check unitary of cu3.control against tensored unitary of cu3',
             target_c_cu3, mat_c_cu3),
            ('check unitary of cnu3 against tensored unitary of u3',
             target_cnu3, mat_cnu3)
        ]
        for itest in tests:
            info, target, decomp = itest[0], itest[1], itest[2]
            with self.subTest(i=info):
                self.log.info(info)
                self.assertTrue(matrix_equal(target, decomp,
                                             ignore_phase=True))

    def test_multi_control_u1(self):
        """Test the matrix representation of the controlled and controlled-controlled U1 gate."""
        import qiskit.extensions.standard.u1 as u1

        num_ctrl = 3
        # U1 gate params
        theta = 0.2

        # cnu1 gate
        u1gate = u1.U1Gate(theta)
        cnu1 = u1gate.control(num_ctrl)
        width = cnu1.num_qubits
        qr = QuantumRegister(width)
        qcnu1 = QuantumCircuit(qr)
        qcnu1.append(cnu1, qr, [])

        # U1 gate
        qu1 = QuantumCircuit(1)
        qu1.u1(theta, 0)

        # CU1 gate
        qcu1 = QuantumCircuit(2)
        qcu1.cu1(theta, 0, 1)

        # c-cu1 gate
        width = 3
        qr = QuantumRegister(width)
        qc_cu1 = QuantumCircuit(qr)
        cu1gate = u1.CU1Gate(theta)
        c_cu1 = cu1gate.control(1)
        qc_cu1.append(c_cu1, qr, [])

        job = execute([qcnu1, qu1, qcu1, qc_cu1],
                      BasicAer.get_backend('unitary_simulator'),
                      basis_gates=['u1', 'u2', 'u3', 'id', 'cx'])
        result = job.result()

        # Circuit unitaries
        mat_cnu1 = result.get_unitary(0)
        # trace out ancillae

        mat_u1 = result.get_unitary(1)
        mat_cu1 = result.get_unitary(2)
        mat_c_cu1 = result.get_unitary(3)

        # Target Controlled-U1 unitary
        target_cnu1 = _compute_control_matrix(mat_u1, num_ctrl)
        target_cu1 = np.kron(mat_u1, np.diag([0, 1])) + np.kron(
            np.eye(2), np.diag([1, 0]))
        target_c_cu1 = np.kron(mat_cu1, np.diag([0, 1])) + np.kron(
            np.eye(4), np.diag([1, 0]))

        tests = [
            ('check unitary of u1.control against tensored unitary of u1',
             target_cu1, mat_cu1),
            ('check unitary of cu1.control against tensored unitary of cu1',
             target_c_cu1, mat_c_cu1),
            ('check unitary of cnu1 against tensored unitary of u1',
             target_cnu1, mat_cnu1)
        ]
        for itest in tests:
            info, target, decomp = itest[0], itest[1], itest[2]
            with self.subTest(i=info):
                self.log.info(info)
                self.assertTrue(matrix_equal(target, decomp,
                                             ignore_phase=True))

    @data(1, 2, 3, 4)
    def test_multi_controlled_u1_matrix(self, num_controls):
        """Test the matrix representation of the multi-controlled CU1 gate.

        Based on the test moved here from Aqua:
        https://github.com/Qiskit/qiskit-aqua/blob/769ca8f/test/aqua/test_mcu1.py
        """

        # registers for the circuit
        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]
            lam = 0.3165354 * pi
            qc = QuantumCircuit(q_controls, q_target)
            for idx, bit in enumerate(bitstr):
                if bit == '0':
                    qc.x(q_controls[idx])

            qc.mcu1(lam, q_controls, q_target[0])

            # for idx in subset:
            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)

            base = U1Gate(lam).to_matrix()
            expected = _compute_control_matrix(base,
                                               num_controls,
                                               ctrl_state=ctrl_state)
            with self.subTest(msg='control state = {}'.format(ctrl_state)):
                self.assertTrue(matrix_equal(simulated, expected))

    @data(1, 2, 3, 4)
    def test_multi_control_toffoli_matrix_clean_ancillas(self, num_controls):
        """Test the multi-control Toffoli gate with clean ancillas.

        Based on the test moved here from Aqua:
        https://github.com/Qiskit/qiskit-aqua/blob/769ca8f/test/aqua/test_mct.py
        """
        # set up circuit
        q_controls = QuantumRegister(num_controls)
        q_target = QuantumRegister(1)
        qc = QuantumCircuit(q_controls, q_target)

        if num_controls > 2:
            num_ancillas = num_controls - 2
            q_ancillas = QuantumRegister(num_controls)
            qc.add_register(q_ancillas)
        else:
            num_ancillas = 0
            q_ancillas = None

        # apply hadamard on control qubits and toffoli gate
        qc.mct(q_controls, q_target[0], q_ancillas, mode='basic')

        # execute the circuit and obtain statevector result
        backend = BasicAer.get_backend('unitary_simulator')
        simulated = execute(qc, backend).result().get_unitary(qc)

        # compare to expectation
        if num_ancillas > 0:
            simulated = simulated[:2**(num_controls + 1), :2**(num_controls +
                                                               1)]

        base = XGate().to_matrix()
        expected = _compute_control_matrix(base, num_controls)
        self.assertTrue(matrix_equal(simulated, expected))

    @data(1, 2, 3, 4, 5)
    def test_multi_control_toffoli_matrix_basic_dirty_ancillas(
            self, num_controls):
        """Test the multi-control Toffoli gate with dirty ancillas (basic-dirty-ancilla).

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

        q_ancillas = None
        if num_controls <= 2:
            num_ancillas = 0
        else:
            num_ancillas = num_controls - 2
            q_ancillas = QuantumRegister(num_ancillas)
            qc.add_register(q_ancillas)

        qc.mct(q_controls, q_target[0], q_ancillas, mode='basic-dirty-ancilla')

        simulated = execute(
            qc,
            BasicAer.get_backend('unitary_simulator')).result().get_unitary(qc)
        if num_ancillas > 0:
            simulated = simulated[:2**(num_controls + 1), :2**(num_controls +
                                                               1)]

        base = XGate().to_matrix()
        expected = _compute_control_matrix(base, num_controls)
        self.assertTrue(matrix_equal(simulated, expected, atol=1e-8))

    @data(1, 2, 3, 4, 5)
    def test_multi_control_toffoli_matrix_advanced_dirty_ancillas(
            self, num_controls):
        """Test the multi-control Toffoli gate with dirty ancillas (advanced).

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

        q_ancillas = None
        if num_controls <= 4:
            num_ancillas = 0
        else:
            num_ancillas = 1
            q_ancillas = QuantumRegister(num_ancillas)
            qc.add_register(q_ancillas)

        qc.mct(q_controls, q_target[0], q_ancillas, mode='advanced')

        simulated = execute(
            qc,
            BasicAer.get_backend('unitary_simulator')).result().get_unitary(qc)
        if num_ancillas > 0:
            simulated = simulated[:2**(num_controls + 1), :2**(num_controls +
                                                               1)]

        base = XGate().to_matrix()
        expected = _compute_control_matrix(base, num_controls)
        self.assertTrue(matrix_equal(simulated, expected, atol=1e-8))

    @data(1, 2, 3)
    def test_multi_control_toffoli_matrix_noancilla_dirty_ancillas(
            self, num_controls):
        """Test the multi-control Toffoli gate with dirty ancillas (noancilla).

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

        qc.mct(q_controls, q_target[0], None, mode='noancilla')

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

        base = XGate().to_matrix()
        expected = _compute_control_matrix(base, num_controls)
        self.assertTrue(matrix_equal(simulated, expected, atol=1e-8))

    @combine(num_controls=[1, 2, 4],
             base_gate_name=['x', 'y', 'z'],
             use_basis_gates=[True, False])
    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))

    @combine(num_controls=[1, 2, 4], use_basis_gates=[True, False])
    def test_multi_controlled_y_rotation_matrix_basic_mode(
            self, num_controls, use_basis_gates):
        """Test the multi controlled Y rotation using the mode 'basic'.

        Based on the test moved here from Aqua:
        https://github.com/Qiskit/qiskit-aqua/blob/769ca8f/test/aqua/test_mcr.py
        """

        # get the number of required ancilla qubits
        if num_controls <= 2:
            num_ancillas = 0
        else:
            num_ancillas = num_controls - 2

        q_controls = QuantumRegister(num_controls)
        q_target = QuantumRegister(1)

        for ctrl_state in range(2**num_controls):
            bitstr = bin(ctrl_state)[2:].zfill(num_controls)[::-1]
            theta = 0.871236 * pi
            if num_ancillas > 0:
                q_ancillas = QuantumRegister(num_ancillas)
                qc = QuantumCircuit(q_controls, q_target, q_ancillas)
            else:
                qc = QuantumCircuit(q_controls, q_target)
                q_ancillas = None

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

            qc.mcry(theta,
                    q_controls,
                    q_target[0],
                    q_ancillas,
                    mode='basic',
                    use_basis_gates=use_basis_gates)

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

            rot_mat = RYGate(theta).to_matrix()

            backend = BasicAer.get_backend('unitary_simulator')
            simulated = execute(qc, backend).result().get_unitary(qc)
            if num_ancillas > 0:
                simulated = simulated[:2**(num_controls +
                                           1), :2**(num_controls + 1)]

            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))

    @data(0, 1, 2)
    def test_mcx_gates_yield_explicit_gates(self, num_ctrl_qubits):
        """Test the creating a MCX gate yields the explicit definition if we know it."""
        cls = MCXGate(num_ctrl_qubits).__class__
        explicit = {0: XGate, 1: CXGate, 2: CCXGate}
        self.assertEqual(cls, explicit[num_ctrl_qubits])

    @data(0, 3, 4, 5, 8)
    def test_mcx_gates(self, num_ctrl_qubits):
        """Test the mcx gates."""
        backend = BasicAer.get_backend('statevector_simulator')
        reference = np.zeros(2**(num_ctrl_qubits + 1))
        reference[-1] = 1

        for gate in [
                MCXGrayCode(num_ctrl_qubits),
                MCXRecursive(num_ctrl_qubits),
                MCXVChain(num_ctrl_qubits, False),
                MCXVChain(num_ctrl_qubits, True),
        ]:
            with self.subTest(gate=gate):
                circuit = QuantumCircuit(gate.num_qubits)
                if num_ctrl_qubits > 0:
                    circuit.x(list(range(num_ctrl_qubits)))
                circuit.append(gate, list(range(gate.num_qubits)), [])
                statevector = execute(circuit,
                                      backend).result().get_statevector()

                # account for ancillas
                if hasattr(
                        gate,
                        'num_ancilla_qubits') and gate.num_ancilla_qubits > 0:
                    corrected = np.zeros(2**(num_ctrl_qubits + 1),
                                         dtype=complex)
                    for i, statevector_amplitude in enumerate(statevector):
                        i = int(
                            bin(i)[2:].zfill(
                                circuit.num_qubits)[gate.num_ancilla_qubits:],
                            2)
                        corrected[i] += statevector_amplitude
                    statevector = corrected

                np.testing.assert_array_almost_equal(statevector.real,
                                                     reference)

    @data(1, 2, 3, 4)
    def test_inverse_x(self, num_ctrl_qubits):
        """Test inverting the controlled X gate."""
        cnx = XGate().control(num_ctrl_qubits)
        inv_cnx = cnx.inverse()
        result = Operator(cnx).compose(Operator(inv_cnx))
        np.testing.assert_array_almost_equal(result.data,
                                             np.identity(result.dim[0]))

    @data(1, 2, 3)
    def test_inverse_circuit(self, num_ctrl_qubits):
        """Test inverting a controlled gate based on a circuit definition."""
        qc = QuantumCircuit(3)
        qc.h(0)
        qc.cx(0, 1)
        qc.cx(1, 2)
        qc.rx(np.pi / 4, [0, 1, 2])
        gate = qc.to_gate()
        cgate = gate.control(num_ctrl_qubits)
        inv_cgate = cgate.inverse()
        result = Operator(cgate).compose(Operator(inv_cgate))
        np.testing.assert_array_almost_equal(result.data,
                                             np.identity(result.dim[0]))

    @data(1, 2, 3, 4, 5)
    def test_controlled_unitary(self, num_ctrl_qubits):
        """Test the matrix data of an Operator, which is based on a controlled gate."""
        num_target = 1
        q_target = QuantumRegister(num_target)
        qc1 = QuantumCircuit(q_target)
        # for h-rx(pi/2)
        theta, phi, lamb = 1.57079632679490, 0.0, 4.71238898038469
        qc1.u3(theta, phi, lamb, q_target[0])
        base_gate = qc1.to_gate()
        # get UnitaryGate version of circuit
        base_op = Operator(qc1)
        base_mat = base_op.data
        cgate = base_gate.control(num_ctrl_qubits)
        test_op = Operator(cgate)
        cop_mat = _compute_control_matrix(base_mat, num_ctrl_qubits)
        self.assertTrue(is_unitary_matrix(base_mat))
        self.assertTrue(matrix_equal(cop_mat, test_op.data, ignore_phase=True))

    @data(1, 2, 3, 4, 5)
    def test_controlled_random_unitary(self, num_ctrl_qubits):
        """Test the matrix data of an Operator based on a random UnitaryGate."""
        num_target = 2
        base_gate = random_unitary(2**num_target).to_instruction()
        base_mat = base_gate.to_matrix()
        cgate = base_gate.control(num_ctrl_qubits)
        test_op = Operator(cgate)
        cop_mat = _compute_control_matrix(base_mat, num_ctrl_qubits)
        self.assertTrue(matrix_equal(cop_mat, test_op.data, ignore_phase=True))

    @data(1, 2, 3)
    def test_open_controlled_unitary_matrix(self, num_ctrl_qubits):
        """test open controlled unitary matrix"""
        # verify truth table
        num_target_qubits = 2
        num_qubits = num_ctrl_qubits + num_target_qubits
        target_op = Operator(XGate())
        for i in range(num_target_qubits - 1):
            target_op = target_op.tensor(XGate())

        for i in range(2**num_qubits):
            input_bitstring = bin(i)[2:].zfill(num_qubits)
            input_target = input_bitstring[0:num_target_qubits]
            input_ctrl = input_bitstring[-num_ctrl_qubits:]
            phi = Statevector.from_label(input_bitstring)
            cop = Operator(
                _compute_control_matrix(target_op.data,
                                        num_ctrl_qubits,
                                        ctrl_state=input_ctrl))
            for j in range(2**num_qubits):
                output_bitstring = bin(j)[2:].zfill(num_qubits)
                output_target = output_bitstring[0:num_target_qubits]
                output_ctrl = output_bitstring[-num_ctrl_qubits:]
                psi = Statevector.from_label(output_bitstring)
                cxout = np.dot(phi.data, psi.evolve(cop).data)
                if input_ctrl == output_ctrl:
                    # flip the target bits
                    cond_output = ''.join(
                        [str(int(not int(a))) for a in input_target])
                else:
                    cond_output = input_target
                if cxout == 1:
                    self.assertTrue((output_ctrl == input_ctrl)
                                    and (output_target == cond_output))
                else:
                    self.assertTrue(((output_ctrl == input_ctrl) and
                                     (output_target != cond_output))
                                    or output_ctrl != input_ctrl)

    @data(*ControlledGate.__subclasses__())
    def test_base_gate_setting(self, gate_class):
        """Test all gates in standard extensions which are of type ControlledGate
        and have a base gate setting.
        """
        num_free_params = len(
            _get_free_params(gate_class.__init__, ignore=['self']))
        free_params = [0.1 * i for i in range(num_free_params)]
        if gate_class in [MCU1Gate]:
            free_params[1] = 3
        elif gate_class in [MCXGate]:
            free_params[0] = 3

        base_gate = gate_class(*free_params)
        cgate = base_gate.control()
        self.assertEqual(base_gate.base_gate, cgate.base_gate)

    @data(*[
        gate for name, gate in allGates.__dict__.items()
        if isinstance(gate, type)
    ])
    def test_all_inverses(self, gate):
        """Test all gates in standard extensions except those that cannot be controlled
        or are being deprecated.
        """
        if not (issubclass(gate, ControlledGate)
                or issubclass(gate, allGates.IGate)):
            # only verify basic gates right now, as already controlled ones
            # will generate differing definitions
            try:
                numargs = len(_get_free_params(gate))
                args = [2] * numargs

                gate = gate(*args)
                self.assertEqual(gate.inverse().control(2),
                                 gate.control(2).inverse())
            except AttributeError:
                # skip gates that do not have a control attribute (e.g. barrier)
                pass

    @data(2, 3)
    def test_relative_phase_toffoli_gates(self, num_ctrl_qubits):
        """Test the relative phase Toffoli gates.

        This test compares the matrix representation of the relative phase gate classes
        (i.e. RCCXGate().to_matrix()), the matrix obtained from the unitary simulator,
        and the exact version of the gate as obtained through `_compute_control_matrix`.
        """
        # get target matrix (w/o relative phase)
        base_mat = XGate().to_matrix()
        target_mat = _compute_control_matrix(base_mat, num_ctrl_qubits)

        # build the matrix for the relative phase toffoli using the unitary simulator
        circuit = QuantumCircuit(num_ctrl_qubits + 1)
        if num_ctrl_qubits == 2:
            circuit.rccx(0, 1, 2)
        else:  # num_ctrl_qubits == 3:
            circuit.rcccx(0, 1, 2, 3)
        simulator = BasicAer.get_backend('unitary_simulator')
        simulated_mat = execute(circuit, simulator).result().get_unitary()

        # get the matrix representation from the class itself
        if num_ctrl_qubits == 2:
            repr_mat = RCCXGate().to_matrix()
        else:  # num_ctrl_qubits == 3:
            repr_mat = RC3XGate().to_matrix()

        # test up to phase
        # note, that all entries may have an individual phase! (as opposed to a global phase)
        self.assertTrue(matrix_equal(np.abs(simulated_mat), target_mat))

        # compare simulated matrix with the matrix representation provided by the class
        self.assertTrue(matrix_equal(simulated_mat, repr_mat))

    def test_open_controlled_gate(self):
        """
        Test controlled gates with control on '0'
        """
        base_gate = XGate()
        base_mat = base_gate.to_matrix()
        num_ctrl_qubits = 3

        ctrl_state = 5
        cgate = base_gate.control(num_ctrl_qubits, ctrl_state=ctrl_state)
        target_mat = _compute_control_matrix(base_mat,
                                             num_ctrl_qubits,
                                             ctrl_state=ctrl_state)
        self.assertEqual(Operator(cgate), Operator(target_mat))

        ctrl_state = None
        cgate = base_gate.control(num_ctrl_qubits, ctrl_state=ctrl_state)
        target_mat = _compute_control_matrix(base_mat,
                                             num_ctrl_qubits,
                                             ctrl_state=ctrl_state)
        self.assertEqual(Operator(cgate), Operator(target_mat))

        ctrl_state = 0
        cgate = base_gate.control(num_ctrl_qubits, ctrl_state=ctrl_state)
        target_mat = _compute_control_matrix(base_mat,
                                             num_ctrl_qubits,
                                             ctrl_state=ctrl_state)
        np.set_printoptions(linewidth=200, )
        self.assertEqual(Operator(cgate), Operator(target_mat))

        ctrl_state = 7
        cgate = base_gate.control(num_ctrl_qubits, ctrl_state=ctrl_state)
        target_mat = _compute_control_matrix(base_mat,
                                             num_ctrl_qubits,
                                             ctrl_state=ctrl_state)
        self.assertEqual(Operator(cgate), Operator(target_mat))

        ctrl_state = '110'
        cgate = base_gate.control(num_ctrl_qubits, ctrl_state=ctrl_state)
        target_mat = _compute_control_matrix(base_mat,
                                             num_ctrl_qubits,
                                             ctrl_state=ctrl_state)
        self.assertEqual(Operator(cgate), Operator(target_mat))

    def test_open_controlled_gate_raises(self):
        """
        Test controlled gates with open controls raises if ctrl_state isn't allowed.
        """
        base_gate = XGate()
        num_ctrl_qubits = 3
        with self.assertRaises(CircuitError):
            base_gate.control(num_ctrl_qubits, ctrl_state=-1)
        with self.assertRaises(CircuitError):
            base_gate.control(num_ctrl_qubits, ctrl_state=2**num_ctrl_qubits)
        with self.assertRaises(CircuitError):
            base_gate.control(num_ctrl_qubits, ctrl_state='201')
コード例 #9
0
 def test_swap_definition_specification(self):
     """Test the instantiation of a controlled swap gate with explicit definition."""
     swap = SwapGate()
     cswap = ControlledGate('cswap', 3, [], num_ctrl_qubits=1,
                            definition=swap.definition)
     self.assertEqual(swap.definition, cswap.definition)