-
Notifications
You must be signed in to change notification settings - Fork 71
Create a bloq for Semi-Classical QFT #1610
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
base: main
Are you sure you want to change the base?
Changes from all commits
cc3b901
ecdf953
62a2863
c48b1b2
2a3e38a
e411885
ca452a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"id": "de9c5ff4", | ||
"metadata": { | ||
"cq.autogen": "title_cell" | ||
}, | ||
"source": [ | ||
"# Semi-Classical QFT" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "70368002", | ||
"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": "f7a1c4c5", | ||
"metadata": { | ||
"cq.autogen": "SemiClassicalQFT.bloq_doc.md" | ||
}, | ||
"source": [ | ||
"## `SemiClassicalQFT`\n", | ||
"Represents QFT followed by measurement.\n", | ||
"\n", | ||
"When QFT is followed by measurement, we can replace all two qubit gates with classically\n", | ||
"controlled Rz rotations (at most $n-1$ Rz rotations). The two structures (QFT + Measurement)\n", | ||
"and SemiClassicaQFT behave statistically the same.\n", | ||
"\n", | ||
"\n", | ||
"#### Registers\n", | ||
" - `q`: A `QUInt` of `bitsize` qubits on which the QFT is performed and then measured. \n", | ||
"\n", | ||
"#### Parameters\n", | ||
" - `bitsize`: Size of the input register to apply QFT on.\n", | ||
" - `is_adjoint`: Whether to apply QFT or QFT†. \n", | ||
"\n", | ||
"#### References\n", | ||
" - [Semiclassical Fourier Transform for Quantum Computation, Griffiths & Niu](https://arxiv.org/abs/quant-ph/9511007). \n", | ||
" - [Implementation of the Semiclassical Quantum Fourier Transform in a Scalable System](https://www.science.org/doi/10.1126/science.1110335). \n", | ||
" - [stackexchange answer, Gidney](https://quantumcomputing.stackexchange.com/a/23712). \n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "6da027d2", | ||
"metadata": { | ||
"cq.autogen": "SemiClassicalQFT.bloq_doc.py" | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"from qualtran.bloqs.qft import SemiClassicalQFT" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "649aaa69", | ||
"metadata": { | ||
"cq.autogen": "SemiClassicalQFT.example_instances.md" | ||
}, | ||
"source": [ | ||
"### Example Instances" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "6d39d25c", | ||
"metadata": { | ||
"cq.autogen": "SemiClassicalQFT.semi_classical_qft" | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"semi_classical_qft = SemiClassicalQFT(3)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "c2f31d47", | ||
"metadata": { | ||
"cq.autogen": "SemiClassicalQFT.graphical_signature.md" | ||
}, | ||
"source": [ | ||
"#### Graphical Signature" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "3ac8fb19", | ||
"metadata": { | ||
"cq.autogen": "SemiClassicalQFT.graphical_signature.py" | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"from qualtran.drawing import show_bloqs\n", | ||
"show_bloqs([semi_classical_qft],\n", | ||
" ['`semi_classical_qft`'])" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "bd0754a1", | ||
"metadata": { | ||
"cq.autogen": "SemiClassicalQFT.call_graph.md" | ||
}, | ||
"source": [ | ||
"### Call Graph" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "44d351d0", | ||
"metadata": { | ||
"cq.autogen": "SemiClassicalQFT.call_graph.py" | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"from qualtran.resource_counting.generalizers import ignore_split_join\n", | ||
"semi_classical_qft_g, semi_classical_qft_sigma = semi_classical_qft.call_graph(max_depth=1, generalizer=ignore_split_join)\n", | ||
"show_call_graph(semi_classical_qft_g)\n", | ||
"show_counts_sigma(semi_classical_qft_sigma)" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"name": "python" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Copyright 2025 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from functools import cached_property | ||
from typing import TYPE_CHECKING | ||
|
||
import attrs | ||
|
||
from qualtran import Bloq, bloq_example, BloqDocSpec, QUInt, Register, Side, Signature | ||
from qualtran.bloqs.basic_gates import Hadamard, Rz | ||
from qualtran.bloqs.basic_gates._shims import Measure | ||
from qualtran.resource_counting import BloqCountDictT, SympySymbolAllocator | ||
|
||
if TYPE_CHECKING: | ||
from qualtran.symbolics import SymbolicInt | ||
|
||
|
||
@attrs.frozen | ||
class SemiClassicalQFT(Bloq): | ||
r"""Represents QFT followed by measurement. | ||
|
||
When QFT is followed by measurement, we can replace all two qubit gates with classically | ||
controlled Rz rotations (at most $n-1$ Rz rotations). The two structures (QFT + Measurement) | ||
and SemiClassicaQFT behave statistically the same. | ||
|
||
|
||
Registers: | ||
q: A `QUInt` of `bitsize` qubits on which the QFT is performed and then measured. | ||
|
||
Args: | ||
bitsize: Size of the input register to apply QFT on. | ||
is_adjoint: Whether to apply QFT or QFT†. | ||
|
||
References: | ||
[Semiclassical Fourier Transform for Quantum Computation, Griffiths & Niu](https://arxiv.org/abs/quant-ph/9511007) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you follow the standard reference format https://qualtran.readthedocs.io/en/latest/Autodoc.html#references
|
||
|
||
[Implementation of the Semiclassical Quantum Fourier Transform in a Scalable System](https://www.science.org/doi/10.1126/science.1110335) | ||
|
||
[stackexchange answer, Gidney](https://quantumcomputing.stackexchange.com/a/23712) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can use the stack exchange title as the title |
||
""" | ||
|
||
bitsize: 'SymbolicInt' | ||
is_adjoint: bool = False | ||
|
||
@cached_property | ||
def signature(self) -> 'Signature': | ||
return Signature([Register('q', QUInt(self.bitsize), side=Side.LEFT)]) | ||
|
||
def build_call_graph(self, ssa: SympySymbolAllocator) -> 'BloqCountDictT': | ||
t = ssa.new_symbol('t') | ||
return {Hadamard(): self.bitsize, Measure(): self.bitsize, Rz(t): self.bitsize - 1} | ||
Comment on lines
+61
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
||
|
||
@bloq_example | ||
def _semi_classical_qft() -> SemiClassicalQFT: | ||
semi_classical_qft = SemiClassicalQFT(3) | ||
return semi_classical_qft | ||
|
||
|
||
_SEMI_CLASSICAL_QFT_DOC = BloqDocSpec(bloq_cls=SemiClassicalQFT, examples=(_semi_classical_qft,)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Copyright 2025 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import pytest | ||
import sympy | ||
|
||
from qualtran.bloqs.qft import semi_classical_qft | ||
from qualtran.resource_counting import get_cost_value, QECGatesCost | ||
|
||
|
||
@pytest.mark.parametrize('n', [*range(1, 10), sympy.Symbol('n')]) | ||
def test_semi_classical_qft_cost(n): | ||
blq = semi_classical_qft.SemiClassicalQFT(n) | ||
cost = get_cost_value(blq, QECGatesCost()) | ||
assert cost.rotation == n - 1 | ||
assert cost.clifford == n | ||
assert cost.measurement == n |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we usually put Args first