def construct_circuit(self, measurement=False):
        """Construct circuit.

        Args:
            measurement (bool): Boolean flag to indicate if measurement should be included in the circuit.


        Returns:
            QuantumCircuit: quantum circuit.
        """

        breakpoints = []

        # Get n value used in Shor's algorithm, to know how many qubits are used
        self._n = math.ceil(math.log(self._N, 2))

        # quantum register where the sequential QFT is performed
        self._up_qreg = QuantumRegister(2 * self._n, name='up')
        # quantum register where the multiplications are made
        self._down_qreg = QuantumRegister(self._n, name='down')
        # auxilliary quantum register used in addition and multiplication
        self._aux_qreg = QuantumRegister(self._n + 2, name='aux')

        up_cqreg = ClassicalRegister(2 * self._n, name='m_up')
        down_cqreg = ClassicalRegister(self._n, name='m_down')

        # Create Quantum Circuit
        circuit = QuantumCircuit(self._up_qreg, self._down_qreg, self._aux_qreg, up_cqreg, down_cqreg)

        # Initialize down register to 1 and create maximal superposition in top register
        circuit.u2(0, np.pi, self._up_qreg)
        circuit.u3(np.pi, 0, np.pi, self._down_qreg[0])

        # validate maximal superposition in top register
        breakpoints.append(circuit.get_breakpoint_uniform(self._up_qreg, up_cqreg, 0.05))
        # validate initialize down register to 1
        breakpoints.append(circuit.get_breakpoint_classical(self._down_qreg, down_cqreg, 0.05, 1))

        # Apply the multiplication gates as showed in the report in order to create the exponentiation
        for i in range(0, 2 * self._n):
            self._controlled_multiple_mod_N(
                circuit,
                self._up_qreg[i],
                self._down_qreg,
                self._aux_qreg,
                int(pow(self._a, pow(2, i)))
            )

        # Apply inverse QFT
        ftc.construct_circuit(circuit=circuit, qubits=self._up_qreg, do_swaps=True, inverse=True)

        # validate uncomputation is complete and registers are in product state
        breakpoints.append(circuit.get_breakpoint_product(self._up_qreg[:], up_cqreg[:], self._down_qreg[:], down_cqreg[:], .05))

        if measurement:
            circuit.measure(self._up_qreg, up_cqreg)

        logger.info(summarize_circuits(circuit))

        return breakpoints, circuit
 def construct_circuit(self, mode, qubits=None, circuit=None):
     if mode == 'vector':
         # note the difference between QFT and DFT in the phase definition:
         # QFT: \omega = exp(2*pi*i/N) ; DFT: \omega = exp(-2*pi*i/N)
         # so linalg.inv(linalg.dft()) is correct for QFT
         return linalg.inv(linalg.dft(2 ** self._num_qubits, scale='sqrtn'))
     elif mode == 'circuit':
         ftc = FourierTransformCircuits(self._num_qubits, approximation_degree=0, inverse=False)
         return ftc.construct_circuit(qubits, circuit)
     else:
         raise ValueError('Mode should be either "vector" or "circuit"')
Exemple #3
0
 def construct_circuit(self, mode, qubits=None, circuit=None):
     if mode == 'vector':
         # TODO: implement vector mode for approximate iqft
         raise NotImplementedError()
     elif mode == 'circuit':
         ftc = FourierTransformCircuits(self._num_qubits,
                                        approximation_degree=self._degree,
                                        inverse=True)
         return ftc.construct_circuit(qubits, circuit)
     else:
         raise ValueError('Mode should be either "vector" or "circuit"')
 def _controlled_controlled_phi_add_mod_N_inv(self, circuit, q, ctl1, ctl2, aux, a):
     """
     Circuit that implements the inverse of doubly controlled modular addition by a
     """
     self._controlled_controlled_phi_add(circuit, q, ctl1, ctl2, a, inverse=True)
     ftc.construct_circuit(
         circuit=circuit,
         qubits=[q[i] for i in reversed(range(self._n + 1))],
         do_swaps=False,
         inverse=True
     )
     circuit.u3(np.pi, 0, np.pi, q[self._n])
     circuit.cx(q[self._n], aux)
     circuit.u3(np.pi, 0, np.pi, q[self._n])
     ftc.construct_circuit(
         circuit=circuit,
         qubits=[q[i] for i in reversed(range(self._n + 1))],
         do_swaps=False
     )
     self._controlled_controlled_phi_add(circuit, q, ctl1, ctl2, a)
     self._controlled_phi_add(circuit, q, aux, inverse=True)
     ftc.construct_circuit(
         circuit=circuit,
         qubits=[q[i] for i in reversed(range(self._n + 1))],
         do_swaps=False,
         inverse=True
     )
     circuit.cx(q[self._n], aux)
     ftc.construct_circuit(
         circuit=circuit,
         qubits=[q[i] for i in reversed(range(self._n + 1))],
         do_swaps=False
     )
     self._phi_add(circuit, q)
     self._controlled_controlled_phi_add(circuit, q, ctl1, ctl2, a, inverse=True)
Exemple #5
0
 def _build_circuit(self, qubits=None, circuit=None, do_swaps=True):
     return ftc.construct_circuit(
         circuit=circuit,
         qubits=qubits,
         inverse=True,
         approximation_degree=self._degree,
         do_swaps=do_swaps
     )
Exemple #6
0
    def _controlled_multiple_mod_N(self, circuit, ctl, q, aux, a):
        """
        Circuit that implements single controlled modular multiplication by a
        """
        ftc.construct_circuit(
            circuit=circuit,
            qubits=[aux[i] for i in reversed(range(self._n + 1))],
            do_swaps=False)

        for i in range(0, self._n):
            self._controlled_controlled_phi_add_mod_N(circuit, aux, q[i], ctl,
                                                      aux[self._n + 1],
                                                      (2**i) * a % self._N)
        ftc.construct_circuit(
            circuit=circuit,
            qubits=[aux[i] for i in reversed(range(self._n + 1))],
            do_swaps=False,
            inverse=True)

        for i in range(0, self._n):
            circuit.cswap(ctl, q[i], aux[i])

        def modinv(a, m):
            def egcd(a, b):
                if a == 0:
                    return (b, 0, 1)
                else:
                    g, y, x = egcd(b % a, a)
                    return (g, x - (b // a) * y, y)

            g, x, _ = egcd(a, m)
            if g != 1:
                raise Exception('modular inverse does not exist')

            return x % m

        a_inv = modinv(a, self._N)
        ftc.construct_circuit(
            circuit=circuit,
            qubits=[aux[i] for i in reversed(range(self._n + 1))],
            do_swaps=False)

        for i in reversed(range(self._n)):
            self._controlled_controlled_phi_add_mod_N_inv(
                circuit, aux, q[i], ctl, aux[self._n + 1],
                math.pow(2, i) * a_inv % self._N)
        ftc.construct_circuit(
            circuit=circuit,
            qubits=[aux[i] for i in reversed(range(self._n + 1))],
            do_swaps=False,
            inverse=True)
Exemple #7
0
    def construct_circuit(self):
        """Construct circuit.

        Returns:
            QuantumCircuit: quantum circuit.
        """

        # Get n value used in Shor's algorithm, to know how many qubits are used
        self._n = math.ceil(math.log(self._N, 2))

        # quantum register where the sequential QFT is performed
        self._up_qreg = QuantumRegister(2 * self._n, name='up')
        # quantum register where the multiplications are made
        self._down_qreg = QuantumRegister(self._n, name='down')
        # auxilliary quantum register used in addition and multiplication
        self._aux_qreg = QuantumRegister(self._n + 2, name='aux')

        # Create Quantum Circuit
        circuit = QuantumCircuit(self._up_qreg, self._down_qreg,
                                 self._aux_qreg)

        # Initialize down register to 1 and create maximal superposition in top register
        circuit.u2(0, np.pi, self._up_qreg)
        circuit.u3(np.pi, 0, np.pi, self._down_qreg[0])

        # Apply the multiplication gates as showed in the report in order to create the exponentiation
        for i in range(0, 2 * self._n):
            self._controlled_multiple_mod_N(circuit, self._up_qreg[i],
                                            self._down_qreg, self._aux_qreg,
                                            int(pow(self._a, pow(2, i))))

        # Apply inverse QFT
        ftc.construct_circuit(circuit=circuit,
                              qubits=self._up_qreg,
                              do_swaps=True,
                              inverse=True)

        logger.info(summarize_circuits(circuit))

        return circuit
Exemple #8
0
def applyIQFT_circuit(L: int, current_state: np.ndarray) -> np.ndarray:
    """
        Apply IQFT on control register of current state and returns final state using qiskit circuit

    :param L: number of qubits in target register
    :param current_state: state to apply IQFT on
    :return: state after IQFT
    """

    circuit = QuantumCircuit(3 * L)
    circuit.initialize(current_state.reshape(2**(3 * L)), circuit.qubits)
    circuit = QFT.construct_circuit(circuit=circuit,
                                    qubits=circuit.qubits[L:3 * L],
                                    inverse=True,
                                    do_swaps=True)

    backend = qt.Aer.get_backend('statevector_simulator')
    # backend = QCGPUProvider().get_backend('statevector_simulator')
    final_state = execute(circuit, backend, shots=1).result().get_statevector()

    return final_state