Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
7e4c201
Fix #531: Allow empty graphs in check_well_formed
ECZ-Quantum-Labs Jun 10, 2026
c396701
Fix formatting with ruff
ECZ-Quantum-Labs Jun 11, 2026
03f214a
Add test for issue #531: empty graph well-formedness
ECZ-Quantum-Labs Jun 11, 2026
adfbbc5
fix: format test_empty_graph_fix.py
ECZ-Quantum-Labs Jun 11, 2026
831dce7
fix: add type annotations to test_empty_graph_fix.py
ECZ-Quantum-Labs Jun 11, 2026
9de31ea
fix: resolve all lint errors in test_empty_graph_fix.py
ECZ-Quantum-Labs Jun 11, 2026
8a78182
fix: specify generic type argument Any for OpenGraph to pass mypy
ECZ-Quantum-Labs Jun 11, 2026
a89d19b
fix: resolve ruff linting, docstring and import sorting requirements
ECZ-Quantum-Labs Jun 11, 2026
065a20e
fix: comply with ruff docstring and import sorting rules
ECZ-Quantum-Labs Jun 11, 2026
e90509a
fix: generic type hint for opengraph strictly applied
ECZ-Quantum-Labs Jun 11, 2026
b4f8fc7
fix: correct opengraph import syntax error
ECZ-Quantum-Labs Jun 11, 2026
df9cd74
chore: trigger CI rebuild
ECZ-Quantum-Labs Jun 12, 2026
eb341fd
fix: add type argument to OpenGraph
ECZ-Quantum-Labs Jun 12, 2026
a86e539
Fix #531: Allow empty graphs in check_well_formed + add test
ECZ-Quantum-Labs Jun 13, 2026
a953392
fix: add missing future annotations and sort imports for #531
ECZ-Quantum-Labs Jun 15, 2026
5e7e63c
fix: add type annotations and correct imports for mypy compliance
ECZ-Quantum-Labs Jun 16, 2026
6621bf4
fix: add pyright ignore for pytest.approx type checking
ECZ-Quantum-Labs Jun 22, 2026
4196cec
fix: resolve lint and format errors
ECZ-Quantum-Labs Jun 23, 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
7 changes: 6 additions & 1 deletion graphix/flow/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1378,13 +1378,18 @@ def _check_flow_general_properties(flow: PauliFlow[_AM_co]) -> None:
- The nodes in the partial order are the nodes in the open graph.
- The first layer of the partial order layers is :math:`O`, the output nodes of the open graph. This is guaranteed because open graphs without outputs do not have flow.
"""
if len(flow.og.graph.nodes) == 0:
return

if not _check_correction_function_domain(flow.og, flow.correction_function):
raise FlowGenericError(FlowGenericErrorReason.IncorrectCorrectionFunctionDomain)

if not _check_correction_function_image(flow.og, flow.correction_function):
raise FlowGenericError(FlowGenericErrorReason.IncorrectCorrectionFunctionImage)

if len(flow.partial_order_layers) == 0:
if len(flow.partial_order_layers) == 0 and len(flow.og.graph.nodes) > 0:
if not flow.og.graph:
return
raise PartialOrderError(PartialOrderErrorReason.Empty)

first_layer = flow.partial_order_layers[0]
Expand Down
21 changes: 21 additions & 0 deletions tests/test_empty_graph_fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from __future__ import annotations

from typing import TYPE_CHECKING

import networkx as nx

from graphix.opengraph import OpenGraph

if TYPE_CHECKING:
from graphix.measurements import Measurement


def test_empty_graph_well_formed() -> None:
"""Test that empty graphs pass the well-formedness check.

This is a regression test for issue #531.
"""
og: OpenGraph[Measurement] = OpenGraph(graph=nx.Graph(), input_nodes=[], output_nodes=[], measurements={})
pf = og.extract_causal_flow()
pf.check_well_formed()
assert True
18 changes: 18 additions & 0 deletions tests/test_issue_531.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from __future__ import annotations

from typing import Any

import networkx as nx

from graphix.opengraph import OpenGraph


def test_empty_graph() -> None:
og: OpenGraph[Any] = OpenGraph(graph=nx.Graph(), input_nodes=[], output_nodes=[], measurements={})
pf = og.extract_causal_flow()
pf.check_well_formed() # This should NOT raise PartialOrderError anymore
print("✅ Test passed! Empty graph is now well-formed.")


if __name__ == "__main__":
test_empty_graph()
6 changes: 3 additions & 3 deletions tests/test_tnsim.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ def test_with_graphtrans_sequential(self, fx_bg: PCG64, jumps: int, fx_rng: Gene
for qargs in itertools.permutations(input_list):
value1 = state.expectation_value(random_op3, list(qargs))
value2 = tn_mbqc.expectation_value(random_op3, list(qargs))
assert value1 == pytest.approx(value2)
assert value1 == pytest.approx(value2) # pyright: ignore[reportUnknownMemberType]

@pytest.mark.parametrize("jumps", range(1, 11))
def test_coef_state(self, fx_bg: PCG64, jumps: int, fx_rng: Generator) -> None:
Expand All @@ -373,7 +373,7 @@ def test_coef_state(self, fx_bg: PCG64, jumps: int, fx_rng: Generator) -> None:
coef_tn = tn.basis_coefficient(number)
coef_sv = statevec_ref.flatten()[number]

assert abs(coef_tn) == pytest.approx(abs(coef_sv))
assert abs(coef_tn) == pytest.approx(abs(coef_sv)) # pyright: ignore[reportUnknownMemberType]

@pytest.mark.parametrize(("nqubits", "jumps"), itertools.product(range(2, 6), range(1, 6)))
def test_to_statevector(self, fx_bg: PCG64, nqubits: int, jumps: int, fx_rng: Generator) -> None:
Expand Down Expand Up @@ -408,4 +408,4 @@ def test_evolve(self, fx_bg: PCG64, jumps: int, fx_rng: Generator) -> None:
expval_tn = tn_mbqc.expectation_value(random_op3_exp, [0, 1, 2])
expval_ref = state.expectation_value(random_op3_exp, [0, 1, 2])

assert expval_tn == pytest.approx(expval_ref)
assert expval_tn == pytest.approx(expval_ref) # pyright: ignore[reportUnknownMemberType]
Loading