Skip to content
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

Add tests to the library #130

Merged
merged 133 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
133 commits
Select commit Hold shift + click to select a range
71c40b4
✨ Introduced layers
nelimee Feb 1, 2024
53cff06
Merge branch 'main' into qec_movement
nelimee Feb 1, 2024
475b4ff
Merge branch 'QCHackers:main' into qec_movement
nelimee Feb 1, 2024
1264ed5
Merge remote-tracking branch 'refs/remotes/origin/qec_movement' into …
nelimee Feb 1, 2024
0610748
RelativeMeasurementGate origin now optional
nelimee Feb 1, 2024
8d6576f
Added _cirq helper methods to RoundedPlaquette
nelimee Feb 1, 2024
4e8ae2f
Fix a few regressions, see #103
nelimee Feb 1, 2024
8d3ed54
Removed ObservableGate origin from notebooks
nelimee Feb 1, 2024
78ec711
Code factorisation
nelimee Feb 1, 2024
7d3ab05
Implement XXXX->XX and ZZZZ->ZZ plaquettes
nelimee Feb 2, 2024
2746530
✨ Separation Template and AtomicTemplate
nelimee Feb 2, 2024
7e38a0b
✨ Implement expected_plaquettes_number
nelimee Feb 2, 2024
f600f9a
🐛 Fixed TemplateOrchestrator::shape API
nelimee Feb 2, 2024
363cdc9
Merge branch 'main' into qec_movement
nelimee Feb 2, 2024
64aae60
Merge branch 'template_hierarchy_refactor' into qec_movement
nelimee Feb 2, 2024
eb4bc92
🐛 Fixed display_template
nelimee Feb 2, 2024
14f7f73
Merge branch 'template_hierarchy_refactor' into qec_movement
nelimee Feb 2, 2024
c44729e
🎨 TemplateOrchestrator.instanciate behaviour fix
nelimee Feb 2, 2024
205c9fb
Merge branch 'template_hierarchy_refactor' into qec_movement
nelimee Feb 2, 2024
05e72dc
📝 Update typing information on generate_circuit
nelimee Feb 2, 2024
278b4a3
Merge branch 'template_hierarchy_refactor' into qec_movement
nelimee Feb 2, 2024
1744c0c
✨ Introduce TemplateStack
nelimee Feb 2, 2024
8758eb5
📝 BaseLayer can now be constructed from Template
nelimee Feb 2, 2024
796e79d
🎨 Adding XXFromXXXX (and Z equivalent) to library
nelimee Feb 2, 2024
8bb9c77
📝 Initial implementation of movement using layers
nelimee Feb 2, 2024
118ea82
Merge branch 'main' into template_hierarchy_refactor
nelimee Feb 5, 2024
e3acdfa
🏷️ generate_circuit accepts dict[int, Plaquette]
nelimee Feb 5, 2024
521e320
📝 Add default_increment doc to AtomicTemplate
nelimee Feb 5, 2024
fb20627
🐛 Fixed offset bug in generate_circuit
nelimee Feb 5, 2024
a876b9e
🚚 ♻️ TemplateOrchestrator -> ComposedTemplate
nelimee Feb 5, 2024
f58d740
♻️ ✨ Remove BaseShape and refactor Template
nelimee Feb 5, 2024
45b3da2
📝 Update documentation
nelimee Feb 5, 2024
f120d85
🐛 Fix a bug in expected_plaquettes_number
nelimee Feb 5, 2024
d83d5ab
🐛 Allow scale_width=None in get_dimensions
nelimee Feb 5, 2024
39b4a13
🚚 ScalableQubitSquare -> ScalableQubitSquare
nelimee Feb 5, 2024
cb68778
🚚 ScalableQubitRectangle->QubitRectangleTemplate
nelimee Feb 5, 2024
879a590
🐛 📌 Fix a Python 3.9 incompatible code
nelimee Feb 6, 2024
e52f7fa
📝 Remove references to the Shape hierarchy
nelimee Feb 6, 2024
ba09517
Simplify Dimension
nelimee Feb 6, 2024
824b86b
⚰️ Removing unused templates
nelimee Feb 6, 2024
d91ab72
♻️ Arbitraty callable -> LinearFunction
nelimee Feb 6, 2024
a051055
Merge branch 'main' into remove_shape
nelimee Feb 6, 2024
24e0f0a
🎨 Change LinearFunction to frozen dataclass
nelimee Feb 6, 2024
c57452c
Merge branch 'remove_shape' into qec_movement
nelimee Feb 6, 2024
2f35d3c
✨ Add ShiftedTemplate
nelimee Feb 6, 2024
53e19f7
🐛 Freeze a few dataclasses to get __hash__
nelimee Feb 6, 2024
16dcad8
⚰️ Remove top_left_corner from BaseLayer
nelimee Feb 6, 2024
c1c8e52
✨ Remove offset from TemplateStack
nelimee Feb 6, 2024
6beb52d
✨ Implement FixedDimension
nelimee Feb 6, 2024
ba74071
🚚 TemplateStack -> StackedTemplate
nelimee Feb 6, 2024
1f844f6
🐛 Fix order in exception message
nelimee Feb 6, 2024
a08aa00
📝 Fix RoundedPlaquette docstring
nelimee Feb 6, 2024
2dd5759
🐛 Fix get_unused_qubits for RoundedPlaquette
nelimee Feb 6, 2024
e753a4b
🏷️ Update types in notebook
nelimee Feb 6, 2024
303e616
🎨 Improve SHIFT_COORDS management in BaseLayer
nelimee Feb 6, 2024
cb05374
✨ Allow RoundedPlaquette to use "unused" qubits
nelimee Feb 6, 2024
c62ddf3
🐛 Fix bug in ZZFromZZZZPlaquette
nelimee Feb 6, 2024
e0d6e4e
Merge branch 'main' into remove_shape
nelimee Feb 7, 2024
2732efe
🚚 instanciate -> instantiate
nelimee Feb 7, 2024
498650b
🐛 Fix bad merging in notebook
nelimee Feb 7, 2024
7045c7a
✨ Introduce FixedDimension
nelimee Feb 7, 2024
54eccfc
📝 Remove notebook outputs
nelimee Feb 7, 2024
1cecd93
📝 Update movement notebook to AtomicTemplate
nelimee Feb 7, 2024
e58fc67
✨ RawRectangleTemplate raises for illegal input
nelimee Feb 7, 2024
6ba8f2b
✅ Add tests to scale and atomic.rectangle
nelimee Feb 7, 2024
012fcaa
Merge branch 'main' into remove_shape
nelimee Feb 7, 2024
4692d73
✅ Add AlternatingSquareTemplate tests
nelimee Feb 7, 2024
9a1eaef
📝 Improve documentation
nelimee Feb 7, 2024
e3375e7
📝Added warning to AlternatingCornerSquareTemplate
nelimee Feb 7, 2024
33dfde9
📝 Update documentation
nelimee Feb 7, 2024
a5fa80d
🎨 Use FixedDimension instead of raw Dimension
nelimee Feb 7, 2024
1dde1b7
Merge branch 'main' into remove_shape
nelimee Feb 7, 2024
43dc20e
📝 Improve documentation
nelimee Feb 7, 2024
36d5adb
📝 Logical qubit movement Z notebook
nelimee Feb 7, 2024
97bd184
📝 Logical qubit movement Z notebook
nelimee Feb 7, 2024
e59c383
Merge remote-tracking branch 'refs/remotes/origin/qec_movement' into …
nelimee Feb 7, 2024
eaba7e1
Remove unreachable code
nelimee Feb 8, 2024
8c96fa8
Merge branch 'main' into remove_shape
nelimee Feb 8, 2024
a5d8bc0
Merge branch 'remove_shape' into qec_movement
nelimee Feb 8, 2024
88df7b9
♻️ Change slightly CircuitMeasurementMap API
nelimee Feb 8, 2024
0673973
Merge branch 'fix_measurement_map_raising' into unit_testing
nelimee Feb 8, 2024
3702fa5
Raise an exception if wrong current_moment_index
nelimee Feb 8, 2024
2f0231d
relative offset getter considers current moment
nelimee Feb 8, 2024
8edf742
Merge branch 'fix_measurement_map_raising' into unit_testing
nelimee Feb 8, 2024
842dbc7
✅ Add tests
nelimee Feb 8, 2024
c5b4c83
➕ Add pytest-cov in testing dependencies
nelimee Feb 8, 2024
aa37713
Merge branch 'main' into qec_movement
nelimee Feb 9, 2024
b0d958e
Merge branch 'qec_movement' into unit_testing
nelimee Feb 9, 2024
5f76b4c
✨ Add PlaquetteSide enumeration
nelimee Feb 14, 2024
7b5c140
🎨 Use of PlaquetteSide in SquarePlaquette
nelimee Feb 14, 2024
fb1b51e
🐛 SquarePlaquette.origin == (0, 0)
nelimee Feb 14, 2024
c59cf76
🎨 Plaquette hierarchy rework
nelimee Feb 14, 2024
53931ef
🐛 Fix type issue in SquarePlaquette
nelimee Feb 15, 2024
680a661
🎨 Update plaquette implementation
nelimee Feb 15, 2024
ce1f3dd
✨ Introduced initialisation plaquettes
nelimee Feb 15, 2024
d101933
Update __init__.py
nelimee Feb 15, 2024
ce08573
🎨 Improve MeasurementMap error reporting
nelimee Feb 15, 2024
cd20679
♻️ Simplified initialisation.py implementations
nelimee Feb 15, 2024
51659ee
✨ Add __repr__ to operation.py for debugging
nelimee Feb 15, 2024
d42a4b4
🐛 Various fixes on new Plaquette implementation
nelimee Feb 15, 2024
969689c
Update logical qubit memory notebook
nelimee Feb 15, 2024
aeae860
📝 Remove unused import
nelimee Feb 15, 2024
5d4e90e
📝 Update extended memory experiment
nelimee Feb 15, 2024
a7e763d
Merge branch 'main' into refactor_plaquette_hierarchy
nelimee Feb 21, 2024
13b9c1d
🚚 X{,Square}InitialisationPlaquette
nelimee Feb 21, 2024
326777a
✅ circuit_test fix
nelimee Feb 21, 2024
0330441
✅ Fix circuit_test
nelimee Feb 21, 2024
06e3b67
✅ from __future__ import annotations
nelimee Feb 21, 2024
193b922
🐛 Fix bug with _check_plaquette_number
nelimee Feb 21, 2024
327b303
✨ Add empty plaquettes
nelimee Feb 21, 2024
50a4090
📝 Update notebook moving qubit
nelimee Feb 22, 2024
8199fe6
Merge branch 'main' into refactor_plaquette_hierarchy
nelimee Feb 22, 2024
01f9130
♻️ Refactor measurement plaquettes
nelimee Feb 24, 2024
12b59b2
Merge branch 'main' into refactor_plaquette_hierarchy
nelimee Feb 24, 2024
07d4585
Merge branch 'refactor_plaquette_hierarchy' into unit_testing
nelimee Feb 24, 2024
73921d0
⚰️ Remove PlaquetteList from imports
nelimee Feb 24, 2024
e7234be
🧪 Fix empty_shift_coords test
nelimee Feb 24, 2024
496d804
✅ Fix stack and shifted template tests
nelimee Feb 24, 2024
e7871ac
Merge branch 'main' into unit_testing
nelimee Feb 28, 2024
94d946c
🚨 Fix import in _version.py
nelimee Feb 28, 2024
c0b0a45
🚨 Adding 2 #type: ignore for linter
nelimee Feb 28, 2024
770831f
⚰️ Removing layer-related code
nelimee Feb 28, 2024
5da16fc
⚰️ Removing unused notebook code
nelimee Feb 28, 2024
f8be0d4
⚰️ Remove AtomicTemplate
nelimee Feb 28, 2024
59acddf
⚰️ Remove unused topology.py
nelimee Feb 28, 2024
3725e2c
🐛 Raise exception on some generate_circuit input
nelimee Feb 28, 2024
2f926c8
✅ Add tests
nelimee Feb 28, 2024
1c04f79
Merge branch 'main' into unit_testing
nelimee Mar 1, 2024
0c4169a
✅ Add PlaquetteQubit tests
nelimee Mar 1, 2024
d3f6ecb
✨ Improve error reporting on TemplateWithIndices
nelimee Mar 1, 2024
d0968fe
✅ Add TemplateWithIndices tests
nelimee Mar 1, 2024
d0fe1fb
🐛 Fix a crash on ComposedTemplate
nelimee Mar 1, 2024
0db3f8f
✅ Add a few ComposedTemplate tests
nelimee Mar 1, 2024
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Repository = "https://github.com/QCHackers/tqec"
Issues = "https://github.com/QCHackers/tqec/issues"

[project.optional-dependencies]
test = ["pytest", "mypy"]
test = ["pytest", "mypy", "pytest-cov"]
dev = ["sinter", "pymatching", "jupyterlab", "tqec[test]"]
all = ["tqec[test, dev]"]

Expand Down
2 changes: 1 addition & 1 deletion src/tqec/_version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import importlib
import importlib.metadata

__version__ = importlib.metadata.version("tqec")
13 changes: 10 additions & 3 deletions src/tqec/circuit/circuit.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import typing as ty
from copy import deepcopy

import cirq
Expand Down Expand Up @@ -34,22 +35,28 @@ def generate_circuit(
we want to implement.
plaquettes: description of the computation that should happen at
different time-slices of the quantum error correction experiment (or
at least part of it).
at least part of it). If provided as a dictionary, plaquettes should be
1-indexed (i.e., ``0 not in plaquettes`` should be ``True``).

Returns:
a cirq.Circuit instance implementing the (part of) quantum error
correction experiment represented by the provided inputs.

Raises:
TQECException: if the provided plaquettes do not match the expected
number of plaquettes for the given template.
TQECException: if ``len(plaquettes) != template.expected_plaquettes_number`` or
if plaquettes is provided as a dicitonary and ``0 in plaquettes``.
"""
# Check that the user gave enough plaquettes.
if len(plaquettes) != template.expected_plaquettes_number:
raise TQECException(
f"{len(plaquettes)} plaquettes have been provided, but "
f"{template.expected_plaquettes_number} were expected."
)
if isinstance(plaquettes, ty.Mapping) and 0 in plaquettes:
raise TQECException(
"If using a dictionary, the input plaquettes parameter should not "
f"contain the entry 0. Found a value ({plaquettes[0]}) at entry 0."
)

# If plaquettes are given as a list, make that a dict to simplify the following operations
if isinstance(plaquettes, list):
Expand Down
208 changes: 41 additions & 167 deletions src/tqec/circuit/circuit_test.py
Original file line number Diff line number Diff line change
@@ -1,181 +1,55 @@
"""Example taken from /notebooks/logical_qubit_memory_experiment.ipynb"""

import cirq
import pytest

from tqec.circuit.circuit import generate_circuit
from tqec.circuit.operations.operation import make_shift_coords
from tqec.enums import PlaquetteOrientation
from tqec.plaquette.library import (
MeasurementRoundedPlaquette,
MeasurementSquarePlaquette,
XXMemoryPlaquette,
XXXXMemoryPlaquette,
ZRoundedInitialisationPlaquette,
ZSquareInitialisationPlaquette,
ZZMemoryPlaquette,
ZZZZMemoryPlaquette,
)
from tqec.exceptions import TQECException
from tqec.plaquette.library import ZSquareInitialisationPlaquette
from tqec.plaquette.plaquette import Plaquette
from tqec.templates.constructions.qubit import QubitSquareTemplate
from tqec.templates.scale import Dimension, LinearFunction
from tqec.templates.atomic.rectangle import RawRectangleTemplate
from tqec.templates.base import Template


def _normalise_circuit(norm_circuit: cirq.Circuit) -> cirq.Circuit:
ordered_transformers = [
cirq.drop_empty_moments,
]
for transformer in ordered_transformers:
norm_circuit = transformer(norm_circuit)
return norm_circuit
@pytest.fixture
def initialisation_plaquette() -> Plaquette:
return ZSquareInitialisationPlaquette()


def _make_repeated_layer(repeat_circuit: cirq.Circuit) -> cirq.Circuit:
# Note: we do not care on which qubit it is applied, but we want a SHIFT_COORDS instruction
# to be inserted somewhere in the repetition loop. It is inserted at the beginning.
any_qubit = next(iter(repeat_circuit.all_qubits()), None)
assert (
any_qubit is not None
), "Could not find any qubit in the given Circuit instance."
circuit_to_repeat = cirq.Circuit([make_shift_coords(0, 0, 1)]) + repeat_circuit
repeated_circuit_operation = cirq.CircuitOperation(
circuit_to_repeat.freeze()
).repeat(9)
return cirq.Circuit([repeated_circuit_operation])
@pytest.fixture
def one_by_one_template() -> Template:
return RawRectangleTemplate([[0]])


def _generate_circuit() -> cirq.Circuit:
template = QubitSquareTemplate(Dimension(2, LinearFunction(2)))
plaquettes: list[list[Plaquette]] = [
[
ZRoundedInitialisationPlaquette(PlaquetteOrientation.UP),
XXMemoryPlaquette(
PlaquetteOrientation.UP,
[1, 2, 5, 6, 7, 8],
include_detector=False,
is_first_round=True,
),
XXMemoryPlaquette(PlaquetteOrientation.UP, [1, 2, 5, 6, 7, 8]),
MeasurementRoundedPlaquette(
PlaquetteOrientation.UP, include_detector=False
),
],
[
ZRoundedInitialisationPlaquette(PlaquetteOrientation.LEFT),
ZZMemoryPlaquette(
PlaquetteOrientation.LEFT, [1, 5, 6, 8], is_first_round=True
),
ZZMemoryPlaquette(PlaquetteOrientation.LEFT, [1, 5, 6, 8]),
MeasurementRoundedPlaquette(PlaquetteOrientation.LEFT),
],
[
ZSquareInitialisationPlaquette(),
XXXXMemoryPlaquette(
[1, 2, 3, 4, 5, 6, 7, 8], include_detector=False, is_first_round=True
),
XXXXMemoryPlaquette([1, 2, 3, 4, 5, 6, 7, 8]),
MeasurementSquarePlaquette(include_detector=False),
],
[
ZSquareInitialisationPlaquette(),
ZZZZMemoryPlaquette([1, 3, 4, 5, 6, 8], is_first_round=True),
ZZZZMemoryPlaquette([1, 3, 4, 5, 6, 8]),
MeasurementSquarePlaquette(),
],
[
ZRoundedInitialisationPlaquette(PlaquetteOrientation.RIGHT),
ZZMemoryPlaquette(
PlaquetteOrientation.RIGHT, [1, 3, 4, 8], is_first_round=True
),
ZZMemoryPlaquette(PlaquetteOrientation.RIGHT, [1, 3, 4, 8]),
MeasurementRoundedPlaquette(PlaquetteOrientation.RIGHT),
],
[
ZRoundedInitialisationPlaquette(PlaquetteOrientation.DOWN),
XXMemoryPlaquette(
PlaquetteOrientation.DOWN,
[1, 2, 3, 4, 7, 8],
include_detector=False,
is_first_round=True,
),
XXMemoryPlaquette(PlaquetteOrientation.DOWN, [1, 2, 3, 4, 7, 8]),
MeasurementRoundedPlaquette(
PlaquetteOrientation.DOWN, include_detector=False
),
],
]
layer_modificators = {1: _make_repeated_layer}
def test_generate_initialisation_circuit_list(
initialisation_plaquette: Plaquette, one_by_one_template
):
circuit = generate_circuit(one_by_one_template, [initialisation_plaquette])
assert circuit == cirq.Circuit(
cirq.R(q.to_grid_qubit()) for q in initialisation_plaquette.qubits
)

# 4. Actually create the cirq.Circuit instance by concatenating the circuits generated
# for each layers and potentially modified by the modifiers defined above.
circuit = cirq.Circuit()
for layer_index in range(4):
layer_circuit = generate_circuit(
template,
[plaquette_list[layer_index] for plaquette_list in plaquettes],
)
layer_circuit = _normalise_circuit(layer_circuit)
circuit += layer_modificators.get(layer_index, lambda circ: circ)(layer_circuit)

return circuit
def test_generate_initialisation_circuit_dict(
initialisation_plaquette: Plaquette, one_by_one_template
):
circuit = generate_circuit(one_by_one_template, {1: initialisation_plaquette})
assert circuit == cirq.Circuit(
cirq.R(q.to_grid_qubit()) for q in initialisation_plaquette.qubits
)


def test_generate_initialisation_circuit_dict_0_indexed(
initialisation_plaquette: Plaquette, one_by_one_template
):
with pytest.raises(TQECException):
generate_circuit(one_by_one_template, {0: initialisation_plaquette})

def test_generate_circuit():
"""Minimal test to check that the circuit is generated correctly
The target qubits are taken from the orginal notebook output.
"""
generated_circuit = _generate_circuit()
generate_qubits = [(q.row, q.col) for q in generated_circuit.all_qubits()]
target_qubits = [
(6, 2),
(3, 7),
(3, 9),
(1, 1),
(10, 6),
(8, 8),
(1, 5),
(2, 0),
(6, 4),
(2, 2),
(6, 6),
(1, 3),
(7, 1),
(7, 3),
(4, 2),
(1, 7),
(7, 5),
(1, 9),
(7, 7),
(2, 4),
(6, 8),
(9, 1),
(2, 6),
(9, 3),
(9, 7),
(4, 6),
(4, 4),
(7, 9),
(5, 1),
(5, 3),
(2, 8),
(9, 5),
(5, 7),
(8, 2),
(0, 4),
(9, 9),
(3, 1),
(4, 8),
(5, 5),
(3, 3),
(4, 10),
(3, 5),
(10, 2),
(8, 4),
(5, 9),
(8, 6),
(0, 8),
(6, 0),
(8, 10),
]
generate_qubits.sort()
target_qubits.sort()
assert generate_qubits == target_qubits

def test_generate_circuit_wrong_number_of_plaquettes(
initialisation_plaquette: Plaquette, one_by_one_template
):
with pytest.raises(TQECException):
generate_circuit(
one_by_one_template, [initialisation_plaquette, initialisation_plaquette]
)
with pytest.raises(TQECException):
generate_circuit(one_by_one_template, [])
Loading
Loading