:py:mod:`pygsti.circuits.subcircuit_selection` ============================================== .. py:module:: pygsti.circuits.subcircuit_selection .. autoapi-nested-parse:: Utility functions for subcircuit selection Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: pygsti.circuits.subcircuit_selection.HasGetMethod Functions ~~~~~~~~~ .. autoapisummary:: pygsti.circuits.subcircuit_selection.sample_subcircuits pygsti.circuits.subcircuit_selection.simple_weighted_subcirc_selection pygsti.circuits.subcircuit_selection.greedy_growth_subcirc_selection pygsti.circuits.subcircuit_selection.random_connected_subgraph Attributes ~~~~~~~~~~ .. autoapisummary:: pygsti.circuits.subcircuit_selection.MAX_STARTING_LAYER_ATTEMPTS .. py:data:: MAX_STARTING_LAYER_ATTEMPTS :value: '1000' .. py:class:: HasGetMethod Bases: :py:obj:`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: ... .. py:method:: get(qubits: List[int]) -> float .. py:function:: sample_subcircuits(full_circs: Union[pygsti.circuits.circuit.Circuit, List[pygsti.circuits.circuit.Circuit]], width_depths: Dict[int, List[int]], coupling_map: Union[str, List[int], List[str], qiskit.transpiler.CouplingMap], instruction_durations: Union[qiskit.transpiler.InstructionDurations, HasGetMethod], use_qiskit_for_instruction_durations: Optional[bool] = None, num_samples_per_width_depth: int = 10, strategy: Union[Literal['simple', 'greedy'], Callable[Ellipsis, Any]] = 'simple', strategy_args: Optional[dict] = None, depth_metric: Literal['layer_count', 'falcon_depth'] = 'layer_count', num_test_samples: Optional[int] = None, rand_state: Optional[numpy.random.RandomState] = None) -> pygsti.protocols.protocol.FreeformDesign Samples subcircuits from a full circuit based on specified width and depth pairs. Parameters ------------- full_circs : Union[pygsti.circuits.Circuit, List[pygsti.circuits.Circuit]] The full circuit(s) from which to sample subcircuits. width_depths : Dict[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_map : Union[str, qiskit.transpiler.CouplingMap] The coupling map defining the connectivity of qubits. Can be 'all-to-all', 'linear', or a qiskit CouplingMap object. instruction_durations : qiskit.transpiler.InstructionDurations A qiskit InstructionDurations object used to determine delay times for idle subcircuit layers. use_qiskit_for_instruction_durations : bool, 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_depth : int, optional The number of subcircuits to sample for each width-depth combination. Default is 10. strategy : Union[str, Callable[..., Any]], optional The subcircuit sampling strategy to use ('simple', 'greedy', or a custom function). Default is 'simple'. strategy_args : Dict, optional Additional arguments if a custom sampling strategy function is used. Default is None. depth_metric : str, 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_samples : int, 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. .. py:function:: simple_weighted_subcirc_selection(full_circ: pygsti.circuits.circuit.Circuit, width: int, depth: int, num_subcircs: int, coupling_map: Union[str, List[int], List[str], qiskit.transpiler.CouplingMap], instruction_durations: Union[qiskit.transpiler.InstructionDurations, HasGetMethod], use_qiskit_for_instruction_durations: Optional[bool] = None, depth_metric: Literal['layer_count', 'falcon_depth'] = 'layer_count', rand_state: Optional[numpy.random.RandomState] = None, return_depth_info: bool = False, stochastic_2q_drops: bool = False, verbosity: Literal[0, 1] = 1) -> List[List[pygsti.circuits.circuit.Circuit], List[int], Optional[List[int]], Optional[List[Tuple[int, int]]], Optional[List[int]], Optional[List[List[int]]]] 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_circs : Union[pygsti.circuits.Circuit, List[pygsti.circuits.Circuit]] The full circuit(s) from which to sample subcircuits. width : int width of subcircuit to snip out. depth: int depth of subcircuit to snip out. num_subcircs : int The number of subcircuits to snip out for the given width and depth. coupling_map : Union[str, qiskit.transpiler.CouplingMap] The coupling map defining the connectivity of qubits. Can be 'all-to-all', 'linear', or a qiskit CouplingMap object. instruction_durations : qiskit.transpiler.InstructionDurations A qiskit InstructionDurations object used to determine delay times for idle subcircuit layers. use_qiskit_for_instruction_durations : bool, 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_info : bool, optional Whether to include compiled depths and the start and end layer for each subcircuit. Default is False. stochastic_2q_drops : bool, 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. verbosity : int, 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. .. py:function:: 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: Optional[numpy.random.RandomState] = None, verbosity: Literal[0, 1] = 1, return_depth_info: bool = False) -> Tuple[List[pygsti.circuits.circuit.Circuit], List[int], Optional[List[int]], Optional[List[Tuple[int, int]]]] 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_circ : pygsti.circuits.Circuit The full circuit from which to select subcircuits. width : int The target width of the subcircuits to be selected. depth : int The target depth of the subcircuits to be selected. num_subcircs : int, optional The number of subcircuits to select. Default is 1. num_test_subcircs : int, optional The number of test subcircuits to generate. Default is 10. rand_state : Optional[_np.random.RandomState], optional A random state for reproducibility. Default is None. verbosity : int, optional Level of verbosity for logging. Default is 1. return_depth_info : bool, 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. .. py:function:: random_connected_subgraph(G: networkx.Graph, width: int, rand_state: Optional[numpy.random.RandomState] = None) -> Union[Set[int], Set[str]] Generates a random set of nodes that form a connected subgraph of a specified width from a given graph. Parameters ------------- G : networkx.Graph The graph from which to generate the connected subgraph. width : int The target width of the subgraph to be generated. rand_state : Optional[_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.