def test_mlae_circuits(self, efficient_circuit): """ Test the circuits constructed for MLAE """ prob = 0.5 problem = EstimationProblem(BernoulliStateIn(prob), objective_qubits=[0]) for k in [2, 5]: qae = MaximumLikelihoodAmplitudeEstimation(k) angle = 2 * np.arcsin(np.sqrt(prob)) # compute all the circuits used for MLAE circuits = [] # 0th power q_objective = QuantumRegister(1, 'q') circuit = QuantumCircuit(q_objective) circuit.ry(angle, q_objective) circuits += [circuit] # powers of 2 for power in range(k): q_objective = QuantumRegister(1, 'q') circuit = QuantumCircuit(q_objective) # A operator circuit.ry(angle, q_objective) # Q^(2^j) operator if efficient_circuit: qae.grover_operator = BernoulliGrover(prob) circuit.ry(2 * 2**power * angle, q_objective[0]) else: oracle = QuantumCircuit(1) oracle.z(0) state_preparation = QuantumCircuit(1) state_preparation.ry(angle, 0) grover_op = GroverOperator(oracle, state_preparation) grover_op.global_phase = np.pi for _ in range(2**power): circuit.compose(grover_op, inplace=True) circuits += [circuit] actual_circuits = qae.construct_circuits(problem, measurement=False) for actual, expected in zip(actual_circuits, circuits): self.assertEqual(Operator(actual), Operator(expected))
class TestBernoulli(QiskitAlgorithmsTestCase): """Tests based on the Bernoulli A operator. This class tests * the estimation result * the constructed circuits """ def setUp(self): super().setUp() self._statevector = QuantumInstance( backend=BasicAer.get_backend("statevector_simulator"), seed_simulator=2, seed_transpiler=2, ) self._unitary = QuantumInstance( backend=BasicAer.get_backend("unitary_simulator"), shots=1, seed_simulator=42, seed_transpiler=91, ) def qasm(shots=100): return QuantumInstance( backend=BasicAer.get_backend("qasm_simulator"), shots=shots, seed_simulator=2, seed_transpiler=2, ) self._qasm = qasm @idata( [ [0.2, AmplitudeEstimation(2), {"estimation": 0.5, "mle": 0.2}], [0.49, AmplitudeEstimation(3), {"estimation": 0.5, "mle": 0.49}], [0.2, MaximumLikelihoodAmplitudeEstimation([0, 1, 2]), {"estimation": 0.2}], [0.49, MaximumLikelihoodAmplitudeEstimation(3), {"estimation": 0.49}], [0.2, IterativeAmplitudeEstimation(0.1, 0.1), {"estimation": 0.2}], [0.49, IterativeAmplitudeEstimation(0.001, 0.01), {"estimation": 0.49}], [0.2, FasterAmplitudeEstimation(0.1, 3, rescale=False), {"estimation": 0.2}], [0.12, FasterAmplitudeEstimation(0.1, 2, rescale=False), {"estimation": 0.12}], ] ) @unpack def test_statevector(self, prob, qae, expect): """statevector test""" qae.quantum_instance = self._statevector problem = EstimationProblem(BernoulliStateIn(prob), 0, BernoulliGrover(prob)) result = qae.estimate(problem) self.assertGreaterEqual(self._statevector.time_taken, 0.0) self._statevector.reset_execution_results() for key, value in expect.items(): self.assertAlmostEqual( value, getattr(result, key), places=3, msg=f"estimate `{key}` failed" ) @idata( [ [0.2, 100, AmplitudeEstimation(4), {"estimation": 0.14644, "mle": 0.193888}], [0.0, 1000, AmplitudeEstimation(2), {"estimation": 0.0, "mle": 0.0}], [ 0.2, 100, MaximumLikelihoodAmplitudeEstimation([0, 1, 2, 4, 8]), {"estimation": 0.199606}, ], [0.8, 10, IterativeAmplitudeEstimation(0.1, 0.05), {"estimation": 0.811711}], [0.2, 1000, FasterAmplitudeEstimation(0.1, 3, rescale=False), {"estimation": 0.198640}], [ 0.12, 100, FasterAmplitudeEstimation(0.01, 3, rescale=False), {"estimation": 0.119037}, ], ] ) @unpack def test_qasm(self, prob, shots, qae, expect): """qasm test""" qae.quantum_instance = self._qasm(shots) problem = EstimationProblem(BernoulliStateIn(prob), [0], BernoulliGrover(prob)) result = qae.estimate(problem) for key, value in expect.items(): self.assertAlmostEqual( value, getattr(result, key), places=3, msg=f"estimate `{key}` failed" ) @data(True, False) 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 problem = EstimationProblem(BernoulliStateIn(prob), objective_qubits=[0]) for m in [2, 5]: qae = AmplitudeEstimation(m) angle = 2 * np.arcsin(np.sqrt(prob)) # manually set up the inefficient AE circuit qr_eval = QuantumRegister(m, "a") qr_objective = QuantumRegister(1, "q") circuit = QuantumCircuit(qr_eval, qr_objective) # initial Hadamard gates for i in range(m): circuit.h(qr_eval[i]) # A operator circuit.ry(angle, qr_objective) if efficient_circuit: qae.grover_operator = BernoulliGrover(prob) for power in range(m): circuit.cry(2 * 2 ** power * angle, qr_eval[power], qr_objective[0]) else: oracle = QuantumCircuit(1) oracle.z(0) state_preparation = QuantumCircuit(1) state_preparation.ry(angle, 0) grover_op = GroverOperator(oracle, state_preparation) grover_op.global_phase = np.pi for power in range(m): circuit.compose( grover_op.power(2 ** power).control(), qubits=[qr_eval[power], qr_objective[0]], inplace=True, ) # fourier transform iqft = QFT(m, do_swaps=False).inverse().reverse_bits() circuit.append(iqft.to_instruction(), qr_eval) actual_circuit = qae.construct_circuit(problem, measurement=False) self.assertEqual(Operator(circuit), Operator(actual_circuit)) @data(True, False) def test_iqae_circuits(self, efficient_circuit): """Test circuits resulting from iterative amplitude estimation. Build the circuit manually and from the algorithm and compare the resulting unitaries. """ prob = 0.5 problem = EstimationProblem(BernoulliStateIn(prob), objective_qubits=[0]) for k in [2, 5]: qae = IterativeAmplitudeEstimation(0.01, 0.05) angle = 2 * np.arcsin(np.sqrt(prob)) # manually set up the inefficient AE circuit q_objective = QuantumRegister(1, "q") circuit = QuantumCircuit(q_objective) # A operator circuit.ry(angle, q_objective) if efficient_circuit: qae.grover_operator = BernoulliGrover(prob) circuit.ry(2 * k * angle, q_objective[0]) else: oracle = QuantumCircuit(1) oracle.z(0) state_preparation = QuantumCircuit(1) state_preparation.ry(angle, 0) grover_op = GroverOperator(oracle, state_preparation) grover_op.global_phase = np.pi for _ in range(k): circuit.compose(grover_op, inplace=True) actual_circuit = qae.construct_circuit(problem, k, measurement=False) self.assertEqual(Operator(circuit), Operator(actual_circuit)) @data(True, False) def test_mlae_circuits(self, efficient_circuit): """Test the circuits constructed for MLAE""" prob = 0.5 problem = EstimationProblem(BernoulliStateIn(prob), objective_qubits=[0]) for k in [2, 5]: qae = MaximumLikelihoodAmplitudeEstimation(k) angle = 2 * np.arcsin(np.sqrt(prob)) # compute all the circuits used for MLAE circuits = [] # 0th power q_objective = QuantumRegister(1, "q") circuit = QuantumCircuit(q_objective) circuit.ry(angle, q_objective) circuits += [circuit] # powers of 2 for power in range(k): q_objective = QuantumRegister(1, "q") circuit = QuantumCircuit(q_objective) # A operator circuit.ry(angle, q_objective) # Q^(2^j) operator if efficient_circuit: qae.grover_operator = BernoulliGrover(prob) circuit.ry(2 * 2 ** power * angle, q_objective[0]) else: oracle = QuantumCircuit(1) oracle.z(0) state_preparation = QuantumCircuit(1) state_preparation.ry(angle, 0) grover_op = GroverOperator(oracle, state_preparation) grover_op.global_phase = np.pi for _ in range(2 ** power): circuit.compose(grover_op, inplace=True) circuits += [circuit] actual_circuits = qae.construct_circuits(problem, measurement=False) for actual, expected in zip(actual_circuits, circuits): self.assertEqual(Operator(actual), Operator(expected))
class TestSineIntegral(QiskitAlgorithmsTestCase): """Tests based on the A operator to integrate sin^2(x). This class tests * the estimation result * the confidence intervals """ def setUp(self): super().setUp() self._statevector = QuantumInstance( backend=BasicAer.get_backend("statevector_simulator"), seed_simulator=123, seed_transpiler=41, ) def qasm(shots=100): return QuantumInstance( backend=BasicAer.get_backend("qasm_simulator"), shots=shots, seed_simulator=7192, seed_transpiler=90000, ) self._qasm = qasm @idata( [ [2, AmplitudeEstimation(2), {"estimation": 0.5, "mle": 0.270290}], [4, MaximumLikelihoodAmplitudeEstimation(4), {"estimation": 0.272675}], [3, IterativeAmplitudeEstimation(0.1, 0.1), {"estimation": 0.272082}], [3, FasterAmplitudeEstimation(0.01, 1), {"estimation": 0.272082}], ] ) @unpack def test_statevector(self, n, qae, expect): """Statevector end-to-end test""" # construct factories for A and Q # qae.state_preparation = SineIntegral(n) qae.quantum_instance = self._statevector estimation_problem = EstimationProblem(SineIntegral(n), objective_qubits=[n]) # result = qae.run(self._statevector) result = qae.estimate(estimation_problem) self.assertGreaterEqual(self._statevector.time_taken, 0.0) self._statevector.reset_execution_results() for key, value in expect.items(): self.assertAlmostEqual( value, getattr(result, key), places=3, msg=f"estimate `{key}` failed" ) @idata( [ [4, 10, AmplitudeEstimation(2), {"estimation": 0.5, "mle": 0.333333}], [3, 10, MaximumLikelihoodAmplitudeEstimation(2), {"estimation": 0.256878}], [3, 1000, IterativeAmplitudeEstimation(0.01, 0.01), {"estimation": 0.271790}], [3, 1000, FasterAmplitudeEstimation(0.1, 4), {"estimation": 0.274168}], ] ) @unpack def test_qasm(self, n, shots, qae, expect): """QASM simulator end-to-end test.""" # construct factories for A and Q qae.quantum_instance = self._qasm(shots) estimation_problem = EstimationProblem(SineIntegral(n), objective_qubits=[n]) result = qae.estimate(estimation_problem) for key, value in expect.items(): self.assertAlmostEqual( value, getattr(result, key), places=3, msg=f"estimate `{key}` failed" ) @idata( [ [ AmplitudeEstimation(3), "mle", { "likelihood_ratio": (0.2494734, 0.3003771), "fisher": (0.2486176, 0.2999286), "observed_fisher": (0.2484562, 0.3000900), }, ], [ MaximumLikelihoodAmplitudeEstimation(3), "estimation", { "likelihood_ratio": (0.2598794, 0.2798536), "fisher": (0.2584889, 0.2797018), "observed_fisher": (0.2659279, 0.2722627), }, ], ] ) @unpack def test_confidence_intervals(self, qae, key, expect): """End-to-end test for all confidence intervals.""" n = 3 qae.quantum_instance = self._statevector estimation_problem = EstimationProblem(SineIntegral(n), objective_qubits=[n]) # statevector simulator result = qae.estimate(estimation_problem) self.assertGreater(self._statevector.time_taken, 0.0) self._statevector.reset_execution_results() methods = ["lr", "fi", "oi"] # short for likelihood_ratio, fisher, observed_fisher alphas = [0.1, 0.00001, 0.9] # alpha shouldn't matter in statevector for alpha, method in zip(alphas, methods): confint = qae.compute_confidence_interval(result, alpha, method) # confidence interval based on statevector should be empty, as we are sure of the result self.assertAlmostEqual(confint[1] - confint[0], 0.0) self.assertAlmostEqual(confint[0], getattr(result, key)) # qasm simulator shots = 100 alpha = 0.01 qae.quantum_instance = self._qasm(shots) result = qae.estimate(estimation_problem) for method, expected_confint in expect.items(): confint = qae.compute_confidence_interval(result, alpha, method) np.testing.assert_array_almost_equal(confint, expected_confint) self.assertTrue(confint[0] <= getattr(result, key) <= confint[1]) def test_iqae_confidence_intervals(self): """End-to-end test for the IQAE confidence interval.""" n = 3 qae = IterativeAmplitudeEstimation(0.1, 0.01, quantum_instance=self._statevector) expected_confint = (0.1984050, 0.3511015) estimation_problem = EstimationProblem(SineIntegral(n), objective_qubits=[n]) # statevector simulator result = qae.estimate(estimation_problem) self.assertGreaterEqual(self._statevector.time_taken, 0.0) self._statevector.reset_execution_results() confint = result.confidence_interval # confidence interval based on statevector should be empty, as we are sure of the result self.assertAlmostEqual(confint[1] - confint[0], 0.0) self.assertAlmostEqual(confint[0], result.estimation) # qasm simulator shots = 100 qae.quantum_instance = self._qasm(shots) result = qae.estimate(estimation_problem) confint = result.confidence_interval np.testing.assert_array_almost_equal(confint, expected_confint) self.assertTrue(confint[0] <= result.estimation <= confint[1])