pygsti.layouts.distlayout.DistributableCOPALayout

Contents

pygsti.layouts.distlayout.DistributableCOPALayout#

class DistributableCOPALayout(circuits, unique_circuits, to_unique, unique_complete_circuits, create_atom_fn, create_atom_args, num_atom_processors, num_param_dimension_processors=(), param_dimensions=(), param_dimension_blk_sizes=(), resource_alloc=None, verbosity=0)#

Bases: CircuitOutcomeProbabilityArrayLayout

A circuit-outcome-probability-array (COPA) layout that is distributed among many processors.

This layout divides the work of computing arrays with one dimension corresponding to the layout’s “elements” (circuit outcomes) and 0, 1, or 2 parameter dimensions corresponding to first or second derivatives of a by-element quantity with respect to a model’s parameters.

The size of element dimension is given by the number of unique circuits and the outcomes retained for each circuit. Computation along the element dimension is broken into “atoms”, which hold a slice that indexes the element dimension along with the necessary information (used by a forward simulator) to compute those elements. This often includes the circuits and outcomes an atom’s elements correspond to, and perhaps precomputed structures for speeding up the circuit computation. An atom-creating function is used to initialize a DistributableCOPALayout.

Technical note: the atoms themselves determine which outcomes for each circuit are included in the layout, so the layout doesn’t know how many elements it contains until the atoms are created. This makes for an awkward _update_indices callback that adjusts an atom’s indices based on the selected circuits of the (local) layout, since this selection can only be performed after the atoms are created.

The size of the parameter dimensions is given directly via the param_dimensions argument. These dimensions are divided into “blocks” (slices of the entire dimension) but there is no analogous atom-like object for the blocks, as there isn’t any need to hold meta-data specific to a block. The size of the parameter-blocks is essentially constant along each parameter dimension, and specified by the param_dimension_blk_sizes argument.

Along each of the (possible) array dimensions, we also assign a number of atom (for the element dimension) or block (for the parameter dimensions) “processors”. These are not physical CPUs but are logical objects act by processing atoms or blocks, respectively. A single atom processor is assigned one or more atoms to process, and similarly with block processors.

The total number of physical processors, N, is arranged in a grid so that:

N = num_atom_processors x num_param1_processors x num_param2_processors

This may restricts the allowed values of N is the number of atom/block processors is fixed or constrained. The reason there are 2 levels of “breaking up” the computation are so that intermediate memory may be controlled. If we merged the notion of atoms and atom-processors, for instance, so that each atom processor always had exactly 1 atom to process, then the only way to divide up a computation would be to use more processors. Since computations can involve intermediate memory usage that far exceeds the memory required to hold the results, it is useful to be able to break up a computation into chunks even when there is, e.g., just a single processor. Separating atom/blocks from atom-processors and param-block-processors allow us to divide a computation into chunks that use manageable amounts of intermediate memory regardless of the number of processors available. When intermediate memory is not a concern, then there is no reason to assign more than one atom/block to it’s corresponding processor type.

When creating a DistributableCOPALayout the caller can separately specify the number of atoms (length of create_atom_args) or the size of parameter blocks and the number of atom-processors or the number of param-block-processors.

Furthermore, a ResourceAllocation object can be given that specifies a shared-memory structure to the physical processors, where the total number of cores is divided into node-groups that are able to share memory. The total number of cores is divided like this:

  • first, we divide the cores into atom-processing groups, i.e. “atom-processors”. An atom-processor is most accurately seen as a comm (group of processors). If shared memory is being used, either the entire atom-processor must be contained within a single node OR the atom-processor must contain an integer number of nodes (it cannot contain a mixed fractional number of nodes, e.g. 1+1/2).

  • each atom processor is divided into param1-processors, which process sections arrays within that atom processor’s element slice and within the param1-processors parameter slice. Similarly, each param1-processor cannot contain a mixed fraction number of nodes - it must be a fraction < 1 or an integer number of nodes.

  • each param1-processor is divided into param2-processors, with exactly the same rules as for the param1-processors.

These nested MPI communicators neatly divide up the entries of arrays that have shape (nElements, nParams1, nParams2) or arrays with fewer dimensions, in which case processors that would have computed different entries of a missing dimension just duplicate the computation of array entries in the existing dimensions.

Arrays will also be used that do not have a leading nElements dimension (e.g. when element-contributions have been summed over), with shapes involving just the parameter dimensions. For these arrays, we also construct a “fine” processor grouping where all the cores are divided among the (first) parameter dimension. The array types “jtf” and “jtj” are distributed according to this “fine” grouping.

Parameters:
  • circuits (list of Circuits) – The circuits whose outcome probabilities are to be computed. This list may contain duplicates.

  • unique_circuits (list of Circuits) – The same as circuits, except duplicates are removed. Often this value is obtained by a derived class calling the class method _compute_unique_circuits().

  • to_unique (dict) – A mapping that translates an index into circuits to one into unique_circuits. Keys are the integers 0 to len(circuits) and values are indices into unique_circuits.

  • unique_complete_circuits (list, optional) – A list, parallel to unique_circuits, that contains the “complete” version of these circuits. This information is currently unused, and is included for potential future expansion and flexibility.

  • create_atom_fn (function) – A function that creates an atom when given one of the elements of create_atom_args.

  • create_atom_args (list) – A list of tuples such that each element is a tuple of arguments for create_atom_fn. The length of this list specifies the number of atoms, and the caller must provide the same list on all processors. When the layout is created, create_atom_fn will be used to create some subset of the atoms on each processor.

  • num_atom_processors (int) – The number of “atom processors”. An atom processor is not a physical processor, but a group of physical processors that is assigned one or more of the atoms (see above).

  • num_param_dimension_processors (tuple, optional) – A 1- or 2-tuple of integers specifying how many parameter-block processors (again, not physical processors, but groups of processors that are assigned to parameter blocks) are used when dividing the physical processors into a grid. The first and second elements correspond to counts for the first and second parameter dimensions, respectively.

  • param_dimensions (tuple, optional) – The full (global) number of parameters along each parameter dimension. Can be an empty, 1-, or 2-tuple of integers which dictates how many parameter dimensions this layout supports.

  • param_dimension_blk_sizes (tuple, optional) – The parameter block sizes along each present parameter dimension, so this should be the same shape as param_dimensions. A block size of None means that there should be no division into blocks, and that each block processor computes all of its parameter indices at once.

  • resource_alloc (ResourceAllocation, optional) – The resources available for computing circuit outcome probabilities.

  • verbosity (int or VerbosityPrinter) – Determines how much output to send to stdout. 0 means no output, higher integers mean more output.

Methods

__init__(circuits, unique_circuits, ...[, ...])

add_mongodb_write_ops(write_ops, mongodb[, ...])

Accumulate write and update operations for writing this object to a MongoDB database.

allgather_local_array(array_type, array_portion)

Gathers an array onto all the processors.

allocate_local_array(array_type, dtype[, ...])

Allocate an array that is distributed according to this layout.

allsum_local_quantity(typ, value[, ...])

Gathers an array onto all the processors.

copy()

Create a copy of this layout.

create_from(circuits[, model, dataset, ...])

Creates a simple layout from a list of circuits.

distribution_info(nprocs)

Generates information about how this layout is distributed across multiple processors.

dump(f[, format])

Serializes and writes this object to a given output stream.

dumps([format])

Serializes this object and returns it as a string.

fill_jtf(j, f, jtf)

Calculate the matrix-vector product j.T @ f.

fill_jtj(j, jtj[, shared_mem_buf])

Calculate the matrix-matrix product j.T @ j.

free_local_array(local_array)

Frees an array allocated by allocate_local_array().

from_mongodb(mongodb, doc_id, **kwargs)

Create and initialize an object from a MongoDB instance.

from_mongodb_doc(mongodb, collection_name, ...)

Create and initialize an object from a MongoDB instance and pre-loaded primary document.

from_nice_serialization(state)

Create and initialize an object from a "nice" serialization.

gather_local_array(array_type, array_portion)

Gathers an array onto the root processor.

gather_local_array_base(array_type, ...[, ...])

Gathers an array onto the root processor or all the processors.

indices(circuit)

The element indices corresponding to a circuit in this layout.

indices_and_outcomes(circuit)

The element indices and outcomes corresponding to a circuit in this layout.

indices_and_outcomes_for_index(index)

Lookup the element indices and outcomes corresponding to a given circuit by the circuit's index.

indices_for_index(index)

Lookup the element indices corresponding to a given circuit by the circuit's index.

iter_unique_circuits()

Iterate over the element-indices, circuit, and outcomes of each unique circuit in this layout.

load(f[, format])

Load an object of this type, or a subclass of this type, from an input stream.

loads(s[, format])

Load an object of this type, or a subclass of this type, from a string.

memory_estimate(array_type[, dtype])

Memory required to allocate an array of a given type (in bytes).

outcomes(circuit)

The outcome labels of a circuit in this layout.

outcomes_for_index(index)

Lookup the outcomes of a given circuit by the circuit's index.

read(path[, format])

Read an object of this type, or a subclass of this type, from a file.

remove_from_mongodb(mongodb, doc_id[, ...])

Remove the documents corresponding to an instance of this class from a MongoDB database.

remove_me_from_mongodb(mongodb[, session, ...])

resource_alloc([sub_alloc_name, ...])

Retrieves the resource-allocation objectfor this layout.

to_nice_serialization()

Serialize this object in a way that adheres to "niceness" rules of common text file formats.

write(path, **format_kwargs)

Writes this object to a file.

write_to_mongodb(mongodb[, session, ...])

Write this object to a MongoDB database.

Attributes

collection_name

global_layout

The global layout that this layout is or is a part of.

max_atom_cachesize

The largest cache size among all this layout's atoms

max_atom_elements

The most elements owned by a single atom.

num_circuits

The total number of circuits in this layout.

num_elements

The total number of elements in this layout.

add_mongodb_write_ops(write_ops, mongodb, overwrite_existing=False, **kwargs)#

Accumulate write and update operations for writing this object to a MongoDB database.

Similar to write_to_mongodb() but collects write operations instead of actually executing any write operations on the database. This function may be preferred to write_to_mongodb() when this object is being written as a part of a larger entity and executing write operations is saved until the end.

As in write_to_mongodb(), self.collection_name is the collection name and _id is either: 1) the ID used by a previous write or initial read-in, if one exists, OR 2) a new random bson.objectid.ObjectId

Parameters:
  • write_ops (WriteOpsByCollection) – An object that keeps track of pymongo write operations on a per-collection basis. This object accumulates write operations to be performed at some point in the future.

  • mongodb (pymongo.database.Database) – The MongoDB instance to write data to.

  • overwrite_existing (bool, optional) – Whether existing documents should be overwritten. The default of False causes a ValueError to be raised if a document with the given _id already exists and is different from what is being written.

  • **kwargs (dict) – Additional keyword arguments potentially used by subclass implementations. Any arguments allowed by a subclass’s _add_auxiliary_write_ops_and_update_doc method is allowed here.

Returns:

The identifier (_id value) of the main document that was written.

Return type:

bson.objectid.ObjectId

allgather_local_array(array_type, array_portion, extra_elements=0, return_shared=False)#

Gathers an array onto all the processors.

Gathers the portions of an array that was distributed using this layout (i.e. according to the host_element_slice, etc. slices in this layout). This could be an array allocated by allocate_local_array() but need not be, as this routine does not require that array_portion be shared. Arrays can be 1, 2, or 3-dimensional. The dimensions are understood to be along the “element”, “parameter”, and “2nd parameter” directions in that order.

Parameters:
  • array_portion (numpy.ndarray) – The portion of the final array that is local to the calling processor. This could be a shared memory array, but just needs to be of the correct size.

  • extra_elements (int, optional) – The number of additional “extra” elements to append to the element dimension, beyond those called for by this layout. Should match usage in allocate_local_array().

  • return_shared (bool, optional) – If True then, when shared memory is being used, the shared array used to accumulate the gathered results is returned directly along with its shared-memory handle (None if shared memory isn’t used). This results in a small performance gain.

Returns:

  • result (numpy.ndarray or None) – The full (global) output array.

  • shared_memory_handle (multiprocessing.shared_memory.SharedMemory or None) – Returned only when return_shared == True. The shared memory handle associated with result, which is needed to free the memory.

allocate_local_array(array_type, dtype, zero_out=False, memory_tracker=None, extra_elements=0)#

Allocate an array that is distributed according to this layout.

Creates an array for holding elements and/or derivatives with respect to model parameters, possibly distributed among multiple processors as dictated by this layout.

Parameters:
  • array_type (("e", "ep", "ep2", "epp", "p", "jtj", "jtf", "c", "cp", "cp2", "cpp")) – The type of array to allocate, often corresponding to the array shape. Let nE be the layout’s number of elements, nP1 and nP2 be the number of parameters we differentiate with respect to (for first and second derivatives), and nC be the number of circuits. Then the array types designate the following array shapes: - “e”: (nE,) - “ep”: (nE, nP1) - “ep2”: (nE, nP2) - “epp”: (nE, nP1, nP2) - “p”: (nP1,) - “jtj”: (nP1, nP2) - “jtf”: (nP1,) - “c”: (nC,) - “cp”: (nC, nP1) - “cp2”: (nC, nP2) - “cpp”: (nC, nP1, nP2) Note that, even though the “p” and “jtf” types are the same shape they are used for different purposes and are distributed differently when there are multiple processors. The “p” type is for use with other element-dimensions-containing arrays, whereas the “jtf” type assumes that the element dimension has already been summed over.

  • dtype (numpy.dtype) – The NumPy data type for the array.

  • zero_out (bool, optional) – Whether the array should be zeroed out initially.

  • memory_tracker (ResourceAllocation, optional) – If not None, the amount of memory being allocated is added, using add_tracked_memory() to this resource allocation object.

  • extra_elements (int, optional) – The number of additional “extra” elements to append to the element dimension, beyond those called for by this layout. Such additional elements are used to store penalty terms that are treated by the objective function just like usual outcome-probability-type terms.

Returns:

An array that looks and acts just like a normal NumPy array, but potentially with internal handles to utilize shared memory.

Return type:

LocalNumpyArray

allsum_local_quantity(typ, value, use_shared_mem='auto')#

Gathers an array onto all the processors.

Gathers the portions of an array that was distributed using this layout (i.e. according to the host_element_slice, etc. slices in this layout). This could be an array allocated by allocate_local_array() but need not be, as this routine does not require that array_portion be shared. Arrays can be 1, 2, or 3-dimensional. The dimensions are understood to be along the “element”, “parameter”, and “2nd parameter” directions in that order.

Parameters:
  • array_portion (numpy.ndarray) – The portion of the final array that is local to the calling processor. This could be a shared memory array, but just needs to be of the correct size.

  • extra_elements (int, optional) – The number of additional “extra” elements to append to the element dimension, beyond those called for by this layout. Should match usage in allocate_local_array().

  • return_shared (bool, optional) – If True then, when shared memory is being used, the shared array used to accumulate the gathered results is returned directly along with its shared-memory handle (None if shared memory isn’t used). This results in a small performance gain.

Returns:

  • result (numpy.ndarray or None) – The full (global) output array.

  • shared_memory_handle (multiprocessing.shared_memory.SharedMemory or None) – Returned only when return_shared == True. The shared memory handle associated with result, which is needed to free the memory.

copy()#

Create a copy of this layout.

Return type:

MatrixCOPALayout

classmethod create_from(circuits, model=None, dataset=None, param_dimensions=(), resource_alloc=None)#

Creates a simple layout from a list of circuits.

Optionally, a model can be used to “complete” (add implied prep or POVM layers) circuits, and a dataset to restrict the layout’s elements to the observed outcomes.

Parameters:
  • circuits (list of Circuits) – The circuits to include in the layout. Note that the produced layout may not retain the ordering of these circuits internally, but that it’s .global_layout does.

  • model (Model, optional) – A model used to “complete” the circuits (add implied prep and/or POVM layers). Usually this is a/the model that will be used to compute outcomes probabilities using this layout. If None, then each element of circuits is assumed to be a complete circuit, i.e., to begin with a state preparation layer and end with a POVM layer.

  • dataset (DataSet, optional) – If not None, restrict what is simplified to only those probabilities corresponding to non-zero counts (observed outcomes) in this data set.

  • param_dimensions (tuple, optional) – A tuple containing, optionally, the parameter-space dimension used when taking first and second derivatives with respect to the circuit outcome probabilities.

  • resource_alloc (ResourceAllocation, optional) – The resources available for computing circuit outcome probabilities.

Return type:

CircuitOutcomeProbabilityArrayLayout

distribution_info(nprocs)#

Generates information about how this layout is distributed across multiple processors.

This is useful when comparing and selecting a layout, as this information can be used to compute the amount of required memory per processor.

Parameters:

nprocs (int) – The number of processors.

Return type:

dict

dump(f, format='json', **format_kwargs)#

Serializes and writes this object to a given output stream.

Parameters:
  • f (file-like) – A writable output stream.

  • format ({'json', 'repr'}) – The format to write.

  • format_kwargs (dict, optional) – Additional arguments specific to the format being used. For example, the JSON format accepts indent as an argument because json.dump does.

Return type:

None

dumps(format='json', **format_kwargs)#

Serializes this object and returns it as a string.

Parameters:
  • format ({'json', 'repr'}) – The format to write.

  • format_kwargs (dict, optional) – Additional arguments specific to the format being used. For example, the JSON format accepts indent as an argument because json.dump does.

Return type:

str

fill_jtf(j, f, jtf)#

Calculate the matrix-vector product j.T @ f.

Here j is often a jacobian matrix, and f a vector of objective function term values. j and f must be local arrays, created with allocate_local_array(). This function performs any necessary MPI/shared-memory communication when the arrays are distributed over multiple processors.

Parameters:
  • j (LocalNumpyArray) – A local 2D array (matrix) allocated using allocate_local_array with the “ep” (jacobian) type.

  • f (LocalNumpyArray) – A local array allocated using allocate_local_array with the “e” (element array) type.

  • jtf (LocalNumpyArray) – The result. This must be a pre-allocated local array of type “jtf”.

Return type:

None

fill_jtj(j, jtj, shared_mem_buf=None)#

Calculate the matrix-matrix product j.T @ j.

Here j is often a jacobian matrix, so the result is an approximate Hessian. This function performs any necessary MPI/shared-memory communication when the arrays are distributed over multiple processors.

Parameters:
  • j (LocalNumpyArray) – A local 2D array (matrix) allocated using allocate_local_array with the “ep” (jacobian) type.

  • jtj (LocalNumpyArray) – The result. This must be a pre-allocated local array of type “jtj”.

Return type:

None

free_local_array(local_array)#

Frees an array allocated by allocate_local_array().

This method should always be paired with a call to allocate_local_array(), since the allocated array may utilize shared memory, which must be explicitly de-allocated.

Parameters:

local_array (numpy.ndarray or LocalNumpyArray) – The array to free, as returned from allocate_local_array.

Return type:

None

classmethod from_mongodb(mongodb, doc_id, **kwargs)#

Create and initialize an object from a MongoDB instance.

Parameters:
  • mongodb (pymongo.database.Database) – The MongoDB instance to load from.

  • doc_id (bson.objecctid.ObjectId or dict) – The object ID or filter used to find a single object ID within the database. This document is loaded from the collection given by the collection_name attribute of this class.

  • **kwargs (dict) – Additional keyword arguments potentially used by subclass implementations. Any arguments allowed by a subclass’s _create_obj_from_doc_and_mongodb method is allowed here.

Return type:

object

classmethod from_mongodb_doc(mongodb, collection_name, doc, **kwargs)#

Create and initialize an object from a MongoDB instance and pre-loaded primary document.

Parameters:
  • mongodb (pymongo.database.Database) – The MongoDB instance to load from.

  • collection_name (str) – The collection name within mongodb that doc was loaded from. This is needed for the sole purpose of setting the created (returned) object’s database “coordinates”.

  • doc (dict) – The already-retrieved main document for the object being loaded. This takes the place of giving an identifier for this object.

  • **kwargs (dict) – Additional keyword arguments potentially used by subclass implementations. Any arguments allowed by a subclass’s _create_obj_from_doc_and_mongodb method is allowed here.

Return type:

object

classmethod from_nice_serialization(state)#

Create and initialize an object from a “nice” serialization.

A “nice” serialization here means one created by a prior call to to_nice_serialization using this class or a subclass of it. Nice serializations adhere to additional rules (e.g. that dictionary keys must be strings) that make them amenable to common file formats (e.g. JSON).

The state argument is typically a dictionary containing ‘module’ and ‘state’ keys specifying the type of object that should be created. This type must be this class or a subclass of it.

Parameters:

state (object) – An object, usually a dictionary, representing the object to de-serialize.

Return type:

object

gather_local_array(array_type, array_portion, extra_elements=0, return_shared=False)#

Gathers an array onto the root processor.

Gathers the portions of an array that was distributed using this layout (i.e. according to the host_element_slice, etc. slices in this layout). This could be an array allocated by allocate_local_array() but need not be, as this routine does not require that array_portion be shared. Arrays can be 1, 2, or 3-dimensional. The dimensions are understood to be along the “element”, “parameter”, and “2nd parameter” directions in that order.

Parameters:
  • array_portion (numpy.ndarray) – The portion of the final array that is local to the calling processor. This could be a shared memory array, but just needs to be of the correct size.

  • extra_elements (int, optional) – The number of additional “extra” elements to append to the element dimension, beyond those called for by this layout. Should match usage in allocate_local_array().

  • return_shared (bool, optional) – If True then, when shared memory is being used, the shared array used to accumulate the gathered results is returned directly along with its shared-memory handle (None if shared memory isn’t used). This results in a small performance gain.

Returns:

  • result (numpy.ndarray or None) – The full (global) output array on the root (rank=0) processor and None on all other processors.

  • shared_memory_handle (multiprocessing.shared_memory.SharedMemory or None) – Returned only when return_shared == True. The shared memory handle associated with result, which is needed to free the memory.

gather_local_array_base(array_type, array_portion, extra_elements=0, all_gather=False, return_shared=False)#

Gathers an array onto the root processor or all the processors.

Gathers the portions of an array that was distributed using this layout (i.e. according to the host_element_slice, etc. slices in this layout). This could be an array allocated by allocate_local_array() but need not be, as this routine does not require that array_portion be shared. Arrays can be 1, 2, or 3-dimensional. The dimensions are understood to be along the “element”, “parameter”, and “2nd parameter” directions in that order.

Parameters:
  • array_type (("e", "ep", "ep2", "epp", "p", "jtj", "jtf", "c", "cp", "cp2", "cpp")) – The type of array to allocate, often corresponding to the array shape. See allocate_local_array() for a more detailed description.

  • array_portion (numpy.ndarray) – The portion of the final array that is local to the calling processor. This should be a shared memory array when a resource_alloc with shared memory enabled was used to construct this layout.

  • extra_elements (int, optional) – The number of additional “extra” elements to append to the element dimension, beyond those called for by this layout. Should match usage in allocate_local_array().

  • all_gather (bool, optional) – Whether the result should be returned on all the processors (when all_gather=True) or just the rank-0 processor (when all_gather=False).

  • return_shared (bool, optional) – Whether the returned array is allowed to be a shared-memory array, which results in a small performance gain because the array used internally to gather the results can be returned directly. When True a shared memory handle is also returned, and the caller assumes responsibility for freeing the memory via pygsti.tools.sharedmemtools.cleanup_shared_ndarray().

Returns:

  • gathered_array (numpy.ndarray or None) – The full (global) output array on the root (rank=0) processor and None on all other processors, unless all_gather == True, in which case the array is returned on all the processors.

  • shared_memory_handle (multiprocessing.shared_memory.SharedMemory or None) – Returned only when return_shared == True. The shared memory handle associated with gathered_array, which is needed to free the memory.

indices(circuit)#

The element indices corresponding to a circuit in this layout.

This is a slice into the element-dimension of arrays allocated using this layout, e.g. an ‘e’-type array allocated by allocate_local_array(). The entries of such an array correspond to different outcomes of this circuit, which are separately given by outcomes() or alongside the indices in indices_and_outcomes().

Parameters:

circuit (Circuit) – The circuit to lookup element indices of.

Return type:

slice

indices_and_outcomes(circuit)#

The element indices and outcomes corresponding to a circuit in this layout.

Returns both the element indices and outcome labels corresponding to a circuit in this layout. These quantities can be separately obtained using the indices() and outcomes() methods, respectively.

Parameters:

circuit (Circuit) – The circuit to lookup element indices and outcomes of.

Returns:

  • element_indices (slice)

  • outcome_labels (tuple)

indices_and_outcomes_for_index(index)#

Lookup the element indices and outcomes corresponding to a given circuit by the circuit’s index.

Similar to indices_and_outcomes() but uses a circuit’s index within this layout directly, thus avoiding having to hash a Circuit object and gaining a modicum of performance.

Parameters:

index (int) – The index of a circuit within this layout, i.e., within self.circuits.

Returns:

  • element_indices (slice)

  • outcome_labels (tuple)

indices_for_index(index)#

Lookup the element indices corresponding to a given circuit by the circuit’s index.

Similar to indices() but uses a circuit’s index within this layout directly, thus avoiding having to hash a Circuit object and gaining a modicum of performance.

Parameters:

index (int) – The index of a circuit within this layout, i.e., within self.circuits.

Return type:

slice

iter_unique_circuits()#

Iterate over the element-indices, circuit, and outcomes of each unique circuit in this layout.

A generator used to iterate over a (element_indices, circuit, outcomes) tuple for each unique circuit held by this layout, where element_indices and outcomes are the values that would be retrieved by the indices() and outcomes() methods, and circuit is the unique circuit itself.

Return type:

generator

classmethod load(f, format='json')#

Load an object of this type, or a subclass of this type, from an input stream.

Parameters:
  • f (file-like) – An open input stream to read from.

  • format ({'json'}) – The format of the input stream data.

Return type:

NicelySerializable

classmethod loads(s, format='json')#

Load an object of this type, or a subclass of this type, from a string.

Parameters:
  • s (str) – The serialized object.

  • format ({'json'}) – The format of the string data.

Return type:

NicelySerializable

memory_estimate(array_type, dtype='d')#

Memory required to allocate an array of a given type (in bytes).

Parameters:
  • array_type ({'e', 'ep', 'epp'}) – The type of array. This string specifies the shape of the array, with ‘e’ indicating dimension holding the layout’s elements and ‘p’ indicating parameter dimensions.

  • dtype (numpy.dtype) – The NumPy data type for the array.

Returns:

The memory that would be required, in bytes.

Return type:

int

outcomes(circuit)#

The outcome labels of a circuit in this layout.

Parameters:

circuit (Circuit) – The circuit to lookup outcome labels of.

Return type:

tuple

outcomes_for_index(index)#

Lookup the outcomes of a given circuit by the circuit’s index.

Similar to outcomes() but uses a circuit’s index within this layout directly, thus avoiding having to hash a Circuit object and gaining a modicum of performance.

Parameters:

index (int) – The index of a circuit within this layout, i.e., within self.circuits.

Return type:

tuple

classmethod read(path, format=None)#

Read an object of this type, or a subclass of this type, from a file.

Parameters:
  • path (str or Path or file-like) – The filename to open or an already open input stream.

  • format ({'json', None}) – The format of the file. If None this is determined automatically by the filename extension of a given path.

Return type:

NicelySerializable

classmethod remove_from_mongodb(mongodb, doc_id, collection_name=None, session=None, recursive='default')#

Remove the documents corresponding to an instance of this class from a MongoDB database.

Parameters:
  • mongodb (pymongo.database.Database) – The MongoDB instance to remove documents from.

  • doc_id (bson.objectid.ObjectId) – The identifier of the root document stored in the database.

  • collection_name (str, optional) – the MongoDB collection within mongodb where the main document resides. If None, then <this_class>.collection_name is used (which is usually what you want).

  • session (pymongo.client_session.ClientSession, optional) – MongoDB session object to use when interacting with the MongoDB database. This can be used to implement transactions among other things.

  • recursive (RecursiveRemovalSpecification, optional) – An object that filters the type of documents that are removed. Used when working with inter-related experiment designs, data, and results objects to only remove the types of documents you know aren’t being shared with other documents.

Return type:

None

resource_alloc(sub_alloc_name=None, empty_if_missing=True)#

Retrieves the resource-allocation objectfor this layout.

Sub-resource-allocations can also be obtained by passing a non-None sub_alloc_name.

Parameters:
  • sub_alloc_name (str) – The name to retrieve

  • empty_if_missing (bool) – When True, an empty resource allocation object is returned when sub_alloc_name doesn’t exist for this layout. Otherwise a KeyError is raised when this occurs.

Return type:

ResourceAllocation

to_nice_serialization()#

Serialize this object in a way that adheres to “niceness” rules of common text file formats.

Returns:

Usually a dictionary representing the serialized object, but may also be another native Python type, e.g. a string or list.

Return type:

object

write(path, **format_kwargs)#

Writes this object to a file.

Parameters:
  • path (str or Path) – The name of the file that is written.

  • format_kwargs (dict, optional) – Additional arguments specific to the format being used. For example, the JSON format accepts indent as an argument because json.dump does.

Return type:

None

write_to_mongodb(mongodb, session=None, overwrite_existing=False, **kwargs)#

Write this object to a MongoDB database.

The collection name used is self.collection_name, and the _id is either: 1) the ID used by a previous write or initial read-in, if one exists, OR 2) a new random bson.objectid.ObjectId

Parameters:
  • mongodb (pymongo.database.Database) – The MongoDB instance to write data to.

  • session (pymongo.client_session.ClientSession, optional) – MongoDB session object to use when interacting with the MongoDB database. This can be used to implement transactions among other things.

  • overwrite_existing (bool, optional) – Whether existing documents should be overwritten. The default of False causes a ValueError to be raised if a document with the given _id already exists and is different from what is being written.

  • **kwargs (dict) – Additional keyword arguments potentially used by subclass implementations. Any arguments allowed by a subclass’s _add_auxiliary_write_ops_and_update_doc method is allowed here.

Returns:

The identifier (_id value) of the main document that was written.

Return type:

bson.objectid.ObjectId

property global_layout#

The global layout that this layout is or is a part of. Cannot be comm-dependent.

property max_atom_cachesize#

The largest cache size among all this layout’s atoms

property max_atom_elements#

The most elements owned by a single atom.

property num_circuits#

The total number of circuits in this layout. In a multi-processor context, the number of circuits locally owned by the current processor.

property num_elements#

The total number of elements in this layout. In a multi-processor context, the number of elements locally owned by the current processor.