Skip to content

Commit

Permalink
Add equivalence-library rules between rzz and cp
Browse files Browse the repository at this point in the history
These gates are locally equivalence (as are all the Ising-interaction
gates), and this simple additional rule lets things like QFT, which are
defined by Qiskit's default constructor in terms of `cp`, get converted
into `rzz` or `rzx`.

One `ControlledGate` test needed a case removing, because the underlying
control mechanism now works correctly.
  • Loading branch information
jakelishman committed Aug 25, 2024
1 parent d3040a0 commit 9a2add5
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 1 deletion.
43 changes: 43 additions & 0 deletions qiskit/circuit/library/standard_gates/equivalence_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,21 @@ def _cnot_rxx_decompose(plus_ry: bool = True, plus_rxx: bool = True):
cphase_to_cu1.append(CU1Gate(theta), [0, 1])
_sel.add_equivalence(CPhaseGate(theta), cphase_to_cu1)

# CPhaseGate
#
# global phase: ϴ/4
# ┌─────────┐
# q_0: ─■──── q_0: ─■─────────┤ Rz(ϴ/2) ├
# │P(ϴ) ≡ │ZZ(-ϴ/2) ├─────────┤
# q_1: ─■──── q_1: ─■─────────┤ Rz(ϴ/2) ├
# └─────────┘
theta = Parameter("theta")
cphase_to_rzz = QuantumCircuit(2, global_phase=theta / 4)
cphase_to_rzz.rzz(-theta / 2, 0, 1)
cphase_to_rzz.rz(theta / 2, 0)
cphase_to_rzz.rz(theta / 2, 1)
_sel.add_equivalence(CPhaseGate(theta), cphase_to_rzz)

# RGate
#
# ┌────────┐ ┌───────────────────────┐
Expand Down Expand Up @@ -394,6 +409,19 @@ def _cnot_rxx_decompose(plus_ry: bool = True, plus_rxx: bool = True):
def_rzx.append(inst, qargs, cargs)
_sel.add_equivalence(RZXGate(theta), def_rzx)

# RZXGate to RZZGate
# ┌─────────┐
# q_0: ┤0 ├ q_0: ──────■───────────
# │ Rzx(ϴ) │ ≡ ┌───┐ │ZZ(ϴ) ┌───┐
# q_1: ┤1 ├ q_1: ┤ H ├─■──────┤ H ├
# └─────────┘ └───┘ └───┘
theta = Parameter("theta")
rzx_to_rzz = QuantumCircuit(2)
rzx_to_rzz.h(1)
rzx_to_rzz.rzz(theta, 0, 1)
rzx_to_rzz.h(1)
_sel.add_equivalence(RZXGate(theta), rzx_to_rzz)


# RYGate
#
Expand Down Expand Up @@ -654,6 +682,21 @@ def _cnot_rxx_decompose(plus_ry: bool = True, plus_rxx: bool = True):
rzz_to_rzx.h(1)
_sel.add_equivalence(RZZGate(theta), rzz_to_rzx)

# RZZ to CPhase
#
# global phase: ϴ/2
# ┌───────┐
# q_0: ─■───── q_0: ─■────────┤ Rz(ϴ) ├
# │ZZ(ϴ) ≡ │P(-2*ϴ) ├───────┤
# q_1: ─■───── q_1: ─■────────┤ Rz(ϴ) ├
# └───────┘
theta = Parameter("theta")
rzz_to_cphase = QuantumCircuit(2, global_phase=theta / 2)
rzz_to_cphase.cp(-theta * 2, 0, 1)
rzz_to_cphase.rz(theta, 0)
rzz_to_cphase.rz(theta, 1)
_sel.add_equivalence(RZZGate(theta), rzz_to_cphase)

# RZZ to RYY
q = QuantumRegister(2, "q")
theta = Parameter("theta")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
features_circuits:
- |
New equivalence rules in the standard equivalence library mean that the transpiler can now
directly convert between two-qubit continuous Pauli rotations, rather than always decomposing
into a discrete two-CX-based solution.
1 change: 0 additions & 1 deletion test/python/circuit/test_controlled_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -1438,7 +1438,6 @@ def test_control_zero_operand_gate(self, num_ctrl_qubits):
@data(
RXGate,
RYGate,
RZGate,
RXXGate,
RYYGate,
RZXGate,
Expand Down

0 comments on commit 9a2add5

Please sign in to comment.