Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add equivalence-library rules between rzz and cp #13019

Merged
merged 2 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
17 changes: 17 additions & 0 deletions releasenotes/notes/cphase-rzz-equivalence-e8afc37b71a74366.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
features_circuits:
- |
The standard equivalence library (:data:`.SessionEquivalenceLibrary`) now has rules that can
directly convert between Qiskit's standard-library 2q continuous Ising-type interactions (e.g.
:class:`.CPhaseGate`, :class:`.RZZGate`, :class:`.RZXGate`, and so on) using local equivalence
relations. Previously, several of these conversions would go via a 2-CX form, which resulted
in less efficient circuit generation.

.. note::

In general, the :class:`.BasisTranslator` is not guaranteed to find the "best" equivalence
relation for a given :class:`.Target`, but will always find an equivalence if one exists. We
rely on more expensive resynthesis and gate-optimization passes in the transpiler to improve
the output. These passes are currently not as effective for basis sets with a continuously
parametrized two-qubit interaction as they are for discrete super-controlled two-qubit
interactions.
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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did you need to remove this test?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test is asserting that a failure occurs, and for most of the gates in the list, they shouldn't really fail - we've got enough equivalence and translation rules that it should be possible to translate the gate into one we can represent better. The add_control logic is just not super smart about gate translation.

As a side effect of this PR, the RZ path now happens to convert things to CPhaseGate rather than CRZGate (or something like that), so the control works further than it did before.

RXXGate,
RYYGate,
RZXGate,
Expand Down
Loading