Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
rileyjmurray committed May 28, 2024
1 parent 3e62da3 commit 26c682f
Show file tree
Hide file tree
Showing 20 changed files with 39 additions and 612 deletions.
192 changes: 0 additions & 192 deletions pygsti/algorithms/randomcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -2620,198 +2620,6 @@ def create_mirror_rb_circuit(pspec, absolute_compilation, length, qubit_labels=N

return circuit, idealout

#### Commented out as most of this functionality can be found elsewhere and this code has not been tested recently.
# def sample_one_q_generalized_rb_circuit(m, group_or_model, inverse=True, random_pauli=False, interleaved=None,
# group_inverse_only=False, group_prep=False, compilation=None,
# generated_group=None, model_to_group_labels=None, seed=None, rand_state=None):
# """
# Makes a random 1-qubit RB circuit, with RB over an arbitrary group.

# This function also contains a range of other options that allow circuits for many
# types of RB to be generated, including:

# - Clifford RB
# - Direct RB
# - Interleaved Clifford or direct RB
# - Unitarity Clifford or direct RB

# The function can in-principle be used beyond 1-qubit RB, but it relies on explicit matrix representation
# of a group, which is infeasble for, e.g., the many-qubit Clifford group.

# Note that this function has *not* been carefully tested. This will be rectified in the future,
# or this function will be replaced.

# Parameters
# ----------
# m : int
# The number of random gates in the circuit.

# group_or_model : Model or MatrixGroup
# Which Model of MatrixGroup to create the random circuit for. If
# inverse is true and this is a Model, the Model gates must form
# a group (so in this case it requires the *target model* rather than
# a noisy model). When inverse is true, the MatrixGroup for the model
# is generated. Therefore, if inverse is true and the function is called
# multiple times, it will be much faster if the MatrixGroup is provided.

# inverse : Bool, optional
# If true, the random circuit is followed by its inverse gate. The model
# must form a group if this is true. If it is true then the circuit
# returned is length m+1 (2m+1) if interleaved is False (True).

# random_pauli : <TODO typ>, optional
# <TODO description>

# interleaved : Str, optional
# If not None, then a oplabel string. When a oplabel string is provided,
# every random gate is followed by this gate. So the returned circuit is of
# length 2m+1 (2m) if inverse is True (False).

# group_inverse_only : <TODO typ>, optional
# <TODO description>

# group_prep : bool, optional
# If group_inverse_only is True and inverse is True, setting this to true
# creates a "group pre-twirl". Does nothing otherwise (which should be changed
# at some point).

# compilation : <TODO typ>, optional
# <TODO description>

# generated_group : <TODO typ>, optional
# <TODO description>

# model_to_group_labels : <TODO typ>, optional
# <TODO description>

# seed : int, optional
# Seed for random number generator; optional.

# rand_state : numpy.random.RandomState, optional
# A RandomState object to generate samples from. Can be useful to set
# instead of `seed` if you want reproducible distribution samples across
# multiple random function calls but you don't want to bother with
# manually incrementing seeds between those calls.

# Returns
# -------
# Circuit
# The random circuit of length:
# m if inverse = False, interleaved = None
# m + 1 if inverse = True, interleaved = None
# 2m if inverse = False, interleaved not None
# 2m + 1 if inverse = True, interleaved not None
# """
# assert hasattr(group_or_model, 'gates') or hasattr(group_or_model,
# 'product'), 'group_or_model must be a MatrixGroup of Model'
# group = None
# model = None
# if hasattr(group_or_model, 'gates'):
# model = group_or_model
# if hasattr(group_or_model, 'product'):
# group = group_or_model

# if rand_state is None:
# rndm = _np.random.RandomState(seed) # ok if seed is None
# else:
# rndm = rand_state

# if (inverse) and (not group_inverse_only):
# if model:
# group = _rbobjs.MatrixGroup(group_or_model.operations.values(),
# group_or_model.operations.keys())

# rndm_indices = rndm.randint(0, len(group), m)
# if interleaved:
# interleaved_index = group.label_indices[interleaved]
# interleaved_indices = interleaved_index * _np.ones((m, 2), _np.int64)
# interleaved_indices[:, 0] = rndm_indices
# rndm_indices = interleaved_indices.flatten()

# random_string = [group.labels[i] for i in rndm_indices]
# effective_op = group.product(random_string)
# inv = group.inverse_index(effective_op)
# random_string.append(inv)

# if (inverse) and (group_inverse_only):
# assert (model is not None), "gateset_or_group should be a Model!"
# assert (compilation is not None), "Compilation of group elements to model needs to be specified!"
# assert (generated_group is not None), "Generated group needs to be specified!"
# if model_to_group_labels is None:
# model_to_group_labels = {}
# for gate in model.primitive_op_labels:
# assert(gate in generated_group.labels), "model labels are not in \
# the generated group! Specify a model_to_group_labels dictionary."
# model_to_group_labels = {'gate': 'gate'}
# else:
# for gate in model.primitive_op_labels:
# assert(gate in model_to_group_labels.keys()), "model to group labels \
# are invalid!"
# assert(model_to_group_labels[gate] in generated_group.labels), "model to group labels \
# are invalid!"

# opLabels = model.primitive_op_labels
# rndm_indices = rndm.randint(0, len(opLabels), m)
# if interleaved:
# interleaved_index = opLabels.index(interleaved)
# interleaved_indices = interleaved_index * _np.ones((m, 2), _np.int64)
# interleaved_indices[:, 0] = rndm_indices
# rndm_indices = interleaved_indices.flatten()

# # This bit of code is a quick hashed job. Needs to be checked at somepoint
# if group_prep:
# rndm_group_index = rndm.randint(0, len(generated_group))
# prep_random_string = compilation[generated_group.labels[rndm_group_index]]
# prep_random_string_group = [generated_group.labels[rndm_group_index], ]

# random_string = [opLabels[i] for i in rndm_indices]
# random_string_group = [model_to_group_labels[opLabels[i]] for i in rndm_indices]
# # This bit of code is a quick hashed job. Needs to be checked at somepoint
# if group_prep:
# random_string = prep_random_string + random_string
# random_string_group = prep_random_string_group + random_string_group
# #print(random_string)
# inversion_group_element = generated_group.inverse_index(generated_group.product(random_string_group))

# # This bit of code is a quick hash job, and only works when the group is the 1-qubit Cliffords
# if random_pauli:
# pauli_keys = ['Gc0', 'Gc3', 'Gc6', 'Gc9']
# rndm_index = rndm.randint(0, 4)

# if rndm_index == 0 or rndm_index == 3:
# bitflip = False
# else:
# bitflip = True
# inversion_group_element = generated_group.product([inversion_group_element, pauli_keys[rndm_index]])

# inversion_sequence = compilation[inversion_group_element]
# random_string.extend(inversion_sequence)

# if not inverse:
# if model:
# opLabels = model.primitive_op_labels
# rndm_indices = rndm.randint(0, len(opLabels), m)
# if interleaved:
# interleaved_index = opLabels.index(interleaved)
# interleaved_indices = interleaved_index * _np.ones((m, 2), _np.int64)
# interleaved_indices[:, 0] = rndm_indices
# rndm_indices = interleaved_indices.flatten()
# random_string = [opLabels[i] for i in rndm_indices]

# else:
# rndm_indices = rndm.randint(0, len(group), m)
# if interleaved:
# interleaved_index = group.label_indices[interleaved]
# interleaved_indices = interleaved_index * _np.ones((m, 2), _np.int64)
# interleaved_indices[:, 0] = rndm_indices
# rndm_indices = interleaved_indices.flatten()
# random_string = [group.labels[i] for i in rndm_indices]

# if not random_pauli:
# return _cir.Circuit(random_string)
# if random_pauli:
# return _cir.Circuit(random_string), bitflip


def create_random_germ(pspec, depths, interacting_qs_density, qubit_labels, rand_state=None):
"""
Expand Down
3 changes: 2 additions & 1 deletion pygsti/baseobjs/basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ def vector_elements(self):
if self.sparse:
return [_sps.lil_matrix(el).reshape((self.elsize, 1)) for el in self.elements]
else:
# Use flatten (rather than ravel) to ensure a copy is made.
return [el.flatten() for el in self.elements]

def copy(self):
Expand Down Expand Up @@ -1468,7 +1469,7 @@ def to_elementstd_transform_matrix(self):
if self.sparse:
vel = _sps.lil_matrix(el.reshape(-1, 1)) # sparse vector == sparse n x 1 matrix
else:
vel = el.flatten()
vel = el.ravel()
toSimpleStd[:, i] = vel
return toSimpleStd

Expand Down
2 changes: 1 addition & 1 deletion pygsti/evotypes/qibo/effectreps.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def probability(self, state):

qibo_circuit = state.qibo_circuit
results = qibo_circuit(initial_state)
return _np.real_if_close(_np.dot(effect_state.flatten().conjugate(), results.state().flatten()))
return _np.real_if_close(effect_state.ravel().conjugate() @ results.state().ravel())

def to_dense(self, on_space):
return self.state_rep.to_dense(on_space)
Expand Down
4 changes: 3 additions & 1 deletion pygsti/extras/drift/stabilityanalyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1235,9 +1235,11 @@ def run_instability_detection(self, significance=0.05, freqstest=None, tests='au

# If we're not testing a single spectrum we need to flatten the >1D array.
if len(_np.shape(spectra)) > 1:
# Use flatten (rather than ravel) to ensure a copy is made.
powerlist = spectra[indices].flatten()
# If we're testing a single spectrum, we can just copy the 1D array.
else: powerlist = spectra[indices].copy()
else:
powerlist = spectra[indices].copy()

# The indices that will go with the elements in the flattened spectra.
powerindices = [tup for tup in _itertools.product(*iterBenjHoch)]
Expand Down
Loading

0 comments on commit 26c682f

Please sign in to comment.