Пример #1
0
    def test_mcmt_v_chain_ancilla_test(self):
        """Test too few and too many ancillas for the MCMT V-chain mode."""
        with self.subTest(msg="insufficient number of auxiliary qubits on gate"):
            qc = QuantumCircuit(5)
            mcmt = MCMTVChain(ZGate(), 3, 1)
            with self.assertRaises(QiskitError):
                qc.append(mcmt, range(5))

        with self.subTest(msg="too many auxiliary qubits on gate"):
            qc = QuantumCircuit(9)
            mcmt = MCMTVChain(ZGate(), 3, 1)
            with self.assertRaises(QiskitError):
                qc.append(mcmt, range(9))
Пример #2
0
    def test_mcmt_v_chain_simulation(self, cgate, num_controls, num_targets):
        """Test the MCMT V-chain implementation test on a simulation."""
        controls = QuantumRegister(num_controls)
        targets = QuantumRegister(num_targets)

        subsets = [tuple(range(i)) for i in range(num_controls + 1)]
        for subset in subsets:
            qc = QuantumCircuit(targets, controls)
            # Initialize all targets to 1, just to be sure that
            # the generic gate has some effect (f.e. Z gate has no effect
            # on a 0 state)
            qc.x(targets)

            num_ancillas = max(0, num_controls - 1)

            if num_ancillas > 0:
                ancillas = QuantumRegister(num_ancillas)
                qc.add_register(ancillas)
                qubits = controls[:] + targets[:] + ancillas[:]
            else:
                qubits = controls[:] + targets[:]

            for i in subset:
                qc.x(controls[i])

            mcmt = MCMTVChain(cgate, num_controls, num_targets)
            qc.compose(mcmt, qubits, inplace=True)

            for i in subset:
                qc.x(controls[i])

            vec = Statevector.from_label("0" * qc.num_qubits).evolve(qc)

            # target register is initially |11...1>, with length equal to 2**(n_targets)
            vec_exp = np.array([0] * (2 ** (num_targets) - 1) + [1])

            if isinstance(cgate, CZGate):
                # Z gate flips the last qubit only if it's applied an odd number of times
                if len(subset) == num_controls and (num_controls % 2) == 1:
                    vec_exp[-1] = -1
            elif isinstance(cgate, CHGate):
                # if all the control qubits have been activated,
                # we repeatedly apply the kronecker product of the Hadamard
                # with itself and then multiply the results for the original
                # state of the target qubits
                if len(subset) == num_controls:
                    h_i = 1 / np.sqrt(2) * np.array([[1, 1], [1, -1]])
                    h_tot = np.array([1])
                    for _ in range(num_targets):
                        h_tot = np.kron(h_tot, h_i)
                    vec_exp = np.dot(h_tot, vec_exp)
            else:
                raise ValueError(f"Test not implement for gate: {cgate}")

            # append the remaining part of the state
            vec_exp = np.concatenate(
                (vec_exp, [0] * (2 ** (num_controls + num_ancillas + num_targets) - vec_exp.size))
            )
            f_i = state_fidelity(vec, vec_exp)
            self.assertAlmostEqual(f_i, 1)
Пример #3
0
    def test_mcmt_v_chain_ancilla_test(self):
        """Test too few and too many ancillas for the MCMT V-chain mode."""
        with self.subTest(msg='insufficient number of ancillas on gate'):
            qc = QuantumCircuit(5)
            mcmt = MCMTVChain(ZGate(), 3, 1)
            with self.assertRaises(QiskitError):
                qc.append(mcmt, [0, 1, 2, 3, 4])

        with self.subTest(msg='insufficient number of ancillas on method'):
            qc = QuantumCircuit(5)
            mcmt = MCMTVChain(ZGate(), 3, 1)
            with self.assertRaises(QiskitError):
                qc.append(mcmt, [0, 1, 2, 3, 4], [])

        with self.subTest(msg='too many ancillas works on method'):
            qc = QuantumCircuit(8)
            qc.mcmt(CZGate(), [0, 1, 2], 3, [4, 5, 6, 7])
Пример #4
0
        def control(num_ctrl_qubits=1, label=None, ctrl_state=None):
            qr_state = QuantumRegister(self.num_state_qubits + 1)
            if self.num_state_qubits > 1:
                qr_ancilla = AncillaRegister(max(1, self.num_state_qubits - 1))
                qc_control = QuantumCircuit(qr_state,
                                            qr_ancilla,
                                            name="off_diags")
            else:
                qc_control = QuantumCircuit(qr_state, name="off_diags")
                qr_ancilla = None
            # Control will be qr[0]
            q_control = qr_state[0]
            qr = qr_state[1:]
            qc_control.cu(-2 * theta, 3 * np.pi / 2, np.pi / 2, 0, q_control,
                          qr[0])

            for i in range(0, self.num_state_qubits - 1):
                q_controls = []
                q_controls.append(q_control)
                qc_control.cx(qr[i], qr[i + 1])
                q_controls.append(qr[i + 1])

                # Now we want controlled by 0
                qc_control.x(qr[i])
                for j in range(i, 0, -1):
                    qc_control.cx(qr[i], qr[j - 1])
                    q_controls.append(qr[j - 1])
                qc_control.x(qr[i])

                # Multicontrolled x rotation
                if len(q_controls) > 1:
                    ugate = UGate(-2 * theta, 3 * np.pi / 2, np.pi / 2)
                    qc_control.append(
                        MCMTVChain(ugate, len(q_controls), 1),
                        q_controls[:] + [qr[i]] +
                        qr_ancilla[:len(q_controls) - 1],
                    )
                else:
                    qc_control.cu(-2 * theta, 3 * np.pi / 2, np.pi / 2, 0,
                                  q_controls[0], qr[i])

                # Uncompute
                qc_control.x(qr[i])
                for j in range(0, i):
                    qc_control.cx(qr[i], qr[j])
                qc_control.x(qr[i])
                qc_control.cx(qr[i], qr[i + 1])
            return qc_control
Пример #5
0
    def _off_diag_circ(self, theta: float = 1) -> QuantumCircuit:
        """Circuit implementing the matrix consisting of entries in the off diagonals.

        Args:
            theta: Scale factor for the off diagonal entries (e.g. evolution_time/trotter_steps).

        Returns:
            The quantum circuit implementing the matrix consisting of entries in the off diagonals.
        """
        theta *= self.off_diag

        qr = QuantumRegister(self.num_state_qubits)
        if self.num_state_qubits > 1:
            qr_ancilla = AncillaRegister(max(1, self.num_state_qubits - 2))
            qc = QuantumCircuit(qr, qr_ancilla, name="off_diags")
        else:
            qc = QuantumCircuit(qr, name="off_diags")
            qr_ancilla = None

        qc.u(-2 * theta, 3 * np.pi / 2, np.pi / 2, qr[0])

        for i in range(0, self.num_state_qubits - 1):
            q_controls = []
            qc.cx(qr[i], qr[i + 1])
            q_controls.append(qr[i + 1])

            # Now we want controlled by 0
            qc.x(qr[i])
            for j in range(i, 0, -1):
                qc.cx(qr[i], qr[j - 1])
                q_controls.append(qr[j - 1])
            qc.x(qr[i])

            # Multicontrolled rotation
            if len(q_controls) > 1:
                ugate = UGate(-2 * theta, 3 * np.pi / 2, np.pi / 2)
                qc.append(
                    MCMTVChain(ugate, len(q_controls), 1),
                    q_controls[:] + [qr[i]] + qr_ancilla[:len(q_controls) - 1],
                )
            else:
                qc.cu(-2 * theta, 3 * np.pi / 2, np.pi / 2, 0, q_controls[0],
                      qr[i])

            # Uncompute
            qc.x(qr[i])
            for j in range(0, i):
                qc.cx(qr[i], qr[j])
            qc.x(qr[i])
            qc.cx(qr[i], qr[i + 1])

        # pylint: disable=unused-argument
        def control(num_ctrl_qubits=1, label=None, ctrl_state=None):
            qr_state = QuantumRegister(self.num_state_qubits + 1)
            if self.num_state_qubits > 1:
                qr_ancilla = AncillaRegister(max(1, self.num_state_qubits - 1))
                qc_control = QuantumCircuit(qr_state,
                                            qr_ancilla,
                                            name="off_diags")
            else:
                qc_control = QuantumCircuit(qr_state, name="off_diags")
                qr_ancilla = None
            # Control will be qr[0]
            q_control = qr_state[0]
            qr = qr_state[1:]
            qc_control.cu(-2 * theta, 3 * np.pi / 2, np.pi / 2, 0, q_control,
                          qr[0])

            for i in range(0, self.num_state_qubits - 1):
                q_controls = []
                q_controls.append(q_control)
                qc_control.cx(qr[i], qr[i + 1])
                q_controls.append(qr[i + 1])

                # Now we want controlled by 0
                qc_control.x(qr[i])
                for j in range(i, 0, -1):
                    qc_control.cx(qr[i], qr[j - 1])
                    q_controls.append(qr[j - 1])
                qc_control.x(qr[i])

                # Multicontrolled x rotation
                if len(q_controls) > 1:
                    ugate = UGate(-2 * theta, 3 * np.pi / 2, np.pi / 2)
                    qc_control.append(
                        MCMTVChain(ugate, len(q_controls), 1),
                        q_controls[:] + [qr[i]] +
                        qr_ancilla[:len(q_controls) - 1],
                    )
                else:
                    qc_control.cu(-2 * theta, 3 * np.pi / 2, np.pi / 2, 0,
                                  q_controls[0], qr[i])

                # Uncompute
                qc_control.x(qr[i])
                for j in range(0, i):
                    qc_control.cx(qr[i], qr[j])
                qc_control.x(qr[i])
                qc_control.cx(qr[i], qr[i + 1])
            return qc_control

        qc.control = control
        return qc