def rzx_xz(theta: float = None): """Template for CX - RXGate - CX.""" if theta is None: theta = Parameter('ϴ') qc = QuantumCircuit(2) qc.cx(1, 0) qc.rx(theta, 1) qc.cx(1, 0) qc.rz(np.pi / 2, 0) qc.rx(np.pi / 2, 0) qc.rz(np.pi / 2, 0) qc.rzx(-1 * theta, 0, 1) qc.rz(np.pi / 2, 0) qc.rx(np.pi / 2, 0) qc.rz(np.pi / 2, 0) return qc
def test_expressions_division_by_zero(self): """Verify divding a Parameter by 0, or binding 0 as a denominator raises.""" x = Parameter('x') with self.assertRaises(ZeroDivisionError): _ = x / 0 with self.assertRaises(ZeroDivisionError): _ = x / 0.0 expr = 2 / x with self.assertRaises(ZeroDivisionError): _ = expr.bind({x: 0}) with self.assertRaises(ZeroDivisionError): _ = expr.bind({x: 0.0})
def __init__( self, basis_gates: Optional[List[str]] = None, default_values: Optional[Dict] = None, use_drag: bool = True, link_parameters: bool = True, ): """Setup the schedules. Args: basis_gates: The basis gates to generate. default_values: Default values for the parameters this dictionary can contain the following keys: "duration", "amp", "β", and "σ". If "σ" is not provided this library will take one fourth of the pulse duration as default value. use_drag: If set to False then Gaussian pulses will be used instead of DRAG pulses. link_parameters: if set to True then the amplitude and DRAG parameters of the X and Y gates will be linked as well as those of the SX and SY gates. """ super().__init__(basis_gates, default_values) self._link_parameters = link_parameters dur = Parameter("duration") sigma = Parameter("σ") # Generate the pulse parameters def _beta(use_drag): return Parameter("β") if use_drag else None x_amp, x_beta = Parameter("amp"), _beta(use_drag) if self._link_parameters: y_amp, y_beta = 1.0j * x_amp, x_beta else: y_amp, y_beta = Parameter("amp"), _beta(use_drag) sx_amp, sx_beta = Parameter("amp"), _beta(use_drag) if self._link_parameters: sy_amp, sy_beta = 1.0j * sx_amp, sx_beta else: sy_amp, sy_beta = Parameter("amp"), _beta(use_drag) # Create the schedules for the gates sched_x = self._single_qubit_schedule("x", dur, x_amp, sigma, x_beta) sched_y = self._single_qubit_schedule("y", dur, y_amp, sigma, y_beta) sched_sx = self._single_qubit_schedule("sx", dur, sx_amp, sigma, sx_beta) sched_sy = self._single_qubit_schedule("sy", dur, sy_amp, sigma, sy_beta) for sched in [sched_x, sched_y, sched_sx, sched_sy]: if sched.name in self._basis_gates: self._schedules[sched.name] = sched
def test_appending_for_loop_op(self): """Verify we can append a ForLoopOp to a QuantumCircuit.""" body = QuantumCircuit(3, 1) loop_parameter = Parameter("foo") indexset = range(0, 10, 2) body.rx(loop_parameter, [0, 1, 2]) op = ForLoopOp(indexset, loop_parameter, body) qc = QuantumCircuit(5, 2) qc.append(op, [1, 2, 3], [1]) self.assertEqual(qc.data[0].operation.name, "for_loop") self.assertEqual(qc.data[0].operation.params, [indexset, loop_parameter, body]) self.assertEqual(qc.data[0].qubits, tuple(qc.qubits[1:4])) self.assertEqual(qc.data[0].clbits, (qc.clbits[1], ))
def test_qobj_with_hamiltonian(self): """test qobj output with hamiltonian""" qr = QuantumRegister(4) qc = QuantumCircuit(qr) qc.rx(np.pi / 4, qr[0]) matrix = Operator.from_label('XIZ') theta = Parameter('theta') uni = HamiltonianGate(matrix, theta, label='XIZ') qc.append(uni, [qr[0], qr[1], qr[3]]) qc.cx(qr[3], qr[2]) qc = qc.bind_parameters({theta: np.pi / 2}) qobj = qiskit.compiler.assemble(qc) instr = qobj.experiments[0].instructions[1] self.assertEqual(instr.name, 'hamiltonian') # Also test label self.assertEqual(instr.label, 'XIZ') np.testing.assert_array_almost_equal( np.array(instr.params[0]).astype(np.complex64), matrix.data)
def get_ghz_mqc_para(n, extent='full'): ''' This function creates an MQC circuit with n qubits, where the middle phase rotation around the z axis is by delta ''' q = QuantumRegister(n, 'q') circ = get_ghz_simple(n, obs=False) delta = Parameter('t') circinv = circ.inverse() circ.barrier() circ.u1(delta, q) circ.x(q) circ.barrier() circ += circinv meas = get_ghz_measurement(n, extent) circ = circ + meas circ.draw() return circ, delta
def test_run_path_with_expressions_multiple_params_per_instruction(self): """Test parameterized circuit path via backed.run()""" shots = 1000 backend = AerSimulator() circuit = QuantumCircuit(2) theta = Parameter('theta') theta_squared = theta * theta circuit.rx(theta, 0) circuit.cx(0, 1) circuit.rz(theta_squared, 1) circuit.u(theta, theta_squared, theta, 1) circuit.measure_all() parameter_binds = [{theta: [0, pi, 2 * pi]}] res = backend.run(circuit, shots=shots, parameter_binds=parameter_binds).result() counts = res.get_counts() self.assertEqual(counts, [{'00': shots}, {'01': shots}, {'00': shots}])
def test_parameterized_calibrations_transpile(self): """Check that gates can be matched to their calibrations before and after parameter assignment.""" tau = Parameter('tau') circ = QuantumCircuit(3, 3) circ.append(Gate('rxt', 1, [2*3.14*tau]), [0]) def q0_rxt(tau): with pulse.build() as q0_rxt: pulse.play(pulse.library.Gaussian(20, 0.4*tau, 3.0), pulse.DriveChannel(0)) return q0_rxt circ.add_calibration('rxt', [0], q0_rxt(tau), [2*3.14*tau]) transpiled_circ = transpile(circ, FakeAlmaden()) self.assertEqual(set(transpiled_circ.count_ops().keys()), {'rxt'}) circ = circ.assign_parameters({tau: 1}) transpiled_circ = transpile(circ, FakeAlmaden()) self.assertEqual(set(transpiled_circ.count_ops().keys()), {'rxt'})
def test_quantum_circuit_with_bound_parameters(self, recorder): """Tests loading a quantum circuit that already had bound parameters.""" theta = Parameter('θ') qc = QuantumCircuit(3, 1) qc.rz(theta, [0]) qc_1 = qc.bind_parameters({theta: 0.5}) quantum_circuit = load(qc_1) with recorder: quantum_circuit() assert len(recorder.queue) == 1 assert recorder.queue[0].name == 'RZ' assert recorder.queue[0].params == [0.5] assert recorder.queue[0].wires == [0]
def test_parameter_expression_circuit_for_device(self): """Verify that a circuit including expressions of parameters can be transpiled for a device backend.""" qr = QuantumRegister(2, name='qr') qc = QuantumCircuit(qr) theta = Parameter('theta') square = theta * theta qc.rz(square, qr[0]) transpiled_qc = transpile(qc, backend=FakeMelbourne(), initial_layout=Layout.generate_trivial_layout(qr)) qr = QuantumRegister(14, 'q') expected_qc = QuantumCircuit(qr) expected_qc.u1(square, qr[0]) self.assertEqual(expected_qc, transpiled_qc)
def test_single_parameter_binds(self): """Test passing parameter binds as a dictionary to the circuit sampler.""" try: from qiskit.providers.aer import Aer except Exception as ex: # pylint: disable=broad-except self.skipTest(f"Aer doesn't appear to be installed. Error: '{str(ex)}'") return x = Parameter("x") circuit = QuantumCircuit(1) circuit.ry(x, 0) expr = ~StateFn(H) @ StateFn(circuit) sampler = CircuitSampler(Aer.get_backend("aer_simulator_statevector")) res = sampler.convert(expr, params={x: 0}).eval() self.assertIsInstance(res, complex)
def test_for_loop_iterable_instantiation(self): """Verify creation and properties of a ForLoopOp using an iterable indexset.""" body = QuantumCircuit(3, 1) loop_parameter = Parameter("foo") indexset = iter(range(0, 10, 2)) body.rx(loop_parameter, 0) op = ForLoopOp(indexset, loop_parameter, body) self.assertIsInstance(op, ControlFlowOp) self.assertIsInstance(op, Instruction) self.assertEqual(op.name, "for_loop") self.assertEqual(op.num_qubits, 3) self.assertEqual(op.num_clbits, 1) self.assertEqual(op.params, [tuple(range(0, 10, 2)), loop_parameter, body]) self.assertEqual(op.blocks, (body, ))
def test_circuit_generation(self): """Test creating a series of circuits parametrically""" theta = Parameter('θ') qr = QuantumRegister(1) qc = QuantumCircuit(qr) qc.rx(theta, qr) backend = BasicAer.get_backend('qasm_simulator') qc_aer = transpile(qc, backend) # generate list of circuits circs = [] theta_list = numpy.linspace(0, numpy.pi, 20) for theta_i in theta_list: circs.append(qc_aer.bind_parameters({theta: theta_i})) qobj = assemble(circs) for index, theta_i in enumerate(theta_list): self.assertEqual(float(qobj.experiments[index].instructions[0].params[0]), theta_i)
def test_parameterized_circuit_for_device(self): """Verify that a parameterized circuit can be transpiled for a device backend.""" qr = QuantumRegister(2, name='qr') qc = QuantumCircuit(qr) theta = Parameter('theta') qc.rz(theta, qr[0]) transpiled_qc = transpile( qc, backend=FakeMelbourne(), initial_layout=Layout.generate_trivial_layout(qr)) qr = QuantumRegister(14, 'q') expected_qc = QuantumCircuit(qr) expected_qc.append(U1Gate(theta), [qr[0]]) self.assertEqual(expected_qc, transpiled_qc)
def _build(self): if self._data is not None: return self._check_configuration() self._data = [] # get the evolved operators as circuits coeff = Parameter('c') evolved_ops = [ self.evolution.convert((coeff * op).exp_i()) for op in self.operators ] circuits = [ evolved_op.reduce().to_circuit() for evolved_op in evolved_ops ] # set the registers num_qubits = circuits[0].num_qubits try: qr = QuantumRegister(num_qubits, 'q') self.add_register(qr) except CircuitError: # the register already exists, probably because of a previous composition pass # build the circuit times = ParameterVector('t', self.reps * len(self.operators)) times_it = iter(times) first = True for _ in range(self.reps): for circuit in circuits: if first: first = False else: if self._insert_barriers: self.barrier() self.compose(circuit.assign_parameters({coeff: next(times_it)}), inplace=True) if self._initial_state: self.compose(self._initial_state, front=True, inplace=True)
def _single_qubit_schedule( name: str, dur: Parameter, amp: Parameter, sigma: Parameter, beta: Optional[Parameter] = None, ) -> ScheduleBlock: """Build a single qubit pulse.""" chan = pulse.DriveChannel(Parameter("ch0")) if beta is not None: with pulse.build(name=name) as sched: pulse.play(pulse.Drag(duration=dur, amp=amp, sigma=sigma, beta=beta), chan) else: with pulse.build(name=name) as sched: pulse.play(pulse.Gaussian(duration=dur, amp=amp, sigma=sigma), chan) return sched
def test_single_parameterized_circuit(self): """Parameters should be treated as opaque gates.""" qr = QuantumRegister(1) qc = QuantumCircuit(qr) theta = Parameter("theta") qc.append(U1Gate(0.3), [qr]) qc.append(U1Gate(0.4), [qr]) qc.append(U1Gate(theta), [qr]) qc.append(U1Gate(0.1), [qr]) qc.append(U1Gate(0.2), [qr]) dag = circuit_to_dag(qc) expected = QuantumCircuit(qr) expected.append(U1Gate(theta + 1.0), [qr]) after = Optimize1qGates().run(dag) self.assertEqual(circuit_to_dag(expected), after)
def test_matrix_op_parameterized_evolution(self): """ parameterized MatrixOp evolution test """ theta = Parameter('θ') op = (-1.052373245772859 * I ^ I) + \ (0.39793742484318045 * I ^ Z) + \ (0.18093119978423156 * X ^ X) + \ (-0.39793742484318045 * Z ^ I) + \ (-0.01128010425623538 * Z ^ Z) op = op * theta wf = (op.to_matrix_op().exp_i()) @ CX @ (H ^ I) @ Zero self.assertIn(theta, wf.to_circuit().parameters) op = op.assign_parameters({theta: 1}) exp_mat = op.to_matrix_op().exp_i().to_matrix() ref_mat = scipy.linalg.expm(-1j * op.to_matrix()) np.testing.assert_array_almost_equal(ref_mat, exp_mat) wf = wf.assign_parameters({theta: 3}) self.assertNotIn(theta, wf.to_circuit().parameters)
def test_repeated_gates_to_dag_and_back(self): """Verify circuits with repeated parameterized gates can be converted to DAG and back, maintaining consistency of circuit._parameter_table.""" from qiskit.converters import circuit_to_dag, dag_to_circuit qr = QuantumRegister(1) qc = QuantumCircuit(qr) theta = Parameter('theta') qc.u1(theta, qr[0]) double_qc = qc + qc test_qc = dag_to_circuit(circuit_to_dag(double_qc)) for assign_fun in ['bind_parameters', 'assign_parameters']: with self.subTest(assign_fun=assign_fun): bound_test_qc = getattr(test_qc, assign_fun)({theta: 1}) self.assertEqual(len(bound_test_qc.parameters), 0)
def test_gradient_rzx(self, method): """Test the state gradient for ZX rotation """ ham = Z ^ Z a = Parameter('a') q = QuantumRegister(2) qc = QuantumCircuit(q) qc.h(q) qc.rzx(a, q[0], q[1]) op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.) params = [a] state_grad = Gradient(grad_method=method).convert(operator=op, params=params) values_dict = [{a: np.pi / 8}, {a: np.pi / 2}] correct_values = [[0.], [0.]] for i, value_dict in enumerate(values_dict): np.testing.assert_array_almost_equal(state_grad.assign_parameters(value_dict).eval(), correct_values[i], decimal=1)
def test_quantum_circuit_by_passing_parameters(self, recorder): """Tests the load method for a QuantumCircuit initialized by passing the number of registers required.""" theta = Parameter("θ") angle = 0.5 qc = QuantumCircuit(3, 1) qc.rz(theta, [0]) quantum_circuit = load(qc) with recorder: quantum_circuit(params={theta: angle}) assert len(recorder.queue) == 1 assert recorder.queue[0].name == "RZ" assert recorder.queue[0].parameters == [angle] assert recorder.queue[0].wires == Wires([0])
def test_simple_unroll_parameterized_without_expressions(self): """Verify unrolling parameterized gates without expressions.""" qr = QuantumRegister(1) qc = QuantumCircuit(qr) theta = Parameter('theta') qc.rz(theta, qr[0]) dag = circuit_to_dag(qc) pass_ = UnrollCustomDefinitions(std_eqlib, ['u1', 'cx']) dag = pass_.run(dag) unrolled_dag = BasisTranslator(std_eqlib, ['u1', 'cx']).run(dag) expected = QuantumCircuit(qr, global_phase=-theta / 2) expected.append(U1Gate(theta), [qr[0]]) self.assertEqual(circuit_to_dag(expected), unrolled_dag)
def test_single_parameterized_circuit(self, basis): """Parameters should be treated as opaque gates.""" qr = QuantumRegister(1) qc = QuantumCircuit(qr) theta = Parameter("theta") qc.p(0.3, qr) qc.p(0.4, qr) qc.p(theta, qr) qc.p(0.1, qr) qc.p(0.2, qr) passmanager = PassManager() passmanager.append(BasisTranslator(sel, basis)) passmanager.append(Optimize1qGatesDecomposition(basis)) result = passmanager.run(qc) self.assertTrue( Operator(qc.bind_parameters({theta: 3.14})).equiv( Operator(result.bind_parameters({theta: 3.14}))))
def test_qfi_overlap_works_with_bound_parameters(self): """Test all QFI methods work if the circuit contains a gate with bound parameters.""" x = Parameter("x") circuit = QuantumCircuit(1) circuit.ry(np.pi / 4, 0) circuit.rx(x, 0) state = StateFn(circuit) methods = ["lin_comb_full", "overlap_diag", "overlap_block_diag"] reference = 0.5 for method in methods: with self.subTest(method): qfi = QFI(method) value = np.real( qfi.convert(state, [x]).bind_parameters({ x: 0.12 }).eval()) self.assertAlmostEqual(value[0][0], reference)
def test_assign_parameter_to_subroutine(self): """Test that assign parameter objects to subroutines.""" param1 = Parameter('amp') waveform = pulse.library.Constant(duration=100, amp=param1) program_layer0 = pulse.Schedule() program_layer0 += pulse.Play(waveform, DriveChannel(0)) reference = deepcopy(program_layer0).assign_parameters({param1: 0.1}) # to call instruction program_layer1 = pulse.Schedule() program_layer1 += pulse.instructions.Call(program_layer0) target = deepcopy(program_layer1).assign_parameters({param1: 0.1}) self.assertEqual(inline_subroutines(target), reference) # to nested call instruction program_layer2 = pulse.Schedule() program_layer2 += pulse.instructions.Call(program_layer1) target = deepcopy(program_layer2).assign_parameters({param1: 0.1}) self.assertEqual(inline_subroutines(target), reference)
def test_schedule_block_in_instmap(self): """Test schedule block in instmap can be scheduled.""" duration = Parameter("duration") with build() as pulse_prog: play(Gaussian(duration, 0.1, 10), DriveChannel(0)) instmap = InstructionScheduleMap() instmap.add("block_gate", (0, ), pulse_prog, ["duration"]) qc = QuantumCircuit(1) qc.append(Gate("block_gate", 1, [duration]), [0]) qc.assign_parameters({duration: 100}, inplace=True) sched = schedule(qc, self.backend, inst_map=instmap) ref_sched = Schedule() ref_sched += Play(Gaussian(100, 0.1, 10), DriveChannel(0)) self.assertEqual(sched, ref_sched)
def test_gradient_rzz(self, method): # pylint: disable=wrong-spelling-in-comment """Test the state gradient for ZZ rotation """ ham = Z ^ X a = Parameter('a') q = QuantumRegister(2) qc = QuantumCircuit(q) qc.h(q[0]) qc.rzz(a, q[0], q[1]) op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.) params = [a] state_grad = Gradient(grad_method=method).convert(operator=op, params=params) values_dict = [{a: np.pi / 4}, {a: np.pi / 2}] correct_values = [[-0.707], [-1.]] for i, value_dict in enumerate(values_dict): np.testing.assert_array_almost_equal(state_grad.assign_parameters(value_dict).eval(), correct_values[i], decimal=1)
def test_1q_hamiltonian(self): """test 1 qubit hamiltonian""" qr = QuantumRegister(1, 'q0') cr = ClassicalRegister(1, 'c0') qc = QuantumCircuit(qr, cr) matrix = np.zeros((2, 2)) qc.x(qr[0]) theta = Parameter('theta') qc.append(HamiltonianGate(matrix, theta), [qr[0]]) qc = qc.bind_parameters({theta: 1}) # test of text drawer self.log.info(qc) dag = circuit_to_dag(qc) dag_nodes = dag.named_nodes('hamiltonian') self.assertTrue(len(dag_nodes) == 1) dnode = dag_nodes[0] self.assertIsInstance(dnode.op, HamiltonianGate) self.assertListEqual(dnode.qargs, qc.qubits) assert_allclose(dnode.op.to_matrix(), np.eye(2))
def test_qaoa_qc_mixer_many_parameters(self): """QAOA test with a mixer as a parameterized circuit with the num of parameters > 1.""" optimizer = COBYLA() qubit_op, _ = self._get_operator(W1) num_qubits = qubit_op.num_qubits mixer = QuantumCircuit(num_qubits) for i in range(num_qubits): theta = Parameter("θ" + str(i)) mixer.rx(theta, range(num_qubits)) qaoa = QAOA(optimizer, reps=2, mixer=mixer, quantum_instance=self.statevector_simulator) result = qaoa.compute_minimum_eigenvalue(operator=qubit_op) x = self._sample_most_likely(result.eigenstate) self.log.debug(x) graph_solution = self._get_graph_solution(x) self.assertIn(graph_solution, S1)
def test_3q_hamiltonian(self): """test 3 qubit hamiltonian on non-consecutive bits""" qr = QuantumRegister(4) qc = QuantumCircuit(qr) qc.x(qr[0]) matrix = Operator.from_label("XZY") theta = Parameter("theta") uni3q = HamiltonianGate(matrix, theta) qc.append(uni3q, [qr[0], qr[1], qr[3]]) qc.cx(qr[3], qr[2]) # test of text drawer self.log.info(qc) qc = qc.bind_parameters({theta: -np.pi / 2}) dag = circuit_to_dag(qc) nodes = dag.multi_qubit_ops() self.assertEqual(len(nodes), 1) dnode = nodes[0] self.assertIsInstance(dnode.op, HamiltonianGate) self.assertEqual(dnode.qargs, [qr[0], qr[1], qr[3]]) np.testing.assert_almost_equal(dnode.op.to_matrix(), 1j * matrix.data)