Skip to content

Commit 719780d

Browse files
matulniEmlyn Graham
authored andcommitted
Refactor of flow tools - OpenGraph.compose (#375)
This commit adapts the existing method `:func: OpenGraph.compose` to the new API introduced in #358.
1 parent 347e312 commit 719780d

File tree

3 files changed

+292
-229
lines changed

3 files changed

+292
-229
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## Unreleased
99

1010
### Added
11-
- #347:
11+
- #374:
1212
- Introduced new method `graphix.opengraph.OpenGraph.is_equal_structurally` which compares the underlying structure of two open graphs.
1313
- Added new method `isclose` to `graphix.fundamentals.AbstractMeasurement` which defaults to `==` comparison.
1414

1515
### Fixed
1616

1717
### Changed
18+
- #374: Adapted existing method `graphix.opengraph.OpenGraph.isclose` to the new API introduced in #358.
19+
- #375: Adapted existing method `graphix.opengraph.OpenGraph.compose` to the new API introduced in #358.
1820

1921
## [0.3.3] - 2025-10-23
2022

21-
- #347: Adapted existing method `graphix.opengraph.OpenGraph.isclose` to the new API introduced in #358.
2223
### Added
2324

2425
- #343: Circuit exporter to OpenQASM3:

graphix/opengraph.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -360,25 +360,22 @@ def find_pauli_flow(self: OpenGraph[_M_co]) -> PauliFlow[_M_co] | None:
360360
correction_matrix
361361
) # The constructor returns `None` if the correction matrix is not compatible with any partial order on the open graph.
362362

363-
# TODO: Generalise `compose` to any type of OpenGraph
364-
def compose(
365-
self: OpenGraph[Measurement], other: OpenGraph[Measurement], mapping: Mapping[int, int]
366-
) -> tuple[OpenGraph[Measurement], dict[int, int]]:
367-
r"""Compose two open graphs by merging subsets of nodes from `self` and `other`, and relabeling the nodes of `other` that were not merged.
363+
def compose(self, other: OpenGraph[_M_co], mapping: Mapping[int, int]) -> tuple[OpenGraph[_M_co], dict[int, int]]:
364+
r"""Compose two open graphs by merging subsets of nodes from ``self`` and ``other``, and relabeling the nodes of ``other`` that were not merged.
368365
369366
Parameters
370367
----------
371-
other : OpenGraph
372-
Open graph to be composed with `self`.
368+
other : OpenGraph[_M_co]
369+
Open graph to be composed with ``self``.
373370
mapping: dict[int, int]
374-
Partial relabelling of the nodes in `other`, with `keys` and `values` denoting the old and new node labels, respectively.
371+
Partial relabelling of the nodes in ``other``, with ``keys`` and ``values`` denoting the old and new node labels, respectively.
375372
376373
Returns
377374
-------
378-
og: OpenGraph
379-
composed open graph
375+
og: OpenGraph[_M_co]
376+
Composed open graph.
380377
mapping_complete: dict[int, int]
381-
Complete relabelling of the nodes in `other`, with `keys` and `values` denoting the old and new node label, respectively.
378+
Complete relabelling of the nodes in ``other``, with ``keys`` and ``values`` denoting the old and new node label, respectively.
382379
383380
Notes
384381
-----
@@ -399,13 +396,14 @@ def compose(
399396
raise ValueError("Keys of mapping must be correspond to nodes of other.")
400397
if len(mapping) != len(set(mapping.values())):
401398
raise ValueError("Values in mapping contain duplicates.")
399+
402400
for v, u in mapping.items():
403401
if (
404402
(vm := other.measurements.get(v)) is not None
405403
and (um := self.measurements.get(u)) is not None
406404
and not vm.isclose(um)
407405
):
408-
raise ValueError(f"Attempted to merge nodes {v}:{u} but have different measurements")
406+
raise OpenGraphError(f"Attempted to merge nodes with different measurements: {v, vm} -> {u, um}.")
409407

410408
shift = max(*self.graph.nodes, *mapping.values()) + 1
411409

0 commit comments

Comments
 (0)