Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
2935073
Add `gen` as dependency
inmzhang Sep 30, 2025
08b756d
Move `PauliBasis` and `ExtendedBasis` enums into `tqec.utils.enums`
inmzhang Sep 30, 2025
1b3fe8b
Add S gate teleportation to gallery
inmzhang Sep 30, 2025
2376a4b
Use uppercase for `PauliBasis` enum values
inmzhang Sep 30, 2025
e164975
Add Y basis supports for memory and move rotation gallery function
inmzhang Sep 30, 2025
ab7f183
Implement y-basis circuit with `gen`
inmzhang Oct 1, 2025
c07f161
Merge branch 'main' into feat/y-basis-block
inmzhang Oct 1, 2025
cc07ce8
Rename `Block` as `LayeredBlock`
inmzhang Oct 1, 2025
3e65cb9
Fix the issues resulted from uppercasing the `PauliBasis` and `Extend…
inmzhang Oct 1, 2025
7e17f0a
Introduces `InjectedBlock` type and `Block` base type
inmzhang Oct 1, 2025
0bef212
Add spec information for `YHalfCube`
inmzhang Oct 1, 2025
67b4398
Implement Y basis block generator
inmzhang Oct 1, 2025
a09b842
Enable adding `InjectedBlock` instances to `TopologicalComputationGraph`
inmzhang Oct 1, 2025
715ddf4
Do not shift the block graph's z position and attach layer's z inform…
inmzhang Oct 1, 2025
6a8ff75
Add Y observable information to abstract observable
inmzhang Oct 1, 2025
89ff33b
Fix typo
inmzhang Oct 1, 2025
d54f927
Fix left PauliBasis uppercase issue
inmzhang Oct 1, 2025
2263bc0
Deduplicate position z values to fix tests
inmzhang Oct 1, 2025
55a1d02
Fix abstract observable test
inmzhang Oct 2, 2025
12922dd
Fix typo
inmzhang Oct 2, 2025
816376f
Add observable instructions at the factory level
inmzhang Oct 2, 2025
136e7bd
Add very ugly proof of concept implementation of tree circuit injection
inmzhang Oct 2, 2025
468e9b6
refactor the injection code but still complex
inmzhang Oct 3, 2025
75fb81b
Allow empty sequenced layers and fix tests
inmzhang Oct 3, 2025
d82359a
Split large chunks into smaller one to get the auto-solved measuremen…
inmzhang Oct 3, 2025
b42852b
Merge branch 'main' into feat/y-basis-block
inmzhang Oct 3, 2025
a352245
Add S gate gallery notebook
inmzhang Oct 3, 2025
26699d9
Bump the detector database version as a breaking change
inmzhang Oct 4, 2025
6e4d129
Apply suggestions from code review
inmzhang Oct 15, 2025
1b1fe5e
Add `pymatching>=2.3.1` to docs dependency group and bump pymatching …
inmzhang Oct 15, 2025
6f00fe6
Fix ax label
inmzhang Oct 15, 2025
90f7f1d
Do not bump major version of detector database
inmzhang Oct 15, 2025
dd04ef2
remove empty moments after building circuit
inmzhang Oct 15, 2025
e2484e1
Update links in the notebook
inmzhang Oct 15, 2025
5719232
Merge branch 'main' into feat/y-basis-block
inmzhang Oct 15, 2025
3f3f7de
Add S gate gallery to `index.rst`
inmzhang Oct 15, 2025
28f6e8d
Y half cube updates (#736)
KabirDubey Oct 16, 2025
08acc94
Revert the changes of class abstraction
inmzhang Oct 16, 2025
b8ef1e5
Do not early return when the Y-port check passes and revert changes m…
inmzhang Oct 17, 2025
020a151
improve test coverage
inmzhang Oct 17, 2025
15365fe
Merge main
inmzhang Nov 4, 2025
92476ed
xor cube top observable qubits together
inmzhang Nov 4, 2025
bc034bb
Add test script
inmzhang Nov 9, 2025
4d0afbb
dirty fix for automatic flow solving
inmzhang Nov 24, 2025
bcad2d8
Merge branch 'main' into feat/y-basis-block
inmzhang Nov 24, 2025
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
Binary file added docs/_static/media/gallery/s_gate.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ def setup(app):
"gallery/move_rotation": "_static/media/gallery/move_rotation.png",
"gallery/three_cnots": "_static/media/gallery/three_cnots.png",
"gallery/steane_encoding": "_static/media/gallery/steane_encoding.png",
"gallery/s_gate": "_static/media/gallery/s_gate.png",
}


Expand Down
Binary file added docs/gallery/Figure 1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/gallery/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ This section contains a collection of constructed logical computations and their
move_rotation.ipynb
three_cnots.ipynb
steane_encoding.ipynb
s_gate.ipynb
822 changes: 822 additions & 0 deletions docs/gallery/s_gate.ipynb
Comment thread
KabirDubey marked this conversation as resolved.

Large diffs are not rendered by default.

484 changes: 484 additions & 0 deletions docs/media/gallery/s_gate/circuit.stim

Large diffs are not rendered by default.

107 changes: 107 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
from tqec import BlockGraph, NoiseModel, compile_block_graph
from tqec.compile.convention import FIXED_BOUNDARY_CONVENTION
from tqec.utils.position import Position3D

g = BlockGraph()

n0 = g.add_cube(Position3D(0, 0, 0), "ZZX")
n1 = g.add_cube(Position3D(1, 0, 0), "XZX")
n2 = g.add_cube(Position3D(-1, 0, 0), "XZX")
n3 = g.add_cube(Position3D(0, 1, 0), "ZXX")
n4 = g.add_cube(Position3D(0, -1, 0), "ZXX")

n5 = g.add_cube(Position3D(1, 0, 1), "Y")
n6 = g.add_cube(Position3D(-1, 0, 1), "Y")
n7 = g.add_cube(Position3D(0, 1, 1), "Y")
n8 = g.add_cube(Position3D(0, -1, 1), "Y")

g.add_pipe(n0, n1)
g.add_pipe(n0, n2)
g.add_pipe(n0, n3)
g.add_pipe(n0, n4)
g.add_pipe(n1, n5)
g.add_pipe(n2, n6)
g.add_pipe(n3, n7)
g.add_pipe(n4, n8)

correlation_surface = g.find_correlation_surfaces()[0]
g.view_as_html(
"test.html", show_correlation_surface=correlation_surface, pop_faces_at_directions=("+Z", "-Y")
)

cg = compile_block_graph(g, observables=[correlation_surface], convention=FIXED_BOUNDARY_CONVENTION)
circuit = cg.generate_stim_circuit(k=3)

# circuit.to_file("sliding_annotated.stim")
noisy_circuit = NoiseModel.uniform_depolarizing(1e-3).noisy_circuit(circuit)
# noisy_circuit.detector_error_model().to_file("sliding.dem")
# explained = noisy_circuit.explain_detector_error_model_errors(
# dem_filter=stim.DetectorErrorModel("error(0.001931182734310662227) D1 D3 D20 D22")
# )

# noisy_circuit.to_file("test2.stim")
# noisy_circuit.detector_error_model().to_file("test.dem")
# noisy_circuit.detector_error_model(
# decompose_errors=True, block_decomposition_from_introducing_remnant_edges=True
# )
# errors = noisy_circuit.explain_detector_error_model_errors(
# dem_filter=stim.DetectorErrorModel("error(6.669779853440971351e-05) D494 D604 D611 D640 D673")
# )
# print(errors[0])


logical_error = noisy_circuit.shortest_graphlike_error(
ignore_ungraphlike_errors=False, canonicalize_circuit_errors=True
)
# html_str = gen.stim_circuit_html_viewer(noisy_circuit, known_error=explained)
# html_str = gen.stim_circuit_html_viewer(noisy_circuit, known_error=logical_error)
# with open("stim_circuit.html", "w") as f:
# print(html_str, file=f)
print("Length of shortest graphlike error:", len(logical_error))


# SAVE_DIR = Path("results")
#
#
# def generate_graphs() -> None:
# zx_graph = g.to_zx_graph()
#
# stats = start_simulation_using_sinter(
# g,
# range(1, 4),
# list(numpy.logspace(-4, -1, 10)),
# NoiseModel.uniform_depolarizing,
# manhattan_radius=2,
# observables=[correlation_surface],
# num_workers=cpu_count(),
# max_shots=1_000_000,
# max_errors=5_000,
# decoders=["pymatching"],
# print_progress=True,
# )
#
# for i, stat in enumerate(stats):
# fig, ax = plt.subplots()
# sinter.plot_error_rate(
# ax=ax,
# stats=stat,
# x_func=lambda stat: stat.json_metadata["p"],
# group_func=lambda stat: stat.json_metadata["d"],
# )
# plot_observable_as_inset(ax, zx_graph, correlation_surface)
# ax.grid(axis="both")
# ax.legend()
# ax.loglog()
# ax.set_title("Logical CNOT Error Rate")
# ax.set_xlabel("Physical Error Rate")
# ax.set_ylabel("Logical Error Rate")
# fig.savefig(SAVE_DIR / f"ghz_result_observable_{i}.png")
#
#
# def main():
# SAVE_DIR.mkdir(exist_ok=True)
# generate_graphs()
#
#
# if __name__ == "__main__":
# main()
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ classifiers = [
"Typing :: Typed",
]
dependencies = [
Comment thread
inmzhang marked this conversation as resolved.
"gen @ git+https://github.com/inmzhang/gen.git",
"matplotlib>=3.9",
"networkx>=3.0",
"numpy>=1.22,<2.3", # Upper bound: https://github.com/tqec/tqec/pull/659
Expand Down
1 change: 1 addition & 0 deletions src/tqec/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
from .computation.block_graph import BlockGraph as BlockGraph
from .utils import Basis as Basis
from .utils import NoiseModel as NoiseModel
from .utils import PauliBasis as PauliBasis
53 changes: 43 additions & 10 deletions src/tqec/compile/blocks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,57 @@
operations happening in parallel should be encoded in the same moment (i.e.,
between the same two ``TICK`` instructions) in the resulting ``.stim`` file.

Moreover, blocks might have different "schedules". For example, the regular
memory block follow the schedule:
This module provides two implementations of the :class:`~tqec.compile.blocks.block.Block`
abstract base class:

1. initialisation layer,
2. repeat [memory layer],
3. measurement layer,
1. **LayeredBlock** - Represents blocks as a sequence of layers that can be instances
of :class:`~tqec.compile.blocks.layers.atomic.base.BaseLayer` or
:class:`~tqec.compile.blocks.layers.composed.base.BaseComposedLayer`. This is the
standard representation for blocks that follow a layer-synchronous schedule.

Note that different blocks may have different schedules. For example, the
regular memory block follows the schedule:

1. initialisation layer,
2. repeat [memory layer],
3. measurement layer,

whereas a spatial pipe in the ``Y`` axis needs to alternate plaquettes in its
repeated layer, leading to a schedule that is:
repeated layer, leading to a schedule that is::

1. initialisation layer,
2. repeat [memory layer 1 alternated with memory layer 2],
3. measurement layer.

Both of these can be represented as LayeredBlock instances.

2. **InjectedBlock** - Represents blocks via direct circuit representation using
:class:`~tqec.compile.blocks.block.CircuitWithInterface`.

1. initialisation layer,
2. repeat [memory layer 1 alternated with memory layer 2],
3. measurement layer.
Block Compilation
==================

In a topological computation, :class:`~tqec.compile.blocks.block.Block` instances
execute in parallel, and ``tqec`` must ensure that operations happening in parallel
are encoded in the same moment (i.e., between the same two ``TICK`` instructions)
in the resulting ``.stim`` file.

For LayeredBlock instances, this is handled by the layer merging system. For
InjectedBlock instances, this is handled by the
:class:`~tqec.compile.tree.injection.InjectionBuilder` which weaves injected
circuits into layer-generated circuits while maintaining correct detector
annotations via flow interfaces from Gidney's gen library.

See Also
========

All these restrictions are handled by representing
:class:`~tqec.compile.blocks.block.Block` instances with
:class:`~tqec.compile.blocks.layers.atomic.base.BaseLayer` and
:class:`~tqec.compile.blocks.layers.composed.base.BaseComposedLayer` instances.
See :mod:`tqec.compile.blocks.layers` for more details.

- See :mod:`tqec.compile.blocks.layers` for more layered block details.
- :mod:`tqec.compile.tree.injection` for injection mechanics
- :mod:`tqec.compile.blocks.enums` for alignment and border enumerations

"""
Loading