:py:mod:`pygsti.algorithms.randomcircuit` ========================================= .. py:module:: pygsti.algorithms.randomcircuit .. autoapi-nested-parse:: Random circuit sampling functions. Module Contents --------------- Functions ~~~~~~~~~ .. autoapisummary:: pygsti.algorithms.randomcircuit.sample_haar_random_one_qubit_unitary_parameters pygsti.algorithms.randomcircuit.sample_random_clifford_one_qubit_unitary_parameters pygsti.algorithms.randomcircuit.sample_compiled_haar_random_one_qubit_gates_zxzxz_circuit pygsti.algorithms.randomcircuit.sample_compiled_random_clifford_one_qubit_gates_zxzxz_circuit pygsti.algorithms.randomcircuit.sample_random_cz_zxzxz_circuit pygsti.algorithms.randomcircuit.find_all_sets_of_compatible_two_q_gates pygsti.algorithms.randomcircuit.sample_circuit_layer_by_edgegrab pygsti.algorithms.randomcircuit.sample_circuit_layer_by_q_elimination pygsti.algorithms.randomcircuit.sample_circuit_layer_by_co2_q_gates pygsti.algorithms.randomcircuit.sample_circuit_layer_of_one_q_gates pygsti.algorithms.randomcircuit.create_random_circuit pygsti.algorithms.randomcircuit.create_direct_rb_circuit pygsti.algorithms.randomcircuit.create_clifford_rb_circuit pygsti.algorithms.randomcircuit.sample_pauli_layer_as_compiled_circuit pygsti.algorithms.randomcircuit.sample_one_q_clifford_layer_as_compiled_circuit pygsti.algorithms.randomcircuit.create_mirror_rb_circuit pygsti.algorithms.randomcircuit.create_random_germ pygsti.algorithms.randomcircuit.create_random_germpower_circuits pygsti.algorithms.randomcircuit.create_random_germpower_mirror_circuits pygsti.algorithms.randomcircuit.create_binary_rb_circuit pygsti.algorithms.randomcircuit.random_alternating_clifford_circ .. py:function:: sample_haar_random_one_qubit_unitary_parameters() TODO: docstring .. py:function:: sample_random_clifford_one_qubit_unitary_parameters() TODO: docstring .. py:function:: sample_compiled_haar_random_one_qubit_gates_zxzxz_circuit(pspec, zname='Gzr', xname='Gxpi2', qubit_labels=None) TODO: docstring #generate layer of random unitaries and make a series of circuit layers with the compiled versions of these .. py:function:: sample_compiled_random_clifford_one_qubit_gates_zxzxz_circuit(pspec, zname='Gzr', xname='Gxpi2', qubit_labels=None) TODO: docstring #generate layer of random unitaries and make a series of circuit layers with the compiled versions of these .. py:function:: sample_random_cz_zxzxz_circuit(pspec, length, qubit_labels=None, two_q_gate_density=0.25, one_q_gate_type='haar', two_q_gate_args_lists=None) TODO: docstring Generates a forward circuits with benchmark depth d for non-clifford mirror randomized benchmarking. The circuits alternate Haar-random 1q unitaries and layers of Gczr gates. If two_q_gate_args_lists is None, then we set it to {'Gczr': [(str(_np.pi / 2),), (str(-_np.pi / 2),)]}. .. py:function:: find_all_sets_of_compatible_two_q_gates(edgelist, n, gatename='Gcnot', aslabel=False) TODO: docstring Parameters ---------- edgelist : n : int The number of two-qubit gates to have in the set. gatename : , optional aslabel : , optional Returns ------- .. py:function:: sample_circuit_layer_by_edgegrab(pspec, qubit_labels=None, two_q_gate_density=0.25, one_q_gate_names=None, gate_args_lists=None, rand_state=None) TODO: docstring Parameters ---------- pspec : qubit_labels : , optional mean_two_q_gates : , optional modelname : , optional rand_state: RandomState, optional A np.random.RandomState object for seeding RNG Returns ------- .. py:function:: sample_circuit_layer_by_q_elimination(pspec, qubit_labels=None, two_q_prob=0.5, rand_state=None) Samples a random circuit layer by eliminating qubits one by one. This sampler works with any connectivity, but the expected number of 2-qubit gates in a layer depends on both the specified 2-qubit gate probability and the exact connectivity graph. This sampler is the following algorithm: List all the qubits, and repeat the following steps until all qubits are deleted from this list. 1) Uniformly at random pick a qubit from the list, and delete it from the list 2) Flip a coin with bias `two_q_prob` to be "Heads". 3) If "Heads" then -- if there is one or more 2-qubit gates from this qubit to other qubits still in the list -- pick one of these at random. 4) If we haven't chosen a 2-qubit gate for this qubit ("Tails" or "Heads" but there are no possible 2-qubit gates) then pick a uniformly random 1-qubit gate to apply to this qubit. Parameters ---------- pspec : QubitProcessorSpec The QubitProcessorSpec for the device that the circuit layer is being sampled for. Unless `qubit_labels` is not None, a circuit layer is sampled over all the qubits in `pspec`. qubit_labels : list, optional If not None, a list of the qubits to sample the circuit layer for. This is a subset of `pspec.qubit_labels`. If None, the circuit layer is sampled to acton all the qubits in `pspec`. two_q_prob : float, optional If a 2-qubit can is still possible on a qubit at that stage of the sampling, this is the probability a 2-qubit gate is chosen for that qubit. The expected number of 2-qubit gates per layer depend on this quantity and the connectivity graph of the device. rand_state: RandomState, optional A np.random.RandomState object for seeding RNG Returns ------- list of gates A list of gate Labels that defines a "complete" circuit layer (there is one and only one gate acting on each qubit in `pspec` or `qubit_labels`). .. py:function:: sample_circuit_layer_by_co2_q_gates(pspec, qubit_labels, co2_q_gates, co2_q_gates_prob='uniform', two_q_prob=1.0, one_q_gate_names='all', rand_state=None) Samples a random circuit layer using the specified list of "compatible two-qubit gates" (co2_q_gates). That is, the user inputs a list (`co2_q_gates`) specifying 2-qubit gates that are "compatible" -- meaning that they can be implemented simulatenously -- and a distribution over the different compatible sets, and a layer is sampled from this via: 1. Pick a set of compatible two-qubit gates from the list `co2_q_gates`, according to the distribution specified by `co2_q_gates_prob`. 2. For each 2-qubit gate in the chosen set of compatible gates, with probability `two_q_prob` add this gate to the layer. 3. Uniformly sample 1-qubit gates for any qubits that don't yet have a gate on them, from those 1-qubit gates specified by `one_q_gate_names`. For example, consider 4 qubits with linear connectivity. a valid `co2_q_gates` list is `co2_q_gates = [[,],[Label(Gcphase,(0,1)),Label(Gcphase,(2,3))]]` which consists of an element containing zero 2-qubit gates and an element containing two 2-qubit gates that can be applied in parallel. In this example there are 5 possible sets of compatible 2-qubit gates: 1. [,] (zero 2-qubit gates) 2. [Label(Gcphase,(0,1)),] (one of the three 2-qubit gate) 3. [Label(Gcphase,(1,2)),] (one of the three 2-qubit gate) 4. [Label(Gcphase,(2,3)),] (one of the three 2-qubit gate) 5. [Label(Gcphase,(0,1)), Label(Gcphase,(2,3)),] (the only compatible pair of 2-qubit gates). The list of compatible two-qubit gates `co2_q_gates` can be any list containing anywhere from 1 to all 5 of these lists. In order to allow for convenient sampling of some commonly useful distributions, `co2_q_gates` can be a list of lists of lists of compatible 2-qubit gates ("nested" sampling). In this case, a list of lists of compatible 2-qubit gates is picked according to the distribution `co2_q_gates_prob`, and then one of the sublists of compatible 2-qubit gates in the selected list is then chosen uniformly at random. For example, this is useful for sampling a layer containing one uniformly random 2-qubit gate with probability p and a layer of 1-qubit gates with probability 1-p. Here, we can specify `co2_q_gates` as `[[],[[the 1st 2Q-gate,],[the 2nd 2Q-gate,], ...]]` and set `two_q_prob=1` and `co2_q_gates_prob = [1-p,p]`. Parameters ---------- pspec : QubitProcessorSpec The QubitProcessorSpec for the device that the circuit layer is being sampled for. Unless `qubit_labels` is not None, a circuit layer is sampled over all the qubits in `pspec`. qubit_labels : list If not None, a list of the qubits to sample the circuit layer for. This is a subset of `pspec.qubit_labels`. If None, the circuit layer is sampled to act on all the qubits in `pspec`. co2_q_gates : list This is either: 1. A list of lists of 2-qubit gate Labels that can be applied in parallel. 2. A list of lists of lists of 2-qubit gate Labels that can be applied in parallel. In case (1) each list in `co2_q_gates` should contain 2-qubit gates, in the form of Labels, that can be applied in parallel and act only on the qubits in `pspec` if `qubit_labels` is None, or act only on the qubits in `qubit_labels` if `qubit_labels` is not None. The sampler then picks one of these compatible sets of gates (with probability specified by `co2_q_gates_prob`, and converts this into a circuit layer by applying the 2-qubit gates it contains with the user-specified probability `two_q_prob`, and augmenting these 2-qubit gates with 1-qubit gates on all other qubits. In case (2) a sublist of lists is sampled from `co2_q_gates` according to `co2_q_gates_prob` and then we proceed as in case (1) but as though `co2_q_gates_prob` is the uniform distribution. co2_q_gates_prob : str or list of floats If a list, they are unnormalized probabilities to sample each of the elements of `co2_q_gates`. So it is a list of non-negative floats of the same length as `co2_q_gates`. If 'uniform', then the uniform distribution is used. two_q_prob : float, optional The probability for each two-qubit gate to be applied to a pair of qubits, after a set of compatible 2-qubit gates has been chosen. The expected number of 2-qubit gates in a layer is `two_q_prob` times the expected number of 2-qubit gates in a set of compatible 2-qubit gates sampled according to `co2_q_gates_prob`. one_q_gate_names : 'all' or list of strs, optional If not 'all', a list of the names of the 1-qubit gates to be sampled from when applying a 1-qubit gate to a qubit. If this is 'all', the full set of 1-qubit gate names is extracted from the QubitProcessorSpec. rand_state: RandomState, optional A np.random.RandomState object for seeding RNG Returns ------- list of gates A list of gate Labels that defines a "complete" circuit layer (there is one and only one gate acting on each qubit). .. py:function:: sample_circuit_layer_of_one_q_gates(pspec, qubit_labels=None, one_q_gate_names='all', pdist='uniform', modelname='clifford', rand_state=None) Samples a random circuit layer containing only 1-qubit gates. The allowed 1-qubit gates are specified by `one_q_gate_names`, and the 1-qubit gates are sampled independently and uniformly. Parameters ---------- pspec : QubitProcessorSpec The QubitProcessorSpec for the device that the circuit layer is being sampled for. Unless `qubit_labels` is not None, a circuit layer is sampled over all the qubits in `pspec`. qubit_labels : list, optional If not None, a list of the qubits to sample the circuit layer for. This is a subset of `pspec.qubit_labels`. If None, the circuit layer is sampled to acton all the qubits in `pspec`. one_q_gate_names : 'all' or list of strs, optional If not 'all', a list of the names of the 1-qubit gates to be sampled from when applying a 1-qubit gate to a qubit. If this is 'all', the full set of 1-qubit gate names is extracted from the QubitProcessorSpec. pdist : 'uniform' or list of floats, optional If a list, they are unnormalized probabilities to sample each of the 1-qubit gates in the list `one_q_gate_names`. If this is not 'uniform', then oneQgatename` must not be 'all' (it must be a list so that it is unambigious which probability correpsonds to which gate). So if not 'uniform', `pdist` is a list of non-negative floats of the same length as `one_q_gate_names`. If 'uniform', then the uniform distribution over the gates is used. modelname : str, optional Only used if one_q_gate_names is 'all'. Specifies which of the `pspec.models` to use to extract the model. The `clifford` default is suitable for Clifford or direct RB, but will not use any non-Clifford gates in the model. rand_state: RandomState, optional A np.random.RandomState object for seeding RNG Returns ------- list of gates A list of gate Labels that defines a "complete" circuit layer (there is one and only one gate acting on each qubit). .. py:function:: create_random_circuit(pspec, length, qubit_labels=None, sampler='Qelimination', samplerargs=None, addlocal=False, lsargs=None, rand_state=None) Samples a random circuit of the specified length (or ~ twice this length). The created circuit's layers are independently sampled according to the specified sampling distribution. Parameters ---------- pspec : QubitProcessorSpec The QubitProcessorSpec for the device that the circuit is being sampled for. This is always handed to the sampler, as the first argument of the sampler function. Unless `qubit_labels` is not None, the circuit is sampled over all the qubits in `pspec`. length : int If `addlocal` is False, this is the length of the sampled circuit. If `addlocal is True the length of the circuits is 2*length+1 with odd-indexed layers sampled according to the sampler specified by `sampler`, and the the zeroth layer + the even-indexed layers consisting of random 1-qubit gates (with the sampling specified by `lsargs`) qubit_labels : list, optional If not None, a list of the qubits to sample the circuit for. This is a subset of `pspec.qubit_labels`. If None, the circuit is sampled to act on all the qubits in `pspec`. sampler : str or function, optional If a string, this should be one of: {'edgegrab'', 'Qelimination', 'co2Qgates', 'local'}. Except for 'local', this corresponds to sampling layers according to the sampling function in rb.sampler named circuit_layer_by* (with * replaced by 'sampler'). For 'local', this corresponds to sampling according to rb.sampler.circuit_layer_of_oneQgates. If this is a function, it should be a function that takes as the first argument a QubitProcessorSpec, and returns a random circuit layer as a list of gate Label objects. Note that the default 'Qelimination' is not necessarily the most useful in-built sampler, but it is the only sampler that requires no parameters beyond the QubitProcessorSpec *and* works for arbitrary connectivity devices. See the docstrings for each of these samplers for more information. samplerargs : list, optional A list of arguments that are handed to the sampler function, specified by `sampler`. The first argument handed to the sampler is `pspec` and `samplerargs` lists the remaining arguments handed to the sampler. For some in-built samplers this is not optional. addlocal : bool, optional If False, the circuit sampled is of length `length` and each layer is independently sampled according to the sampler specified by `sampler`. If True, the circuit sampled is of length 2*`length`+1 where: the zeroth + all even layers are consisting of independently random 1-qubit gates (with the sampling specified by `lsargs`); the odd-indexed layers are independently sampled according to `sampler`. So `length`+1 layers consist only of 1-qubit gates, and `length` layers are sampled according to `sampler`. lsargs : list, optional A list of arguments that are handed to the 1-qubit gate layers sampler rb.sampler.circuit_layer_of_oneQgates for the alternating 1-qubit-only layers that are included in the circuit if `addlocal` is True. This argument is not used if `addlocal` is false. Note that `pspec` is used as the first, and only required, argument of rb.sampler.circuit_layer_of_oneQgates. If `lsargs` = [] then all available 1-qubit gates are uniformly sampled from. To uniformly sample from only a subset of the available 1-qubit gates (e.g., the Paulis to Pauli-frame-randomize) then `lsargs` should be a 1-element list consisting of a list of the relevant gate names (e.g., `lsargs` = ['Gi, 'Gxpi, 'Gypi', 'Gzpi']). rand_state: RandomState or int, optional (default None) A np.random.RandomState object for seeding RNG. If an integer is passed in this is used to set the seed for a newly constructed RNG. Returns ------- Circuit A random circuit of length `length` (if not addlocal) or length 2*`length`+1 (if addlocal) with layers independently sampled using the specified sampling distribution. .. py:function:: create_direct_rb_circuit(pspec, clifford_compilations, length, qubit_labels=None, sampler='Qelimination', samplerargs=None, addlocal=False, lsargs=None, randomizeout=True, cliffordtwirl=True, conditionaltwirl=True, citerations=20, compilerargs=None, partitioned=False, seed=None) Generates a "direct randomized benchmarking" (DRB) circuit. DRB is the protocol introduced in arXiv:1807.07975 (2018). The length of the "core" circuit is given by `length` and may be any integer >= 0. An n-qubit DRB circuit consists of (1) a circuit the prepares a uniformly random stabilizer state; (2) a length-l circuit (specified by `length`) consisting of circuit layers sampled according to some user-specified distribution (specified by `sampler`), (3) a circuit that maps the output of the preceeding circuit to a computational basis state. See arXiv:1807.07975 (2018) for further details. Parameters ---------- pspec : QubitProcessorSpec The QubitProcessorSpec for the device that the circuit is being sampled for, which defines the "native" gate-set and the connectivity of the device. The returned DRB circuit will be over the gates in `pspec`, and will respect the connectivity encoded by `pspec`. Note that `pspec` is always handed to the sampler, as the first argument of the sampler function (this is only of importance when not using an in-built sampler for the "core" of the DRB circuit). Unless `qubit_labels` is not None, the circuit is sampled over all the qubits in `pspec`. clifford_compilation : CompilationRules Rules for compiling the "native" gates of `pspec` into Clifford gates. length : int The "direct RB length" of the circuit, which is closely related to the circuit depth. It must be an integer >= 0. Unless `addlocal` is True, it is the depth of the "core" random circuit, sampled according to `sampler`, specified in step (2) above. If `addlocal` is True, each layer in the "core" circuit sampled according to "sampler` is followed by a layer of 1-qubit gates, with sampling specified by `lsargs` (and the first layer is proceeded by a layer of 1-qubit gates), and so the circuit of step (2) is length 2*`length` + 1. qubit_labels : list, optional If not None, a list of the qubits to sample the circuit for. This is a subset of `pspec.qubit_labels`. If None, the circuit is sampled to act on all the qubits in `pspec`. sampler : str or function, optional If a string, this should be one of: {'pairingQs', 'Qelimination', 'co2Qgates', 'local'}. Except for 'local', this corresponds to sampling layers according to the sampling function in rb.sampler named circuit_layer_by* (with * replaced by 'sampler'). For 'local', this corresponds to sampling according to rb.sampler.circuit_layer_of_oneQgates [which is not a valid form of sampling for n-qubit DRB, but is not explicitly forbidden in this function]. If `sampler` is a function, it should be a function that takes as the first argument a QubitProcessorSpec, and returns a random circuit layer as a list of gate Label objects. Note that the default 'Qelimination' is not necessarily the most useful in-built sampler, but it is the only sampler that requires no parameters beyond the QubitProcessorSpec *and* works for arbitrary connectivity devices. See the docstrings for each of these samplers for more information. samplerargs : list, optional A list of arguments that are handed to the sampler function, specified by `sampler`. The first argument handed to the sampler is `pspec`, the second argument is `qubit_labels`, and `samplerargs` lists the remaining arguments handed to the sampler. This is not optional for some choices of `sampler`. addlocal : bool, optional Whether to follow each layer in the "core" circuit, sampled according to `sampler` with a layer of 1-qubit gates. lsargs : list, optional Only used if addlocal is True. A list of optional arguments handed to the 1Q gate layer sampler circuit_layer_by_oneQgate(). Specifies how to sample 1Q-gate layers. randomizeout : bool, optional If False, the ideal output of the circuit (the "success" or "survival" outcome) is the all-zeros bit string. If True, the ideal output of the circuit is randomized to a uniformly random bit-string. This setting is useful for, e.g., detecting leakage/loss/measurement-bias etc. cliffordtwirl : bool, optional Wether to begin the circuit with a sequence that generates a random stabilizer state. For standard DRB this should be set to True. There are a variety of reasons why it is better to have this set to True. conditionaltwirl : bool, optional DRB only requires that the initial/final sequences of step (1) and (3) create/measure a uniformly random / particular stabilizer state, rather than implement a particular unitary. step (1) and (3) can be achieved by implementing a uniformly random Clifford gate and the unique inversion Clifford, respectively. This is implemented if `conditionaltwirl` is False. However, steps (1) and (3) can be implemented much more efficiently than this: the sequences of (1) and (3) only need to map a particular input state to a particular output state, if `conditionaltwirl` is True this more efficient option is chosen -- this is option corresponds to "standard" DRB. (the term "conditional" refers to the fact that in this case we essentially implementing a particular Clifford conditional on a known input). citerations : int, optional Some of the stabilizer state / Clifford compilation algorithms in pyGSTi (including the default algorithms) are randomized, and the lowest-cost circuit is chosen from all the circuit generated in the iterations of the algorithm. This is the number of iterations used. The time required to generate a DRB circuit is linear in `citerations`. Lower-depth / lower 2-qubit gate count compilations of steps (1) and (3) are important in order to successfully implement DRB on as many qubits as possible. compilerargs : list, optional A list of arguments that are handed to the compile_stabilier_state/measurement()functions (or the compile_clifford() function if `conditionaltwirl `is False). This includes all the optional arguments of these functions *after* the `iterations` option (set by `citerations`). For most purposes the default options will be suitable (or at least near-optimal from the compilation methods in-built into pyGSTi). See the docstrings of these functions for more information. partitioned : bool, optional If False, a single circuit is returned consisting of the full circuit. If True, three circuits are returned in a list consisting of: (1) the stabilizer-prep circuit, (2) the core random circuit, (3) the pre-measurement circuit. In that case the full circuit is obtained by appended (2) to (1) and then (3) to (1). seed : int, optional A seed to initialize the random number generator used for creating random clifford circuits. Returns ------- Circuit or list of Circuits If partioned is False, a random DRB circuit sampled as specified. If partioned is True, a list of three circuits consisting of (1) the stabilizer-prep circuit, (2) the core random circuit, (3) the pre-measurement circuit. In that case the full circuit is obtained by appended (2) to (1) and then (3) to (1) [except in the case of cliffordtwirl=False, when it is a list of two circuits]. Tuple A length-n tuple of integers in [0,1], corresponding to the error-free outcome of the circuit. Always all zeros if `randomizeout` is False. The ith element of the tuple corresponds to the error-free outcome for the qubit labelled by: the ith element of `qubit_labels`, if `qubit_labels` is not None; the ith element of `pspec.qubit_labels`, otherwise. In both cases, the ith element of the tuple corresponds to the error-free outcome for the qubit on the ith wire of the output circuit. .. py:function:: create_clifford_rb_circuit(pspec, clifford_compilations, length, qubit_labels=None, randomizeout=False, citerations=20, compilerargs=None, interleaved_circuit=None, seed=None, return_native_gate_counts=False, exact_compilation_key=None) Generates a "Clifford randomized benchmarking" (CRB) circuit. CRB is the current-standard RB protocol defined in "Scalable and robust randomized benchmarking of quantum processes", Magesan et al. PRL 106 180504 (2011). This consists of a circuit of `length`+1 uniformly random n-qubit Clifford gates followed by the unique inversion Clifford, with all the Cliffords compiled into the "native" gates of a device as specified by `pspec`. The circuit output by this function will respect the connectivity of the device, as encoded into `pspec` (see the QubitProcessorSpec object docstring for how to construct the relevant `pspec`). Note the convention that the the output Circuit consists of `length+2` Clifford gates, rather than the more usual convention of defining the "CRB length" to be the number of Clifford gates - 1. This is for consistency with the other RB functions in pyGSTi: in all RB-circuit-generating functions in pyGSTi length zero corresponds to the minimum-length circuit allowed by the protocol. Note that changing the "RB depths" by a constant additive factor is irrelevant for fitting purposes (except that it changes the obtained "SPAM" fit parameter). Parameters ---------- pspec : QubitProcessorSpec The QubitProcessorSpec for the device that the circuit is being sampled for, which defines the "native" gate-set and the connectivity of the device. The returned CRB circuit will be over the gates in `pspec`, and will respect the connectivity encoded by `pspec`. clifford_compilations : dict A dictionary with at least the potential keys `'absolute'` and `'paulieq'` and corresponding :class:`CompilationRules` values. These compilation rules specify how to compile the "native" gates of `pspec` into Clifford gates. Additional :class:`CompilationRules` can be provided, particularly for use with `exact_compilation_key`. length : int The "CRB length" of the circuit -- an integer >= 0 -- which is the number of Cliffords in the circuit - 2 *before* each Clifford is compiled into the native gate-set. qubit_labels : list, optional If not None, a list of the qubits that the RB circuit is to be sampled for. This should be all or a subset of the qubits in the device specified by the QubitProcessorSpec `pspec`. If None, it is assumed that the RB circuit should be over all the qubits. Note that the ordering of this list is the order of the "wires" in the returned circuit, but is otherwise irrelevant. If desired, a circuit that explicitly idles on the other qubits can be obtained by using methods of the Circuit object. randomizeout : bool, optional If False, the ideal output of the circuit (the "success" or "survival" outcome) is the all-zeros bit string. This is probably considered to be the "standard" in CRB. If True, the ideal output of the circuit is randomized to a uniformly random bit-string. This setting is useful for, e.g., detecting leakage/loss/measurement-bias etc. citerations : int, optional Some of the Clifford compilation algorithms in pyGSTi (including the default algorithm) are randomized, and the lowest-cost circuit is chosen from all the circuit generated in the iterations of the algorithm. This is the number of iterations used. The time required to generate a CRB circuit is linear in `citerations` * (`length` + 2). Lower-depth / lower 2-qubit gate count compilations of the Cliffords are important in order to successfully implement CRB on more qubits. compilerargs : list, optional A list of arguments that are handed to compile_clifford() function, which includes all the optional arguments of compile_clifford() *after* the `iterations` option (set by `citerations`). In order, this list should be values for: algorithm : str. A string that specifies the compilation algorithm. The default in compile_clifford() will always be whatever we consider to be the 'best' all-round algorithm aargs : list. A list of optional arguments for the particular compilation algorithm. costfunction : 'str' or function. The cost-function from which the "best" compilation for a Clifford is chosen from all `citerations` compilations. The default costs a circuit as 10x the num. of 2-qubit gates in the circuit + 1x the depth of the circuit. prefixpaulis : bool. Whether to prefix or append the Paulis on each Clifford. paulirandomize : bool. Whether to follow each layer in the Clifford circuit with a random Pauli on each qubit (compiled into native gates). I.e., if this is True the native gates are Pauli-randomized. When True, this prevents any coherent errors adding (on average) inside the layers of each compiled Clifford, at the cost of increased circuit depth. Defaults to False. For more information on these options, see the `:func:compile_clifford()` docstring. seed : int, optional A seed to initialize the random number generator used for creating random clifford circuits. return_native_gate_counts: bool, optional Whether to return the number of native gates in the first `length`+1 compiled Cliffords exact_compilation_key: str, optional The key into `clifford_compilations` to use for exact deterministic complation of Cliffords. The underlying :class:`CompilationRules` object must provide compilations for all possible n-qubit Cliffords that will be generated. This also requires the pspec is able to generate the symplectic representations for all n-qubit Cliffords in :meth:`compute_clifford_symplectic_reps`. This is currently generally intended for use out-of-the-box with 1-qubit Clifford RB; however, larger number of qubits can be used so long as the user specifies the processor spec and compilation rules properly. Returns ------- full_circuit : Circuit A random CRB circuit over the "native" gate-set specified. idealout : tuple A length-n tuple of integers in [0,1], corresponding to the error-free outcome of the circuit. Always all zeros if `randomizeout` is False. The ith element of the tuple corresponds to the error-free outcome for the qubit labelled by: the ith element of `qubit_labels`, if `qubit_labels` is not None; the ith element of `pspec.qubit_labels`, otherwise. In both cases, the ith element of the tuple corresponds to the error-free outcome for the qubit on the ith wire of the output circuit. native_gate_counts: dict Total number of native gates, native 2q gates, and native circuit size in the first `length`+1 compiled Cliffords. Only returned when `return_num_native_gates` is True .. py:function:: sample_pauli_layer_as_compiled_circuit(pspec, absolute_compilation, qubit_labels=None, keepidle=False, rand_state=None) Samples a uniformly random n-qubit Pauli and converts it to the gate-set of `pspec`. Parameters ---------- pspec : QubitProcessorSpec The QubitProcessorSpec for the device. absolute_compilation : CompilationRules Rules for exactly (absolutely) compiling the "native" gates of `pspec` into clifford gates. qubit_labels : list, optional If not None, a list of a subset of the qubits from `pspec` that the pauli circuit should act on. keepidle : bool, optional Whether to always have the circuit at-least depth 1. rand_state: RandomState, optional A np.random.RandomState object for seeding RNG Returns ------- Circuit A circuit corresponding to a uniformly random n-qubit Pauli, converted to the native gate-set of `pspec`. .. py:function:: sample_one_q_clifford_layer_as_compiled_circuit(pspec, absolute_compilation, qubit_labels=None, rand_state=None) Samples a uniformly random layer of 1-qubit Cliffords. Create a uniformly random layer of 1-qubit Cliffords on all the qubits, and then converts it to the native gate-set of `pspec`. That is, an independent and uniformly random 1-qubit Clifford is sampled for each qubit. Parameters ---------- pspec : QubitProcessorSpec The QubitProcessorSpec for the device. absolute_compilation : CompilationRules Rules for exactly (absolutely) compiling the "native" gates of `pspec` into clifford gates. qubit_labels : list, optional If not None, a list of a subset of the qubits from `pspec` that the circuit should act on. rand_state: RandomState, optional A np.random.RandomState object for seeding RNG Returns ------- Circuit A circuit corresponding to an independent, uniformly random 1-qubit Clifford gate on each qubit. .. py:function:: create_mirror_rb_circuit(pspec, absolute_compilation, length, qubit_labels=None, sampler='Qelimination', samplerargs=None, localclifford=True, paulirandomize=True, seed=None) Generates a "mirror randomized benchmarking" (MRB) circuit. This is specific to the case of Clifford gates and can be performed, optionally, with Pauli-randomization and Clifford-twirling. This RB method is currently in development; this docstring will be updated in the future with further information on this technique. To implement mirror RB it is necessary for U^(-1) to in the gate-set for every U in the gate-set. Parameters ---------- pspec : QubitProcessorSpec The QubitProcessorSpec for the device that the circuit is being sampled for. The `pspec` is always handed to the sampler, as the first argument of the sampler function. absolute_compilation : CompilationRules Rules for exactly (absolutely) compiling the "native" gates of `pspec` into clifford gates. length : int The "mirror RB length" of the circuit, which is closely related to the circuit depth. It must be an even integer, and can be zero. If `localclifford` and `paulirandomize` are False, this is the depth of the sampled circuit. The first length/2 layers are all sampled independently according to the sampler specified by `sampler`. The remaining half of the circuit is the "inversion" circuit that is determined by the first half. If `paulirandomize` is True and `localclifford` is False, the depth of the circuits is 2*length+1 with odd-indexed layers sampled according to the sampler specified by `sampler`, and the the zeroth layer + the even-indexed layers consisting of random 1-qubit Pauli gates. If `paulirandomize` and `localclifford` are True, the depth of the circuits is 2*length+1 + X where X is a random variable (between 0 and normally <= ~12-16) that accounts for the depth from the layer of random 1-qubit Cliffords at the start and end of the circuit. If `paulirandomize` is False and `localclifford` is True, the depth of the circuits is length + X where X is a random variable (between 0 and normally <= ~12-16) that accounts for the depth from the layer of random 1-qubit Cliffords at the start and end of the circuit. qubit_labels : list, optional If not None, a list of the qubits that the RB circuit is to be sampled for. This should be all or a subset of the qubits in the device specified by the QubitProcessorSpec `pspec`. If None, it is assumed that the RB circuit should be over all the qubits. Note that the ordering of this list is the order of the "wires" in the returned circuit, but is otherwise irrelevant. sampler : str or function, optional If a string, this should be one of: {'pairingQs', 'Qelimination', 'co2Qgates', 'local'}. Except for 'local', this corresponds to sampling layers according to the sampling function in rb.sampler named circuit_layer_by* (with * replaced by 'sampler'). For 'local', this corresponds to sampling according to rb.sampler.circuit_layer_of_oneQgates [which is not a valid option for n-qubit MRB -- it results in sim. 1-qubit MRB -- but it is not explicitly forbidden by this function]. If `sampler` is a function, it should be a function that takes as the first argument a QubitProcessorSpec, and returns a random circuit layer as a list of gate Label objects. Note that the default 'Qelimination' is not necessarily the most useful in-built sampler, but it is the only sampler that requires no parameters beyond the QubitProcessorSpec *and* works for arbitrary connectivity devices. See the docstrings for each of these samplers for more information. samplerargs : list, optional A list of arguments that are handed to the sampler function, specified by `sampler`. The first argument handed to the sampler is `pspec` and `samplerargs` lists the remaining arguments handed to the sampler. localclifford : bool, optional Whether to start the circuit with uniformly random 1-qubit Cliffords and all of the qubits (compiled into the native gates of the device). paulirandomize : bool, optional Whether to have uniformly random Pauli operators on all of the qubits before and after all of the layers in the "out" and "back" random circuits. At length 0 there is a single layer of random Pauli operators (in between two layers of 1-qubit Clifford gates if `localclifford` is True); at length l there are 2l+1 Pauli layers as there are seed : int, optional A seed to initialize the random number generator used for creating random clifford circuits. Returns ------- Circuit A random MRB circuit, sampled as specified, of depth: `length`, if not paulirandomize and not local clifford. 2*`length`+1 if paulirandomize and not local clifford. `length` + X, if not paulirandomize and local clifford, where X is a random variable that accounts for the depth from the layers of random 1-qubit Cliffords (X = 2 if the 1 qubit Clifford gates are "native" gates in the QubitProcessorSpec). 2*`length`+1 + X, if paulirandomize and local clifford, where X is a random variable that accounts for the depth from the layers of random 1-qubit Cliffords (X = 2 if the 1 qubit Clifford gates are "native" gates in the QubitProcessorSpec). Tuple A length-n tuple of integers in [0,1], corresponding to the error-free outcome of the circuit. Always all zeros if `randomizeout` is False. The ith element of the tuple corresponds to the error-free outcome for the qubit labelled by: the ith element of `qubit_labels`, if `qubit_labels` is not None; the ith element of `pspec.qubit_labels`, otherwise. In both cases, the ith element of the tuple corresponds to the error-free outcome for the qubit on the ith wire of the output circuit. .. py:function:: create_random_germ(pspec, depths, interacting_qs_density, qubit_labels, rand_state=None) TODO: docstring Parameters ---------- pspec : depths : interacting_qs_density : qubit_labels : Returns ------- .. py:function:: create_random_germpower_circuits(pspec, depths, interacting_qs_density, qubit_labels, fixed_versus_depth=False, rand_state=None) TODO: docstring Parameters ---------- pspec : depths : interacting_qs_density : qubit_labels : fixed_versus_depth : , optional rand_state: RandomState, optional A np.random.RandomState object for seeding RNG .. py:function:: create_random_germpower_mirror_circuits(pspec, absolute_compilation, depths, qubit_labels=None, localclifford=True, paulirandomize=True, interacting_qs_density=1 / 8, fixed_versus_depth=False, seed=None) TODO: docstring length : consistent with RB length. Parameters ---------- pspec : absolute_compilation : CompilationRules Rules for exactly (absolutely) compiling the "native" gates of `pspec` into clifford gates. depths : qubit_labels : , optional localclifford : , optional paulirandomize : , optional interacting_qs_density : , optional fixed_versus_depth : , optional Returns ------- .. py:function:: create_binary_rb_circuit(pspec, clifford_compilations, length, qubit_labels=None, layer_sampling='mixed1q2q', sampler='Qelimination', samplerargs=None, addlocal=False, lsargs=None, seed=None) Generates a "binary randomized benchmarking" (BiRB) circuit. Parameters ---------- pspec : QubitProcessorSpec The QubitProcessorSpec for the device that the circuit is being sampled for. The `pspec` is always handed to the sampler, as the first argument of the sampler function. clifford_compilations : CompilationRules Rules for exactly (absolutely) compiling the "native" gates of `pspec` into Clifford gates. length : int The "benchmark depth" of the circuit, which is the number of randomly sampled layers of gates in the core circuit. The full BiRB circuit has depth=length+2. qubit_labels : list, optional If not None, a list of the qubits that the RB circuit is to be sampled for. This should be all or a subset of the qubits in the device specified by the QubitProcessorSpec `pspec`. If None, it is assumed that the RB circuit should be over all the qubits. Note that the ordering of this list is the order of the ``wires'' in the returned circuit, but is otherwise irrelevant. layer_sampling : str, optional Determines the structure of the randomly sampled layers of gates: 1. 'mixed1q2q': Layers contain radomly-sampled two-qubit gates and randomly-sampled single-qubit gates on all remaining qubits. 2. 'alternating1q2q': Each layer consists of radomly-sampled two-qubit gates, with all other qubits idling, followed by randomly sampled single-qubit gates on all qubits. sampler : str or function, optional If a string, this should be one of: {'pairingQs', 'Qelimination', 'co2Qgates', 'local'}. Except for 'local', this corresponds to sampling layers according to the sampling function in rb.sampler named circuit_layer_by* (with * replaced by 'sampler'). For 'local', this corresponds to sampling according to rb.sampler.circuit_layer_of_oneQgates [which is not a valid option for n-qubit BiRB, but it is not explicitly forbidden by this function]. If `sampler` is a function, it should be a function that takes as the first argument a QubitProcessorSpec, and returns a random circuit layer as a list of gate Label objects. Note that the default 'Qelimination' is not necessarily the most useful in-built sampler, but it is the only sampler that requires no parameters beyond the QubitProcessorSpec *and* works for arbitrary connectivity devices. See the docstrings for each of these samplers for more information. samplerargs : list, optional A list of arguments that are handed to the sampler function, specified by `sampler`. The first argument handed to the sampler is `pspec` and `samplerargs` lists the remaining arguments handed to the sampler. seed : int, optional A seed to initialize the random number generator used for creating random clifford circuits. addlocal : bool, optional Whether to follow each layer in the "core" circuits, sampled according to `sampler` with a layer of 1-qubit gates. lsargs : list, optional Only used if addlocal is True. A list of optional arguments handed to the 1Q gate layer sampler circuit_layer_by_oneQgate(). Specifies how to sample 1Q-gate layers. Returns ------- Circuit A random BiRB circuit. String A length-n string of 'Z's and 'I's, which describes the target Pauli measurement for the BiRB circuit. The circuit, when run without errors, produces an eigenstate of the target Pauli operator. Int (Either 1 or -1) Specifies the sign of the target Pauli measurement. .. py:function:: random_alternating_clifford_circ(pspec, depth, qubit_labels=None, two_q_gate_density=0.25, rand_state=None) Generates a random circuit with composite layers cponsisting of a layer of two-qubit gates followed by a layer of of single-qubit gates. Parameters ---------- pspec : QubitProcessorSpec The QubitProcessorSpec for the device that the circuit is being sampled for. The `pspec` is always handed to the sampler, as the first argument of the sampler function. depth : int The number of composite layers in the final circuit. qubit_labels : list, optional If not None, a list of the qubFalseits that the RB circuit is to be sampled for. This should be all or a subset of the qubits in the device specified by the QubitProcessorSpec `pspec`. If None, it is assumed that the RB circuit should be over all the qubits. Note that the ordering of this list is the order of the ``wires'' in the returned circuit, but is otherwise irrelevant. samplerargs : list, optional A list of arguments that are handed to the sampler function, specified by `sampler`. The first argument handed to the sampler is `pspec` and `samplerargs` lists the remaining arguments handed to the sampler. Returns ------- Circuit A random circuit with 2*depth layers