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