def _get_ideal_data(self, circuit: QuantumCircuit, **run_options) -> List[float]: """Return ideal measurement probabilities. In case the user does not have Aer installed use Terra to calculate the ideal state. Args: circuit: the circuit to extract the ideal data from run_options: backend run options. Returns: list: list of the probabilities for each state in the circuit (as Numpy array) """ ideal_circuit = circuit.remove_final_measurements(inplace=False) if self._simulation_backend: ideal_circuit.save_probabilities() # always transpile with optimization_level 0, even if the non ideal circuits will run # with different optimization level, because we need to compare the results to the # exact generated probabilities ideal_circuit = transpile(ideal_circuit, self._simulation_backend, optimization_level=0) ideal_result = self._simulation_backend.run( ideal_circuit, **run_options).result() probabilities = ideal_result.data().get("probabilities") else: from qiskit.quantum_info import Statevector state_vector = Statevector(ideal_circuit) probabilities = state_vector.probabilities() return probabilities
def assertMultiplicationIsCorrect( self, num_state_qubits: int, num_result_qubits: int, multiplier: QuantumCircuit ): """Assert that multiplier correctly implements the product. Args: num_state_qubits: The number of bits in the numbers that are multiplied. num_result_qubits: The number of qubits to limit the output to with modulo. multiplier: The circuit performing the multiplication of two numbers with ``num_state_qubits`` bits. """ circuit = QuantumCircuit(*multiplier.qregs) # create equal superposition circuit.h(range(2 * num_state_qubits)) # apply multiplier circuit circuit.compose(multiplier, inplace=True) # obtain the statevector and the probabilities, we don't trace out the ancilla qubits # as we verify that all ancilla qubits have been uncomputed to state 0 again statevector = Statevector(circuit) probabilities = statevector.probabilities() pad = "0" * circuit.num_ancillas # state of the ancillas # compute the expected results expectations = np.zeros_like(probabilities) num_bits_product = num_state_qubits * 2 # iterate over all possible inputs for x in range(2 ** num_state_qubits): for y in range(2 ** num_state_qubits): # compute the product product = x * y % (2 ** num_result_qubits) # compute correct index in statevector bin_x = bin(x)[2:].zfill(num_state_qubits) bin_y = bin(y)[2:].zfill(num_state_qubits) bin_res = bin(product)[2:].zfill(num_bits_product) bin_index = pad + bin_res + bin_y + bin_x index = int(bin_index, 2) expectations[index] += 1 / 2 ** (2 * num_state_qubits) np.testing.assert_array_almost_equal(expectations, probabilities)
def assertAdditionIsCorrect(self, num_state_qubits: int, adder: QuantumCircuit, inplace: bool, kind: str): """Assert that adder correctly implements the summation. This test prepares a equal superposition state in both input registers, then performs the addition on the superposition and checks that the output state is the expected superposition of all possible additions. Args: num_state_qubits: The number of bits in the numbers that are added. adder: The circuit performing the addition of two numbers with ``num_state_qubits`` bits. inplace: If True, compare against an inplace addition where the result is written into the second register plus carry qubit. If False, assume that the result is written into a third register of appropriate size. kind: TODO """ circuit = QuantumCircuit(*adder.qregs) # create equal superposition if kind == "full": num_superpos_qubits = 2 * num_state_qubits + 1 else: num_superpos_qubits = 2 * num_state_qubits circuit.h(range(num_superpos_qubits)) # apply adder circuit circuit.compose(adder, inplace=True) # obtain the statevector and the probabilities, we don't trace out the ancilla qubits # as we verify that all ancilla qubits have been uncomputed to state 0 again statevector = Statevector(circuit) probabilities = statevector.probabilities() pad = "0" * circuit.num_ancillas # state of the ancillas # compute the expected results expectations = np.zeros_like(probabilities) num_bits_sum = num_state_qubits + 1 # iterate over all possible inputs for x in range(2**num_state_qubits): for y in range(2**num_state_qubits): # compute the sum if kind == "full": additions = [x + y, 1 + x + y] elif kind == "half": additions = [x + y] else: additions = [(x + y) % (2**num_state_qubits)] # compute correct index in statevector bin_x = bin(x)[2:].zfill(num_state_qubits) bin_y = bin(y)[2:].zfill(num_state_qubits) for i, addition in enumerate(additions): bin_res = bin(addition)[2:].zfill(num_bits_sum) if kind == "full": cin = str(i) bin_index = (pad + bin_res + bin_x + cin if inplace else pad + bin_res + bin_y + bin_x + cin) else: bin_index = (pad + bin_res + bin_x if inplace else pad + bin_res + bin_y + bin_x) index = int(bin_index, 2) expectations[index] += 1 / 2**num_superpos_qubits np.testing.assert_array_almost_equal(expectations, probabilities)