def test_reflection_qubits(self): """Test setting idle qubits doesn't apply any operations on these qubits.""" oracle = QuantumCircuit(4) oracle.z(3) grover_op = GroverOperator(oracle, reflection_qubits=[0, 3]) dag = circuit_to_dag(grover_op.decompose()) self.assertEqual(set(dag.idle_wires()), {dag.qubits[1], dag.qubits[2]})
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))
def test_num_mcx_ancillas(self): """Test the number of ancilla bits for the mcx gate in zero_reflection.""" # # q_0: ──■────────────────────── # │ # q_1: ──■────────────────────── # │ # q_2: ──┼────■───────────────── # │ │ # q_3: ──┼────■───────────────── # ┌─┴─┐ │ # q_4: ┤ X ├──┼────■──────────── # └───┘┌─┴─┐ │ # q_5: ─────┤ X ├──■──────────── # ┌───┐├───┤┌─┴─┐┌───┐┌───┐ # q_6: ┤ X ├┤ H ├┤ X ├┤ H ├┤ X ├ # └───┘└───┘└───┘└───┘└───┘ oracle = QuantumCircuit(7) oracle.x(6) oracle.h(6) oracle.ccx(0, 1, 4) oracle.ccx(2, 3, 5) oracle.ccx(4, 5, 6) oracle.h(6) oracle.x(6) grover_op = GroverOperator(oracle, reflection_qubits=[0, 1]) self.assertEqual(grover_op.width(), 7)
def setUp(self): super().setUp() self._oracle = Statevector.from_label('111') self._expected_grover_op = GroverOperator(oracle=self._oracle) self._expected = QuantumCircuit(self._expected_grover_op.num_qubits) self._expected.compose(self._expected_grover_op.state_preparation, inplace=True) self._expected.compose(self._expected_grover_op.power(2), inplace=True) backend = BasicAer.get_backend('statevector_simulator') self._sv = QuantumInstance(backend)
def gen_grover(width): oracle = QuantumCircuit(width, name='q') oracle.z(width - 1) full_circuit = GroverOperator(oracle, insert_barriers=False, name='q') full_circuit = dag_to_circuit(circuit_to_dag(full_circuit)) full_circuit.qregs[0].name = 'q' full_circuit = full_circuit.decompose() full_circuit = transpile(full_circuit, optimization_level=3) return full_circuit
def test_num_mcx_ancillas(self): """Test the number of ancilla bits for the mcx gate in zero_reflection.""" oracle = QuantumCircuit(7) oracle.x(6) oracle.h(6) oracle.ccx(0, 1, 4) oracle.ccx(2, 3, 5) oracle.ccx(4, 5, 6) oracle.h(6) oracle.x(6) grover_op = GroverOperator(oracle, reflection_qubits=[0, 1]) self.assertEqual(grover_op.width(), 7)
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))
def test_construct_circuit(self): """Test construct_circuit""" oracle = QuantumCircuit(2) oracle.cz(0, 1) problem = AmplificationProblem(oracle) grover = Grover() constructed = grover.construct_circuit(problem, 2, measurement=False) grover_op = GroverOperator(oracle) expected = QuantumCircuit(2) expected.h([0, 1]) expected.compose(grover_op.power(2), inplace=True) self.assertTrue(Operator(constructed).equiv(Operator(expected)))
def test_groverop_getter(self, kind): """Test the default construction of the Grover operator.""" oracle = QuantumCircuit(2) oracle.cz(0, 1) if kind == 'oracle_only': problem = AmplificationProblem(oracle) expected = GroverOperator(oracle) else: stateprep = QuantumCircuit(2) stateprep.ry(0.2, [0, 1]) problem = AmplificationProblem(oracle, state_preparation=stateprep) expected = GroverOperator(oracle, stateprep) self.assertEqual(Operator(expected), Operator(problem.grover_operator))
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))
def grover_operator(self) -> Optional[QuantumCircuit]: r"""Get the :math:`\mathcal{Q}` operator, or Grover operator. If the Grover operator is not set, we try to build it from the :math:`\mathcal{A}` operator and `objective_qubits`. This only works if `objective_qubits` is a list of integers. Returns: The Grover operator, or None if neither the Grover operator nor the :math:`\mathcal{A}` operator is set. """ if self._grover_operator is not None: return self._grover_operator # build the reflection about the bad state: a MCZ with open controls (thus X gates # around the controls) and X gates around the target to change from a phaseflip on # |1> to a phaseflip on |0> num_state_qubits = self.state_preparation.num_qubits \ - self.state_preparation.num_ancillas oracle = QuantumCircuit(num_state_qubits) oracle.h(self.objective_qubits[-1]) if len(self.objective_qubits) == 1: oracle.x(self.objective_qubits[0]) else: oracle.mcx(self.objective_qubits[:-1], self.objective_qubits[-1]) oracle.h(self.objective_qubits[-1]) # construct the grover operator return GroverOperator(oracle, self.state_preparation)
def test_good_state(self, backend_str, expect): """Test with a good state function.""" def is_good_state(bitstr): return bitstr[1] == "1" # construct the estimation problem where the second qubit is ignored a_op = QuantumCircuit(2) a_op.ry(2 * np.arcsin(np.sqrt(0.2)), 0) # oracle only affects first qubit oracle = QuantumCircuit(2) oracle.z(0) # reflect only on first qubit q_op = GroverOperator(oracle, a_op, reflection_qubits=[0]) # but we measure both qubits (hence both are objective qubits) problem = EstimationProblem( a_op, objective_qubits=[0, 1], grover_operator=q_op, is_good_state=is_good_state ) # construct algo backend = QuantumInstance( BasicAer.get_backend(backend_str), seed_simulator=2, seed_transpiler=2 ) # cannot use rescaling with a custom grover operator fae = FasterAmplitudeEstimation(0.01, 5, rescale=False, quantum_instance=backend) # run the algo result = fae.estimate(problem) # assert the result is correct self.assertAlmostEqual(result.estimation, expect, places=5)
class TestGroverFunctionality(QiskitAlgorithmsTestCase): """Test for the functionality of Grover""" def setUp(self): super().setUp() self._oracle = Statevector.from_label('111') self._expected_grover_op = GroverOperator(oracle=self._oracle) self._expected = QuantumCircuit(self._expected_grover_op.num_qubits) self._expected.compose(self._expected_grover_op.state_preparation, inplace=True) self._expected.compose(self._expected_grover_op.power(2), inplace=True) backend = BasicAer.get_backend('statevector_simulator') self._sv = QuantumInstance(backend) def test_iterations(self): """Test the iterations argument""" grover = Grover(oracle=self._oracle, good_state=['111'], iterations=2) ret = grover.run(self._sv) self.assertTrue( Operator(ret['circuit']).equiv(Operator(self._expected))) grover = Grover(oracle=self._oracle, good_state=['111'], iterations=[1, 2, 3]) ret = grover.run(self._sv) self.assertTrue(ret.oracle_evaluation) self.assertIn(ret.top_measurement, ['111'])
def grover_operator(self) -> Optional[QuantumCircuit]: r"""Get the :math:`\mathcal{Q}` operator, or Grover operator. If the Grover operator is not set, we try to build it from the :math:`\mathcal{A}` operator and `objective_qubits`. This only works if `objective_qubits` is a list of integers. Returns: The Grover operator, or None if neither the Grover operator nor the :math:`\mathcal{A}` operator is set. """ if self._grover_operator is not None: return self._grover_operator if self.state_preparation is not None and isinstance( self.objective_qubits, list): # build the reflection about the bad state num_state_qubits = self.state_preparation.num_qubits \ - self.state_preparation.num_ancillas oracle = QuantumCircuit(num_state_qubits) oracle.x(self.objective_qubits) oracle.h(self.objective_qubits[-1]) if len(self.objective_qubits) == 1: oracle.x(self.objective_qubits[0]) else: oracle.mcx(self.objective_qubits[:-1], self.objective_qubits[-1]) oracle.h(self.objective_qubits[-1]) oracle.x(self.objective_qubits) # construct the grover operator return GroverOperator(oracle, self.state_preparation) return None
def test_reflection_qubits(self): """Test setting idle qubits doesn't apply any operations on these qubits.""" oracle = QuantumCircuit(4) oracle.z(3) grover_op = GroverOperator(oracle, reflection_qubits=[0, 3]) dag = circuit_to_dag(grover_op) self.assertEqual(set(wire.index for wire in dag.idle_wires()), {1, 2})
def test_grover_operator(self): """Test the base case for the Grover operator.""" with self.subTest('single Z oracle'): oracle = QuantumCircuit(3) oracle.z(2) # good state if last qubit is 1 grover_op = GroverOperator(oracle) self.assertGroverOperatorIsCorrect(grover_op, oracle) with self.subTest('target state x0x1'): oracle = QuantumCircuit(4) oracle.x(1) oracle.z(1) oracle.x(1) oracle.z(3) grover_op = GroverOperator(oracle) self.assertGroverOperatorIsCorrect(grover_op, oracle)
def test_quantum_info_input(self): """Test passing quantum_info.Operator and Statevector as input.""" mark = Statevector.from_label('001') diffuse = 2 * DensityMatrix.from_label('000') - Operator.from_label('III') grover_op = GroverOperator(oracle=mark, zero_reflection=diffuse) self.assertGroverOperatorIsCorrect(grover_op, oracle=np.diag((-1) ** mark.data), zero_reflection=diffuse.data)
def test_grover_operator_getter(self): """Test the getter of grover_operator""" oracle = QuantumCircuit(2) oracle.cz(0, 1) grover = Grover(oracle=oracle, good_state=["11"]) constructed = grover.grover_operator expected = GroverOperator(oracle) self.assertTrue(Operator(constructed).equiv(Operator(expected)))
def test_run_grover_operator_oracle(self): """Test execution with a grover operator oracle""" oracle = QuantumCircuit(2) oracle.cz(0, 1) grover_op = GroverOperator(oracle) grover = Grover(oracle=grover_op.oracle, grover_operator=grover_op, good_state=["11"]) ret = grover.run(self._qasm) self.assertIn(ret.top_measurement, ['11'])
def _init_grover_ops(self): """ Inits grover oracles for the actions set :return: a list of qiskit instructions ready to be appended to circuit """ states_binars = [format(i, '0{}b'.format(self.acts_reg_dim)) for i in range(self.acts_dim)] targ_states = [Statevector.from_label(s) for s in states_binars] grops = [GroverOperator(oracle=ts) for ts in targ_states] return [g.to_instruction() for g in grops]
def test_grover_operator(self): """Test GroverOperator""" oracle = QuantumCircuit(2) oracle.cz(0, 1) grover_op = GroverOperator(oracle) grover = Grover(oracle=grover_op.oracle, grover_operator=grover_op, good_state=["11"]) grover_op = grover._grover_operator self.assertTrue(Operator(grover_op).equiv(Operator(self._expected_grover_op)))
def test_custom_state_in(self): """Test passing a custom state_in operator.""" oracle = QuantumCircuit(1) oracle.z(0) bernoulli = QuantumCircuit(1) sampling_probability = 0.2 bernoulli.ry(2 * np.arcsin(np.sqrt(sampling_probability)), 0) grover_op = GroverOperator(oracle, bernoulli) self.assertGroverOperatorIsCorrect(grover_op, oracle, bernoulli)
def test_construct_circuit(self): """Test construct_circuit""" oracle = QuantumCircuit(2) oracle.cz(0, 1) grover = Grover(oracle=oracle, good_state=["11"]) constructed = grover.construct_circuit(1) grover_op = GroverOperator(oracle) expected = QuantumCircuit(2) expected.compose(grover_op.state_preparation, inplace=True) expected.compose(grover_op, inplace=True) self.assertTrue(Operator(constructed).equiv(Operator(expected)))
def test_state_preparation_quantumcircuit(self): """Test QuantumCircuit state_preparation""" state_preparation = QuantumCircuit(2) state_preparation.h(0) oracle = QuantumCircuit(3) oracle.cz(0, 1) grover = Grover(oracle=oracle, state_preparation=state_preparation, good_state=["011"]) grover_op = grover._grover_operator expected_grover_op = GroverOperator(oracle, state_preparation=state_preparation) self.assertTrue(Operator(grover_op).equiv(Operator(expected_grover_op)))
def test_run_custom_grover_operator(self): """Test execution with a grover operator oracle""" oracle = QuantumCircuit(2) oracle.cz(0, 1) grover_op = GroverOperator(oracle) problem = AmplificationProblem(oracle=oracle, grover_operator=grover_op, is_good_state=['11']) grover = Grover(quantum_instance=self.qasm) ret = grover.amplify(problem) self.assertIn(ret.top_measurement, ['11'])
def test_custom_zero_reflection(self): """Test passing in a custom zero reflection.""" oracle = QuantumCircuit(1) oracle.z(0) zero_reflection = QuantumCircuit(1) zero_reflection.x(0) zero_reflection.rz(np.pi, 0) zero_reflection.x(0) grover_op = GroverOperator(oracle, zero_reflection=zero_reflection) with self.subTest("zero reflection up to phase works"): self.assertGroverOperatorIsCorrect(grover_op, oracle) with self.subTest("circuits match"): expected = QuantumCircuit(*grover_op.qregs, global_phase=np.pi) expected.compose(oracle, inplace=True) expected.h(0) # state_in is H expected.compose(zero_reflection, inplace=True) expected.h(0) self.assertEqual(expected, grover_op.decompose())
def grover_operator(self) -> Optional[QuantumCircuit]: r"""Get the :math:`\mathcal{Q}` operator, or Grover operator. If the Grover operator is not set, we try to build it from the :math:`\mathcal{A}` operator and `objective_qubits`. This only works if `objective_qubits` is a list of integers. Returns: The Grover operator, or None if neither the Grover operator nor the :math:`\mathcal{A}` operator is set. """ if self._grover_operator is None: return GroverOperator(self.oracle, self.state_preparation) return self._grover_operator
def test_stateprep_contains_instruction(self): """Test wrapping works if the state preparation is not unitary.""" oracle = QuantumCircuit(1) oracle.z(0) instr = QuantumCircuit(1) instr.s(0) instr = instr.to_instruction() stateprep = QuantumCircuit(1) stateprep.append(instr, [0]) grover_op = GroverOperator(oracle, stateprep) self.assertEqual(grover_op.num_qubits, 1)
def setUp(self): super().setUp() self.a_bernoulli = BernoulliStateIn(0) self.q_bernoulli = BernoulliGrover(0) self.i_bernoulli = [0] num_qubits = 5 self.a_integral = SineIntegral(num_qubits) oracle = QuantumCircuit(num_qubits + 1) oracle.x(num_qubits) oracle.z(num_qubits) oracle.x(num_qubits) self.q_integral = GroverOperator(oracle, self.a_integral) self.i_integral = [num_qubits]
def _construct_grover_operator(oracle, state_preparation, mct_mode): # check the type of state_preparation if not (isinstance(state_preparation, QuantumCircuit) or state_preparation is None): raise TypeError('Unsupported type "{}" of state_preparation'.format( type(state_preparation))) # check to oracle type reflection_qubits = None if not isinstance(oracle, (QuantumCircuit, Statevector)): raise TypeError('Unsupported type "{}" of oracle'.format(type(oracle))) grover_operator = GroverOperator(oracle=oracle, state_preparation=state_preparation, reflection_qubits=reflection_qubits, mcx_mode=mct_mode) return grover_operator