pygsti.circuits.circuit.Circuit

Contents

pygsti.circuits.circuit.Circuit#

class Circuit(layer_labels=(), line_labels='auto', num_lines=None, editable=False, stringrep=None, name='', check=True, expand_subcircuits='default', occurrence=None, compilable_layer_indices=None)#

Bases: object

A quantum circuit.

A Circuit represents a quantum circuit, consisting of state preparation, gates, and measurement operations. It is composed of some number of “lines”, typically one per qubit, and stores the operations on these lines as a sequence of Label objects, one per circuit layer, whose .sslbls members indicate which line(s) the label belongs on. When a circuit is created with ‘editable=True’, a rich set of operations may be used to construct the circuit in place, after which done_editing() should be called so that the Circuit can be properly hashed as needed.

default_expand_subcircuits#

By default, expand sub-circuit labels.

Type:

bool

line_labels#

The line labels (often qubit labels) of this circuit.

Type:

tuple

layertup#

This Circuit’s layers as a standard Python tuple of layer Labels.

Type:

tuple

tup#

This Circuit as a standard Python tuple of layer Labels and line labels.

Type:

tuple

str#

The Python string representation of this Circuit.

Type:

str

layer_labels#

When static: a tuple of Label objects labelling each top-level circuit layer When editable: a list of lists, one per top-level layer, holding just the non-LabelTupTup (non-compound) labels. I.e. in the static case a LabelTupTup which specifies a complete circuit layer is assumed to contain no LabelTupTups as sub-components. Similarly, in the editable case a nested sublist which contains a set of Labels for a complete circuit layer is assumed to contain no further nested sublists as elements. For more complicated nested circuit structures, if required, circuits can contain CircuitLabel objects as elements. see :class:pygsti.baseobjs.label.CircuitLabel.

Creates a new Circuit object, encapsulating a quantum circuit.

You only need to supply the first layer_labels argument, though usually (except for just 1 or 2 qubits) you’ll want to also supply line_labels or num_lines. If you’ll be adding to or altering the circuit before using it, you should set editable=True.

Parameters:
  • layer_labels (iterable of Labels or str) –

    This argument provides a list of the layer labels specifying the state preparations, gates, and measurements for the circuit. This argument can also be a Circuit or a string, in which case it is parsed as a text-formatted circuit. Internally this will eventually be converted to a list of Label objects, one per layer, but it may be specified using anything that can be readily converted to a Label objects. For example, any of the following are allowed:

    • [‘Gx’,’Gx’] : X gate on each of 2 layers

    • [Label(‘Gx’),Label(‘Gx’)] : same as above

    • [(‘Gx’,0),(‘Gy’,0)] : X then Y on qubit 0 (2 layers)

    • [[(‘Gx’,0),(‘Gx’,1)],[(‘Gy’,0),(‘Gy’,1)]] : parallel X then Y on qubits 0 & 1

    Note Labels stored in an iterable type with a non-deterministic iteration order like dictionaries and sets, may result in unexpected layer orders.

  • line_labels (iterable, optional) – The (string valued) label for each circuit line. If ‘auto’, then line_labels is taken to be the list of all state-space labels present within layer_labels. If there are no such labels (e.g. if layer_labels contains just gate names like (‘Gx’,’Gy’)), then the special value ‘*’ is used as a single line label.

  • num_lines (int, optional) – Specify this instead of line_labels to set the latter to the integers between 0 and num_lines-1.

  • editable (bool) – Whether the created Circuit is created in able to be modified. If True, then you should call done_editing() once the circuit is completely assembled, as this makes the circuit read-only and allows it to be hashed.

  • stringrep (string, optional) – A string representation for the circuit. If None (the default), then this will be generated automatically when needed. One reason you’d want to specify this is if you know of a nice compact string representation that you’d rather use, e.g. “Gx^4” instead of the automatically generated “GxGxGxGx”. If you want to initialize a Circuit entirely from a string representation you can either specify the string in as layer_labels or set layer_labels to None and stringrep to any valid (one-line) circuit string.

  • name (str, optional) – A name for this circuit (useful if/when used as a block within larger circuits).

  • check (bool, optional) – Whether stringrep should be checked against layer_labels to ensure they are consistent, and whether the labels in layer_labels are a subset of line_labels. The only reason you’d want to set this to False is if you’re absolutely sure stringrep and line_labels are consistent and want to save computation time.

  • expand_subcircuits (bool or "default") – If “default”, then the value of Circuit.default_expand_subcircuits is used. If True, then any sub-circuits (e.g. anything exponentiated like “(GxGy)^4”) will be expanded when it is stored within the created Circuit. If False, then such sub-circuits will be left as-is. It’s typically more robust to expand sub-circuits as this facilitates comparison (e.g. so “GxGx” == “Gx^2”), but in cases when you have massive exponents (e.g. “Gx^8192”) it may improve performance to set expand_subcircuits=False.

  • occurrence (hashable, optional) – A value to set as the “occurrence id” for this circuit. This value doesn’t affect the circuit an any way except by affecting it’s hashing and equivalence testing. Circuits with different occurrence ids are not equivalent. Occurrence values effectively allow multiple copies of the same circuit to be stored in a dictionary or DataSet.

  • compilable_layer_indices (tuple, optional) – The circuit-layer indices that may be internally altered (but retaining the same target operation) and/or combined with the following circuit layer by a hardware compiler when executing this circuit. Layers that are not “compilable” are effectively followed by a barrier which prevents the hardware compiler from restructuring the circuit across the layer boundary.

Methods

__init__([layer_labels, line_labels, ...])

Creates a new Circuit object, encapsulating a quantum circuit.

append_circuit(circuit)

Append a circuit to the end of this circuit, returning a copy.

append_circuit_inplace(circuit)

Append a circuit to the end of this circuit.

cast(obj)

Convert obj into a Circuit.

change_gate_library(compilation[, ...])

Re-express a circuit over a different model.

clear()

Removes all the gates in a circuit (preserving the number of lines).

clear_labels([layers, lines, clear_straddlers])

Removes all the gates within the given circuit region.

compress_depth_inplace([...])

Compresses the depth of this circuit using very simple re-write rules.

convert_to_cirq(qubit_conversion[, ...])

Converts this circuit to a Cirq circuit.

convert_to_openqasm([num_qubits, ...])

Converts this circuit to an openqasm string.

convert_to_qiskit([num_qubits, ...])

Convert a pyGSTi circuit to a Qiskit QuantumCircuit.

convert_to_quil([num_qubits, ...])

Converts this circuit to a quil string.

convert_to_stim_tableau([...])

Converts this circuit to a stim tableau

convert_to_stim_tableau_layers([...])

Converts this circuit to a list of stim tableau layers

copy([editable])

Returns a copy of the circuit.

delete_idle_layers_inplace()

Deletes all layers in this circuit that contain no gate operations.

delete_idling_lines([idle_layer_labels])

Removes from this circuit all lines that are idling at every layer, returning a copy.

delete_idling_lines_inplace([idle_layer_labels])

Removes from this circuit all lines that are idling at every layer.

delete_layers([layers])

Deletes one or more layers from the circuit.

delete_lines(lines[, delete_straddlers])

Deletes one or more lines from the circuit.

done_editing()

Make this circuit read-only, so that it can be hashed (e.g. used as a dictionary key).

expand_subcircuits()

Returns a new circuit with CircuitLabel labels expanded.

expand_subcircuits_inplace()

Expands all CircuitLabel labels within this circuit.

extract_labels([layers, lines, strict])

Get a subregion - a "rectangle" - of this Circuit.

factorize_repetitions_inplace()

Attempt to replace repeated sub-circuits with CircuitLabel objects.

format_display_str([width])

Formats a string for displaying this circuit subject to a maximum width.

from_cirq(circuit[, qubit_conversion, ...])

Converts and instantiates a pyGSTi Circuit object from a Cirq Circuit object.

from_pythonstr(python_string, op_labels)

Decode an "encoded string" into a Circuit.

from_qiskit(circuit[, qubit_conversion, ...])

Converts and instantiates a pyGSTi Circuit object from a Qiskit QuantumCircuit object.

from_tuple(tup)

Creates a Circuit from a tuple

idling_lines([idle_layer_labels])

Returns the line labels corresponding to idling lines.

insert_circuit(circuit, j)

Inserts a circuit into this circuit, returning a copy.

insert_circuit_inplace(circuit, j)

Inserts a circuit into this circuit.

insert_idling_layers(insert_before, ...[, lines])

Inserts into this circuit one or more idling (blank) layers, returning a copy.

insert_idling_layers_inplace(insert_before, ...)

Inserts into this circuit one or more idling (blank) layers.

insert_idling_lines(insert_before, line_labels)

Insert one or more idling (blank) lines into this circuit, returning a copy.

insert_idling_lines_inplace(insert_before, ...)

Insert one or more idling (blank) lines into this circuit.

insert_labels_as_lines(lbls[, ...])

Inserts into this circuit the contents of lbls into new lines, returning a copy.

insert_labels_as_lines_inplace(lbls[, ...])

Inserts into this circuit the contents of lbls into new lines.

insert_labels_into_layers(lbls, ...[, lines])

Inserts into this circuit the contents of lbls into new full or partial layers, returning a copy.

insert_labels_into_layers_inplace(lbls, ...)

Inserts into this circuit the contents of lbls into new full or partial layers.

insert_layer(circuit_layer, j)

Inserts a single layer into a circuit, returning a copy.

insert_layer_inplace(circuit_layer, j)

Inserts a single layer into a circuit.

layer(j)

Returns a tuple of the components, i.e. the (non-identity) gates, in the layer at depth j.

layer_label(j)

Returns the layer, as a Label, at depth j.

layer_label_with_idles(j[, idle_gate_name])

Returns the layer, as a Label, at depth j, with idle_gate_name at empty circuit locations.

layer_with_idles(j[, idle_gate_name])

Returns a tuple of the components of the layer at depth j, with idle_gate_name at empty circuit locations.

map_names_inplace(mapper)

The names of all of the simple labels are updated in-place according to the mapping function mapper.

map_state_space_labels(mapper)

Creates a new Circuit whose line labels are updated according to the mapping function mapper.

map_state_space_labels_inplace(mapper)

The labels of all of the lines (wires/qubits) are updated according to the mapping function mapper.

num_nq_gates(nq)

The number of nq-qubit gates in the circuit.

parallelize([can_break_labels, adjacent_only])

Compress a circuit's gates by performing them in parallel.

prefix_circuit(circuit)

Prefix a circuit to the beginning of this circuit, returning a copy.

prefix_circuit_inplace(circuit)

Prefix a circuit to the beginning of this circuit.

reorder_lines(order)

Reorders the lines (wires/qubits) of the circuit, returning a copy.

reorder_lines_inplace(order)

Reorders the lines (wires/qubits) of the circuit.

repeat(ntimes[, expand])

Repeat this circuit ntimes times.

replace_gatename(old_gatename, new_gatename)

Returns a copy of this Circuit except that old_gatename is changed to new_gatename.

replace_gatename_inplace(old_gatename, ...)

Changes the name of a gate throughout this Circuit.

replace_gatename_with_idle(gatename)

Returns a copy of this Circuit with a given gatename treated as an idle gate.

replace_gatename_with_idle_inplace(gatename)

Treats a given gatename as an idle gate throughout this Circuit.

replace_layer(old_layer, new_layer)

Returns a copy of this Circuit except that old_layer is changed to new_layer.

replace_layer_with_circuit(circuit, j)

Replaces the j-th layer of this circuit with circuit, returning a copy.

replace_layer_with_circuit_inplace(circuit, j)

Replaces the j-th layer of this circuit with circuit.

replace_layers_with_aliases(alias_dict)

Performs a find and replace using layer aliases.

replace_with_idling_line_inplace(line_label)

Converts the specified line to an idling line, by removing all its gates.

reverse_inplace()

Reverses the order of the circuit.

sandwich(x, y)

Method for sandwiching labels around this circuit.

serialize([expand_subcircuits])

Serialize the parallel gate operations of this Circuit.

set_labels(lbls[, layers, lines])

Write lbls to the block defined by the layers and lines arguments.

simulate(**kwargs)

sort_layer_labels_inplace()

For every layer of the circuit ensure that the gates mentioned within the layer are sorted in increasing order of the qubits that the gate acts on.

tensor_circuit(circuit[, line_order])

The tensor product of this circuit and circuit, returning a copy.

tensor_circuit_inplace(circuit[, line_order])

The tensor product of this circuit and circuit.

to_label([nreps])

Construct and return this entire circuit as a CircuitLabel.

to_pythonstr(op_labels)

Convert this circuit to an "encoded" python string.

two_q_gate_count()

The number of two-qubit gates in the circuit.

Attributes

Castable

alias of Circuit | tuple | list | str

compilable_by_layer

Boolean array indicating whether each layer is "compilable" or not.

compilable_layer_indices

Tuple of the layer indices corresponding to "compilable" layers.

default_expand_subcircuits

depth

The circuit depth.

duration

layerstr

Just the string representation of the circuit layers (no '@<line_labels>' suffix)

layertup

This Circuit's layers as a standard Python tuple of layer Labels.

line_labels

The line labels (often qubit labels) of this circuit.

linesstr

Just the string representation of the circuit's line labels (the '@<line_labels>' suffix)

name

The name of this circuit.

num_gates

The number of gates in the circuit.

num_layers

The number of circuit layers.

num_lines

The number of lines in this circuit.

num_multiq_gates

The number of multi-qubit (2+ qubits) gates in the circuit.

occurrence

The occurrence id of this circuit.

size

Returns the circuit size.

str

The Python string representation of this Circuit.

tup

This Circuit as a standard Python tuple of layer Labels and line labels.

width

The circuit width.

append_circuit(circuit)#

Append a circuit to the end of this circuit, returning a copy.

This circuit must satisfy the requirements of insert_circuit(). See that method for more details.

Parameters:

circuit (A Circuit object) – The circuit to be appended.

Return type:

Circuit

append_circuit_inplace(circuit)#

Append a circuit to the end of this circuit.

This circuit must satisfy the requirements of insert_circuit(). See that method for more details.

Parameters:

circuit (A Circuit object) – The circuit to be appended.

Return type:

None

static cast(obj)#

Convert obj into a Circuit.

Parameters:

obj (object) – Object to convert

Return type:

Circuit

change_gate_library(compilation, allowed_filter=None, allow_unchanged_gates=False, depth_compression=True, one_q_gate_relations=None)#

Re-express a circuit over a different model.

Parameters:
  • compilation (dict or CompilationLibrary.) –

    If a dictionary, the keys are some or all of the gates that appear in the circuit, and the values are replacement circuits that are normally compilations for each of these gates (if they are not, the action of the circuit will be changed). The circuits need not be on all of the qubits, and need only satisfy the requirements of the insert_circuit method. There must be a key for every gate except the self.identity gate, unless allow_unchanged_gates is False. In that case, gate that aren’t a key in this dictionary are left unchanged.

    If a CompilationLibrary, this will be queried via the retrieve_compilation_of() method to find compilations for all of the gates in the circuit. So this CompilationLibrary must contain or be able to auto-generate compilations for the requested gates, except when allow_unchanged_gates is True. In that case, gates that a compilation is not returned for are left unchanged.

  • allowed_filter (dict or set, optional) – Specifies which gates are allowed to be used when generating compilations from compilation. Can only be not None if compilation is a CompilationLibrary. If a dict, keys must be gate names (like “Gcnot”) and values QubitGraph objects indicating where that gate (if it’s present in the library) may be used. If a set, then it specifies a set of qubits and any gate in the current library that is confined within that set is allowed. If None, then all gates within the library are allowed.

  • allow_unchanged_gates (bool, optional) – Whether to allow some gates to remain unchanged, and therefore to be absent from compilation. When True such gates are left alone; when False an error is raised if any such gates are encountered.

  • depth_compression (bool, optional) – Whether to perform depth compression after changing the gate library. If one_q_gate_relations is None this will only remove idle layers and compress the circuit by moving everything as far forward as is possible without knowledge of the action of any gates other than self.identity. See the depth_compression method for more details. Under most circumstances this should be true; if it is False changing gate library will often result in a massive increase in circuit depth.

  • one_q_gate_relations (dict, optional) – Gate relations for the one-qubit gates in the new gate library, that are used in the depth compression, to cancel / combine gates. E.g., one key-value pair might be (‘Gh’,’Gh’) : ‘I’, to signify that two Hadamards c ompose to the idle gate ‘Gi’. See the depth_compression() method for more details.

Return type:

None

clear()#

Removes all the gates in a circuit (preserving the number of lines).

Return type:

None

clear_labels(layers=None, lines=None, clear_straddlers=False)#

Removes all the gates within the given circuit region. Does not reduce the number of layers or lines.

Parameters:
  • layers (int, slice, or list/tuple of ints) – Defines the horizontal dimension of the region to clear. See extract_labels() for details.

  • lines (str/int, slice, or list/tuple of strs/ints) – Defines the vertical dimension of the region to clear. See extract_labels() for details.

  • clear_straddlers (bool, optional) – Whether or not gates which straddle cleared and non-cleared lines should be cleared. If False and straddling gates exist, an error will be raised.

Return type:

None

compress_depth_inplace(one_q_gate_relations=None, verbosity=0)#

Compresses the depth of this circuit using very simple re-write rules.

  1. If one_q_gate_relations is provided, all sequences of 1-qubit gates in the circuit are compressed as far as is possible using only the pair-wise combination rules provided by this dict (see below).

  2. All gates are shifted forwarded as far as is possible without any knowledge of what any of the gates are.

  3. All idle-only layers are deleted.

Parameters:
  • one_q_gate_relations (dict) –

    Keys that are pairs of strings, corresponding to 1-qubit gate names, with values that are a single string, also corresponding to a 1-qubit gate name. Whenever a 1-qubit gate with name name1 is followed in the circuit by a 1-qubit gate with name2 then, if one_q_gate_relations[name1,name2] = name3, name1 -> name3 and name2 -> self.identity, the identity name in the circuit. Moreover, this is still implemented when there are self.identity gates between these 1-qubit gates, and it is implemented iteratively in the sense that if there is a sequence of 1-qubit gates with names name1, name2, name3, … and there are relations for all of (name1,name2) -> name12, (name12,name3) -> name123 etc then the entire sequence of 1-qubit gates will be compressed into a single possibly non-idle 1-qubit gate followed by idle gates in place of the previous 1-qubit gates.

    If a QubitProcessorSpec object has been created for the gates/device in question, the QubitProcessorSpec.oneQgate_relations is the appropriate (and auto-generated) one_q_gate_relations.

    Note that this function will not compress sequences of 1-qubit gates that cannot be compressed by independently inspecting sequential non-idle pairs (as would be the case with, for example, Gxpi Gzpi Gxpi Gzpi, if the relation did not know that (Gxpi,Gzpi) -> Gypi, even though the sequence is the identity).

  • verbosity (int, optional) – If > 0, information about the depth compression is printed to screen.

Return type:

None

convert_to_cirq(qubit_conversion, wait_duration=None, gatename_conversion=None, idle_gate_name='Gi')#

Converts this circuit to a Cirq circuit.

Parameters:
  • qubit_conversion (dict) – Mapping from qubit labels (e.g. integers) to Cirq qubit objects.

  • wait_duration (cirq.Duration, optional) – If no gatename_conversion dict is given, the idle operation is not converted to a gate. If wait_duration is specified and gatename_conversion is not specified, then the idle operation will be converted to a cirq.WaitGate with the specified duration.

  • gatename_conversion (dict, optional) – If not None, a dictionary that converts the gatenames in the circuit to the Cirq gates that will appear in the Cirq circuit. If only standard pyGSTi names are used (e.g., ‘Gh’, ‘Gp’, ‘Gcnot’, ‘Gcphase’, etc) this dictionary need not be specified, and an automatic conversion to the standard Cirq names will be implemented.

  • idle_gate_name (str, optional) – Name to use for idle gates. Defaults to ‘Gi’

Return type:

A Cirq Circuit object.

convert_to_openqasm(num_qubits=None, standard_gates_version='u3', gatename_conversion=None, qubit_conversion=None, block_between_layers=True, block_between_gates=False, include_delay_on_idle=False, gateargs_map=None, auxiliary_lookup=None)#

Converts this circuit to an openqasm string.

Parameters:
  • num_qubits (int, optional) – The number of qubits for the openqasm file. If None, then this is assumed to equal the number of line labels in this circuit.

  • version (string, optional) – Either ‘u3’ or ‘x-sx-rz’. Specifies the naming convention for the QASM gates. With ‘u3’, all single-qubit gates are specified in terms of the ‘u3’ gate, used by IBM and QisKit until ~2021 (see the qasm_u3 function). With ‘x-sx-rz’, all single-gates are specified in terms of ‘x’ (an x pi rotation), ‘sx’ (an x pi/2 rotation) and ‘rz’ (a parameterized rotation around z by an angle theta).

  • gatename_conversion (dict, optional) – If not None, a dictionary that converts the gatenames in the circuit to the gatenames that will appear in the openqasm output. If only standard pyGSTi names are used (e.g., ‘Gh’, ‘Gp’, ‘Gcnot’, ‘Gcphase’, etc) this dictionary need not be specified, and an automatic conversion to the standard openqasm names will be implemented.

  • qubit_conversion (dict, optional) – If not None, a dictionary converting the qubit labels in the circuit to the desired qubit labels in the openqasm output. Can be left as None if the qubit labels are either (1) integers, or (2) of the form ‘Qi’ for integer i. In this case they are converted to integers (i.e., for (1) the mapping is trivial, for (2) the mapping strips the ‘Q’).

  • block_between_layers (bool, optional) – When True, add in a barrier after every circuit layer. Including such barriers can be important for QCVV testing, as this can help reduce the “behind-the-scenes” compilation (beyond necessary conversion to native instructions) experience by the circuit.

  • block_between_gates (bool, optional) – When True, add in a barrier after every gate (effectively serializing the circuit). Defaults to False.

  • include_delay_on_idle (bool, optional) – When True, includes a delay operation on implicit idles in each layer, as per Qiskit’s OpenQASM 2.0 convention after the deprecation of the id operation. Defaults to False, to avoid this behaviour if generating actually valid OpenQASM (with no opaque delay instruction) is desired. Can be set to True, which is commensurate with legacy usage of this function.

  • gateargs_map (dict, optional) – If not None, a dict that maps strings (representing pyGSTi standard gate names) to functions that map the parameters of a pyGSTi gate to a string to be combined with the QASM name to specify the specific gate, in QASM. If only standard pyGSTi names are used (e.g., ‘Gh’, ‘Gzr’, ‘Gczr, etc) or none of the gates are parameterized, this dictionary need not be specified, and an automatic conversion to the standard openqasm format will be implemented.

Returns:

An openqasm string.

Return type:

str

convert_to_qiskit(num_qubits=None, qubit_conversion=None, qiskit_gate_conversion=None, block_between_layers=True, qubits_to_measure=None)#

Convert a pyGSTi circuit to a Qiskit QuantumCircuit.

Parameters:
  • num_qubits (int, optional) – size of Qiskit QuantumCircuit to create from the pyGSTi circuit. If None, the number of line labels will set the size of the QuantumCircuit. It is often useful to provide this field if the pyGSTi circuit is to be executed on a backend that has more qubits than the pyGSTi circuit.

  • qubit_conversion (dict, optional) – mapping from pyGSTi line labels to Qiskit qubits, either as indices or Qiskit Qubit objects. If none, a literal mapping is used. If ‘remove-Q’ is set, then the ‘Q’ at the beginning of the line label is removed: e.g., ‘Q53’ becomes 53 (integer).

  • qiskit_gate_conversion (dict, optional) – A dictionary mapping gate names contained in this circuit to the corresponding gate names used in the rendered Qiskit QuantumCircuit. If None, a standard set of conversions is used (see standard_gatenames_qiskit_conversions()).

  • block_between_layers (bool, optional) – Set whether or not pyGSTi layer structure is maintained in the Qiskit circuit. Default is True. If set to False, Qiskit will move all gates to their earliest possible execution point.

  • qubits_to_measure (str or list, optional) – Set which pyGSTi qubits should be measured in the rendered Qiskit QuantumCircuit. If None, no qubits are measured. If ‘all’, all qubits in the length-num_qubits Qiskit QuantumRegister are measured. If ‘active’, only the qubits for which a qubit conversion is specified are measured. If a list of pyGSTi line labels is provided, then only the corresponding Qiskit qubits are measured.

Returns:

a Qiskit QuantumCircuit corresponding to the pyGSTi circuits.

Return type:

qiskit.QuantumCircuit

convert_to_quil(num_qubits=None, gatename_conversion=None, qubit_conversion=None, readout_conversion=None, block_between_layers=True, block_idles=True, gate_declarations=None)#

Converts this circuit to a quil string.

Parameters:
  • num_qubits (int, optional) – The number of qubits for the quil file. If None, then this is assumed to equal the number of line labels in this circuit.

  • gatename_conversion (dict, optional) – A dictionary mapping gate names contained in this circuit to the corresponding gate names used in the rendered quil. If None, a standard set of conversions is used (see standard_gatenames_quil_conversions()).

  • qubit_conversion (dict, optional) – If not None, a dictionary converting the qubit labels in the circuit to the desired qubit labels in the quil output. Can be left as None if the qubit labels are either (1) integers, or (2) of the form ‘Qi’ for integer i. In this case they are converted to integers (i.e., for (1) the mapping is trivial, for (2) the mapping strips the ‘Q’).

  • readout_conversion (dict, optional) – If not None, a dictionary converting the qubit labels mapped through qubit_conversion to the bit labels for readot. E.g. Suppose only qubit 2 (on Rigetti hardware) is in use. Then the pyGSTi string will have only one qubit (labeled 0); it will get remapped to 2 via qubit_conversion={0:2}. At the end of the quil circuit, readout should go recorded in bit 0, so readout_conversion = {0:0}. (That is, qubit with pyGSTi label 0 gets read to Rigetti bit 0, even though that qubit has Rigetti label 2.)

  • block_between_layers (bool, optional) – When True, add in a barrier after every circuit layer. Including such “pragma” blocks can be important for QCVV testing, as this can help reduce the “behind-the-scenes” compilation (beyond necessary conversion to native instructions) experience by the circuit.

  • block_idles (bool, optional) – In the special case of global idle gates, pragma-block barriers are inserted even when block_between_layers=False. Set block_idles=False to disable this behavior, which typically results in global idle gates being removed by the compiler.

  • gate_declarations (dict, optional) – If not None, a dictionary that provides unitary maps for particular gates that are not already in the quil syntax.

Returns:

A quil string.

Return type:

str

convert_to_stim_tableau(gate_name_conversions=None, num_qubits=None, qubit_label_conversions=None)#

Converts this circuit to a stim tableau

Parameters:
  • gate_name_conversions (dict, optional (default None)) – A map from pygsti gatenames to standard stim tableaus. If None a standard set of gate names is used from pygsti.tools.internalgates

  • num_qubits (int, optional (default None)) – Number of qubits which should be included in the overall Tableau. If None this value will be attempted to be inferred from the Circuit’s line_labels.

  • qubit_label_conversions (dict, optional (default None)) –

    A map from the circuit’s qubit labels into integers in the range 0 to N-1, where N is the number of qubits, where the integer indices indicate which qubit in the stim Tableau to map a given circuit operation into. If not specified an attempt will be made to infer this mapping based on the circuit’s qubit labels and an exception will be made if this inference is not possible.

    Note: in the following line_labels = self.line_labels.

    Inference is supported for line labels with the following format.

    • Qubit labels that are either integers, or string representations of integers, prefixed by the character ‘Q’ or ‘q’, that are monotonically increasing.

    If num_qubits is not specified, then these qubit labels will be mapped into the range [0,N-1] based on their index.

    If num_qubits is specified then there are different subcases:

    If num_qubits == len(line_labels) then these qubit labels will be mapped into the range [0,N-1] based on their index. If num_qubit > len(line_labels) we have two possibilities:

    1. If max(line_labels) <= num_qubits then the line_labels are mapped directly into their value in the range [0, N-1].

    2. If max(line_labels) > num_qubits then the line_labels are mapped into [0,N-1] using their index.

    Note if num_qubits<len(line_labels) then an exception is raised.

    If the default conversion behavior doesn’t suit your needs, or doesn’t support your label format then a manual dictionary should be specified.

Return type:

A single stim.Tableau representing the entire circuit.

convert_to_stim_tableau_layers(gate_name_conversions=None, num_qubits=None, qubit_label_conversions=None)#

Converts this circuit to a list of stim tableau layers

Parameters:
  • gate_name_conversions (dict, optional (default None)) – A map from pygsti gatenames to standard stim tableaus. If None a standard set of gate names is used from pygsti.tools.internalgates

  • num_qubits (int, optional (default None)) – Number of qubits which should be included in the each Tableau. If None this value will be attempted to be inferred from the Circuit’s line_labels.

  • qubit_label_conversions (dict, optional (default None)) –

    A map from the circuit’s qubit labels into integers in the range 0 to N-1, where N is the number of qubits, where the integer indices indicate which qubit in the stim Tableau to map a given circuit operation into. If not specified an attempt will be made to infer this mapping based on the circuit’s qubit labels and an exception will be made if this inference is not possible.

    Note: in the following line_labels = self.line_labels.

    Inference is supported for line labels with the following format.

    • Qubit labels that are either integers, or string representations of integers, prefixed by the character ‘Q’ or ‘q’, that are monotonically increasing.

    If num_qubits is not specified, then these qubit labels will be mapped into the range [0,N-1] based on their index.

    If num_qubits is specified then there are different subcases:

    If num_qubits == len(line_labels) then these qubit labels will be mapped into the range [0,N-1] based on their index. If num_qubit > len(line_labels) we have two possibilities:

    1. If max(line_labels) <= num_qubits then the line_labels are mapped directly into their value in the range [0, N-1].

    2. If max(line_labels) > num_qubits then the line_labels are mapped into [0,N-1] using their index.

    Note if num_qubits<len(line_labels) then an exception is raised.

    If the default conversion behavior doesn’t suit your needs, or doesn’t support your label format then a manual dictionary should be specified.

Return type:

A layer by layer list of stim tableaus

copy(editable='auto')#

Returns a copy of the circuit.

Parameters:

editable ({True,False,"auto"}) – Whether returned copy is editable. If “auto” is given, then the copy is editable if and only if this Circuit is.

Return type:

Circuit

delete_idle_layers_inplace()#

Deletes all layers in this circuit that contain no gate operations.

One of the steps of the depth_compression() method.

Returns:

False if the circuit is unchanged, and True otherwise.

Return type:

bool

delete_idling_lines(idle_layer_labels=None)#

Removes from this circuit all lines that are idling at every layer, returning a copy.

Parameters:

idle_layer_labels (iterable, optional) – A list or tuple of layer-labels that should be treated as idle operations, so their presence will not disqualify a line from being “idle”. E.g. [“Gi”] will cause “Gi” layers to be considered idle layers.

Return type:

Circuit

delete_idling_lines_inplace(idle_layer_labels=None)#

Removes from this circuit all lines that are idling at every layer.

Parameters:

idle_layer_labels (iterable, optional) – A list or tuple of layer-labels that should be treated as idle operations, so their presence will not disqualify a line from being “idle”. E.g. [“Gi”] will cause “Gi” layers to be considered idle layers.

Return type:

None

delete_layers(layers=None)#

Deletes one or more layers from the circuit.

Parameters:

layers (int, slice, or list/tuple of ints) – The layer index or indices to delete. See extract_labels() for details.

Return type:

None

delete_lines(lines, delete_straddlers=False)#

Deletes one or more lines from the circuit.

Parameters:
  • lines (str/int, slice, or list/tuple of strs/ints) – The line label(s) to delete. See extract_labels() for details.

  • delete_straddlers (bool, optional) – Whether or not gates which straddle deleted and non-deleted lines should be removed. If False and straddling gates exist, an error will be raised.

Return type:

None

done_editing()#

Make this circuit read-only, so that it can be hashed (e.g. used as a dictionary key).

This is done automatically when attempting to hash a Circuit for the first time, so there’s calling this function can usually be skipped (but it’s good for code clarity).

Return type:

None

expand_subcircuits()#

Returns a new circuit with CircuitLabel labels expanded.

Return type:

Circuit

expand_subcircuits_inplace()#

Expands all CircuitLabel labels within this circuit.

This operation is done in place and so can only be performed on an editable Circuit.

Return type:

None

extract_labels(layers=None, lines=None, strict=True)#

Get a subregion - a “rectangle” - of this Circuit.

This can be used to select multiple layers and/or lines of this Circuit. The strict argument controls whether gates need to be entirely within the given rectangle or can be intersecting it. If layers is a single integer then a Label is returned (representing a layer or a part of a layer), otherwise a Circuit is returned.

Parameters:
  • layers (int, slice, or list/tuple of ints) – Which layers to select (the horizontal dimension of the selection rectangle). Layers are always selected by index, and this argument can be a single (integer) index - in which case a Label is returned - or multiple indices as given by a slice or list - in which case a Circuit is returned. Note that, even though we speak of a “rectangle”, layer indices do not need to be contiguous. The special value None selects all layers.

  • lines (str/int, slice, or list/tuple of strs/ints) – Which lines to select (the vertical dimension of the selection rectangle). Lines are selected by their line-labels (elements of the circuit’s .line_labels property), which can be strings and/or integers. A single or multiple line-labels can be specified. If the line labels are integers a slice can be used, otherwise a list or tuple of labels is the only way to select multiple of them. Note that line-labels do not need to be contiguous. The special value None selects all lines.

  • strict (bool, optional) – When True, only gates lying completely within the selected region are included in the return value. If a gate straddles the region boundary (e.g. if we select just line 1 and the circuit contains “Gcnot:1:2”) then it is silently not-included in the returned label or circuit. If False, then gates which straddle the region boundary are included. Note that this may result in a Label or Circuit containing more line labels than where requested in the call to extract_labels(…)..

Returns:

The requested portion of this circuit, given as a Label if layers is a single integer and as a Circuit otherwise. Note: if you want a Circuit when only selecting one layer, set layers to a slice or tuple containing just a single index. Note that the returned circuit doesn’t retain any original metadata, such as the compilable layer indices or occurrence id.

Return type:

Label or Circuit

factorize_repetitions_inplace()#

Attempt to replace repeated sub-circuits with CircuitLabel objects.

More or less the reverse of expand_subcircuits(), this method attempts to collapse repetitions of the same labels into single CircuitLabel labels within this circuit.

This operation is done in place and so can only be performed on an editable Circuit.

Return type:

None

format_display_str(width=80)#

Formats a string for displaying this circuit subject to a maximum width.

Parameters:

width (int, optional) – The maximum width in characters. If the circuit is longer than this width it is wrapped using multiple lines (like a musical score).

Return type:

str

static from_cirq(circuit, qubit_conversion=None, cirq_gate_conversion=None, remove_implied_idles=True, global_idle_replacement_label='auto')#

Converts and instantiates a pyGSTi Circuit object from a Cirq Circuit object.

Parameters:
  • circuit (cirq Circuit) – The cirq Circuit object to parse into a pyGSTi circuit.

  • qubit_conversion (dict, optional (default None)) – A dictionary specifying a mapping between cirq qubit objects and pyGSTi qubit labels (either integers or strings). If None, then a default mapping is created.

  • cirq_gate_conversion (dict, optional (default None)) – If specified a dictionary with keys given by cirq gate objects, and values given by pygsti gate names which overrides the built-in conversion dictionary used by default.

  • remove_implied_idles (bool, optional (default True)) – A flag indicating whether to remove explicit idles that are part of a circuit layer containing other explicitly specified gates (i.e., whether to abide by the normal pyGSTi implicit idle convention).

  • global_idle_replacement_label (string or Label or None, optional (default 'auto')) – An option specified for the handling of global idle layers. If None, no replacement of global idle layers is performed and a verbatim conversion from the cirq layer is performed. If the string ‘auto’, then the behavior is to replace global idle layers with the gate label Label(()), which is the special syntax for the global idle layer, stylized typically as ‘[]’. If another string then replace with a gate label with the specified name acting on all of the qubits appearing in the cirq circuit. If a Label object, use this directly, this does not check for compatibility so it is up to the user to ensure the labels are compatible.

Returns:

A pyGSTi Circuit instance equivalent to the specified Cirq one.

Return type:

pygsti_circuit

static from_pythonstr(python_string, op_labels)#

Decode an “encoded string” into a Circuit.

Create a Circuit from a python string where each operation label is represented as a single character, starting with ‘A’ and continuing down the alphabet. This performs the inverse of to_pythonstr().

Parameters:
  • python_string (string) – string whose individual characters correspond to the operation labels of a operation sequence.

  • op_labels (tuple) – tuple containing all the operation labels that will be mapped from alphabet characters, beginning with ‘A’.

Return type:

Circuit

Examples

“AABA” => (‘Gx’,’Gx’,’Gy’,’Gx’)

static from_qiskit(circuit, qubit_conversion=None, qiskit_gate_conversion=None, use_standard_gate_conversion_as_backup=True, allow_different_gates_in_same_layer=True, verbose=False)#

Converts and instantiates a pyGSTi Circuit object from a Qiskit QuantumCircuit object.

Parameters:
  • circuit (Qiskit QuantumCircuit) – The Qiskit QuantumCircuit object to parse into a pyGSTi circuit.

  • qubit_conversion (dict, optional (default None)) – A dictionary specifying a mapping between Qiskit qubit indices and pyGSTi qubit labels (either integers or strings). If None, then a default mapping is created.

  • qiskit_gate_conversion (dict, optional (default None)) – If specified a dictionary with keys given by Qiskit gate objects, and values given by pyGSTi gate names which overrides the built-in conversion dictionary used by default.

  • use_standard_gate_conversion_as_backup (boolean (default True)) – Determines how the circuit conversion will be handled when the custom Qiskit gate conversion dict does not have an entry for the encountered gate. If True, this method will fall back on the standard conversions found in qiskit_gatenames_standard_conversions(). If False, the method will fail.

  • allow_different_gates_in_same_layer (boolean (default True)) – determines if gates with different names can be in the same layer. For instance, if a CZ gate and CX gate can both fit in the same layer, they will either be placed in the same layer (if True) or split into separate layers (if False).

  • verbose (bool)

Returns:

pygsti_circuit

A pyGSTi Circuit instance equivalent to the specified Qiskit one.

Dict {qiskit_qubit_idx, pyGSTi_qubit}

Dictionary that contains the mapping from the Qiskit qubit index to the corresponding pyGSTi qubit.

Return type:

Tuple

static from_tuple(tup)#

Creates a Circuit from a tuple

Parameters:

tup (tuple) – The tuple to convert.

Return type:

Circuit

idling_lines(idle_layer_labels=None)#

Returns the line labels corresponding to idling lines.

Parameters:

idle_layer_labels (iterable, optional) – A list or tuple of layer-labels that should be treated as idle operations, so their presence will not disqualify a line from being “idle”. E.g. [“Gi”] will cause “Gi” layers to be considered idle layers.

Return type:

tuple

insert_circuit(circuit, j)#

Inserts a circuit into this circuit, returning a copy.

The circuit to insert can be over more qubits than this circuit, as long as all qubits that are not part of this circuit are idling. In this case, the idling qubits are all discarded. The circuit to insert can also be on less qubits than this circuit: all other qubits are set to idling. So, the labels of the circuit to insert for all non-idling qubits must be a subset of the labels of this circuit.

Parameters:
  • circuit (Circuit) – The circuit to be inserted.

  • j (int) – The layer index (depth) at which to insert the circuit.

Return type:

Circuit

insert_circuit_inplace(circuit, j)#

Inserts a circuit into this circuit.

The circuit to insert can be over more qubits than this circuit, as long as all qubits that are not part of this circuit are idling. In this case, the idling qubits are all discarded. The circuit to insert can also be on less qubits than this circuit: all other qubits are set to idling. So, the labels of the circuit to insert for all non-idling qubits must be a subset of the labels of this circuit.

Parameters:
  • circuit (Circuit) – The circuit to be inserted.

  • j (int) – The layer index (depth) at which to insert the circuit.

Return type:

None

insert_idling_layers(insert_before, num_to_insert, lines=None)#

Inserts into this circuit one or more idling (blank) layers, returning a copy.

By default, complete layer(s) are inserted. The lines argument allows you to insert partial layers (on only a subset of the lines).

Parameters:
  • insert_before (int) – The layer index to insert the new layers before. Can be from 0 (insert at the beginning) to len(self)-1 (insert at end), and negative indexing can be used to insert relative to the last layer. The special value None inserts at the end.

  • num_to_insert (int) – The number of new layers to insert.

  • lines (str/int, slice, or list/tuple of strs/ints, optional) – Which lines should have new layers (blank circuit space) inserted into them. A single or multiple line-labels can be specified, similarly as in extract_labels(). The default value None stands for all lines.

Return type:

Circuit

insert_idling_layers_inplace(insert_before, num_to_insert, lines=None)#

Inserts into this circuit one or more idling (blank) layers.

By default, complete layer(s) are inserted. The lines argument allows you to insert partial layers (on only a subset of the lines).

Parameters:
  • insert_before (int) – The layer index to insert the new layers before. Can be from 0 (insert at the beginning) to len(self)-1 (insert at end), and negative indexing can be used to insert relative to the last layer. The special value None inserts at the end.

  • num_to_insert (int) – The number of new layers to insert.

  • lines (str/int, slice, or list/tuple of strs/ints, optional) – Which lines should have new layers (blank circuit space) inserted into them. A single or multiple line-labels can be specified, similarly as in extract_labels(). The default value None stands for all lines.

Return type:

None

insert_idling_lines(insert_before, line_labels)#

Insert one or more idling (blank) lines into this circuit, returning a copy.

Parameters:
  • insert_before (str or int) – The line label to insert new lines before. The special value None inserts lines at the bottom of this circuit.

  • line_labels (list or tuple) – A list or tuple of the new line labels to insert (can be integers and/or strings).

Return type:

Circuit

insert_idling_lines_inplace(insert_before, line_labels)#

Insert one or more idling (blank) lines into this circuit.

Parameters:
  • insert_before (str or int) – The line label to insert new lines before. The special value None inserts lines at the bottom of this circuit.

  • line_labels (list or tuple) – A list or tuple of the new line labels to insert (can be integers and/or strings).

Return type:

None

insert_labels_as_lines(lbls, layer_to_insert_before=None, line_to_insert_before=None, line_labels='auto')#

Inserts into this circuit the contents of lbls into new lines, returning a copy.

By default, lbls is inserted at the beginning of the new lines(s). The layer_to_insert_before argument allows you to insert lbls beginning at a layer of your choice.

Parameters:
  • lbls (list/tuple of Labels, or Circuit) – A list of layer labels to insert as new lines. The state-space (line) labels within lbls must not overlap with that of this circuit or an error is raised. If lbls contains more layers than this circuit currently has, new layers are added automatically.

  • layer_to_insert_before (int) – The layer index to insert lbls before. Can be from 0 (insert at the beginning) to len(self)-1 (insert at end), and negative indexing can be used to insert relative to the last layer. The default value of None inserts at the beginning.

  • line_to_insert_before (str or int) – The line label to insert the new lines before. The default value of None inserts lines at the bottom of the circuit.

  • line_labels (list, tuple, or "auto") – The labels of the new lines being inserted. If “auto”, then these are inferred from lbls.

Return type:

None

insert_labels_as_lines_inplace(lbls, layer_to_insert_before=None, line_to_insert_before=None, line_labels='auto')#

Inserts into this circuit the contents of lbls into new lines.

By default, lbls is inserted at the beginning of the new lines(s). The layer_to_insert_before argument allows you to insert lbls beginning at a layer of your choice.

Parameters:
  • lbls (list/tuple of Labels, or Circuit) – A list of layer labels to insert as new lines. The state-space (line) labels within lbls must not overlap with that of this circuit or an error is raised. If lbls contains more layers than this circuit currently has, new layers are added automatically.

  • layer_to_insert_before (int) – The layer index to insert lbls before. Can be from 0 (insert at the beginning) to len(self)-1 (insert at end), and negative indexing can be used to insert relative to the last layer. The default value of None inserts at the beginning.

  • line_to_insert_before (str or int) – The line label to insert the new lines before. The default value of None inserts lines at the bottom of the circuit.

  • line_labels (list, tuple, or "auto") – The labels of the new lines being inserted. If “auto”, then these are inferred from lbls.

Return type:

None

insert_labels_into_layers(lbls, layer_to_insert_before, lines=None)#

Inserts into this circuit the contents of lbls into new full or partial layers, returning a copy.

By default, complete layer(s) are inserted. The lines argument allows you to insert partial layers (on only a subset of the lines).

Parameters:
  • lbls (list/tuple of Labels, or Circuit) – The full or partial layer labels to insert. The length of this list, tuple, or circuit determines the number of layers which are inserted.

  • layer_to_insert_before (int) – The layer index to insert lbls before. Can be from 0 (insert at the beginning) to len(self)-1 (insert at end), and negative indexing can be used to insert relative to the last layer. The special value None inserts at the end.

  • lines (str/int, slice, or list/tuple of strs/ints, optional) – Which lines should have lbls inserted into them. Currently this can only be a larger set than the set of line labels present in lbls (in future versions this may allow filtering of lbls). value None stands for all lines.

Return type:

Circuit

insert_labels_into_layers_inplace(lbls, layer_to_insert_before, lines=None)#

Inserts into this circuit the contents of lbls into new full or partial layers.

By default, complete layer(s) are inserted. The lines argument allows you to insert partial layers (on only a subset of the lines).

Parameters:
  • lbls (list/tuple of Labels, or Circuit) – The full or partial layer labels to insert. The length of this list, tuple, or circuit determines the number of layers which are inserted.

  • layer_to_insert_before (int) – The layer index to insert lbls before. Can be from 0 (insert at the beginning) to len(self)-1 (insert at end), and negative indexing can be used to insert relative to the last layer. The special value None inserts at the end.

  • lines (str/int, slice, or list/tuple of strs/ints, optional) – Which lines should have lbls inserted into them. Currently this can only be a larger set than the set of line labels present in lbls (in future versions this may allow filtering of lbls). value None stands for all lines.

Return type:

None

insert_layer(circuit_layer, j)#

Inserts a single layer into a circuit, returning a copy.

The input layer does not need to contain a gate that acts on every qubit, but it should not contain more than one gate on a qubit.

Parameters:
  • circuit_layer (Label) – The layer to insert. A (possibly compound) Label object or something that can be converted into one, e.g. ((‘Gx’,0),(‘Gcnot’,1,2)) or just ‘Gx’.

  • j (int) – The layer index (depth) at which to insert the circuit_layer.

Return type:

Circuit

insert_layer_inplace(circuit_layer, j)#

Inserts a single layer into a circuit.

The input layer does not need to contain a gate that acts on every qubit, but it should not contain more than one gate on a qubit.

Parameters:
  • circuit_layer (Label) – The layer to insert. A (possibly compound) Label object or something that can be converted into one, e.g. ((‘Gx’,0),(‘Gcnot’,1,2)) or just ‘Gx’.

  • j (int) – The layer index (depth) at which to insert the circuit_layer.

Return type:

None

layer(j)#

Returns a tuple of the components, i.e. the (non-identity) gates, in the layer at depth j.

These are the .components of the Label returned by indexing this Circuit (using square brackets) with j, i.e. this returns this_circuit[j].components.

Parameters:

j (int) – The index (depth) of the layer to be returned

Return type:

tuple

layer_label(j)#

Returns the layer, as a Label, at depth j.

This label contains as components all the (non-identity) gates in the layer..

Parameters:

j (int) – The index (depth) of the layer to be returned

Return type:

Label

layer_label_with_idles(j, idle_gate_name='I')#

Returns the layer, as a Label, at depth j, with idle_gate_name at empty circuit locations.

This effectively places an explicit idle_gate_name gates wherever there is an implied identity operation in the circuit.

Parameters:
  • j (int) – The index (depth) of the layer to be returned

  • idle_gate_name (str, optional) – The idle gate name to use. Note that state space (qubit) labels will be added to this name to form a Label.

Return type:

Label

layer_with_idles(j, idle_gate_name='I')#

Returns a tuple of the components of the layer at depth j, with idle_gate_name at empty circuit locations.

This effectively places an explicit idle_gate_name gates wherever there is an implied identity operation in the circuit.

Parameters:
  • j (int) – The index (depth) of the layer to be returned

  • idle_gate_name (str, optional) – The idle gate name to use. Note that state space (qubit) labels will be added to this name to form a Label.

Return type:

tuple

map_names_inplace(mapper)#

The names of all of the simple labels are updated in-place according to the mapping function mapper.

Parameters:

mapper (dict or function) – A dictionary whose keys are the existing gate name values and whose values are the new names (strings) or a function which takes a single (existing name) argument and returns a new name.

Return type:

None

map_state_space_labels(mapper)#

Creates a new Circuit whose line labels are updated according to the mapping function mapper.

Parameters:

mapper (dict or function) – A dictionary whose keys are the existing self.line_labels values and whose value are the new labels, or a function which takes a single (existing line-label) argument and returns a new line-label.

Return type:

Circuit

map_state_space_labels_inplace(mapper)#

The labels of all of the lines (wires/qubits) are updated according to the mapping function mapper.

Parameters:

mapper (dict or function) – A dictionary whose keys are the existing self.line_labels values and whose value are the new labels, or a function which takes a single (existing line-label) argument and returns a new line-label.

Return type:

None

num_nq_gates(nq)#

The number of nq-qubit gates in the circuit.

(Note that this cannot distinguish between “true” nq-qubit gates and gate that have been defined to act on nq qubits but that represent some tensor-product gate.)

Parameters:

nq (int) – The qubit-count of the gates to count. For example, if nq == 3, this function returns the number of 3-qubit gates.

Return type:

int

parallelize(can_break_labels=True, adjacent_only=False)#

Compress a circuit’s gates by performing them in parallel.

Construct a circuit with the same underlying labels as this one, but with as many gates performed in parallel as possible (with some restrictions - see the Parameters section below). Generally, gates are moved as far left (toward the start) of the circuit as possible.

Parameters:
  • can_break_labels (bool, optional) – Whether compound (parallel-gate) labels in this Circuit can be separated during the parallelization process. For example, if can_break_labels=True then “Gx:0[Gy:0Gy:1]” => “[Gx:0Gy:1]Gy:0” whereas if can_break_labels=False the result would remain “Gx:0[Gy:0Gy:1]” because [Gy:0Gy:1] cannot be separated.

  • adjacent_only (bool, optional) – It True, then operation labels are only allowed to move into an adjacent label, that is, they cannot move “through” other operation labels. For example, if adjacent_only=True then “Gx:0Gy:0Gy:1” => “Gx:0[Gy:0Gy:1]” whereas if adjacent_only=False the result would be “[Gx:0Gy:1]Gy:0. Setting this to True is sometimes useful if you want to parallelize a serial string in such a way that subsequently calling .serialize() will give you back the original string.

Return type:

Circuit

prefix_circuit(circuit)#

Prefix a circuit to the beginning of this circuit, returning a copy.

This circuit must satisfy the requirements of the insert_circuit(). See that method for more details.

Parameters:

circuit (A Circuit object) – The circuit to be prefixed.

Return type:

Circuit

prefix_circuit_inplace(circuit)#

Prefix a circuit to the beginning of this circuit.

This circuit must satisfy the requirements of the insert_circuit(). See that method for more details.

Parameters:

circuit (A Circuit object) – The circuit to be prefixed.

Return type:

None

reorder_lines(order)#

Reorders the lines (wires/qubits) of the circuit, returning a copy.

Note that the ordering of the lines is unimportant for most purposes.

Parameters:

order (list) – A list containing all of the circuit line labels (self.line_labels) in the order that the should be converted to.

Return type:

Circuit

reorder_lines_inplace(order)#

Reorders the lines (wires/qubits) of the circuit.

Note that the ordering of the lines is unimportant for most purposes.

Parameters:

order (list) – A list containing all of the circuit line labels (self.line_labels) in the order that the should be converted to.

Return type:

None

repeat(ntimes, expand='default')#

Repeat this circuit ntimes times.

Parameters:
  • ntimes (int) – Number of repetitions.

  • expand (bool or "default", optional) – When False, the returned circuit will contain a CircuitLabel encapsulating the repetitions without explicitly storing them. When True, the returned circuit will be expanded into the ntimes repetitions. “default” means to use the value in the class variable Circuit.default_expand_subcircuits.

Return type:

Circuit

replace_gatename(old_gatename, new_gatename)#

Returns a copy of this Circuit except that old_gatename is changed to new_gatename.

Note that the “name” is only a part of the “label” identifying each gate, and doesn’t include the lines (qubits) a gate acts upon. For example, the “Gx:0” and “Gx:1” labels both have the same name but act on different qubits.

Parameters:
  • old_gatename (str) – The gate name to replace.

  • new_gatename (str) – The name to replace old_gatename with.

Return type:

Circuit

replace_gatename_inplace(old_gatename, new_gatename)#

Changes the name of a gate throughout this Circuit.

Note that the name is only a part of the label identifying each gate, and doesn’t include the lines (qubits) a gate acts upon. For example, the “Gx:0” and “Gx:1” labels both have the same name but act on different qubits.

Parameters:
  • old_gatename (str) – The gate name to replace.

  • new_gatename (str) – The name to replace old_gatename with.

Return type:

None

replace_gatename_with_idle(gatename)#

Returns a copy of this Circuit with a given gatename treated as an idle gate.

This effectively removes this gate name from the circuit, and replaces a layer containing only this gate name with an idle layer.

Parameters:

gatename (str) – The gate name to replace.

Return type:

Circuit

replace_gatename_with_idle_inplace(gatename)#

Treats a given gatename as an idle gate throughout this Circuit.

This effectively removes this gate name from the circuit, and replaces a layer containing only this gate name with an idle layer.

Parameters:

gatename (str) – The gate name to replace.

Return type:

None

replace_layer(old_layer, new_layer)#

Returns a copy of this Circuit except that old_layer is changed to new_layer.

Parameters:
  • old_layer (str or Label) – The layer to find.

  • new_layer (str or Label) – The layer to replace found layers with.

Return type:

Circuit

replace_layer_with_circuit(circuit, j)#

Replaces the j-th layer of this circuit with circuit, returning a copy.

Parameters:
  • circuit (Circuit) – The circuit to insert

  • j (int) – The layer index to replace.

Return type:

Circuit

replace_layer_with_circuit_inplace(circuit, j)#

Replaces the j-th layer of this circuit with circuit.

Parameters:
  • circuit (Circuit) – The circuit to insert

  • j (int) – The layer index to replace.

Return type:

None

replace_layers_with_aliases(alias_dict)#

Performs a find and replace using layer aliases.

Returns a copy of this Circuit except that it’s layers that match keys of alias_dict are replaced with the corresponding values.

Parameters:

alias_dict (dict) – A dictionary whose keys are layer Labels (or equivalent tuples or strings), and whose values are Circuits.

Return type:

Circuit

replace_with_idling_line_inplace(line_label, clear_straddlers=True)#

Converts the specified line to an idling line, by removing all its gates.

If there are any multi-qubit gates acting on this line, this function will raise an error when clear_straddlers=False.

Parameters:
  • line_label (str or int) – The label of the line to convert to an idling line.

  • clear_straddlers (bool, optional) – Whether or not gates which straddle the line_label should also be cleared. If False and straddling gates exist, an error will be raised.

Return type:

None

reverse_inplace()#

Reverses the order of the circuit.

Return type:

None

sandwich(x, y)#

Method for sandwiching labels around this circuit.

Parameters:
  • x (tuple of Label objects) – Tuple of Labels to prepend to this Circuit.

  • y (tuple of Label objects) – Same as x, but appended instead.

Return type:

Circuit

serialize(expand_subcircuits=False)#

Serialize the parallel gate operations of this Circuit.

Construct a new Circuit whereby all layers containing multiple gates are converted to separate single-gate layers, effectively putting each elementary gate operation into its own layer. Ordering is dictated by the ordering of the compound layer labels.

Parameters:

expand_subcircuits (bool) – Whether subcircuits should be expanded before performing the serialization. If False, the circuit may contain CircuitLabel layers.

Return type:

Circuit

set_labels(lbls, layers=None, lines=None)#

Write lbls to the block defined by the layers and lines arguments.

Note that lbls can be anything interpretable as a Label or list of labels.

Parameters:
  • lbls (Label, list/tuple of Labels, or Circuit) – When layers is a single integer, lbls should be a single “layer label” of type Label. Otherwise, lbls should be a list or tuple of Label objects with length equal to the number of layers being set. A Circuit may also be used in this case.

  • layers (int, slice, or list/tuple of ints) – Which layers to set (the horizontal dimension of the destination rectangle). Layers are always selected by index, and this argument can be a single (integer) index or multiple indices as given by a slice or list. Note that these indices do not need to be contiguous. The special value None stands for all layers.

  • lines (str/int, slice, or list/tuple of strs/ints) – Which lines to set (the vertical dimension of the destination rectangle). Lines are selected by their line-labels, which can be strings and/or integers. A single or multiple line-labels can be specified. If the line labels are integers a slice can be used, otherwise a list or tuple of labels is the only way to specify multiple of them. The line-labels do not need to be contiguous. The special value None stands for all lines, and in this case new lines will be created if there are new state-space labels in lbls (when lines is not None an error is raised instead).

Return type:

None

sort_layer_labels_inplace()#

For every layer of the circuit ensure that the gates mentioned within the layer are sorted in increasing order of the qubits that the gate acts on.

Note that any two qubit gate acting on i, j will not be flipped to act on j,i.

If this circuit believes that the layer is already sorted then it will not resort the layer.

Updates the circuit inplace.

tensor_circuit(circuit, line_order=None)#

The tensor product of this circuit and circuit, returning a copy.

That is, it adds circuit to this circuit as new lines. The line labels of circuit must be disjoint from the line labels of this circuit, as otherwise applying the circuits in parallel does not make sense.

Parameters:
  • circuit (A Circuit object) – The circuit to be tensored.

  • line_order (List, optional) – A list of all the line labels specifying the order of the circuit in the updated circuit. If None, the lines of circuit are added below the lines of this circuit. Note that, for many purposes, the ordering of lines of the circuit is irrelevant.

Return type:

Circuit

tensor_circuit_inplace(circuit, line_order=None)#

The tensor product of this circuit and circuit.

That is, it adds circuit to this circuit as new lines. The line labels of circuit must be disjoint from the line labels of this circuit, as otherwise applying the circuits in parallel does not make sense.

Parameters:
  • circuit (A Circuit object) – The circuit to be tensored.

  • line_order (List, optional) – A list of all the line labels specifying the order of the circuit in the updated circuit. If None, the lines of circuit are added below the lines of self. Note that, for many purposes, the ordering of lines of the circuit is irrelevant.

Return type:

None

to_label(nreps=1)#

Construct and return this entire circuit as a CircuitLabel.

Note: occurrence-id information is not stored in a circuit label, so circuits that differ only in their occurrence_id will return circuit labels that are equal.

Parameters:

nreps (int, optional) – The number of times this circuit will be repeated (CircuitLabels support exponentiation and you can specify this here).

Return type:

CircuitLabel

to_pythonstr(op_labels)#

Convert this circuit to an “encoded” python string.

In the returned string each operation label is represented as a single character, starting with ‘A’ and continuing down the alphabet. This can be useful for processing operation sequences using python’s string tools (regex in particular).

Parameters:

op_labels (tuple) – An iterable containing at least all the layer-Labels that appear in this Circuit, and which will be mapped to alphabet characters, beginning with ‘A’.

Returns:

The converted operation sequence.

Return type:

string

Examples

(‘Gx’,’Gx’,’Gy’,’Gx’) => “AABA”

two_q_gate_count()#

The number of two-qubit gates in the circuit.

(Note that this cannot distinguish between “true” 2-qubit gates and gate that have been defined to act on two qubits but that represent some tensor-product gate.)

Return type:

int

property compilable_by_layer#

Boolean array indicating whether each layer is “compilable” or not.

property compilable_layer_indices#

Tuple of the layer indices corresponding to “compilable” layers.

property depth#

The circuit depth.

This is the number of layers in simple circuits. For circuits containing sub-circuit blocks, this includes the full depth of these blocks. If you just want the number of top-level layers, use num_layers().

Return type:

int

property layerstr#

Just the string representation of the circuit layers (no ‘@<line_labels>’ suffix)

property layertup: Tuple[LabelTupTup, ...] | Sequence[Label | Sequence[Label]] | Tuple[Label, ...]#

This Circuit’s layers as a standard Python tuple of layer Labels.

Return type:

tuple

property line_labels#

The line labels (often qubit labels) of this circuit.

property linesstr#

Just the string representation of the circuit’s line labels (the ‘@<line_labels>’ suffix)

property name#

The name of this circuit.

Note: the name is not a part of the hashed value. The name is used to name the CircuitLabel returned from to_label().

property num_gates#

The number of gates in the circuit.

Return type:

int

property num_layers#

The number of circuit layers.

In simple circuits, this is the same as the depth (given by depth()). For circuits containing sub-circuit blocks, this gives the number of top-level layers in this circuit.

Return type:

int

property num_lines#

The number of lines in this circuit.

Return type:

int

property num_multiq_gates#

The number of multi-qubit (2+ qubits) gates in the circuit.

(Note that this cannot distinguish between “true” multi-qubit gates and gate that have been defined to act on more than one qubit but that represent some tensor-product gate.)

Return type:

int

property occurrence#

The occurrence id of this circuit.

property size#

Returns the circuit size.

This is the sum of the sizes of all the gates in the circuit. A gate that acts on n-qubits has a size of n, with the exception of the idle which has a size of 0. Hence, the circuit is given by: size = depth * num_lines - num_1Q_idles.

Return type:

int

property str#

The Python string representation of this Circuit.

Return type:

str

property tup#

This Circuit as a standard Python tuple of layer Labels and line labels.

Return type:

tuple

property width#

The circuit width.

This is the number of qubits on which the circuit acts. This includes qubits that only idle, but are included as part of the circuit according to self.line_labels.

Return type:

int