pygsti.circuits.subcircuit_selection

Utility functions for subcircuit selection

Module Contents

Classes

HasGetMethod

Base class for protocol classes.

Functions

sample_subcircuits(...)

Samples subcircuits from a full circuit based on specified width and depth pairs.

simple_weighted_subcirc_selection(...)

Samples subcircuits from a full circuit using a simple approach. The simple approach

greedy_growth_subcirc_selection(...)

Selects subcircuits using a greedy growth strategy, starting with one gate in one layer

random_connected_subgraph(→ Union[Set[int], Set[str]])

Generates a random set of nodes that form a

Attributes

MAX_STARTING_LAYER_ATTEMPTS

pygsti.circuits.subcircuit_selection.MAX_STARTING_LAYER_ATTEMPTS = '1000'
class pygsti.circuits.subcircuit_selection.HasGetMethod

Bases: Protocol

Base class for protocol classes.

Protocol classes are defined as:

class Proto(Protocol):
    def meth(self) -> int:
        ...

Such classes are primarily used with static type checkers that recognize structural subtyping (static duck-typing).

For example:

class C:
    def meth(self) -> int:
        return 0

def func(x: Proto) -> int:
    return x.meth()

func(C())  # Passes static type check

See PEP 544 for details. Protocol classes decorated with @typing.runtime_checkable act as simple-minded runtime protocols that check only the presence of given attributes, ignoring their type signatures. Protocol classes can be generic, they are defined as:

class GenProto(Protocol[T]):
    def meth(self) -> T:
        ...
get(qubits: List[int]) float
pygsti.circuits.subcircuit_selection.sample_subcircuits(full_circs: pygsti.circuits.circuit.Circuit | List[pygsti.circuits.circuit.Circuit], width_depths: Dict[int, List[int]], coupling_map: str | List[int] | List[str] | qiskit.transpiler.CouplingMap, instruction_durations: qiskit.transpiler.InstructionDurations | HasGetMethod, use_qiskit_for_instruction_durations: bool | None = None, num_samples_per_width_depth: int = 10, strategy: Literal['simple', 'greedy'] | Callable[Ellipsis, Any] = 'simple', strategy_args: dict | None = None, depth_metric: Literal['layer_count', 'falcon_depth'] = 'layer_count', num_test_samples: int | None = None, rand_state: numpy.random.RandomState | None = None) pygsti.protocols.protocol.FreeformDesign

Samples subcircuits from a full circuit based on specified width and depth pairs.

Parameters

full_circsUnion[pygsti.circuits.Circuit, List[pygsti.circuits.Circuit]]

The full circuit(s) from which to sample subcircuits.

width_depthsDict[int, List[int]]

A dictionary whose keys are subcircuit widths and whose values are lists of depths to sample for that subcircuit depth. Defines a list of (width, depth) pairs for subcircuits.

coupling_mapUnion[str, qiskit.transpiler.CouplingMap]

The coupling map defining the connectivity of qubits. Can be ‘all-to-all’, ‘linear’, or a qiskit CouplingMap object.

instruction_durationsqiskit.transpiler.InstructionDurations

A qiskit InstructionDurations object used to determine delay times for idle subcircuit layers.

use_qiskit_for_instruction_durationsbool, optional

Whether to use qiskit gatenames instead of pyGSTi gatenames when looking up instruction durations in instruction_durations. If this argument is not provided, then the lookup gatename is based on the type of instruction_durations. If instruction_durations is an InstructionDurations object, the qiskit gatenames are used, else the pyGSTi gatenames are used.

num_samples_per_width_depthint, optional

The number of subcircuits to sample for each width-depth combination. Default is 10.

strategyUnion[str, Callable[…, Any]], optional

The subcircuit sampling strategy to use (‘simple’, ‘greedy’, or a custom function). Default is ‘simple’.

strategy_argsDict, optional

Additional arguments if a custom sampling strategy function is used. Default is None.

depth_metricstr, optional

The metric to use for measuring depth (‘layer_count’ or ‘falcon_depth’). If layer_count, the depth is calculated as the number of layers in the subcircuit. If falcon_depth, the gate set must be U3-CX; U3 gates contribute 2 to the depth and CX gates contribute 1 to the depth. The falcon_depth metric is based on the Falcon generation of IBMQ devices. Default is ‘layer_count’.

num_test_samplesint, optional

The number of test samples to use if the ‘greedy’ subcircuit sampling strategy is employed. If strategy is not greedy, this argument is ignored. Default is None.

rand_state_np.random.RandomState, optional

A random state for reproducibility. Default is None.

Returns

pygsti.protocols.FreeformDesign

A FreeformDesign object containing the sampled subcircuits and auxiliary information, including a circuit ID and depth.

pygsti.circuits.subcircuit_selection.simple_weighted_subcirc_selection(full_circ: pygsti.circuits.circuit.Circuit, width: int, depth: int, num_subcircs: int, coupling_map: str | List[int] | List[str] | qiskit.transpiler.CouplingMap, instruction_durations: qiskit.transpiler.InstructionDurations | HasGetMethod, use_qiskit_for_instruction_durations: bool | None = None, depth_metric: Literal['layer_count', 'falcon_depth'] = 'layer_count', rand_state: numpy.random.RandomState | None = None, return_depth_info: bool = False, stochastic_2q_drops: bool = False, verbosity: Literal[0, 1] = 1) List[List[pygsti.circuits.circuit.Circuit], List[int], List[int] | None, List[Tuple[int, int]] | None, List[int] | None, List[List[int]] | None]

Samples subcircuits from a full circuit using a simple approach. The simple approach is to identify a starting layer, along with a connected subset of active qubits, and snip out a subcircuit with the desired width and depth.

Parameters

full_circsUnion[pygsti.circuits.Circuit, List[pygsti.circuits.Circuit]]

The full circuit(s) from which to sample subcircuits.

widthint

width of subcircuit to snip out.

depth: int

depth of subcircuit to snip out.

num_subcircsint

The number of subcircuits to snip out for the given width and depth.

coupling_mapUnion[str, qiskit.transpiler.CouplingMap]

The coupling map defining the connectivity of qubits. Can be ‘all-to-all’, ‘linear’, or a qiskit CouplingMap object.

instruction_durationsqiskit.transpiler.InstructionDurations

A qiskit InstructionDurations object used to determine delay times for idle subcircuit layers.

use_qiskit_for_instruction_durationsbool, optional

Whether to use qiskit gatenames instead of pyGSTi gatenames when looking up instruction durations in instruction_durations. If this argument is not provided, then the lookup gatename is based on the type of instruction_durations. If instruction_durations is an InstructionDurations object, the qiskit gatenames are used, else the pyGSTi gatenames are used.

rand_state_np.random.RandomState, optional

A random state for reproducibility. Default is None.

return_depth_infobool, optional

Whether to include compiled depths and the start and end layer for each subcircuit. Default is False.

stochastic_2q_dropsbool, optional

Whether to apply stochastic dropping of 2-qubit gates. Default is False, in which case all dangling 2-qubit gates are dropped. A gate is considered dangling if it has support on at least one qubit that is not in the selected subset of qubits snipped out for the subcircuit.

verbosityint, optional

Level of verbosity for logging. Default is 1.

Returns

Tuple[List[pygsti.circuits.Circuit], List[int],

Optional[List[int], Optional[List[Tuple[int,int]]]], Optional[List[int]], Optional[List[int]]]

A tuple containing the selected subcircuits and the counts of dropped gates. If return_depth_info is set to True, then the returns are extended to include the compiled depth of each subcircuit and the start and end layers of each subcircuit. If stochastic_2q_drops is set to True, then the returns are extended to include the number of dangling gates in each subcircuit and the indices of added layers.

pygsti.circuits.subcircuit_selection.greedy_growth_subcirc_selection(full_circ: pygsti.circuits.circuit.Circuit, width: int, depth: int, num_subcircs: int = 1, num_test_subcircs: int = 10, rand_state: numpy.random.RandomState | None = None, verbosity: Literal[0, 1] = 1, return_depth_info: bool = False) Tuple[List[pygsti.circuits.circuit.Circuit], List[int], List[int] | None, List[Tuple[int, int]] | None]

Selects subcircuits using a greedy growth strategy, starting with one gate in one layer and adding gates with overlapping support in subsequent layers.

Parameters

full_circpygsti.circuits.Circuit

The full circuit from which to select subcircuits.

widthint

The target width of the subcircuits to be selected.

depthint

The target depth of the subcircuits to be selected.

num_subcircsint, optional

The number of subcircuits to select. Default is 1.

num_test_subcircsint, optional

The number of test subcircuits to generate. Default is 10.

rand_stateOptional[_np.random.RandomState], optional

A random state for reproducibility. Default is None.

verbosityint, optional

Level of verbosity for logging. Default is 1.

return_depth_infobool, optional

Whether to include compiled depths and the start and end layer for each subcircuit. Default is False.

Returns

Tuple[List[_Circuit], List[int],

Optional[List[int]], Optional[List[Tuple[int,int]]]]

A tuple containing the selected subcircuits and the counts of dropped gates. If return_depth_info is set to True, then the returns are extended to include the compiled depth of each subcircuit and the start and end layers of each subcircuit.

pygsti.circuits.subcircuit_selection.random_connected_subgraph(G: networkx.Graph, width: int, rand_state: numpy.random.RandomState | None = None) Set[int] | Set[str]

Generates a random set of nodes that form a connected subgraph of a specified width from a given graph.

Parameters

Gnetworkx.Graph

The graph from which to generate the connected subgraph.

widthint

The target width of the subgraph to be generated.

rand_stateOptional[_np.random.RandomState]

A random state for reproducibility. Default is None.

Returns

set[int or str]

A set of nodes representing the generated connected subgraph.