Skip to content

Commit

Permalink
Add Unitary and TensorProduct block encodings
Browse files Browse the repository at this point in the history
  • Loading branch information
charlesyuan314 committed Jun 27, 2024
1 parent c6aa419 commit 110b29b
Show file tree
Hide file tree
Showing 12 changed files with 637 additions and 3 deletions.
2 changes: 2 additions & 0 deletions dev_tools/autogenerate-bloqs-notebooks-v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,8 @@
qualtran.bloqs.block_encoding.lcu_block_encoding._LCU_BLOCK_ENCODING_DOC,
qualtran.bloqs.block_encoding.lcu_block_encoding._LCU_ZERO_STATE_BLOCK_ENCODING_DOC,
qualtran.bloqs.block_encoding.chebyshev_polynomial._CHEBYSHEV_BLOQ_DOC,
qualtran.bloqs.block_encoding.unitary._UNITARY_DOC,
qualtran.bloqs.block_encoding.tensor_product._TENSOR_PRODUCT_DOC,
],
directory=f'{SOURCE_DIR}/bloqs/block_encoding/',
),
Expand Down
2 changes: 1 addition & 1 deletion qualtran/_infra/registers.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def build_from_dtypes(cls, **registers: QDType) -> 'Signature':
registers: keyword arguments mapping register name to QDType. All registers
will be 0-dimensional and THRU.
"""
return cls(Register(name=k, dtype=v) for k, v in registers.items() if v.num_qubits)
return cls(Register(name=k, dtype=v) for k, v in registers.items())

def lefts(self) -> Iterable[Register]:
"""Iterable over all registers that appear on the LEFT as input."""
Expand Down
2 changes: 1 addition & 1 deletion qualtran/_infra/registers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def test_signature_build():
sig1 = Signature([Register("r1", QInt(7)), Register("r2", QBit())])
sig2 = Signature.build_from_dtypes(r1=QInt(7), r2=QBit())
assert sig1 == sig2
sig1 = Signature([Register("r1", QInt(7))])
sig1 = Signature([Register("r1", QInt(7)), Register("r2", QAny(0))])
sig2 = Signature.build_from_dtypes(r1=QInt(7), r2=QAny(0))
assert sig1 == sig2

Expand Down
2 changes: 2 additions & 0 deletions qualtran/bloqs/block_encoding/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@
LCUBlockEncoding,
LCUBlockEncodingZeroState,
)
from qualtran.bloqs.block_encoding.tensor_product import TensorProduct
from qualtran.bloqs.block_encoding.unitary import Unitary
232 changes: 232 additions & 0 deletions qualtran/bloqs/block_encoding/block_encoding.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,238 @@
"show_call_graph(chebyshev_poly_g)\n",
"show_counts_sigma(chebyshev_poly_sigma)"
]
},
{
"cell_type": "markdown",
"id": "6836a23d",
"metadata": {
"cq.autogen": "Unitary.bloq_doc.md"
},
"source": [
"## `Unitary`\n",
"Trivial block encoding of a unitary operator.\n",
"\n",
"Builds the block encoding as\n",
"$\n",
" B[U] = U\n",
"$\n",
"where $U$ is a unitary operator. Here, $B[U]$ is a $(1, 0, 0)$-block encoding of $U$.\n",
"\n",
"#### Parameters\n",
" - `U`: The unitary operator to block-encode.\n",
" - `dtype`: The quantum data type of the system `U` operates over. \n",
"\n",
"#### Registers\n",
" - `system`: The system register.\n",
" - `ancilla`: The ancilla register (size 0).\n",
" - `resource`: The resource register (size 0).\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "10bda229",
"metadata": {
"cq.autogen": "Unitary.bloq_doc.py"
},
"outputs": [],
"source": [
"from qualtran.bloqs.block_encoding import Unitary"
]
},
{
"cell_type": "markdown",
"id": "da23b898",
"metadata": {
"cq.autogen": "Unitary.example_instances.md"
},
"source": [
"### Example Instances"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "63966178",
"metadata": {
"cq.autogen": "Unitary.unitary_block_encoding"
},
"outputs": [],
"source": [
"from qualtran import QBit\n",
"from qualtran.bloqs.basic_gates import TGate\n",
"\n",
"unitary_block_encoding = Unitary(TGate(), dtype=QBit())"
]
},
{
"cell_type": "markdown",
"id": "670e3692",
"metadata": {
"cq.autogen": "Unitary.graphical_signature.md"
},
"source": [
"#### Graphical Signature"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "97b4f383",
"metadata": {
"cq.autogen": "Unitary.graphical_signature.py"
},
"outputs": [],
"source": [
"from qualtran.drawing import show_bloqs\n",
"show_bloqs([unitary_block_encoding],\n",
" ['`unitary_block_encoding`'])"
]
},
{
"cell_type": "markdown",
"id": "91e9171c",
"metadata": {
"cq.autogen": "Unitary.call_graph.md"
},
"source": [
"### Call Graph"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0042bd79",
"metadata": {
"cq.autogen": "Unitary.call_graph.py"
},
"outputs": [],
"source": [
"from qualtran.resource_counting.generalizers import ignore_split_join\n",
"unitary_block_encoding_g, unitary_block_encoding_sigma = unitary_block_encoding.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
"show_call_graph(unitary_block_encoding_g)\n",
"show_counts_sigma(unitary_block_encoding_sigma)"
]
},
{
"cell_type": "markdown",
"id": "278a14ac",
"metadata": {
"cq.autogen": "TensorProduct.bloq_doc.md"
},
"source": [
"## `TensorProduct`\n",
"Tensor product of a sequence of block encodings.\n",
"\n",
"Builds the block encoding as\n",
"$$\n",
" B[U_1 ⊗ U_2 ⊗ \\cdots ⊗ U_n] = B[U_1] ⊗ B[U_2] ⊗ \\cdots ⊗ B[U_n]\n",
"$$\n",
"\n",
"When each $B[U_i]$ is a $(\\alpha_i, a_i, \\epsilon_i)$-block encoding of $U_i$, we have that\n",
"$B[U_1 ⊗ \\cdots ⊗ U_n]$ is a $(\\prod_i \\alpha_i, \\sum_i a_i, \\sum_i \\alpha_i \\epsilon_i)$-block\n",
"encoding of $U_1 ⊗ \\cdots ⊗ U_n$.\n",
"\n",
"#### Parameters\n",
" - `U`: A sequence of block encodings. \n",
"\n",
"#### Registers\n",
" - `system`: The system register.\n",
" - `ancilla`: The ancilla register.\n",
" - `resource`: The resource register. \n",
"\n",
"#### References\n",
" - [Quantum algorithms: A survey of applications and end-to-end complexities](https://arxiv.org/abs/2310.03011). Dalzell et al. (2023). Ch. 10.2.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4f1e952b",
"metadata": {
"cq.autogen": "TensorProduct.bloq_doc.py"
},
"outputs": [],
"source": [
"from qualtran.bloqs.block_encoding import TensorProduct"
]
},
{
"cell_type": "markdown",
"id": "004fde81",
"metadata": {
"cq.autogen": "TensorProduct.example_instances.md"
},
"source": [
"### Example Instances"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1478a7ac",
"metadata": {
"cq.autogen": "TensorProduct.tensor_product_block_encoding"
},
"outputs": [],
"source": [
"from qualtran import QBit\n",
"from qualtran.bloqs.basic_gates import Hadamard, TGate\n",
"from qualtran.bloqs.block_encoding.unitary import Unitary\n",
"\n",
"tensor_product_block_encoding = TensorProduct(\n",
" [Unitary(TGate(), dtype=QBit()), Unitary(Hadamard(), dtype=QBit())]\n",
")"
]
},
{
"cell_type": "markdown",
"id": "611fefc9",
"metadata": {
"cq.autogen": "TensorProduct.graphical_signature.md"
},
"source": [
"#### Graphical Signature"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f34e93d7",
"metadata": {
"cq.autogen": "TensorProduct.graphical_signature.py"
},
"outputs": [],
"source": [
"from qualtran.drawing import show_bloqs\n",
"show_bloqs([tensor_product_block_encoding],\n",
" ['`tensor_product_block_encoding`'])"
]
},
{
"cell_type": "markdown",
"id": "53df4024",
"metadata": {
"cq.autogen": "TensorProduct.call_graph.md"
},
"source": [
"### Call Graph"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0883c9f0",
"metadata": {
"cq.autogen": "TensorProduct.call_graph.py"
},
"outputs": [],
"source": [
"from qualtran.resource_counting.generalizers import ignore_split_join\n",
"tensor_product_block_encoding_g, tensor_product_block_encoding_sigma = tensor_product_block_encoding.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
"show_call_graph(tensor_product_block_encoding_g)\n",
"show_counts_sigma(tensor_product_block_encoding_sigma)"
]
}
],
"metadata": {
Expand Down
28 changes: 27 additions & 1 deletion qualtran/bloqs/block_encoding/block_encoding_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
import abc
from typing import Tuple

from qualtran import Bloq, BloqDocSpec, Register
from qualtran import Bloq, BloqDocSpec, QDType, Register
from qualtran.bloqs.block_encoding.lcu_select_and_prepare import PrepareOracle
from qualtran.symbolics import SymbolicFloat


class BlockEncoding(Bloq):
Expand Down Expand Up @@ -67,6 +68,31 @@ class `BlockEncoding` bloq, which expects values for $\alpha$, $\epsilon$,
def pretty_name(self) -> str:
return 'B[H]'

@property
def dtype(self) -> QDType:
"""The type of the system being block encoded."""
raise NotImplementedError

@property
def alpha(self) -> SymbolicFloat:
"""The normalization constant."""
raise NotImplementedError

@property
def num_ancillas(self) -> int:
"""The number of ancilla qubits."""
raise NotImplementedError

@property
def num_resource(self) -> int:
"""The number of resource qubits not counted in ancillas."""
raise NotImplementedError

@property
def epsilon(self) -> SymbolicFloat:
"""The precision to which the block encoding is to be prepared."""
raise NotImplementedError

@property
@abc.abstractmethod
def selection_registers(self) -> Tuple[Register, ...]:
Expand Down
Loading

0 comments on commit 110b29b

Please sign in to comment.