コード例 #1
0
    def _build_operator(
            self, func_dict: Dict[Union[int, Tuple[int, int]],
                                  int]) -> QuantumCircuit:
        """Creates a circuit for the state preparation operator.

        Args:
            func_dict: Representation of the QUBO problem. The keys should be subscripts of the
                coefficients (e.g. x_1 -> 1), with the constant (if present) being represented with
                a key of -1 (i.e. d[-1] = constant). Quadratic coefficients should use a tuple for
                the key, with the corresponding subscripts inside (e.g. 2*x_1*x_2 -> d[(1,2)]=2).

        Returns:
            Circuit object describing the state preparation operator.
        """

        # Build initial circuit.
        key_val = QuantumRegister(self._num_key + self._num_value, "key_value")
        circuit = QuantumCircuit(key_val)
        if self._measurement:
            measure = ClassicalRegister(self._num_key + self._num_value)
            circuit.add_register(measure)
        circuit.h(key_val)

        # Linear Coefficients.
        for i in range(self._num_value):
            if func_dict.get(-1, 0) != 0:
                circuit.u1(
                    1 / 2**self._num_value * 2 * np.pi * 2**i * func_dict[-1],
                    key_val[self._num_key + i])
            for j in range(self._num_key):
                if func_dict.get(j, 0) != 0:
                    circuit.cu1(
                        1 / 2**self._num_value * 2 * np.pi * 2**i *
                        func_dict[j], key_val[j], key_val[self._num_key + i])

        # Quadratic Coefficients.
        for i in range(self._num_value):
            for k, v in func_dict.items():
                if isinstance(k, tuple):
                    circuit.mcu1(1 / 2**self._num_value * 2 * np.pi * 2**i * v,
                                 [key_val[k[0]], key_val[k[1]]],
                                 key_val[self._num_key + i])

        # Add IQFT.
        iqft = IQFT(self._num_value)
        value = [
            key_val[v]
            for v in range(self._num_key, self._num_key + self._num_value)
        ]
        iqft.construct_circuit(qubits=value, circuit=circuit)

        return circuit
コード例 #2
0
    def test_qae_circuit(self, efficient_circuit):
        """Test circuits resulting from canonical amplitude estimation.

        Build the circuit manually and from the algorithm and compare the resulting unitaries.
        """
        prob = 0.5

        for m in range(2, 7):
            qae = AmplitudeEstimation(m, a_factory=BernoulliAFactory(prob))
            angle = 2 * np.arcsin(np.sqrt(prob))

            # manually set up the inefficient AE circuit
            q_ancilla = QuantumRegister(m, 'a')
            q_objective = QuantumRegister(1, 'q')
            circuit = QuantumCircuit(q_ancilla, q_objective)

            # initial Hadamard gates
            for i in range(m):
                circuit.h(q_ancilla[i])

            # A operator
            circuit.ry(angle, q_objective)

            if efficient_circuit:
                qae.q_factory = BernoulliQFactory(qae.a_factory)
                for power in range(m):
                    circuit.cry(2 * 2**power * angle, q_ancilla[power],
                                q_objective[0])

            else:
                q_factory = QFactory(qae.a_factory, i_objective=0)
                for power in range(m):
                    for _ in range(2**power):
                        q_factory.build_controlled(circuit, q_objective,
                                                   q_ancilla[power])

            # fourier transform
            iqft = Standard(m)
            circuit = iqft.construct_circuit(qubits=q_ancilla,
                                             circuit=circuit,
                                             do_swaps=False)
            expected_unitary = self._unitary.execute(circuit).get_unitary()

            actual_circuit = qae.construct_circuit(measurement=False)
            actual_unitary = self._unitary.execute(
                actual_circuit).get_unitary()

            diff = np.sum(np.abs(actual_unitary - expected_unitary))
            self.assertAlmostEqual(diff, 0)