pytket.zx
pytket.zx#
- class pytket.zx.CliffordGen#
Specialisation of
ZXGen
for arbitrary-arity, symmetric Clifford generators with a single boolean parameter.- __init__(self: pytket.zx.CliffordGen, zxtype: pytket.zx.ZXType, param: bool, qtype: pytket.zx.QuantumType) None #
Construct from a ZX type, parameter and quantum type.
- property param#
The parameter of the generator.
- class pytket.zx.DirectedGen#
Specialisation of
ZXGen
for asymmetric ZX generators which can be doubled to form a Quantum variant. Asymmetric effects handled by ports to distinguish operands.- __init__(self: pytket.zx.DirectedGen, zxtype: pytket.zx.ZXType, qtype: pytket.zx.QuantumType) None #
Construct from a ZX type and quantum type.
- property n_ports#
The number of ports on the generator.
- property signature#
A list of
QuantumType
s indicating the expectedQuantumType
at each port.
- class pytket.zx.PhasedGen#
Specialisation of
ZXGen
for arbitrary-arity, symmetric generators with a single continuous parameter.- __init__(self: pytket.zx.PhasedGen, zxtype: pytket.zx.ZXType, param: Expression, qtype: pytket.zx.QuantumType) None #
Construct from a ZX type, parameter and quantum type.
- property param#
The parameter of the generator.
- class pytket.zx.QuantumType#
Enum for specifying quantumness of vertices, ports, and wires in
ZXDiagram
s for mixed quantum-classical processes.Members:
Quantum : Quantum components of diagrams, represented in the framework of completely-positive maps by two parallel copies of a system related by conjugation.
Classical : Classical components of diagrams, represented in the framework of completely-positive maps by a single self-conjugate system.
- __init__(self: pytket.zx.QuantumType, value: int) None #
- property name#
- class pytket.zx.Rewrite#
An in-place transformation of a ZXDiagram.
- __init__(*args, **kwargs)#
- apply(self: pytket.zx.Rewrite, diag: pytket.zx.ZXDiagram) bool #
Performs the transformation on the diagram in place.
- Parameters
diag – The diagram to be transformed.
- Returns
True if any changes were made, else False.
- static basic_wires() pytket.zx.Rewrite #
Replaces every Hadamard wire by an explicit Hbox node.
- static decompose_boxes() pytket.zx.Rewrite #
Replaces every
ZXBox
by its internal diagram recursively until noZXBox
es remain.
- static extend_at_boundary_paulis() pytket.zx.Rewrite #
Identifies adjacent Pauli spiders where one is adjacent to a boundary. This rule applies I/O extensions to push the match into the interior from which it can be handled by
remove_interior_paulis()
.
- static extend_for_PX_outputs() pytket.zx.Rewrite #
Identifies output vertices in MBQC form that are given a measurement basis (i.e. are not PX(0)). This rule applies I/O extensions to make the phased qubits non-outputs. This is required before flow identification can be run.
- static gadgetise_interior_paulis() pytket.zx.Rewrite #
Identifies interior Paulis (spiders where the phase is an integer multiple of pi) with all neighbours having non-Pauli phase and degree > 1. Pivots about an incident edge to yield a gadget node.
- static internalise_gadgets() pytket.zx.Rewrite #
Identifies Degree-1 XY vertices next to a PX vertex, e.g. as the result of rebasing a phase gadget. Replaces matches by a single YZ vertex.
- static io_extension() pytket.zx.Rewrite #
Guarantees that the edge on each boundary vertex is Basic. If a boundary has a Hadamard, then we add a ZSpider identity as in I/O extensions in MBQC.
- static merge_gadgets() pytket.zx.Rewrite #
Identifies pairs of phase gadgets over the same sets of qubits and merges them.
- static parallel_h_removal() pytket.zx.Rewrite #
Remove parallel edges between ZX spiders (a.k.a. the Hopf rule). Matches either pairs of H edges between spiders of the same colour or Basic edges between spiders of different colour. This applies to Quantum edges between a pair of Classical spiders.
- static rebase_to_mbqc() pytket.zx.Rewrite #
Expands every generator into MBQC vertices.
- static rebase_to_zx() pytket.zx.Rewrite #
Expands every generator into ZSpiders, XSpiders, and a combination of Basic and Hadamard edges.
- static red_to_green() pytket.zx.Rewrite #
Converts all red spiders (XSpider) to green (ZSpider) with Hadamards around them. The Hadamards are applied by flipping the wire type of incident edges between Basic and H.
- static reduce_graphlike_form() pytket.zx.Rewrite #
Given a diagram in graphlike form, applies local complementations and pivoting to remove as many interior Clifford-angled vertices as possible. The only remaining Clifford-angled vertices will be either the axis of a phase-gadget or near a boundary.
- static remove_interior_cliffords() pytket.zx.Rewrite #
Removes interior proper Cliffords (spiders where the phase is an odd multiple of pi/2 radians or 0.5 half-turns). Performs local complementation about the vertex and removes it.
- static remove_interior_paulis() pytket.zx.Rewrite #
Removes adjacent interior Paulis (spiders where the phase is an integer multiple of pi radians or integer half-turns). Pivots about the edge connecting the vertices and removes them.
- static repeat(rewrite: pytket.zx.Rewrite) pytket.zx.Rewrite #
Applies a given
Rewrite
repeatedly to a diagram until no further changes are made (i.e. it no longer returns True). apply will return True if at least one run returned True.
- static self_loop_removal() pytket.zx.Rewrite #
Removes both H and Basic self loop edges around ZX spiders. Basic edges can simply be removed. Removing H loops introduces an extra pi phase on the spider.
- static separate_boundaries() pytket.zx.Rewrite #
Guarantees that each boundary vertex is adjacent to a unique ZSpider. This adds identity chains when two boundaries are either directly connected or are adjacent to the same spider.
- static sequence(sequence: List[pytket.zx.Rewrite]) pytket.zx.Rewrite #
Composes a list of
Rewrite
s together in sequence. The apply method will return True if ANY of the individual Rewrites returned True.
- static spider_fusion() pytket.zx.Rewrite #
Merges two adjacent ZX spiders (XSpider, ZSpider) of the same colour connected by a Basic wire into a single spider. Also merges two adjacent spiders of different colour connected by a H edge.
- static to_MBQC_diag() pytket.zx.Rewrite #
Given a diagram in graphlike form, will rebase to MBQC generators, ensure that output qubits are PX(0) (i.e. they match unmeasured qubits) and degree-1 vertices are absorbed into a PX neighbour, i.e. reducing phase-gadgets to single vertices in a different measurement plane.
- static to_graphlike_form() pytket.zx.Rewrite #
Given a diagram with ZX generators, yields a diagram with only ZSpiders, connected by at most one Hadamard edge, with boundaries connected via Basic edges.
- class pytket.zx.ZXBox#
Specialisation of
ZXGen
for encapsulations of some other ZX diagrams. In general, arbitrary diagrams may be asymmetric tensors with both Quantum and Classical boundaries, so ports are used to distinguish each boundary.- __init__(self: pytket.zx.ZXBox, zxdiag: pytket.zx.ZXDiagram) None #
Construct from a ZX diagram.
- property diagram#
The internal diagram represented by the box.
- property n_ports#
The number of ports on the generator.
- property signature#
A list of
QuantumType
s indicating the expectedQuantumType
at each port.
- class pytket.zx.ZXDiagram#
Undirected graphs for mixed process ZX diagrams. The boundary is an ordered list which may mix inputs, outputs, and “open” vertices (not specified to be inputs or outputs). Directed vertices (e.g. Boxes, Triangles, etc.) have numbered ports to distinguish different incident edges. The content of each vertex is given by a
ZXGen
generator, describing theZXType
(e.g. XSpider, Input, Triangle), the QuantumType for single/doubled versions of typical generators, and any parameters such as phase. Wires are undirected and have aZXWireType
(e.g. Basic, Hadamard) andQuantumType
(a single wire or a doubled pair for a quantum system).- __init__(*args, **kwargs)#
Overloaded function.
__init__(self: pytket.zx.ZXDiagram) -> None
Constructs an empty ZX diagram.
__init__(self: pytket.zx.ZXDiagram, inputs: int, outputs: int, classical_inputs: int, classical_outputs: int) -> None
Constructs an empty ZX diagram with a given number of unconnected boundary vertices.
- Parameters
in – Number of quantum inputs.
out – Number of quantum outputs.
classical_in – Number of classical inputs.
classical_out – Number of classical outputs.
__init__(self: pytket.zx.ZXDiagram, other: pytket.zx.ZXDiagram) -> None
Constructs a copy of an existing ZX diagram.
- Parameters
other – ZX diagram to copy.
- add_vertex(*args, **kwargs)#
Overloaded function.
add_vertex(self: pytket.zx.ZXDiagram, gen: pytket.zx.ZXGen) -> pytket.zx.ZXVert
Adds a new vertex to the diagram for an arbitrary
ZXGen
.- Parameters
gen – The
ZXGen
for the new vertex.- Returns
The handle to the new vertex.
add_vertex(self: pytket.zx.ZXDiagram, type: pytket.zx.ZXType, qtype: pytket.zx.QuantumType = <QuantumType.Quantum: 0>) -> pytket.zx.ZXVert
Adds a new vertex to the diagram for an unparameterised, doubleable generator type.
- Parameters
type – The
ZXType
for the new vertex.qtype – The
QuantumType
for the new vertex. Defaults to Quantum.
- Returns
The handle to the new vertex.
add_vertex(self: pytket.zx.ZXDiagram, type: pytket.zx.ZXType, param: bool, qtype: pytket.zx.QuantumType = <QuantumType.Quantum: 0>) -> pytket.zx.ZXVert
Adds a new vertex to the diagram for a Boolean-parameterised, doubleable generator type.
- Parameters
type – The
ZXType
for the new vertex.param – The parameter for the new vertex.
qtype – The
QuantumType
for the new vertex. Defaults to Quantum.
- Returns
The handle to the new vertex.
add_vertex(self: pytket.zx.ZXDiagram, type: pytket.zx.ZXType, param: Expression, qtype: pytket.zx.QuantumType = <QuantumType.Quantum: 0>) -> pytket.zx.ZXVert
Adds a new vertex to the diagram for a parameterised, doubleable generator type.
- Parameters
type – The
ZXType
for the new vertex.param – The parameter for the new vertex.
qtype – The
QuantumType
for the new vertex. Defaults to Quantum.
- Returns
The handle to the new vertex.
- add_wire(self: pytket.zx.ZXDiagram, u: pytket.zx.ZXVert, v: pytket.zx.ZXVert, type: pytket.zx.ZXWireType = ZXWireType.Basic, qtype: pytket.zx.QuantumType = QuantumType.Quantum, u_port: Optional[int] = None, v_port: Optional[int] = None) pytket.zx.ZXWire #
Adds a new wire to the diagram between the given vertices.
- Parameters
u – Handle to the first vertex.
v – Handle to the other vertex.
type –
ZXWireType
for the wire. Defaults to Basic.qtype –
QuantumType
for the wire. Defaults to Quantum.u_port – Port on vertex u to connect to. Defaults to None.
v_port – Port on vertex v to connect to. Defaults to None.
- Returns
The handle to the new wire.
- add_zxbox(self: pytket.zx.ZXDiagram, inner: pytket.zx.ZXDiagram) pytket.zx.ZXVert #
Adds a new vertex to the diagram for a box with some inner implementation.
- Parameters
inner – The
ZXDiagram
to internalise inside the box. The current state is copied by value.- Returns
The handle to the new vertex.
- adj_wires(self: pytket.zx.ZXDiagram, v: pytket.zx.ZXVert) List[pytket.zx.ZXWire] #
Given a vertex, returns a list of all incident wires. Self-loops will only appear once in the list. The order of the wire list may not be semantically relevant.
- check_validity(self: pytket.zx.ZXDiagram) None #
Performs a check for the internal validity of the
ZXDiagram
and raises an exception if it is invalid. - Inputs/Outputs must have degree 1 and all exist within the boundary. - Undirected vertices (those without ports) have no ports on incident edges. - Directed vertices (those with ports) have exactly one incident edge at each port. -QuantumType
of wires are compatible with theQuantumType
s of the ports they attach to.
- count_vertices(self: pytket.zx.ZXDiagram, type: pytket.zx.ZXType) int #
Counts the number of vertices of a given
ZXType
in the diagram.
- count_wires(self: pytket.zx.ZXDiagram, type: pytket.zx.ZXWireType) int #
Counts the number of wired of a given
ZXWireType
in the diagram.
- degree(self: pytket.zx.ZXDiagram, v: pytket.zx.ZXVert) int #
Returns the degree of the given vertex.
- free_symbols(self: pytket.zx.ZXDiagram) Set[Symbol] #
Returns the set of symbolic parameters in the diagram.
- get_boundary(self: pytket.zx.ZXDiagram, type: Optional[pytket.zx.ZXType] = None, qtype: Optional[pytket.zx.QuantumType] = None) List[pytket.zx.ZXVert] #
Returns handles to boundary vertices in order. Optionally filter by type of boundary vertex.
- Parameters
type –
ZXType
to filter by, from {ZXType.Input()
,ZXType.Output()
,ZXType.Open()
, None}. Defaults to None.:param qtype:QuantumType
to filter by, from {QuantumType.Quantum()
,QuantumType.Classical()
, None}. Defaults to None.
- get_name(self: pytket.zx.ZXDiagram, v: pytket.zx.ZXVert) str #
Returns the readable string description of a given vertex
- get_qtype(self: pytket.zx.ZXDiagram, v: pytket.zx.ZXVert) Optional[pytket.zx.QuantumType] #
Returns the
QuantumType
of the given vertex if defined, None otherwise.
- get_vertex_ZXGen(self: pytket.zx.ZXDiagram, v: pytket.zx.ZXVert) pytket.zx.ZXGen #
Returns the content of a given vertex as a
ZXGen
.
- get_wire_ends(self: pytket.zx.ZXDiagram, w: pytket.zx.ZXWire) Tuple[Tuple[pytket.zx.ZXVert, Optional[int]], Tuple[pytket.zx.ZXVert, Optional[int]]] #
Returns a tuple ((vertex0, port0), (vertex1, port1)) describing the two ends of the wire.
- get_wire_qtype(self: pytket.zx.ZXDiagram, w: pytket.zx.ZXWire) pytket.zx.QuantumType #
Returns the
QuantumType
of the given wire.
- get_wire_type(self: pytket.zx.ZXDiagram, w: pytket.zx.ZXWire) pytket.zx.ZXWireType #
Returns the
ZXWireType
of the given wire.
- get_zxtype(self: pytket.zx.ZXDiagram, v: pytket.zx.ZXVert) pytket.zx.ZXType #
Returns the
ZXType
of the given vertex.
- is_symbolic(self: pytket.zx.ZXDiagram) bool #
Returns True if the diagram contains any free symbols, False otherwise.
- multiply_scalar(self: pytket.zx.ZXDiagram, scalar: Expression) None #
Multiplies the global scalar by a numerical (possibly symbolic) constant.
- neighbours(self: pytket.zx.ZXDiagram, v: pytket.zx.ZXVert) List[pytket.zx.ZXVert] #
Given a vertex, returns a list of all vertices neighbouring it. Each neighbour will only appear in the list once regardless of how many shared edges there are. The order of the neighbour list may not be semantically relevant.
- other_end(self: pytket.zx.ZXDiagram, w: pytket.zx.ZXWire, v: pytket.zx.ZXVert) pytket.zx.ZXVert #
Given a wire and a vertex at one end of the wire, gives the vertex at the other end of the wire. This can be used to traverse the undirected edges of the graph.
- remove_vertex(self: pytket.zx.ZXDiagram, v: pytket.zx.ZXVert) None #
Removes the given vertex and all incident wires from the diagram. If the vertex is in the boundary, it is removed from the boundary.
- remove_wire(self: pytket.zx.ZXDiagram, w: pytket.zx.ZXWire) None #
Removes the given wire from the diagram.
- set_vertex_ZXGen(self: pytket.zx.ZXDiagram, v: pytket.zx.ZXVert, gen: pytket.zx.ZXGen) None #
Updates the content of a given vertex to a particular
ZXGen
.
- set_wire_qtype(self: pytket.zx.ZXDiagram, w: pytket.zx.ZXWire, qtype: pytket.zx.QuantumType) None #
Updates the
QuantumType
of the given wire.
- set_wire_type(self: pytket.zx.ZXDiagram, w: pytket.zx.ZXWire, type: pytket.zx.ZXWireType) None #
Updates the
ZXWireType
of the given wire.
- symbol_substitution(*args, **kwargs)#
Overloaded function.
symbol_substitution(self: pytket.zx.ZXDiagram, symbol_map: Dict[Symbol, Expression]) -> None
In-place substitution for symbolic expressions; iterated through each parameterised vertex and performs the substitution. This will not affect any symbols captured within boxed operations.
- Parameters
symbol_map – A map from SymPy symbols to SymPy expressions.
symbol_substitution(self: pytket.zx.ZXDiagram, symbol_map: Dict[Symbol, float]) -> None
In-place substitution for symbolic expressions; iterated through each parameterised vertex and performs the substitution. This will not affect any symbols captured within boxed operations.
- Parameters
symbol_map – A map from SymPy symbols to floating-point values.
- to_circuit(self: pytket.zx.ZXDiagram) Tuple[pytket.circuit.Circuit, Dict[pytket.zx.ZXVert, pytket.circuit.UnitID]] #
Extracts a unitary diagram in MBQC form as a Circuit following the routine by Backens et al. (“There and back again: A circuit extraction tale”).
- Returns
A pair of the generated
Circuit
, and a map from each boundary vertex in theZXDiagram
to its correspondingUnitID
in theCircuit
.
- to_doubled_diagram(self: pytket.zx.ZXDiagram) pytket.zx.ZXDiagram #
classical boundaries only have the unconjugated version
- to_graphviz_str(self: pytket.zx.ZXDiagram) str #
Returns a graphviz source string
- wire_at_port(self: pytket.zx.ZXDiagram, v: pytket.zx.ZXVert, port: int) pytket.zx.ZXWire #
Given a vertex, returns the unique wire at the given port number. Raises an exception if multiple wires are found at the given port.
- wire_between(self: pytket.zx.ZXDiagram, u: pytket.zx.ZXVert, v: pytket.zx.ZXVert) Optional[pytket.zx.ZXWire] #
Given two vertices, returns either an arbitrary edge between them if one exists or None if they are not adjacent.
- wires_between(self: pytket.zx.ZXDiagram, u: pytket.zx.ZXVert, v: pytket.zx.ZXVert) List[pytket.zx.ZXWire] #
Given two vertices, returns a list of all wires between them. The order of the wire list may not be semantically relevant.
- property n_vertices#
Counts the number of vertices in the diagram. Includes boundary vertices and disconnected vertices.
- property n_wires#
Counts the number of edges in the diagram.
- property scalar#
Returns the global scalar stored numerically. This may be a symbolic expression.
- property vertices#
Returns a list of handles to all vertices in the diagram. The order of vertices may not be semantically relevant.
- property wires#
Returns a list of handles to all wires in the diagram. The order of wires may not be semantically relevant.
- class pytket.zx.ZXGen#
Encapsulates the information about the generator depicted by a given vertex in a
ZXDiagram
.- __init__(*args, **kwargs)#
- static create(*args, **kwargs)#
Overloaded function.
create(type: pytket.zx.ZXType, qtype: pytket.zx.QuantumType = <QuantumType.Quantum: 0>) -> pytket.zx.ZXGen
Create a boundary type generator.
create(type: pytket.zx.ZXType, param: Expression, qtype: pytket.zx.QuantumType = <QuantumType.Quantum: 0>) -> pytket.zx.ZXGen
Create a boundary type generator.
- property qtype#
The
QuantumType
of the generator (if applicable).
- property type#
The type of generator.
- class pytket.zx.ZXType#
Enum for available types of generators in
ZXDiagram
s.Members:
Input : An input boundary vertex. Can either be Quantum or Classical. Must have degree 1. No ports.
Output : An output boundary vertex. Can either be Quantum or Classical. Must have degree 1. No ports.
Open : A boundary vertex that has not yet been specified as input or output. Can either be Quantum or Classical. Must have degree 1. No ports.
ZSpider : A Z (green) spider. Parameterised by a single phase in half-turns. Can either be Quantum or Classical - Quantum spiders can only have Quantum wires, Quantum wires on Classical spiders act as two wires. Can have arbitrary degree. No ports.
XSpider : An X (red) spider. Parameterised by a single phase in half-turns. Can either be Quantum or Classical - Quantum spiders can only have Quantum wires, Quantum wires on Classical spiders act as two wires. Can have arbitrary degree. No ports.
Hbox : A Hadamard box for ZH diagrams. Parameterised by a single complex value. Can either be Quantum or Classical - Quantum spiders can only have Quantum wires, Quantum wires on Classical spiders act as two wires. Can have arbitrary degree. No ports.
XY : A (postselected) XY qubit in MBQC. Corresponds to a Z spider with negative phase.
XZ : A (postselected) XZ qubit in MBQC. Corresponds to a 0.5-phase (n+1)-ary Z spider connected to a phaseful 1-ary X spider.
YZ : A (postselected) YZ qubit in MBQC. Corresponds to a 0-phase (n+1)-ary Z spider connected to a phaseful 1-ary X spider.
PX : A (postselected) Pauli X qubit in MBQC. Corresponds to a Z spider with phase either 0 (param=False) or 1 (param=True).
PY : A (postselected) Pauli Y qubit in MBQC. Corresponds to a Z spider with phase either -0.5 (param=False) or +0.5 (param=True).
PZ : A (postselected) Pauli Z qubit in MBQC. Corresponds to a 0-phase (n+1)-ary Z spider connected to a 1-ary X spider with phase either 0 (param=False) or 1 (param=True).
Triangle : A Triangle operator, [[1, 1], [0, 1]]. Can either be Quantum or Classical, only admitting wires of the same type. Port 0 for the base of the triangle (input), port 1 for the tip (output).
ZXBox : A box encapsulating another
ZXDiagram
. Inherits ports from the boundary of the internal diagram, with port numbers matching the boundary order andQuantumType
admitted at each port matching that of the boundary vertex.- __init__(self: pytket.zx.ZXType, value: int) None #
- property name#
- class pytket.zx.ZXVert#
A handle to a vertex in a
ZXDiagram
. Each instance is specific to a givenZXDiagram
instance and can be invalidated by rewrites. Exceptions or errors may occur if calling functions on aZXVert
that is not present in the givenZXDiagram
.- __init__(*args, **kwargs)#
- class pytket.zx.ZXWire#
A handle to a wire in a
ZXDiagram
. Each instance is specific to a givenZXDiagram
instance and can be invalidated by rewrites. Exceptions or errors may occur if calling functions on aZXWire
that is not present in the givenZXDiagram
.- __init__(*args, **kwargs)#
- class pytket.zx.ZXWireType#
Enum for available types of wires in
ZXDiagram
s.Members:
Basic : A basic identity wire.
H : A Hadamard edge.
- __init__(self: pytket.zx.ZXWireType, value: int) None #
- property name#
- pytket.zx.circuit_to_zx(arg0: pytket.circuit.Circuit) Tuple[pytket.zx.ZXDiagram, Dict[pytket.circuit.UnitID, Tuple[pytket.zx.ZXVert, pytket.zx.ZXVert]]] #
Construct a ZX diagram from a circuit. Return the ZX diagram and a map Between the ZX boundary vertices and the resource UIDs of the circuit.