Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- #512: Method `Circuit.simulate_statevector` accepts a `backend: DenseStateBackend[_DenseStateT] | Literal["statevector", "densitymatrix"]` parameter.

- #557: Homogeneize namespace. See commit text or COMPATIBILITY.md for a detailed renaming list. Fixed the following convention:
- `.to_<object>` for transformations that can only return `object` or raise an exception. Equivalently, we use `.from_<object>` for constructors.
- `.to_<object>_or_none` for transformations that can return `object` or `None`. Equivalently, we use `.from_<object>_or_none` for constructors.
- accessor methods use nouns instead of verb + noun. Example: `Pattern.max_degree` instead of `Pattern.compute_max_degree`.

## [0.3.5] - 2026-03-26

### Added
Expand Down
57 changes: 57 additions & 0 deletions COMPATIBILITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Backwards compatibility

Graphix does not guarantee backwards compatibility between 0.x version releases. Here we list API changes which may break existing code using Graphix.

## Unreleased

- #557: Namespace homogenisation.

The following methods and classes have been renamed to provide a homogeneous, consistent and pythonic naming convention:

| Old | New |
|---|---|
| `Pattern.extract_opengraph` | `Pattern.to_opengraph` |
| `Pattern.extract_xzcorrections` | `Pattern.to_xzcorrections` |
| `Pattern.extract_causal_flow` | `Pattern.to_causalflow` |
| `Pattern.extract_gflow` | `Pattern.to_gflow` |
| `Pattern.extract_pauli_flow` | `Pattern.to_pauliflow` |
| `Pattern.extract_signals` | `Pattern.signals` |
| `Pattern.extract_partial_order_layers` | `Pattern.partial_order_layers` |
| `Pattern.extract_measurement_commands` | `Pattern.measurement_commands` |
| `Pattern.compute_max_degree` | `Pattern.max_degree` |
| `Pattern.extract_graph` | `Pattern.graph` |
| `Pattern.extract_nodes` | `Pattern.nodes` |
| `Pattern.extract_isolated_nodes` | `Pattern.isolated_nodes` |
| `Pattern.extract_clifford` | `Pattern.clifford_commands` |
| `StandardizedPattern.extract_opengraph` | `StandardizedPattern.to_opengraph` |
| `StandardizedPattern.extract_xzcorrections` | `StandardizedPattern.to_xzcorrections` |
| `XZCorrections.to_causal_flow` | `XZCorrections.to_causalflow` |
| `XZCorrections.to_pauli_flow` | `XZCorrections.to_pauliflow` |
| `XZCorrections.extract_dag` | `XZCorrections.to_dag` |
| `PauliFlow.try_from_correction_matrix` | `PauliFlow.from_correctionmatrix_or_none` |
| `PauliFlow.to_corrections` | `PauliFlow.to_xzcorrections` |
| `GFlow.to_corrections` | `GFlow.to_xzcorrections` |
| `CausalFlow.to_corrections` | `CausalFlow.to_xzcorrections` |
| `State.to_statevector` | `State.to_statevector_numpy` |
| `State.to_densitymatrix` | `State.to_densitymatrix_numpy` |
| `Opengraph.extract_causal_flow` | `Opengraph.to_causal_flow` |
| `Opengraph.extract_gflow` | `Opengraph.to_gflow` |
| `Opengraph.extract_pauli_flow` | `Opengraph.to_pauliflow` |
| `OpenGraph.extract_circuit` | `Opengraph.to_circuit` |
| `Opengraph.find_causal_flow` | `Opengraph.to_causalflow_or_none` |
| `Opengraph.find_gflow` | `Opengraph.to_gflow_or_none` |
| `Opengraph.find_pauli_flow` | `Opengraph.to_pauliflow_or_none` |
| `Noise.to_kraus_channel` | `Noise.to_krauschannel` |
| `<...>.to_standardized_pattern` | `<...>.to_standardizedpattern` |
| `<...>.from_standardized_pattern` | `<...>.from_standardizedpattern` |
| `Measurement.try_to_pauli` | `Measurement.to_pauli_or_none` |
| `ComplexUnit.try_from` | `ComplexUnit.from_or_none` |
| `MatGF2.compute_rank` | `MatGF2.rank` |
| `Statevec` | `Statevector` |







2 changes: 1 addition & 1 deletion benchmarks/statevec.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def simple_random_circuit(nqubit, depth):
pattern = circuit.transpile()
pattern.standardize()
pattern.minimize_space()
nqubit = len(pattern.extract_nodes())
nqubit = len(pattern.nodes())
start = perf_counter()
pattern.simulate_pattern(max_qubit_num=30)
end = perf_counter()
Expand Down
2 changes: 1 addition & 1 deletion docs/source/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ Note that the input state has *teleported* to qubits 6 and 7 after the computati
og = OpenGraph(nx.Graph([0, 1]), output_nodes=[0, 1])
>>> print(og.to_pattern().simulate_pattern())
Statevec object with statevector [[ 0.5+0.j 0.5+0.j]
Statevector object with statevector [[ 0.5+0.j 0.5+0.j]
[ 0.5+0.j -0.5+0.j]] and length (2, 2).


Expand Down
2 changes: 1 addition & 1 deletion docs/source/lc-mbqc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ For example, let us try the transformation rules in Elliot *et al.* [#el]_ with
:alt: Pauli measurement of graph


We can perform this with :class:`~graphix.graphsim.GraphState` class and then compare to the :class:`~graphix.sim.statevec.Statevec` full statevector simulation:
We can perform this with :class:`~graphix.graphsim.GraphState` class and then compare to the :class:`~graphix.sim.statevec.Statevector` full statevector simulation:

.. code-block:: python

Expand Down
14 changes: 7 additions & 7 deletions docs/source/modifier.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Pattern Manipulation

.. automethod:: simulate_pattern

.. automethod:: compute_max_degree
.. automethod:: max_degree

.. automethod:: compose

Expand All @@ -50,17 +50,17 @@ Pattern Manipulation

.. automethod:: is_standard

.. automethod:: extract_graph
.. automethod:: graph

.. automethod:: extract_nodes
.. automethod:: nodes

.. automethod:: extract_causal_flow
.. automethod:: to_causalflow

.. automethod:: extract_gflow
.. automethod:: to_gflow

.. automethod:: extract_opengraph
.. automethod:: to_opengraph

.. automethod:: extract_measurement_commands
.. automethod:: measurement_commands

.. automethod:: parallelize_pattern

Expand Down
2 changes: 1 addition & 1 deletion docs/source/simulator.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Statevector
.. autoclass:: StatevectorBackend
:members:

.. autoclass:: Statevec
.. autoclass:: Statevector
:members:

Density Matrix
Expand Down
6 changes: 3 additions & 3 deletions docs/source/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ We can use the :class:`~graphix.simulator.PatternSimulator` to classically simul
Alternatively, we can simply call :meth:`~graphix.pattern.Pattern.simulate_pattern` of :class:`~graphix.pattern.Pattern` object to do it in one line:

>>> print(pattern.simulate_pattern(backend='statevector'))
Statevec object with statevector [1.+0.j 0.+0.j] and length (2,).
Statevector object with statevector [1.+0.j 0.+0.j] and length (2,).

Note again that we started with :math:`|+\rangle` state so the answer is correct.

Expand Down Expand Up @@ -157,7 +157,7 @@ This reveals the graph structure of the resource state which we can inspect:
.. code-block:: python

import networkx as nx
graph = pattern.extract_graph()
graph = pattern.graph()
pos = {0: (0, 0), 1: (0, -0.5), 2: (1, 0), 3: (4, 0), 4: (1, -0.5), 5: (2, -0.5), 6: (3, -0.5), 7: (4, -0.5)}
graph_params = {'node_size': 240, 'node_color': 'w', 'edgecolors': 'k', 'with_labels': True}
nx.draw(graph, pos=pos, **graph_params)
Expand Down Expand Up @@ -269,7 +269,7 @@ In the following example, we apply dephasing noise to qubit preparation commands
return 1

@typing_extensions.override
def to_kraus_channel(self) -> KrausChannel:
def to_krauschannel(self) -> KrausChannel:
return dephasing_channel(self.prob)

@dataclass
Expand Down
2 changes: 1 addition & 1 deletion examples/fusion_extraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

# %%
# Here we say we want a graph state with 9 nodes and 12 edges.
# We can obtain resource graph for a measurement pattern by using :code:`pattern.extract_graph()`.
# We can obtain resource graph for a measurement pattern by using :code:`pattern.graph()`.
gs = Graph()
nodes = [0, 1, 2, 3, 4, 5, 6, 7, 8]
edges = [(0, 1), (1, 2), (2, 3), (3, 0), (3, 4), (0, 5), (4, 5), (5, 6), (6, 7), (7, 0), (7, 8), (8, 1)]
Expand Down
2 changes: 1 addition & 1 deletion examples/ghz_with_tn.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
pattern = circuit.transpile().pattern
pattern.standardize()

graph = pattern.extract_graph()
graph = pattern.graph()
print(f"Number of nodes: {len(graph.nodes)}")
print(f"Number of edges: {len(graph.edges)}")
pos = nx.spring_layout(graph)
Expand Down
2 changes: 1 addition & 1 deletion examples/qft_with_tn.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def qft(circuit: Circuit, n: int) -> None:
pattern = circuit.transpile().pattern
pattern.standardize()
pattern.shift_signals()
graph = pattern.extract_graph()
graph = pattern.graph()
print(f"Number of nodes: {len(graph.nodes)}")
print(f"Number of edges: {len(graph.edges)}")

Expand Down
6 changes: 3 additions & 3 deletions examples/rotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@

import numpy as np

from graphix import Circuit, Statevec
from graphix import Circuit, Statevector
from graphix.ops import Ops
from graphix.states import BasicStates

rng = np.random.default_rng()

# %%
# Here, :class:`~graphix.sim.statevec.Statevec` is our simple statevector simulator class.
# Here, :class:`~graphix.sim.statevec.Statevector` is our simple statevector simulator class.
# Next, let us define the problem with a standard quantum circuit.
# Note that in graphix all qubits starts in ``|+>`` states. For this example,
# we use Hadamard gate (:meth:`graphix.transpiler.Circuit.h`) to start with ``|0>`` states instead.
Expand Down Expand Up @@ -74,7 +74,7 @@
# %%
# Let us compare with statevector simulation of the original circuit:

state = Statevec(nqubit=2, data=BasicStates.ZERO) # starts with |0> states
state = Statevector(nqubit=2, data=BasicStates.ZERO) # starts with |0> states
state.evolve_single(Ops.rx(theta[0]), 0)
state.evolve_single(Ops.rx(theta[1]), 1)
print("overlap of states: ", np.abs(np.dot(state.psi.flatten().conjugate(), out_state.psi.flatten())))
Expand Down
2 changes: 1 addition & 1 deletion examples/tn_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def ansatz(
# %%
# Print some properties of the graph.

graph = pattern.extract_graph()
graph = pattern.graph()
print(f"Number of nodes: {len(graph.nodes)}")
print(f"Number of edges: {len(graph.edges)}")

Expand Down
2 changes: 1 addition & 1 deletion examples/visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
3: Measurement.YZ(0),
}
og = OpenGraph(graph, inputs, outputs, measurements)
cf = og.extract_gflow()
cf = og.to_gflow()
cf.draw(measurement_labels=True)

# %%
4 changes: 2 additions & 2 deletions graphix/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from graphix.pattern import DrawPatternAnnotations, Pattern
from graphix.pauli import Pauli
from graphix.pretty_print import OutputFormat
from graphix.sim import DensityMatrix, DensityMatrixBackend, Statevec, StatevectorBackend
from graphix.sim import DensityMatrix, DensityMatrixBackend, Statevector, StatevectorBackend
from graphix.space_minimization import SpaceMinimizationHeuristics
from graphix.states import BasicStates, PlanarState
from graphix.transpiler import Circuit
Expand Down Expand Up @@ -64,7 +64,7 @@
"Sign",
"SpaceMinimizationHeuristics",
"StandardizedPattern",
"Statevec",
"Statevector",
"StatevectorBackend",
"XZCorrections",
"__version__",
Expand Down
4 changes: 2 additions & 2 deletions graphix/_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def mat_mul(self, other: MatGF2 | npt.NDArray[np.uint8]) -> MatGF2:

return MatGF2(_mat_mul_jit(np.ascontiguousarray(self), np.ascontiguousarray(other)), copy=False)

def compute_rank(self) -> np.intp:
def rank(self) -> np.intp:
"""Get the rank of the matrix.

Returns
Expand Down Expand Up @@ -100,7 +100,7 @@ def right_inverse(self) -> MatGF2 | None:
red = aug.row_reduction(ncols=n, copy=False) # Reduced row echelon form

# Check that rank of right block is equal to the number of rows.
# We don't use `MatGF2.compute_rank()` to avoid row-reducing twice.
# We don't use `MatGF2.rank()` to avoid row-reducing twice.
if m != np.count_nonzero(red[:, :n].any(axis=1)):
return None
rinv = np.zeros((n, m), dtype=np.uint8).view(MatGF2)
Expand Down
2 changes: 1 addition & 1 deletion graphix/circ_ext/extraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ def clifford_x_map_from_focused_flow(flow: PauliFlow[Measurement]) -> tuple[Paul
og_extended, ancillary_inputs_map = extend_input(og)

# Here it's crucial to not infer Pauli measurements to avoid converting measurements inadvertently.
flow_extended = og_extended.extract_pauli_flow()
flow_extended = og_extended.to_pauliflow()

# `flow_extended` is guaranteed to be focused if `flow` is focused.
# This function assumes that `flow` is focused and does not check it.
Expand Down
Loading
Loading