Skip to content

Commit

Permalink
planted noisy kXOR algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
anurudhp committed Oct 18, 2024
1 parent 3117a84 commit 1da6f23
Show file tree
Hide file tree
Showing 55 changed files with 14,300 additions and 19 deletions.
56 changes: 56 additions & 0 deletions dev_tools/qualtran_dev_tools/notebook_specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@
import qualtran.bloqs.gf_arithmetic.gf2_multiplication
import qualtran.bloqs.gf_arithmetic.gf2_square
import qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp
import qualtran.bloqs.max_k_xor_sat
import qualtran.bloqs.max_k_xor_sat.arithmetic
import qualtran.bloqs.max_k_xor_sat.guided_hamiltonian
import qualtran.bloqs.mcmt.and_bloq
import qualtran.bloqs.mcmt.controlled_via_and
import qualtran.bloqs.mcmt.ctrl_spec_and
Expand Down Expand Up @@ -859,6 +862,58 @@
),
]

# --------------------------------------------------------------------------
# ----- Quartic Speedups paper ------------------------------------------
# --------------------------------------------------------------------------
ALGO_QUARTIC_SPEEDUPS = [
# ----- Preliminaries ------------------------------------------
NotebookSpecV2(
title='Guided (sparse) Hamiltonian Problem',
module=qualtran.bloqs.max_k_xor_sat.guided_hamiltonian.guided_hamiltonian,
bloq_specs=[
qualtran.bloqs.max_k_xor_sat.guided_hamiltonian.guided_hamiltonian._GUIDED_HAMILTONIAN_DOC,
qualtran.bloqs.max_k_xor_sat.guided_hamiltonian.guided_hamiltonian._GUIDED_HAMILTONIAN_PHASE_ESTIMATION_DOC,
],
),
NotebookSpecV2(
title='Arithmetic Primitives',
module=qualtran.bloqs.max_k_xor_sat.arithmetic,
bloq_specs=[
qualtran.bloqs.max_k_xor_sat.arithmetic.sort_in_place._SORT_IN_PLACE_DOC,
qualtran.bloqs.max_k_xor_sat.arithmetic.symmetric_difference._SYMMETRIC_DIFFERENCE_DOC,
qualtran.bloqs.max_k_xor_sat.arithmetic.has_duplicates._HAS_DUPLICATES_DOC,
],
),
# ----- Algorithm ------------------------------------------
NotebookSpecV2(
title='kXOR: Instance load Oracles',
module=qualtran.bloqs.max_k_xor_sat.load_kxor_instance,
bloq_specs=[qualtran.bloqs.max_k_xor_sat.load_kxor_instance._LOAD_INSTANCE_DOC],
),
NotebookSpecV2(
title='Noisy kXOR: Guiding State',
module=qualtran.bloqs.max_k_xor_sat.guiding_state,
bloq_specs=[
qualtran.bloqs.max_k_xor_sat.guiding_state._SIMPLE_GUIDING_STATE_DOC,
qualtran.bloqs.max_k_xor_sat.guiding_state._GUIDING_STATE_DOC,
],
),
NotebookSpecV2(
title='Noisy kXOR: Block-encoding the Kikuchi Matrix',
module=qualtran.bloqs.max_k_xor_sat.kikuchi_block_encoding,
bloq_specs=[
qualtran.bloqs.max_k_xor_sat.kikuchi_adjacency_matrix._KIKUCHI_MATRIX_ENTRY_DOC,
qualtran.bloqs.max_k_xor_sat.kikuchi_adjacency_list._KIKUCHI_NONZERO_INDEX_DOC,
qualtran.bloqs.max_k_xor_sat.kikuchi_block_encoding._KIKUCHI_HAMILTONIAN_DOC,
],
),
NotebookSpecV2(
title='Algorithm: Planted Noise kXOR',
module=qualtran.bloqs.max_k_xor_sat.planted_noisy_kxor,
bloq_specs=[qualtran.bloqs.max_k_xor_sat.planted_noisy_kxor._PLANTED_NOISY_KXOR_DOC],
),
]

NB_BY_SECTION = [
('Basic Gates', BASIC_GATES),
('Chemistry', CHEMISTRY),
Expand All @@ -867,5 +922,6 @@
('GF Arithmetic', GF_ARITHMETIC),
('Rotations', ROT_QFT_PE),
('Block Encoding', BLOCK_ENCODING),
('Paper: Quartic Quantum Speedups for Planted Inference', ALGO_QUARTIC_SPEEDUPS),
('Other', OTHER),
]
11 changes: 11 additions & 0 deletions docs/bloqs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,17 @@ Bloqs Library
block_encoding/chebyshev_polynomial.ipynb
block_encoding/lcu_block_encoding.ipynb

.. toctree::
:maxdepth: 2
:caption: Paper: Quartic Quantum Speedups for Planted Inference:

max_k_xor_sat/guided_hamiltonian/guided_hamiltonian.ipynb
max_k_xor_sat/arithmetic/arithmetic.ipynb
max_k_xor_sat/load_kxor_instance.ipynb
max_k_xor_sat/guiding_state.ipynb
max_k_xor_sat/kikuchi_block_encoding.ipynb
max_k_xor_sat/planted_noisy_kxor.ipynb

.. toctree::
:maxdepth: 2
:caption: Other:
Expand Down
11 changes: 6 additions & 5 deletions qualtran/bloqs/arithmetic/sorting.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
bloq_example,
BloqBuilder,
BloqDocSpec,
DecomposeNotImplementedError,
DecomposeTypeError,
QBit,
QUInt,
Expand Down Expand Up @@ -222,8 +223,6 @@ def __attrs_post_init__(self):
k = self.half_length
if not is_symbolic(k):
assert k >= 1, "length of input lists must be positive"
# TODO(#1090) support non-power-of-two input lengths
assert (k & (k - 1)) == 0, "length of input lists must be a power of 2"

@cached_property
def signature(self) -> 'Signature':
Expand All @@ -249,14 +248,16 @@ def is_symbolic(self):
def build_composite_bloq(
self, bb: 'BloqBuilder', xs: 'SoquetT', ys: 'SoquetT'
) -> dict[str, 'SoquetT']:
if is_symbolic(self.half_length):
k = self.half_length
if is_symbolic(k):
raise DecomposeTypeError(f"Cannot decompose symbolic {self=}")
if (k & (k - 1)) == 0:
# TODO(#1090) support non-power-of-two input lengths
raise DecomposeNotImplementedError("length of input lists must be a power of 2")

assert isinstance(xs, np.ndarray)
assert isinstance(ys, np.ndarray)

k = self.half_length

first_round_junk = []
for i in range(k):
xs[i], ys[k - 1 - i], anc = bb.add(Comparator(self.bitsize), a=xs[i], b=ys[k - 1 - i])
Expand Down
1 change: 1 addition & 0 deletions qualtran/bloqs/block_encoding/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@
from qualtran.bloqs.block_encoding.phase import Phase
from qualtran.bloqs.block_encoding.product import Product
from qualtran.bloqs.block_encoding.sparse_matrix import SparseMatrix
from qualtran.bloqs.block_encoding.sparse_matrix_hermitian import SparseMatrixHermitian
from qualtran.bloqs.block_encoding.tensor_product import TensorProduct
from qualtran.bloqs.block_encoding.unitary import Unitary
8 changes: 8 additions & 0 deletions qualtran/bloqs/block_encoding/block_encoding_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ def ancilla_bitsize(self) -> SymbolicInt:
def resource_bitsize(self) -> SymbolicInt:
"""The number of resource qubits not counted in ancillas."""

@property
def ctrl_bitsize(self) -> SymbolicInt:
"""The number of control qubits, useful to define optimized custom controlled circuits.
Usually either 0 or 1, as all other control cases can be reduced to 1.
"""
return 0

@property
@abc.abstractmethod
def epsilon(self) -> SymbolicFloat:
Expand Down
203 changes: 203 additions & 0 deletions qualtran/bloqs/block_encoding/sparse_matrix_hermitian.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "30c4ebd9",
"metadata": {
"cq.autogen": "title_cell"
},
"source": [
"# Sparse Matrix (Hermitian)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e5d9072c",
"metadata": {
"cq.autogen": "top_imports"
},
"outputs": [],
"source": [
"from qualtran import Bloq, CompositeBloq, BloqBuilder, Signature, Register\n",
"from qualtran import QBit, QInt, QUInt, QAny\n",
"from qualtran.drawing import show_bloq, show_call_graph, show_counts_sigma\n",
"from typing import *\n",
"import numpy as np\n",
"import sympy\n",
"import cirq"
]
},
{
"cell_type": "markdown",
"id": "9cb4d637",
"metadata": {
"cq.autogen": "SparseMatrixHermitian.bloq_doc.md"
},
"source": [
"## `SparseMatrixHermitian`\n",
"Hermitian Block encoding of a sparse-access Hermitian matrix.\n",
"\n",
"Given column and entry oracles $O_c$ and $O_A$ for an $s$-sparse Hermitian matrix\n",
"$A \\in \\mathbb{C}^{2^n \\times 2^n}$, i.e. one where each row / column has exactly $s$ non-zero\n",
"entries, computes a $(s, n+1, \\epsilon)$-block encoding of $A$ as follows:\n",
"```\n",
" ┌────┐\n",
"a |0> ─┤ ├─ |0> ───────────────────────X────────────────────\n",
" │ │ ┌──┐ | ┌──┐\n",
" │ U │ = │ n│ ┌────┐ ┌────┐ | ┌────┐ ┌────┐ │ n│\n",
"l |0^n> ─┤ A ├─ |0^n> ─┤H ├─┤ O ├─┤ ├─X──|─┤ ├─┤ O* ├─┤H ├─\n",
" │ │ └──┘ | c | │ │ | | │ │ | c | └──┘\n",
" │ │ └────┘ │ O │ │ | │ O* │ └────┘\n",
"b |0> ─┤ ├─ |0> ────────|────┤ A ├─|──X─┤ A ├───|─────────\n",
" | | ┌────┐ | | | | | ┌────┐\n",
" | | | O | | | | | | | O* |\n",
"j |Psi> ─┤ ├─ |Psi> ──────┤ c ├─┤ ├─X────┤ ├─┤ c ├──────\n",
" └────┘ └────┘ └────┘ └────┘ └────┘\n",
"```\n",
"\n",
"To encode a matrix of irregular dimension, the matrix should first be embedded into one of\n",
"dimension $2^n \\times 2^n$ for suitable $n$.\n",
"To encode a matrix where each row / column has at most $s$ non-zero entries, some zeroes should\n",
"be treated as if they were non-zero so that each row / column has exactly $s$ non-zero entries.\n",
"\n",
"For encoding a non-hermitian matrix, or a slightly more efficient (but non Hermitian-encoding)\n",
"of a matrix, use :class:`SparseMatrix` instead.\n",
"\n",
"#### Parameters\n",
" - `col_oracle`: The column oracle $O_c$. See `RowColumnOracle` for definition.\n",
" - `entry_oracle`: The entry oracle $O_A$. See `EntryOracle` for definition.\n",
" - `eps`: The precision of the block encoding. \n",
"\n",
"#### Registers\n",
" - `ctrl`: The single qubit control register. (present only if `cv` is not `None`)\n",
" - `system`: The system register.\n",
" - `ancilla`: The ancilla register.\n",
" - `resource`: The resource register (present only if `bitsize > 0`). \n",
"\n",
"#### References\n",
" - [Lecture Notes on Quantum Algorithms for Scientific Computation](https://arxiv.org/abs/2201.08309). Lin Lin (2022). Ch. 6.5. Proposition 6.8, Fig 6.7.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "01cdcc22",
"metadata": {
"cq.autogen": "SparseMatrixHermitian.bloq_doc.py"
},
"outputs": [],
"source": [
"from qualtran.bloqs.block_encoding import SparseMatrixHermitian"
]
},
{
"cell_type": "markdown",
"id": "6bd99e38",
"metadata": {
"cq.autogen": "SparseMatrixHermitian.example_instances.md"
},
"source": [
"### Example Instances"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8337e6aa",
"metadata": {
"cq.autogen": "SparseMatrixHermitian.sparse_matrix_symb_hermitian_block_encoding"
},
"outputs": [],
"source": [
"from qualtran.bloqs.block_encoding.sparse_matrix import TopLeftRowColumnOracle\n",
"from qualtran.bloqs.block_encoding.sparse_matrix_hermitian import UniformSqrtEntryOracle\n",
"\n",
"n = sympy.Symbol('n', positive=True, integer=True)\n",
"col_oracle = TopLeftRowColumnOracle(system_bitsize=n)\n",
"entry_oracle = UniformSqrtEntryOracle(system_bitsize=n, entry=0.3)\n",
"sparse_matrix_symb_hermitian_block_encoding = SparseMatrixHermitian(\n",
" col_oracle, entry_oracle, eps=0\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "642141ad",
"metadata": {
"cq.autogen": "SparseMatrixHermitian.sparse_matrix_hermitian_block_encoding"
},
"outputs": [],
"source": [
"from qualtran.bloqs.block_encoding.sparse_matrix import TopLeftRowColumnOracle\n",
"from qualtran.bloqs.block_encoding.sparse_matrix_hermitian import UniformSqrtEntryOracle\n",
"\n",
"col_oracle = TopLeftRowColumnOracle(system_bitsize=2)\n",
"entry_oracle = UniformSqrtEntryOracle(system_bitsize=2, entry=0.3)\n",
"sparse_matrix_hermitian_block_encoding = SparseMatrixHermitian(col_oracle, entry_oracle, eps=0)"
]
},
{
"cell_type": "markdown",
"id": "4f3434b5",
"metadata": {
"cq.autogen": "SparseMatrixHermitian.graphical_signature.md"
},
"source": [
"#### Graphical Signature"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4b875699",
"metadata": {
"cq.autogen": "SparseMatrixHermitian.graphical_signature.py"
},
"outputs": [],
"source": [
"from qualtran.drawing import show_bloqs\n",
"show_bloqs([sparse_matrix_symb_hermitian_block_encoding, sparse_matrix_hermitian_block_encoding],\n",
" ['`sparse_matrix_symb_hermitian_block_encoding`', '`sparse_matrix_hermitian_block_encoding`'])"
]
},
{
"cell_type": "markdown",
"id": "a0918562",
"metadata": {
"cq.autogen": "SparseMatrixHermitian.call_graph.md"
},
"source": [
"### Call Graph"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8128a66e",
"metadata": {
"cq.autogen": "SparseMatrixHermitian.call_graph.py"
},
"outputs": [],
"source": [
"from qualtran.resource_counting.generalizers import ignore_split_join\n",
"sparse_matrix_symb_hermitian_block_encoding_g, sparse_matrix_symb_hermitian_block_encoding_sigma = sparse_matrix_symb_hermitian_block_encoding.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
"show_call_graph(sparse_matrix_symb_hermitian_block_encoding_g)\n",
"show_counts_sigma(sparse_matrix_symb_hermitian_block_encoding_sigma)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading

0 comments on commit 1da6f23

Please sign in to comment.