Circuits

trueq.Circuit

Represents a quantum Circuit to be performed on a device, along with relevant additional information about the circuit.

trueq.CircuitCollection

Represents a collection of instances of Circuit.

Circuit

class trueq.Circuit(cycles=None, key=None, results=None)

Represents a quantum Circuit to be performed on a device, along with relevant additional information about the circuit.

Note

All True-Q™ circuit generation and analysis methods assume that circuits are run by initializing systems independently in the ground state, applying the parallelized gates (referred to as cycles) obtained by iterating over the circuit, measuring the systems in the computational basis, and populating results with the results.

Specifically, all local gates required to rotate preparations and measurements are already included in cycles.

A circuit is stored as a list of Cycles. It also has private attributes for ease of use with randomized compiling and standard quantum algorithms.

Parameters
  • cycles (list) – Cycles of the circuit. This is a list of the form, for example, [{(1,): tq.Gate.x, (0, 2): tq.Gate.cz}, ...].

  • key (Key) – A hashable object used to group similar circuits for analysis. For example, Key(protocol=SRB,n_random_cycles=10).

  • results (Results | dict) – Results to add to the circuit on construction, see also Circuit.results.

measure_all()

Add a cycle of measurements at the end of the current circuit.

This adds trueq.Meas onto each label currently in the circuit.

Returns

This instance.

Return type

Circuit

property dim

The dimension of each subsystem, e.g. 2 if this circuit acts on qubits. This property is inherited from its cycles. If no cycles specify a dimension, then the dimension is unknown and this value is equal to None.

Type

int | None

property key

Metadata related to this circuit. This is used in analysis methods of protocols, and for organizing circuits within CircuitCollections.

Type

Key

property n_sys

The number of distinct systems participating in this Circuit.

Type

int

property labels

The sorted union of all system labels acted on by gates in this Circuit.

Type

tuple

property n_cycles

The number of Cycles in this Circuit.

Type

int

property cycles

A list of Cycles that represent the Circuit.

Type

list

property results

Results from running this Circuit on a quantum device; a dictionary whose keys are bitstrings, and whose values are total observations of corresponding bitstrings.

Bitstrings are python strings containing \(0\) and \(1\), e.g., '0110', see Results.

The initial value of this property is {}, which implies that has_results is False.

Note that these values will internally be normalized to their sum, and not to \(1\) —for example, with respect to all of our analysis routines, the following results are identical:

{'0': 123, '1': 4}
{'0': 1230, '1': 40}
{'0': 12300, '1': 400}
Type

dict

property has_results

Whether the results property has been set.

Type

bool

append(cycles_or_circuit)

Appends one or more Cycles or another Circuit to this circuit. If another circuit is being appended, its Keys and Resultss cannot conflict with this circuit’s keys or results. Dictionaries are automatically converted to cycles.

Parameters

cycle_circuit – The cycle, list of cycles, or circuit to append.

property meas_locs

Returns a list of the locations of all measurements in the Circuit.

The ordering of this list is the same as the expected bit-string order in the circuit’s Resultss.

The order of measurements is decided first by the index of the cycle, e.g.: measurements placed in the first cycle of a circuit are returned before measurements in later cycles. Then the order inside of a cycle is decided by the label on which the measurement is placed, e.g.: measurements placed on label (0,) comes before label (5,)

The returned list contains tuples, where the first entry of tuple is the cycle index, and the second entry of the tuple is the label the measurement is on.

import trueq as tq

# (Cycle 0: measure qubit 0), (Cycle 1: measure qubits 1 and 5)
circ = tq.Circuit([{(0,): tq.Meas()}, {(5,): tq.Meas(), (1,): tq.Meas()}])

# meas_locs returns locations of measurements in the form (cycle, qubit)
circ.meas_locs
[(0, 0), (1, 1), (1, 5)]
Return type

list of tuple

property n_meas

The total number of measurement operations in the circuit.

Type

int

draw(filename=None)

Draw the circuit as an SVG. If a filename is provided, write the svg to the file.

import trueq as tq

# Make an example SRB circuit
circuit = tq.make_srb([[0, 5], [1, 2], 3, 4], [3], 1)[0]
circuit.draw()
0 1 2 3 4 5 Key: twirl: (('C', 3), ('C', 4), ('C', 0, 5), ('C', 1, 2)) protocol: SRB compiled_pauli: ZIIZXY n_random_cycles: 3 Labels: (0, 5) Name: Gate(IY, XY, ...) Locally Equivalent: iSWAP Generators: IY: 138.56 ZX: -138.56 ZZ: -138.56 XY: 90.00 -0.35 0.35j -0.35 0.35j -0.35 0.35j 0.35 -0.35j 0.35 0.35j -0.35 -0.35j -0.35 -0.35j -0.35 -0.35j -0.35 -0.35j 0.35 0.35j -0.35 -0.35j -0.35 -0.35j -0.35 0.35j -0.35 0.35j 0.35 -0.35j -0.35 0.35j Labels: (1, 2) Name: Gate(IX, IY, ...) Locally Equivalent: iSWAP Generators: XZ: 90.00 IY: -90.00 IX: 90.00 ZZ: 90.00 ZY: -45.00 XY: 45.00 XX: -45.00 ... -0.35 -0.35j 0.35 -0.35j 0.35 -0.35j 0.35 0.35j -0.35 -0.35j -0.35 0.35j -0.35 0.35j 0.35 0.35j 0.35 -0.35j -0.35 -0.35j 0.35 0.35j 0.35 -0.35j 0.35 -0.35j 0.35 0.35j -0.35 -0.35j 0.35 -0.35j Labels: (3,) Name: Gate.cliff17 Aliases: Gate.cliff17 Generators: Z: 69.28 X: -69.28 Y: -69.28 0.50 -0.50j 0.50 0.50j -0.50 0.50j 0.50 0.50j 17 Labels: (4,) Name: Gate.s Aliases: Gate.s Gate.cliff9 Generators: Z: 90.00 0.71 -0.71j 0.71 0.71j S Imm Labels: (0, 5) Name: Gate(IX, IY, ...) Locally Equivalent: iSWAP Generators: XI: 73.48 YZ: -73.48 ZX: 73.48 ZY: -73.48 IX: -73.48 IY: -73.48 YX: -34.64 ... 0.71 0.71 -0.71 -0.71 -0.71j 0.71j -0.71j 0.71j Labels: (1, 2) Name: Gate(IX, IY, ...) Locally Equivalent: CNOT Generators: IZ: 135.00 ZZ: 135.00 ZI: -90.00 ZX: -63.64 IX: 63.64 ZY: 63.64 IY: -63.64 -1.00j -1.00 -1.00j -1.00 Labels: (3,) Name: Gate.cliff18 Aliases: Gate.cliff18 Generators: X: -69.28 Z: -69.28 Y: 69.28 0.50 0.50j -0.50 0.50j 0.50 0.50j 0.50 -0.50j 18 Labels: (4,) Name: Gate.cliff20 Aliases: Gate.cliff20 Generators: X: 69.28 Z: -69.28 Y: -69.28 0.50 0.50j 0.50 -0.50j -0.50 -0.50j 0.50 -0.50j 20 Imm Labels: (0, 5) Name: Gate(IX) Locally Equivalent: U(2)⊗U(2) Generators: IX: 180.00 1.00 1.00 1.00 1.00 Labels: (1, 2) Name: Gate(IX, IY, ...) Locally Equivalent: iSWAP Generators: IX: -90.00 XI: -90.00 XX: 90.00 ZI: -69.28 XY: -69.28 ZX: -69.28 ZZ: -69.28 ... -0.71 0.71j -0.71 0.71j -0.71j 0.71 -0.71j 0.71 Labels: (3,) Name: Gate.cliff11 Aliases: Gate.cliff11 Generators: X: 127.28 Y: -127.28 0.71 -0.71j -0.71 -0.71j 11 Labels: (4,) Name: Gate.cliff5 Aliases: Gate.cliff5 Generators: X: 90.00 0.71 -0.71j -0.71j 0.71 5 Imm Labels: (0, 5) Name: Gate(IX, IY, ...) Locally Equivalent: iSWAP Generators: ZY: -80.50 ZX: -80.50 XI: -80.50 YI: 80.50 ZZ: 80.50 IY: 49.55 YZ: -49.55 ... 0.50 -0.50j -0.50 0.50j -0.50 0.50j -0.50 0.50j -0.50 -0.50j -0.50 -0.50j 0.50 0.50j -0.50 -0.50j Labels: (1, 2) Name: Gate(IX, XI, ...) Locally Equivalent: CNOT Generators: ZY: 99.10 ZZ: -99.10 YY: -99.10 XZ: 99.10 ZI: 99.10 XI: 23.39 YZ: 23.39 ... -0.50 -0.50j 0.50 -0.50j 0.50 -0.50j -0.50 -0.50j 0.50 -0.50j 0.50 0.50j -0.50 -0.50j -0.50 0.50j Labels: (3,) Name: Gate.cliff13 Aliases: Gate.cliff13 Generators: Z: 127.28 X: -127.28 0.71 -0.71 -0.71 -0.71 13 Labels: (4,) Name: Gate.cliff21 Aliases: Gate.cliff21 Generators: X: 69.28 Y: -69.28 Z: 69.28 0.50 0.50j 0.50 0.50j 0.50 -0.50j -0.50 0.50j 21 Imm Labels: (0,) Name: Meas() M Labels: (1,) Name: Meas() M Labels: (2,) Name: Meas() M Labels: (3,) Name: Meas() M Labels: (4,) Name: Meas() M Labels: (5,) Name: Meas() M
Parameters

filename (str) – A filename to write the SVG output to.

to_dict(include_cycles=True)

Returns a dictionary representation of a Circuit object. This dictionary representation contains only base Python classes.

Parameters

include_cycles (bool) – Whether to include the cycles in the dictionary representation.

Return type

dict

static from_dict(dic)

Returns a Circuit constructed from a dictionary representation.

Return type

Circuit

to_cirq(metadata=None, config='ZXZ', device=None, join_meas=True)

Converts a Circuit into a cirq.Circuit.

import cirq
import trueq as tq

circ = tq.Circuit([{(0, 1): tq.Gate.cx}])

ext_circ = tq.interface.cirq.from_trueq_circ(circ)

ext_circ.to_trueq().draw()
0 1 Key: Imm Labels: (0, 1) Name: Gate.cx Aliases: Gate.cx Gate.cnot Locally Equivalent: CNOT Generators: ZI: 90.00 ZX: -90.00 IX: 90.00 1.00 1.00 1.00 1.00 CX CX

Note

Arbitrary single-qubit operations are decomposed using the ZXZ QubitMode by default.

If an SU(4) gate is provided which is not directly equivalent to a single gate in get_priority_list(), it is decomposed using the Compiler().

Parameters
  • circuit (Circuit) – The True-Q™ circuit to be converted into a Cirq circuit.

  • metadata (CirqMetadata) – Metadata required to accurately reproduce the original Cirq circuit. If this is not provided, measurements are added at the end of the circuit.

  • config (Config | str) – If a Config which contains gates which are directly decomposable into Cirq native gates is provided, then conversion will take place into gates specified by that config. Alternatively, config accepts text strings and uses them as the mode argument for get_config.

  • device (None or cirq.Device) – A cirq.Device, if no device is provided, an unconstrained device with cirq.GridQubit is assumed.

  • join_meas (bool) – This determines if Meas are joined into single cirq.meas() objects, or single meas object in parallel in the given moment/cycle.

Return type

cirq.Circuit

to_pyquil(metadata=None, config='ZXZ')

Converts a Circuit into a pyquil.Program.

import pyquil
import trueq as tq

circ = tq.Circuit([{(0, 1): tq.Gate.cx}])

ext_circ = tq.interface.pyquil.from_trueq_circ(circ)

ext_circ.to_trueq().draw()
0 1 Key: Imm Labels: (0, 1) Name: PyQuil.CNOT Aliases: Gate.cx Gate.cnot Generators: ZI: 90.00 ZX: -90.00 IX: 90.00 0.71 -0.71j 0.71 -0.71j 0.71 -0.71j 0.71 -0.71j CX CX

Note

Measurements are always assumed to be at the end of a circuit.

Arbitrary single-qubit operations are decomposed using the ZXZ QubitMode by default.

If an SU(4) gate is provided which is not directly equivalent to a single gate in get_priority_list(), it is decomposed using the Compiler().

Parameters
  • circ (Circuit) – The True-Q™ circuit to be converted into a PyQuil Program.

  • metadata (PyquilMetadata) – Metadata required to accurately reproduce the original PyQuil program. By default, measurements are placed at the end of the circuit on all qubits, reading out to a classical register called ‘ro’.

  • config (Config | str) – If a Config which contains gates which are directly decomposable into PyQuil native gates is provided, then conversion will take place into gates specified by that config. Alternatively, config accepts text strings and uses them as the mode argument for get_config.

Return type

pyquil.Program

to_qasm(custom_header=None, include_auto_header=True)

Converts a Circuit into a QASM 2.0 text string.

Circuits converted to QASM will use the gate definitions found in the get_config(). These definitions will by default be included at the top of the output QASM file (this behavior can be disabled by setting include_auto_header=False). Additional lines in the header can be included by providing a list of strings to custom_header, which will be appended as new lines at the top of the file.

Note

Barriers are added between every Cycle in addition to every location where a Block is present.

Parameters
  • circuit (Circuit) – The circuit to be converted to QASM.

  • custom_header (list) – A list of strings which will be put at the top of the file, with each string being placed on a seperate line.

  • include_auto_header (bool) – If the get_config is not the qelib1 config, then QASM requires all gates present to be written as combinations of U3 and CNOT gates (see the docs for QASM, for more details), this flag determines if these definitions should be included in the header of the QASM file.

Return type

str

to_qiskit(metadata=None, config=None)

Converts a Circuit into a qiskit.QuantumCircuit.

import qiskit
import trueq as tq

circ = tq.Circuit([{(0, 1): tq.Gate.cx}])

ext_circ = tq.interface.qiskit.from_trueq_circ(circ)

ext_circ.to_trueq().draw()
0 1 Key: Imm Labels: (0, 1) Name: Gate.cx Aliases: Gate.cx Gate.cnot Locally Equivalent: CNOT Generators: ZI: 90.00 ZX: -90.00 IX: 90.00 1.00 1.00 1.00 1.00 CX CX

Note

Single qubit gates are reduced as much as possible up to numerical precision, e.g., some U3 gates become U2 or U1 gates.

Blocking operations are added at the end of every Cycle to ensure that the physical noise process is consistent.

Parameters
  • circuit (Circuit) – The True-Q™ circuit to be converted into a Qiskit QuantumCircuit

  • metadata (QiskitMetadata) – Metadata required to accurately reproduce the original Qiskit QuantumCircuit. By default, the returned QuantumCircuit will have one quantum register and one classical register and have measurements at the end of the circuit mapping each quantum bit to each classical bit.

  • config (Config) – A given config object which contains gates which can be performed by qiskit, but also has hardware restrictions. For example, a Config object can represent a CNOT gate that is restricted to specific sets of qubits, and a CNOT gate is a known native gate in Qiskit. Providing this config means that not only will the circuit be converted into Qiskit representation, but also that it will satisfy hardware restrictions. If no config is provided, all possible qiskit gates are used in the compilation.

Returns

A Qiskit circuit representation of the Circuit

Return type

qiskit.QuantumCircuit

Circuit Collection

class trueq.CircuitCollection(circuits=None)

Represents a collection of instances of Circuit.

Parameters

circuits (list) – A list of Circuits to initially populate this collection with, or None.

property n_circuits

The number of Circuits in this collection.

Type

int

property n_sys

The number of systems of all Circuits in this collection.

Type

int

property labels

Which systems are targeted by this Circuit.

Type

tuple

append(circuit)

Appends one or more Circuits to the collection.

Parameters

circuit (Circuit | Iterable) – An instance of Circuit, or any iterable of Circuit objects (including another CircuitCollection).

property n_results

The number of experimental Circuits that have been populated with results, an integer between \(0\) and n_circuits.

Type

int

property has_no_results

Whether none of the experimental Circuit's have been populated with data.

Type

bool

property has_some_results

Whether at least one of the experimental Circuits have been populated with data.

Type

bool

property has_all_results

Whether all of the experimental Circuits have been populated with data.

Type

bool

save(filename, overwrite=False, include_cycles=True)

Saves this collection to disk in a binary format, including all results. This collection can be reinstantiated at a later time using trueq.utils.load().

import trueq as tq
circuits = tq.make_srb([0], [4, 20])
tq.Simulator().add_depolarizing(0.01).run(circuits)

# save into a temporary folder for this example
with tq.utils.temp_folder():
    # the extension .tq is arbitrary but recommended
    circuits.save("my_circuits1.tq")

    # save discarding all cycle/gate information for a smaller file size
    circuits.save("my_circuits2.tq", include_cycles=False)
Parameters
  • filename (str) – A filename to save the circuit collection as.

  • overwrite (bool) – Any existing file will be overwritten if this is True, else saving will raise FileExistsError

  • include_cycles (bool) – Whether the cycle information in each circuit should be retained. If false, then all circuits will have their cycles stripped in the saved version to save space. Results and other information will be saved so that analysis and plotting will work on a reinstantiated copy.

fit(labels=None)

Fits all applicable data found and returns all estimates as an EstimateCollection.

Fits for a subset of data can be obtained by calling fit() on a reduced CircuitCollection by using subset():

import trueq as tq

# make a circuit collection of SRB and XRB circuits
circuits = tq.make_srb([0], [2,32])
circuits.append(tq.make_xrb([0], [2,32]))

# run the circuits on a noisy simulator
tq.Simulator().add_depolarizing(0.01).run(circuits)

# fit the results for just SRB
circuits.subset(protocol="SRB").fit()
SRB
Streamlined Randomized Benchmarking
Cliffords
(0,)
Key:
  • labels: (0,)
  • protocol: SRB
  • twirl: (('C', 0),)
${e}_{P}$
The probability of an error acting on the targeted systems during a random gate.
8.4e-03 (5.9e-04)
0.008439832044981777, 0.0005914849087839458
${p}$
Decay parameter of the exponential decay $Ap^m$.
9.9e-01 (7.9e-04)
0.988746890606691, 0.0007886465450452609
${A}$
SPAM parameter of the exponential decay $Ap^m$.
9.9e-01 (7.5e-03)
0.9901593567915155, 0.007521905309559784

Many protocols have well defined fits for a strict subset of qubits that the protocol was invoked on. For example, if cycle benchmarking acts on a 10 qubit cycle, fitting 6 of these ten qubits returns a valid estimate of the infidelity on those qubits in the context of the entire cycle. The optional argument labels allows you to customize such subsets of labels.

Parameters

labels (None | Iterable) – A list of lists of qubit labels; fits will be produced on each subset. For convenience, isolated labels are treated as a list of length 1, for example, labels = [[0], [1], [2]] is equivalent to labels = [0, 1, 2]. If no labels are provided (None), they are generated automatically on a protocol-by-protocol basis.

Return type

EstimateCollection

plot = PlottingSuite(<8 plotters>)

An object that stores all plotting functions deemed relevant to this CircuitCollection. If one of these functions is called, the data from this circuit collection is analyzed and used.

Note

If there is a plotting function that you expected to be present but is not, double check the circuit’s Keys to see which types of circuits are present, and also verify that circuits relevant to the plot you want have results entered.

Type

PlottingSuite

batch(max_size, extra_circuits=None, sequencer=None)

Divides the circuits in this collection into a series of batches that are limited in size. This is useful if, for example, your hardware has a finite amount of memory to store circuits with. For this example, we will use True-Q™’s built-in simulator in place of a physical device. In practice, this can be used to batch jobs for submission to hardware, using the modifications suggested in the comments below.

import trueq as tq
import trueq.sequencer as tqs

# make a bunch of circuits
circuits = tq.make_crosstalk_diagnostics([0, 1, 2], [4, 70])

# initialize a simulator to stand in for a physical device
my_device = tq.Simulator()

# Split collection into batches such that there are no more than 80
# circuits in each batch. For a hardware device, the method run() should be
# replaced with a method which runs circuits on the device and returns the
# results for each member of the batch, and the content of this for loop
# would become batch.results = my_device.run(batch) to set the results
# parameter of batch to the returned results.
for batch in circuits.batch(80):
    my_device.run(batch)

# we can also set batch size by total number of cycles or gates
circuits.batch(tqs.NCycles(1000))
circuits.batch(tqs.NGates(1e6))

# We can riffle the circuits by sequence length. Running on a device, we
# again replace the contents of this for loop with
# batch.results = my_device.run(batch) to save the results to the circuit
for batch in circuits.batch(80, sequencer=tqs.RIFFLER):
    my_device.run(batch, overwrite=True)

The batcher also supports automatically adding a fixed set of circuits to each batch. For example, we can add readout calibration circuits to each batch:

import trueq as tq

circuits = tq.make_crosstalk_diagnostics([0, 1, 2], [4, 70])
ro_circuits = tq.make_rcal([0, 1, 2])

# Initialize a simulator to stand in for a physical device. In practice, all
# instances of my_device.run(batch) should be replaced with
# batch.results = my_device.run_on_device(batch) for a device called
# my_device with a function run_on_device() which runs circuits on hardware
# and returns the results.
my_device = tq.Simulator()

for batch in circuits.batch(80, extra_circuits=ro_circuits):
    my_device.run(batch)
Parameters
  • max_size (int | list | CircuitRuler) – The maximum number of circuits per batch, or any CircuitRuler such as NCycles, py:class:~trueq.sequencer.Gates, or py:class:~trueq.sequencer.TotalTime. You can also specify a list of CircuitRulers; every batch will not surpass any of the rulers’ limits.

  • extra_circuits (CircuitCollection) – A list of circuits to be placed at the start of every batch. Copies are made of these circuits in every batch.

  • sequencer (CircuitSequencer) – Specifies how the circuits should be ordered when batching. This is useful, for example, if you want to riffle long circuits with short sequences within a batch, so that all of your long circuits don’t end up in the same batch, see trueq.sequencer.RIFFLER. If no sequencer is given, the existing circuit collection order is used.

keys(**filter)

Returns a KeySet of unique keys in this CircuitCollection that match the given name/values present in the filter.

Parameters

filter – Key/value pairs to be used as a filter.

Return type

set

similar_keys(*names, invert=False, **filter)

Returns a generator over disjoint KeySets, where all of the keys in each set have equal values for all names appearing in the given names, and have any specific values specified in filter.

import trueq as tq

circuits = tq.make_srb([0], [4, 10, 50], 30)

print("Grouping keys based on matching 'protocol': ")
for keys in circuits.similar_keys("protocol"):
    print(keys)

print("\nGrouping keys based on 'protocol' and 'n_random_cycles': ")
for keys in circuits.similar_keys("protocol", "n_random_cycles"):
    print(keys)
Grouping keys based on matching 'protocol': 
KeySet(
	Key(compiled_pauli='Z', n_random_cycles=4, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='Y', n_random_cycles=50, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='I', n_random_cycles=50, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='I', n_random_cycles=4, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='X', n_random_cycles=10, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='I', n_random_cycles=10, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='Z', n_random_cycles=50, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='X', n_random_cycles=4, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='Y', n_random_cycles=4, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='X', n_random_cycles=50, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='Z', n_random_cycles=10, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='Y', n_random_cycles=10, protocol='SRB', twirl=(('C', 0),)))

Grouping keys based on 'protocol' and 'n_random_cycles': 
KeySet(
	Key(compiled_pauli='Z', n_random_cycles=4, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='I', n_random_cycles=4, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='X', n_random_cycles=4, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='Y', n_random_cycles=4, protocol='SRB', twirl=(('C', 0),)))
KeySet(
	Key(compiled_pauli='I', n_random_cycles=50, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='Z', n_random_cycles=50, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='Y', n_random_cycles=50, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='X', n_random_cycles=50, protocol='SRB', twirl=(('C', 0),)))
KeySet(
	Key(compiled_pauli='I', n_random_cycles=10, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='Z', n_random_cycles=10, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='Y', n_random_cycles=10, protocol='SRB', twirl=(('C', 0),)),
	Key(compiled_pauli='X', n_random_cycles=10, protocol='SRB', twirl=(('C', 0),)))
Parameters
  • names (list) – An iterable of key names.

  • invert (bool) – Whether the list of names to use should be those presented, or all names execpt those presented.

  • filter – Key/value pairs to be used as a filter.

update_keys(*other, keep=None, remove=None, **kwargs)

Updates every circuit’s key in this collection with new keywords/values. If a given key does not have a given keyword, it is added. If it already exists, it is overwritten. See also copy() which this method uses.

import trueq as tq
circuits = tq.make_srb(0, [4, 10])

# give each circuit a new keyword 'banana' with value 10
circuits.update_keys(banana=10)

# change 'n_random_cycles' to 5 for those circuits where it is 4
circuits.subset(n_random_cycles=4).update_keys(n_random_cycles=5)

circuits.keys()
KeySet
List of all the keys in the KeySet
protocol
The characterization protocol used to generate a circuit.
twirl
The twirling groups used on each subsystem.
n_random_cycles
The number of independent random cycles in the circuit.
compiled_pauli
The n-qubit Pauli operator that was compiled into the circuit immediately before measurement.
banana
Key
Key:
  • banana: 10
  • compiled_pauli: I
  • n_random_cycles: 5
  • protocol: SRB
  • twirl: (('C', 0),)
SRB (('C', 0),) 5 I 10
Key
Key:
  • banana: 10
  • compiled_pauli: X
  • n_random_cycles: 5
  • protocol: SRB
  • twirl: (('C', 0),)
SRB (('C', 0),) 5 X 10
Key
Key:
  • banana: 10
  • compiled_pauli: Y
  • n_random_cycles: 5
  • protocol: SRB
  • twirl: (('C', 0),)
SRB (('C', 0),) 5 Y 10
Key
Key:
  • banana: 10
  • compiled_pauli: Z
  • n_random_cycles: 5
  • protocol: SRB
  • twirl: (('C', 0),)
SRB (('C', 0),) 5 Z 10
Key
Key:
  • banana: 10
  • compiled_pauli: I
  • n_random_cycles: 10
  • protocol: SRB
  • twirl: (('C', 0),)
SRB (('C', 0),) 10 I 10
Key
Key:
  • banana: 10
  • compiled_pauli: X
  • n_random_cycles: 10
  • protocol: SRB
  • twirl: (('C', 0),)
SRB (('C', 0),) 10 X 10
Key
Key:
  • banana: 10
  • compiled_pauli: Y
  • n_random_cycles: 10
  • protocol: SRB
  • twirl: (('C', 0),)
SRB (('C', 0),) 10 Y 10
Key
Key:
  • banana: 10
  • compiled_pauli: Z
  • n_random_cycles: 10
  • protocol: SRB
  • twirl: (('C', 0),)
SRB (('C', 0),) 10 Z 10
Parameters
  • other (Key | dict) – One or more dict-like objects to update the keys with. Updating is applied in the given order. If a name specified in any of these objects already exists after the keep or remove process has taken place, it is updated.

  • keep (str | list) – A string or list of strings specifying the only names to keep during the updates. By default, all names are kept. Only one of the options keep or remove may be used.

  • remove (str | list) – A string or list of strings specifying names to remove during the updates. By default, no names are removed. Only one of the options keep or remove may be used.

  • kwargs – Name-value items to update the keys with. If a name specified here already exists after the keep or remove process has taken place, it is updated.

Raises

ValueError – If the mutally exclusive keep and remove are both set to True.

Returns

This circuit collection.

Return type

CircuitCollection

subset(has_results=None, new_collection=True, **filter)

Selects a subset of this collection’s Circuits by matching against a filter. This returns a new CircuitCollection, with references to the original circuits, i.e. no circuit copies are made. Optionally, by using the new_collection flag, the output type can be a generator over circuits that match the filter rather than a new collection object.

import trueq as tq

circuits = tq.make_srb([0], [4,32])
circuits.append(tq.make_rcal([0]))

# make a new CircuitCollection with only the SRB circuits from the
# CircuitCollection defined above
srb_circuits = circuits.subset(protocol="SRB")
assert srb_circuits.keys().protocol == {"SRB"}

# loop over circuits with no results
# for efficiency, use new_collection=False to avoid new instantiation
for circuit in circuits.subset(has_results=False, new_collection=False):
    circuit.results = {"0": 1}
Parameters
  • has_results (None | bool) – Whether to filter on circuits which have or do not have results entered. If True, only circuits with results are included, if False, only circuits without results are included, and if None (default) all circuits are included.

  • new_collection (bool) – Whether to create a new CircuitCollection and return it. Otherwise, a generator over circuits will be returned, which saves memory.

  • filter – Key/value pairs to be used as a filter.

Return type

generator | CircuitCollection

to_dict_list(include_cycles=True)

Returns a list of dictionary representations of the Circuit objects in this collection.

Parameters

include_cycles (bool) – Whether to include the cycles in the dictionary representations.

Return type

list

static from_dict_list(lst)

Returns a CircuitCollection constructed from a list of dictionary representations of trueq.Circuits.

Return type

CircuitCollection

batch_size(ruler)

The size of this collection according to the given method of counting circuit size. For example, NCycles, NGates, or TotalTime.

Parameters

ruler (CircuitRuler) – A callable that returns the size of a given circuit.

property results

A list of the Results for every circuit in this collection, where the order of this list matches the order of this collection. This property is also settable, see Circuit.results for allowed formats for setting.

import trueq as tq
circuits = tq.make_srb([0], [4, 100])

print("Circuits start with empty results initially:")
print(circuits.results[:5])

# set all results to the same value
circuits.results = [{"0": 10, "1": 100}] * len(circuits)

print("\nAfter setting the results:")
circuits.results[:5]
Circuits start with empty results initially:
[Results({}), Results({}), Results({}), Results({}), Results({})]

After setting the results:
[Results({'0': 10, '1': 100}),
 Results({'0': 10, '1': 100}),
 Results({'0': 10, '1': 100}),
 Results({'0': 10, '1': 100}),
 Results({'0': 10, '1': 100})]
Type

list

sum_results(decompile_paulis=True, **filter)

Sums together all results in the collection that match the given filter.

import trueq as tq
circuits = tq.make_srb([0], [4, 100])
circuits.append(tq.make_xrb([0], [4, 100]))
tq.Simulator().add_overrotation(0.05).run(circuits, n_shots=10)

print("Sum of all results in the circuit collection:")
print(circuits.sum_results())

print("\nTotal number of shots ran for the XRB protocol:")
print(circuits.sum_results(protocol="XRB").n_shots)

print("\nSum of results where `n_random_cycles=4`:")
print(circuits.sum_results(n_random_cycles=4).n_shots)
Sum of all results in the circuit collection:
Results({'0': 1398, '1': 1002})

Total number of shots ran for the XRB protocol:
1800

Sum of results where `n_random_cycles=4`:
1200
Parameters
  • decompile_paulis (bool) – Whether to adjust ditstrings of each circuit’s results by the 'compiled_pauli' key value of the corresponding circuit when summing. In most cases, and especially for randomized compiling, this value should be True.

  • filter – Key/value pairs to be used as a filter.

Return type

Results