4
$\begingroup$

I have a quantum circuit with 3 two-qubits gates XX, YY, and ZZ (as defined in the qiskit circuit library) with arbitrary angles on each gate. I'd like to replace the YY and ZZ gates with XXs. I know how to do this mathematically with RZ and RY single qubit rotations, but I don't know how to programmically get Qiskit to do this switch. Unfortunately, the transpiler converts the YY and ZZ into CNOTs and then into XXs (evaluated at $\pi/2$). I want to avoid this though and preserve the arbitrary angles on YY and ZZ when converting them into XX gates. Is there a way I can tell the transpiler how to handle YY and ZZ gates?

Or maybe remove the YY and ZZ gates from the quantum circuit from QuantumCircuit.data and insert XX gates (with the appropriate RZ and RY rotations)?

$\endgroup$

1 Answer 1

5
$\begingroup$

The proper way to implement this would be writing your own transpiler pass, a TransformationPass to be more precise, which replaces the RYY and RZZ gates with your decomposition. If you want to decompose it into RXX gates the following should do the trick:

from qiskit.circuit import QuantumCircuit
from qiskit.converters import circuit_to_dag
from qiskit.transpiler import TransformationPass

class RXXTranslator(TransformationPass):
    """A transpiler pass to replace RYY and RZZ gates with RXX gates."""

    def run(self, dag):
        """Run the pass."""

        # iterate over all operations
        for node in dag.op_nodes():

            # if we hit a RYY or RZZ gate replace it
            if node.op.name in ["ryy", "rzz"]:
                # get the rotation angle
                angle = node.op.params[0]

                # calculate the replacement
                replacement = QuantumCircuit(2)
                if node.op.name == "ryy":
                    replacement.sdg([0, 1])
                else:
                    replacement.h([0, 1])

                replacement.rxx(angle, 0, 1)

                if node.op.name == "ryy":
                    replacement.s([0, 1])
                else:
                    replacement.h([0, 1])

                # replace the node with our new decomposition
                dag.substitute_node_with_dag(node, circuit_to_dag(replacement))

        return dag


circuit = QuantumCircuit(2)
circuit.rxx(0.1, 0, 1)
circuit.ryy(0.2, 0, 1)
circuit.rzz(0.3, 0, 1)

as_rxx = RXXTranslator()(circuit)
print(as_rxx.draw())

which outputs

     ┌───────────┐┌─────┐┌───────────┐┌───┐┌───┐┌───────────┐┌───┐
q_0: ┤0          ├┤ Sdg ├┤0          ├┤ S ├┤ H ├┤0          ├┤ H ├
     │  Rxx(0.1) │├─────┤│  Rxx(0.2) │├───┤├───┤│  Rxx(0.3) │├───┤
q_1: ┤1          ├┤ Sdg ├┤1          ├┤ S ├┤ H ├┤1          ├┤ H ├
     └───────────┘└─────┘└───────────┘└───┘└───┘└───────────┘└───┘
$\endgroup$
1
  • $\begingroup$ Wow! Thank you so much! I haven't seen examples of making custom transpiler passes before. This works great! $\endgroup$ Commented Dec 1, 2021 at 16:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.