pytket.transform¶
Python API module for interfacing with tket c++ implemented functions and modules. Exports class Transform
- enum pytket.transform.PauliSynthStrat(value)¶
Enum for available strategies to synthesise Pauli gadgets
Valid values are as follows:
- Individual = PauliSynthStrat.Individual¶
Synthesise gadgets individually
- Pairwise = PauliSynthStrat.Pairwise¶
Synthesise gadgets using an efficient pairwise strategy from Cowtan et al (https://arxiv.org/abs/1906.01734)
- Sets = PauliSynthStrat.Sets¶
Synthesise gadgets in commuting sets
- Greedy = PauliSynthStrat.Greedy¶
Synthesise gadgets using a greedy algorithm adapted from arxiv.org/abs/2103.08602. This strategy is currently only accepted by TermSequenceBox. For synthesising general circuits try using GreedyPauliSimp.
WARNING: This strategy will not preserve the global phase of the circuit.
- class pytket.transform.Transform¶
An in-place transformation of a
Circuit
.- __init__(self, arg: collections.abc.Callable[[pytket.circuit.Circuit], bool], /) None ¶
- apply(self, 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
- 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
- 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
- sequence(sequence: collections.abc.Sequence[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
- round_angles(n: int, only_zeros: bool = False) pytket.transform.Transform ¶
- Parameters:
only_zeros – if True, only round angles less than \(\pi / 2^{n+1}\) to zero, leave other angles alone (default False)
- 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.
- CommuteSQThroughSWAP(avg_node_errors: collections.abc.Mapping[pytket.unit_id.Node, float]) pytket.transform.Transform ¶
- CommuteSQThroughSWAP(op_node_errors: collections.abc.Mapping[pytket.unit_id.Node, collections.abc.Mapping[pytket.circuit.OpType, float]]) pytket.transform.Transform
Overloaded function.
CommuteSQThroughSWAP(avg_node_errors: collections.abc.Mapping[pytket.unit_id.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: collections.abc.Mapping[pytket.unit_id.Node, collections.abc.Mapping[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
- 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.
- DecomposeBRIDGE() pytket.transform.Transform ¶
Decomposes all BRIDGE gates into CX gates.
- DecomposeBoxes(excluded_types: collections.abc.Set[pytket.circuit.OpType] = set(), excluded_opgroups: collections.abc.Set[str] = set(), included_types: collections.abc.Set[pytket.circuit.OpType] | None = None, included_opgroups: collections.abc.Set[str] | None = None) pytket.transform.Transform ¶
Recursively replaces all boxes by their decomposition into circuits.
Arguments specify ways to filter which boxes are decomposed. A box must satisfy ALL filters in order to be decomposed (i.e. be in the inclusive sets and not in the exclusive sets).
- Parameters:
excluded_types – box
OpType
s excluded from decompositionexcluded_opgroups – opgroups excluded from decomposition
included_types – optional, only decompose these box
OpType
sincluded_opgroups – optional, only decompose these opgroups
- DecomposeCCX() pytket.transform.Transform ¶
Decomposes all 3-qubit Toffoli (CCX) gates into Clifford+T gates.
- 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
- DecomposeControlledRys() pytket.transform.Transform ¶
Decomposes all arbitrarily-quantum-controlled Rys into CX and Ry gates.
- DecomposeNPhasedX() pytket.transform.Transform ¶
Decompose NPhasedX gates into single-qubit PhasedX gates.
- 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
- DecomposeSWAPtoCX(arc: pytket.architecture.Architecture) 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
- 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, or by a single float. 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.
- GreedyPauliSimp(discount_rate: float = 0.7, depth_weight: float = 0.3, max_tqe_candidates: int = 500, max_lookahead: int = 500, seed: int = 0, allow_zzphase: bool = False, thread_timeout: int = 100, trials: int = 1) pytket.transform.Transform ¶
Convert a circuit into a graph of Pauli gadgets to account for commutation and phase folding, and resynthesises them using a greedy algorithm adapted from arxiv.org/abs/2103.08602. The method for synthesising the final Clifford operator is adapted from arxiv.org/abs/2305.10966.
WARNING: This transformation will not preserve the global phase of the circuit.
- Parameters:
discount_rate – Rate used to discount the cost impact from gadgets that are further away. Default to 0.7.
depth_weight – Degree of depth optimisation. Default to 0.3.
max_tqe_candidates – Maximum number of 2-qubit Clifford gate candidates to evaluate at each step. Default to 500.
max_lookahead – Maximum lookahead when evaluating each Clifford gate candidate. Default to 500.
seed – Unsigned integer seed used for sampling candidates and tie breaking. Default to 0.
allow_zzphase – If set to True, allows the algorithm to implement 2-qubit rotations using ZZPhase gates when deemed optimal. Defaults to False.
thread_timeout – Sets maximum out of time spent finding a single solution in one thread.
trials – Sets maximum number of found solutions. The smallest circuit is returned, prioritising the number of 2qb-gates, then the number of gates, then the depth.
- Returns:
a pass to perform the simplification
- KAKDecomposition(target_2qb_gate: pytket.circuit.OpType = OpType.CX, cx_fidelity: float = 1.0, allow_swaps: bool = True) pytket.transform.Transform ¶
- KAKDecomposition(cx_fidelity: float) pytket.transform.Transform
Overloaded function.
KAKDecomposition(target_2qb_gate: pytket.circuit.OpType = OpType.CX, 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
- 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.
- OptimiseCliffords(allow_swaps: bool = True, target_2qb_gate: pytket.circuit.OpType = OpType.CX) pytket.transform.Transform ¶
An optimisation pass that applies a number of rewrite rules for simplifying Clifford gate sequences, similar to Duncan & Fagan (https://arxiv.org/abs/1901.10114). Produces a circuit comprising TK1 gates and the two-qubit gate specified as the target.
- Parameters:
allow_swaps – whether the rewriting may introduce implicit wire swaps
target_2qb_gate – target two-qubit gate (either CX or TK2)
- OptimisePauliGadgets(cx_config: pytket.circuit.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.
- OptimisePhaseGadgets(cx_config: pytket.circuit.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.
- 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.
- 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.
- PushCliffordsThroughMeasures() pytket.transform.Transform ¶
Derives a new set of end-of-Circuit measurement operators by acting on end-of-Circuit measurements with a Clifford subcircuit. The new set of measurement operators is necessarily commuting and is implemented by adding a new mutual diagonalisation Clifford subcirciuit to the end of the Circuit and implementing the remaining diagonal measurement operators by measuring and permuting the output.
- RebaseToCirq() pytket.transform.Transform ¶
Rebase from any gate set into PhasedX, Rz, CZ.
- RebaseToCliffordSingles(tk2_to_cx: bool = True) 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.
- Parameters:
tk2_to_cx – whether to rebase TK2 gates to CX and standard Cliffords
- RebaseToIonQ() pytket.transform.Transform ¶
Rebase from any gate set into the gate set supported by IonQ (GPI, GPI2, AAMS).
- 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).
- 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).
- RebaseToQuil() pytket.transform.Transform ¶
Rebase from any gate set into Rx, Rz, CZ.
- RebaseToRzRx() pytket.transform.Transform ¶
Rebase single qubit gates into Rz, Rx.
- RebaseToTket() pytket.transform.Transform ¶
Rebase from any gate set into TK1, CX.
- ReduceSingles() pytket.transform.Transform ¶
Reduces each sequence of single-qubit rotations into a single TK1.
- 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.
- SynthesisePauliGraph(synth_strat: pytket.transform.PauliSynthStrat = PauliSynthStrat.Sets, cx_config: pytket.circuit.CXConfigType = CXConfigType.Snake) pytket.transform.Transform ¶
Synthesises Pauli Graphs.
- 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.
- UCCSynthesis(synth_strat: pytket.transform.PauliSynthStrat = PauliSynthStrat.Sets, cx_config: pytket.circuit.CXConfigType = CXConfigType.Snake) pytket.transform.Transform ¶
Synthesises UCC circuits in the form that Term Sequencing provides them.
- ZZPhaseToRz() pytket.transform.Transform ¶
Fixes all ZZPhase gate angles to [-1, 1) half turns.
- 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