Full API documentation
Below is listed the documentation for all the supported functions, classes and methods in PyZX. Some functionality of PyZX is still experimental or not well-tested (like the ZH-diagram interface and rewrite rules), so it is not listed here.
Consider also looking at the AllFeatures notebook for demonstrations of many of this functionality in practice.
Graph API
ZX-graphs are internally represented by instances of classes that implement the methods of BaseGraph. These methods are listed below. The only complete implementation currently is GraphS.
- class GraphS
Purely Pythonic implementation of
BaseGraph.
To create a graph of a specific backend a convenience method Graph is supplied:
- Graph(backend=None)
Returns an instance of an implementation of
BaseGraph. By defaultGraphSis used. Currentlybackendis allowed to be simple (for the default), or ‘graph_tool’ and ‘igraph’. This method is the preferred way to instantiate a ZX-diagram in PyZX.- Return type:
Example
To construct an empty ZX-diagram, just write:
g = zx.Graph()
Below you can find full documentation of all the functions supplied by a Graph in PyZX.
- class BaseGraph
Base class for letting graph backends interact with PyZX. For a backend to work with PyZX, there should be a class that implements all the methods of this class. For implementations of this class see
GraphSorGraphIG.- add_edge(edge_pair, edgetype=EdgeType.SIMPLE)
Adds a single edge of the given type and return its id
- Return type:
TypeVar(ET)
- add_edge_table(etab)
Takes a dictionary mapping (source,target) –> (#edges, #h-edges) specifying that #edges regular edges must be added between source and target and $h-edges Hadamard edges. The method selectively adds or removes edges to produce that ZX diagram which would result from adding (#edges, #h-edges), and then removing all parallel edges using Hopf/spider laws.
- Return type:
None
- add_edges(edge_pairs, edgetype=EdgeType.SIMPLE)
Adds a list of edges to the graph.
- Return type:
None
- add_phase_gadget(phase, targets, edge_type=EdgeType.HADAMARD, vertex_type=VertexType.Z)
Add a phase gadget acting on the given target vertices. Returns a tuple (hub, phase_vertex) of the created vertices.
- Return type:
tuple[TypeVar(VT, bound=int),TypeVar(VT, bound=int)]
- add_to_phase(vertex, phase)
Add the given phase to the phase value of the given vertex.
- Return type:
None
- add_vertex(ty=VertexType.BOUNDARY, qubit=-1, row=-1, phase=None, ground=False, index=None)
Add a single vertex to the graph and return its index. The optional parameters allow you to respectively set the type, qubit index, row index and phase of the vertex. For H-boxes and Z-boxes with complex labels, use set_h_box_label or set_z_box_label after creating the vertex.
- Return type:
TypeVar(VT, bound=int)
- add_vertex_indexed(v)
Adds a vertex that is guaranteed to have the chosen index (i.e. ‘name’). If the index isn’t available, raises a ValueError. This method is used in the editor and ZXLive to support undo, which requires vertices to preserve their index.
- Return type:
None
- add_vertices(amount)
Add the given amount of vertices, and return the indices of the new vertices added to the graph.
- Return type:
Sequence[TypeVar(VT, bound=int)]
- adjoint()
Returns a new graph equal to the adjoint of this graph.
- Return type:
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]
- apply_effect(effect)
Inserts an effect into the outputs of the graph.
effectshould be a string with every character representing an output effect for each qubit. The possible types of effects are one of ‘0’, ‘1’, ‘+’, ‘-’ for the respective kets. If ‘/’ is specified this output is skipped.- Return type:
None
- apply_state(state)
Inserts a state into the inputs of the graph.
stateshould be a string with every character representing an input state for each qubit. The possible types of states are on of ‘0’, ‘1’, ‘+’, ‘-’ for the respective kets. If ‘/’ is specified this input is skipped.- Return type:
None
- auto_detect_io()
Adds every vertex that is of boundary-type to the list of inputs or outputs. Whether it is an input or output is determined by looking whether its neighbor is further to the right or further to the left of the input. Inputs and outputs are sorted by vertical position. Raises an exception if boundary vertex does not have a unique neighbor or if this neighbor is on the same horizontal position.
- Return type:
None
- clear_edata(edge)
Removes all edata associated to an edge
- Return type:
None
- clear_vdata(vertex)
Removes all vdata associated to a vertex
- Return type:
None
- clone()
This method should return an identical copy of the graph, without any relabeling.
This needs to be implemented in the backend, since different backends deal with names differently.
- Return type:
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]
- compose(other)
Inserts a graph after this one. The amount of qubits of the graphs must match. Also available by the operator graph1 + graph2
- Return type:
None
- connected(v1, v2)
Returns whether vertices v1 and v2 share an edge.
- Return type:
bool
- copy(adjoint=False, backend=None)
Create a copy of the graph. If
adjointis set, the adjoint of the graph will be returned (inputs and outputs flipped, phases reversed). Whenbackendis set, a copy of the graph with the given backend is produced. By default the copy will have the same backend.- Parameters:
adjoint (
bool) – set to True to make the copy be the adjoint of the graphbackend (
Optional[str]) – the backend of the output graph
- Return type:
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]- Returns:
A copy of the graph
Note
The copy will have consecutive vertex indices, even if the original graph did not.
- depth()
Returns the value of the highest row number given to a vertex. This is -1 when no rows have been set.
- Return type:
Union[float,int]
- edata(edge, key, default=None)
Returns the data value of the given edge associated to the key. If this key has no value associated with it, it returns the default value.
- Return type:
Any
- edata_dict(edge)
Return a dict of all edge data for the given edge.
- Return type:
dict[str,Any]
- edata_keys(edge)
Returns an iterable of the edge data key names.
- Return type:
Iterable[str]
- edge(s, t, et=EdgeType.SIMPLE)
Returns the name of the first edge with the given source/target and type. Behaviour is undefined if the vertices are not connected.
- Return type:
TypeVar(ET)
- edge_s(edge)
Returns the source of the given edge.
- Return type:
TypeVar(VT, bound=int)
- edge_set()
Returns the edges of the graph as a Python set. Should be overloaded if the backend supplies a cheaper version than this. Note this ignores parallel edges.
- Return type:
Union[set[TypeVar(ET)],Counter[TypeVar(ET)]]
- edge_st(edge)
Returns a tuple of source/target of the given edge.
- Return type:
tuple[TypeVar(VT, bound=int),TypeVar(VT, bound=int)]
- edge_t(edge)
Returns the target of the given edge.
- Return type:
TypeVar(VT, bound=int)
- edge_type(e)
Returns the type of the given edge:
EdgeType.SIMPLEif it is regular,EdgeType.HADAMARDif it is a Hadamard edge, 0 if the edge is not in the graph.- Return type:
EdgeType
- edges(s=None, t=None)
Iterator that returns all the edges in the graph, or all the edges connecting the pair of vertices. Output type depends on implementation in backend.
- Return type:
Iterable[TypeVar(ET)]
- classmethod from_json(js)
Converts the given .qgraph json string into a Graph. Works with the output of
to_json.- Return type:
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]
- classmethod from_tikz(tikz, warn_overlap=True, fuse_overlap=True, ignore_nonzx=False)
Converts a tikz diagram into a pyzx Graph. The tikz diagram is assumed to be one generated by Tikzit, and hence should have a nodelayer and a edgelayer..
- Parameters:
s – a string containing a well-defined Tikz diagram.
warn_overlap (
bool) – If True raises a Warning if two vertices have the exact same position.fuse_overlap (
bool) – If True fuses two vertices that have the exact same position. Only has effect if warn_overlap is False.ignore_nonzx (
bool) – If True suppresses most errors about unknown vertex/edge types and labels.
- Return type:
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]
Warning
Vertices that might look connected in the output of the tikz are not necessarily connected at the level of tikz itself, and won’t be treated as such in pyzx.
- get_auto_simplify()
Returns whether this graph auto-simplifies parallel edges
For multigraphs, this parameter might change, but simple graphs should always return True.
- Return type:
bool
- grounds()
Returns the set of vertices connected to a ground.
- Return type:
set[TypeVar(VT, bound=int)]
- incident_edges(vertex)
Returns all neighboring edges of the given vertex.
- Return type:
Iterable[TypeVar(ET)]
- inputs()
Gets the inputs of the graph.
- Return type:
tuple[TypeVar(VT, bound=int),...]
- is_ground(vertex)
Returns a boolean indicating if the vertex is connected to a ground.
- Return type:
bool
- is_hybrid()
Returns whether this is a hybrid quantum-classical graph, i.e. a graph with ground generators.
- Return type:
bool
- is_id()
Returns whether the graph is just a set of identity wires, i.e. a graph where all the vertices are either inputs or outputs, and they are connected to each other in a non-permuted manner.
- Return type:
bool
- is_phase_gadget(v)
Returns True if the vertex is the ‘hub’ of a phase gadget
- Return type:
bool
- is_well_formed()
Returns whether the graph is a well-formed ZX-diagram. This means that it has no isolated boundary vertices, each boundary vertex has a unique neighbor, W_input vertices have two neighbors: W_output and other, and W_output vertices have at least two neighbors: W_input and other.
- Return type:
bool
- classmethod load(filename, fmt=None, **kwargs)
Loads a graph from a file.
- Parameters:
filename (
str) – Path to the file to read.fmt (
Optional[str]) – Format of the file. Supported formats are ‘json’ and ‘tikz’. If not specified, the format is inferred from the file extension.**kwargs (
Any) – Additional keyword arguments passed to the underlying parser. For ‘tikz’ format: warn_overlap, fuse_overlap, ignore_nonzx.
- Return type:
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]- Returns:
The loaded graph.
- Raises:
ValueError – If the format is not supported or cannot be inferred.
- merge(other)
Merges this graph with the other graph in-place. Returns (list-of-vertices, list-of-edges) corresponding to the id’s of the vertices and edges of the other graph.
- Return type:
tuple[list[TypeVar(VT, bound=int)],list[TypeVar(ET)]]
- neighbors(vertex)
Returns all neighboring vertices of the given vertex.
- Return type:
Iterable[TypeVar(VT, bound=int)]
- normalize()
Puts every node connecting to an input/output at the correct qubit index and row.
- Return type:
None
- num_edges(s=None, t=None, et=None)
Returns the amount of edges in the graph
- Return type:
int
- num_inputs()
Gets the number of inputs of the graph.
- Return type:
int
- num_outputs()
Gets the number of outputs of the graph.
- Return type:
int
- num_vertices()
Returns the amount of vertices in the graph.
- Return type:
int
- outputs()
Gets the outputs of the graph.
- Return type:
tuple[TypeVar(VT, bound=int),...]
- pack_circuit_rows()
Compresses the rows of the graph so that every index is used.
- Return type:
None
- phase(vertex)
Returns the phase value of the given vertex.
- Return type:
Union[Fraction,int,Poly]
- phases()
Returns a mapping of vertices to their phase values.
- Return type:
Mapping[TypeVar(VT, bound=int),Union[Fraction,int,Poly]]
- qubit(vertex)
Returns the qubit index associated to the vertex. If no index has been set, returns -1.
- Return type:
Union[float,int]
- qubit_count()
Returns the number of inputs of the graph
- Return type:
Union[float,int]
- qubits()
Returns a mapping of vertices to their qubit index.
- Return type:
Mapping[TypeVar(VT, bound=int),Union[float,int]]
- rebind_variables_to_registry()
Rebind all variables in phases, Z-box labels, and the scalar to this graph’s registry. This should be called after deep copying a graph to ensure all variables reference the new graph’s registry.
- Return type:
None
- remove_edge(edge)
Removes the given edge from the graph.
- Return type:
None
- remove_edges(edges)
Removes the list of edges from the graph.
- Return type:
None
- remove_isolated_vertices()
Deletes all vertices and vertex pairs that are not connected to any other vertex.
- Return type:
None
- remove_vertex(vertex)
Removes the given vertex from the graph.
- Return type:
None
- remove_vertices(vertices)
Removes the list of vertices from the graph.
- Return type:
None
- row(vertex)
Returns the row that the vertex is positioned at. If no row has been set, returns -1.
- Return type:
Union[float,int]
- rows()
Returns a mapping of vertices to their row index.
- Return type:
Mapping[TypeVar(VT, bound=int),Union[float,int]]
- save(filename, fmt=None)
Saves the graph to a file.
- Parameters:
filename (
str) – Path to the file to write.fmt (
Optional[str]) – Format to use. Supported formats are ‘json’ and ‘tikz’. If not specified, the format is inferred from the file extension.
- Raises:
ValueError – If the format is not supported or cannot be inferred.
- Return type:
None
- set_auto_simplify(s)
Set whether this graph auto-simplifies parallel edges
Simple graphs should always auto-simplify, so this method is a no-op.
- Return type:
None
- set_edata(edge, key, val)
Sets the edge data associated to key to val.
- Return type:
None
- set_edata_dict(edge, d)
Set all edge data for the given edge from a dict, clearing existing data first.
- Return type:
None
- set_edge_type(e, t)
Sets the type of the given edge.
- Return type:
None
- set_ground(vertex, flag=True)
Connect or disconnect the vertex to a ground.
- Return type:
None
- set_inputs(inputs)
Sets the inputs of the graph.
- Return type:
None
- set_outputs(outputs)
Sets the outputs of the graph.
- Return type:
None
- set_phase(vertex, phase)
Sets the phase of the vertex to the given value.
- Return type:
None
- set_phase_master(m)
Points towards an instance of the class
Simplifier. Used for phase teleportation.- Return type:
None
- set_position(vertex, q, r)
Set both the qubit index and row index of the vertex.
- Return type:
None
- set_qubit(vertex, q)
Sets the qubit index associated to the vertex.
- Return type:
None
- set_row(vertex, r)
Sets the row the vertex should be positioned at.
- Return type:
None
- set_type(vertex, t)
Sets the type of the given vertex to t.
- Return type:
None
- set_vdata(vertex, key, val)
Sets the vertex data associated to key to val.
- Return type:
None
- stats()
- Return type:
str- Returns:
Returns a string with some information regarding the degree distribution of the graph.
- subgraph_from_vertices(verts)
Returns the subgraph consisting of the specified vertices.
- Return type:
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]
- substitute_variables(var_values, in_place=False)
Substitute values for symbolic variables in all phases and Z-box labels.
Note: H-box labels are always concrete complex numbers, so they are not eligible for substitution.
- Parameters:
var_values (
Mapping[str,float|complex|Fraction|Poly]) – Mapping from variable names (strings) to their substitution values (float, complex, Fraction, or Poly). Complex values are only valid for Z-box labels; phases must be real-valued.in_place (
bool) – If True, modify this graph. If False (default), return a new graph with substitutions applied.
- Return type:
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]- Returns:
The graph with variables substituted (self if in_place=True, a copy otherwise).
Example
>>> g.substitute_variables({'theta': 0.5, 'phi': Fraction(1, 4)})
- tensor(other)
Take the tensor product of two graphs. Places the second graph below the first one. Can also be called using the operator
graph1 @ graph2- Return type:
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]
- to_dict(include_scalar=True)
Returns a dictionary representation of the graph, which can then be converted into json.
- Return type:
dict[str,Any]
- to_graphml()
Returns a GraphML representation of the graph.
- Return type:
str
- to_json(include_scalar=True)
Returns a json representation of the graph. Convert back into a graph using
from_json.- Return type:
str
- to_matrix(preserve_scalar=True, strategy='naive')
Returns a representation of the graph as a matrix using
tensorfy- Return type:
ndarray
- to_tensor(preserve_scalar=True, strategy='naive')
Returns a representation of the graph as a tensor using
tensorfy- Return type:
ndarray
- to_tikz(draw_scalar=False)
Returns a Tikz representation of the graph.
- Return type:
str
- type(vertex)
Returns the type of the given vertex: VertexType.BOUNDARY if it is a boundary, VertexType.Z if it is a Z node, VertexType.X if it is a X node, VertexType.H_BOX if it is an H-box.
- Return type:
VertexType
- types()
Returns a mapping of vertices to their types.
- Return type:
Mapping[TypeVar(VT, bound=int),VertexType]
- update_phase_index(old, new)
When a phase is moved from a vertex to another vertex, we need to tell the phase_teleportation algorithm that this has happened. This function does that. Used in some of the rules in simplify.
- Return type:
None
- vdata(vertex, key, default=None)
Returns the data value of the given vertex associated to the key. If this key has no value associated with it, it returns the default value.
- Return type:
Any
- vdata_keys(vertex)
Returns an iterable of the vertex data key names. Used e.g. in making a copy of the graph in a backend-independent way.
- Return type:
Iterable[str]
- vertex_degree(vertex)
Returns the degree of the given vertex.
- Return type:
int
- vertex_set()
Returns the vertices of the graph as a Python set. Should be overloaded if the backend supplies a cheaper version than this.
- Return type:
set[TypeVar(VT, bound=int)]
- vertices()
Iterator over all the vertices.
- Return type:
Iterable[TypeVar(VT, bound=int)]
Circuit API
- class Circuit(qubit_amount, name='', bit_amount=None)
Class for representing quantum circuits.
This class is mostly just a wrapper for a list of gates with methods for converting between different representations of a quantum circuit.
The methods in this class that convert a specification of a circuit into an instance of this class, generally do not check whether the specification is well-defined. If a bad input is given, the behaviour is undefined.
- add_circuit(circ, mask=None, bit_mask=None)
Adds the gate of another circuit to this one. If
maskis not given, then they must have the same amount of qubits and they are mapped one-to-one. If mask is given then it must be a list specifying to which qubits the qubits in the given circuit correspond. Similarly, ifbit_maskis not given, then they must have the same amount of bits.Example:
c1 = Circuit(qubit_amount=4) c2 = Circuit(qubit_amount=2) c2.add_gate("CNOT",0,1) c1.add_circuit(c2, mask=[0,3]) # Now c1 has a CNOT from the first to the last qubit
If the circuits have the same amount of qubits then it can also be called as an operator:
c1 = Circuit(2) c2 = Circuit(2) c1 += c2
- Return type:
None
- add_gate(gate, *args, **kwargs)
Adds a gate to the circuit.
gatecan either be an instance of aGate, or it can be the name of a gate, in which case additional arguments should be given.Example:
circuit.add_gate("CNOT", 1, 4) # adds a CNOT gate with control 1 and target 4 circuit.add_gate("ZPhase", 2, phase=Fraction(3,4)) # Adds a ZPhase gate on qubit 2 with phase 3/4
- Return type:
None
- add_gates(gates, qubit)
Adds a series of single qubit gates on the same qubit.
gatesshould be a space-separated string of gatenames.Example:
circuit.add_gates("S T H T H", 1)
- Return type:
None
- static from_graph(g, split_phases=True)
Produces a
Circuitcontaining the gates of the given ZX-graph. If the ZX-graph is not circuit-like then the behaviour of this function is undefined.split_phasesgoverns whether nodes with phases should be split into Z,S, and T gates or if generic ZPhase/XPhase gates should be used.- Return type:
- static from_qasm(s)
Produces a
Circuitbased on a QASM input string. Supports OpenQASM 2 and 3, includingreset,measure, andif(classical control / feedforward) statements. It currently doesn’t support custom gates that have parameters.- Return type:
- static from_qasm_file(fname)
Produces a
Circuitbased on a QASM description of a circuit. Supports OpenQASM 2 and 3, includingreset,measure, andif(classical control / feedforward) statements. It currently doesn’t support custom gates that have parameters.- Return type:
- static from_qc_file(fname)
Produces a
Circuitbased on a .qc description of a circuit. If a Toffoli gate with more than 2 controls is encountered, ancilla qubits are added. Currently up to 5 controls are supported.- Return type:
- static from_qsim_file(fname)
Produces a
Circuitbased on a .qc description of a circuit. If a Toffoli gate with more than 2 controls is encountered, ancilla qubits are added. Currently up to 5 controls are supported.- Return type:
- static from_quipper(s)
Produces a
Circuitbased on a Quipper ASCII description of a circuit. Currently measurement instructions are not supported and are discarded.- Return type:
- static from_quipper_file(fname)
Produces a
Circuitbased on a Quipper ASCII description of a circuit. Currently measurement instructions are not supported and are discarded.- Return type:
- initialize_qubits(initialize_qubits)
- Parameters:
initialize_qubits (
List[bool]) – A list of booleans of length equal to the number of qubits in the circuit. If the i-th entry is True, the i-th qubit is initialized to |0>, otherwise the qubit will not be initialized.
- static load(circuitfile)
Tries to detect the circuit description language from the filename and its contents, and then tries to load the file into a circuit.
- Return type:
- postselect_qubits(postselect_qubits)
- prepend_gate(gate, *args, **kwargs)
The same as add_gate, but adds the gate to the start of the circuit, not the end.
- stats(depth=False)
Returns statistics on the amount of gates in the circuit, separated into different classes (such as amount of T-gates, two-qubit gates, Hadamard gates).
- Return type:
str
- stats_dict(depth=False)
Returns a dictionary containing statistics on the amount of gates in the circuit, separated into different classes (such as amount of T-gates, two-qubit gates, Hadamard gates).
- Return type:
dict
- tcount()
Returns the amount of T-gates necessary to implement this circuit.
- Return type:
int
- tensor(other)
Takes the tensor product of two Circuits. Places the second one below the first. Can also be done as an operator: circuit1 @ circuit2.
- Return type:
- to_basic_gates()
Returns a new circuit with every gate expanded in terms of X/Z phases, Hadamards and the 2-qubit gates CNOT, CZ, CX.
- Return type:
- to_emoji()
Converts circuit into a representation that can be copy-pasted into the ZX-calculus Discord server.
- Return type:
str
- to_graph(zh=False, compress_rows=True, backend=None, elide_initial_resets=False)
Turns the circuit into a ZX-Graph. If
compress_rowsis set, it tries to put single qubit gates on different qubits, on the same row.elide_initial_resets(default False) skips the discard chain for aReseton an unmodified input wire. Defaults to False because programmatically-constructed circuits may have uninitialized inputs, where a leadingResetis not redundant. Set to True only when those inputs are already represented as explicit |0⟩ states (e.g. viainitialize_qubitsor OpenQASM-style implicit |0⟩ inputs); otherwise eliding turns the leadingResetinto a :rtype:BaseGraphno-op instead of trace-out-and-reprepare. See
circuit_to_graphfor details.
- to_matrix(preserve_scalar=True, strategy='naive')
Returns a numpy matrix describing the circuit.
- Return type:
ndarray
- to_qasm(version=2)
Produces a QASM description of the circuit.
- Return type:
str
- to_qc()
Produces a .qc description of the circuit.
- Return type:
str
- to_quipper()
Produces a Quipper ASCII description of the circuit.
- Return type:
str
- to_tensor(preserve_scalar=True, strategy='naive')
Returns a numpy tensor describing the circuit.
- Return type:
ndarray
- twoqubitcount()
Returns the amount of 2-qubit gates necessary to implement this circuit.
- Return type:
int
- verify_equality(other, up_to_swaps=False, up_to_global_phase=True)
Composes the other circuit with the adjoint of this circuit, and tries to reduce it to the identity using
simplify.full_reduce`. If successful returns True, if not returns None.Note
A successful reduction to the identity is strong evidence that the two circuits are equal, if this function is not able to reduce the graph to the identity this does not prove anything.
- Parameters:
other (
Circuit) – the circuit to compare equality to.up_to_swaps (
bool) – if set to True, only checks equality up to a permutation of the qubits.
- Return type:
bool
Generating Circuits
The following are some methods to generate (random) quantum circuits.
- CNOT_HAD_PHASE_circuit(qubits, depth, p_had=0.2, p_t=0.2, clifford=False, seed=None, sigma=None)
Construct a Circuit consisting of CNOT, HAD and phase gates. The default phase gate is the T gate, but if
clifford=True, then this is replaced by the S gate.- Parameters:
qubits (
int) – number of qubits of the circuitdepth (
int) – number of gates in the circuitp_had (
float) – probability that each gate is a Hadamard gatep_t (
float) – probability that each gate is a T gate (or ifcliffordis set, S gate)clifford (
bool) – when set to True, the phase gates are S gates instead of T gates.seed (
Optional[int]) – When given, this specifies the RNG seed.sigma (
Optional[float]) – standard deviation (hence sigma^2 = variance) of CNOT spread across qubits, following a normal distribution.CNOT (i.e. sigma=inf means all qubits are weighted equally when deciding spread of) –
means (sigma=1) –
gap (CNOTs always span exactly a one qubit) –
connections (and e.g. epsilion=2 favours local qubits over long-range) –
etc. –
- Return type:
- Returns:
A random circuit consisting of Hadamards, CNOT gates and phase gates.
- cliffordT(qubits, depth, p_t=None, p_s=None, p_hsh=None, p_cnot=None, backend=None, seed=None, sigma=None)
Generates a circuit consisting of randomly placed Clifford+T gates. Optionally, take probabilities of adding T, S, HSH, and CNOT. If probabilities for only a subset of gates is given, any remaining probability will be uniformly distributed among the remaining gates.
- Parameters:
qubits (
int) – Amount of qubits in circuit.depth (
int) – Depth of circuit.p_t (
Optional[float]) – Probability that each gate is a T-gate.p_s (
Optional[float]) – Probability that each gate is a S-gate.p_hsh (
Optional[float]) – Probability that each gate is a HSH-gate.p_cnot (
Optional[float]) – Probability that each gate is a CNOT-gate.backend (
Optional[str]) – When given, should be one of the possible Backends backends.seed (
Optional[int]) – When given, this specifies the RNG seed.sigma (
Optional[float]) – standard deviation (hence sigma^2 = variance) of CNOT spread across qubits, following a normal distribution. i.e. sigma=inf means all qubits are weighted equally when deciding spread of CNOT, sigma=1 means CNOTs always span exactly a one qubit gap, and e.g. epsilion=2 favours local qubits over long-range connections, etc.
- Return type:
Instance of graph of the given backend.
- cliffordTmeas(qubits, depth, p_t=None, p_s=None, p_hsh=None, p_cnot=None, p_meas=None, backend=None, seed=None, sigma=None)
Generates a circuit consisting of randomly placed Clifford+T gates. Optionally, take probabilities of adding T, S, HSH, CNOT, and measurements. If probabilities for only a subset of gates is given, any remaining probability will be uniformly distributed among the remaining gates.
- Parameters:
qubits (
int) – Amount of qubits in circuit.depth (
int) – Depth of circuit.p_t (
Optional[float]) – Probability that each gate is a T-gate.p_s (
Optional[float]) – Probability that each gate is a S-gate.p_hsh (
Optional[float]) – Probability that each gate is a HSH-gate.p_cnot (
Optional[float]) – Probability that each gate is a CNOT-gate.p_meas (
Optional[float]) – Probability that each gate is a measurement.backend (
Optional[str]) – When given, should be one of the possible Backends backends.seed (
Optional[int]) – When given, this specifies the RNG seed.sigma (
Optional[float]) – standard deviation (hence sigma^2 = variance) of CNOT spread across qubits, following a normal distribution. i.e. sigma=inf means all qubits are weighted equally when deciding spread of CNOT, sigma=1 means CNOTs always span exactly a one qubit gap, and e.g. epsilion=2 favours local qubits over long-range connections, etc.
- Return type:
Instance of graph of the given backend.
- cliffords(qubits, depth, no_hadamard=False, t_gates=False, backend=None, seed=None, sigma=None)
Generates a circuit consisting of randomly placed Clifford gates. Uses a different approach to generating Clifford circuits then
cliffordT.- Parameters:
qubits (
int) – Amount of qubits in circuit.depth (
int) – Depth of circuit.no_hadamard (
bool) – Whether hadamard edges are allowed to be placed.backend (
Optional[str]) – When given, should be one of the possible Backends backends.seed (
Optional[int]) – When given, this specifies the RNG seed.sigma (
Optional[float]) – standard deviation (hence sigma^2 = variance) of CNOT spread across qubits, following a normal distribution. i.e. sigma=inf means all qubits are weighted equally when deciding spread of CNOT, sigma=1 means CNOTs always span exactly a one qubit gap, and e.g. epsilion=2 favours local qubits over long-range connections, etc.
- Return type:
Instance of graph of the given backend.
- cnots(qubits, depth, backend=None, seed=None, sigma=None)
Generates a circuit consisting of randomly placed CNOT gates.
Args: qubits: Amount of qubits in circuit depth: Depth of circuit backend: When given, should be one of the possible Backends backends. seed: When given, this specifies the RNG seed. sigma: standard deviation (hence sigma^2 = variance) of CNOT spread across qubits, following a normal distribution.
i.e. sigma=inf means all qubits are weighted equally when deciding spread of CNOT, sigma=1 means CNOTs always span exactly a one qubit gap, and e.g. epsilion=2 favours local qubits over long-range connections, etc.
- Return type:
- Returns:
Instance of graph of the given backend
- identity(qubits, depth=1, backend=None)
Generates a
pyzx.graph.Graphrepresenting an identity circuit.- Parameters:
qubits (
int) – number of qubits (i.e. parallel lines of the Graph)depth (
Union[float,int]) – at which row the output vertices should be placedbackend (
Optional[str]) – the backend to use for the output graph
- Return type:
- phase_poly(n_qubits, n_phase_layers, cnots_per_layer)
Create a random phase polynomial circuit.
- Parameters:
n_qubits (
int) – Number of qubits in the circuit.n_phase_layers (
int) – Number of layers of phase gates.cnots_per_layer (
int) – Number of CNOTs in each layer.
- Return type:
- Returns:
A random phase polynomial circuit.
- phase_poly_approximate(n_qubits, n_CNOTs, n_phases)
Create a random phase polynomial circuit with an exact number of CNOT gates.
- Parameters:
n_qubits (
int) – Number of qubits in the circuit.n_CNOTs (
int) – Number of CNOTs in the circuit.n_phases (
int) – Target of phase gates in the circuit. The actual number of phase gates may be slightly different.
- Return type:
- Returns:
A random phase polynomial circuit.
- phase_poly_from_gadgets(n_qubits, n_gadgets)
Create a random phase polynomial circuit from a set of phase gadgets.
- Parameters:
n_qubits (
int) – Number of qubits in the circuit.n_gadgets (
int) – Number of phase gadgets to generate.
- Return type:
- Returns:
A random phase polynomial circuit.
Circuit extraction and matrices over Z2
There is basically a single function that is needed for the most general extraction of a circuit from a ZX-diagram:
- extract_circuit(g, optimize_czs=True, optimize_cnots=2, up_to_perm=False, quiet=True)
Given a graph put into semi-normal form by
full_reduce, it extracts its equivalent set of gates into an instance ofCircuit. This function implements a more optimized version of the algorithm described in There and back again: A circuit extraction taleThe graph must be a unitary (non-hybrid) diagram with equal numbers of inputs and outputs. Graphs containing ground vertices (e.g., from circuits with measurements or resets) are not supported and will raise
ValueError.- Parameters:
g (
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]) – The ZX-diagram graph to be extracted into a Circuit.optimize_czs (
bool) – Whether to try to optimize the CZ-subcircuits by exploiting overlap between the CZ gates.optimize_cnots (
int) – (0,1,2,3) Level of CNOT optimization to apply.up_to_perm (
bool) – If true, returns a circuit that is equivalent to the given graph up to a permutation of the inputs.quiet (
bool) – Whether to print detailed output of the extraction process.
- Raises:
ValueError – If the graph contains ground vertices or has differing numbers of inputs and outputs.
- Return type:
Warning
Note that this function changes the graph
gin place. In particular, if the extraction fails, the modifiedgshows how far the extraction got. If you want to keep the originalgthen inputg.copy()intoextract_circuit.
This function uses some reasoning over matrices over the field Z2. This functionality is implemented in the following class.
- class Mat2(data)
A matrix over Z2, with methods for multiplication, primitive row and column operations, Gaussian elimination, rank, and epi-mono factorisation.
- col_add(c0, c1)
Add r0 to r1
- Return type:
None
- col_swap(c0, c1)
Swap the columns c0 and c1
- Return type:
None
- factor()
Produce a factorisation m = m0 * m1, where
m0.cols() = m1.rows() = m.rank()
- gauss(full_reduce=False, x=None, y=None, blocksize=6, pivot_cols=[])
Compute the echelon form. Returns the number of non-zero rows in the result, i.e. the rank of the matrix.
The parameter ‘full_reduce’ determines whether to compute the full row-reduced form, useful e.g. for matrix inversion and CNOT circuit synthesis.
The parameter ‘blocksize’ gives the size of the blocks in a block matrix for performing Patel/Markov/Hayes optimization, see:
K. Patel, I. Markov, J. Hayes. Optimal Synthesis of Linear Reversible Circuits. QIC 2008
If blocksize is given as self.cols(), then this is equivalent to just eliminating duplicate rows before doing normal Gaussian elimination.
Contains two convenience parameters for saving the primitive row operations. Suppose the row-reduced form of m is computed as:
g * m = m’
Then, x –> g * x and y –> y * g^-1.
Note x and y need not be matrices. x can be any object that implements the method row_add(), and y any object that implements col_add().
- Return type:
int
- nullspace(should_copy=True)
Returns a list of non-zero vectors that span the nullspace of the matrix. If the matrix has trivial kernel it returns the empty list.
- Return type:
List[List[Literal[0,1]]]
- permute_cols(p)
Permute the columns of the matrix according to the permutation p.
- Return type:
None
- permute_rows(p)
Permute the rows of the matrix according to the permutation p.
- Return type:
None
- rank()
Returns the rank of the matrix.
- Return type:
int
- row_add(r0, r1)
Add r0 to r1
- Return type:
None
- row_swap(r0, r1)
Swap the rows r0 and r1
- Return type:
None
- solve(b)
Return a vector x such that M * x = b, or None if there is no solution.
- Return type:
Optional[Mat2]
- to_cnots(optimize=False, use_log_blocksize=False)
Returns a list of CNOTs that implements the matrix as a reversible circuit of qubits.
- Return type:
List[CNOT]
List of simplifications
Below is listed the content of simplify.py.
An overview of all the different rewrite rules can
also be found in the rules notebook.
This module contains the ZX-diagram simplification strategies of PyZX.
Each strategy is an instance of the class rewrite.Rewrite, based on the rule functions found in rewrite_rules.
The main procedures of interest are clifford_simp for simple reductions,
full_reduce for the full rewriting power of PyZX, and teleport_reduce to
use the power of full_reduce while not changing the structure of the graph.
The individual rewrites can also be called directly.
For methods that terminate, they can be called using their simp method, e.g.: spider_simp.simp(g).
As a shorthand you can just call it directly: spider_simp(g).
The rewrites can also be applied manually to specific vertices using their apply method, e.g.: spider_simp.apply(g, v, w).
Whether the apply method takes one or two vertices depends on the rewrite.
You can find all the matches of a rewrite on a graph using the find_all_matches method, e.g.: spider_simp.find_all_matches(g).
- bialg_op_simp(graph): RewriteSimpGraph = <pyzx.rewrite.RewriteSimpGraph object>
Applies the bialgebra rule in reverse to a given pair of Z and X spiders. Can be run automatically on the entire graph.
- bialg_simp(graph): RewriteSimpDoubleVertex = <pyzx.rewrite.RewriteSimpDoubleVertex object>
Applies the bialgebra rule to a given pair of spiders (Z-X or X-H). Can be run automatically on the entire graph.
- clifford_simp(g, matchf=None, quiet=True, stats=None)
Keeps doing rounds of
interior_clifford_simpandpivot_boundary_simpuntil they can’t be applied anymore.- Return type:
int
- copy_simp(graph): RewriteSimpSingleVertex = <pyzx.rewrite.RewriteSimpSingleVertex object>
Copies a given vertex through its neighbor. Can be run automatically on the entire graph.
- drop_orphan_reset_discards(g)
Remove orphan reset-discard components.
A leading
reseton a freshqreginput emitted withelide_initial_resets=Falseproduces a disconnected component rooted at an input boundary and terminating in a degree-1 leaf taggedoutcome_type='reset_discard'carrying a fresh boolean phase_rN. Two shapes are common:BOUNDARY --S-- Z(0) --S-- X(_rN)straight out ofpyzx.circuit.graphparser.circuit_to_graph.BOUNDARY --H-- Z(_rN)afterfull_reduce(which converts the X-leaf to a Z-leaf via Hadamard and removes the identity Z(0) middle spider).
More generally, the component must be a chain whose intermediate vertices are phase-0, degree-2, untagged spiders.
_rNmust appear nowhere else in the graph (no other vertex phases, no Z-box labels, no scalar). Under those conditions, marginalising over_rNcollapses the component to a partial trace of the input boundary, equivalent to the elided graph with |0⟩ applied to that input up to a global scalar factor of1/sqrt(2)per orphan, which is folded intog.scalar.- Parameters:
g (
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]) – The graph to clean up. Modified in place.- Return type:
int- Returns:
The number of orphan components removed.
- full_reduce(g, matchf=None, quiet=True, stats=None)
The main simplification routine of PyZX. It uses a combination of
clifford_simpand the gadgetization strategiespivot_gadget_simpandgadget_simp. It also attempts to runsupplementarity_simpandcopy_simp.- Return type:
None
- gadget_simp(graph): RewriteSimpGraph = <pyzx.rewrite.RewriteSimpGraph object>
Finds and removes phase gadgets that act on the same set of targets. Should only be run on the entire graph.
- id_simp(graph): RewriteSimpSingleVertex = <pyzx.rewrite.RewriteSimpSingleVertex object>
Removes an identity spider. Can be run automatically.
- is_graph_like(g, strict=False)
Checks if a ZX-diagram is graph-like: only contains Z-spiders which are connected by Hadamard edges. If strict is True, then also checks that each boundary vertex is connected to a Z-spider, and that each Z-spider is connected to at most one boundary.
- Return type:
bool
- lcomp_simp(graph): RewriteSimpSingleVertex = <pyzx.rewrite.RewriteSimpSingleVertex object>
Performs a local complementation rewrite on a given vertex. Can be run automatically on the entire graph.
- phase_free_simp(g)
Performs the following set of simplifications on the graph: spider -> bialg
- Return type:
bool
- pivot_boundary_simp(graph): RewriteSimpDoubleVertex = <pyzx.rewrite.RewriteSimpDoubleVertex object>
Performs pivot rewrite on an interior Pauli vertex and a non-Pauli Z-spider with exactly one boundary neighbour.
- pivot_gadget_simp(graph): RewriteSimpDoubleVertex = <pyzx.rewrite.RewriteSimpDoubleVertex object>
Performs pivot rewrite on an interior Pauli vertex and an interior non-Pauli vertex.
- pivot_simp(graph): RewriteSimpDoubleVertex = <pyzx.rewrite.RewriteSimpDoubleVertex object>
Performs a pivot rewrite. Can be run automatically on the entire graph.
- reduce_scalar(g, quiet=True, stats=None)
Modification of
full_reducethat is tailered for scalar ZX-diagrams. It skips the boundary pivots. Input must already be in graph-like form.- Return type:
int
- remove_self_loop_simp(graph): RewriteSimpSingleVertex = <pyzx.rewrite.RewriteSimpSingleVertex object>
Removes all self loops on a vertex. Can be run automatically.
- spider_simp(g)
Performs spider fusion and then removes any self loops
- Return type:
bool
- supplementarity_simp(graph): RewriteSimpGraph = <pyzx.rewrite.RewriteSimpGraph object>
Performs a supplementarity rewrite by removing non-Clifford spiders that act on the same set of targets. Should only be run on the entire graph.
- tcount(g)
Returns the amount of nodes in g that have a non-Clifford phase.
- Return type:
int
- teleport_reduce(g)
This simplification procedure runs
full_reducein a way that does not change the graph structure of the resulting diagram. The only thing that is different in the output graph are the location and value of the phases.- Return type:
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]
- to_clifford_normal_form_graph(g)
Converts a graph that is Clifford into the form described by the right-hand side of eq. (11) of Graph-theoretic Simplification of Quantum Circuits with the ZX-calculus (https://arxiv.org/abs/1902.03178). That is, writes it as a series of layers: Hadamards, phase gates, CZ gates, parity form of Z-spiders to X-spiders, Hadamards, CZ gates, phase gates, Hadamards. Changes the graph in place.
- Return type:
None
- to_gh(g)
Turns every red node into a green node by applying a Hadamard to the edges incident to red nodes
- Return type:
None
- to_graph_like(g)
Puts a ZX-diagram in graph-like form.
- Return type:
None
- to_rg(g, init_z=None, init_x=None)
Try to eliminate H-edges by turning green nodes red
This implements a quadratic-time max-cut heuristic to eliminate H-edges. In the future, we may want to implement a linear-time version that does a worse job for very large graphs.
- Parameters:
g (
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]) – A ZX-graph.init_z (
Optional[Set[TypeVar(VT, bound=int)]]) – An optional set of vertices to make Z.init_x (
Optional[Set[TypeVar(VT, bound=int)]]) – An optional set of vertices to make X.
- Return type:
None
List of optimization functions
Below is listed the content of optimize.py.
This module implements several optimization methods on Circuits.
The function basic_optimization runs a set of back-and-forth gate commutation and cancellation routines.
phase_block_optimize does phase polynomial optimization using the TODD algorithm,
and full_optimize combines these two methods.
- basic_optimization(circuit, do_swaps=True, quiet=True)
Optimizes the circuit using a strategy that involves delayed placement of gates so that more matches for gate cancellations are found. Specifically tries to minimize the number of Hadamard gates to improve the effectiveness of phase-polynomial optimization techniques.
- Parameters:
circuit (
Circuit) – Circuit to be optimized.do_swaps (
bool) – When set uses some rules transforming CNOT gates into SWAP gates. Generally leads to better results, but messes up architecture-aware placement of 2-qubit gates.quiet (
bool) – Whether to print some progress indicators.
- Return type:
- full_optimize(circuit, quiet=True)
Optimizes the circuit using first some basic commutation and cancellation rules, and then a dedicated phase polynomial optimization strategy involving the TODD algorithm.
- phase_block_optimize(circuit, pre_optimize=True, quiet=True)
Optimizes the given circuit, by cutting it into phase polynomial pieces, and using the TODD algorithm to optimize each of these phase polynomials. The phase-polynomial circuits are then resynthesized using the parity network algorithm.
Note
Only works with Clifford+T circuits. Will give wrong output when fed smaller rotation gates, or Toffoli-like gates. Depending on the number of qubits and T-gates this function can take a long time to run. It can be sped up somewhat by using the TOpt implementation of TODD. If this is installed, point towards it using
zx.settings.topt_command, such as for instancezx.settings.topt_command = ['wsl', '../TOpt']for running it in the Windows Subsystem for Linux.- Parameters:
circuit (
Circuit) – The circuit to be optimized.pre_optimize (
bool) – Whether to callbasic_optimizationfirst.quiet (
bool) – Whether to print some progress indicators. Helpful when execution time is long.
- Return type:
List of routing functions
Below is listed the content of routing.py.
This module implements Architecture aware routing methods for Circuit s.
- create_architecture(name, **kwargs)
Creates an architecture from a name.
- Parameters:
name (
Union[str,Architecture]) – The name of the architecture, seepyzx.routing.architecturesfor the available constants.kwargs – Additional arguments to pass to the architecture constructor.
- Return type:
- Returns:
The architecture.
- class Architecture(name, coupling_graph=None, coupling_matrix=None, backend=None, qubit_map=None, reduce_order=None, **kwargs)
Class that represents the architecture of the qubits to be taken into account when routing.
- qubit2vertex(qubit)
Get the internal graph vertex index for a logical architecture qubit.
- Return type:
int
- vertex2qubit(vertex)
Get the logical architecture qubit for an internal graph vertex index.
- Return type:
int
- pre_calc_distances()
Pre-calculates the distances between all pairs of qubits in the architecture.
- Return type:
Dict[Literal['upper','full'],List[Dict[Tuple[int,int],Tuple[int,List[Tuple[int,int]]]]]]- Returns:
The computed distances. distances[“upper”|”full”][until][(v1,v2)] contains the distance between v1 and v2, and the shortest path, where upper|full indicates whether to consider bidirectional edges or not (respectively), until indicates the number of qubits to consider, for “full” the distance is calculated only between qubits with index <= until), and for “upper” the distance is calculated only between qubits with index >= until)
- pre_calc_non_cutting_vertices()
Adds to a dictionary all non-cutting vertices for every possible subset of qubits.
- Raises:
NotImplementedError – Function is not yet complete
- non_cutting_vertices(subgraph_vertices, pre_calc=False)
Find the non-cutting vertices for this subgraph.
- Parameters:
subgraph_vertices (
List[int]) – A list of vertex location within the subgraphpre_calc (
bool) – If true, callspre_calc_non_cutting_vertices, default False
- Return type:
List[int]- Returns:
A list of non-cutting qubits
- get_neighboring_qubits(qubit)
Given a qubit, finds all neighboring qubits in the graph.
- Parameters:
qubit (
int) – Location of qubit index within the graph- Return type:
Set[int]- Returns:
A set of all related qubit indices
- get_neighboring_vertices(vertex)
From a given vertex location, finds all neighboring vertices in the graph.
- Parameters:
vertex (
int) – Location of vertex within the graph- Return type:
Set[int]- Returns:
A set of all neighboring vertices
- to_quil_device()
Convert the graph to a PyQuil NxDevive object.
- Returns:
A NxDevice object relating to the graphs topology representing this architecture
- visualize(filename=None)
Visualise the graph and save it as a png image file.
- Parameters:
filename – The filename of the image to be saved, default None
- floyd_warshall(subgraph_vertices, upper=True, rec_vertices=[])
Implementation of the Floyd-Warshall algorithm to calculate the all-pair distances in a given graph.
- Parameters:
subgraph_vertices (
List[int]) – Subset of vertices to considerupper (
bool) – Whether use bidirectional edges or only ordered edges (src, tgt) such that src > tgt, default Truerec_vertices (
List[int]) – A subgraph for which edges are considered undirected, as if the upper flag was set
- Return type:
Dict[Tuple[int,int],Tuple[int,List[Tuple[int,int]]]]- Returns:
A dict with for each pair of qubits in the graph, a tuple with their distance and the corresponding shortest path
- shortest_path(start_qubit, end_qubit, qubits_to_use=None)
Find the shortest path between two qubits in the graph using breadth-first search (BFS)
- Parameters:
start_qubit (
int) – Location of the start qubit index within the graphend_qubit (
int) – Location of the end qubit index within the graphqubits_to_use (
Optional[List[int]]) – An optional list of qubit indicies to be traversed along the path, default None
- Return type:
Optional[List[int]]- Returns:
An optional list showcasing the path from the start_qubit to the end_qubit
- steiner_tree(start_qubit, qubits_to_use, upper=True)
Approximates the steiner tree given the architecture, a root qubit and the other qubits that should be present. This is done using the pre-calculated all-pairs shortest distance and Prim’s algorithm for creating a minimum spanning tree.
- Parameters:
start_qubit (
int) – The index of the root qubit to be usedqubits_to_use (
List[int]) – The indices of the other qubits that should be present in the steiner treeupper (
bool) – Whether to consider only the nodes the steiner tree is used for creating an upper triangular matrix or a full reduction.
- Yields:
First yields all edges from the tree top-to-bottom, finished with None, then yields all edges from the tree bottom-up, finished with None.
- Return type:
Iterator[Optional[Tuple[int,int]]]
- rec_steiner_tree(start_qubit, terminal_qubits, usable_qubits, rec_qubits, upper=True)
Build a Steiner tree with recursive constraints for given qubits, connecting all terminal qubits using the min number of edges.
- Parameters:
start_qubit – Location of the start qubit index within the graph
terminal_qubits – List of qubit indicies within the graph that must be included in the tree
usable_qubits – List of all qubit indicies within the graph that can be used to build the tree
rec_qubits – list of qubit indicies within the graph where edges are treated as undirected
upper – Whether use bidirectional edges or only ordered edges (src, tgt) such that src > tgt, default True
- Yeilds:
Pairs of qubit indices representing edges in the Steiner tree, yeilds None to signal end of top-down phase and next phase, then yeild None to signal completion
- transpose()
Returns a transposed copy of the architecture with reversed qubit mapping.
- arities()
Returns a list of tuples (i, arity) where i is the index of each node and arity is the number of neighbors, sorted by decreasing arity.
- Return type:
List[Tuple[int,int]]
- class Parity(par, n_qubits=None)
A set of qubits XORed together.
-
parity:
List[bool]
- count()
Returns the number of qubits interacting in the parity.
- Return type:
int
- n_qubits()
Returns the total number of qubits.
- Return type:
int
- to_mat2_row()
Returns an array of 1s and 0s based off the internal parity array.
- Return type:
List[Literal[0,1]]
-
parity:
- class CNOT_tracker(n_qubits, **kwargs)
A circuit-like object that keeps track of row and column operations applied during Gauss elimination via CNOT gates.
-
row_perm:
ndarray The row permutation of the qubit parity matrix.
-
col_perm:
ndarray The column permutation of the qubit parity matrix.
- count_cnots()
Returns the number of CNOT gates in the tracker.
- Return type:
int
- cnot_depth()
Returns the CNOT/CZ depth of the tracked circuit.
- Return type:
int
- row_add(q0, q1)
Track a row addition operation on the matrix.
- add_gate(gate, *args, **kwargs)
Adds a gate to the circuit, if it is a CNOT gate it will track a row addition operation on the matrix.
- col_add(q0, q1)
Track a column addition operation on the matrix.
- static get_metric_names()
Metric names for the CNOT tracker.
- Return type:
List[str]
- gather_metrics()
Gather metrics for the CNOT tracker.
- Return type:
Dict[str,int]
- prepend_gate(gate, *args, **kwargs)
Adds a gate to the circuit.
gatecan either be an instance of aGate, or it can be the name of a gate, in which case additional arguments should be given.Example:
circuit.add_gate("CNOT", 1, 4) # adds a CNOT gate with control 1 and target 4 circuit.add_gate("ZPhase", 2, phase=Fraction(3,4)) # Adds a ZPhase gate on qubit 2 with phase 3/4
- to_qasm(version=2)
Outputs a QASM of the current circuit.
- Parameters:
version (
int) – The QASM version to be used, default 2- Return type:
str- Returns:
The initial wiring, the resulting wiring and the full QASM circuit
- static from_circuit(circuit)
Takes a circuit and outputs a CNOT_tracker of the circuit.
- Parameters:
circuit (
Circuit) – A circuit to be converted- Return type:
- Returns:
A CNOT_tracker of the circuit given
- update_matrix()
Rebuilds the parity matrix from the gates in the circuit.
- static from_qasm_file(fname)
Takes the filename of a QASM and outputs a CNOT_tracker of it.
- Parameters:
fname (
str) – The filename of the QASM- Return type:
- Returns:
A CNOT_tracker of the QASM given
-
row_perm:
- class ElimMode(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Row elimination modes for the cnot mapper procedures
- GAUSS_MODE = 'gauss'
Gaussian elimination, ignoring the architecture.
- STEINER_MODE = 'steiner'
Steiner tree based Gaussian elimination, optimizing the number of SWAPs operations required to synthesize the CNOTs on the restricted architecture.
- GENETIC_GAUSS_MODE = 'genetic_gauss'
Gauss elimination using a genetic algorithm to find the best row permutation.
- GENETIC_STEINER_MODE = 'genetic_steiner'
Steiner Gauss elimination using a genetic algorithm to find the best row permutation.
- PSO_GAUSS_MODE = 'pso_gauss'
Gauss elimination using Particle Swarm Optimization to find the best row permutation.
- PSO_STEINER_MODE = 'pso_steiner'
Steiner Gauss elimination using Particle Swarm Optimization to find the best row permutation.
- class CostMetric(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Metrics for the cost of the gates needed for a given permutation, used by the cnot mapper fitness functions.
- COMBINED = 'combined'
Count both the number of CNOTs and the depth of the circuit
- DEPTH = 'depth'
Count the number of CNOTs in the circuit
- COUNT = 'count'
Count the depth of the circuit
- class FitnessFunction(metric, matrix, mode, architecture, row=True, col=True, full_reduce=True, **kwargs)
A fitness function that calculates the cost of the gates needed for a given permutation.
- gauss(mode, matrix, architecture=None, permutation=None, try_transpose=False, **kwargs)
Performs architecture-aware Gaussian Elimination on a matrix.
- Parameters:
mode (
Optional[ElimMode]) – Type of Gaussian elimination to be used, seeElimMode.matrix (
Mat2) – Target matrix to be reduced.architecture (
Optional[Architecture]) – Device architecture to take into account.permutation (
Optional[List[int]]) – If given, reduce a permuted version of the matrix.kwargs – Other arguments that can be given to the
Mat2.gaussfunction or parameters for the genetic algorithm.
- Return type:
int- Returns:
The rank of the matrix.
matrixis transformed inplace.
- permuted_gauss(matrix, mode=None, architecture=None, population_size=30, crossover_prob=0.8, mutate_prob=0.2, n_iterations=5, row=True, col=True, full_reduce=True, fitness_func=None, x=None, y=None, **kwargs)
Applies gaussian elimination to the given matrix, finding an optimal permutation of the matrix to reduce the number of CNOT gates.
- Parameters:
matrix (
Mat2) – Mat2 matrix to do gaussian elimination overmode (
Optional[ElimMode]) – Elimination mode to usearchitecture (
Optional[Architecture]) – Architecture to take into accountpopulation_size (
int) – For the genetic algorithmcrossover_prob (
float) – For the genetic algorithmmutate_prob (
float) – For the genetic algorithmn_iterations (
int) – For the genetic algorithmrow (
bool) – If the rows should be permutedAcol (
bool) – If the columns should be permutedfull_reduce (
bool) – Whether to do full gaussian reductionfitness_func (
Optional[FitnessFunction]) – Optional fitness function to usex – Optional tracker for the row operations
y – Optional tracker for the column operations
- Return type:
Tuple[List[int],Circuit,int]- Returns:
Best permutation found, list of CNOTS corresponding to the elimination.
- sequential_gauss(matrices, mode=None, architecture=None, fitness_func=None, input_perm=True, output_perm=True, swarm_size=15, n_steps=5, s_crossover=0.4, p_crossover=0.3, pso_mutation=0.2, full_reduce=True, **kwargs)
Applies architecture-aware Gaussian elimination to multiple matrices, sharing the optimization passes when using ParticleSwarmOptimization modes.
- Parameters:
matrix – List of matrices to do gaussian elimination over
mode (
Optional[ElimMode]) – Elimination mode to usearchitecture (
Optional[Architecture]) – Architecture to take into accountfitness_func (
Optional[FitnessFunction]) – Optional fitness function to useinput_perm (
bool) – Allow input permutationoutput_perm (
bool) – Whether the location of the output qubits can be different for the input location. Qubit locations can be optimized with pso.swarm_size (
int) – Swarm size for the swarm optimization.n_steps (
int) – The number of iterations for the particle swarm optimization.s_crossover (
float) – The crossover percentage with the best particle in the swarm for the particle swarm optimizer. Must be between 0.0 and 1.0.p_crossover (
float) – The crossover percentage with the personal best of a particle for the particle swarm optimizer. Must be between 0.0 and 1.0.pso_mutation (
float) – The mutation percentage of a particle for the particle swarm optimizer. Must be between 0.0 and 1.0.full_reduce (
bool) – Fully reduce the matrices
- Return type:
Tuple[List[CNOT_tracker],List[List[int]],int]- Returns:
List of CNOT trackers corresponding to the eliminations, list of final permutations for each matrix, and the cost of the eliminations.
- steiner_gauss(matrix, architecture, full_reduce=False, x=None, y=None)
Performs Gaussian elimination that is constrained by the given architecture
- Parameters:
matrix (
Mat2) – PyZX Mat2 matrix to be reducedarchitecture (
Architecture) – The Architecture object to conform tofull_reduce (
bool) – Whether to fully reduce or only create an upper triangular formx (
Optional[CNOT_tracker]) – Optional CNOT_tracker object to track row operationsy (
Optional[CNOT_tracker]) – Optional CNOT_tracker object to track column operations
- Returns:
Rank of the given matrix
- rec_steiner_gauss(matrix, architecture, full_reduce=False, x=None, y=None, permutation=None, **kwargs)
Performs Gaussian elimination that is constrained bij the given architecture according to https://arxiv.org/pdf/1904.00633.pdf Only works on full rank, square matrices.
- Parameters:
matrix (
Mat2) – PyZX Mat2 matrix to be reducedarchitecture (
Architecture) – The Architecture object to conform tofull_reduce (
bool) – Whether to fully reduce or only create an upper triangular formx (
Optional[CNOT_tracker]) – Optional CNOT_tracker object to track row operationsy (
Optional[CNOT_tracker]) – Optional CNOT_tracker object to track column operationspermutation (
Optional[List[int]]) – Optional permutation of the qubits
- class RoutingMethod(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Phase polynomial routing method to use in
route_phase_poly.- MATROID = 'matroid'
Routing method based on matroid partitioning. Commonly slower than
RoutingMethod.GRAYandRoutingMethod.MEIJER.
- GRAY = 'GraySynth'
Routing method based on Gray synthesis (see arxiv.org/abs/1712.01859 ).
- MEIJER = 'meijer'
Routing method by Meijer and Duncan (see arxiv.org/abs/2004.06052 ).
- GRAY_MEIJER = 'GraySynth+Meijer'
Combination of
RoutingMethod.GRAYandRoutingMethod.MEIJER, keeps the best result of both.
- class RootHeuristic(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Heuristics for choosing the root of a Steiner tree during phase polynomial routing.
- RANDOM = 'gauss'
Randomly choose a root.
- EXHAUSTIVE = 'exhaustive'
Try all possible roots and choose the one with the lowest cost.
- ARITY = 'arity'
Choose the root randomly between the nodes with highest arity.
- RECURSIVE = 'recursive'
Use an already-chosen root in a recursive call.
- to_function()
Looks at the RootHeuristic type and returns the relevant root heuristic
- Return type:
Callable[[Architecture,Mat2,List[int],List[int],int,int,Any],List[int]]
- class SplitHeuristic(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Heuristics for choosing nodes to split a circuit during phase polynomial routing.
- RANDOM = 'random'
Randomly pick a candidate.
- ARITY = 'arity'
Split the circuit on the nodes with highest arity.
- COUNT = 'count'
Split the circuit on all the candidate nodes.
- to_function()
Looks at the SplitHeuristic type and returns the relevant split heuristic
- Return type:
Callable[[Architecture,Mat2,List[int],List[int],Any],List[int]]
- route_phase_poly(circuit, architecture, method=RoutingMethod.GRAY_MEIJER, mode=ElimMode.STEINER_MODE, root_heuristic=RootHeuristic.RECURSIVE, split_heuristic=SplitHeuristic.COUNT, **kwargs)
Compile a circuit to an architecture with restricted connectivity.
- Parameters:
circuit (
Union[Circuit,PhasePoly]) – The circuit to compile.architecture (
Architecture) – The target architecture.method (
RoutingMethod) – The routing method to use.mode (
ElimMode) – The elimination mode to use during the CNOT mapping step.split_heuristic (
SplitHeuristic) – The heuristic to use for splitting the circuit into subcircuits.root_heuristic (
RootHeuristic) – The heuristic to use for finding the root of the circuit.
- Return type:
- Returns:
The compiled circuit.
Functions for dealing with tensors
Below is listed the content of tensor.py.
This module provides methods for converting ZX-graphs into numpy tensors and using these tensors to test semantic equality of ZX-graphs. This module is not meant as an efficient quantum simulator. Due to the way the tensor is calculated it can only handle circuits of small size before running out of memory on a regular machine. Currently, it can reliably transform 9 qubit circuits into tensors. If the ZX-diagram is not circuit-like, but instead has nodes with high degree, it will run out of memory even sooner.
- adjoint(t)
Returns the adjoint of the tensor as if it were representing a circuit:
t = tensorfy(circ) tadj = tensorfy(circ.adjoint()) compare_tensors(adjoint(t),tadj) # This is True
- Return type:
ndarray
- compare_tensors(t1, t2, preserve_scalar=False, strategy='naive')
Returns true if
t1andt2represent equal tensors by callingtensorfy. When preserve_scalar is False (the default), equality is checked up to nonzero rescaling.Example: To check whether two ZX-graphs g1 and g2 are semantically the same you would do:
compare_tensors(g1,g2) # True if g1 and g2 represent the same linear map up to nonzero scalar
- Return type:
bool
- compose_tensors(t1, t2)
Returns a tensor that is the result of composing the tensors together as if they were representing circuits:
t1 = tensorfy(circ1) t2 = tensorfy(circ2) circ1.compose(circ2) t3 = tensorfy(circ1) t4 = compose_tensors(t1,t2) compare_tensors(t3,t4) # This is True
- Return type:
ndarray
- find_scalar_correction(t1, t2)
Returns the complex number
zsuch thatt1 = z*t2. :rtype:complexWarning
This function assumes that
compare_tensors(t1,t2,preserve_scalar=False)is True, i.e. thatt1andt2indeed are equal up to global scalar. If they aren’t, this function returns garbage.
- is_unitary(g)
Returns whether the given ZX-graph is equal to a unitary (up to a number).
- Return type:
bool
- tensor_to_matrix(t, inputs, outputs)
Takes a tensor generated by
tensorfyand turns it into a matrix. Theinputsandoutputsarguments specify the final shape of the matrix: 2^(outputs) x 2^(inputs)- Return type:
ndarray
- tensorfy(g, preserve_scalar=True, strategy='naive', verbose=False)
Returns a multidimensional numpy array representing the linear map the ZX diagram implements. Available simulation strategies are:
‘naive’: good for sparse graphs
‘rw-greedy-b2t’: rank-width with greedy bottom-to-top heuristic
‘rw-greedy-linear’: rank-width with greedy-linear heuristic
‘rw-auto’: choose the best of ‘rw-greedy-b2t’ and ‘rw-greedy-linear’
- Parameters:
g (
BaseGraph[TypeVar(VT, bound=int),TypeVar(ET)]) – ZX diagrampreserve_scalar (
bool) – whether to account for the diagram scalarstrategy (
str) – which simulation strategy to useverbose (
bool) – print additional info
- Return type:
ndarray[tuple[Any,...],dtype[complex128]]- Returns:
Numpy tensor having (num_inputs + num_outputs) dimensions (output dimensions first)
Drawing
Below is listed the content of drawing.py.
- arrange_scalar_diagram(g)
- Return type:
None
- draw(g, labels=False, **kwargs)
Draws the given Circuit or Graph. Depending on the value of
pyzx.settings.drawing_backendeither uses matplotlib or d3 to draw.- Return type:
Any
- draw_3d(g, labels=False, pauli_web=None)
- Return type:
Any
- draw_d3(g, labels=False, scale=None, auto_hbox=None, show_scalar=False, vdata=None, pauli_web=None, auto_layout=False)
If auto_layout is checked, will automatically space vertices of graph with no regard to qubit/row.
- Return type:
Any
- draw_matplotlib(g, labels=False, figsize=(8, 2), h_edge_draw='blue', show_scalar=False, rows=None)
- Return type:
Any
- graphs_to_gif(graphs, filename, frame_duration=0.5)
Given a list of graphs, outputs an animated gif showing them in sequence.
- Parameters:
graphs (
List[BaseGraph]) – The list of Graph instances that should be made into a gif.filename (
str) – the full filename of the output gif.frame_duration (
float) – how long (in seconds) each frame should last.
Warning
This function requires imagio to be installed (pip install imageio).
- matrix_to_latex(m)
Converts a matrix into latex code. Useful for pretty printing the matrix of a Circuit/Graph.
- Return type:
str
Example
# Run this in a Jupyter notebook from ipywidgets import Label c = zx.Circuit(3) display(Label(matrix_to_latex(c.to_matrix())))
- print_matrix(m)
Display a Label() Jupyter widget with a pretty LaTeX representation of the given matrix. Instead of a matrix, can also give a Circuit or Graph.
- Return type:
None
Tikz functionality
Below is listed the content of tikz.py.
Supplies methods to convert ZX-graphs to tikz files. These tikz files are designed to be easily readable by the program Tikzit.
- tikz_to_graph(s, warn_overlap=True, fuse_overlap=True, ignore_nonzx=False, backend=None, ignore_invalid_phases=False, ignore_parse_errors=False, remove_identity_nodes=False)
Converts a tikz diagram into a pyzx Graph. The tikz diagram is assumed to be one generated by Tikzit, and hence should have a nodelayer and a edgelayer..
- Parameters:
s (
str) – a string containing a well-defined Tikz diagram.warn_overlap (
bool) – If True raises a Warning if two vertices have the exact same position.fuse_overlap (
bool) – If True fuses two vertices that have the exact same position. Only has effect if warn_overlap is False.ignore_nonzx (
bool) – If True suppresses most errors about unknown vertex/edge types and labels.backend (
Optional[str]) – Backend of the graph returned.ignore_invalid_phases (
bool) – If True, use default phase (0 for Z/X spiders, 1 for H-boxes and Z-boxes) when an invalid phase label is encountered instead of raising an error.ignore_parse_errors (
bool) – If True, skip nodes and edges that cannot be parsed instead of raising an error. This allows partial import of malformed tikz diagrams.remove_identity_nodes (
bool) – If True, remove ‘none’ style nodes with exactly 2 neighbours, treating them as identity wires.
- Return type:
Warning
- Vertices that might look connected in the output of the tikz are not necessarily connected
at the level of tikz itself, and won’t be treated as such in pyzx.
- tikzit(g, draw_scalar=False)
Opens Tikzit with the graph
gopened as a tikz diagram. For this to work,zx.settings.tikzit_locationmust be pointed towards the Tikzit executable. Even though this function is intended to be used with Tikzit,zx.tikz.tikzit_locationcan point towards any executable that takes a tikz file as an input, such as a text processor.- Return type:
None
- to_tikz(g, draw_scalar=False)
Converts a ZX-graph
gto a string representing a tikz diagram. If the graph has a var_registry with variables, prepend a metadata comment so symbolic variable types survive a TikZ round-trip.- Return type:
str
- to_tikz_sequence(graphs, draw_scalar=False, maxwidth=10)
Given a list of ZX-graphs, outputs a single tikz diagram with the graphs presented in a grid.
maxwidthis the maximum width of the diagram, before a graph is put on a new row in the tikz diagram.- Return type:
str
Heuristics for global optimization
Below listed is the content of genetic.py.
This module contains an implementation of a genetic algorithm. As with simulated annealing, the default goal of this approach is to reduce the 2-qubit count of a fully-simplified ZX-diagram (i.e., of that circuit obtained via extraction) (see demos/LocalSearch).
Mutants are represented as pairs of (ZX-diagram, circuit) to allow for mutation operators that act on either, though by default only the two two congruences defined in congruences.py (that act at the graph-level) are used. Tournament selection is used by default but other options are available. The default fitness function is a weighted gate count defined in scores.py.
- class GeneticOptimizer(actions=[<function rand_pivot>, <function rand_lc>], score=<function default_score>)
Implements a genetic algorithm for evolving a population of (ZX-diagram, circuit) pairs. The primary functionality of this class is defined in the evolve method.
- actions
A list of mutation functions.
- score
A function to calculate the fitness score.
- mutate()
Applies a single mutation to each member of the current population
- update_scores()
Updates the fitness scores of all mutants.
- select(method='tournament')
Selects the next generation of mutants based on the specified method
- Parameters:
method – The selection method to use. Options are: - “tournament”: Randomly selects pairs of mutants and chooses the one with the better score. - “top_half”: Selects the top half of mutants based on their scores and duplicates them. - “top_n”: Selects the top N mutants and replicates them to form the next generation.
- Raises:
RuntimeError – If an unknown selection method is specified.
- evolve(g, n_mutants, n_generations, quiet=True)
The primary functionality of GeneticOptimizer. Given an input ZX-diagram, searches the space of ZX-diagrams generated by the provided action set to minimize the supplied fitness function.
- Parameters:
g – The initial graph.
n_mutants – Number of mutants in the population.
n_generations – Number of generations to evolve.
quiet – If True, suppresses progress output.
- Returns:
The optimized graph.
Below listed is the content of simulated_annealing.py.
- anneal(g, iters=1000, temp=25, cool=0.005, score=<function g_wgc>, cong_ps=[0.5, 0.5], lc_select=<function uniform_weights>, pivot_select=<function uniform_weights>, full_reduce_prob=0.1, reset_prob=0.0, quiet=False)
Performs simulated annealing over ZX-diagram to minimize energy function.
Equivalent ZX-diagrams are generated using congruences from congruences.py. Default goal is to reduce the 2-qubit count of a fully-simplified ZX-diagram.
- Parameters:
g – Initial ZX-diagram to optimize.
iters – Number of iterations to perform (default is 1000).
temp – Initial temperature for annealing (default is 25).
cool – Cooling rate for temperature reduction (default is 0.005).
score – Function to evaluate the energy of a diagram (default is g_wgc).
cong_ps – Probabilities for selecting congruence methods (default is [0.5, 0.5]).
lc_select – Function to select vertices for local complementation (default is uniform_weights).
pivot_select – Function to select edges for pivoting (default is uniform_weights).
full_reduce_prob – Probability of applying full reduction (default is 0.1).
reset_prob – Probability of resetting to the best state (default is 0.0).
quiet – If True, suppresses progress output (default is False).
- Returns:
A tuple containing the best ZX-diagram found and a list of best scores over iterations.
Below listed is the content of congruences.py.
This module contains two congruences (i.e., non-simplification rewrite rules) for exploring the space of equivalent ZX-diagrams. The two congruences defined here are based on the graph-theoretic notions of local complementation and pivoting. The methods lc_cong and pivot_cong take a ZX-diagram and subjects over which to apply the rewrite rule as parameters. The methods apply_rand_lc and apply_rand_pivot select these subjects probabilistically.
- toggle_edge(g, v1, v2)
Utility function that toggles the connectivity between two spiders in a graph-like ZX-diagram.
- Parameters:
g – Graph where the operation is applied.
v1 – First vertex to toggle.
v2 – Second vertex to toggle
- toggle_subset_connectivity(g, vs1, vs2)
Utility function that toggles the connectivity between two subsets of spiders in a graph-like ZX-diagram.
- Parameters:
g – Graph where the operation is applied.
vs1 – First subset of vertices to be toggled.
vs2 – Second subset of vertices to be toggled.
- uniform_weights(g, elts)
Assigns uniform weights to elements for selection. Used as weight function for random local complementation and random pivoting functions.
- Parameters:
g – Graph context for the operation.
elts – Elements to assign weights to.
- Returns:
List of uniform weights.
- unfuse(g, v)
For a Z-spider with a phase and neighbors that are both BOUNDARY and Z, unfuse the phase in the form of a new spider that holds the connectivity to the boundaries. Note that v will maintain its connectivity to any Z spiders (just not boundaries).
- Parameters:
g – Graph where the operation is applied.
v – Vertex to unfuse.
- Returns:
New vertex created during unfusion.
- is_lc_vertex(g, v)
Checks if a spider in a ZX-diagram is a valid subject for local complementation.
- Parameters:
g – Graph where the check is performed.
v – Vertex to check.
- Returns:
True if valid, False otherwise.
- lc_cong(g, v)
Applies local complementation at a provided spider in a ZX-diagram. Assumes v is a Z spider.
- Parameters:
g – Graph where the operation is applied.
v – Vertex to apply local complementation.
- lc_cong2(g, v)
Applies local complementation at a provided spider in a ZX-diagram.
- Parameters:
g – Graph where the operation is applied.
v – Vertex to apply local complementation.
- apply_rand_lc(g, weight_func=<function uniform_weights>)
Applies local complementation to randomly selected spider.
- Parameters:
g – Graph where the operation is applied.
weight_func – Function to determine weights for selection.
- is_pivot_edge(g, e)
Checks if a given edge in a ZX-diagram is a suitable candidate for pivoting
- Parameters:
g – Graph where the check is performed.
e – Edge to check.
- Returns:
True if suitable, False otherwise.
- pivot_cong(g, v1, v2)
Applies pivoting to two connected spiders
- Parameters:
g – Graph where the operation is applied.
v1 – First vertex.
v2 – Second vertex.
- apply_rand_pivot(g, weight_func=<function uniform_weights>)
Applies pivoting to a randomly selected pair of connected spiders.
- Parameters:
g – Graph where the operation is applied.
weight_func – Function to determine weights for selection. Default is uniform weights.
Below listed is the content of scores.py.
This module contains objective functions to guide local search over ZX-diagrams. The wgc method defines a measure of circuit complexity – a weighted gate count where 2-qubit counts incur a higher cost. The g_wgc takes a ZX-diagram as input and optionally applies various optimizations before measuring the complexity of the circuit obtained via extraction.
- wgc(c, two_qb_weight=10)
A measure of the complexity of a given circuit.
- Parameters:
c – Circuit to evaluate.
two_qb_weight – Weight factor for 2-qubit gates, default is 10.
- Returns:
Weighted gate count of the circuit.
- g_wgc(g, two_qb_weight=10, g_simplify=False, c_simplify=True)
A measure of the complexity of the circuit obtained from a a ZX-diagram
- Parameters:
g – ZX-diagram to evaluate.
two_qb_weight – Weight factor for 2-qubit gates, default is 10.
g_simplify – If True, applies full reduction to graph before returning weighted count.
c_simplify – If True, applies basic optimization to circuit before returning weighted count.
- Returns:
Weighted gate count of the extracted circuit.