graphix package¶
Subpackages¶
- graphix.circ_ext package
- graphix.flow package
- Submodules
- graphix.flow.core module
- graphix.flow.exceptions module
FlowPropositionErrorReasonFlowPropositionOrderErrorReasonFlowGenericErrorReasonXZCorrectionsOrderErrorReasonXZCorrectionsGenericErrorReasonPartialOrderErrorReasonPartialOrderLayerErrorReasonFlowErrorXZCorrectionsErrorFlowPropositionErrorFlowPropositionOrderErrorFlowGenericErrorPartialOrderErrorPartialOrderLayerErrorXZCorrectionsOrderErrorXZCorrectionsGenericError
- Module contents
- Submodules
- graphix.noise_models package
- Submodules
- Module contents
- graphix.sim package
- Submodules
- Module contents
BackendDensityMatrixDensityMatrix.__init__()DensityMatrix.rhoDensityMatrix.nqubitDensityMatrix.draw()DensityMatrix.add_nodes()DensityMatrix.evolve_single()DensityMatrix.evolve()DensityMatrix.expectation_single()DensityMatrix.dims()DensityMatrix.tensor()DensityMatrix.cnot()DensityMatrix.swap()DensityMatrix.permute()DensityMatrix.entangle()DensityMatrix.normalize()DensityMatrix.remove_qubit()DensityMatrix.ptrace()DensityMatrix.fidelity()DensityMatrix.flatten()DensityMatrix.apply_channel()DensityMatrix.apply_noise()DensityMatrix.replace_parameter()DensityMatrix.replace_parameters()
DensityMatrixBackendMBQCTensorNetMBQCTensorNet.__init__()MBQCTensorNet.open_tensor()MBQCTensorNet.add_qubit()MBQCTensorNet.evolve_single()MBQCTensorNet.add_qubits()MBQCTensorNet.measure_single()MBQCTensorNet.prepare_graph_state()MBQCTensorNet.basis_coefficient()MBQCTensorNet.basis_amplitude()MBQCTensorNet.to_statevector()MBQCTensorNet.flatten()MBQCTensorNet.norm()MBQCTensorNet.expectation_value()MBQCTensorNet.evolve()MBQCTensorNet.copy()
StatevectorStatevector._psiStatevector._nqubitStatevector._max_qubitsStatevector.__init__()Statevector.psiStatevector.nqubitStatevector.max_qubitsStatevector.ensure_capacity()Statevector.flatten()Statevector.add_nodes()Statevector.entangle()Statevector.evolve_single()Statevector.expectation_single()Statevector.evolve()Statevector.expectation_value()Statevector.remove_qubit()Statevector.project_qubit()Statevector.swap()Statevector.tensor()Statevector.permute()Statevector.fidelity()Statevector.isclose()Statevector.to_dict()Statevector.to_prob_dict()Statevector.draw()
StatevectorBackendTensorNetworkBackend
Submodules¶
- graphix.branch_selector module
- graphix.channels module
- graphix.clifford module
- graphix.command module
- graphix.extraction module
- graphix.fundamentals module
- graphix.graphsim module
MBQCGraphNodeGraphStateGraphState.__init__()GraphState.add_nodes_from()GraphState.add_node()GraphState.local_complement()GraphState.apply_vops()GraphState.extract_vops()GraphState.flip_fill()GraphState.flip_sign()GraphState.advance()GraphState.h()GraphState.s()GraphState.z()GraphState.equivalent_graph_e1()GraphState.equivalent_graph_e2()GraphState.equivalent_fill_node()GraphState.measure_x()GraphState.measure_y()GraphState.measure_z()GraphState.draw()GraphState.to_statevector()GraphState.isolated_nodes()
- graphix.instruction module
repr_angle()InstructionKindInstructionKind.CCXInstructionKind.RZZInstructionKind.CNOTInstructionKind.SWAPInstructionKind.CZInstructionKind.HInstructionKind.SInstructionKind.XInstructionKind.YInstructionKind.ZInstructionKind.JInstructionKind.IInstructionKind.MInstructionKind.RXInstructionKind.RYInstructionKind.RZInstructionKind.SDGInstructionKind.TInstructionKind.TDGInstructionKind.SXInstructionKind.SXDGInstructionKind.CYInstructionKind.PInstructionKind.UInstructionKind.CJInstructionKind.CPInstructionKind.CRXInstructionKind.CRYInstructionKind.CRZInstructionKind.CUInstructionKind.CSWAPInstructionKind.GPHASE
InstructionVisitorBaseInstructionCCXRZZControlledSingleTargetInstructionCYCNOTCZSWAPCSWAPSingleTargetInstructionHSSDGTTDGSXSXDGXYZIMRotationInstructionPRXRYRZJUCUControlledRotationInstructionCPCRXCRYCRZCJGPHASEInstructionInstruction.IInstruction.XInstruction.YInstruction.ZInstruction.HInstruction.SInstruction.SDGInstruction.TInstruction.TDGInstruction.SXInstruction.SXDGInstruction.JInstruction.PInstruction.RXInstruction.RYInstruction.RZInstruction.UInstruction.CJInstruction.CPInstruction.CRXInstruction.CRYInstruction.CRZInstruction.CUInstruction.CU.controlInstruction.CU.targetInstruction.CU.thetaInstruction.CU.phiInstruction.CU.lambda_Instruction.CU.gammaInstruction.CU.__init__()Instruction.CU.kindInstruction.CU.visit()Instruction.CU.controlInstruction.CU.targetInstruction.CU.thetaInstruction.CU.phiInstruction.CU.lambda_Instruction.CU.gamma
Instruction.CNOTInstruction.CYInstruction.CZInstruction.CCXInstruction.RZZInstruction.SWAPInstruction.CSWAPInstruction.MInstruction.GPHASEInstruction.__init__()
- graphix.linalg_validations module
- graphix.measurements module
outcome()toggle_outcome()MeasurementBlochMeasurementBlochMeasurement.angleBlochMeasurement.planeBlochMeasurement.angleBlochMeasurement.planeBlochMeasurement.to_bloch()BlochMeasurement.downcast_bloch()BlochMeasurement.to_pauli_or_none()BlochMeasurement.to_pauli_or_bloch()BlochMeasurement.isclose()BlochMeasurement.to_plane()BlochMeasurement.clifford()BlochMeasurement.with_parameter()BlochMeasurement.with_parameters()BlochMeasurement.__init__()
PauliMeasurementMetaPauliMeasurementPauliMeasurement.axisPauliMeasurement.signPauliMeasurement.to_pauli()PauliMeasurement.to_bloch()PauliMeasurement.downcast_bloch()PauliMeasurement.to_pauli_or_none()PauliMeasurement.to_pauli_or_bloch()PauliMeasurement.to_plane_or_axis()PauliMeasurement.isclose()PauliMeasurement.clifford()PauliMeasurement.with_parameter()PauliMeasurement.with_parameters()PauliMeasurement.__init__()
- graphix.opengraph module
OpenGraphOpenGraph.graphOpenGraph.input_nodesOpenGraph.output_nodesOpenGraph.measurementsOpenGraph.output_cliffordsOpenGraph.graphOpenGraph.input_nodesOpenGraph.output_nodesOpenGraph.measurementsOpenGraph.output_cliffordsOpenGraph.to_pattern()OpenGraph.draw()OpenGraph.map()OpenGraph.to_bloch()OpenGraph.downcast_bloch()OpenGraph.infer_pauli_measurements()OpenGraph.isclose()OpenGraph.is_equal_structurally()OpenGraph.neighbors()OpenGraph.odd_neighbors()OpenGraph.to_causalflow()OpenGraph.to_gflow()OpenGraph.to_pauliflow()OpenGraph.to_causalflow_or_none()OpenGraph.to_gflow_or_none()OpenGraph.to_pauliflow_or_none()OpenGraph.to_circuit()OpenGraph.compose()OpenGraph.with_parameter()OpenGraph.with_parameters()OpenGraph.__init__()
OpenGraphError
- graphix.ops module
controlled()OpsOps.IOps.XOps.YOps.ZOps.SOps.SDGOps.TOps.TDGOps.SXOps.SXDGOps.HOps.CYOps.CZOps.CNOTOps.SWAPOps.CCXOps.CHOps.CSWAPOps.p()Ops.rx()Ops.ry()Ops.rz()Ops.u()Ops.cu()Ops.cj()Ops.cp()Ops.crx()Ops.cry()Ops.crz()Ops.j()Ops.rzz()Ops.build_tensor_pauli_ops()Ops.from_axis()Ops.from_ixyz()
- graphix.optimization module
standardize()StandardizedPatternStandardizedPattern.input_nodesStandardizedPattern.output_nodesStandardizedPattern.n_listStandardizedPattern.e_setStandardizedPattern.m_listStandardizedPattern.z_dictStandardizedPattern.x_dictStandardizedPattern.c_dictStandardizedPattern.__init__()StandardizedPattern.from_pattern()StandardizedPattern.graph()StandardizedPattern.perform_pauli_pushing()StandardizedPattern.max_space()StandardizedPattern.minimize_space()StandardizedPattern.to_pattern()StandardizedPattern.to_standardizedpattern()StandardizedPattern.to_space_optimal_pattern()StandardizedPattern.to_opengraph()StandardizedPattern.partial_order_layers()StandardizedPattern.to_xzcorrections()StandardizedPattern.map()StandardizedPattern.to_bloch()StandardizedPattern.infer_pauli_measurements()StandardizedPattern.remove_pauli_measurements()StandardizedPattern.input_nodesStandardizedPattern.output_nodesStandardizedPattern.n_listStandardizedPattern.e_setStandardizedPattern.m_listStandardizedPattern.z_dictStandardizedPattern.x_dictStandardizedPattern.c_dict
remove_useless_domains()single_qubit_domains()remove_local_clifford_commands()
- graphix.parameter module
- graphix.pattern module
DrawPatternAnnotationsPatternPattern.__init__()Pattern.add()Pattern.extend()Pattern.clear()Pattern.replace()Pattern.node_mapping()Pattern.reindex()Pattern.compose()Pattern.input_nodesPattern.output_nodesPattern.n_nodePattern.reorder_output_nodes()Pattern.reorder_input_nodes()Pattern.to_ascii()Pattern.to_latex()Pattern.to_unicode()Pattern.standardize()Pattern.is_standard()Pattern.shift_signals()Pattern.shift_signals_direct()Pattern.signals()Pattern.partial_order_layers()Pattern.to_causalflow()Pattern.to_gflow()Pattern.to_pauliflow()Pattern.to_xzcorrections()Pattern.sort_measurement_commands()Pattern.measurement_commands()Pattern.max_degree()Pattern.nodes()Pattern.isolated_nodes()Pattern.to_opengraph()Pattern.clifford_commands()Pattern.connected_nodes()Pattern.correction_commands()Pattern.parallelize_pattern()Pattern.minimize_space()Pattern.max_space()Pattern.space_list()Pattern.to_pattern()Pattern.remove_input_nodes()Pattern.draw()Pattern.to_qasm3()Pattern.is_parameterized()Pattern.replace_parameter()Pattern.replace_parameters()Pattern.copy()Pattern.check_runnability()Pattern.apply()Pattern.map()Pattern.infer_pauli_measurements()Pattern.blochify()Pattern.to_bloch()Pattern.perform_pauli_pushing()Pattern.remove_pauli_measurements()Pattern.remove_local_clifford_commands()
PatternErrorRunnabilityErrorReasonRunnabilityErrorassert_permutation()ExtractedSignalextract_signal()shift_outcomes()
- graphix.pauli module
- graphix.pretty_print module
- graphix.qasm3_exporter module
- graphix.random_objects module
- graphix.remove_pauli_measurements module
- graphix.repr_mixins module
- graphix.rng module
- graphix.simulator module
- graphix.space_minimization module
- graphix.states module
- graphix.transpiler module
TranspiledPatternTranspiledFlowSimulateResultCircuitCircuit.widthCircuit.instructionCircuit.__init__()Circuit.instructionCircuit.add()Circuit.extend()Circuit.cnot()Circuit.swap()Circuit.cz()Circuit.h()Circuit.s()Circuit.x()Circuit.y()Circuit.z()Circuit.rx()Circuit.ry()Circuit.rz()Circuit.j()Circuit.r()Circuit.rzz()Circuit.ccx()Circuit.i()Circuit.m()Circuit.sdg()Circuit.t()Circuit.tdg()Circuit.sx()Circuit.sxdg()Circuit.cy()Circuit.p()Circuit.u()Circuit.cj()Circuit.cp()Circuit.crx()Circuit.cry()Circuit.crz()Circuit.cr()Circuit.cu()Circuit.cswap()Circuit.gphase()Circuit.transpile_to_causalflow()Circuit.transpile()Circuit.simulate()Circuit.visit()Circuit.apply_angle()Circuit.is_parameterized()Circuit.replace_parameter()Circuit.replace_parameters()Circuit.transpile_to_qasm_gates()Circuit.transpile_rzz()
decompose_rzz()decompose_ccx()decompose_cnot()decompose_swap()decompose_y()decompose_rx()decompose_ry()decompose_rz()decompose_u()decompose_cu()insert_control()decompose_cj()decompose_p()instructions_to_jcz()normalize_angle()TranspileSwapsResultOutputKindOutputIndextranspile_swaps()
- graphix.utils module
- graphix.visualization module
ColoredPlotLimsDrawKwargsVisualizationOptionsVisualizationOptions.pauli_measurementsVisualizationOptions.measurement_labelsVisualizationOptions.local_cliffordVisualizationOptions.node_labelsVisualizationOptions.node_distanceVisualizationOptions.legendVisualizationOptions.figsizeVisualizationOptions.filenameVisualizationOptions.__init__()
GraphVisualizerGraphVisualizer.ogGraphVisualizer.posGraphVisualizer.edge_pathsGraphVisualizer.arrow_pathsGraphVisualizer.n_layersGraphVisualizer.optionsGraphVisualizer._sourceGraphVisualizer.ogGraphVisualizer.posGraphVisualizer.edge_pathsGraphVisualizer.arrow_pathsGraphVisualizer.n_layersGraphVisualizer.optionsGraphVisualizer.from_opengraph()GraphVisualizer.from_flow()GraphVisualizer.from_xzcorrections()GraphVisualizer.visualize()GraphVisualizer.__init__()
Module contents¶
Optimize and simulate measurement-based quantum computation.
- class AmplitudeDampingNoiseModel(prepare_error_prob: float = 0.0, x_error_prob: float = 0.0, z_error_prob: float = 0.0, entanglement_error_prob: float = 0.0, measure_channel_prob: float = 0.0, measure_error_prob: float = 0.0)[source]¶
Bases:
NoiseModelAmplitude damping noise model.
- Parameters:
NoiseModel (class) – Parent abstract class class:
NoiseModel
- __init__(prepare_error_prob: float = 0.0, x_error_prob: float = 0.0, z_error_prob: float = 0.0, entanglement_error_prob: float = 0.0, measure_channel_prob: float = 0.0, measure_error_prob: float = 0.0) None[source]¶
- input_nodes(nodes: Iterable[int], rng: Generator | None = None, *, stacklevel: int = 1) list[CommandOrNoise][source]¶
Return the noise to apply to input nodes.
- command(cmd: CommandOrNoise, rng: Generator | None = None, *, stacklevel: int = 1) list[CommandOrNoise][source]¶
Return the noise to apply to the command
cmd.
- class Axis(*values)[source]¶
Bases:
AbstractMeasurement,EnumReprMixin,EnumAxis: X, Y or Z.
- X = 1¶
- Y = 2¶
- Z = 3¶
- clifford(clifford_gate: Clifford) Axis[source]¶
Return a new measurement command with a
Cliffordapplied.- Parameters:
clifford_gate (Clifford) – Clifford gate to apply before the measurement.
- Returns:
Equivalent measurement representing the pattern
MC.- Return type:
Self
Notes
The return type is
Self, meaning that a Clifford applied to a Bloch measurement returns a Bloch measurement, and a Clifford applied to a Pauli measurement returns a Pauli measurement.The method
Measurement.clifford()does not always commute with the methodMeasurement.to_bloch(): the underlying Pauli measurement will be the same but the Bloch representation can be on different planes.
Examples
>>> from graphix.clifford import Clifford >>> from graphix.measurements import Measurement, PauliMeasurement >>> Measurement.XY(0.25).clifford(Clifford.H) Measurement.YZ(1.75) >>> Measurement.X.clifford(Clifford.S) -Measurement.Y >>> for pauli in PauliMeasurement: ... for clifford in Clifford: ... assert pauli.to_bloch().clifford(clifford).to_pauli_or_none() == pauli.clifford(clifford) >>> Measurement.Y.clifford(Clifford.H).to_bloch() Measurement.XY(1.5) >>> Measurement.Y.to_bloch().clifford(Clifford.H) Measurement.YZ(1.5)
- class BasicStates[source]¶
Bases:
objectBasic states.
- ZERO: ClassVar[PlanarState] = graphix.states.PlanarState(Plane.XZ, 0)¶
- ONE: ClassVar[PlanarState] = graphix.states.PlanarState(Plane.XZ, 1)¶
- PLUS: ClassVar[PlanarState] = graphix.states.PlanarState(Plane.XY, 0)¶
- MINUS: ClassVar[PlanarState] = graphix.states.PlanarState(Plane.XY, 1)¶
- PLUS_I: ClassVar[PlanarState] = graphix.states.PlanarState(Plane.XY, 0.5)¶
- MINUS_I: ClassVar[PlanarState] = graphix.states.PlanarState(Plane.XY, -0.5)¶
- VEC: ClassVar[list[PlanarState]] = [graphix.states.PlanarState(Plane.XY, 0), graphix.states.PlanarState(Plane.XY, 1), graphix.states.PlanarState(Plane.XZ, 0), graphix.states.PlanarState(Plane.XZ, 1), graphix.states.PlanarState(Plane.XY, 0.5), graphix.states.PlanarState(Plane.XY, -0.5)]¶
- class BlochMeasurement(angle: Expression | float, plane: Plane)[source]¶
Bases:
AbstractPlanarMeasurement,MeasurementAn MBQC measurement described by an angle and a plane.
- angle¶
The angle of the measurement in units of \(\pi\). Should be between [0, 2).
- Type:
ExpressionOrFloat
- plane¶
The measurement plane.
- angle: Expression | float¶
- to_bloch() BlochMeasurement[source]¶
Return
self(overridden fromMeasurement).
- downcast_bloch() BlochMeasurement[source]¶
Return
self(overridden fromMeasurement).
- to_pauli_or_none(rel_tol: float = 1e-09, abs_tol: float = 0.0) PauliMeasurement | None[source]¶
Return the measurement description as a Pauli measurement if possible, or
Noneotherwise.- Parameters:
rel_tol (float, optional) – Relative tolerance for comparing angles, passed to
math.isclose(). Default is1e-9.abs_tol (float, optional) – Absolute tolerance for comparing angles, passed to
math.isclose(). Default is0.0.
- Returns:
If
selfis already an instance ofPauliMeasurement, the function returnsself. Ifselfis an instance ofBlochMeasurement, then either the measurement is close to a Pauli measurement (i.e., the angle is close to an integer multiple of π/2) and the corresponding Pauli measurement is returned, or it is not andNoneis returned.- Return type:
PauliMeasurement | None
Notes
A measurement with a parameterized angle is not considered as Pauli, but can become a Pauli measurement after substitution.
Examples
>>> from graphix.measurements import Measurement >>> Measurement.XY(0.5).to_pauli_or_none() Measurement.Y >>> Measurement.Y.to_pauli_or_none() Measurement.Y >>> Measurement.XY(0.25).to_pauli_or_none() is None True >>> from graphix.parameter import Placeholder >>> alpha = Placeholder("alpha") >>> Measurement.XY(alpha).to_pauli_or_none() is None True >>> Measurement.XY(alpha).with_parameter(alpha, 0.5).to_pauli_or_none() Measurement.Y
- to_pauli_or_bloch(rel_tol: float = 1e-09, abs_tol: float = 0.0) PauliMeasurement | BlochMeasurement[source]¶
Return the measurement description as a Pauli measurement if possible, a Bloch measurement otherwise.
- Parameters:
rel_tol (float, optional) – Relative tolerance for comparing angles, passed to
math.isclose(). Default is1e-9.abs_tol (float, optional) – Absolute tolerance for comparing angles, passed to
math.isclose(). Default is0.0.
- Returns:
If
selfis already an instance ofPauliMeasurement, the function returnsself. Ifselfis an instance ofBlochMeasurement, then either the measurement is close to a Pauli measurement (i.e., the angle is close to an integer multiple of π/2) and the corresponding Pauli measurement is returned, or it is not andselfis returned.- Return type:
Examples
>>> from graphix.measurements import Measurement >>> Measurement.XY(0.5).to_pauli_or_bloch() Measurement.Y >>> Measurement.XY(0.25).to_pauli_or_bloch() Measurement.XY(0.25)
- isclose(other: AbstractMeasurement, rel_tol: float = 1e-09, abs_tol: float = 0.0) bool[source]¶
Determine whether two measurements are close in angle and share the same plane.
This method compares the angle of the current measurement with that of another measurement, using
math.isclose()when both angles are floats. The planes must match exactly for the measurements to be considered close. A measurement represented asBlochMeasurementis never considered to be close to a measurement represented asPauliMeasurement.- Parameters:
other (AbstractMeasurement) – The measurement to compare against.
rel_tol (float, optional) – Relative tolerance for comparing angles, passed to
math.isclose(). Default is1e-9.abs_tol (float, optional) – Absolute tolerance for comparing angles, passed to
math.isclose(). Default is0.0.
- Returns:
bool
Trueif both measurements lie in the same plane and their anglesare equal or close within the given tolerances;
Falseotherwise.
Examples
>>> from graphix.measurements import Measurement >>> from graphix.fundamentals import Plane >>> Measurement.XY(0).isclose(Measurement.XY(0)) True >>> Measurement.XY(0).isclose(Measurement.YZ(0)) False >>> Measurement.XY(0.1).isclose(Measurement.XY(0)) False >>> Measurement.XY(0).isclose(Measurement.X) False
- clifford(clifford_gate: Clifford) BlochMeasurement[source]¶
Return a new measurement command with a
Cliffordapplied.- Parameters:
clifford_gate (Clifford) – Clifford gate to apply before the measurement.
- Returns:
Equivalent measurement representing the pattern
MC.- Return type:
Self
Notes
The return type is
Self, meaning that a Clifford applied to a Bloch measurement returns a Bloch measurement, and a Clifford applied to a Pauli measurement returns a Pauli measurement.The method
Measurement.clifford()does not always commute with the methodMeasurement.to_bloch(): the underlying Pauli measurement will be the same but the Bloch representation can be on different planes.
Examples
>>> from graphix.clifford import Clifford >>> from graphix.measurements import Measurement, PauliMeasurement >>> Measurement.XY(0.25).clifford(Clifford.H) Measurement.YZ(1.75) >>> Measurement.X.clifford(Clifford.S) -Measurement.Y >>> for pauli in PauliMeasurement: ... for clifford in Clifford: ... assert pauli.to_bloch().clifford(clifford).to_pauli_or_none() == pauli.clifford(clifford) >>> Measurement.Y.clifford(Clifford.H).to_bloch() Measurement.XY(1.5) >>> Measurement.Y.to_bloch().clifford(Clifford.H) Measurement.YZ(1.5)
- with_parameter(variable: Parameter, substitute: ExpressionOrSupportsFloat) BlochMeasurement[source]¶
Substitute a parameter with a value or expression.
- with_parameters(assignment: Mapping[Parameter, ExpressionOrSupportsFloat]) BlochMeasurement[source]¶
Perform parallel substitution of multiple parameters.
- __init__(angle: Expression | float, plane: Plane) None¶
- class CausalFlow(og: OpenGraph[_AM_co], correction_function: Mapping[int, AbstractSet[int]], partial_order_layers: Sequence[AbstractSet[int]], _CF_PREFIX: str = 'c')[source]¶
Bases:
GFlow[_PM_co],Generic[_PM_co]An unmutable subclass of
GFlowproviding a representation of a causal flow.- This class differs from its parent class in the following:
The extraction of XZ-corrections from the causal flow does assumes that correction sets have one element only.
The method
CausalFlow.is_well_formed()verifies the definition of causal flow (Definition 2 in Ref. [1]).
References
[1] Browne et al., 2007 New J. Phys. 9 250 (arXiv:quant-ph/0702212).
- classmethod from_correctionmatrix_or_none(correction_matrix: CorrectionMatrix[_PM_co]) None[source]¶
Initialize a
GFlowobject from a matrix encoding a correction function.- Parameters:
correction_matrix (CorrectionMatrix[_PM_co]) – Algebraic representation of the correction function.
- Returns:
A gflow if it exists,
Noneotherwise.- Return type:
Self | None
Notes
This method verifies if there exists a partial measurement order on the input open graph compatible with the input correction matrix. See Lemma 3.12, and Theorem 3.1 in Ref. [1]. Failure to find a partial order implies the non-existence of a generalised flow if the correction matrix was calculated by means of Algorithms 2 and 3 in [1].
References
[1] Mitosek and Backens, 2024 (arXiv:2410.23439).
- to_xzcorrections() XZCorrections[_PM_co][source]¶
Compute the XZ-corrections induced by the causal flow encoded in
self.- Return type:
XZCorrections[_PM_co]
Notes
This function partially implements Theorem 1 in Ref. [1]. The generated XZ-corrections can be used to obtain a robustly deterministic pattern on the underlying open graph.
References
[1] Browne et al., 2007 New J. Phys. 9 250 (arXiv:quant-ph/0702212).
- check_well_formed() None[source]¶
Verify if the causal flow is well formed.
- Raises:
FlowError – if the causal flow is not well formed.
Notes
- General properties of flows:
The domain of the correction function is \(O^c\), the non-output nodes of the open graph.
The image of the correction function is a subset of \(I^c\), the non-input nodes of the open graph.
The nodes in the partial order are the nodes in the open graph.
The first layer of the partial order layers is \(O\), the output nodes of the open graph. This is guaranteed because open graphs without outputs do not have flow, unless it is an empty open graph.
- Specific properties of causal flows:
Correction sets have one element only (C0),
\(i \sim c(i)\) (C1),
\(i \prec c(i)\) (C2),
\(\forall k \in N_G(c(i)) \setminus \{i\}, i \prec k\) (C3),
where \(i \in O^c\), \(c\) is the correction function and \(prec\) denotes the partial order.
Causal flows are defined on open graphs with XY measurements only.
See Definition 2 in Ref. [1].
References
[1] Browne et al., 2007 New J. Phys. 9 250 (arXiv:quant-ph/0702212).
- class Circuit(width: int, instr: Iterable[InstructionType] | None = None)[source]¶
Bases:
InplaceParameterizableGate-to-MBQC transpiler.
Holds gate operations and translates into MBQC measurement patterns.
- __init__(width: int, instr: Iterable[InstructionType] | None = None) None[source]¶
Construct a circuit.
- h(qubit: int) None[source]¶
Apply a Hadamard gate.
See
Hfor more information.- Parameters:
qubit (int) – target qubit
- s(qubit: int) None[source]¶
Apply an S gate.
See
Sfor more information.- Parameters:
qubit (int) – target qubit
- x(qubit: int) None[source]¶
Apply a Pauli X gate.
See
Xfor more information.- Parameters:
qubit (int) – target qubit
- y(qubit: int) None[source]¶
Apply a Pauli Y gate.
See
Yfor more information.- Parameters:
qubit (int) – target qubit
- z(qubit: int) None[source]¶
Apply a Pauli Z gate.
See
Zfor more information.- Parameters:
qubit (int) – target qubit
- rx(qubit: int, angle: ParameterizedAngle) None[source]¶
Apply an X rotation gate.
See
RXfor more information.- Parameters:
qubit (int) – target qubit
angle (ParameterizedAngle) – rotation angle in units of π
- ry(qubit: int, angle: ParameterizedAngle) None[source]¶
Apply a Y rotation gate.
See
RYfor more information.- Parameters:
qubit (int) – target qubit
angle (ParameterizedAngle) – angle in units of π
- rz(qubit: int, angle: ParameterizedAngle) None[source]¶
Apply a Z rotation gate.
See
RZfor more information.- Parameters:
qubit (int) – target qubit
angle (ParameterizedAngle) – rotation angle in units of π
- j(qubit: int, angle: ParameterizedAngle) None[source]¶
Apply a J rotation gate.
See
Jfor more information.- Parameters:
qubit (int) – target qubit
angle (ParameterizedAngle) – rotation angle in units of π
- r(qubit: int, axis: Axis, angle: ParameterizedAngle) None[source]¶
Apply a rotation gate on the given axis.
- rzz(control: int, target: int, angle: ParameterizedAngle) None[source]¶
Apply a ZZ-rotation gate.
Equivalent to the sequence CNOT(control, target), Rz(target, angle), CNOT(control, target)
and realizes rotation expressed by \(e^{-i \frac{\theta}{2} Z_c Z_t}\).
See
RZZfor more information.
- ccx(control1: int, control2: int, target: int) None[source]¶
Apply a CCX (Toffoli) gate.
See
CCXfor more information.
- i(qubit: int) None[source]¶
Apply an identity (teleportation) gate.
See
Ifor more information.- Parameters:
qubit (int) – target qubit
- m(qubit: int, axis: Axis) None[source]¶
Measure a quantum qubit.
The measured qubit cannot be used afterwards.
See
Mfor more information.
- sdg(qubit: int) None[source]¶
Apply an SDG gate.
See
SDGfor more information.- Parameters:
qubit (int) – target qubit
- t(qubit: int) None[source]¶
Apply a T gate.
See
Tfor more information.- Parameters:
qubit (int) – target qubit
- tdg(qubit: int) None[source]¶
Apply a TDG gate.
See
TDGfor more information.- Parameters:
qubit (int) – target qubit
- sx(qubit: int) None[source]¶
Apply an SX gate.
See
SXfor more information.- Parameters:
qubit (int) – target qubit
- sxdg(qubit: int) None[source]¶
Apply an SXDG gate.
See
SXDGfor more information.- Parameters:
qubit (int) – target qubit
- p(qubit: int, angle: ParameterizedAngle) None[source]¶
Apply a Phase rotation gate.
See
Pfor more information.- Parameters:
qubit (int) – target qubit
angle (ParameterizedAngle) – rotation angle in units of π
- u(qubit: int, theta: ParameterizedAngle, phi: ParameterizedAngle, lambda_: ParameterizedAngle) None[source]¶
Apply a universal single-qubit gate.
See
Ufor more information.- Parameters:
qubit (int) – target qubit
theta (ParameterizedAngle) – rotation angle in units of π
phi (ParameterizedAngle) – rotation angle in units of π
lambda (ParameterizedAngle) – rotation angle in units of π
- cj(control: int, target: int, angle: ParameterizedAngle) None[source]¶
Apply a controlled-J rotation gate.
See
CJfor more information.
- cp(control: int, target: int, angle: ParameterizedAngle) None[source]¶
Apply a controlled-P rotation gate.
See
CPfor more information.
- crx(control: int, target: int, angle: ParameterizedAngle) None[source]¶
Apply an controlled-X rotation gate.
See
CRXfor more information.
- cry(control: int, target: int, angle: ParameterizedAngle) None[source]¶
Apply a controlled-Y rotation gate.
See
CRYfor more information.
- crz(control: int, target: int, angle: ParameterizedAngle) None[source]¶
Apply a controlled-Z rotation gate.
See
CRZfor more information.
- cr(control: int, target: int, axis: Axis, angle: ParameterizedAngle) None[source]¶
Apply a controlled-rotation gate on the given axis.
- cu(control: int, target: int, theta: ParameterizedAngle, phi: ParameterizedAngle, lambda_: ParameterizedAngle, gamma: ParameterizedAngle) None[source]¶
Apply a controlled-U gate.
See
CUfor more information.- Parameters:
- cswap(control: int, qubit1: int, qubit2: int) None[source]¶
Apply a CSWAP gate.
See
CSWAPfor more information.
- gphase(angle: ParameterizedAngle) None[source]¶
Apply a global phase.
See
GPHASEfor more information.- Parameters:
angle (ParameterizedAngle) – rotation angle in units of π
- transpile_to_causalflow() TranspiledFlow[source]¶
Transpile a circuit via J-∧z decomposition to a causal flow.
- Parameters:
self (the circuit to transpile.)
- Returns:
the result of the transpilation
- Return type:
a causal flow and classical outputs.
- transpile(*, transpile_swaps: bool = True) TranspiledPattern[source]¶
Transpile a circuit via J-∧z decomposition to a pattern.
- Parameters:
transpile_swaps (bool, optional) – If
True(the default), SWAP gates are eliminated by switching the qubits. IfFalse, SWAP gates are transpiled into a sequence of three CNOT gates.- Returns:
The result of the transpilation: a pattern and classical outputs.
- Return type:
- simulate(backend: StatevectorBackend | Literal['statevector'] = 'statevector', input_state: Data | None = None, branch_selector: BranchSelector | None = None, rng: Generator | None = None, *, stacklevel: int = 1) SimulateResult[Statevector][source]¶
- simulate(backend: DensityMatrixBackend | Literal['densitymatrix'], input_state: Data | None = None, branch_selector: BranchSelector | None = None, rng: Generator | None = None, *, stacklevel: int = 1) SimulateResult[DensityMatrix]
- simulate(backend: DenseStateBackend[_DenseStateT], input_state: Data | None = None, branch_selector: BranchSelector | None = None, rng: Generator | None = None, *, stacklevel: int = 1) SimulateResult[_DenseStateT]
Simulate the gate sequence with a backend and input state of choice.
By default, this method uses the statevector backend and initializes the register to \(|+\rangle^{\otimes n}\).
- Parameters:
input_state (Data)
backend (
graphix.sim.base_backend.DenseStateBackend[_DenseStateT], ‘statevector’, or ‘densitymatrix’) – Simulator backend to use. Optional, defaults to “statevector”.branch_selector (
graphix.branch_selector.BranchSelector) – branch selector for measures (default:RandomBranchSelector). It cannot be specified ifbackendis already instantiated.rng (Generator, optional) – Random-number generator for measurements. This generator is used only in case of random branch selection (see
RandomBranchSelector).
- Returns:
result – output state of the statevector simulation and results of classical measures.
- Return type:
SimulateResult
- visit(visitor: InstructionVisitor, *, copy: bool = False) Circuit[source]¶
Apply
visitorto all instructions in the circuit.- Parameters:
visitor (InstructionVisitor) – The visitor specifying the rewriting.
copy (bool, optional) – If
True, the current circuit remains unchanged, and a new circuit is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The rewritten circuit. Equal to
selfifcopyisFalse.- Return type:
Self
- apply_angle(f: Callable[[ParameterizedAngle], ParameterizedAngle], *, copy: bool = False) Circuit[source]¶
Apply
fto all angles that occur in the circuit.- Parameters:
f (Callable[[ParameterizedAngle], ParameterizedAngle]) – The function to apply to every angle.
copy (bool, optional) – If
True, the current circuit remains unchanged, and a new circuit is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The rewritten circuit. Equal to
selfifcopyisFalse.- Return type:
Self
- is_parameterized() bool[source]¶
Return
Trueif there is at least one measurement angle that is not just an instance ofSupportsFloat.A parameterized circuit is a circuit where at least one measurement angle is an expression that is not a number, typically an instance of
sympy.Expr(but we don’t force to choosesympyhere).
- replace_parameter(variable: Parameter, substitute: ExpressionOrSupportsFloat, *, copy: bool = False) Circuit[source]¶
Substitute all occurrences of the given variable in measurement angles by the given value.
- Parameters:
variable (Parameter) – The symbolic expression to be replaced within the measurement angles.
substitute (ExpressionOrSupportsFloat) – The value or symbolic expression to substitute in place of
variable.copy (bool, optional) – If
True, the current object remains unchanged and a new object is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The object with the updated measurement parameters. Equal to
selfifcopyisFalse.- Return type:
Self
- replace_parameters(assignment: Mapping[Parameter, ExpressionOrSupportsFloat], *, copy: bool = False) Circuit[source]¶
Substitute all occurrences of the given keys in measurement angles by the given values in parallel.
- Parameters:
assignment (Mapping[Parameter, ExpressionOrSupportsFloat]) – A dictionary-like mapping where keys are the
Parameterobjects to be replaced and values are the new expressions or numerical values.copy (bool, optional) – If
True, the current object remains unchanged and a new object is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The object with the updated measurement parameters. Equal to
selfifcopyisFalse.- Return type:
Self
- class Clifford(*values)[source]¶
Bases:
EnumClifford gate.
- property matrix: npt.NDArray[np.complex128]¶
Return the matrix of the Clifford gate.
- static try_from_matrix(mat: npt.NDArray[Any]) Clifford | None[source]¶
Find the Clifford gate from the matrix.
Return
Noneif not found.Notes
Global phase is ignored.
- draw(output: OutputFormat | None = None) str[source]¶
Return a string representation of a Clifford.
- Parameters:
clifford (Clifford) – The statevector to format.
output (OutputFormat | None) – Desired formatting style (
ASCII,LaTeXorUnicode).
- Returns:
The formatted Clifford.
- Return type:
- commute_domains(domains: Domains) Domains[source]¶
Commute \(X^sZ^t\) with \(C\).
Given \(X^sZ^t\), return \(X^{s'}Z^{t'}\) such that \(X^sZ^tC = CX^{s'}Z^{t'}\).
Note that applying the method to
conj()computes the reverse commutation: indeed, \(C^\dag X^s Z^t = (X^s Z^t C)^\dag = (C X^{s'} Z^{t'})^\dag = X^{s'}Z^{t'}C^\dag\).
- to_opengraph() OpenGraph[PauliMeasurement][source]¶
Return a local-Clifford-free open graph equivalent to the Clifford gate.
- class CliffordMap(x_map: Sequence[PauliString], z_map: Sequence[PauliString], input_nodes: Sequence[int], output_nodes: Sequence[int])[source]¶
Bases:
objectDataclass to represent a Clifford map.
A Clifford map encodes the action of a Clifford operator on Pauli generators. It describes how single-qubit Pauli operators on the input qubits are mapped, under conjugation, to Pauli strings on the output qubits.
For each input qubit \(i\), the map specifies:
\[P_i = C X_i C^\dagger\]\[P_i = C Z_i C^\dagger\]where the resulting operators \(P_i\) are Pauli strings over the output qubits.
The sequences
input_nodesandoutput_nodesdefine the correspondence between qubit indices and node labels in the input and output spaces.- x_map¶
Images of the \(X\) generators. The \(i\)-th element is the Pauli string corresponding to \(C X_i C^\dagger\).
- Type:
Sequence[PauliString]
- z_map¶
Images of the \(Z\) generators. The \(i\)-th element is the Pauli string corresponding to \(C Z_i C^\dagger\).
- Type:
Sequence[PauliString]
Notes
See Definition 3.3 in Ref. [1].
Elements of
x_mapandz_mapare in one-to-one correspondance withinput_nodes. Each Pauli string is defined over qubit indices corresponding to positions inoutput_nodes.References
[1] Simmons, 2021 (arXiv:2109.05654).
- x_map: Sequence[PauliString]¶
- z_map: Sequence[PauliString]¶
- static from_focused_flow(flow: PauliFlow[Measurement], *, stacklevel: int = 1) CliffordMap[source]¶
Extract a Clifford map from a focused Pauli flow.
This routine associates two Pauli strings (one per generator of the Pauli group, X and Z) to each input node in
flow.og.- Parameters:
flow (PauliFlow[Measurement]) – A focused Pauli flow.
stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.
- Return type:
Notes
See Definition 3.3 and Example C.13 in Ref. [1].
References
[1] Simmons, 2021 (arXiv:2109.05654).
- to_tableau() MatGF2[source]¶
Convert the CliffordMap into its binary tableau representation.
The returned tableau is a
(2n, 2n + 1)binary matrix over GF(2), wherenis the number of qubits. The firstnrows correspond to the images of X generators, and the nextnrows correspond to the images of Z generators. Columns encode the X and Z components of the resulting Pauli strings, along with a sign column.Each PauliString in
x_mapandz_mapis decomposed into its X/Z support: - X contributes a 1 to the X block. - Z contributes a 1 to the Z block. - Y contributes a 1 to both X and Z blocks. The sign of the Pauli string is stored in the final column (0 forSign.PLUSand 1 forSign.MINUS).- Returns:
A binary matrix of shape
(2n, 2n + 1)representing the Clifford tableau.- Return type:
MatGF2
- Raises:
NotImplementedError – If the number of input nodes differs from the number of output nodes (i.e., the map is an isometry instead of a square Clifford).
- __init__(x_map: Sequence[PauliString], z_map: Sequence[PauliString], input_nodes: Sequence[int], output_nodes: Sequence[int]) None¶
- class Command[source]¶
Bases:
objectGrouping of all commands for namespace exposure.
Notes
This class is not meant to be instantiated, but rather serves as a namespace for all command types. The type alias for “any command” is
CommandKind.- class N(node: int, state: State = <factory>)¶
Bases:
BaseN,_KindCheckerPreparation command.
- Parameters:
- class M(node: int, measurement: Measurement = Measurement.X, s_domain: set[int] = <factory>, t_domain: set[int] = <factory>)¶
Bases:
BaseM,_KindCheckerMeasurement command.
- Parameters:
- __init__(node: int, measurement: Measurement = Measurement.X, s_domain: set[int] = <factory>, t_domain: set[int] = <factory>) None¶
- clifford(clifford_gate: Clifford) M¶
Return a new measurement command with a Clifford applied.
- Parameters:
clifford_gate (Clifford) – Clifford gate to apply before the measurement.
- Returns:
Equivalent command representing the pattern
MC.- Return type:
M
- map(f: Callable[[Measurement], Measurement]) M¶
Return a measurement command where the function
fhas been applied to the measurement.- Parameters:
f (Callable[[Measurement], Measurement]) – Function applied to the measurement.
- Returns:
The resulting command.
- Return type:
- measurement: Measurement = Measurement.X¶
- class E(nodes: tuple[int, int])¶
Bases:
_KindChecker,BaseCommandEntanglement command between two qubits.
- class C(node: int, clifford: Clifford)¶
Bases:
_KindChecker,BaseCommandLocal Clifford gate command.
- Parameters:
- class X(node: int, domain: set[int] = <factory>)¶
Bases:
_KindChecker,BaseCommandX correction command.
- Parameters:
- class Z(node: int, domain: set[int] = <factory>)¶
Bases:
_KindChecker,BaseCommandZ correction command.
- Parameters:
- class S(node: int, domain: set[int] = <factory>)¶
Bases:
_KindChecker,BaseCommandS command.
- Parameters:
- class T¶
Bases:
_KindChecker,BaseCommandT command.
- Parameters:
None – The T command acts globally without parameters.
- class ConstBranchSelector(result: Literal[0, 1])[source]¶
Bases:
BranchSelectorBranch selector with a constant measurement outcome.
The value
resultis returned for every qubit.- Parameters:
result (Outcome) – The fixed measurement outcome for all qubits.
- class DensityMatrix(data: Data = graphix.states.PlanarState(Plane.XY, 0), nqubit: int | None = None)[source]¶
Bases:
DenseState,InplaceParameterizableDensityMatrix object.
- __init__(data: Data = graphix.states.PlanarState(Plane.XY, 0), nqubit: int | None = None) None[source]¶
Initialize density matrix objects.
The behaviour builds on the one of graphix.statevec.Statevector.
datacan be: - a singlegraphix.states.State(classical description of a quantum state) - an iterable ofgraphix.states.Stateobjects - an iterable of iterable of scalars (A 2**n x 2**n numerical density matrix) - a graphix.statevec.DensityMatrix object - a graphix.statevec.Statevector objectIf
nqubitis not provided, the number of qubit is inferred fromdataand checked for consistency. If only onegraphix.states.Stateis provided and nqubit is a valid integer, initialize the statevector in the tensor product state. If bothnqubitanddataare provided, consistency of the dimensions is checked. If a graphix.statevec.Statevector or graphix.statevec.DensityMatrix is passed, returns a copy.- Parameters:
data (Data) – input data to prepare the state. Can be a classical description or a numerical input, defaults to graphix.states.BasicStates.PLUS
nqubit (int, optional) – number of qubits to prepare, defaults to None
- draw(output: OutputFormat = OutputFormat.Unicode, *, max_denominator: int = 1000, atol: float = 1e-09, rtol: float = 0.0, precision: int = 4) str[source]¶
Return a pretty-printed matrix representation of the density matrix.
Each entry is rendered with
graphix.pretty_print.complex_to_str(), so common values appear as exact expressions (e.g.1/2) rather than floating-point numbers.- Parameters:
output (OutputFormat, optional) – Desired formatting style. Defaults to
OutputFormat.Unicode.max_denominator (int, optional) – Maximum denominator used by the entry recognition (default:
1000).atol (float, optional) – Absolute tolerance for the recognition heuristics (default:
1e-9).rtol (float, optional) – Relative tolerance for the recognition heuristics (default:
0.0).precision (int, optional) – Number of significant digits to use for entries that fall back to a decimal representation (default:
4).
- Returns:
The formatted density matrix.
- Return type:
- add_nodes(nqubit: int, data: Data) None[source]¶
Add nodes (qubits) to the density matrix and initialize them in a specified state.
- Parameters:
nqubit (int) – The number of qubits to add to the density matrix.
data (Data, optional) –
The state in which to initialize the newly added nodes.
If a single basic state is provided, all new nodes are initialized in that state.
If a list of basic states is provided, it must match the length of
nodes, and each node is initialized with its corresponding state.A single-qubit state vector will be broadcast to all nodes.
A multi-qubit state vector of dimension \(2^n\) initializes the new nodes jointly.
A density matrix must have shape \(2^n \times 2^n\), and is used to jointly initialize the new nodes.
The type of nodes to be added is inferred from the type of the existing
DensityMatrix.
Notes
Previously existing nodes remain unchanged.
- evolve_single(op: NDArray[object_ | complex128], qubit: int) None[source]¶
Single-qubit operation.
- Parameters:
op (np.ndarray) – 2*2 matrix.
qubit (int) – Index of qubit to apply operator.
- evolve(op: Matrix, qubits: Sequence[int]) None[source]¶
Multi-qubit operation.
- Parameters:
op (np.array) – 2^n*2^n matrix
qubits (list of ints) – target qubits’ indexes
- expectation_single(op: NDArray[object_ | complex128], qubit: int) complex[source]¶
Return the expectation value of single-qubit operator.
- Parameters:
op (np.array) – 2*2 Hermite operator
qubit (int) – Index of qubit on which to apply operator.
- Returns:
complex
- Return type:
expectation value (real for hermitian ops!).
- tensor(other: DensityMatrix) None[source]¶
Tensor product state with other density matrix.
Results in self \(\otimes\) other.
- Parameters:
other – DensityMatrix object to be tensored with self.
- permute(permutation: Sequence[int]) None[source]¶
Reorder the qubits.
- Parameters:
permutation (Sequence[int]) – The permutation to apply. For each position in the resulting order, the value gives the index of the qubit in the original ordering.
- fidelity(statevec: Statevector) Expression | float[source]¶
Calculate the fidelity against reference statevector.
- Parameters:
statevec (numpy array) – statevector (flattened numpy array) to compare with
- apply_channel(channel: KrausChannel, qargs: Sequence[int]) None[source]¶
Apply a channel to a density matrix.
:param : :type : rho: density matrix. :param channel: KrausChannel to be applied to the density matrix :type channel:
graphix.channel.KrausChannelobject :param qargs: :type qargs: target qubit indices- Return type:
nothing
- Raises:
ValueError – If the final density matrix is not normalized after application of the channel. This shouldn’t happen since
graphix.channel.KrausChannelobjects are normalized by construction..... –
- apply_noise(qubits: Sequence[int], noise: Noise) None[source]¶
Apply noise.
- Parameters:
qubits (sequence of ints.) – Target qubits
noise (Noise) – Noise to apply
- replace_parameter(variable: Parameter, substitute: ExpressionOrSupportsFloat, *, copy: bool = False) DensityMatrix[source]¶
Substitute all occurrences of the given variable in measurement angles by the given value.
- Parameters:
variable (Parameter) – The symbolic expression to be replaced within the measurement angles.
substitute (ExpressionOrSupportsFloat) – The value or symbolic expression to substitute in place of
variable.copy (bool, optional) – If
True, the current object remains unchanged and a new object is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The object with the updated measurement parameters. Equal to
selfifcopyisFalse.- Return type:
Self
- replace_parameters(assignment: Mapping[Parameter, ExpressionOrSupportsFloat], *, copy: bool = False) DensityMatrix[source]¶
Substitute all occurrences of the given keys in measurement angles by the given values in parallel.
- Parameters:
assignment (Mapping[Parameter, ExpressionOrSupportsFloat]) – A dictionary-like mapping where keys are the
Parameterobjects to be replaced and values are the new expressions or numerical values.copy (bool, optional) – If
True, the current object remains unchanged and a new object is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The object with the updated measurement parameters. Equal to
selfifcopyisFalse.- Return type:
Self
- class DensityMatrixBackend(*, node_index: NodeIndex = <factory>, branch_selector: BranchSelector = <factory>, symbolic: bool = False)[source]¶
Bases:
DenseStateBackend[DensityMatrix]MBQC simulator with density matrix method.
- __init__(*, node_index: NodeIndex = <factory>, branch_selector: BranchSelector = <factory>, symbolic: bool = False) None¶
- state: DensityMatrix¶
- class DepolarisingNoiseModel(prepare_error_prob: float = 0.0, x_error_prob: float = 0.0, z_error_prob: float = 0.0, entanglement_error_prob: float = 0.0, measure_channel_prob: float = 0.0, measure_error_prob: float = 0.0)[source]¶
Bases:
NoiseModelDepolarising noise model.
- Parameters:
NoiseModel (class) – Parent abstract class class:
NoiseModel
- __init__(prepare_error_prob: float = 0.0, x_error_prob: float = 0.0, z_error_prob: float = 0.0, entanglement_error_prob: float = 0.0, measure_channel_prob: float = 0.0, measure_error_prob: float = 0.0) None[source]¶
- input_nodes(nodes: Iterable[int], rng: Generator | None = None, *, stacklevel: int = 1) list[CommandOrNoise][source]¶
Return the noise to apply to input nodes.
- command(cmd: CommandOrNoise, rng: Generator | None = None, *, stacklevel: int = 1) list[CommandOrNoise][source]¶
Return the noise to apply to the command
cmd.
- class DrawPatternAnnotations(*values)[source]¶
Bases:
EnumEnumeration to indicate the possible annotations for
Pattern.draw.- Flow = 1¶
- XZCorrections = 2¶
- class FixedBranchSelector(results: _T, default: BranchSelector | None = None)[source]¶
Bases:
BranchSelector,Generic[_T]Branch selector with predefined measurement outcomes.
The mapping is fixed in
results. By default, an error is raised if a qubit is measured without a predefined outcome. However, another branch selector can be specified indefaultto handle such cases.- Parameters:
results (Mapping[int, bool]) – A dictionary mapping qubits to their measurement outcomes. If a qubit is not present in this mapping, the
defaultbranch selector is used.default (BranchSelector | None, optional) – Branch selector to use for qubits not present in
results. IfNone, an error is raised when an unmapped qubit is measured. Default isNone.
- results: _T¶
- default: BranchSelector | None = None¶
- measure(qubit: int, f_expectation0: Callable[[], float], rng: Generator | None = None, *, stacklevel: int = 1) Outcome[source]¶
Return the predefined measurement outcome of
qubit, if available.If the qubit is not present in
results, thedefaultbranch selector is used. If no default is provided, an error is raised.
- __init__(results: _T, default: BranchSelector | None = None) None¶
- class GFlow(og: OpenGraph[_AM_co], correction_function: Mapping[int, AbstractSet[int]], partial_order_layers: Sequence[AbstractSet[int]], _CF_PREFIX: str = 'g')[source]¶
Bases:
PauliFlow[_PM_co],Generic[_PM_co]An unmutable subclass of
PauliFlowproviding a representation of a generalised flow (gflow).- This class differs from its parent class in the following:
It cannot be constructed from
OpenGraph[Axis]instances, since the gflow is only defined for planar measurements.The extraction of XZ-corrections from the gflow does not require knowledge on the partial order.
The method
GFlow.is_well_formed()verifies the definition of gflow (Definition 2.36 in Ref. [1]).
References
[1] Backens et al., Quantum 5, 421 (2021), doi.org/10.22331/q-2021-03-25-421
- classmethod from_correctionmatrix_or_none(correction_matrix: CorrectionMatrix[_PM_co]) Self | None[source]¶
Initialize a
GFlowobject from a matrix encoding a correction function.- Parameters:
correction_matrix (CorrectionMatrix[_PM_co]) – Algebraic representation of the correction function.
- Returns:
A gflow if it exists,
Noneotherwise.- Return type:
Self | None
Notes
This method verifies if there exists a partial measurement order on the input open graph compatible with the input correction matrix. See Lemma 3.12, and Theorem 3.1 in Ref. [1]. Failure to find a partial order implies the non-existence of a generalised flow if the correction matrix was calculated by means of Algorithms 2 and 3 in [1].
References
[1] Mitosek and Backens, 2024 (arXiv:2410.23439).
- to_xzcorrections() XZCorrections[_PM_co][source]¶
Compute the XZ-corrections induced by the generalised flow encoded in
self.- Return type:
XZCorrections[_PM_co]
Notes
This function partially implements Theorem 2 in Ref. [1]. The generated XZ-corrections can be used to obtain a robustly deterministic pattern on the underlying open graph.
Contrary to the overridden method in the parent class, here we do not need any information on the partial order to build the corrections since a valid correction function \(g\) guarantees that both \(g(i)\setminus \{i\}\) and \(Odd(g(i))\) are in the future of \(i\).
References
[1] Browne et al., 2007 New J. Phys. 9 250 (arXiv:quant-ph/0702212).
- check_well_formed() None[source]¶
Verify if the generalised flow is well formed.
- Raises:
FlowError – if the gflow is not well formed.
Notes
- General properties of flows:
The domain of the correction function is \(O^c\), the non-output nodes of the open graph.
The image of the correction function is a subset of \(I^c\), the non-input nodes of the open graph.
The nodes in the partial order are the nodes in the open graph.
The first layer of the partial order layers contains the outputs of the open graph if there are any.
- Specific properties of gflows:
If \(j \in g(i), i \neq j\), then \(i \prec j\) (G1).
If \(j \in Odd(g(i)), i \neq j\), then \(i \prec j\) (G2).
If \(\lambda(i) = XY\), then \(i \notin g(i)`\) and \(i \in Odd((g(i)))\) (G3).
If \(\lambda(i) = XZ\), then \(i \in g(i)`\) and \(i \in Odd((g(i)))\) (G4).
If \(\lambda(i) = YZ\), then \(i \in g(i)`\) and \(i \notin Odd((g(i)))\) (G5),
where \(i \in O^c\), \(g\) is the correction function, \(prec\) denotes the partial order, \(\lambda(i)\) is the measurement plane of node \(i\), and \(Odd(s)\) is the odd neighbourhood of the set \(s\) in the open graph.
See Definition 2.36 in Ref. [1].
References
[1] Backens et al., Quantum 5, 421 (2021), doi.org/10.22331/q-2021-03-25-421
- class GraphState(*args, backend=None, **kwargs)[source]¶
Bases:
GraphGraph state simulator implemented with
networkx.Performs Pauli measurements on graph states.
ref: M. Elliot, B. Eastin & C. Caves, JPhysA 43, 025301 (2010) and PRA 77, 042307 (2008)
- Each node has attributes:
- hollow:
True if node is hollow (has local H operator)
- sign:
True if node has negative sign (local Z operator)
- loop:
True if node has loop (local S operator)
- __init__(nodes: Iterable[int] | None = None, edges: Iterable[tuple[int, int]] | None = None, vops: Mapping[int, Clifford] | None = None) None[source]¶
Instantiate a graph simulator.
- add_nodes_from(nodes_for_adding: Iterable[int | tuple[int, MBQCGraphNode]], **attr: Any) None[source]¶
Wrap
networkx.Graph.add_nodes_fromto initialize MBQCGraphNode attributes.
- add_node(node_for_adding: int, **attr: Any) None[source]¶
Wrap
networkx.Graph.add_nodeto initialize MBQCGraphNode attributes.
- apply_vops(vops: Mapping[int, Clifford]) None[source]¶
Apply local Clifford operators to the graph state from a dictionary.
- extract_vops() dict[int, Clifford][source]¶
Apply local Clifford operators to the graph state from a dictionary.
- flip_fill(node: int) None[source]¶
Flips the fill (local H) of a node.
- Parameters:
node (int) – graph node to flip the fill
- Return type:
None
- flip_sign(node: int) None[source]¶
Flip the sign (local Z) of a node.
Note that application of Z gate is different from
flip_signif there exist an edge from the node.- Parameters:
node (int) – graph node to flip the sign
- Return type:
None
- advance(node: int) None[source]¶
Flip the loop (local S) of a node.
If the loop already exist, sign is also flipped, reflecting the relation SS=Z. Note that application of S gate is different from
advanceif there exist an edge from the node.- Parameters:
node (int) – graph node to advance the loop.
- Return type:
None
- h(node: int) None[source]¶
Apply H gate to a qubit (node).
- Parameters:
node (int) – graph node to apply H gate
- Return type:
None
- s(node: int) None[source]¶
Apply S gate to a qubit (node).
- Parameters:
node (int) – graph node to apply S gate
- Return type:
None
- z(node: int) None[source]¶
Apply Z gate to a qubit (node).
- Parameters:
node (int) – graph node to apply Z gate
- Return type:
None
- equivalent_graph_e1(node: int) None[source]¶
Tranform a graph state to a different graph state representing the same stabilizer state.
This rule applies only to a node with loop.
- Parameters:
node1 (int) – A graph node with a loop to apply rule E1
- Return type:
None
- equivalent_graph_e2(node1: int, node2: int) None[source]¶
Tranform a graph state to a different graph state representing the same stabilizer state.
This rule applies only to two connected nodes without loop.
- equivalent_fill_node(node: int) int[source]¶
Fill the chosen node by graph transformation rules E1 and E2.
If the selected node is hollow and isolated, it cannot be filled and warning is thrown.
- measure_x(node: int, choice: Outcome = 0) Outcome[source]¶
Perform measurement in X basis.
According to original paper, we realise X measurement by applying H gate to the measured node before Z measurement.
- measure_y(node: int, choice: Outcome = 0) Outcome[source]¶
Perform measurement in Y basis.
According to original paper, we realise Y measurement by applying S,Z and H gate to the measured node before Z measurement.
- measure_z(node: int, choice: Outcome = 0) Outcome[source]¶
Perform measurement in Z basis.
To realize the simple Z measurement on undecorated graph state, we first fill the measured node (remove local H gate)
- draw(fill_color: str = 'C0') None[source]¶
Draw decorated graph state.
Negative nodes are indicated by negative sign of node labels.
- Parameters:
fill_color (str) – optional, fill color of nodes
- to_statevector() Statevector[source]¶
Convert the graph state into a state vector.
- class Instruction[source]¶
Bases:
objectGrouping of all instructions for namespace exposure.
Notes
This class is not meant to be instantiated, but rather serves as a namespace for all instructions except RZZ. The type alias for “any command” is
InstructionKind.- class I(target: int)¶
Bases:
_KindChecker,SingleTargetInstructionI circuit instruction.
The identity gate applies the matrix \(\left[\begin{matrix}1 & 0\\\mathrm 0 & 1\end{matrix}\right]\).
- class X(target: int)¶
Bases:
_KindChecker,SingleTargetInstructionX circuit instruction.
The X gate applies the matrix \(\left[\begin{matrix}0 & 1\\1 & 0\end{matrix}\right]\).
- class Y(target: int)¶
Bases:
_KindChecker,SingleTargetInstructionY circuit instruction.
The Y gate applies the matrix \(\left[\begin{matrix}0 & -\mathrm i\\\mathrm i & 0\end{matrix}\right]\).
- class Z(target: int)¶
Bases:
_KindChecker,SingleTargetInstructionZ circuit instruction.
The Z gate applies the matrix \(\left[\begin{matrix}1 & 0\\\mathrm 0 & -1\end{matrix}\right]\).
- class H(target: int)¶
Bases:
_KindChecker,SingleTargetInstructionH circuit instruction.
The Hadamard gate applies the matrix \(\frac 1 {\sqrt 2}\left[\begin{matrix}1 & 1\\1 & -1\end{matrix}\right]\).
- class S(target: int)¶
Bases:
_KindChecker,SingleTargetInstructionS circuit instruction.
The S gate applies the matrix \(\left[\begin{matrix}1 & 0\\0 & \mathrm i\end{matrix}\right]\).
- class SDG(target: int)¶
Bases:
_KindChecker,SingleTargetInstructionSDG circuit instruction.
The \(S^\dagger\) gate applies the matrix \(\left[\begin{matrix}1 & 0\\0 & - \mathrm i\end{matrix}\right]\).
We have \(S^\dagger = \mathrm e^{\mathrm i \frac \pi 4} R_Z(-\frac \pi 2)\).
- class T(target: int)¶
Bases:
_KindChecker,SingleTargetInstructionT circuit instruction.
The \(T\) gate applies the matrix \(\left[\begin{matrix}1 & 0\\0 & \mathrm e^{\mathrm i \frac \pi 4}\end{matrix}\right]\).
We have \(T = \mathrm e^{\mathrm i \frac \pi 8} R_Z(\frac \pi 4)\).
- class TDG(target: int)¶
Bases:
_KindChecker,SingleTargetInstructionTDG circuit instruction.
The \(T^\dagger\) gate applies the matrix \(\left[\begin{matrix}1 & 0\\0 & \mathrm e^{- \mathrm i \frac \pi 4}\end{matrix}\right]\).
We have \(T^\dagger = \mathrm e^{\mathrm i \frac \pi 8} R_Z(- \frac \pi 4)\).
- class SX(target: int)¶
Bases:
_KindChecker,SingleTargetInstructionSX circuit instruction.
The \(SX\) (\(\sqrt X\)) gate applies the matrix \(\frac 1 2 \left[\begin{matrix}1 + \mathrm i & 1 - \mathrm i\\1 - \mathrm i & 1 + \mathrm i\end{matrix}\right]\).
We have \(SX = \mathrm e^{\mathrm i \frac \pi 4} R_X(\frac \pi 2)\).
- class SXDG(target: int)¶
Bases:
_KindChecker,SingleTargetInstructionSXDG circuit instruction.
The \(SX^\dagger\) (\({\sqrt X}^\dagger\)) gate applies the matrix \(\frac 1 2 \left[\begin{matrix}1 - \mathrm i & 1 + \mathrm i\\1 + \mathrm i & 1 - \mathrm i\end{matrix}\right]\).
We have \(SX^\dagger = \mathrm e^{\mathrm i \frac \pi 4} R_X(-\frac \pi 2)\).
- class J(target: int, angle: Expression | float)¶
Bases:
_KindChecker,RotationInstructionJ circuit instruction.
The \(J(\theta)\) gate applies the matrix
\[\begin{split}\frac 1 {\sqrt 2} \left[\begin{matrix} 1 & \mathrm e^{\mathrm i \theta}\\ 1 & - \mathrm e^{\mathrm i \theta} \end{matrix}\right]\end{split}\]We have \(J(\theta) = \mathrm e^{\mathrm i \theta/2} H \mathrm{RZ}(\theta)\).
- __init__(target: int, angle: Expression | float) None¶
- class P(target: int, angle: Expression | float)¶
Bases:
_KindChecker,RotationInstructionP rotation circuit instruction.
The \(P(\theta)\) gate applies the matrix
\[\begin{split}\left[\begin{matrix} 1 & 0\\ 0 & \mathrm e^{\mathrm i \theta} \end{matrix}\right]\end{split}\]We have \(P(\theta) = \mathrm e^{\theta/2} R_Z(\theta)\).
- __init__(target: int, angle: Expression | float) None¶
- class RX(target: int, angle: Expression | float)¶
Bases:
_KindChecker,RotationInstructionX rotation circuit instruction.
The \(RX(\theta)\) gate applies the matrix
\[\begin{split}\left[\begin{matrix} \cos \frac \theta 2 & -\mathrm i \sin \frac \theta 2\\ -\mathrm i \sin \frac \theta 2 & \cos \frac \theta 2 \end{matrix}\right]\end{split}\]- __init__(target: int, angle: Expression | float) None¶
- class RY(target: int, angle: Expression | float)¶
Bases:
_KindChecker,RotationInstructionY rotation circuit instruction.
The \(RY(\theta)\) gate applies the matrix
\[\begin{split}\left[\begin{matrix} \cos \frac \theta 2 & - \sin \frac \theta 2\\ \sin \frac \theta 2 & \cos \frac \theta 2 \end{matrix}\right]\end{split}\]- __init__(target: int, angle: Expression | float) None¶
- class RZ(target: int, angle: Expression | float)¶
Bases:
_KindChecker,RotationInstructionZ rotation circuit instruction.
The \(RZ(\theta)\) gate applies the matrix
\[\begin{split}\left[\begin{matrix} \mathrm e^{-\mathrm i \frac \theta 2} & 0\\ 0 & \mathrm e^{\mathrm i \frac \theta 2} \end{matrix}\right]\end{split}\]- __init__(target: int, angle: Expression | float) None¶
- class U(target: int, theta: Expression | float, phi: Expression | float, lambda_: Expression | float)¶
Bases:
_KindChecker,BaseInstructionU circuit instruction.
The \(U(\theta, \phi, \lambda)\) gate applies the matrix
\[\begin{split}\left[\begin{matrix} \cos \frac \theta 2 & - \mathrm e^{\mathrm i\lambda} \sin \frac \theta 2 \\ \mathrm e^{\mathrm i \phi} \sin \frac \theta 2 & \mathrm e^{\mathrm i (\phi + \lambda)} \cos \frac \theta 2 \end{matrix}\right]\end{split}\]It can be decomposed as
\[U(\theta, \phi, \lambda) = \mathrm e^{\mathrm i\frac{\phi + \lambda}{2}} R_Z(\phi) R_Y(\theta) R_Z(\lambda) = \mathrm e^{\mathrm i\frac{\theta}{2}} H J\left(\phi + \frac{\pi}{2}\right) J(\theta) J\left(\lambda - \frac{\pi}{2}\right)\]- __init__(target: int, theta: Expression | float, phi: Expression | float, lambda_: Expression | float) None¶
- visit(visitor: InstructionVisitor, *, copy: bool = False) Self¶
Rewrite the instruction according to the given visitor.
- Parameters:
visitor (InstructionVisitor) – The visitor specifying the rewriting.
copy (bool, optional) – If
True, the current instruction remains unchanged, and a new instruction is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The rewritten instruction. Equal to
selfifcopyisFalse.- Return type:
Self
- theta: Expression | float¶
- phi: Expression | float¶
- lambda_: Expression | float¶
- class CJ(target: int, control: int, angle: Expression | float)¶
Bases:
_KindChecker,ControlledRotationInstructionControlled-J circuit instruction.
The \(CJ(\alpha)\) gate applies the matrix
\[\begin{split}\left[\begin{matrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & \frac 1 {\sqrt 2} & \frac 1 {\sqrt 2} \mathrm e^{\mathrm i \alpha}\\ 0 & 0 & \frac 1 {\sqrt 2} & - \frac 1 {\sqrt 2} \mathrm e^{\mathrm i \alpha} \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
control,target.Following Lemmas 4.3 and 5.1 of Barenco et al. (1995), we define:
\[\begin{split}\begin{aligned} A &= R_Y\left(\frac \pi 4\right),\\ B &= R_Y\left(- \frac \pi 4\right) R_Z(- \delta),\\ C &= R_Z(\delta),\\ \delta &= \frac {\alpha + \pi} 2 \end{aligned}\end{split}\]These operators satisfy \(ABC = I\) and \(AXBXC = \mathrm e^{-\mathrm i \delta} J(\alpha)\).
Consequently, \(CJ(\alpha)\) can be decomposed as:
\[CJ(\alpha) = (P(\delta) \otimes I) \, (I \otimes A) \, CX \, (I \otimes B) \, CX \, (I \otimes C)\]- angle¶
Rotation angle.
- Type:
ParameterizedAngle
References
Barenco, A., Bennett, C. H., Cleve, R., DiVincenzo, D. P., Margolus, N., Shor, P., Sleator, T., Smolin, J. A., & Weinfurter, H. (1995). Elementary gates for quantum computation. Physical Review A, 52(5), 3457-3467. https://doi.org/10.1103/physreva.52.3457
- class CP(target: int, control: int, angle: Expression | float)¶
Bases:
_KindChecker,ControlledRotationInstructionControlled-P circuit instruction.
The \(CP(\theta)\) gate applies the matrix
\[\begin{split}\left[\begin{matrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & \mathrm e^{\mathrm i \theta} \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
control,target.- angle¶
Phase angle.
- Type:
ParameterizedAngle
- class CRX(target: int, control: int, angle: Expression | float)¶
Bases:
_KindChecker,ControlledRotationInstructionControlled-X rotation circuit instruction.
The \(CRX(\theta)\) gate applies the matrix
\[\begin{split}\left[\begin{matrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & \cos \frac \theta 2 & -\mathrm i \sin \frac \theta 2\\ 0 & 0 & -\mathrm i \sin \frac \theta 2 & \cos \frac \theta 2 \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
control,target.- angle¶
Rotation angle.
- Type:
ParameterizedAngle
- class CRY(target: int, control: int, angle: Expression | float)¶
Bases:
_KindChecker,ControlledRotationInstructionControlled-Y rotation circuit instruction.
\[\begin{split}\left[\begin{matrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & \cos \frac \theta 2 & - \sin \frac \theta 2\\ 0 & 0 & \sin \frac \theta 2 & \cos \frac \theta 2 \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
control,target.- angle¶
Rotation angle.
- Type:
ParameterizedAngle
- class CRZ(target: int, control: int, angle: Expression | float)¶
Bases:
_KindChecker,ControlledRotationInstructionControlled-Z rotation circuit instruction.
\[\begin{split}\left[\begin{matrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & \mathrm e^{-\mathrm i \frac \theta 2} & 0\\ 0 & 0 & 0 & \mathrm e^{\mathrm i \frac \theta 2} \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
control,target.- angle¶
Rotation angle.
- Type:
ParameterizedAngle
- class CU(control: int, target: int, theta: Expression | float, phi: Expression | float, lambda_: Expression | float, gamma: Expression | float)¶
Bases:
_KindChecker,BaseInstructionControlled-U circuit instruction.
The \(CU(\theta, \phi, \lambda, \gamma)\) gate applies the matrix
\[\begin{split}\left[\begin{matrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \mathrm e^{\mathrm i\gamma} \cos\left(\frac{\theta}{2}\right) & -\mathrm e^{\mathrm i(\gamma + \lambda)} \sin\left(\frac{\theta}{2}\right) \\ 0 & 0 & \mathrm e^{\mathrm i(\gamma + \phi)} \sin\left(\frac{\theta}{2}\right) & \mathrm e^{\mathrm i(\gamma + \phi + \lambda)} \cos\left(\frac{\theta}{2}\right) \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
control,target.It can be decomposed as
\[CU(\theta, \phi, \lambda, \gamma) = \left(P\left(\frac{\gamma - \theta} 2\right) \otimes I\right) CJ(0) CJ\left(\phi + \frac \pi 2\right) CJ(\theta) CJ\left(\lambda - \frac \pi 2\right)\]- theta¶
Rotation angle around the Y axis.
- Type:
ParameterizedAngle
- phi¶
Rotation angle around the Z axis after the Y rotation.
- Type:
ParameterizedAngle
- lambda_¶
Rotation angle around the Z axis before the Y rotation.
- Type:
ParameterizedAngle
- gamma¶
Global phase angle.
- Type:
ParameterizedAngle
- __init__(control: int, target: int, theta: Expression | float, phi: Expression | float, lambda_: Expression | float, gamma: Expression | float) None¶
- visit(visitor: InstructionVisitor, *, copy: bool = False) Self¶
Rewrite the instruction according to the given visitor.
- Parameters:
visitor (InstructionVisitor) – The visitor specifying the rewriting.
copy (bool, optional) – If
True, the current instruction remains unchanged, and a new instruction is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The rewritten instruction. Equal to
selfifcopyisFalse.- Return type:
Self
- theta: Expression | float¶
- phi: Expression | float¶
- lambda_: Expression | float¶
- gamma: Expression | float¶
- class CNOT(target: int, control: int)¶
Bases:
_KindChecker,ControlledSingleTargetInstructionCNOT circuit instruction.
The CNOT gate applies the matrix
\[\begin{split}\left[\begin{matrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0 \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
control,target.
- class CY(target: int, control: int)¶
Bases:
_KindChecker,ControlledSingleTargetInstructionCY circuit instruction.
The CY gate applies the matrix
\[\begin{split}\left[\begin{matrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & -\mathrm i\\ 0 & 0 & \mathrm i & 0 \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
control,target.
- class CZ(targets: tuple[int, int])¶
Bases:
_KindChecker,BaseInstructionCZ circuit instruction.
The CZ gate applies the matrix
\[\begin{split}\left[\begin{matrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & -1 \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
targets[0],targets[1].- visit(visitor: InstructionVisitor, *, copy: bool = False) CZ¶
Rewrite the instruction according to the given visitor.
- Parameters:
visitor (InstructionVisitor) – The visitor specifying the rewriting.
copy (bool, optional) – If
True, the current instruction remains unchanged, and a new instruction is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The rewritten instruction. Equal to
selfifcopyisFalse.- Return type:
Self
- class CCX(target: int, controls: tuple[int, int])¶
Bases:
_KindChecker,BaseInstructionToffoli circuit instruction.
The CCX gate applies the matrix
\[\begin{split}\left[\begin{matrix} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
controls[0],controls[1],target.- visit(visitor: InstructionVisitor, *, copy: bool = False) CCX¶
Rewrite the instruction according to the given visitor.
- Parameters:
visitor (InstructionVisitor) – The visitor specifying the rewriting.
copy (bool, optional) – If
True, the current instruction remains unchanged, and a new instruction is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The rewritten instruction. Equal to
selfifcopyisFalse.- Return type:
Self
- class RZZ(target: int, control: int, angle: Expression | float)¶
Bases:
_KindChecker,BaseInstructionRZZ circuit instruction.
The \(\mathrm{RZZ}(\theta)\) gate applies the matrix
\[\begin{split}\left[\begin{matrix} \mathrm e^{-\mathrm i \frac \theta 2} & 0 & 0 & 0\\ 0 & \mathrm e^{\mathrm i \frac \theta 2} & 0 & 0\\ 0 & 0 & \mathrm e^{\mathrm i \frac \theta 2} & 0\\ 0 & 0 & 0 & \mathrm e^{-\mathrm i \frac \theta 2} \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
control,target.We have \(\mathrm{RZZ}(\theta) = \mathrm{CNOT} (I \otimes \mathrm{RZ}(\theta)) \mathrm{CNOT}\).
- angle¶
Rotation angle.
- Type:
ParameterizedAngle
- visit(visitor: InstructionVisitor, *, copy: bool = False) RZZ¶
Rewrite the instruction according to the given visitor.
- Parameters:
visitor (InstructionVisitor) – The visitor specifying the rewriting.
copy (bool, optional) – If
True, the current instruction remains unchanged, and a new instruction is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The rewritten instruction. Equal to
selfifcopyisFalse.- Return type:
Self
- angle: Expression | float¶
- class SWAP(targets: tuple[int, int])¶
Bases:
_KindChecker,BaseInstructionSWAP circuit instruction.
The SWAP gate applies the matrix
\[\begin{split}\left[\begin{matrix} 1 & 0 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1 \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
targets[0],targets[1].- visit(visitor: InstructionVisitor, *, copy: bool = False) SWAP¶
Rewrite the instruction according to the given visitor.
- Parameters:
visitor (InstructionVisitor) – The visitor specifying the rewriting.
copy (bool, optional) – If
True, the current instruction remains unchanged, and a new instruction is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The rewritten instruction. Equal to
selfifcopyisFalse.- Return type:
Self
- class CSWAP(control: int, targets: tuple[int, int])¶
Bases:
_KindChecker,BaseInstructionCSWAP circuit instruction.
The CSWAP gate applies the matrix
\[\begin{split}\left[\begin{matrix} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \end{matrix}\right]\end{split}\]in the computational basis. The basis states use big-endian ordering, with the most significant qubit first. The qubits are numbered in the order
control,targets[0],targets[1].- visit(visitor: InstructionVisitor, *, copy: bool = False) CSWAP¶
Rewrite the instruction according to the given visitor.
- Parameters:
visitor (InstructionVisitor) – The visitor specifying the rewriting.
copy (bool, optional) – If
True, the current instruction remains unchanged, and a new instruction is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The rewritten instruction. Equal to
selfifcopyisFalse.- Return type:
Self
- class M(target: int, axis: Axis)¶
Bases:
_KindChecker,BaseInstructionM circuit instruction.
- visit(visitor: InstructionVisitor, *, copy: bool = False) M¶
Rewrite the instruction according to the given visitor.
- Parameters:
visitor (InstructionVisitor) – The visitor specifying the rewriting.
copy (bool, optional) – If
True, the current instruction remains unchanged, and a new instruction is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The rewritten instruction. Equal to
selfifcopyisFalse.- Return type:
Self
- class GPHASE(angle: Expression | float)¶
Bases:
_KindChecker,BaseInstructionGPHASE circuit instruction.
- angle¶
Phase angle.
- Type:
ParameterizedAngle
- __init__(angle: Expression | float) None¶
- visit(visitor: InstructionVisitor, *, copy: bool = False) GPHASE¶
Rewrite the instruction according to the given visitor.
- Parameters:
visitor (InstructionVisitor) – The visitor specifying the rewriting.
copy (bool, optional) – If
True, the current instruction remains unchanged, and a new instruction is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The rewritten instruction. Equal to
selfifcopyisFalse.- Return type:
Self
- angle: Expression | float¶
- class KrausChannel(kraus_data: Iterable[KrausData])[source]¶
Bases:
objectQuantum channel class in the Kraus representation.
Defined by Kraus operators \(K_i\) with scalar prefactors
coef) \(c_i\), where the channel act on density matrix as \(\rho' = \sum_i K_i^\dagger \rho K_i\). The data should satisfy \(\sum K_i^\dagger K_i = I\).- __init__(kraus_data: Iterable[KrausData]) None[source]¶
Initialize
KrausChannelgiven a Kraus operator.- Parameters:
kraus_data (Iterable[KrausData]) – Iterable of Kraus operator data.
- Raises:
ValueError – If kraus_data is empty.
- class Measurement[source]¶
Bases:
AbstractMeasurement,ParameterizableAn MBQC measurement.
Base class for
BlochMeasurementandPauliMeasurement.This class contains three class variables
X,Y, andZfor the positive Pauli measurements on the three axes, and three static methodsXY,YZ, andXZ, each parameterized by an angle and returning a Bloch measurement on each of the three planes.The three static methods
XY,YZ, andXZare capitalized, contrary to what PEP 8 prescribes, to remain consistent with the names of the Pauli measurements and to match the names of the planes in thePlaneenum.- X: ClassVar[PauliMeasurement] = Measurement.X¶
- Y: ClassVar[PauliMeasurement] = Measurement.Y¶
- Z: ClassVar[PauliMeasurement] = Measurement.Z¶
- static XY(angle: Expression | float) BlochMeasurement[source]¶
Return a Bloch measurement on the XY plane.
- static YZ(angle: Expression | float) BlochMeasurement[source]¶
Return a Bloch measurement on the YZ plane.
- static XZ(angle: Expression | float) BlochMeasurement[source]¶
Return a Bloch measurement on the XZ plane.
- abstractmethod to_bloch() BlochMeasurement[source]¶
Return the measurement description as an angle and a plane on the Bloch sphere.
There is no unique Bloch representation for each Pauli measurement. For instance,
>>> from graphix.measurements import Measurement >>> Measurement.XY(0.5).to_pauli_or_none() == Measurement.YZ(0.5).to_pauli_or_none() == Measurement.Y True
This method follows the convention illustrated below:
>>> from graphix.measurements import PauliMeasurement >>> for pm in PauliMeasurement: ... print(f"{pm}.to_bloch() == {pm.to_bloch()}") +X.to_bloch() == Measurement.XY(0) -X.to_bloch() == Measurement.XY(1) +Y.to_bloch() == Measurement.XY(0.5) -Y.to_bloch() == Measurement.XY(1.5) +Z.to_bloch() == Measurement.YZ(0) -Z.to_bloch() == Measurement.YZ(1)
- abstractmethod downcast_bloch() BlochMeasurement[source]¶
Return the measurement description if it is already given as an angle and a plane on the Bloch sphere; raise
TypeErrorotherwise.Examples
>>> from graphix.measurements import Measurement >>> Measurement.XY(0).downcast_bloch() Measurement.XY(0) >>> Measurement.X.downcast_bloch() Traceback (most recent call last): ... TypeError: Bloch measurement expected, but Pauli measurement was found.
- abstractmethod to_pauli_or_none(rel_tol: float = 1e-09, abs_tol: float = 0.0) PauliMeasurement | None[source]¶
Return the measurement description as a Pauli measurement if possible, or
Noneotherwise.- Parameters:
rel_tol (float, optional) – Relative tolerance for comparing angles, passed to
math.isclose(). Default is1e-9.abs_tol (float, optional) – Absolute tolerance for comparing angles, passed to
math.isclose(). Default is0.0.
- Returns:
If
selfis already an instance ofPauliMeasurement, the function returnsself. Ifselfis an instance ofBlochMeasurement, then either the measurement is close to a Pauli measurement (i.e., the angle is close to an integer multiple of π/2) and the corresponding Pauli measurement is returned, or it is not andNoneis returned.- Return type:
PauliMeasurement | None
Notes
A measurement with a parameterized angle is not considered as Pauli, but can become a Pauli measurement after substitution.
Examples
>>> from graphix.measurements import Measurement >>> Measurement.XY(0.5).to_pauli_or_none() Measurement.Y >>> Measurement.Y.to_pauli_or_none() Measurement.Y >>> Measurement.XY(0.25).to_pauli_or_none() is None True >>> from graphix.parameter import Placeholder >>> alpha = Placeholder("alpha") >>> Measurement.XY(alpha).to_pauli_or_none() is None True >>> Measurement.XY(alpha).with_parameter(alpha, 0.5).to_pauli_or_none() Measurement.Y
- abstractmethod to_pauli_or_bloch(rel_tol: float = 1e-09, abs_tol: float = 0.0) PauliMeasurement | BlochMeasurement[source]¶
Return the measurement description as a Pauli measurement if possible, a Bloch measurement otherwise.
- Parameters:
rel_tol (float, optional) – Relative tolerance for comparing angles, passed to
math.isclose(). Default is1e-9.abs_tol (float, optional) – Absolute tolerance for comparing angles, passed to
math.isclose(). Default is0.0.
- Returns:
If
selfis already an instance ofPauliMeasurement, the function returnsself. Ifselfis an instance ofBlochMeasurement, then either the measurement is close to a Pauli measurement (i.e., the angle is close to an integer multiple of π/2) and the corresponding Pauli measurement is returned, or it is not andselfis returned.- Return type:
Examples
>>> from graphix.measurements import Measurement >>> Measurement.XY(0.5).to_pauli_or_bloch() Measurement.Y >>> Measurement.XY(0.25).to_pauli_or_bloch() Measurement.XY(0.25)
- class NoiseModel[source]¶
Bases:
ABCAbstract base class for all noise models.
- abstractmethod input_nodes(nodes: Iterable[int], rng: Generator | None = None, *, stacklevel: int = 1) list[CommandOrNoise][source]¶
Return the noise to apply to input nodes.
- abstractmethod command(cmd: CommandOrNoise, rng: Generator | None = None, *, stacklevel: int = 1) list[CommandOrNoise][source]¶
Return the noise to apply to the command
cmd.
- abstractmethod confuse_result(cmd: BaseM, result: Outcome, rng: Generator | None = None, *, stacklevel: int = 1) Outcome[source]¶
Return a possibly flipped measurement outcome.
- Parameters:
result (Outcome) – Ideal measurement result.
cmd (BaseM) – The measurement command that produced the given outcome.
- Returns:
Possibly corrupted result.
- Return type:
Outcome
- transpile(sequence: Iterable[CommandOrNoise], rng: Generator | None = None, *, stacklevel: int = 1) list[CommandOrNoise][source]¶
Apply the noise to a sequence of commands and return the resulting sequence.
- class OpenGraph(graph: nx.Graph[int], input_nodes: Sequence[int], output_nodes: Sequence[int], measurements: Mapping[int, _AM_co], output_cliffords: Mapping[int, Clifford] = <factory>)[source]¶
Bases:
Parameterizable,Simulable[_AM_co],Generic[_AM_co]An unmutable dataclass providing a representation of open graph states.
- graph¶
The underlying resource-state graph. Nodes represent qubits and edges represent the application of \(CZ\) gate on the linked nodes.
- Type:
- input_nodes¶
An ordered sequence of node labels corresponding to the open graph inputs.
- Type:
Sequence[int]
- output_nodes¶
An ordered sequence of node labels corresponding to the open graph outputs.
- Type:
Sequence[int]
- measurements¶
A mapping between the non-output nodes of the open graph (
key) and their corresponding measurement label (value). Measurement labels can be specified asMeasurement,PlaneorAxisinstances.- Type:
Mapping[int, _AM_co]
- output_cliffords¶
A mapping between output nodes of the open graph (
key) and Clifford operators. This attribute allows to preserve the semantics of (deterministic) patterns with local-clifford commands when extracting the open graph. SeePattern.to_opengraph().
Notes
The inputs and outputs of
OpenGraphinstances in Graphix are defined as ordered sequences of node labels. This contrasts the usual definition of open graphs in the literature, where inputs and outputs are unordered sets of nodes labels. This restriction facilitates the interplay withPatternobjects, where the order of input and output nodes represents a choice of Hilbert space basis.Example
>>> import networkx as nx >>> from graphix.opengraph import OpenGraph >>> from graphix.measurements import Measurement >>> >>> graph = nx.Graph([(0, 1), (1, 2)]) >>> measurements = {i: Measurement.XY(0.5 * i) for i in range(2)} >>> input_nodes = [0] >>> output_nodes = [2] >>> og = OpenGraph(graph, input_nodes, output_nodes, measurements)
- to_pattern(*, stacklevel: int = 1) Pattern[source]¶
Extract a deterministic pattern from an
OpenGraph[Measurement]if it exists.- Parameters:
stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.
- Returns:
A deterministic pattern on the open graph.
- Return type:
- Raises:
OpenGraphError – If the open graph does not have flow.
Notes
The open graph instance must be of parametric type
Measurementto allow for a pattern extraction, otherwise it does not contain information about the measurement angles.This method proceeds by searching a flow on the open graph and converting it into a pattern as prescripted in Ref. [1_to_pattern]. It first attempts to find a causal flow because the corresponding flow-finding algorithm has lower complexity. If it fails, it attemps to find a Pauli flow because this property is more general than a generalised flow, and the corresponding flow-finding algorithms have the same complexity in the current implementation.
References
[1_to_pattern]Browne et al., NJP 9, 250 (2007)
- draw(**options: Unpack[DrawKwargs]) None[source]¶
Visualize the opengraph.
- Parameters:
options (Unpack[DrawKwargs]) – Options controlling graph visualization. See
VisualizationOptions.
- map(f: Callable[[_A], _B]) OpenGraph[_B][source]¶
Apply a function to every measurement of the open graph and return the resulting open graph.
- Parameters:
f (Callable[[_A], _B]) – Function applied to each measurement.
- Returns:
The resulting open graph.
- Return type:
OpenGraph[_B]
Notes
The types of measurements can be changed by
f.Example
>>> import networkx as nx >>> from graphix.opengraph import OpenGraph >>> from graphix.measurements import Measurement >>> graph = nx.Graph([(0, 1), (1, 2)]) >>> measurements = {0: Measurement.XY(0.5), 1: Measurement.YZ(1)} >>> og = OpenGraph(graph, [0], [2], measurements) >>> og.map(lambda m: m.plane).measurements {0: Plane.XY, 1: Plane.YZ}
- to_bloch() OpenGraph[BlochMeasurement][source]¶
Return the open graph where all measurements are converted to Bloch.
Example
>>> import networkx as nx >>> from graphix.opengraph import OpenGraph >>> from graphix.measurements import Measurement >>> graph = nx.Graph([(0, 1), (1, 2)]) >>> measurements = {0: Measurement.X, 1: Measurement.Y} >>> og = OpenGraph(graph, [0], [2], measurements) >>> og.to_bloch().measurements {0: Measurement.XY(0), 1: Measurement.XY(0.5)}
- downcast_bloch() OpenGraph[BlochMeasurement][source]¶
Return the open graph if all measurements are described as Bloch measurements; raise
TypeErrorotherwise.If this method succeeds, the returned graph is identical to the original one, but this function narrows the static type of the measurements. The returned graph can be used with functions that require all measurements are described as Bloch measurements, such as
OpenGraph.to_causalflow().Example
>>> import networkx as nx >>> from graphix.opengraph import OpenGraph >>> from graphix.measurements import Measurement >>> graph = nx.Graph([(0, 1), (1, 2)]) >>> measurements = {0: Measurement.XY(0.5), 1: Measurement.YZ(1)} >>> og = OpenGraph(graph, [0], [2], measurements) >>> og.downcast_bloch().measurements {0: Measurement.XY(0.5), 1: Measurement.YZ(1)} >>> measurements = {0: Measurement.X, 1: Measurement.Y} >>> og = OpenGraph(graph, [0], [2], measurements) >>> og.downcast_bloch() Traceback (most recent call last): ... TypeError: Bloch measurement expected, but Pauli measurement was found.
- infer_pauli_measurements(rel_tol: float = 1e-09, abs_tol: float = 0.0) OpenGraph[Measurement][source]¶
Return an equivalent open graph in which Bloch measurements close to a Pauli measurement are replaced by Pauli measurements.
Pauli measurements are measurements with a Pauli angle, i.e. an integer multiple of \(\pi/2\).
This method can be used before calling methods such as
OpenGraph.to_pauliflow_or_none, that deal with Pauli measurements in a special way.- Parameters:
pattern (pattern) – Source pattern.
rel_tol (float, optional) – Relative tolerance for comparing angles, passed to
math.isclose(). Default is1e-9.abs_tol (float, optional) – Absolute tolerance for comparing angles, passed to
math.isclose(). Default is0.0.
- Returns:
An equivalent open graph in which Bloch measurements close to a Pauli measurement are replaced by Pauli measurements.
- Return type:
Example
>>> import networkx as nx >>> from graphix.opengraph import OpenGraph >>> from graphix.measurements import Measurement >>> graph = nx.Graph([(0, 1), (1, 2)]) >>> measurements = {0: Measurement.XY(0.5), 1: Measurement.YZ(1)} >>> og = OpenGraph(graph, [0], [2], measurements) >>> og.infer_pauli_measurements().measurements {0: Measurement.Y, 1: -Measurement.Z}
- isclose(other: OpenGraph[_AM_co], rel_tol: float = 1e-09, abs_tol: float = 0.0) bool[source]¶
Check if two open graphs are equal within a given tolerance.
- Parameters:
- Returns:
Trueif the two open graphs are approximately equal.- Return type:
Notes
- This method verifies the open graphs have:
Truly equal underlying graphs (not up to an isomorphism).
Equal input and output nodes.
Same measurement planes or axes and approximately equal measurement angles if the open graph is of parametric type
Measurement.Equal
output_cliffordsmappings.
The static typer does not allow an
isclosecomparison of two open graphs with different parametric type. For a structural comparison, seeOpenGraph.is_equal_structurally().
- is_equal_structurally(other: OpenGraph[AbstractMeasurement]) bool[source]¶
Compare the underlying structure of two open graphs.
- Parameters:
other (OpenGraph[AbstractMeasurement])
- Returns:
Trueifselfandoghave the same structure.- Return type:
Notes
This method verifies the open graphs have:
Truly equal underlying graphs (not up to an isomorphism).
Equal input and output nodes. This assumes equal types as well, i.e., if
self.input_nodesis alistandother.input_nodesis atuple, this method will returnFalse.Equal
output_cliffordsmappings.
It assumes the open graphs are well formed.
The static typer allows comparing the structure of two open graphs with different parametric type.
- neighbors(nodes: Collection[int]) set[int][source]¶
Return the set containing the neighborhood of a set of nodes in the open graph.
- odd_neighbors(nodes: Collection[int]) set[int][source]¶
Return the set containing the odd neighborhood of a set of nodes in the open graph.
- to_causalflow() CausalFlow[_PM_co][source]¶
Try to extract a causal flow on the open graph.
This method is a wrapper over
OpenGraph.to_causalflow_or_none()with a single return type.This method requires all measurements to be planar: to extract the causal flow from a graph that contains Pauli measurements, you can apply
OpenGraph.to_bloch()first.- Returns:
A causal flow object if the open graph has causal flow.
- Return type:
CausalFlow[_PM_co]
- Raises:
OpenGraphError – If the open graph does not have a causal flow.
See also
- to_gflow() GFlow[_PM_co][source]¶
Try to extract a maximally delayed generalised flow (gflow) on the open graph.
This method is a wrapper over
OpenGraph.to_gflow_or_none()with a single return type.This method requires all measurements to be planar: to extract a gflow from a graph that contains Pauli measurements, you can apply
OpenGraph.to_bloch()first.- Returns:
A gflow object if the open graph has gflow.
- Return type:
GFlow[_PM_co]
- Raises:
OpenGraphError – If the open graph does not have a gflow.
See also
- to_pauliflow(*, stacklevel: int = 1) PauliFlow[_AM_co][source]¶
Try to extract a maximally delayed Pauli on the open graph.
This method is a wrapper over
OpenGraph.to_pauliflow_or_none()with a single return type.- Parameters:
stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.
- Returns:
A Pauli flow object if the open graph has Pauli flow.
- Return type:
PauliFlow[_AM_co]
- Raises:
OpenGraphError – If the open graph does not have a Pauli flow.
- to_causalflow_or_none() CausalFlow[_PM_co] | None[source]¶
Return a causal flow on the open graph if it exists.
This method requires all measurements to be planar: to find the causal flow from a graph that contains Pauli measurements, you can apply
OpenGraph.to_bloch()first.- Returns:
A causal flow object if the open graph has causal flow or
Noneotherwise.- Return type:
CausalFlow[_PM_co] | None
See also
Notes
The open graph instance must be of parametric type
MeasurementorPlanesince the causal flow is only defined on open graphs with \(XY\) measurements.This function implements the algorithm presented in Ref. [1] with polynomial complexity on the number of nodes, \(O(N^2)\).
References
[1] Mhalla and Perdrix, (2008), Finding Optimal Flows Efficiently, doi.org/10.1007/978-3-540-70575-8_70
- to_gflow_or_none() GFlow[_PM_co] | None[source]¶
Return a maximally delayed Pauli on the open graph if it exists.
This method requires all measurements to be planar: to find a gflow in a graph that contains Pauli measurements, you can apply
OpenGraph.to_bloch()first.- Returns:
A gflow object if the open graph has gflow or
Noneotherwise.- Return type:
GFlow[_PM_co] | None
See also
Notes
The open graph instance must be of parametric type
MeasurementorPlanesince the gflow is only defined on open graphs with planar measurements. Measurement instances with a Pauli angle (integer multiple of \(\pi/2\)) are interpreted asPlaneinstances, in contrast withOpenGraph.to_pauliflow_or_none().This function implements the algorithm presented in Ref. [1] with polynomial complexity on the number of nodes, \(O(N^3)\).
References
[1] Mitosek and Backens, 2024 (arXiv:2410.23439).
- to_pauliflow_or_none(*, stacklevel: int = 1) PauliFlow[_AM_co] | None[source]¶
Return a maximally delayed Pauli on the open graph if it exists.
- Parameters:
stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.
- Returns:
A Pauli flow object if the open graph has Pauli flow or
Noneotherwise.- Return type:
PauliFlow[_AM_co] | None
Notes
Measurements are considered to be Pauli only if they are represented as
graphix.measurements.PauliMeasurement. The methodOpenGraph.infer_pauli_measurements()can be called first to convert all measurements with a Pauli angle (integer multiple of \(\pi/2\)) into Pauli measurements.This function implements the algorithm presented in Ref. [1] with polynomial complexity on the number of nodes, \(O(N^3)\).
References
[1] Mitosek and Backens, 2024 (arXiv:2410.23439).
Example
>>> import warnings >>> import networkx as nx >>> from graphix.opengraph import OpenGraph >>> from graphix.measurements import Measurement >>> graph = nx.Graph([(0, 1), (1, 2)]) >>> measurements = {0: Measurement.XZ(0.5), 1: Measurement.XZ(0.5)} >>> og = OpenGraph(graph, [0], [2], measurements) >>> with warnings.catch_warnings(): ... warnings.filterwarnings("ignore", message="Open graph with non-inferred Pauli measurements.") ... og.to_pauliflow() Traceback (most recent call last): ... graphix.opengraph.OpenGraphError: The open graph does not have a Pauli flow. >>> og.infer_pauli_measurements().measurements {0: Measurement.X, 1: Measurement.X} >>> str(og.infer_pauli_measurements().to_pauliflow()) 'p(0) = {1}, p(1) = {2}; {0, 1} < {2}'
- to_circuit(pexp_cp: Callable[[PauliExponentialDAG, Circuit], None] | None = None, cm_cp: Callable[[CliffordMap, Circuit], None] | None = None, *, stacklevel: int = 1) Circuit[source]¶
Extract a unitary in the form of a circuit from an open graph resource state.
This method acts as a wrapper around the circuit extraction routine, simplifying its usage. It first attempts to extract the Pauli flow of the open graph, then applies the circuit extraction procedure described in Ref. [1_to_circuit], and finally compiles the resulting circuit using the provided passes. To obtain the open graph’s unitary in the form of a Pauli exponential DAG along with a Clifford transformation, as presented in Ref. [1_to_circuit], one should instead operate directly on the flow object using
PauliFlow.extract_circuit().- Parameters:
pexp_cp (Callable[[PauliExponentialDAG, Circuit], None] | None) – Compilation pass to synthesize a Pauli exponential DAG. If
None(default),graphix.circ_ext.compilation.pexp_ladder_pass()is employed.cm_cp (Callable[[CliffordMap, Circuit], None] | None) – Compilation pass to synthesize a Clifford map. If
None(default),graphix.circ_ext.compilation.cm_berg_pass()is employed. This pass only handles unitaries so far (Clifford maps with the same number of input and ouptut nodes).stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.
- Returns:
Quantum circuit represented as a set of instructions.
- Return type:
Notes
The open graph instance must be of parametric type
Measurementto allow for a circuit extraction, otherwise it does not contain information about the measurement angles.This wrapper extracts a Pauli flow rather than a gflow, as the former is more general while the underlying extraction algorithms have the same computational complexity in both cases. The resulting unitary is identical whether it is obtained from a
GFlowor from aPauliFlowwith inferred Pauli measurements. However, compilation passes that simultaneously diagonalize Pauli exponentials within the same layer of the Pauli exponential DAG may benefit from flows of lower depth, which is often the case for Pauli flow. The passgraphix.circ_ext.compilation.pexp_ladder_pass()does not take into account the flow’s depth.
References
Examples
>>> import warnings >>> import networkx as nx >>> from graphix.opengraph import OpenGraph >>> from graphix.measurements import Measurement >>> og = OpenGraph( ... graph=nx.Graph([(0, 1), (1, 2), (3, 4), (4, 5), (6, 7), (7, 8), (1, 3), (4, 6)]), ... input_nodes=(0, 3, 6), ... output_nodes=(2, 5, 8), ... measurements=dict.fromkeys((0, 1, 3, 4, 6, 7), Measurement.XY(angle=0)), ... ) >>> with warnings.catch_warnings(): ... warnings.filterwarnings("ignore", message="Open graph with non-inferred Pauli measurements.") ... og.to_circuit() Circuit(width=3, instr=[H(2), H(1), CNOT(2, 1), H(1), H(1), H(0), CNOT(2, 0), CNOT(1, 0), H(2), H(1), H(0)]) >>> # The default compilation passes do not exploit the lower depth of the Pauli flow >>> # compared the gflow. >>> og.infer_pauli_measurements().to_circuit() Circuit(width=3, instr=[H(2), H(1), CNOT(2, 1), H(1), H(1), H(0), CNOT(2, 0), CNOT(1, 0), H(2), H(1), H(0)])
- compose(other: OpenGraph[_AM_co], mapping: Mapping[int, int]) tuple[OpenGraph[_AM_co], dict[int, int]][source]¶
Compose two open graphs by merging subsets of nodes from
selfandother, and relabeling the nodes ofotherthat were not merged.- Parameters:
- Returns:
og (OpenGraph[_AM_co]) – Composed open graph.
mapping_complete (dict[int, int]) – Complete relabelling of the nodes in
other, withkeysandvaluesdenoting the old and new node label, respectively.
Notes
Let’s denote \(\{G(V_1, E_1), I_1, O_1\}\) the open graph
self, \(\{G(V_2, E_2), I_2, O_2\}\) the open graphother, \(\{G(V, E), I, O\}\) the resulting open graphogand{v:u}an element ofmapping.We define \(V, U\) the set of nodes in
mapping.keys()andmapping.values(), and \(M = U \cap V_1\) the set of merged nodes.The open graph composition requires that
\(V \subseteq V_2\).
If both
vanduare measured, the corresponding measurements must have the same plane and angle.
The returned open graph follows this convention:
\(I = (I_1 \cup I_2) \setminus M \cup (I_1 \cap I_2 \cap M)\),
\(O = (O_1 \cup O_2) \setminus M \cup (O_1 \cap O_2 \cap M)\),
If only one node of the pair
{v:u}is measured, this measure is assigned to \(u \in V\) in the resulting open graph.Input (and, respectively, output) nodes in the returned open graph have the order of the open graph
selffollowed by those of the open graphother. Merged nodes are removed, except when they are input (or output) nodes in both open graphs, in which case, they appear in the order they originally had in the graphself.Clifford operations on output nodes:
if two output nodes \(o_1\) and \(o_2\) are merged, then \(C(o_1) = C_2(o_2) \circ C_1(o_1)\);
if an output node \(o_1\) is merged with a measured node \(m_2\), then \(M(o_1) = M_2(m_2) \circ C_1(o_1)\);
if a measured node \(m_1\) is merged with an output node \(o_2\), then \(M(m_1) = M_1(m_1) \circ C_2(o_2)\).
- with_parameter(variable: Parameter, substitute: ExpressionOrSupportsFloat) OpenGraph[_M][source]¶
Substitute a parameter with a value or expression in all measurement angles.
Creates a new open graph where every measurement angle containing the specified variable is updated using the provided substitution. The original open graph instance remains unmodified.
- Parameters:
variable (Parameter) – The symbolic expression to be replaced within the measurement angles.
substitute (ExpressionOrSupportsFloat) – The value or symbolic expression to substitute in place of
variable.
- Returns:
A new instance of OpenGraph with the updated measurement parameters.
- Return type:
Notes
Substitution relies on object identity. You must provide the exact parameter object instance currently stored in the measurements. Passing a new object with the same name will not trigger a substitution if it is not the same instance in memory.
Examples
>>> import networkx as nx >>> from graphix.fundamentals import Plane >>> from graphix.measurements import Measurement >>> from graphix.opengraph import OpenGraph >>> from graphix.parameter import Placeholder >>> # Initialize placeholders and open graph >>> parametric_angles = [Placeholder(f"alpha{i}") for i in range(2)] >>> measurements = {node: Measurement.XY(angle) for node, angle in enumerate(parametric_angles)} >>> og = OpenGraph( ... graph=nx.Graph([(0, 1), (1, 2)]), ... input_nodes=[0], ... output_nodes=[2], ... measurements=measurements, ... ) >>> # To perform substitution, use the actual object in memory >>> new_og = og.with_parameter(parametric_angles[0], 0.3) >>> # Note: og.with_parameter(Placeholder("alpha0"), 0.3) would not trigger any substitution.
- with_parameters(assignment: Mapping[Parameter, ExpressionOrSupportsFloat]) OpenGraph[_M][source]¶
Perform parallel substitution of multiple parameters in measurement angles.
Creates a new open graph where occurrences of parameters defined in the assignment mapping are replaced by their corresponding values. The original open graph instance remains unmodified.
- Parameters:
assignment (Mapping[Parameter, ExpressionOrSupportsFloat]) – A dictionary-like mapping where keys are the
Parameterobjects to be replaced and values are the new expressions or numerical values.- Returns:
A new instance of OpenGraph with the updated measurement angles.
- Return type:
Notes
The notes provided in
self.subs()apply here as well.Examples
>>> import networkx as nx >>> from graphix.fundamentals import Plane >>> from graphix.measurements import Measurement >>> from graphix.opengraph import OpenGraph >>> from graphix.parameter import Placeholder >>> # Initialize placeholders >>> alpha = Placeholder("alpha") >>> beta = Placeholder("beta") >>> measurements = {0: Measurement.XY(alpha), 1: Measurement.XY(beta)} >>> og = OpenGraph(nx.Graph([(0, 1)]), [0], [], measurements) >>> # Substitute multiple parameters at once >>> subs_map = {alpha: 0.5, beta: 1.2} >>> new_og = og.with_parameters(subs_map)
- class OutputFormat(*values)[source]¶
Bases:
EnumEnumeration of the output format for pretty-printing.
- ASCII = 1¶
- LaTeX = 2¶
- Unicode = 3¶
- class Pattern(input_nodes: Iterable[int] | None = None, cmds: Iterable[CommandType] | None = None, output_nodes: Iterable[int] | None = None)[source]¶
Bases:
InplaceParameterizable,Simulable[Measurement]MBQC pattern class.
Pattern holds a sequence of commands to operate the MBQC (Pattern.seq), and provide modification strategies to improve the structure and simulation efficiency of the pattern accoring to measurement calculus.
ref: V. Danos, E. Kashefi and P. Panangaden. J. ACM 54.2 8 (2007)
- __init__(input_nodes: Iterable[int] | None = None, cmds: Iterable[CommandType] | None = None, output_nodes: Iterable[int] | None = None) None[source]¶
Construct a pattern.
- Parameters:
input_nodes (Iterable[int] | None) – Optional. List of input qubits.
cmds (Iterable[CommandType] | None) – Optional. List of initial commands.
output_nodes (Iterable[int] | None) – Optional. List of output qubits.
- add(cmd: CommandType) None[source]¶
Add command to the end of the pattern.
An MBQC command is an instance of
graphix.command.CommandType.- Parameters:
cmd (
graphix.command.CommandType) – MBQC command.
- extend(*cmds: CommandType | Iterable[CommandType]) None[source]¶
Add sequences of commands.
- Parameters:
cmds – sequences of commands
- replace(cmds: list[CommandType], input_nodes: list[int] | None = None) None[source]¶
Replace pattern with a given sequence of pattern commands.
- Parameters:
cmds – list of commands
input_nodes – optional, list of input qubits (by default, keep the same input nodes as before)
- node_mapping(mapping: Mapping[Node, Node] | None = None, *, start: int = 0, avoids: Collection[Node] | None = None, preserves: Collection[Node] | None = None) dict[Node, Node][source]¶
Compute an injective mapping of node indices.
The resulting mapping can be passed to
reindex(). Fresh indices are allocated in increasing order, starting atstartand skipping any values already used.- Parameters:
mapping (Mapping[Node, Node] | None, optional) – An initial (partial) mapping that will be extended. A
ValueErroris raised if the supplied mapping is not injective.start (int, optional) – The starting index from which fresh indices are allocated.
avoids (Collection[Node] | None, optional) – Indices that must not be assigned to a node.
preserves (Collection[Node] | None, optional) – Nodes that should not appear in the mapping. Their index will not be changed by
reindex().
- Returns:
A dictionary that maps each node of
self(except those listed inpreserves) to a distinct integer index.- Return type:
dict[Node, Node]
Notes
The resulting dictionary is guaranteed to be an extension of
mapping, i.e., all entries frommappingappear in the resulting dictionary. In particular, the constraints specified inavoidsandpreservesonly affect nodes that are freshly generated by the function; they do not apply to the nodes already present inmapping.
- reindex(mapping: Callable[[Node], Node] | Mapping[Node, Node] | None = None, *, copy: bool = False) Pattern[source]¶
Return a pattern whose nodes have been re-indexed using
f.This method does not verify that
fis injective. The semantic of the pattern is only preserved whenfis injective. A non-injective mapping can even break the runnability of the resulting pattern.- Parameters:
mapping (Callable[[Node], Node] | Mapping[Node, Node] | None, optional) – A function or a mapping that translates the current node indices to new ones. Indices that are not present in the mapping are left unchanged. If
fis omitted, a default mapping is computed by usingnode_mapping().copy (bool, optional) – If
True, the current pattern remains unchanged, and a new pattern is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The re-indexed pattern. Equal to
selfifcopyisFalse.- Return type:
- compose(other: Pattern, mapping: Mapping[int, int], preserve_mapping: bool = False) tuple[Pattern, dict[int, int]][source]¶
Compose two patterns by merging subsets of outputs from
selfand a subset of inputs ofother, and relabeling the nodes ofotherthat were not merged.- Parameters:
other (Pattern) – Pattern to be composed with
self.mapping (Mapping[int, int]) – Partial relabelling of the nodes in
other, withkeysandvaluesdenoting the old and new node labels, respectively.preserve_mapping (bool) – Boolean flag controlling the ordering of the output nodes in the returned pattern.
- Returns:
p (Pattern) – composed pattern
mapping_complete (dict[int, int]) – Complete relabelling of the nodes in
other, withkeysandvaluesdenoting the old and new node label, respectively.
Notes
Let’s denote \((I_j, O_j, V_j, S_j)\) the ordered set of inputs and outputs, the computational space and the sequence of commands of pattern \(P_j\), respectively, with \(j = 1\) for pattern
selfand \(j = 2\) for patternother. Let’s denote \(P\) the resulting pattern with \((I, O, V, S)\). Let’s denote \(K, U\) the sets ofkeysandvaluesofmapping, \(M_1 = O_1 \cap U\) the set of merged outputs, and \(M_2 = \{k \in I_2 \cap K | k \rightarrow v, v \in M_1 \}\) the set of merged inputs.The pattern composition requires that
\(K \subseteq V_2\).
- For a pair \((k, v) \in (K, U)\)
\(U \cap V_1 \setminus O_1 = \emptyset\). If \(v \in O_1\), then \(k \in I_2\), otherwise an error is raised.
\(v\) can always satisfy \(v \notin V_1\), thereby allowing a custom relabelling.
The returned pattern follows this convention:
Nodes of pattern
othernot specified inmapping(i.e., \(V_2 \cap K^c\)) are relabelled in ascending order.The sequence of the resulting pattern is \(S = S_2 S_1\), where nodes in \(S_2\) are relabelled according to
mapping.\(I = I_1 \cup (I_2 \setminus M_2)\).
\(O = (O_1 \setminus M_1) \cup O_2\).
Input (and, respectively, output) nodes in the returned pattern have the order of the pattern
selffollowed by those of the patternother. Merged nodes are removed.If
preserve_mapping = Trueand \(|M_1| = |I_2| = |O_2|\), then the outputs of the returned pattern are the outputs of patternself, where the nth merged output is replaced by the output of patternothercorresponding to its nth input instead.
- property output_nodes: list[int]¶
List all nodes that are either
input_nodesor prepared withNcommands and that have not been measured with anMcommand.
- property n_node: int¶
Count of nodes that are either
input_nodesor prepared withNcommands.
- reorder_output_nodes(output_nodes: Iterable[int]) None[source]¶
Arrange the order of output_nodes.
- Parameters:
output_nodes (iterable of int) – output nodes order determined by user. each index corresponds to that of logical qubits.
- reorder_input_nodes(input_nodes: Iterable[int]) None[source]¶
Arrange the order of input_nodes.
- Parameters:
input_nodes (iterable of int) – input nodes order determined by user. each index corresponds to that of logical qubits.
- to_ascii(left_to_right: bool = False, limit: int | None = 40, target: Container[command.CommandKind] | None = None) str[source]¶
Return the ASCII string representation of the pattern.
- Parameters:
left_to_right (bool, optional) – If
True, the first command will appear at the beginning of the resulting string. IfFalse(the default), the first command will appear at the end of the string.limit (int | None, optional) – If set to an int (default: 40), only first
limitcommands are printed, and an ellipsis is added at the end to indicate that some commands have been elided. Iflimit=None, there is no limit on the number of printed commands.target (Container[command.CommandKind], optional) – If set, only commands of kinds specified in
targetare printed.
Examples
>>> from graphix import Circuit >>> circuit = Circuit(1) >>> circuit.h(0) >>> pattern = circuit.transpile().pattern >>> pattern.to_ascii() 'X(1,{0}) M(0,0) E(0,1) N(1)' >>> pattern.to_ascii(left_to_right=True) 'N(1) E(0,1) M(0,0) X(1,{0})' >>> from graphix.command import CommandKind >>> pattern.to_ascii(target={CommandKind.M}) 'M(0,0)' >>> pattern.to_ascii(target={CommandKind.X, CommandKind.Z}) 'X(1,{0})' >>> circuit = Circuit(3) >>> circuit.ccx(0, 1, 2) >>> pattern = circuit.transpile().pattern >>> pattern.to_ascii(limit=5) 'X(24,{21}) Z(24,{20}) X(32,{31}) Z(32,{28})...(98 more commands)' >>> pattern.to_ascii(limit=5, left_to_right=True) 'N(3) E(2,3) M(2,0) N(4)...(98 more commands)' >>> pattern.to_ascii(limit=None) 'X(24,{21}) Z(24,{20}) X(32,{31}) Z(32,{28}) X(30,...E(4,1) [M(3,0)]{2} E(3,4) N(4) M(2,0) E(2,3) N(3)'
- to_latex(left_to_right: bool = False, limit: int | None = 40, target: Container[command.CommandKind] | None = None) str[source]¶
Return a string containing the LaTeX representation of the pattern.
- Parameters:
left_to_right (bool, optional) – If
True, the first command will appear at the beginning of the resulting string. IfFalse(the default), the first command will appear at the end of the string.limit (int | None, optional) – If set to an int (default: 40), only first
limitcommands are printed, and an ellipsis is added at the end to indicate that some commands have been elided. Iflimit=None, there is no limit on the number of printed commands.target (Container[command.CommandKind], optional) – If set, only commands of kinds specified in
targetare printed.
Examples
>>> from graphix import Circuit >>> circuit = Circuit(1) >>> circuit.h(0) >>> pattern = circuit.transpile().pattern >>> pattern.to_latex() '\\(X_{1}^{0}\\,M_{0}^{0}\\,E_{0,1}\\,N_{1}\\)' >>> pattern.to_latex(left_to_right=True) '\\(N_{1}\\,E_{0,1}\\,M_{0}^{0}\\,X_{1}^{0}\\)' >>> from graphix.command import CommandKind >>> pattern.to_latex(target={CommandKind.M}) '\\(M_{0}^{0}\\)' >>> pattern.to_latex(target={CommandKind.X, CommandKind.Z}) '\\(X_{1}^{0}\\)'
- to_unicode(left_to_right: bool = False, limit: int | None = 40, target: Container[command.CommandKind] | None = None) str[source]¶
Return the Unicode string representation of the pattern.
- Parameters:
left_to_right (bool, optional) – If
True, the first command will appear at the beginning of the resulting string. IfFalse(the default), the first command will appear at the end of the string.limit (int | None, optional) – If set to an int (default: 40), only first
limitcommands are printed, and an ellipsis is added at the end to indicate that some commands have been elided. Iflimit=None, there is no limit on the number of printed commands.target (Container[command.CommandKind], optional) – If set, only commands of kinds specified in
targetare printed.
Examples
>>> from graphix import Circuit >>> circuit = Circuit(1) >>> circuit.h(0) >>> pattern = circuit.transpile().pattern >>> pattern.to_unicode() 'X₁⁰ M₀(0) E₀₋₁ N₁' >>> pattern.to_unicode(left_to_right=True) 'N₁ E₀₋₁ M₀(0) X₁⁰' >>> from graphix.command import CommandKind >>> pattern.to_unicode(target={CommandKind.M}) 'M₀(0)' >>> pattern.to_unicode(target={CommandKind.X, CommandKind.Z}) 'X₁⁰'
- standardize() None[source]¶
Execute standardization of the pattern.
‘standard’ pattern is one where commands are sorted in the order of ‘N’, ‘E’, ‘M’ and then byproduct commands (‘X’ and ‘Z’) and finally Clifford commands (‘C’).
- shift_signals(method: str = 'direct') dict[int, set[int]][source]¶
Perform signal shifting procedure.
Extract the t-dependence of the measurement into ‘S’ commands and commute them to the end of the command sequence where it can be removed. This procedure simplifies the dependence structure of the pattern.
- Ref for the original ‘mc’ method:
Danos, E. Kashefi and P. Panangaden. J. ACM 54.2 8 (2007)
- Parameters:
method (str, optional) – ‘direct’ shift_signals is executed on a conventional Pattern sequence. ‘mc’ shift_signals is done using the original algorithm in the measurement calculus paper.
- Returns:
signal_dict – For each node, the signal that have been shifted.
- Return type:
- signals() dict[int, set[int]][source]¶
Extract ‘t’ domain of measurement commands, turn them into signal ‘S’ commands and add to the command sequence.
This is used for shift_signals() method.
- partial_order_layers() tuple[frozenset[int], ...][source]¶
Extract the measurement order of the pattern in the form of layers.
This method standardizes the pattern, builds a directed acyclical graph (DAG) from measurement and correction domains, and then performs a topological sort.
- Returns:
Measurement partial order between the pattern’s nodes in a layer form.
- Return type:
- Raises:
RunnabilityError – If the pattern is not runnable.
Notes
This function wraps
optimization.StandardizedPattern.partial_order_layers(), and the returned object is described in the notes of this method.
- to_causalflow() CausalFlow[BlochMeasurement][source]¶
Extract the causal flow structure from the current measurement pattern.
This method does not call the flow-extraction routine on the underlying open graph, but constructs the flow from the pattern corrections instead.
- Returns:
The causal flow associated with the current pattern.
- Return type:
- Raises:
FlowError – If the pattern: - Contains measurements in forbidden planes (XZ or YZ), - Is empty, or - Induces a correction function and a partial order which fail the well-formedness checks for a valid causal flow.
ValueError – If
Ncommands in the pattern do not represent a \(|+\rangle\) state or if the pattern corrections form closed loops.
Notes
Applying the chain
Pattern.to_causalflow().to_xzcorrections().to_pattern()to a strongly deterministic pattern returns a new pattern implementing the same unitary transformation. This equivalence holds as long as the original pattern contains no Clifford commands, since those are discarded during open-graph extraction.This method requires that all the measurements in the pattern are represented as Bloch measurements (i.e., there are no
PauliMeasurement`s). Use :meth:`to_bloch()to convert all Pauli measurements.
- to_gflow() GFlow[BlochMeasurement][source]¶
Extract the generalized flow (gflow) structure from the current measurement pattern.
This method does not call the flow-extraction routine on the underlying open graph, but constructs the gflow from the pattern corrections instead.
- Returns:
The gflow associated with the current pattern.
- Return type:
- Raises:
FlowError – If the pattern is empty or if the extracted structure does not satisfy the well-formedness conditions required for a valid gflow.
ValueError – If
Ncommands in the pattern do not represent a \(|+\rangle\) state or if the pattern corrections form closed loops.
Notes
The notes provided in
self.to_causalflow()apply here as well.
- to_pauliflow() PauliFlow[Measurement][source]¶
Extract the Pauli flow structure from the current measurement pattern.
This method does not call the flow-extraction routine on the underlying open graph, but reconstructs the Pauli flow from the pattern corrections instead (see
graphix.flow.core.XZCorrections.to_pauliflow()). Contrary toto_causalflow()andto_gflow(), Pauli measurements are kept as axes rather than downcast to planar Bloch measurements, so that the Pauli-basis structure is preserved.- Returns:
The Pauli flow associated with the current pattern.
- Return type:
- Raises:
FlowError – If the pattern is empty or if no Pauli flow is compatible with the pattern corrections.
ValueError – If
Ncommands in the pattern do not represent a \(|+\rangle\) state or if the pattern corrections form closed loops.
Notes
The notes provided in
self.to_causalflow()apply here as well.
- to_xzcorrections() XZCorrections[Measurement][source]¶
Extract the XZ-corrections from the current measurement pattern.
- Returns:
The XZ-corrections associated with the current pattern.
- Return type:
- Raises:
XZCorrectionsError – If the extracted correction dictionaries are not well formed.
ValueError – If
Ncommands in the pattern do not represent a \(\ket{+}\) state or if the pattern corrections form closed loops.
Notes
To ensure that applying the chain
Pattern.to_xzcorrections().to_pattern()to a strongly deterministic pattern returns a new pattern implementing the same unitary transformation, XZ-corrections must be extracted from a standardized pattern. This requirement arises for the same reason that flow extraction also operates correctly on standardized patterns only. This equivalence holds as long as the original pattern contains no Clifford commands, since those are discarded during open-graph extraction. See docstring inoptimization.StandardizedPattern.to_gflow()for additional information.
- sort_measurement_commands(meas_order: list[int]) list[M][source]¶
Convert measurement order to sequence of measurement commands.
- measurement_commands() dict[int, M][source]¶
Return a dictionary mapping nodes to measurement commands.
- max_degree() int[source]¶
Get max degree of a pattern.
- Returns:
max_degree – max degree of a pattern
- Return type:
- to_opengraph() OpenGraph[Measurement][source]¶
Extract the underlying resource-state open graph from the pattern.
This method standardizes the pattern first to guarantee that Clifford commands are properly encoded in the resulting open graph. Specifically, Cliffords acting on measured nodes are absorbed into measurements, while Cliffords acting on output nodes are stored in
OpenGraph.output_cliffords.- Return type:
- clifford_commands() dict[int, Clifford][source]¶
Extract Clifford commands.
- Returns:
vops
- Return type:
- connected_nodes(node: int, prepared: set[int] | None = None) list[int][source]¶
Find nodes that are connected to a specified node.
These nodes must be in the statevector when the specified node is measured, to ensure correct computation. If connected nodes already exist in the statevector (prepared), then they will be ignored as they do not need to be prepared again.
- parallelize_pattern() None[source]¶
Optimize the pattern to reduce the depth of the computation by gathering measurement commands that can be performed simultaneously.
This optimized pattern runs efficiently on GPUs and quantum hardwares with depth (e.g. coherence time) limitations.
- minimize_space(heuristics: Iterable[SpaceMinimizationHeuristic] | None = None, *, copy: bool = False) Pattern[source]¶
Return a pattern that reduces the maximal space, i.e. the number of qubits simultaneously required to execute the pattern.
See
graphix.space_minimization.minimize_space()for more information about the default heuristics.To obtain a space-optimal pattern while preserving the measurement order, use
minimize_space([]). This commutes theNandEcommands so that the pattern is space-optimal among patterns with the same measurement order (seeStandardizedPattern.to_space_optimal_pattern()).- Parameters:
heuristics (Iterable[SpaceMinimizationHeuristic] | None = None) – The heuristics to try in order. By default,
DEFAULT_HEURISTICSis used.copy (bool, optional) – If
True, the current pattern remains unchanged and a new pattern is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The optimized pattern. Equal to
selfifcopyisFalse.- Return type:
- max_space() int[source]¶
Compute the maximum number of nodes that must be present in the graph (graph space) during the execution of the pattern.
For statevector simulation, this is equivalent to the maximum memory needed for classical simulation.
- Returns:
n_nodes – max number of nodes present in the graph during pattern execution.
- Return type:
- space_list() list[int][source]¶
Return the list of the number of nodes present in the graph (space) during each step of execution of the pattern (for N and M commands).
- Returns:
N_list – time evolution of ‘space’ at each ‘N’ and ‘M’ commands of pattern.
- Return type:
- remove_input_nodes() None[source]¶
Remove the input nodes from the pattern and replace them with N commands.
This removes the possibility of choosing the input state, fixing the input state to the plus state. .. seealso::
graphix.command.N
- draw(*, annotations: DrawPatternAnnotations | None = DrawPatternAnnotations.Flow, flow_from_pattern: bool = True, stacklevel: int = 1, **options: Unpack[DrawKwargs]) None[source]¶
Visualize the underlying graph of the pattern with annotations.
- Parameters:
annotations (DrawPatternAnnotations | None, default=DrawPatternAnnotations.Flow) –
- Annotations to be shown.
DrawPatternAnnotations.Flow(default): show the pattern’s flow if it exists.DrawPatternAnnotations.XZCorrections: show the pattern’s XZ-corrections.None: show the underlying open graph only.
flow_from_pattern (bool, default=True) – If
True, the command sequence of the pattern is used to derive a flow structure. IfFalse, only the underlying open graph is used.options (Unpack[DrawKwargs]) – Options controlling graph visualization. See
VisualizationOptions.stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.
- Raises:
PatternError – If the underlying open graph does not have flow.
Notes
If
flow_from_pattern==Truebut the pattern is not compatible with a causal flow, gflow, or Pauli flow, an attempt to extract the flow from the underlying open graph will be made while warning the user.
- to_qasm3(filename: Path | str, input_state: dict[int, State] | State = graphix.states.PlanarState(Plane.XY, 0)) None[source]¶
Export measurement pattern to OpenQASM 3.0 file.
- is_parameterized() bool[source]¶
Return
Trueif there is at least one measurement angle that is not just an instance ofSupportsFloat.A parameterized pattern is a pattern where at least one measurement angle is an expression that is not a number, typically an instance of
sympy.Expr(but we don’t force to choosesympyhere).
- replace_parameter(variable: Parameter, substitute: ExpressionOrSupportsFloat, *, copy: bool = False) Pattern[source]¶
Substitute all occurrences of the given variable in measurement angles by the given value.
- Parameters:
variable (Parameter) – The symbolic expression to be replaced within the measurement angles.
substitute (ExpressionOrSupportsFloat) – The value or symbolic expression to substitute in place of
variable.copy (bool, optional) – If
True, the current object remains unchanged and a new object is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The object with the updated measurement parameters. Equal to
selfifcopyisFalse.- Return type:
Self
- replace_parameters(assignment: Mapping[Parameter, ExpressionOrSupportsFloat], *, copy: bool = False) Pattern[source]¶
Substitute all occurrences of the given keys in measurement angles by the given values in parallel.
- Parameters:
assignment (Mapping[Parameter, ExpressionOrSupportsFloat]) – A dictionary-like mapping where keys are the
Parameterobjects to be replaced and values are the new expressions or numerical values.copy (bool, optional) – If
True, the current object remains unchanged and a new object is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The object with the updated measurement parameters. Equal to
selfifcopyisFalse.- Return type:
Self
- check_runnability() None[source]¶
Check whether the pattern is runnable.
Raises
RunnabilityErrorexception if it is not.Notes
The runnability check can only guarantee the runnability of MBQC+LC patterns. Patterns that make use of custom :class:
BaseNand :class:BaseMcommands can have additional runnability constraints that are not checked by this method. For instance, in the Veriphix implementation of VBQC, blind measurements have hidden domains that cannot be checked.
- apply(f: Callable[[Measurement], Measurement], *, copy: bool = False) Pattern[source]¶
Apply the function
fto each measurement.- Parameters:
f (Callable[[Measurement], Measurement]) – Function applied to each measurement.
copy (bool, optional) – If
True, the current pattern remains unchanged and a new pattern is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
The resulting pattern. If
copyisFalse, the result isself.- Return type:
Example
>>> from graphix import Pattern, command >>> from graphix.measurements import BlochMeasurement, Measurement >>> pattern = Pattern(input_nodes=[0], cmds=[command.M(0, Measurement.XZ(0.25))]) >>> pattern.apply(lambda m: BlochMeasurement(m.angle + 1, m.plane)) Pattern(input_nodes=[0], cmds=[M(0, Measurement.XZ(1.25))]) >>> pattern Pattern(input_nodes=[0], cmds=[M(0, Measurement.XZ(1.25))])
- map(f: Callable[[Measurement], Measurement]) Pattern[source]¶
Return a pattern where the function
fhas been applied to each measurement.Equivalent to
self.apply(f, copy=True).- Parameters:
f (Callable[[Measurement], Measurement]) – Function applied to each measurement.
- Returns:
The resulting pattern.
- Return type:
Example
>>> from graphix import Pattern, command >>> from graphix.measurements import BlochMeasurement, Measurement >>> pattern = Pattern(input_nodes=[0], cmds=[command.M(0, Measurement.XZ(0.25))]) >>> pattern.map(lambda m: BlochMeasurement(m.angle + 1, m.plane)) Pattern(input_nodes=[0], cmds=[M(0, Measurement.XZ(1.25))]) >>> pattern Pattern(input_nodes=[0], cmds=[M(0, Measurement.XZ(0.25))])
- infer_pauli_measurements(*, rel_tol: float = 1e-09, abs_tol: float = 0.0, copy: bool = False) Pattern[source]¶
Replace Bloch measurements close to a Pauli measurement by Pauli measurements.
- Parameters:
rel_tol (float, optional) – Relative tolerance for comparing angles, passed to
math.isclose(). Default is1e-9.abs_tol (float, optional) – Absolute tolerance for comparing angles, passed to
math.isclose(). Default is0.0.copy (bool, optional) – If
True, the current pattern remains unchanged and a new pattern is returned. The default isFalse, meaning that changes are performed in place.
- Returns:
A pattern in which Bloch measurements close to a Pauli measurement are replaced by Pauli measurements. If
copyisFalse, the result isself.- Return type:
Example
>>> from graphix import Pattern, command >>> from graphix.measurements import BlochMeasurement, Measurement >>> pattern = Pattern(input_nodes=[0], cmds=[command.M(0, Measurement.XY(0.5))]) >>> pattern.infer_pauli_measurements() Pattern(input_nodes=[0], cmds=[M(0, Measurement.Y)])
- blochify(*, copy: bool = False) Pattern[source]¶
Represent all measurements as Bloch measurements.
- Parameters:
copy (bool, optional) – If
True, the current pattern remains unchanged and a new pattern is returned. The default isFalse, meaning that changes are performed in place.- Returns:
A pattern in which all measurements are Bloch measurements. If
copyisFalse, the result isself.- Return type:
Example
>>> from graphix import Pattern, command >>> from graphix.measurements import BlochMeasurement, Measurement >>> pattern = Pattern(input_nodes=[0], cmds=[command.M(0, Measurement.Y)]) >>> pattern.blochify() Pattern(input_nodes=[0], cmds=[M(0, Measurement.XY(0.5))]) >>> pattern Pattern(input_nodes=[0], cmds=[M(0, Measurement.XY(0.5))])
- to_bloch() Pattern[source]¶
Return an equivalent pattern in which all measurements are represented as Bloch measurements.
Equivalent to
self.blochify(copy=True).Example
>>> from graphix import Pattern, command >>> from graphix.measurements import BlochMeasurement, Measurement >>> pattern = Pattern(input_nodes=[0], cmds=[command.M(0, Measurement.Y)]) >>> pattern.to_bloch() Pattern(input_nodes=[0], cmds=[M(0, Measurement.XY(0.5))]) >>> pattern Pattern(input_nodes=[0], cmds=[M(0, Measurement.Y)])
- perform_pauli_pushing(*, leave_nodes: Set[int] | None = None, copy: bool = False, standardize: bool = False, stacklevel: int = 1) Pattern[source]¶
Move Pauli measurements before the other measurements.
If you need to recover the cut between Pauli measurements and non-Pauli measurements or the shifted signal, you can use
from_standardizedpattern()instead.- Parameters:
leave_nodes (AbstractSet[Node], optional) – Nodes that should not be moved. This constraint only applies to Pauli nodes and has no effect on non-Pauli nodes.
copy (bool, optional) – If
True, the current pattern remains unchanged and a new pattern is returned. The default isFalse, meaning that changes are performed in place.standardize (bool, optional) – If
True, the pattern is returned in standardized form. The default isFalse: the nodes are prepared on a need-by-need basis, minimizing space usage.stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.
- Returns:
The pattern in which Pauli measurements have been moved before the other measurements. If
copyisFalse, the result isself.- Return type:
Notes
This function relies on
StandardizedPattern.perform_pauli_pushing().
- remove_pauli_measurements(*, copy: bool = False, standardize: bool = False, stacklevel: int = 1) Pattern[source]¶
Remove non-input Pauli measurements from the given pattern.
See
remove_pauli_measurements()for more information.- Parameters:
copy (bool, optional) – If
True, the current pattern remains unchanged and a new pattern is returned. The default isFalse, meaning that changes are performed in place.standardize (bool, optional) – If
True, the pattern is returned in standardized form. The default isFalse: the nodes are prepared on a need-by-need basis, minimizing space usage.stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.
- Returns:
The pattern in which Pauli measurements have been moved before the other measurements. If
copyisFalse, the result isself.- Return type:
- remove_local_clifford_commands(*, copy: bool = False) Pattern[source]¶
Return an equivalent pattern where local Clifford commands have been replaced by MBQC commands.
See
remove_local_clifford_commands()for more information.- Parameters:
copy (bool, optional) – If
True, the current pattern remains unchanged and a new pattern is returned. The default isFalse, meaning that changes are performed in place.stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.
- Returns:
The pattern in which local Clifford commands have been replaced by MBQC commands. If
copyisFalse, the result isself.- Return type:
- class Pauli(symbol: IXYZ = SingletonI.I, unit: ComplexUnit = ComplexUnit.ONE)[source]¶
Bases:
objectPauli gate:
u * {I, X, Y, Z}where u is a complex unit.Pauli gates can be multiplied with other Pauli gates (with
@), with complex units and unit constants (with*), and can be negated.- symbol: IXYZ = 1¶
- unit: ComplexUnit = 0¶
- property matrix: npt.NDArray[np.complex128]¶
Return the matrix of the Pauli gate.
- eigenstate(binary: int = 0) PlanarState[source]¶
Return the eigenstate of the Pauli.
- static iterate(symbol_only: bool = False) Iterator[Pauli][source]¶
Iterate over all Pauli gates.
- Parameters:
(bool (symbol_only)
optional) (Exclude the unit in the iteration. Defaults to False.)
- __init__(symbol: IXYZ = SingletonI.I, unit: ComplexUnit = ComplexUnit.ONE) None¶
- class PauliExponential(angle: Expression | float, pauli_string: PauliString)[source]¶
Bases:
objectDataclass representing a Pauli exponential.
A Pauli exponential corresponds to the unitary operator
\[U(\alpha) = \exp \left(i \frac{\alpha}{2} P\right),\]where \(\alpha\) is a real-valued angle and \(P\) is a Pauli string.
- angle¶
The Pauli exponential angle \(\alpha\) in units of \(\pi\). When extracted from a corrected node, it corresponds to the node’s measurement divided by two.
- Type:
ParameterizedAngle
- pauli_string¶
The signed Pauli string \(P\) specifying the tensor product of Pauli operators acting on qubit indices.
- Type:
- angle: Expression | float¶
- pauli_string: PauliString¶
- static from_measured_node(flow: PauliFlow[Measurement], node: Node) PauliExponential[source]¶
Extract the Pauli exponential of a measured node and its focused correction set.
- Parameters:
flow (PauliFlow[Measurement]) – A focused Pauli flow. The resulting Pauli string is extracted from its correction function.
node (int) – A measured node whose associated Pauli string is computed.
- Returns:
Primary extraction string associated to the input measured nodes. The sets in the returned
PauliStringinstance are disjoint.- Return type:
Notes
See Eq. (13) and Lemma 4.4 in Ref. [1]. The phase of the Pauli string is given by Eq. (37).
References
[1] Simmons, 2021 (arXiv:2109.05654).
- __init__(angle: Expression | float, pauli_string: PauliString) None¶
- class PauliExponentialDAG(pauli_exponentials: Mapping[int, PauliExponential], partial_order_layers: Sequence[AbstractSet[int]], output_nodes: Sequence[int])[source]¶
Bases:
objectDataclass to represent a multi-qubit rotation formed by a sequence of Pauli exponentials extracted from a pattern.
- pauli_exponentials¶
Mapping between measured nodes (
keys) and Pauli exponentials (values).- Type:
Mapping[int, PauliExponential]
- partial_order_layers¶
Partial order between the Pauli exponentials in a layer form. The set
layers[i]comprises the nodes in layeri. Nodes in layeriare “larger” in the partial order than nodes in layeri+1. The pattern’s output nodes are always in layer 0.- Type:
Sequence[AbstractSet[int]]
Notes
See Definition 3.3 in Ref. [1].
The Pauli strings in the Pauli exponentials are defined on qubit indices which correspond to the indices of the sequence
output_nodes.References
[1] Simmons, 2021 (arXiv:2109.05654).
- pauli_exponentials: Mapping[int, PauliExponential]¶
- static from_focused_flow(flow: PauliFlow[Measurement]) PauliExponentialDAG[source]¶
Extract a Pauli exponential rotation from a focused Pauli flow.
This routine associates a Pauli exponential to each measured node in
flow. The flow’s partial order defines a partial order between the Pauli exponentials such that Pauli exponentials in the same layer commute.- Parameters:
flow (PauliFlow[Measurement]) – A focused Pauli flow.
- Return type:
Notes
See Definition 3.3 and Example C.13 in Ref. [1].
References
[1] Simmons, 2021 (arXiv:2109.05654).
- class PauliFlow(og: OpenGraph[_AM_co], correction_function: Mapping[int, AbstractSet[int]], partial_order_layers: Sequence[AbstractSet[int]], _CF_PREFIX: str = 'p')[source]¶
Bases:
Parameterizable,Simulable[_AM_co],Generic[_AM_co]An unmutable dataclass providing a representation of a Pauli flow.
- correction_function¶
Pauli flow correction function.
correction_function[i]is the set of qubits correcting the measurement of qubiti.
- partial_order_layers¶
Partial order between the open graph’s nodes in a layer form. The set
layers[i]comprises the nodes in layeri. Nodes in layeriare “larger” in the partial order than nodes in layeri+1. Output nodes are always in layer 0 if there are any.- Type:
Sequence[AbstractSet[int]]
Notes
See Definition 5 in Ref. [1] for a definition of Pauli flow.
The flow’s correction function defines a partial order (see Def. 2.8 and 2.9, Lemma 2.11 and Theorem 2.12 in Ref. [2]), therefore, only
ogandcorrection_functionare necessary to initialize anPauliFlowinstance (seePauliFlow.from_correctionmatrix_or_none()). However, flow-finding algorithms generate a partial order in a layer form, which is necessary to extract the flow’s XZ-corrections, so it is stored as an attribute.
References
[1] Browne et al., 2007 New J. Phys. 9 250 (arXiv:quant-ph/0702212). [2] Mitosek and Backens, 2024 (arXiv:2410.23439).
- classmethod from_correctionmatrix_or_none(correction_matrix: CorrectionMatrix[_AM_co]) Self | None[source]¶
Initialize a
PauliFlowobject from a matrix encoding a correction function.- Parameters:
correction_matrix (CorrectionMatrix[_AM_co]) – Algebraic representation of the correction function.
- Returns:
A Pauli flow if it exists,
Noneotherwise.- Return type:
Self | None
Notes
This method verifies if there exists a partial measurement order on the input open graph compatible with the input correction matrix. See Lemma 3.12, and Theorem 3.1 in Ref. [1]. Failure to find a partial order implies the non-existence of a Pauli flow if the correction matrix was calculated by means of Algorithms 2 and 3 in [1].
References
[1] Mitosek and Backens, 2024 (arXiv:2410.23439).
- to_xzcorrections() XZCorrections[_AM_co][source]¶
Compute the X and Z corrections induced by the Pauli flow encoded in
self.- Return type:
XZCorrections[_AM_co]
Notes
This method partially implements Theorem 4 in [1]. The generated X and Z corrections can be used to obtain a robustly deterministic pattern on the underlying open graph.
References
[1] Browne et al., 2007 New J. Phys. 9 250 (arXiv:quant-ph/0702212).
- to_pattern(total_measurement_order: TotalOrder | None = None) Pattern[source]¶
Generate a pattern from this
PauliFlow[Measurement]instance.See
XZCorrections.to_pattern()for further details about thetotal_measurement_orderparameter and the exceptions that may be raised.
- is_well_formed() bool[source]¶
Verify if flow is well formed.
This method is a wrapper over
self.check_well_formed`()catching the ``FlowError` exceptions.- Return type:
Trueifselfis a well-formed flow,Falseotherwise.
- check_well_formed() None[source]¶
Verify if the Pauli flow is well formed.
- Raises:
FlowError – if the Pauli flow is not well formed.
Notes
- General properties of flows:
The domain of the correction function is \(O^c\), the non-output nodes of the open graph.
The image of the correction function is a subset of \(I^c\), the non-input nodes of the open graph.
The nodes in the partial order are the nodes in the open graph.
The first layer of the partial order layers contains the outputs of the open graph if there are any.
- Specific properties of Pauli flows:
If \(j \in p(i), i \neq j, \lambda(j) \notin \{X, Y\}\), then \(i \prec j\) (P1).
If \(j \in Odd(p(i)), i \neq j, \lambda(j) \notin \{Y, Z\}\), then \(i \prec j\) (P2).
If \(neg i \prec j, i \neq j, \lambda(j) = Y\), then either \(j \notin p(i)\) and \(j \in Odd((p(i)))\) or \(j \in p(i)\) and \(j \notin Odd((p(i)))\) (P3).
If \(\lambda(i) = XY\), then \(i \notin p(i)\) and \(i \in Odd((p(i)))\) (P4).
If \(\lambda(i) = XZ\), then \(i \in p(i)\) and \(i \in Odd((p(i)))\) (P5).
If \(\lambda(i) = YZ\), then \(i \in p(i)\) and \(i \notin Odd((p(i)))\) (P6).
If \(\lambda(i) = X\), then \(i \in Odd((p(i)))\) (P7).
If \(\lambda(i) = Z\), then \(i \in p(i)\) (P8).
If \(\lambda(i) = Y\), then either \(i \notin p(i)\) and \(i \in Odd((p(i)))\) or \(i \in p(i)\) and \(i \notin Odd((p(i)))\) (P9),
where \(i \in O^c\), \(c\) is the correction function, \(prec\) denotes the partial order, \(\lambda(i)\) is the measurement plane or axis of node \(i\), and \(Odd(s)\) is the odd neighbourhood of the set \(s\) in the open graph.
See Definition 5 in Ref. [1] or Definition 2.4 in Ref. [2].
References
[1] Browne et al., 2007 New J. Phys. 9 250 (arXiv:quant-ph/0702212). [2] Mitosek and Backens, 2024 (arXiv:2410.23439).
- node_measurement_label(node: int) Plane | Axis[source]¶
Get the measurement label of a given node in the open graph.
This method interprets measurements with a Pauli angle as
Axisinstances, in consistence with the Pauli flow extraction routine.
- to_ascii(multiline: bool = False) str[source]¶
Return an ASCII string representing the flow’s correction function and partial order layers.
- to_latex(multiline: bool = False) str[source]¶
Return a string containing the LaTeX representation of the flow’s correction function and partial order layers.
See notes in
to_ascii()for additional information.
- to_unicode(multiline: bool = False) str[source]¶
Return a Unicode string representing the flow’s correction function and partial order layers.
See notes in
to_ascii()for additional information.
- draw(**options: Unpack[DrawKwargs]) None[source]¶
Visualize the opengraph, correction structure and partial order.
- Parameters:
options (Unpack[DrawKwargs]) – Options controlling graph visualization. See
VisualizationOptions.
- with_parameter(variable: Parameter, substitute: ExpressionOrSupportsFloat) _T_PauliFlowMeasurement[source]¶
Substitute a parameter with a value or expression in all measurement angles of the open graph.
- Parameters:
variable (Parameter) – The symbolic expression to be replaced within the measurement angles.
substitute (ExpressionOrSupportsFloat) – The value or symbolic expression to substitute in place of
variable.
- Returns:
A new instance of the flow object with the updated measurement parameters.
- Return type:
_T_PauliFlowMeasurement
Notes
See notes and examples in
OpenGraph.with_parameter().
- with_parameters(assignment: Mapping[Parameter, ExpressionOrSupportsFloat]) _T_PauliFlowMeasurement[source]¶
Perform parallel substitution of multiple parameters in measurement angles of the open graph.
- Parameters:
assignment (Mapping[Parameter, ExpressionOrSupportsFloat]) – A dictionary-like mapping where keys are the
Parameterobjects to be replaced and values are the new expressions or numerical values.- Returns:
A new instance of the flow object with the updated measurement angles.
- Return type:
_T_PauliFlowMeasurement
Notes
See notes and examples in
OpenGraph.with_parameters().
- is_focused() bool[source]¶
Verify if the input Pauli flow is focused.
- Returns:
Trueif the input Pauli flow is focused,Falseotherwise.- Return type:
Notes
This function verifies Definition 4.3 in Ref. [1].
References
[1] Simmons, 2021 (arXiv:2109.05654).
- property extraction_pauli_strings: dict[int, PauliString][source]¶
Compute the extraction Pauli strings associated with each node in the correction function.
This property requires the flow to be focused.
- Returns:
A dictionary where the keys are node indices (from the correction function) and the values are the computed
PauliStringobjects.- Return type:
- Raises:
ValueError – If the flow is not focused (i.e.,
self.is_focused()is False).
Notes
This property is cached; the dictionary is computed only once upon the first access and stored for subsequent calls. See notes in
PauliString.from_measured_nodefor additional information.
- extract_circuit(*, stacklevel: int = 1) ExtractionResult[source]¶
Extract a circuit from a flow.
This routine assumes that the flow
selfis focused (see Notes).- Parameters:
stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.
- Returns:
Wrapper over a Pauli-exponential DAG and a Clifford map encoding the linear transformation implemented by the input flow.
- Return type:
Notes
This method implements the algorithm in [1].
Flows are guaranteed to be focused if obtained from
OpenGraph.to_pauliflow()orOpenGraph.to_gflow()(see [2]).
References
[1] Simmons, 2021 (arXiv:2109.05654). [2] Mitosek and Backens, 2024 (arXiv:2410.23439).
- class PauliMeasurement(axis: Axis, sign: Sign = Sign.PLUS)[source]¶
Bases:
MeasurementPauli measurement.
- to_pauli() Pauli[source]¶
Return the Pauli gate.
This method returns an instance of
Pauliand should not be confused withto_pauli_or_none(), which overrides the method fromMeasurement, and returnsself.Examples
>>> from graphix.measurements import Measurement >>> Measurement.X.to_pauli() Pauli.X >>> (-Measurement.Y).to_pauli() -Pauli.Y
- to_bloch() BlochMeasurement[source]¶
Return the measurement description as an angle and a plane on the Bloch sphere.
There is no unique Bloch representation for each Pauli measurement. For instance,
>>> from graphix.measurements import Measurement >>> Measurement.XY(0.5).to_pauli_or_none() == Measurement.YZ(0.5).to_pauli_or_none() == Measurement.Y True
This method follows the convention illustrated below:
>>> from graphix.measurements import PauliMeasurement >>> for pm in PauliMeasurement: ... print(f"{pm}.to_bloch() == {pm.to_bloch()}") +X.to_bloch() == Measurement.XY(0) -X.to_bloch() == Measurement.XY(1) +Y.to_bloch() == Measurement.XY(0.5) -Y.to_bloch() == Measurement.XY(1.5) +Z.to_bloch() == Measurement.YZ(0) -Z.to_bloch() == Measurement.YZ(1)
- downcast_bloch() BlochMeasurement[source]¶
Raise
TypeError(overridden fromMeasurement).
- to_pauli_or_none(rel_tol: float = 1e-09, abs_tol: float = 0.0) PauliMeasurement[source]¶
Return
self(overridden fromMeasurement).
- to_pauli_or_bloch(rel_tol: float = 1e-09, abs_tol: float = 0.0) PauliMeasurement[source]¶
Return
self(overridden fromMeasurement).
- to_plane_or_axis() Axis[source]¶
Return
self.axis(overridden fromMeasurement).
- isclose(other: AbstractMeasurement, rel_tol: float = 1e-09, abs_tol: float = 0.0) bool[source]¶
Determine whether this measurement is close to another.
Subclasses should implement a notion of “closeness” between two measurements, comparing measurement-specific attributes. The default comparison for
floatvalues involves checking equality within given relative or absolute tolerances.- Parameters:
other (AbstractMeasurement) – The measurement to compare against.
rel_tol (float, optional) – Relative tolerance for determining closeness. Relevant for comparing angles in the
Measurementsubclass. Default is1e-9.abs_tol (float, optional) – Absolute tolerance for determining closeness. Relevant for comparing angles in the
Measurementsubclass. Default is0.0.
- Returns:
Trueif this measurement is considered close tootheraccording to the subclass’s comparison rules;Falseotherwise.- Return type:
- clifford(clifford_gate: Clifford) PauliMeasurement[source]¶
Return a new measurement command with a
Cliffordapplied.- Parameters:
clifford_gate (Clifford) – Clifford gate to apply before the measurement.
- Returns:
Equivalent measurement representing the pattern
MC.- Return type:
Self
Notes
The return type is
Self, meaning that a Clifford applied to a Bloch measurement returns a Bloch measurement, and a Clifford applied to a Pauli measurement returns a Pauli measurement.The method
Measurement.clifford()does not always commute with the methodMeasurement.to_bloch(): the underlying Pauli measurement will be the same but the Bloch representation can be on different planes.
Examples
>>> from graphix.clifford import Clifford >>> from graphix.measurements import Measurement, PauliMeasurement >>> Measurement.XY(0.25).clifford(Clifford.H) Measurement.YZ(1.75) >>> Measurement.X.clifford(Clifford.S) -Measurement.Y >>> for pauli in PauliMeasurement: ... for clifford in Clifford: ... assert pauli.to_bloch().clifford(clifford).to_pauli_or_none() == pauli.clifford(clifford) >>> Measurement.Y.clifford(Clifford.H).to_bloch() Measurement.XY(1.5) >>> Measurement.Y.to_bloch().clifford(Clifford.H) Measurement.YZ(1.5)
- with_parameter(variable: Parameter, substitute: ExpressionOrSupportsFloat) Self[source]¶
Substitute a parameter with a value or expression.
- class PauliString(dim: int, axes: Mapping[int, Axis], sign: Sign = Sign.PLUS)[source]¶
Bases:
objectDataclass representing a Pauli string.
Notes
The identity operators in the Pauli string are omitted in
axes, but they can be inferred from the dimension of the Hilbert spacedim.- static from_str(ps: str) PauliString[source]¶
Construct a PauliString from its string representation.
The sign prefix (
'+'or'-') is optional; if omitted, the sign defaults toSign.PLUS.- Parameters:
ps (str) – String encoding of a Pauli string. Optionally starts with
'+'or'-', followed by zero or more single-character Pauli operators ('X','Y','Z', or'I').- Returns:
The PauliString instance corresponding to the input string.
- Return type:
- Raises:
ValueError – If the first character is not
'+'or'-'or a valid operator character, or any operator character is not one of'X','Y','Z','I'.
Examples
>>> PauliString.from_str("+XYZ") PauliString(dim=3, axes={0: Axis.X, 1: Axis.Y, 2: Axis.Z}, sign=Sign.PLUS) >>> PauliString.from_str("-IXI") PauliString(dim=3, axes={1: Axis.X}, sign=Sign.MINUS) >>> PauliString.from_str("X") PauliString(dim=1, axes={0: Axis.X}, sign=Sign.PLUS) >>> PauliString.from_str("") PauliString(dim=0, axes={}, sign=Sign.PLUS)
- static from_tableau(tab: MatGF2) PauliString[source]¶
Construct a
PauliStringfrom a one-dimensional tableau representation.The tableau encodes a Pauli operator of the form \(\pm P_0 \otimes P_1 \otimes \cdots \otimes P_{n-1}\), where each single-qubit Pauli is stored as an (x, z) bit pair and the final element encodes the sign.
Layout of
tab(length2n + 1):[ x_0, x_1, …, x_{n-1} | z_0, z_1, …, z_{n-1} | sign ]Encoding conventions:
(x=1, z=0)→ X(x=0, z=1)→ Z(x=1, z=1)→ Y(x=0, z=0)→ I (identity, qubit absent inaxes)sign = 0→ +1sign = 1→ -1
- Parameters:
tab (MatGF2) – A one-dimensional GF(2) array of odd length
2n + 1representing an n-qubit Pauli operator.- Returns:
The Pauli operator encoded by
tab.- Return type:
- Raises:
ValueError – If
tabis not one-dimensional orlen(tab)is even.
Examples
>>> tab = MatGF2(np.array([1, 1, 1])) >>> PauliString.from_tableau(tab) PauliString(dim=1, axes={0: Axis.Y}, sign=Sign.MINUS) >>> tab = MatGF2(np.array([0, 0, 0, 1, 0])) >>> PauliString.from_tableau(tab) PauliString(dim=2, axes={1: Axis.Z}, sign=Sign.PLUS)
- to_tableau() MatGF2[source]¶
Serialise this PauliString into a one-dimensional tableau representation.
Produces the inverse of
from_tableau(): aMatGF2of length2n + 1whose layout is:[ x_0, x_1, …, x_{n-1} | z_0, z_1, …, z_{n-1} | sign ]Encoding conventions:
X →
(x=1, z=0)Z →
(x=0, z=1)Y →
(x=1, z=1)I →
(x=0, z=0)(absent inself.axes)+sign →0-sign →1
- Returns:
A one-dimensional GF(2) array of length
2 * self.dim + 1.- Return type:
MatGF2
Examples
>>> ps = PauliString.from_str("-XY") >>> ps.to_tableau() MatGF2([1, 1, 0, 1, 1], dtype=uint8)
- class Placeholder(name: str)[source]¶
Bases:
AffineExpression,ParameterPlaceholder for measurement angles.
These placeholder may appear in affine expressions. Placeholders and affine expressions may be used as angles in rotation gates of
Circuitclass or for the measurement angle of the measurement commands. Pattern optimizations such that standardization, signal shifting and Pauli preprocessing can be applied to patterns with placeholders.These placeholders and affine expressions do not support arbitrary computation and are not suitable for simulation. You may use
Circuit.subs()orPattern.subs()with an actual value before the computation.
- class PlanarState(plane: Plane, angle: float)[source]¶
Bases:
StateLight object used to instantiate backends.
doesn’t cover all possible states but this is covered in
graphix.sim.statevec.Statevectorandgraphix.sim.densitymatrix.DensityMatrixconstructors.- Parameters:
plane (
graphix.pauli.Plane) – One of the three planes (XY, XZ, YZ)angle (float) – Angle (in units of π)
- Returns:
State
- Return type:
graphix.states.Stateobject
- class Plane(*values)[source]¶
Bases:
AbstractPlanarMeasurement,EnumReprMixin,EnumPlane: XY, YZ or XZ.
- XY = 1¶
- YZ = 2¶
- XZ = 3¶
- polar(angle: float) tuple[float, float, float][source]¶
- polar(angle: Expression) tuple[Expression, Expression, Expression]
Return the Cartesian coordinates of the point of module 1 at the given angle, following the conventional orientation for cos and sin.
- clifford(clifford_gate: Clifford) Plane[source]¶
Return a new measurement command with a
Cliffordapplied.- Parameters:
clifford_gate (Clifford) – Clifford gate to apply before the measurement.
- Returns:
Equivalent measurement representing the pattern
MC.- Return type:
Self
Notes
The return type is
Self, meaning that a Clifford applied to a Bloch measurement returns a Bloch measurement, and a Clifford applied to a Pauli measurement returns a Pauli measurement.The method
Measurement.clifford()does not always commute with the methodMeasurement.to_bloch(): the underlying Pauli measurement will be the same but the Bloch representation can be on different planes.
Examples
>>> from graphix.clifford import Clifford >>> from graphix.measurements import Measurement, PauliMeasurement >>> Measurement.XY(0.25).clifford(Clifford.H) Measurement.YZ(1.75) >>> Measurement.X.clifford(Clifford.S) -Measurement.Y >>> for pauli in PauliMeasurement: ... for clifford in Clifford: ... assert pauli.to_bloch().clifford(clifford).to_pauli_or_none() == pauli.clifford(clifford) >>> Measurement.Y.clifford(Clifford.H).to_bloch() Measurement.XY(1.5) >>> Measurement.Y.to_bloch().clifford(Clifford.H) Measurement.YZ(1.5)
- class RandomBranchSelector(pr_calc: bool = True)[source]¶
Bases:
BranchSelectorRandom branch selector.
- Parameters:
pr_calc (bool, optional) – Whether to compute the probability distribution before selecting the measurement result. If
False, measurements yield 0/1 with equal probability (50% each). Default isTrue.
- measure(qubit: int, f_expectation0: Callable[[], float], rng: Generator | None = None, *, stacklevel: int = 1) Outcome[source]¶
Return the measurement outcome of
qubit.If
pr_calcisTrue, the measurement outcome is determined based on the computed probability of outcome 0. Otherwise, the result is randomly chosen with a 50% chance for either outcome.
- class SpaceMinimizationHeuristics[source]¶
Bases:
objectPredefined heuristics.
- static causal_flow(pattern: StandardizedPattern) SpaceMinimizationHeuristicResult | None[source]¶
Use the causal flow layer to minimize space.
This minimization heuristic is optimal but requires the pattern to have a causal flow.
- static order_unchanged(pattern: StandardizedPattern) SpaceMinimizationHeuristicResult | None[source]¶
Leave the measurement order unchanged.
Since this heuristic preserves the original measurement order, it cannot return a pattern with worse max space than the original.
Usually, this heuristic is included in the list of heuristics considered to ensure that the result of space minimization cannot have a worse max space than the original pattern. This is the case by default, but the user can remove this heuristic from the list to see the effect of the other heuristics even if they don’t reduce the max space of the pattern.
- static greedy_degree(pattern: StandardizedPattern) SpaceMinimizationHeuristicResult | None[source]¶
Choose greedily the nodes by minimal degree.
This minimization heuristic can improve but can also worsen the max space in some situations.
- class StandardizedPattern(input_nodes: Iterable[Node], output_nodes: Iterable[Node], n_list: Iterable[command.N], e_set: Iterable[Iterable[Node]], m_list: Iterable[command.M], z_dict: Mapping[Node, Iterable[Node]], x_dict: Mapping[Node, Iterable[Node]], c_dict: Mapping[Node, Clifford])[source]¶
Bases:
_StandardizedPattern,Simulable[Measurement]Pattern in standardized form.
Use the method
to_pattern()to get the standardized pattern.This class uses immutable data structures for its fields (
tuple,frozensetandMapping).Instances can be generated with the constructor from any compatible data structures, and an instance can be generated directly from a pattern with the class method
from_pattern().The constructor instantiates the
Mappingfields asMappingProxyTypeobjects over fresh dictionaries, ensuring their immutability. We expose the typeMappinginstead ofMappingProxyTypefor the readability, as they provide the same interface.- c_dict¶
Mapping associating Clifford corrections to some output nodes.
- Type:
Mapping[Node, Clifford]
- __init__(input_nodes: Iterable[Node], output_nodes: Iterable[Node], n_list: Iterable[command.N], e_set: Iterable[Iterable[Node]], m_list: Iterable[command.M], z_dict: Mapping[Node, Iterable[Node]], x_dict: Mapping[Node, Iterable[Node]], c_dict: Mapping[Node, Clifford]) None[source]¶
Return a new StandardizedPattern with immutable data structures.
- classmethod from_pattern(pattern: Pattern) Self[source]¶
Compute the standardized form of the given pattern.
- graph() nx.Graph[int][source]¶
Return the graph state from the command sequence, extracted from ‘N’ and ‘E’ commands.
- Returns:
graph_state
- Return type:
nx.Graph
- perform_pauli_pushing(leave_nodes: AbstractSet[Node] | None = None, *, stacklevel: int = 1) StandardizedPattern[source]¶
Move Pauli measurements before the other measurements.
If you need to recover the cut between Pauli measurements and non-Pauli measurements or the shifted signal, you can use
from_standardizedpattern()instead.- Parameters:
leave_nodes (AbstractSet[Node], optional) – Nodes that should not be moved. This constraint only applies to Pauli nodes and has no effect on non-Pauli nodes.
stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.
- Returns:
The pattern in which Pauli measurements have been moved before the other measurements.
- Return type:
- max_space() int[source]¶
Compute the maximum number of nodes that must be present in the graph (graph space) during the execution of the space-optimal pattern for the given measurement order.
This is equivalent to
to_space_optimal_pattern().max_space().- Returns:
n_nodes – Maximum number of nodes present in the graph during space-optimal pattern execution.
- Return type:
- minimize_space(heuristics: Iterable[SpaceMinimizationHeuristic] | None = None) StandardizedPattern[source]¶
Return a pattern with an optimized measurement order that reduces the maximal space, i.e. the number of qubits simultaneously required to execute the pattern.
Note that standardized patterns always have a maximal space equal to the total number of nodes in the open graph, because standardization requires the entire graph to be prepared before measurement.
Space reduction is specifically realized when the optimized order is applied via
to_space_optimal_pattern().See
graphix.space_minimization.minimize_space()for default heuristics.- Parameters:
heuristics (Iterable[SpaceMinimizationHeuristic] | None, default None) – The heuristics to apply sequentially. Defaults to
DEFAULT_HEURISTICS.- Returns:
The optimized pattern.
- Return type:
- to_standardizedpattern() StandardizedPattern[source]¶
Return self.
- to_space_optimal_pattern() Pattern[source]¶
Return a pattern that is space-optimal for the given measurement order.
This method treats the measurement order as fixed, performing node preparations (
N) and entanglements (E) as late as possible to minimize space usage. While the resulting pattern is guaranteed to be optimal for this specific order, the method does not explore alternative orders.To find an alternative measurement order that further reduces space, use
minimize_space().
- to_opengraph() OpenGraph[Measurement][source]¶
Extract the underlying resource-state open graph from the pattern.
- Return type:
- Raises:
ValueError – If
Ncommands in the pattern do not represent a \(\ket{+}\) state.
- partial_order_layers() tuple[frozenset[int], ...][source]¶
Extract the measurement order of the pattern in the form of layers.
This method builds a directed acyclical graph (DAG) from the pattern and then performs a topological sort.
- Returns:
Measurement partial order between the pattern’s nodes in a layer form.
- Return type:
- Raises:
ValueError – If the correction domains in the pattern form closed loops. This implies that the pattern is not runnable.
Notes
- The returned object follows the same conventions as the
partial_order_layersattribute ofPauliFlowandXZCorrectionsobjects: Nodes in the same layer can be measured simultaneously.
Nodes in layer
imust be measured after nodes in layeri + 1.All output nodes (if any) are in the first layer.
There cannot be any empty layers.
- to_xzcorrections() XZCorrections[Measurement][source]¶
Extract the XZ-corrections from the current measurement pattern.
- Returns:
The XZ-corrections associated with the current pattern.
- Return type:
- Raises:
XZCorrectionsError – If the extracted correction dictionaries are not well formed.
ValueError – If
Ncommands in the pattern do not represent a \(\ket{+}\) state or if the pattern corrections form closed loops.
- map(f: Callable[[Measurement], Measurement]) StandardizedPattern[source]¶
Return a pattern where the function
fhas been applied to each measurement.- Parameters:
f (Callable[[Measurement], Measurement]) – Function applied to each measurement.
- Returns:
The resulting pattern.
- Return type:
- to_bloch() StandardizedPattern[source]¶
Return an equivalent pattern in which all measurements are represented as Bloch measurements.
- infer_pauli_measurements(*, rel_tol: float = 1e-09, abs_tol: float = 0.0) StandardizedPattern[source]¶
Return a pattern where Bloch measurements close to a Pauli measurement are replaced by Pauli measurements.
- Parameters:
rel_tol (float, optional) – Relative tolerance for comparing angles, passed to
math.isclose(). Default is1e-9.abs_tol (float, optional) – Absolute tolerance for comparing angles, passed to
math.isclose(). Default is0.0.
- Returns:
A pattern in which Bloch measurements close to a Pauli measurement are replaced by Pauli measurements. If
copyisFalse, the result isself.- Return type:
- remove_pauli_measurements(*, stacklevel: int = 1) StandardizedPattern[source]¶
Remove non-input Pauli measurements from the given pattern.
See
remove_pauli_measurements()for more information.- Parameters:
stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.
- Returns:
The pattern in which Pauli measurements have been moved before the other measurements.
- Return type:
- input_nodes¶
- output_nodes¶
- n_list¶
- e_set¶
- m_list¶
- z_dict¶
- x_dict¶
- c_dict¶
- class Statevector(data: Data = graphix.states.PlanarState(Plane.XY, 0), nqubit: int | None = None, max_qubits: int | None = None)[source]¶
Bases:
DenseStateStatevector object.
- _psi¶
Complex-valued 1-dimensional array representing the quantum statevector. Only the first
2**nqubitcomplex values have meaning.- Type:
npt.NDArray[np.complex128]
- _max_qubits¶
Maximum Hilbert space size allowed for internal computations. It determines the size of
self._psi. For circuit simulations, it corresponds to the number of qubits, while for pattern simulations it corresponds to the pattern’s maximum space. The methodStatevector.ensure_capacity()allows to increase this number.- Type:
Notes
The internal representation of the quantum state is guaranteed to be normalized after initialization, and it is assumed to remain normalized thereafter.
Using
evolve_single(),expectation_single(),evolve(), orexpectation_value()with non-unitary operators does not preserve the norm of the statevector and may lead to unexpected behavior.In pattern simulation, node measurements call
evolve_single()with a projector (a non-unitary operator). However, the measured qubit is immediately removed viaremove_qubit(), which restores the unit norm of the internal quantum state. Seegraphix.sim.base_backend.DenseStateBackend.measure()for additional details.- __init__(data: Data = graphix.states.PlanarState(Plane.XY, 0), nqubit: int | None = None, max_qubits: int | None = None) None[source]¶
Initialize a statevector object.
datacan be: - a singlegraphix.states.State(classical description of a quantum state) - an iterable ofgraphix.states.Stateobjects - an iterable of scalars (a \(2^n\) numerical statevector) - a singlegraphix.sim.statevec.StatevectorIf
nqubitis not provided, it is inferred fromdata. Ifmax_qubitsis not provided, it is set to match the inferredmax_qubits. If only onegraphix.states.Stateis provided andnqubitis a valid integer, the statevector is initialized in the tensor product state. If a class:graphix.sim.statevec.Statevectoris provided, a copy is returned. Consistency between providednqubit,max_qubitsanddatais checked.- Parameters:
data (Data, optional) – Input data to prepare the state. Can be a classical description or a numerical input, defaults to
graphix.states.BasicStates.PLUS.nqubit (int | None, optional) – Number of qubits to prepare. If
None(default), it’s inferred fromdata.max_qubits (int | None, optional.) – Maximum Hilbert space size for array preallocation. If
None(default), it’s set equal tonqubit.
- Raises:
ValueError – If
nqubit,max_qubitsordataare not consistent with each other.
- property psi: NDArray[complex128]¶
View of the meaningful elements in
self._psi.These are the first
2**self.nqubitelements.
- ensure_capacity(required_qubits: int) None[source]¶
Extend the state vector if the required qubit capacity exceeds the current one.
It copies the full state vector if
required_qubits > self.max_qubits, otherwise does nothing.- Parameters:
required_qubits (int) – Minimum number of qubits the state vector must support. If expansion is needed,
self._psiis extended to size2**required_qubits.
- flatten() NDArray[object_ | complex128][source]¶
Return flattened state vector.
A view of only the first
2**self.nqubitelements ofself._psiis returned.
- add_nodes(nqubit: int, data: Data) None[source]¶
Add nodes (qubits) to the state vector and initialize them in a specified state.
Previously existing nodes remain unchanged.
- Parameters:
nqubit (int) – The number of qubits to add to the state vector.
data (Data) –
The state in which to initialize the newly added nodes.
If a single basic state is provided, all new nodes are initialized in that state.
If a list of basic states is provided, it must match the length of
nodes, and each node is initialized with its corresponding state.A single-qubit state vector will be broadcast to all nodes.
A multi-qubit state vector of dimension \(2^n\), where \(n = \mathrm{len}(nodes)\), initializes the new nodes jointly.
Notes
This method can extend the size of
self._psifor convenience, but this requires allocating a full new array.
- evolve_single(op: NDArray[object_ | complex128], qubit: int) None[source]¶
Apply a single-qubit operator.
- Parameters:
op (npt.NDArray[np.complex128]) – Complex-valued matrix of shape \((2, 2)\) representing the operator to apply.
qubit (int) – Target qubit index.
- expectation_single(op: NDArray[object_ | complex128], qubit: int) complex[source]¶
Return the expectation value of a single-qubit operator.
- Parameters:
op (npt.NDArray[np.complex128]) – Complex-valued matrix of shape \((2, 2)\) representing the operator to measure.
qubit (int) – Target qubit index.
- Returns:
Expectation value.
- Return type:
Notes
This method assumes that quantum state represented by
self.psiis normalized. See the class docstring for details.
- evolve(op: Matrix, qubits: Sequence[int]) None[source]¶
Apply a multi-qubit operator.
- Parameters:
op (npt.NDArray[np.complex128]) – Complex-valued matrix of shape \((2^n, 2^n)\) representing the operator to apply.
qubits (Sequence[int]) – Target qubit indices.
Notes
This method is a fallback for circuit simulation and it’s not required for pattern simulation. It does not have an efficient JIT-compiled implementation.
- expectation_value(op: Matrix, qubits: Sequence[int]) complex[source]¶
Return the expectation value of a multi-qubit operator.
- Parameters:
op (npt.NDArray[np.complex128]) – Complex-valued matrix of shape \((2^n, 2^n)\) representing the operator to measure.
qubits (Sequence[int]) – Target qubit indices.
Notes
This method assumes that quantum state represented by
self.psiis normalized. See the class docstring for details.
- remove_qubit(qubit: int) None[source]¶
Remove a separable qubit from the system and assemble the statevector of the remaining qubits.
This method is deprecated. See
self.project_qubit().- Parameters:
qubit (int) – Target qubit index.
- project_qubit(op: NDArray[object_ | complex128], qubit: int) None[source]¶
Project out a qubit from the system and assemble the statevector of the remaining qubits.
This method evolves the statevector with
opand removesqubit. It assumes that after the application ofop,qubitis a separable qubit.Let \(P \ket{\psi} = \sum c_i \ket{i}\) be the statevector after the application of the projector \(P\) (
op), with sum taken over \(i \in [ 0 \dots 00,\ 0\dots 01,\ \dots,\ 1 \dots 11 ]\), this method returns\[\begin{split}\ket{\psi}' =& c_{0 \dots 0_{\mathrm{k-1}}0_{\mathrm{k}}0_{\mathrm{k+1}} \dots 00} \ket{0 \dots 0_{\mathrm{k-1}}0_{\mathrm{k+1}} \dots 00} \\ & + c_{0 \dots 0_{\mathrm{k-1}}0_{\mathrm{k}}0_{\mathrm{k+1}} \dots 01} \ket{0 \dots 0_{\mathrm{k-1}}0_{\mathrm{k+1}} \dots 01} \\ & + c_{0 \dots 0_{\mathrm{k-1}}0_{\mathrm{k}}0_{\mathrm{k+1}} \dots 10} \ket{0 \dots 0_{\mathrm{k-1}}0_{\mathrm{k+1}} \dots 10} \\ & + \dots \\ & + c_{1 \dots 1_{\mathrm{k-1}}0_{\mathrm{k}}1_{\mathrm{k+1}} \dots 11} \ket{1 \dots 1_{\mathrm{k-1}}1_{\mathrm{k+1}} \dots 11},\end{split}\](after normalization) for \(k =\)
qubit. If the \(k\) th qubit is in the \(\ket{1}\) state, all the amplitudes above will be zero. In that case the returned state will be the one above with \(0_{\mathrm{k}}\) replaced with \(1_{\mathrm{k}}\).Warning
This method assumes that
opis a projector, and therefore thatqubitis a separablequbitafter applyingop. It is implemented as a significantly faster alternative for partial trace to be used after single-qubit measurements. Separability is not checked.- Parameters:
op (npt.NDArray[np.complex128]) – Complex-valued matrix of shape \((2, 2)\) representing the projector to apply.
qubit (int) – Target qubit index.
Notes
This method combines
evolve_single()andremove_qubit().First, the relevant entries of
self.psiare partitioned into two disjoint subvectors. The partition depends on the value ofq. For a three-qubit statevector[a0, a1, a2, a3, a4, a5, a6, a7]:q = 0: sv0 = [a0, a1, a2, a3], sv1 = [a4, a5, a6, a7] q = 1: sv0 = [a0, a1, a4, a5], sv1 = [a2, a3, a6, a7] q = 2: sv0 = [a0, a2, a4, a6], sv1 = [a1, a3, a5, a7]
The statevector is then iterated over as in
evolve_single(), updatingself.psiin place while computing the norm of each partition separately.If both resulting subvectors have nonzero norm, they are guaranteed to be identical. The subvector
sv0is normalized and written to the first2**(nqubit - 1)entries ofself.psi.If exactly one subvector has nonzero norm, that subvector is selected. If both have zero norm, a
RuntimeErroris raised.
- tensor(other: Statevector) None[source]¶
Tensor product state with other qubits.
Results in
self\(\otimes\)other.- Parameters:
other (
graphix.sim.statevec.Statevector) – Statevector to be tensored withself.
Notes
This method is used internally by
add_nodes().
- permute(permutation: Sequence[int]) None[source]¶
Reorder the qubits.
- Parameters:
permutation (Sequence[int]) – The permutation to apply. For each position in the resulting order, the value gives the index of the qubit in the original ordering.
- fidelity(other: Statevector | NDArray[object_ | complex128]) float[source]¶
Calculate the fidelity against another statevector.
The fidelity is defined as \(|\langle\psi_1|\psi_2\rangle|^2\).
- Parameters:
other (
graphix.sim.statevec.Statevector) – Statevector to compare with.- Returns:
Fidelity between the two statevectors.
- Return type:
- isclose(other: Statevector | NDArray[object_ | complex128], *, rtol: float = 1e-09, atol: float = 0.0) bool[source]¶
Check if two quantum states are equal up to global phase.
Two states are considered close if their fidelity is close to 1.
- Parameters:
other (
graphix.sim.statevec.Statevector) – Statevector to compare with.rtol (float) – Relative tolerance for
math.isclose().atol (float) – Absolute tolerance for
math.isclose().
- Returns:
Trueif the states are equal up to global phase.- Return type:
- to_dict(encoding: _ENCODING = 'MSB', *, rtol: float = 0.0, atol: float = 1e-08) dict[str, np.object_ | np.complex128][source]¶
Convert the statevector to dictionary form.
This dictionary representation uses a ket-like notation where the dictionary
keysare qubit strings for the basis vectors andvaluesare the corresponding complex amplitudes. Amplitudes below a certain threshold are filtered out.- Parameters:
encoding (Literal["LSB", "MSB"], default="MSB") – Encoding for the basis kets. See notes for additional information.
rtol (float, default=0.0) – Relative tolerance used when deciding whether a coefficient should be treated as zero. Values whose magnitude is within this relative tolerance of zero are omitted from the resulting dictionary.
atol (float, default=1e-8) – Absolute tolerance used when deciding whether a coefficient should be treated as zero. Values whose magnitude is within this relative tolerance of zero are omitted from the resulting dictionary.
- Returns:
The statevector in dictionary form.
- Return type:
Notes
The encoding determines the bit ordering convention used when mapping basis states to dictionary keys. Consider a tensor product of three qubits:
\[\]lvertpsirangle = q_0 otimes q_1 otimes q_2.
If
encoding == "MSB"the first qubit is represented in the Most Significant Bit ->q0q1q2. This is the default representation in Graphix. Ifencoding == "LSB"the first qubit is represented in the Least Significant Bit ->q2q1q0. This is the default representation in other software packages such as Qiskit.Example
>>> from graphix.states import BasicStates >>> from graphix.sim.statevec import Statevector >>> sv = Statevector(data=[BasicStates.ZERO, BasicStates.ONE]) >>> sv.to_dict() {'01': np.complex128(1+0j)} >>> sv.to_dict(encoding="LSB") {'10': np.complex128(1+0j)}
- to_prob_dict(encoding: _ENCODING = 'MSB', *, rtol: float = 0.0, atol: float = 1e-08) dict[str, np.object_ | np.float64][source]¶
Convert the statevector to a probability distirbution in a dictionary form.
This dictionary representation uses a ket-like notation where the dictionary
keysare qubit strings for the basis vectors andvaluesare the corresponding probabilities. Basis vector whose amplitude is below a certain threshold are filtered out.- Parameters:
encoding (Literal["LSB", "MSB"], default="MSB") – Encoding for the basis kets. See
to_dict()for additional information.rtol (float, default=0.0) – Relative tolerance used when deciding whether a coefficient should be treated as zero. Values whose magnitude is within this relative tolerance of zero are omitted from the resulting dictionary.
atol (float, default=1e-8) – Absolute tolerance used when deciding whether a coefficient should be treated as zero. Values whose magnitude is within this relative tolerance of zero are omitted from the resulting dictionary.
- Returns:
The probability distribution associated to the statevector in dictionary form.
- Return type:
See also
meth:
to_dict
- draw(output: OutputFormat | None = None, *, encoding: _ENCODING = 'MSB', max_denominator: int = 1000, atol: float = 1e-09, rtol: float = 0.0, precision: int = 4) str[source]¶
Return a pretty-printed ket-notation representation of the statevector.
Amplitudes are rendered with
graphix.pretty_print.complex_to_str(), so common values appear as exact expressions (e.g.√2/2) rather than floating-point numbers.- Parameters:
output (OutputFormat, optional) – Desired formatting style. Defaults to
OutputFormat.Unicode.encoding ({"LSB", "MSB"}, optional) – Bit-ordering convention for the basis kets (default:
"MSB"). Seeto_dict().max_denominator (int, optional) – Maximum denominator used by the amplitude recognition (default:
1000).atol (float, optional) – Absolute tolerance for dropping near-zero amplitudes and for the recognition heuristics (default:
1e-9).rtol (float, optional) – Relative tolerance for dropping near-zero amplitudes (default:
0.0).precision (int, optional) – Number of significant digits to use for amplitudes that fall back to a decimal representation (default:
4).
- Returns:
The formatted statevector.
- Return type:
Examples
>>> from graphix.transpiler import Circuit >>> circuit = Circuit(2) >>> circuit.h(0) >>> circuit.cz(0, 1) >>> print(circuit.simulate().state.draw()) sqrt(2)/2(|00> + |01>)
- class StatevectorBackend(state: Statevector = <factory>, *, node_index: NodeIndex = <factory>, branch_selector: BranchSelector = <factory>, symbolic: bool = False)[source]¶
Bases:
DenseStateBackend[Statevector]Numba JIT-compiled MBQC statevector backend simulator based on Ref. [1].
See also
graphix.sim.base_backend.DenseStateBackendBase class describing available parameters and shared behavior.
Notes
By default, the backend is initialized with a 0-dimensional statevector (a scalar
1) andmax_qubits = 0.The internal state representation can be expanded using
StatevectorBackend.add_nodes, but this is inefficient since it requires copying the full quantum state array.To preallocate memory for a fixed system size, use
StatevectorBackend.with_capacity().References
[1] McGuffin, M. J., Robert J-M., and Ikeda K. “How to Write a Simulator for Quantum Circuits from Scratch: A Tutorial.”, 2025 (arXiv:2506.08142).
- state: Statevector¶
- classmethod with_capacity(max_qubits: int, state: Statevector | None = None, **kwargs: Unpack[DenseStateBackendKwargs]) Self[source]¶
Initialize the backend with preallocated statevector capacity.
- Parameters:
max_qubits (int) – Maximum number of qubits supported by the statevector. For pattern simulation this corresponds to
Pattern.max_space().state (Statevector | None = None) – Initial backend state. If
None, the backend is initialized with a 0-dimensional statevector (scalar1).**kwargs – Options for
graphix.sim.base_backend.DenseStateBackend. Seegraphix.sim.base_backend.DenseStateBackendKwargs.
- Returns:
Backend instance with capacity for up to
max_qubitsqubits.- Return type:
Self
- __init__(state: Statevector = <factory>, *, node_index: NodeIndex = <factory>, branch_selector: BranchSelector = <factory>, symbolic: bool = False) None¶
- class XZCorrections(og: OpenGraph[_AM_co], x_corrections: Mapping[int, AbstractSet[int]], z_corrections: Mapping[int, AbstractSet[int]], partial_order_layers: Sequence[AbstractSet[int]])[source]¶
Bases:
Parameterizable,Simulable[_AM_co],Generic[_AM_co]An unmutable dataclass providing a representation of XZ-corrections.
- x_corrections¶
Mapping of X-corrections: in each (
key,value) pair,keyis a measured node, andvalueis the set of nodes on which an X-correction must be applied depending on the measurement result ofkey.
- z_corrections¶
Mapping of Z-corrections: in each (
key,value) pair,keyis a measured node, andvalueis the set of nodes on which an Z-correction must be applied depending on the measurement result ofkey.
- partial_order_layers¶
Partial order between the open graph’s nodes in a layer form determined by the corrections. The set
layers[i]comprises the nodes in layeri. Nodes in layeriare “larger” in the partial order than nodes in layeri+1. If the open graph has output nodes, they are always in layer 0. Non-corrected, measured nodes are always in the last layer.- Type:
Sequence[AbstractSet[int]]
Notes
The XZ-corrections mappings define a partial order, therefore, only
og,x_correctionsandz_correctionsare necessary to initialize anXZCorrectionsinstance (seeXZCorrections.from_measured_nodes_mapping()). However, XZ-corrections are often extracted from a flow whose partial order is known and can be used to construct a pattern, so it can also be passed as an argument to thedataclassconstructor. The correctness of the input parameters is not verified automatically.- static from_measured_nodes_mapping(og: OpenGraph[_AM_co], x_corrections: Mapping[int, AbstractSet[int]] | None = None, z_corrections: Mapping[int, AbstractSet[int]] | None = None) XZCorrections[_AM_co][source]¶
Create an
XZCorrectionsinstance from the XZ-corrections mappings.- Parameters:
og (OpenGraph[_AM_co]) – Open graph with respect to which the corrections are defined.
x_corrections (Mapping[int, AbstractSet[int]] | None) – Mapping of X-corrections: in each (
key,value) pair,keyis a measured node, andvalueis the set of nodes on which an X-correction must be applied depending on the measurement result ofkey.z_corrections (Mapping[int, AbstractSet[int]] | None) – Mapping of X-corrections: in each (
key,value) pair,keyis a measured node, andvalueis the set of nodes on which an X-correction must be applied depending on the measurement result ofkey.
- Return type:
XZCorrections[_AM_co]
- Raises:
XZCorrectionsError – If the input dictionaries are not well formed. In well-formed correction dictionaries: - Keys are a subset of the measured nodes. - Values correspond to nodes of the open graph. - Corrections do not form closed loops.
Notes
This method computes the partial order induced by the XZ-corrections.
- to_pattern(total_measurement_order: TotalOrder | None = None) Pattern[source]¶
Generate a unique pattern from an instance of
XZCorrections[Measurement].- Parameters:
total_measurement_order (TotalOrder | None) – Ordered sequence of all the non-output nodes in the open graph indicating the measurement order. This parameter must be compatible with the partial order induced by the XZ-corrections. Optional, defaults to
None. IfNonean arbitrary total order compatible withself.partial_order_layersis generated.- Return type:
- Raises:
XZCorrectionsError – If the input total measurement order is not compatible with the partial order induced by the XZ-corrections.
Notes
The
XZCorrectionsinstance must be of parametric typeMeasurementto allow for a pattern extraction, otherwise the underlying open graph does not contain information about the measurement angles.The resulting pattern is guaranteed to be runnable if the
XZCorrectionsobject is well formed, but does not need to be deterministic. It will be deterministic if the XZ-corrections were inferred from a flow. In this case, this routine follows the recipe in Theorems 1, 2 and 4 in Ref. [1].
References
[1] Browne et al., NJP 9, 250 (2007).
- to_causalflow() CausalFlow[_PM_co][source]¶
Extract a causal flow from XZ-corrections.
This method does not invoke the flow-extraction routine on the underlying open graph. Instead, it assigns the
x_correctionsmapping to the flow’s correction function and verifies that it is compatible with the intrinsic partial order of the XZ-corrections. If the resulting correction function is incompatible with this partial order, or the open graph contains measurements in XZ or YZ planes, aFlowErroris raised.- Return type:
CausalFlow[_PM_co]
Notes
See Theorem 1 in Ref. [1].
References
[1] Browne et al., 2007 New J. Phys. 9 250 (arXiv:quant-ph/0702212).
- to_gflow() GFlow[_PM_co][source]¶
Extract a gflow from XZ-corrections.
This method does not invoke the flow-extraction routine on the underlying open graph. Instead, it assigns the
x_correctionsmapping to the flow’s correction function and verifies that it is compatible with the intrinsic partial order of the XZ-corrections. Nodes measured in planes XZ or YZ are assigned to their correcting set. If the resulting correction function is incompatible with this partial orderFlowErroris raised.- Return type:
GFlow[_PM_co]
Notes
See Theorem 2 in Ref. [1].
References
[1] Browne et al., 2007 New J. Phys. 9 250 (arXiv:quant-ph/0702212).
- to_pauliflow() PauliFlow[_AM_co][source]¶
Extract a Pauli flow from XZ-corrections.
This method does not invoke the flow-extraction routine on the underlying open graph. Instead, it reconstructs, for every measured node, a correction set whose future part matches the observed XZ-corrections and which satisfies the Pauli-flow propositions (P1-P9, see
PauliFlow.check_well_formed()).The difficulty, compared with
to_gflow(), is that the Pauli-flow correction sets may contain anachronical corrections: corrections targeting nodes measured in the X or Y Pauli bases that lie in the present or the past of the corrected node. Such corrections do not appear in the pattern, becausePauliFlow.to_xzcorrections()only keeps the part of each correction set lying in the future (the& futurefilter). They must therefore be reconstructed rather than read off the corrections.For each measured node
ithis is cast as a system of linear equations over GF(2): the membership of the future nodes in the correction set is pinned by the X-corrections ofi; the free variables are the anachronical (non-future, X/Y-measured) candidates and, where the proposition allows it,iitself; and the equations encode the odd-neighbourhood constraints, namely the Z-corrections on the future nodes (P-future), the vanishing of the odd neighbourhood on past non-(Y/Z) nodes (P2), the coupling on past Y-measured nodes (P3) and the local proposition oni(P4-P9). The system is reduced withgraphix._linalg.MatGF2.gauss_elimination()and solved withgraphix._linalg.solve_f2_linear_system().- Return type:
PauliFlow[_AM_co]
- Raises:
FlowError – If no Pauli flow is compatible with the XZ-corrections (raised by
_reconstruct_pauli_correction_function()when the GF(2) system has no solution for at least one measured node).
Notes
See Theorem 4 in Ref. [1] and Definition 5 therein for the Pauli-flow propositions.
References
[1] Browne et al., 2007 New J. Phys. 9 250 (arXiv:quant-ph/0702212).
- to_bloch() XZCorrections[BlochMeasurement][source]¶
Return the XZ-corrections where all measurements in the open graph are converted to Bloch.
See
OpenGraph.to_bloch()for additional information.
- downcast_bloch() XZCorrections[BlochMeasurement][source]¶
Return the open graph if all measurements are described as Bloch measurements; raise
TypeErrorotherwise.See
OpenGraph.downcast_bloch()for additional information.
- generate_total_measurement_order() Sequence[int][source]¶
Generate a sequence of all the non-output nodes in the open graph in an arbitrary order compatible with the intrinsic partial order of the XZ-corrections.
- Return type:
TotalOrder
- to_dag() nx.DiGraph[int][source]¶
Extract the directed graph induced by the XZ-corrections.
- Returns:
Directed graph in which an edge
i -> jrepresents a correction applied to qubitj, conditioned on the measurement outcome of qubiti.- Return type:
nx.DiGraph[int]
Notes
Not all nodes of the underlying open graph are nodes of the returned directed graph, but only those involved in a correction, either as corrected qubits or belonging to a correction domain.
The output of this method is not guaranteed to be a directed acyclical graph (i.e., a directed graph without any loops). This is only the case if the
XZCorrectionsobject is well formed, which is verified by the methodXZCorrections.is_wellformed().
- is_compatible(total_measurement_order: Sequence[int]) bool[source]¶
Verify if a given total measurement order is compatible with the intrisic partial order of the XZ-corrections.
- Parameters:
total_measurement_order (TotalOrder) – An ordered sequence of all the non-output nodes in the open graph.
- Returns:
Trueiftotal_measurement_orderis compatible withself.partial_order_layers,Falseotherwise.- Return type:
- check_well_formed() None[source]¶
Verify if the XZ-corrections are well formed.
- Raises:
XZCorrectionsError – if the XZ-corrections are not well formed.
Notes
- A correct
XZCorrectionsinstance verifies the following properties: Keys of the correction dictionaries are measured nodes, i.e., a subset of \(O^c\).
Corrections respect the partial order.
The first layer of the partial order contains all the output nodes if there are any.
The partial order contains all the nodes (without duplicates) and it does not have empty layers.
This method assumes that the open graph is well formed.
- to_ascii(multiline: bool = False) str[source]¶
Return an ASCII string representing the XZCorrections’ mappings and partial order layers.
- to_latex(multiline: bool = False) str[source]¶
Return a string containing the LaTeX representation of the XZCorrections’ mappings and partial order layers.
See notes in
to_ascii()for additional information.
- to_unicode(multiline: bool = False) str[source]¶
Return a Unicode string representing the XZCorrections’ mappings and partial order layers.
See notes in
to_ascii()for additional information.
- draw(**options: Unpack[DrawKwargs]) None[source]¶
Visualize the opengraph, correction structure and partial order.
- Parameters:
options (Unpack[DrawKwargs]) – Options controlling graph visualization. See
VisualizationOptions.
- with_parameter(variable: Parameter, substitute: ExpressionOrSupportsFloat) XZCorrections[_M][source]¶
Substitute a parameter with a value or expression in all measurement angles of the open graph.
- Parameters:
variable (Parameter) – The symbolic expression to be replaced within the measurement angles.
substitute (ExpressionOrSupportsFloat) – The value or symbolic expression to substitute in place of
variable.
- Returns:
A new instance of the XZCorrections object with the updated measurement parameters.
- Return type:
Notes
See notes and examples in
OpenGraph.with_parameter().
- with_parameters(assignment: Mapping[Parameter, ExpressionOrSupportsFloat]) XZCorrections[_M][source]¶
Perform parallel substitution of multiple parameters in measurement angles of the open graph.
- Parameters:
assignment (Mapping[Parameter, ExpressionOrSupportsFloat]) – A dictionary-like mapping where keys are the
Parameterobjects to be replaced and values are the new expressions or numerical values.- Returns:
A new instance of the XZCorrections object with the updated measurement angles.
- Return type:
Notes
See notes and examples in
OpenGraph.with_parameters().
- angle_to_rad(angle: float) float[source]¶
- angle_to_rad(angle: Expression) Expression
Convert a Graphix angle to radians.
In Graphix, angles are expressed in units of π.
- rad_to_angle(angle: float) float[source]¶
- rad_to_angle(angle: Expression) Expression
Convert an angle expressed in radians to a Graphix angle.
In Graphix, angles are expressed in units of π.