Twirl

class trueq.Twirl(twirl=None, labels=None, dim=None)

A dictionary-like container mapping qubit labels to the corresponding twirling groups. Twirls are used in benchmarking protocols, e.g. cycle benchmarking (CB) and k-body noise reconstruction (KNR), or in randomized compiling (RC) to generate random twirling gates from specific groups in order to create dressed cycles.

Currently supported twirling groups are: "P" (Pauli), "C" (Clifford), "U" (unitary), or "I" (identity). Warning: "I" is provided as a convenience method for expert users to identify coherent errors and/or crosstalk even though an exponential decay is not expected.

The easiest way to initialize a twirl is to specify a twirling group and the labels on which this group will act. This will result in a “homogenous” twirl, i.e. one that contains a single twirling group acting on all labels:

import trueq as tq

tq.Twirl("C", (0, (1, 2)))
Twirl({(0,): 'C', (1, 2): 'C'}, dim=2)

If you specify a single-qubit twirling group, see SINGLE_QUDIT_GROUPS, any multi-qubit labels passed to the constructor will be automatically broken up into single-qubit labels:

import trueq as tq

twirl1 = tq.Twirl("P", (0, (1, 2)))
twirl2 = tq.Twirl("P", (0, 1, 2))

twirl1, twirl2
(Twirl({(0,): 'P', (1,): 'P', (2,): 'P'}, dim=2),
 Twirl({(0,): 'P', (1,): 'P', (2,): 'P'}, dim=2))

If you want to initialize a twirl with single-qubit Cliffords, regardless whether or not your cycle or labels contain multi-qubit gates, you can use the shorthand "C1" twirling group for convenience:

import trueq as tq

tq.Twirl("C1", (0, (1, 2)))
Twirl({(0,): 'C', (1,): 'C', (2,): 'C'}, dim=2)

The dimension of each subsystem in the twirling group can be specified, otherwise a default value will be used:

import trueq as tq

tq.Twirl("C", (0, (1, 2)), dim=3)

# the default dim can be specified for many trueq objects with set_dim()
tq.settings.set_dim(3)
assert tq.Twirl("C", 0).dim == 3
tq.settings.set_dim(2)

A more explicit way of initializing a twirl is to pass it a dictionary mapping qubit labels to the corresponding twirling groups:

import trueq as tq

tq.Twirl({0: "C", (1, 2): "C"})
Twirl({(0,): 'C', (1, 2): 'C'}, dim=2)

Initializing a twirl with a dictionary allows you to specify “mixed” twirls, i.e. ones that contain multiple twirling groups acting on distinct labels:

import trueq as tq

tq.Twirl({(0, 1): "C", (2, 3): "U", 4: "P"})
Twirl({(0, 1): 'C', (2, 3): 'U', (4,): 'P'}, dim=2)

If you specify a permutation invariant twirling group, e.g. Clifford or U, the subsystem labels will be automatically sorted upon construction:

import trueq as tq

twirl1 = tq.Twirl({(0, 1): "C", (2, 3): "U"})
twirl2 = tq.Twirl({(1, 0): "C", (3, 2): "U"})

twirl1, twirl2
(Twirl({(0, 1): 'C', (2, 3): 'U'}, dim=2),
 Twirl({(0, 1): 'C', (2, 3): 'U'}, dim=2))
Parameters:
  • twirl (dict | str) – Either a dictionary mapping qubit labels to the corresponding twirling groups or a string representing a single twirling group acting on all labels. If twirl and labels are None, then an empty twirl is instantiated.

  • labels (Iterable) – The labels on which the twirling group is acting. Specify this only if twirl is given a str.

  • dim (int | NoneType) – The dimension of the individual subsystems to twirl over, which must be one of SMALL_PRIMES. The default value of None will result in the default dimension obtained from get_dim().

INVARIANT_GROUPS = {'C', 'I', 'P', 'U'}

The set of group strings that are permutation invariant, i.e. the group strings for which qubit label orders do not matter.

SINGLE_QUDIT_GROUPS = {'I', 'P'}

The set of group strings that always result in tensor products of single-qudit groups.

static from_dict(dic)

Returns a Twirl constructed from a dictionary representation.

Parameters:

dic (dict) – A dictionary used to construct a new twirl.

Return type:

Twirl

property dim

The dimension of the individual subsystems to twirl over.

Type:

int

property groups

The set of all twirling groups in this twirl.

Type:

set

property is_mixed

Whether or not this twirl is mixed, i.e. True if there is only one unique twirling group present (length of groups is greater than one) or False otherwise.

Type:

bool

issubset(other)

Checks if this twirl has the same dimension and is a subset of another twirl.

Parameters:

other (Twirl) – Another Twirl instance.

Return type:

bool

items()

Returns the key-value pairs of this twirl.

Return type:

generator

property labels

The sorted union of all system labels in this twirl.

Type:

tuple

labels_intersect(other)

Checks if any system labels in this twirl intersect with the labels of another twirl.

Parameters:

other (Twirl) – Another Twirl instance.

Return type:

bool

pretty(max_chars=50)

Converts this twirl into a pretty string representation.

Parameters:

max_chars (int) – The maximum length of the output.

Return type:

str

property n_sys

The number of qubits in this twirl.

Type:

int

to_dict()

Returns a dictionary representation of this twirl.

Return type:

dict

union(other, enforce_disjoint=True)

Returns a new Twirl instance which is the union of this twirl and another twirl.

Parameters:
  • other (Twirl) – Another Twirl instance.

  • enforce_disjoint (bool) – Whether the labels in the other twirl must have labels completely disjoint from those of this twirl. If disjointness is not enforced, the other twirl must be exactly equal to this twirl on those labels that do overlap.

Return type:

Twirl

Raises:
  • ValueError – If enforce_disjoint=True and there are any overlapping labels between the two twirls.

  • ValueError – If enforce_disjoint=False and there are items in the other twirl not contained in this twirl, but which overlaps the labels of this twirl.

  • ValueError – If the twirls have different dimensions.