pytket.transform

class pytket._tket.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

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.

__init__(self: pytket._tket.transform.PauliSynthStrat, value: int) None
property name
class pytket._tket.transform.Transform

An in-place transformation of a Circuit.

static CnXPairwiseDecomposition() pytket._tket.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.

  1. CommuteSQThroughSWAP(avg_node_errors: dict[pytket._tket.unit_id.Node, float]) -> pytket._tket.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

  1. CommuteSQThroughSWAP(op_node_errors: dict[pytket._tket.unit_id.Node, dict[pytket._tket.circuit.OpType, float]]) -> pytket._tket.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._tket.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._tket.transform.Transform

Decomposes all BRIDGE gates into CX gates.

static DecomposeBoxes(excluded_types: set[pytket._tket.circuit.OpType] = set(), excluded_opgroups: set[str] = set()) pytket._tket.transform.Transform

Recursively replaces all boxes by their decomposition into circuits.

Parameters:
  • excluded_types – box `OpType`s excluded from decomposition

  • excluded_opgroups – opgroups excluded from decomposition

static DecomposeCCX() pytket._tket.transform.Transform

Decomposes all 3-qubit Toffoli (CCX) gates into Clifford+T gates.

static DecomposeCXDirected(arc: pytket._tket.architecture.Architecture) pytket._tket.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._tket.transform.Transform

Decomposes all arbitrarily-quantum-controlled Rys into CX and Ry gates.

static DecomposeNPhasedX() pytket._tket.transform.Transform

Decompose NPhasedX gates into single-qubit PhasedX gates.

static DecomposeSWAP(circuit: pytket._tket.circuit.Circuit) pytket._tket.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._tket.architecture.Architecture) pytket._tket.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._tket.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.

static GlobalisePhasedX(squash: bool = True) pytket._tket.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 transform’s apply method will always return 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 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) pytket._tket.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.

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.

Returns:

a pass to perform the simplification

static KAKDecomposition(*args, **kwargs)

Overloaded function.

  1. KAKDecomposition(target_2qb_gate: pytket._tket.circuit.OpType = <OpType.CX: 45>, cx_fidelity: float = 1.0, allow_swaps: bool = True) -> pytket._tket.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.

  1. KAKDecomposition(cx_fidelity: float) -> pytket._tket.transform.Transform

static NormaliseTK2() pytket._tket.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._tket.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._tket.circuit.CXConfigType = <CXConfigType.Snake: 0>) pytket._tket.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._tket.circuit.CXConfigType = <CXConfigType.Snake: 0>) pytket._tket.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._tket.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._tket.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 PushCliffordsThroughMeasures() pytket._tket.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.

static RebaseToCirq() pytket._tket.transform.Transform

Rebase from any gate set into PhasedX, Rz, CZ.

static RebaseToCliffordSingles() pytket._tket.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 RebaseToIonQ() pytket._tket.transform.Transform

Rebase from any gate set into the gate set supported by IonQ (GPI, GPI2, AAMS).

static RebaseToProjectQ() pytket._tket.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._tket.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._tket.transform.Transform

Rebase from any gate set into Rx, Rz, CZ.

static RebaseToRzRx() pytket._tket.transform.Transform

Rebase single qubit gates into Rz, Rx.

static RebaseToTket() pytket._tket.transform.Transform

Rebase from any gate set into TK1, CX.

static ReduceSingles() pytket._tket.transform.Transform

Reduces each sequence of single-qubit rotations into a single TK1.

static RemoveRedundancies() pytket._tket.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._tket.transform.PauliSynthStrat = <PauliSynthStrat.Sets: 2>, cx_config: pytket._tket.circuit.CXConfigType = <CXConfigType.Snake: 0>) pytket._tket.transform.Transform

Synthesises Pauli Graphs.

static ThreeQubitSquash(target_2qb_gate: pytket._tket.circuit.OpType = <OpType.CX: 45>) pytket._tket.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._tket.transform.PauliSynthStrat = <PauliSynthStrat.Sets: 2>, cx_config: pytket._tket.circuit.CXConfigType = <CXConfigType.Snake: 0>) pytket._tket.transform.Transform

Synthesises UCC circuits in the form that Term Sequencing provides them.

static ZZPhaseToRz() pytket._tket.transform.Transform

Fixes all ZZPhase gate angles to [-1, 1) half turns.

__init__(self: pytket._tket.transform.Transform, arg0: Callable[[pytket._tket.circuit.Circuit], bool]) None
apply(self: pytket._tket.transform.Transform, circuit: pytket._tket.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._tket.transform.Transform) pytket._tket.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 return True if at least one run returned True.

Parameters:

transform – The Transform to be applied repeatedly

Returns:

a new Transform representing the iteration

static round_angles(n: int, only_zeros: bool = False) pytket._tket.transform.Transform
Parameters:

only_zeros – if True, only round angles less than \(\pi / 2^{n+1}\) to zero, leave other angles alone (default False)

static sequence(sequence: Sequence[pytket._tket.transform.Transform]) pytket._tket.transform.Transform

Composes a list of Transforms together in sequence. The apply() method will return True if ANY of the individual Transforms returned True.

Parameters:

sequence – The list of Transforms to be composed

Returns:

the combined Transform

static while_repeat(condition: pytket._tket.transform.Transform, body: pytket._tket.transform.Transform) pytket._tket.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._tket.transform.separate_classical(circ: pytket._tket.circuit.Circuit) tuple[pytket._tket.circuit.Circuit, pytket._tket.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