Skip to content

Commit 514eba4

Browse files
authored
Add identity bloq (#1002)
* Add identity gate. * Address review comments.
1 parent 8654062 commit 514eba4

7 files changed

Lines changed: 316 additions & 0 deletions

File tree

dev_tools/autogenerate-bloqs-notebooks-v2.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@
175175
module=qualtran.bloqs.basic_gates.global_phase,
176176
bloq_specs=[qualtran.bloqs.basic_gates.global_phase._GLOBAL_PHASE_DOC],
177177
),
178+
NotebookSpecV2(
179+
title='Identity Gate',
180+
module=qualtran.bloqs.basic_gates.identity,
181+
bloq_specs=[qualtran.bloqs.basic_gates.identity._IDENTITY_DOC],
182+
),
178183
]
179184

180185

docs/bloqs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Bloqs Library
3434
basic_gates/states_and_effects.ipynb
3535
swap_network/swap_network.ipynb
3636
basic_gates/global_phase.ipynb
37+
basic_gates/identity.ipynb
3738

3839
.. toctree::
3940
:maxdepth: 2

qualtran/bloqs/basic_gates/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from .cnot import CNOT
2525
from .global_phase import GlobalPhase
2626
from .hadamard import Hadamard
27+
from .identity import Identity
2728
from .on_each import OnEach
2829
from .rotation import CZPowGate, Rx, Ry, Rz, XPowGate, YPowGate, ZPowGate
2930
from .s_gate import SGate
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "92a37b86",
6+
"metadata": {
7+
"cq.autogen": "title_cell"
8+
},
9+
"source": [
10+
"# Identity Gate"
11+
]
12+
},
13+
{
14+
"cell_type": "code",
15+
"execution_count": null,
16+
"id": "c6021f9f",
17+
"metadata": {
18+
"cq.autogen": "top_imports"
19+
},
20+
"outputs": [],
21+
"source": [
22+
"from qualtran import Bloq, CompositeBloq, BloqBuilder, Signature, Register\n",
23+
"from qualtran import QBit, QInt, QUInt, QAny\n",
24+
"from qualtran.drawing import show_bloq, show_call_graph, show_counts_sigma\n",
25+
"from typing import *\n",
26+
"import numpy as np\n",
27+
"import sympy\n",
28+
"import cirq"
29+
]
30+
},
31+
{
32+
"cell_type": "markdown",
33+
"id": "422855fc",
34+
"metadata": {
35+
"cq.autogen": "Identity.bloq_doc.md"
36+
},
37+
"source": [
38+
"## `Identity`\n",
39+
"The identity gate\n",
40+
"\n",
41+
"#### Registers\n",
42+
" - `q`: The qubit\n"
43+
]
44+
},
45+
{
46+
"cell_type": "code",
47+
"execution_count": null,
48+
"id": "ae7e658c",
49+
"metadata": {
50+
"cq.autogen": "Identity.bloq_doc.py"
51+
},
52+
"outputs": [],
53+
"source": [
54+
"from qualtran.bloqs.basic_gates import Identity"
55+
]
56+
},
57+
{
58+
"cell_type": "markdown",
59+
"id": "beb2c934",
60+
"metadata": {
61+
"cq.autogen": "Identity.example_instances.md"
62+
},
63+
"source": [
64+
"### Example Instances"
65+
]
66+
},
67+
{
68+
"cell_type": "code",
69+
"execution_count": null,
70+
"id": "69ab2ac9",
71+
"metadata": {
72+
"cq.autogen": "Identity.identity"
73+
},
74+
"outputs": [],
75+
"source": [
76+
"identity = Identity()"
77+
]
78+
},
79+
{
80+
"cell_type": "markdown",
81+
"id": "7d5b3859",
82+
"metadata": {
83+
"cq.autogen": "Identity.graphical_signature.md"
84+
},
85+
"source": [
86+
"#### Graphical Signature"
87+
]
88+
},
89+
{
90+
"cell_type": "code",
91+
"execution_count": null,
92+
"id": "376ca25a",
93+
"metadata": {
94+
"cq.autogen": "Identity.graphical_signature.py"
95+
},
96+
"outputs": [],
97+
"source": [
98+
"from qualtran.drawing import show_bloqs\n",
99+
"show_bloqs([identity],\n",
100+
" ['`identity`'])"
101+
]
102+
},
103+
{
104+
"cell_type": "markdown",
105+
"id": "5099be1d",
106+
"metadata": {
107+
"cq.autogen": "Identity.call_graph.md"
108+
},
109+
"source": [
110+
"### Call Graph"
111+
]
112+
},
113+
{
114+
"cell_type": "code",
115+
"execution_count": null,
116+
"id": "6d7ccccc",
117+
"metadata": {
118+
"cq.autogen": "Identity.call_graph.py"
119+
},
120+
"outputs": [],
121+
"source": [
122+
"from qualtran.resource_counting.generalizers import ignore_split_join\n",
123+
"identity_g, identity_sigma = identity.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
124+
"show_call_graph(identity_g)\n",
125+
"show_counts_sigma(identity_sigma)"
126+
]
127+
}
128+
],
129+
"metadata": {
130+
"kernelspec": {
131+
"display_name": "Python 3",
132+
"language": "python",
133+
"name": "python3"
134+
},
135+
"language_info": {
136+
"name": "python"
137+
}
138+
},
139+
"nbformat": 4,
140+
"nbformat_minor": 5
141+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from functools import cached_property
16+
from typing import Any, Dict, Optional, Tuple, TYPE_CHECKING
17+
18+
import numpy as np
19+
from attrs import frozen
20+
21+
from qualtran import (
22+
Bloq,
23+
bloq_example,
24+
BloqDocSpec,
25+
CompositeBloq,
26+
DecomposeTypeError,
27+
Register,
28+
Signature,
29+
SoquetT,
30+
)
31+
from qualtran.cirq_interop.t_complexity_protocol import TComplexity
32+
from qualtran.drawing import Text, TextBox, WireSymbol
33+
34+
if TYPE_CHECKING:
35+
import cirq
36+
import quimb.tensor as qtn
37+
38+
from qualtran.cirq_interop import CirqQuregT
39+
from qualtran.simulation.classical_sim import ClassicalValT
40+
41+
42+
@frozen
43+
class Identity(Bloq):
44+
r"""The identity gate on one qubit.
45+
46+
Registers:
47+
q: The qubit
48+
"""
49+
50+
@cached_property
51+
def signature(self) -> 'Signature':
52+
return Signature.build(q=1)
53+
54+
def adjoint(self) -> 'Bloq':
55+
return self
56+
57+
def decompose_bloq(self) -> 'CompositeBloq':
58+
raise DecomposeTypeError(f"{self} is atomic")
59+
60+
def add_my_tensors(
61+
self,
62+
tn: 'qtn.TensorNetwork',
63+
tag: Any,
64+
*,
65+
incoming: Dict[str, 'SoquetT'],
66+
outgoing: Dict[str, 'SoquetT'],
67+
):
68+
import quimb.tensor as qtn
69+
70+
tn.add(qtn.Tensor(data=np.eye(2), inds=(outgoing['q'], incoming['q']), tags=["I", tag]))
71+
72+
def as_cirq_op(
73+
self, qubit_manager: 'cirq.QubitManager', q: 'CirqQuregT' # type: ignore[type-var]
74+
) -> Tuple['cirq.Operation', Dict[str, 'CirqQuregT']]: # type: ignore[type-var]
75+
import cirq
76+
77+
(q,) = q
78+
return cirq.I(q), {'q': np.array([q])}
79+
80+
def _t_complexity_(self):
81+
return TComplexity()
82+
83+
def wire_symbol(self, reg: Optional[Register], idx: Tuple[int, ...] = tuple()) -> 'WireSymbol':
84+
if reg is None:
85+
return Text('')
86+
return TextBox('I')
87+
88+
def on_classical_vals(self, q: int) -> Dict[str, 'ClassicalValT']:
89+
return {'q': q}
90+
91+
def pretty_name(self) -> str:
92+
return self.__str__()
93+
94+
def __str__(self) -> str:
95+
return 'I'
96+
97+
98+
@bloq_example
99+
def _identity() -> Identity:
100+
identity = Identity()
101+
return identity
102+
103+
104+
_IDENTITY_DOC = BloqDocSpec(
105+
bloq_cls=Identity,
106+
import_line='from qualtran.bloqs.basic_gates import Identity',
107+
examples=[_identity],
108+
)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Copyright 2023 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import cirq
15+
import numpy as np
16+
17+
from qualtran import BloqBuilder
18+
from qualtran.bloqs.basic_gates import OneState
19+
from qualtran.bloqs.basic_gates.identity import _identity, Identity
20+
from qualtran.simulation.classical_sim import (
21+
format_classical_truth_table,
22+
get_classical_truth_table,
23+
)
24+
25+
26+
def test_to_cirq():
27+
bb = BloqBuilder()
28+
q = bb.add(OneState())
29+
q = bb.add(Identity(), q=q)
30+
cbloq = bb.finalize(q=q)
31+
circuit = cbloq.to_cirq_circuit()
32+
cirq.testing.assert_has_diagram(circuit, "_c(0): ───X───I───")
33+
vec1 = cbloq.tensor_contract()
34+
vec2 = cirq.final_state_vector(circuit)
35+
np.testing.assert_allclose(vec1, vec2)
36+
37+
38+
def test_identity(bloq_autotester):
39+
bloq_autotester(_identity)
40+
41+
42+
def test_unitary_vs_cirq():
43+
i = Identity()
44+
unitary = i.tensor_contract()
45+
cirq_unitary = cirq.unitary(cirq.I)
46+
np.testing.assert_allclose(unitary, cirq_unitary)
47+
48+
49+
def test_i_truth_table():
50+
classical_truth_table = format_classical_truth_table(*get_classical_truth_table(Identity()))
51+
assert (
52+
classical_truth_table
53+
== """\
54+
q | q
55+
--------
56+
0 -> 0
57+
1 -> 1"""
58+
)

qualtran/serialization/resolver_dict.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import qualtran.bloqs.arithmetic.sorting
2323
import qualtran.bloqs.basic_gates.cnot
2424
import qualtran.bloqs.basic_gates.hadamard
25+
import qualtran.bloqs.basic_gates.identity
2526
import qualtran.bloqs.basic_gates.on_each
2627
import qualtran.bloqs.basic_gates.rotation
2728
import qualtran.bloqs.basic_gates.s_gate
@@ -145,6 +146,7 @@
145146
"qualtran.bloqs.arithmetic.sorting.BitonicSort": qualtran.bloqs.arithmetic.sorting.BitonicSort,
146147
"qualtran.bloqs.arithmetic.sorting.Comparator": qualtran.bloqs.arithmetic.sorting.Comparator,
147148
"qualtran.bloqs.basic_gates.cnot.CNOT": qualtran.bloqs.basic_gates.cnot.CNOT,
149+
"qualtran.bloqs.basic_gates.identity.Identity": qualtran.bloqs.basic_gates.identity.Identity,
148150
"qualtran.bloqs.basic_gates.global_phase.GlobalPhase": qualtran.bloqs.basic_gates.global_phase.GlobalPhase,
149151
"qualtran.bloqs.basic_gates.hadamard.Hadamard": qualtran.bloqs.basic_gates.hadamard.Hadamard,
150152
"qualtran.bloqs.basic_gates.on_each.OnEach": qualtran.bloqs.basic_gates.on_each.OnEach,

0 commit comments

Comments
 (0)