Skip to content
Open
Show file tree
Hide file tree
Changes from 64 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
b5af1ab
phase7: copy FLASQ source and test files (raw, unmodified)
wjhuggins Apr 13, 2026
4ed31ff
phase7: add frozendict, pandas, and seaborn dependencies for FLASQ
wjhuggins Apr 13, 2026
e0b0adc
phase7: rewrite all imports and fix adder_example path
wjhuggins Apr 13, 2026
a11767c
phase7: rename test classes to *TestSuite
wjhuggins Apr 13, 2026
4dc927b
phase7: convert notebooks to .ipynb and add notebooks_test.py
wjhuggins Apr 13, 2026
df911e1
license: add Apache 2.0 headers to flasq files
wjhuggins Apr 13, 2026
b97421b
tests: mark slow and xfail tests in flasq
wjhuggins Apr 13, 2026
0cba1a5
phase7: final cleanup and add .gitignore
wjhuggins Apr 13, 2026
97096c6
phase7: add joblib to dependencies
wjhuggins Apr 13, 2026
df79b55
tests: run notebooks in temp dir to avoid polluting CWD
wjhuggins Apr 13, 2026
9e92415
Add script to reproduce cultivation spacetime volume heatmap (paper F…
wjhuggins Apr 14, 2026
bbb571d
refactor: avoid private API _extract_bloq_from_op in cirq_interop.py
wjhuggins Apr 16, 2026
afb0c1d
fix: import CirqGateAsBloq from public path in volume_counting.py
wjhuggins Apr 16, 2026
bb601f0
chore: ignore PDF files in Qualtran
wjhuggins Apr 16, 2026
b77f85f
fix: import CirqQuregT under TYPE_CHECKING in cirq_interop and adder_…
wjhuggins Apr 16, 2026
6c42eab
chore: add tqdm to pyproject.toml dependencies
wjhuggins Apr 16, 2026
d7819e8
dead-code: remove commented-out code in cirq_interop and adder_example
wjhuggins Apr 16, 2026
36d162a
docs: remove meta-comment TODO in gf2_multiplier_test.py
wjhuggins Apr 16, 2026
5cc2f94
chore: enable parallel test execution by default in pyproject.toml
wjhuggins Apr 16, 2026
5318b4e
chore: revert parallel test execution due to missing pytest-xdist
wjhuggins Apr 16, 2026
58a0c9e
chore: enable parallel test execution by default in pyproject.toml
wjhuggins Apr 16, 2026
39eed78
chore: revert parallel test execution in pyproject.toml
wjhuggins Apr 16, 2026
4a6935c
fix: add missing return types to __all__ in flasq/__init__.py
wjhuggins Apr 16, 2026
7a9d36e
fix: use autouse fixture for env vars in notebooks_test.py
wjhuggins Apr 16, 2026
8dca0d2
docs: add slow markers to flasq_model_test and nan_guard_test
wjhuggins Apr 16, 2026
461aa26
dead-code: remove print statements from test files
wjhuggins Apr 16, 2026
899a0df
docs: add slow marker to test_ising_volume_limited_depth_comparison_5…
wjhuggins Apr 16, 2026
effd1fa
fix: resolve T_REACT in hwp_test.py to fix volume-limited check
wjhuggins Apr 16, 2026
a843b44
dead-code: remove remaining TODO in hwp_test.py
wjhuggins Apr 16, 2026
d9500e7
dead-code: remove TODOs in flasq_model_test.py
wjhuggins Apr 16, 2026
a65c164
fix: export bloq_is_t_like from resource_counting to avoid type ignor…
wjhuggins Apr 16, 2026
e274330
fix: remove xfail markers from passing tests in misc_bug_test.py
wjhuggins Apr 16, 2026
98ad76f
refactor: extract convert_sympy_exprs_in_df to utils.py and use in po…
wjhuggins Apr 16, 2026
ae72ef9
refactor: remove redundant static cost check in TotalSpanCost.compute
wjhuggins Apr 16, 2026
163b8d6
refactor: use converter in MeasurementDepth and remove __attrs_post_i…
wjhuggins Apr 16, 2026
fa57231
cleanup: fix stale comment in MeasurementDepth and rename TestHashabl…
wjhuggins Apr 16, 2026
57faeaf
style: run isort on flasq/ to fix import ordering
wjhuggins Apr 16, 2026
d54a935
style: run black on flasq/ to fix code formatting
wjhuggins Apr 16, 2026
05f55b6
style: resolve isort/black conflict in flasq_model_test.py by consoli…
wjhuggins Apr 16, 2026
ca75ebf
fix: resolve upstream API breakage and analysis variable bugs
wjhuggins Apr 16, 2026
0a90650
fix: resolve systemic frozendict typing issues via _to_frozendict wra…
wjhuggins Apr 16, 2026
b45945d
fix: resolve mypy union narrowing, collection variance, and assertion…
wjhuggins Apr 16, 2026
bb4e2db
fix: resolve remaining type narrowing, import, and test collection er…
wjhuggins Apr 16, 2026
5deb8d9
style: reformat after mypy fixes
wjhuggins Apr 16, 2026
770ae58
fix: resolve mypy errors in utils.py by converting frozendict to list…
wjhuggins Apr 16, 2026
e402c5c
fix: resolve mypy errors in plotting.py by adding assert guards for m…
wjhuggins Apr 16, 2026
d51f305
fix: resolve mypy errors in volume_counting.py by fixing isinstance a…
wjhuggins Apr 16, 2026
423b7b9
fix: resolve mypy error in volume_counting_test.py by adding type ign…
wjhuggins Apr 16, 2026
576fb14
fix: resolve mypy errors related to span counting by widening calcula…
wjhuggins Apr 16, 2026
c08d443
fix: resolve mypy errors in flasq_model.py by adding type ignore for …
wjhuggins Apr 16, 2026
3e51685
chore: remove unused imports across FLASQ modules (pylint W0611)
wjhuggins Apr 16, 2026
8dd1729
chore: add missing copyright headers to flasq tests and data scripts …
wjhuggins Apr 16, 2026
94f4059
fix: use raw string for regex in naive_grid_qubit_manager_test.py (py…
wjhuggins Apr 16, 2026
ef47ded
fix: remove f prefix from strings without interpolation in adder_exam…
wjhuggins Apr 16, 2026
0ed9d95
fix: assign floating expressions to discard variable in tests (pylint…
wjhuggins Apr 16, 2026
d9eaa25
fix: use lazy f-string interpolation in measurement_depth.py logging …
wjhuggins Apr 16, 2026
4dfe0d2
fix: replace broad exception catching with specific exception classes…
wjhuggins Apr 16, 2026
8972873
fix: resolve syntax error and logging f-string in measurement_depth.py
wjhuggins Apr 16, 2026
1105296
fix: resolve f-string without interpolation in adder_example.py
wjhuggins Apr 16, 2026
aba6777
fix: resolve pylint warning by changing lru_cache maxsize in flasq_mo…
wjhuggins Apr 16, 2026
89bc37c
fix: disable false positive pylint warnings in test files
wjhuggins Apr 16, 2026
5d73974
style: reformat after pylint fixes
wjhuggins Apr 16, 2026
a42c4b7
fix: resolve final pylint warnings for clean run
wjhuggins Apr 16, 2026
d74f277
ci: enable FLASQ_FAST_MODE_OVERRIDE in notebooks CI job
wjhuggins Apr 17, 2026
e4bfabf
fix: guard symbolic comparison in apply_flasq_cost_model
wjhuggins Apr 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ jobs:
python dev_tools/execute-notebooks.py --n-workers=8
env:
NUMBA_NUM_THREADS: 4
FLASQ_FAST_MODE_OVERRIDE: 'True'
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we document this .. somewhere? How slow are the notebooks in non-fast mode? When we build the docs do we need the full notebook versions? Is there any merit to making the fast mode the default and explaining in the notebooks what to set to get the full version?


format:
runs-on: ubuntu-24.04
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,6 @@ jupyter_kernel.lock

# Mac OS
.DS_Store

# FLASQ generated PDFs
*.pdf
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ dependencies = [

# rotation_synthesis
"mpmath",

# flasq integration
"frozendict",
"pandas >= 2.0",
"seaborn",
"joblib",
"tqdm",
]

[tool.hatch.version]
Expand Down
1 change: 1 addition & 0 deletions qualtran/resource_counting/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@
from ._success_prob import SuccessProb
from ._qubit_counts import QubitCount
from ._bloq_counts import BloqCount, QECGatesCost, GateCounts
from .classify_bloqs import bloq_is_t_like
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't have just this one function re-exported. Can you please update usage of this function to just use its full, alread-public import qualtran.resource_counting.classify_bloqs.bloq_is_t_like?


from . import generalizers
85 changes: 85 additions & 0 deletions qualtran/surface_code/flasq/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Copyright 2024 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.

"""qualtran.surface_code.flasq: FLASQ cost model for fault-tolerant quantum resource estimation."""

from qualtran.surface_code.flasq import cultivation_analysis # noqa: F401 — imported as module
from qualtran.surface_code.flasq.cirq_interop import convert_circuit_for_flasq_analysis
from qualtran.surface_code.flasq.error_mitigation import (
calculate_error_mitigation_metrics,
calculate_failure_probabilities,
)
from qualtran.surface_code.flasq.flasq_model import (
apply_flasq_cost_model,
conservative_FLASQ_costs,
FLASQCostModel,
FLASQSummary,
get_rotation_depth,
optimistic_FLASQ_costs,
)
from qualtran.surface_code.flasq.measurement_depth import MeasurementDepth, TotalMeasurementDepth
from qualtran.surface_code.flasq.naive_grid_qubit_manager import NaiveGridQubitManager
from qualtran.surface_code.flasq.optimization import (
ErrorBudget,
generate_circuit_specific_configs,
generate_configs_for_constrained_qec,
generate_configs_from_cultivation_data,
post_process_for_failure_budget,
post_process_for_logical_depth,
post_process_for_pec_runtime,
run_sweep,
)
from qualtran.surface_code.flasq.span_counting import BloqWithSpanInfo, GateSpan, TotalSpanCost
from qualtran.surface_code.flasq.symbols import (
MIXED_FALLBACK_T_COUNT,
ROTATION_ERROR,
T_REACT,
V_CULT_FACTOR,
)
from qualtran.surface_code.flasq.utils import substitute_until_fixed_point
from qualtran.surface_code.flasq.volume_counting import FLASQGateCounts, FLASQGateTotals

__all__ = [
"FLASQCostModel",
"FLASQSummary",
"apply_flasq_cost_model",
"conservative_FLASQ_costs",
"optimistic_FLASQ_costs",
"get_rotation_depth",
"FLASQGateTotals",
"TotalSpanCost",
"TotalMeasurementDepth",
"convert_circuit_for_flasq_analysis",
"NaiveGridQubitManager",
"ErrorBudget",
"run_sweep",
"generate_configs_for_constrained_qec",
"generate_configs_from_cultivation_data",
"generate_circuit_specific_configs",
"post_process_for_failure_budget",
"post_process_for_pec_runtime",
"post_process_for_logical_depth",
"calculate_error_mitigation_metrics",
"calculate_failure_probabilities",
"MIXED_FALLBACK_T_COUNT",
"ROTATION_ERROR",
"V_CULT_FACTOR",
"T_REACT",
"substitute_until_fixed_point",
"cultivation_analysis",
"FLASQGateCounts",
"GateSpan",
"MeasurementDepth",
"BloqWithSpanInfo",
]
112 changes: 112 additions & 0 deletions qualtran/surface_code/flasq/adder_example_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Copyright 2024 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.

# test_adder_example.py
import cirq

from qualtran.resource_counting import get_cost_value
from qualtran.surface_code.flasq.cirq_interop import convert_circuit_for_flasq_analysis

# Import functions/classes to be tested or used in tests
from qualtran.surface_code.flasq.examples.adder_example import (
analyze_adder_costs,
create_adder_circuit_and_decorations,
)
from qualtran.surface_code.flasq.span_counting import GateSpan, TotalSpanCost
from qualtran.surface_code.flasq.volume_counting import FLASQGateCounts, FLASQGateTotals

TEST_BITSIZE = 4


def test_analyze_adder_costs_runs():
"""Tests that analyze_adder_costs executes without exceptions."""
analyze_adder_costs(TEST_BITSIZE)


def test_create_adder_circuit_runs_and_returns_circuit():
"""Tests create_adder_circuit runs and returns a Cirq circuit."""
circuit, _, _, _ = create_adder_circuit_and_decorations(TEST_BITSIZE)
assert isinstance(circuit, cirq.Circuit)
assert len(list(circuit.all_operations())) > 0


def test_decomposed_adder_flasq_and_span_costs():
"""
Tests applying FLASQ and Span costing to the decomposed adder circuit.
Verifies that costs are calculated and no unknown/uncounted bloqs remain.
"""
original_circuit, signature, in_quregs, out_quregs = create_adder_circuit_and_decorations(
TEST_BITSIZE
)
cbloq, decomposed_circuit = convert_circuit_for_flasq_analysis(
original_circuit, signature=signature, in_quregs=in_quregs, out_quregs=out_quregs
)
assert cbloq is not None # Ensure conversion succeeded
assert decomposed_circuit is not None # Ensure decomposed circuit is returned

flasq_costs = get_cost_value(cbloq, FLASQGateTotals())
assert isinstance(flasq_costs, FLASQGateCounts)
assert not flasq_costs.bloqs_with_unknown_cost
# Check that some expected gates were counted (Add decomposes to Toffoli/CNOT)
assert flasq_costs.toffoli > 0 or flasq_costs.cnot > 0
# 4. Calculate Span costs
span_info = get_cost_value(cbloq, TotalSpanCost())
assert isinstance(span_info, GateSpan)
assert not span_info.uncounted_bloqs
# Check that some span was counted (multi-qubit gates exist)
# Resolve symbols in span_info before making boolean checks
assert span_info.connect_span > 0
# Check the decomposed circuit from the conversion
assert len(list(decomposed_circuit.all_operations())) > 0


import cirq
import numpy as np

from qualtran import QUInt
from qualtran.bloqs.arithmetic import Add
from qualtran.bloqs.mcmt import And
from qualtran.cirq_interop import cirq_optree_to_cbloq


def test_self_contained_adder_issue():
adder_bloq = Add(a_dtype=QUInt(4), b_dtype=QUInt(4))

a_qubits = np.asarray([cirq.LineQubit(i * 3 + 0) for i in range(4)])
b_qubits = np.asarray([cirq.LineQubit(i * 3 + 1) for i in range(4)])

adder_op, _ = adder_bloq.as_cirq_op(
qubit_manager=cirq.SimpleQubitManager(), a=b_qubits, b=a_qubits
)
assert adder_op is not None
circuit = cirq.Circuit(adder_op)

def is_and_or_short(op):

if len(op.qubits) <= 2:
return True

if isinstance(op.gate, And):
return True

return False

circuit = cirq.Circuit(cirq.decompose(circuit, keep=is_and_or_short))

cbloq = cirq_optree_to_cbloq(
circuit.all_operations(),
signature=adder_bloq.signature,
in_quregs={"a": a_qubits, "b": b_qubits},
out_quregs={"a": a_qubits, "b": b_qubits},
)
Loading
Loading