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

Single-qubit and Controlled Z rotations #1455

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
5 changes: 4 additions & 1 deletion dev_tools/qualtran_dev_tools/notebook_specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -590,9 +590,12 @@
title='Basic Rotation Gates',
module=qualtran.bloqs.basic_gates.rotation,
bloq_specs=[
qualtran.bloqs.basic_gates.rotation._Z_POW_DOC,
qualtran.bloqs.basic_gates.rotation._CZ_POW_DOC,
qualtran.bloqs.basic_gates.rotation._RZ_DOC,
qualtran.bloqs.basic_gates.rotation._CRZ_DOC,
qualtran.bloqs.basic_gates.rotation._X_POW_DOC,
qualtran.bloqs.basic_gates.rotation._Y_POW_DOC,
qualtran.bloqs.basic_gates.rotation._Z_POW_DOC,
],
),
NotebookSpecV2(
Expand Down
2 changes: 1 addition & 1 deletion qualtran/bloqs/basic_gates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from .identity import Identity
from .on_each import OnEach
from .power import Power
from .rotation import CZPowGate, Rx, Ry, Rz, XPowGate, YPowGate, ZPowGate
from .rotation import CRz, CZPowGate, Rx, Ry, Rz, XPowGate, YPowGate, ZPowGate
from .s_gate import SGate
from .su2_rotation import SU2RotationGate
from .swap import CSwap, Swap, TwoBitCSwap, TwoBitSwap
Expand Down
45 changes: 13 additions & 32 deletions qualtran/bloqs/basic_gates/global_phase.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,22 @@
"## `GlobalPhase`\n",
"Applies a global phase to the circuit as a whole.\n",
"\n",
"The unitary effect is to multiply the state vector by the complex scalar\n",
"$e^{i pi t}$ for `exponent` $t$.\n",
"For an exponent $t$, the unitary effect is to multiply the state vector by the complex scalar\n",
"$$\n",
"(-1)^t = e^{i \\pi t}\n",
"$$\n",
"\n",
"The global phase of a state or circuit does not affect any observable quantity, but\n",
"keeping track of it can be a useful bookkeeping mechanism for testing circuit identities.\n",
"The global phase becomes important if the gate becomes controlled.\n",
"keeping track of it can be a useful bookkeeping mechanism for testing circuit identities, and\n",
"the global phase becomes important when controlling an operation.\n",
"\n",
"This is fundamentally an atomic operation and this bloq has no decomposition in Qualtran.\n",
"\n",
"The single-qubit controlled version of `GlobalPhase` is `ZPowGate`.\n",
"\n",
"#### Parameters\n",
" - `exponent`: the exponent $t$ of the global phase $e^{i pi t}$ to apply.\n",
" - `eps`: precision\n"
" - `exponent`: the exponent t of the global phase (-1)^t to apply.\n",
" - `eps`: The precision of the rotation. This parameter is for bookkeeping and does not affect e.g. the tensor representation of this gate.\n"
]
},
{
Expand Down Expand Up @@ -108,31 +114,6 @@
" ['`global_phase`'])"
]
},
{
"cell_type": "markdown",
"id": "facc4a57",
"metadata": {
"cq.autogen": "GlobalPhase.call_graph.md"
},
"source": [
"### Call Graph"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "94dfefb2",
"metadata": {
"cq.autogen": "GlobalPhase.call_graph.py"
},
"outputs": [],
"source": [
"from qualtran.resource_counting.generalizers import ignore_split_join\n",
"global_phase_g, global_phase_sigma = global_phase.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
"show_call_graph(global_phase_g)\n",
"show_counts_sigma(global_phase_sigma)"
]
},
{
"cell_type": "markdown",
"id": "c183275c-cc9c-477d-888c-d8b850f67a2e",
Expand All @@ -158,7 +139,7 @@
"id": "b737b871-9c61-4d54-860a-d9928f18808b",
"metadata": {},
"source": [
"When a global phase is controlled, it is equivalent to a ZPowGate"
"When a global phase is controlled, it is equivalent to a `ZPowGate`"
]
},
{
Expand Down
40 changes: 23 additions & 17 deletions qualtran/bloqs/basic_gates/global_phase.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import attrs
import cirq
from attrs import field, frozen
from attrs import frozen

from qualtran import (
AddControlledT,
Expand All @@ -30,31 +30,37 @@
DecomposeTypeError,
SoquetT,
)
from qualtran.bloqs.basic_gates.rotation import ZPowGate
from qualtran.cirq_interop import CirqGateAsBloqBase
from qualtran.symbolics import pi, sarg, sexp, SymbolicComplex, SymbolicFloat

if TYPE_CHECKING:
import quimb.tensor as qtn


@frozen
@frozen(kw_only=True)
class GlobalPhase(CirqGateAsBloqBase):
r"""Applies a global phase to the circuit as a whole.

The unitary effect is to multiply the state vector by the complex scalar
$e^{i pi t}$ for `exponent` $t$.
For an exponent $t$, the unitary effect is to multiply the state vector by the complex scalar
$$
(-1)^t = e^{i \pi t}
$$

The global phase of a state or circuit does not affect any observable quantity, but
keeping track of it can be a useful bookkeeping mechanism for testing circuit identities.
The global phase becomes important if the gate becomes controlled.
keeping track of it can be a useful bookkeeping mechanism for testing circuit identities, and
the global phase becomes important when controlling an operation.

This is fundamentally an atomic operation and this bloq has no decomposition in Qualtran.

The single-qubit controlled version of `GlobalPhase` is `ZPowGate`.

Args:
exponent: the exponent $t$ of the global phase $e^{i pi t}$ to apply.
eps: precision
exponent: the exponent t of the global phase (-1)^t to apply.
eps: The precision of the rotation. This parameter is for bookkeeping and does
not affect e.g. the tensor representation of this gate.
"""

exponent: SymbolicFloat = field(kw_only=True)
exponent: SymbolicFloat
eps: SymbolicFloat = 1e-11

@cached_property
Expand Down Expand Up @@ -87,14 +93,12 @@ def my_tensors(

def get_ctrl_system(self, ctrl_spec: 'CtrlSpec') -> Tuple['Bloq', 'AddControlledT']:
# Delegate to superclass logic for more than one control.
if not (ctrl_spec == CtrlSpec() or ctrl_spec == CtrlSpec(cvs=0)):
if ctrl_spec != CtrlSpec():
return super().get_ctrl_system(ctrl_spec=ctrl_spec)

# Otherwise, it's a ZPowGate
if ctrl_spec == CtrlSpec(cvs=0):
bloq = ZPowGate(exponent=-self.exponent, global_shift=-1, eps=self.eps)
else:
bloq = ZPowGate(exponent=self.exponent, eps=self.eps)
from qualtran.bloqs.basic_gates import ZPowGate

bloq = ZPowGate(exponent=self.exponent, eps=self.eps)

def _add_ctrled(
bb: 'BloqBuilder', ctrl_soqs: Sequence['SoquetT'], in_soqs: Dict[str, 'SoquetT']
Expand All @@ -115,4 +119,6 @@ def _global_phase() -> GlobalPhase:
return global_phase


_GLOBAL_PHASE_DOC = BloqDocSpec(bloq_cls=GlobalPhase, examples=[_global_phase])
_GLOBAL_PHASE_DOC = BloqDocSpec(
bloq_cls=GlobalPhase, examples=[_global_phase], call_graph_example=None
)
Loading
Loading