Example #1
0
    def construct_circuit(self, k=None, omega=0, measurement=False):
        """Construct the kth iteration Quantum Phase Estimation circuit.

        For details of parameters, please see Fig. 2 in https://arxiv.org/pdf/quant-ph/0610214.pdf.

        Args:
            k (int): the iteration idx.
            omega (float): the feedback angle.
            measurement (bool): Boolean flag to indicate if measurement should be included in the circuit.

        Returns:
            QuantumCircuit: the quantum circuit per iteration
        """
        k = self._num_iterations if k is None else k
        a = QuantumRegister(1, name='a')
        q = QuantumRegister(self._operator.num_qubits, name='q')
        self._ancillary_register = a
        self._state_register = q
        qc = QuantumCircuit(q)
        qc += self._state_in.construct_circuit('circuit', q)
        # hadamard on a[0]
        qc.add_register(a)
        qc.u2(0, np.pi, a[0])
        # controlled-U
        qc_evolutions = Operator.construct_evolution_circuit(
            self._slice_pauli_list,
            -2 * np.pi,
            self._num_time_slices,
            q,
            a,
            unitary_power=2**(k - 1),
            shallow_slicing=self._shallow_circuit_concat)
        if self._shallow_circuit_concat:
            qc.data += qc_evolutions.data
        else:
            qc += qc_evolutions
        # global phase due to identity pauli
        qc.u1(2 * np.pi * self._ancilla_phase_coef * (2**(k - 1)), a[0])
        # rz on a[0]
        qc.u1(omega, a[0])
        # hadamard on a[0]
        qc.u2(0, np.pi, a[0])
        if measurement:
            c = ClassicalRegister(1, name='c')
            qc.add_register(c)
            # qc.barrier(self._ancillary_register)
            qc.measure(self._ancillary_register, c)
        return qc
Example #2
0
    def construct_circuit(self, x, qr=None, inverse=False):
        """
        Construct the second order expansion based on given data.

        Args:
            x (numpy.ndarray): 1-D to-be-transformed data.
            qr (QauntumRegister, optional): the QuantumRegister object for the circuit, if None,
                                  generate new registers with name q.
            inverse (bool, optional): whether or not inverse the circuit

        Returns:
            QuantumCircuit: a quantum circuit transform data x.
        """
        if not isinstance(x, np.ndarray):
            raise TypeError("x must be numpy array.")
        if x.ndim != 1:
            raise ValueError("x must be 1-D array.")
        if x.shape[0] != self._num_qubits:
            raise ValueError(
                "number of qubits and data dimension must be the same.")

        if qr is None:
            qr = QuantumRegister(self._num_qubits, name='q')

        qc = QuantumCircuit(qr)
        for _ in range(self._depth):
            for i in range(self._num_qubits):
                qc.u2(0, pi, qr[i])
            for pauli in self._pauli_strings:
                coeff = self._data_map_func(
                    self._extract_data_for_rotation(pauli, x))
                p = Pauli.from_label(pauli)
                qc += Operator.construct_evolution_circuit([[coeff, p]], 1, 1,
                                                           qr)

        if inverse:
            qc = qc.inverse()

        return qc
    def construct_circuit(self,
                          state_register=None,
                          ancillary_register=None,
                          auxiliary_register=None):
        """
        Construct the Phase Estimation circuit

        Args:
            state_register (QuantumRegister): the optional register to use for the quantum state
            ancillary_register (QuantumRegister): the optional register to use for the ancillary measurement qubits
            auxiliary_register (QuantumRegister): an optional auxiliary quantum register

        Returns:
            the QuantumCircuit object for the constructed circuit
        """

        if self._circuit is None:
            if ancillary_register is None:
                a = QuantumRegister(self._num_ancillae, name='a')
            else:
                a = ancillary_register
            self._ancillary_register = a

            if state_register is None:
                if self._operator is not None:
                    q = QuantumRegister(self._operator.num_qubits, name='q')
                elif self._unitary_circuit_factory is not None:
                    q = QuantumRegister(
                        self._unitary_circuit_factory.num_target_qubits,
                        name='q')
                else:
                    raise RuntimeError('Missing operator specification.')
            else:
                q = state_register
            self._state_register = q

            qc = QuantumCircuit(a, q)

            if auxiliary_register is None:
                num_aux_qubits, aux = 0, None
                if self._state_in_circuit_factory is not None:
                    num_aux_qubits = self._state_in_circuit_factory.required_ancillas(
                    )
                if self._unitary_circuit_factory is not None:
                    num_aux_qubits = max(
                        num_aux_qubits,
                        self._unitary_circuit_factory.
                        required_ancillas_controlled())

                if num_aux_qubits > 0:
                    aux = QuantumRegister(num_aux_qubits, name='aux')
                    qc.add_register(aux)
            else:
                aux = auxiliary_register
                qc.add_register(aux)

            # initialize state_in
            if self._state_in is not None:
                qc.data += self._state_in.construct_circuit('circuit', q).data
            elif self._state_in_circuit_factory is not None:
                self._state_in_circuit_factory.build(qc, q, aux)
            else:
                raise RuntimeError('Missing initial state specification.')

            # Put all ancillae in uniform superposition
            qc.u2(0, np.pi, a)

            # phase kickbacks via dynamics
            if self._operator is not None:
                # check for identify paulis to get its coef for applying global phase shift on ancillae later
                num_identities = 0
                for p in self._pauli_list:
                    if np.all(np.logical_not(p[1].z)) and np.all(
                            np.logical_not(p[1].x)):
                        num_identities += 1
                        if num_identities > 1:
                            raise RuntimeError(
                                'Multiple identity pauli terms are present.')
                        self._ancilla_phase_coef = p[0].real if isinstance(
                            p[0], complex) else p[0]

                if len(self._pauli_list) == 1:
                    slice_pauli_list = self._pauli_list
                else:
                    if self._expansion_mode == 'trotter':
                        slice_pauli_list = self._pauli_list
                    elif self._expansion_mode == 'suzuki':
                        slice_pauli_list = Operator._suzuki_expansion_slice_pauli_list(
                            self._pauli_list, 1, self._expansion_order)
                    else:
                        raise ValueError(
                            'Unrecognized expansion mode {}.'.format(
                                self._expansion_mode))
                for i in range(self._num_ancillae):
                    qc_evolutions = Operator.construct_evolution_circuit(
                        slice_pauli_list,
                        -2 * np.pi,
                        self._num_time_slices,
                        q,
                        a,
                        ctl_idx=i,
                        shallow_slicing=self._shallow_circuit_concat)
                    if self._shallow_circuit_concat:
                        qc.data += qc_evolutions.data
                    else:
                        qc += qc_evolutions
                    # global phase shift for the ancilla due to the identity pauli term
                    qc.u1(2 * np.pi * self._ancilla_phase_coef * (2**i), a[i])
            elif self._unitary_circuit_factory is not None:
                for i in range(self._num_ancillae):
                    self._unitary_circuit_factory.build_controlled_power(
                        qc, q, a[i], 2**i, aux)

            # inverse qft on ancillae
            self._iqft.construct_circuit('circuit', a, qc)

            self._circuit = qc

        return self._circuit