pytket.transform
pytket.transform#
- class pytket.transform.CXConfigType#
Enum for available configurations for CXs upon decompose phase gadgets
Members:
Snake : linear nearest neighbour CX sequence. Linear depth.
Star : Every CX has same target, linear depth, good for gate cancellation.
Tree : Balanced tree: logarithmic depth, harder to route.
MultiQGate : Support for multi-qubit architectures, decomposing to 3-qubit XXPhase3 gates instead of CXs where possible.
- __init__(self: pytket.transform.CXConfigType, value: int) None #
- property name#
- class pytket.transform.PauliSynthStrat#
Enum for available strategies to synthesise Pauli gadgets
Members:
Individual : Synthesise gadgets individually
Pairwise : Synthesise gadgets using an efficient pairwise strategy from Cowtan et al (https://arxiv.org/abs/1906.01734)
Sets : Synthesise gadgets in commuting sets
- __init__(self: pytket.transform.PauliSynthStrat, value: int) None #
- property name#
- class pytket.transform.Transform#
An in-place transformation of a
Circuit
.- static CnXPairwiseDecomposition() pytket.transform.Transform #
Decompose CnX gates to 2-qubit gates and single qubit gates. For every two CnX gates, reorder their control qubits to improve the chance of gate cancellation.
- static CommuteSQThroughSWAP(*args, **kwargs)#
Overloaded function.
CommuteSQThroughSWAP(avg_node_errors: Dict[pytket.circuit.Node, float]) -> pytket.transform.Transform
Commutes single qubit gates through SWAP gates, leaving them on the physical qubit with best fidelity for given gate type. Assumes the circuit is already mapped onto the architecture.
- Parameters
avg_node_errors – a dict mapping Nodes to average single-qubit gate errors
CommuteSQThroughSWAP(op_node_errors: Dict[pytket.circuit.Node, Dict[pytket.circuit.OpType, float]]) -> pytket.transform.Transform
Commutes single qubit gates through SWAP gates, leaving them on the physical qubit with best fidelity for given gate type. Assumes the circuit is already mapped onto the architecture.
- Parameters
avg_node_errors – a dict of dicts, mapping Nodes to dicts of OpType to single-qubit gate error maps
- static CommuteThroughMultis() pytket.transform.Transform #
Applies a collection of commutation rules to move single qubit operations past multiqubit operations they commute with, towards the front of the circuit.
- static DecomposeBRIDGE() pytket.transform.Transform #
Decomposes all BRIDGE gates into CX gates.
- static DecomposeBoxes() pytket.transform.Transform #
Decomposes all Boxed operations into elementary gates.
- static DecomposeCCX() pytket.transform.Transform #
Decomposes all 3-qubit Toffoli (CCX) gates into Clifford+T gates.
- static DecomposeCXDirected(arc: pytket.architecture.Architecture) pytket.transform.Transform #
Decompose CX gates to H+CX to match the direction of the CXs to edges of the
Architecture
arc. Assumes the circuit already satisfies the connectivity of arc.- Parameters
arc – The architecture for which CXs should be redirected
- static DecomposeControlledRys() pytket.transform.Transform #
Decomposes all arbitrarily-quantum-controlled Rys into CX and Ry gates.
- static DecomposeNPhasedX() pytket.transform.Transform #
Decompose NPhasedX gates into single-qubit PhasedX gates.
- static DecomposeSWAP(circuit: pytket.circuit.Circuit) pytket.transform.Transform #
Decomposes all SWAP gates to provided replacement circuit.
- Parameters
circuit – A circuit that is logically equivalent to a SWAP operation
- static DecomposeSWAPtoCX(arc: pytket.architecture.Architecture = <pytket.architecture.Architecture, nodes=0>) pytket.transform.Transform #
Decomposes all SWAP gates into triples of CX gates. If the SWAP is adjacent to a CX, it will prefer to insert in the direction that allows for gate cancellation. If an
Architecture
is provided, this will prefer to insert the CXs such that fewer need redirecting.- Parameters
arc – Device architecture used to specify a preference for CX direction
- static DecomposeTK2(allow_swaps: bool = True, **kwargs) pytket.transform.Transform #
Decompose each TK2 gate into two-qubit gates.
We currently support CX, ZZMax and ZZPhase.
If one or more gate fidelities are provided, the two-qubit gate type achieving the highest fidelity will be chosen for the decomposition, as measured using squared trace fidelity. If no fidelities are provided, the TK2 gates will be decomposed exactly using CX gates. For equal fidelities, ZZPhase will be prefered over ZZMax and CX if the decomposition results in fewer two-qubit gates.
All TK2 gate parameters must be normalised, i.e. they must satisfy NormalisedTK2Predicate.
Gate fidelities are passed as keyword arguments to perform noise-aware decompositions. We currently support CX_fidelity, ZZMax_fidelity and ZZPhase_fidelity. If provided, the CX and ZZMax fidelities must be given by a single floating point fidelity. The ZZPhase fidelity is given as a lambda float -> float, mapping a ZZPhase angle parameter to its fidelity. These parameters will be used to return the optimal decomposition of each TK2 gate, taking noise into consideration.
Using the allow_swaps=True (default) option, qubits will be swapped when convenient to reduce the two-qubit gate count of the decomposed TK2.
If the TK2 angles are symbolic values, the decomposition will be exact (i.e. not noise-aware). It is not possible in general to obtain optimal decompositions for arbitrary symbolic parameters, so consider substituting for concrete values if possible.
- Parameters
allow_swaps – Whether to allow implicit wire swaps.
- static GlobalisePhasedX(squash: bool = True) pytket.transform.Transform #
Turns all PhasedX and NPhasedX gates into global gates
Replaces any PhasedX gates with global NPhasedX gates. By default, this transform will squash all single-qubit gates to PhasedX and Rz gates before proceeding further. Existing non-global NPhasedX will not be preserved. This is the recommended setting for best performance. If squashing is disabled, each non-global PhasedX gate will be replaced with two global NPhasedX, but any other gates will be left untouched.
- Parameters
squash – Whether to squash the circuit in pre-processing (default: true).
If squash=true (default), the GlobalisePhasedX().apply method will always returns true. For squash=false, apply() will return true if the circuit was changed and false otherwise.
It is not recommended to use this transformation with symbolic expressions, as in certain cases a blow-up in symbolic expression sizes may occur.
- static KAKDecomposition(*args, **kwargs)#
Overloaded function.
KAKDecomposition(target_2qb_gate: pytket.circuit.OpType = <OpType.CX: 42>, cx_fidelity: float = 1.0, allow_swaps: bool = True) -> pytket.transform.Transform
Squash sequences of two-qubit operations into minimal form.
Squash together sequences of single- and two-qubit gates into minimal form. Can decompose to TK2 or CX gates.
Two-qubit operations can always be expressed in a minimal form of maximum three CXs, or as a single TK2 gate (a result also known as the KAK or Cartan decomposition).
It is in general recommended to squash to TK2 gates, and to then use the DecomposeTK2 pass for noise-aware decompositions to other gatesets. For backward compatibility, decompositions to CX are also supported. In this case, cx_fidelity can be provided to perform approximate decompositions to CX gates.
When decomposing to TK2 gates, any sequence of two or more two-qubit gates on the same set of qubits is replaced by a single TK2 gate. When decomposing to CX, the substitution is only performed if it results in a reduction of the number of CX gates, or if at least one of the two-qubit passes is not a CX.
Using the allow_swaps=True (default) option, qubits will be swapped when convenient to further reduce the two-qubit gate count. (only applicable when decomposing to CX gates).
- Parameters
target_2qb_gate – OpType to decompose to. Either TK2 or CX.
cx_fidelity – Estimated CX gate fidelity, used when target_2qb_gate=CX.
allow_swaps – Whether to allow implicit wire swaps.
KAKDecomposition(cx_fidelity: float) -> pytket.transform.Transform
- static NormaliseTK2() pytket.transform.Transform #
Normalises all TK2 gates.
TK2 gates have three angles in the interval [0, 4], but these can always be normalised to be within the so-called Weyl chamber by adding single-qubit gates.
- More precisely, the three angles a, b, c of TK2(a, b, c) are normalised exactly when the two following conditions are met:
numerical values must be in the Weyl chamber, ie 1/2 >= a >= b >= |c|,
symbolic values must come before any numerical value in the array.
After this transform, all TK2 angles will be normalised and the circuit will satisfy NormalisedTK2Predicate.
- static OptimiseCliffords(allow_swaps: bool = True) pytket.transform.Transform #
An optimisation pass that performs a number of rewrite rules for simplifying Clifford gate sequences, similar to Duncan & Fagan (https://arxiv.org/abs/1901.10114). Given a circuit with CXs and any single-qubit gates, produces a circuit with Z, X, S, V, U1, U2, U3, CX gates. This will not preserve CX placement or orientation and may introduce implicit wire swaps.
- Parameters
allow_swaps – dictates whether the rewriting will disregard CX placement or orientation and introduce wire swaps.
- static OptimisePauliGadgets(cx_config: pytket.transform.CXConfigType = CXConfigType.Snake) pytket.transform.Transform #
An optimisation pass that identifies the Pauli gadgets corresponding to any non-Clifford rotations and synthesises them pairwise (see Cowtan, Duncan, Dilkes, Simmons, & Sivarajah https://arxiv.org/abs/1906.01734). Results use TK1, CX gates.
- static OptimisePhaseGadgets(cx_config: pytket.transform.CXConfigType = CXConfigType.Snake) pytket.transform.Transform #
An optimisation pass that starts by identifying subcircuits corresponding to phase gadgets (see Cowtan, Duncan, Dilkes, Simmons, & Sivarajah https://arxiv.org/abs/1906.01734) and resynthesises them in a balanced-tree form, followed by applying OptimisePostRouting. Results use TK1 and CX gates. This will not preserve CX placement or orientation.
- static OptimisePostRouting() pytket.transform.Transform #
Fast optimisation pass, performing basic simplifications. Works on any circuit, giving the result in TK1 and CX gates. If all multi-qubit gates are CXs, then this preserves their placement and orientation, so it is safe to perform after routing.
- static OptimiseStandard() pytket.transform.Transform #
Fast optimisation pass, performing basic simplifications. Works on any circuit, giving the result in TK1 and TK2 gates. Preserves connectivity of circuit.
- static RebaseToCirq() pytket.transform.Transform #
Rebase from any gate set into PhasedX, Rz, CZ.
- static RebaseToCliffordSingles() pytket.transform.Transform #
Replace all single-qubit unitary gates outside the set {Z, X, S, V} that are recognized as Clifford operations with an equivalent sequence of gates from that set.
- static RebaseToProjectQ() pytket.transform.Transform #
Rebase from any gate set into the gate set supported by ProjectQ (Rx, Ry, Rz, X, Y, Z, S, T, V, H, CX, CZ, CRz, SWAP).
- static RebaseToPyZX() pytket.transform.Transform #
Rebase from any gate set into the gate set supported by PyZX (Rx, Rz, X, Z, S, T, H, CX, CZ, SWAP).
- static RebaseToQuil() pytket.transform.Transform #
Rebase from any gate set into Rx, Rz, CZ.
- static RebaseToRzRx() pytket.transform.Transform #
Rebase single qubit gates into Rz, Rx.
- static RebaseToTket() pytket.transform.Transform #
Rebase from any gate set into TK1, CX.
- static ReduceSingles() pytket.transform.Transform #
Reduces each sequence of single-qubit rotations into a single TK1.
- static RemoveRedundancies() pytket.transform.Transform #
Applies a collection of simple optimisations, such as removing gate-inverse pairs, merging similar rotation gates, and removing identity gates. Preserves the gate set and any placement/orientation of multi-qubit gates.
- static SynthesisePauliGraph(synth_strat: pytket.transform.PauliSynthStrat = PauliSynthStrat.Sets, cx_config: pytket.transform.CXConfigType = CXConfigType.Snake) pytket.transform.Transform #
Synthesises Pauli Graphs.
- static ThreeQubitSquash(target_2qb_gate: pytket.circuit.OpType = OpType.CX) pytket.transform.Transform #
Squash three-qubit subcircuits into subcircuits having fewer 2-qubit gates of the target type, when possible. The supported target types are CX (default) and TK2.
- static UCCSynthesis(synth_strat: pytket.transform.PauliSynthStrat = PauliSynthStrat.Sets, cx_config: pytket.transform.CXConfigType = CXConfigType.Snake) pytket.transform.Transform #
Synthesises UCC circuits in the form that Term Sequencing provides them.
- static ZZPhaseToRz() pytket.transform.Transform #
Fixes all ZZPhase gate angles to [-1, 1) half turns.
- __init__(self: pytket.transform.Transform, arg0: Callable[[pytket.circuit.Circuit], bool]) None #
- apply(self: pytket.transform.Transform, circuit: pytket.circuit.Circuit) bool #
Performs the transformation on the circuit in place.
- Parameters
circuit – The circuit to be transformed
- Returns
True if any changes were made, else False
- static repeat(transform: pytket.transform.Transform) pytket.transform.Transform #
Applies a given Transform repeatedly to a circuit until no further changes are made (i.e. it no longer returns
True
).apply()
will returnTrue
if at least one run returnedTrue
.- Parameters
transform – The Transform to be applied repeatedly
- Returns
a new Transform representing the iteration
- static sequence(sequence: List[pytket.transform.Transform]) pytket.transform.Transform #
Composes a list of Transforms together in sequence. The
apply()
method will returnTrue
if ANY of the individual Transforms returnedTrue
.- Parameters
sequence – The list of Transforms to be composed
- Returns
the combined Transform
- static while_repeat(condition: pytket.transform.Transform, body: pytket.transform.Transform) pytket.transform.Transform #
Repeatedly applies the condition Transform until it returns
False
, running body in between each condition application. Intuitively, this corresponds to “WHILE condition DO body”.- Parameters
condition – The Transform to be applied repeatedly as the condition of a loop
body – The Transform to be applied after each successful test of the condition
- Returns
a new Transform representing the iteration
- pytket.transform.separate_classical(circ: pytket.circuit.Circuit) Tuple[pytket.circuit.Circuit, pytket.circuit.Circuit] #
Separate the input circuit into a ‘main’ circuit and a classical ‘post-processing’ circuit, which are equivalent to the original when composed.
- Parameters
circ – circuit to be separated