def test_rb_experiment(self, qubits: list): """ Initializes data and executes an RB experiment with specific parameters. Args: qubits (list): A list containing qubit indices for the experiment """ backend = AerSimulator.from_backend(FakeParis()) exp_attributes = { "physical_qubits": qubits, "lengths": [1, 4, 6, 9, 13, 16], "num_samples": 3, "seed": 100, } rb_exp = StandardRB( exp_attributes["physical_qubits"], exp_attributes["lengths"], num_samples=exp_attributes["num_samples"], seed=exp_attributes["seed"], ) exp_data = rb_exp.run(backend) exp = exp_data.experiment exp_circuits = rb_exp.circuits() self.validate_metadata(exp_circuits, exp_attributes) self.validate_circuit_data(exp, exp_attributes) self.is_identity(exp_circuits)
def test_interleaved_rb_experiment(self, interleaved_element: "Gate", qubits: list): """ Initializes data and executes an interleaved RB experiment with specific parameters. Args: interleaved_element: The Clifford element to interleave qubits (list): A list containing qubit indices for the experiment """ backend = AerSimulator.from_backend(FakeParis()) exp_attributes = { "interleaved_element": interleaved_element, "physical_qubits": qubits, "lengths": [1, 4, 6, 9, 13, 16], "num_samples": 3, "seed": 100, } rb_exp = InterleavedRB( exp_attributes["interleaved_element"], exp_attributes["physical_qubits"], exp_attributes["lengths"], num_samples=exp_attributes["num_samples"], seed=exp_attributes["seed"], ) experiment_obj = rb_exp.run(backend) exp_data = experiment_obj.experiment exp_circuits = rb_exp.circuits() self.validate_metadata(exp_circuits, exp_attributes) self.validate_circuit_data(exp_data, exp_attributes) self.is_identity(exp_circuits)
def test_json_serialization(self): """Verifies that mitigators can be serialized for DB storage""" qubits = [0, 1] backend = AerSimulator.from_backend(FakeParis()) exp = LocalReadoutError(qubits) exp_data = exp.run(backend).block_for_results() mitigator = exp_data.analysis_results(0).value serialized = json.dumps(mitigator, cls=ExperimentEncoder) loaded = json.loads(serialized, cls=ExperimentDecoder) self.assertTrue( matrix_equal(mitigator.assignment_matrix(), loaded.assignment_matrix()))
def test_parallel_running(self): """Test that parallel experiments work for this experiment""" backend = AerSimulator.from_backend(FakeParis()) exp1 = CorrelatedReadoutError([0, 2]) exp2 = CorrelatedReadoutError([1, 3]) exp = ParallelExperiment([exp1, exp2]) expdata = exp.run(backend=backend).block_for_results() mit1 = expdata.child_data(0).analysis_results(0).value mit2 = expdata.child_data(1).analysis_results(0).value assignment_matrix1 = mit1.assignment_matrix() assignment_matrix2 = mit2.assignment_matrix() self.assertFalse(matrix_equal(assignment_matrix1, assignment_matrix2))
def test_database_save_and_load(self): """Tests saving and loading the mitigator from the DB""" qubits = [0, 1] backend = AerSimulator.from_backend(FakeParis()) exp = LocalReadoutError(qubits) exp_data = exp.run(backend).block_for_results() exp_data.service = FakeService() exp_data.save() loaded_data = ExperimentData.load(exp_data.experiment_id, exp_data.service) exp_res = exp_data.analysis_results() load_res = loaded_data.analysis_results() exp_matrix = exp_res[0].value.assignment_matrix() load_matrix = load_res[0].value.assignment_matrix() self.assertTrue(matrix_equal(exp_matrix, load_matrix))
def setUp(self): super().setUp() self.backend = FakeParis()
def setUp(self): super().setUp() self.backend = FakeParis() self.inst_map = self.backend.defaults().instruction_schedule_map
class TestEchoRZXWeylDecomposition(QiskitTestCase): """Tests the EchoRZXWeylDecomposition pass.""" def setUp(self): super().setUp() self.backend = FakeParis() self.inst_map = self.backend.defaults().instruction_schedule_map def assertRZXgates(self, unitary_circuit, after): """Check the number of rzx gates""" alpha = TwoQubitWeylDecomposition(unitary_circuit).a beta = TwoQubitWeylDecomposition(unitary_circuit).b gamma = TwoQubitWeylDecomposition(unitary_circuit).c expected_rzx_number = 0 if not alpha == 0: expected_rzx_number += 2 if not beta == 0: expected_rzx_number += 2 if not gamma == 0: expected_rzx_number += 2 circuit_rzx_number = QuantumCircuit.count_ops(after)["rzx"] self.assertEqual(expected_rzx_number, circuit_rzx_number) @staticmethod def count_gate_number(gate, circuit): """Count the number of a specific gate type in a circuit""" if gate not in QuantumCircuit.count_ops(circuit): gate_number = 0 else: gate_number = QuantumCircuit.count_ops(circuit)[gate] return gate_number def test_rzx_number_native_weyl_decomposition(self): """Check the number of RZX gates for a hardware-native cx""" qr = QuantumRegister(2, "qr") circuit = QuantumCircuit(qr) circuit.cx(qr[0], qr[1]) unitary_circuit = qi.Operator(circuit).data after = EchoRZXWeylDecomposition(self.inst_map)(circuit) unitary_after = qi.Operator(after).data self.assertTrue(np.allclose(unitary_circuit, unitary_after)) # check whether the after circuit has the correct number of rzx gates. self.assertRZXgates(unitary_circuit, after) def test_h_number_non_native_weyl_decomposition_1(self): """Check the number of added Hadamard gates for a native and non-native rzz gate""" theta = pi / 11 qr = QuantumRegister(2, "qr") # rzz gate in native direction circuit = QuantumCircuit(qr) circuit.rzz(theta, qr[0], qr[1]) # rzz gate in non-native direction circuit_non_native = QuantumCircuit(qr) circuit_non_native.rzz(theta, qr[1], qr[0]) dag = circuit_to_dag(circuit) pass_ = EchoRZXWeylDecomposition(self.inst_map) after = dag_to_circuit(pass_.run(dag)) dag_non_native = circuit_to_dag(circuit_non_native) pass_ = EchoRZXWeylDecomposition(self.inst_map) after_non_native = dag_to_circuit(pass_.run(dag_non_native)) circuit_rzx_number = self.count_gate_number("rzx", after) circuit_h_number = self.count_gate_number("h", after) circuit_non_native_h_number = self.count_gate_number( "h", after_non_native) # for each pair of rzx gates four hadamard gates have to be added in # the case of a non-hardware-native directed gate. self.assertEqual((circuit_rzx_number / 2) * 4, circuit_non_native_h_number - circuit_h_number) def test_h_number_non_native_weyl_decomposition_2(self): """Check the number of added Hadamard gates for a swap gate""" qr = QuantumRegister(2, "qr") # swap gate in native direction. circuit = QuantumCircuit(qr) circuit.swap(qr[0], qr[1]) # swap gate in non-native direction. circuit_non_native = QuantumCircuit(qr) circuit_non_native.swap(qr[1], qr[0]) dag = circuit_to_dag(circuit) pass_ = EchoRZXWeylDecomposition(self.inst_map) after = dag_to_circuit(pass_.run(dag)) dag_non_native = circuit_to_dag(circuit_non_native) pass_ = EchoRZXWeylDecomposition(self.inst_map) after_non_native = dag_to_circuit(pass_.run(dag_non_native)) circuit_rzx_number = self.count_gate_number("rzx", after) circuit_h_number = self.count_gate_number("h", after) circuit_non_native_h_number = self.count_gate_number( "h", after_non_native) # for each pair of rzx gates four hadamard gates have to be added in # the case of a non-hardware-native directed gate. self.assertEqual((circuit_rzx_number / 2) * 4, circuit_non_native_h_number - circuit_h_number) def test_weyl_decomposition_gate_angles(self): """Check the number and angles of the RZX gates for different gates""" thetas = [pi / 9, 2.1, -0.2] qr = QuantumRegister(2, "qr") circuit_rxx = QuantumCircuit(qr) circuit_rxx.rxx(thetas[0], qr[1], qr[0]) circuit_ryy = QuantumCircuit(qr) circuit_ryy.ryy(thetas[1], qr[0], qr[1]) circuit_rzz = QuantumCircuit(qr) circuit_rzz.rzz(thetas[2], qr[1], qr[0]) circuits = [circuit_rxx, circuit_ryy, circuit_rzz] for circuit in circuits: unitary_circuit = qi.Operator(circuit).data dag = circuit_to_dag(circuit) pass_ = EchoRZXWeylDecomposition(self.inst_map) after = dag_to_circuit(pass_.run(dag)) dag_after = circuit_to_dag(after) unitary_after = qi.Operator(after).data # check whether the unitaries are equivalent. self.assertTrue(np.allclose(unitary_circuit, unitary_after)) # check whether the after circuit has the correct number of rzx gates. self.assertRZXgates(unitary_circuit, after) alpha = TwoQubitWeylDecomposition(unitary_circuit).a rzx_angles = [] for node in dag_after.two_qubit_ops(): if node.name == "rzx": rzx_angle = node.op.params[0] # check whether the absolute values of the RZX gate angles # are equivalent to the corresponding Weyl parameter. self.assertAlmostEqual(np.abs(rzx_angle), alpha) rzx_angles.append(rzx_angle) # check whether the angles of every RZX gate pair of an echoed RZX gate # have opposite signs. for idx in range(1, len(rzx_angles), 2): self.assertAlmostEqual(rzx_angles[idx - 1], -rzx_angles[idx]) def test_weyl_unitaries_random_circuit(self): """Weyl decomposition for a random two-qubit circuit.""" theta = pi / 9 epsilon = 5 delta = -1 eta = 0.2 qr = QuantumRegister(2, "qr") circuit = QuantumCircuit(qr) # random two-qubit circuit. circuit.rzx(theta, 0, 1) circuit.rzz(epsilon, 0, 1) circuit.rz(eta, 0) circuit.swap(1, 0) circuit.h(0) circuit.rzz(delta, 1, 0) circuit.swap(0, 1) circuit.cx(1, 0) circuit.swap(0, 1) circuit.h(1) circuit.rxx(theta, 0, 1) circuit.ryy(theta, 1, 0) circuit.ecr(0, 1) unitary_circuit = qi.Operator(circuit).data dag = circuit_to_dag(circuit) pass_ = EchoRZXWeylDecomposition(self.inst_map) after = dag_to_circuit(pass_.run(dag)) unitary_after = qi.Operator(after).data self.assertTrue(np.allclose(unitary_circuit, unitary_after))