From aaaf10760d7a9f88c5043cb1d0f2a6035c2b3ab3 Mon Sep 17 00:00:00 2001 From: ewinston Date: Wed, 24 Jul 2024 16:15:13 -0400 Subject: [PATCH] fix issue/12311 with fractional gate in basis (#12511) * linting * linting...relax check for 3-qubit circuit * update test docstrings * black update * bind RZZ to pi/2 if Rzz(theta) in basis * Apply suggestions from code review --------- Co-authored-by: Matthew Treinish --- .../passes/synthesis/unitary_synthesis.py | 3 ++ .../transpiler/test_basis_translator.py | 50 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/qiskit/transpiler/passes/synthesis/unitary_synthesis.py b/qiskit/transpiler/passes/synthesis/unitary_synthesis.py index c0333099dc73..1ce2f2800c09 100644 --- a/qiskit/transpiler/passes/synthesis/unitary_synthesis.py +++ b/qiskit/transpiler/passes/synthesis/unitary_synthesis.py @@ -37,6 +37,7 @@ CZGate, RXXGate, RZXGate, + RZZGate, ECRGate, RXGate, SXGate, @@ -781,6 +782,8 @@ def _replace_parameterized_gate(op): op = RXXGate(pi / 2) elif isinstance(op, RZXGate) and isinstance(op.params[0], Parameter): op = RZXGate(pi / 4) + elif isinstance(op, RZZGate) and isinstance(op.params[0], Parameter): + op = RZZGate(pi / 2) return op try: diff --git a/test/python/transpiler/test_basis_translator.py b/test/python/transpiler/test_basis_translator.py index fc933cd8f666..e1c8063a4575 100644 --- a/test/python/transpiler/test_basis_translator.py +++ b/test/python/transpiler/test_basis_translator.py @@ -16,6 +16,7 @@ import os from numpy import pi +import scipy from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit from qiskit import transpile @@ -33,13 +34,17 @@ XGate, SXGate, CXGate, + RXGate, + RZZGate, ) from qiskit.converters import circuit_to_dag, dag_to_circuit, circuit_to_instruction from qiskit.exceptions import QiskitError +from qiskit.providers.fake_provider import GenericBackendV2 from qiskit.quantum_info import Operator from qiskit.transpiler.target import Target, InstructionProperties from qiskit.transpiler.exceptions import TranspilerError from qiskit.transpiler.passes.basis import BasisTranslator, UnrollCustomDefinitions +from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager from qiskit.circuit.library.standard_gates.equivalence_library import ( StandardEquivalenceLibrary as std_eqlib, ) @@ -1223,3 +1228,48 @@ def __init__(self): out = BasisTranslator(eq_lib, {"my_h", "my_cx"}, target)(qc) self.assertEqual(out, expected) + + def test_fractional_gate_in_basis_from_string(self): + """Test transpiling with RZZ in basis with only basis_gates option.""" + num_qubits = 2 + seed = 9169 + basis_gates = ["rz", "rx", "rzz"] + qc = QuantumCircuit(num_qubits) + mat = scipy.stats.unitary_group.rvs(2**num_qubits, random_state=seed) + qc.unitary(mat, range(num_qubits)) + pm = generate_preset_pass_manager( + optimization_level=1, basis_gates=basis_gates, seed_transpiler=134 + ) + cqc = pm.run(qc) + self.assertEqual(Operator(qc), Operator(cqc)) + + def test_fractional_gate_in_basis_from_backendv2(self): + """Test transpiling with RZZ in basis of backendv2.""" + num_qubits = 2 + seed = 9169 + basis_gates = ["rz", "rx", "rzz"] + qc = QuantumCircuit(num_qubits) + mat = scipy.stats.unitary_group.rvs(2**num_qubits, random_state=seed) + qc.unitary(mat, range(num_qubits)) + backend = GenericBackendV2(num_qubits, basis_gates=basis_gates) + target = backend.target + pm = generate_preset_pass_manager(optimization_level=1, target=target, seed_transpiler=134) + cqc = pm.run(qc) + self.assertEqual(Operator(qc), Operator.from_circuit(cqc)) + + def test_fractional_gate_in_basis_from_custom_target(self): + """Test transpiling with RZZ in basis of custom target.""" + num_qubits = 2 + seed = 9169 + qc = QuantumCircuit(num_qubits) + mat = scipy.stats.unitary_group.rvs(2**num_qubits, random_state=seed) + qc.unitary(mat, range(num_qubits)) + target = Target() + target.add_instruction(RZGate(self.theta), {(i,): None for i in range(qc.num_qubits)}) + target.add_instruction(RXGate(self.phi), {(i,): None for i in range(qc.num_qubits)}) + target.add_instruction( + RZZGate(self.lam), {(i, i + 1): None for i in range(qc.num_qubits - 1)} + ) + pm = generate_preset_pass_manager(optimization_level=1, target=target, seed_transpiler=134) + cqc = pm.run(qc) + self.assertEqual(Operator(qc), Operator.from_circuit(cqc))