Skip to content

Commit c9e728a

Browse files
committed
Merge branch 'develop' into simplify-TimeIndependentMDCObjectiveFunction
2 parents 1c23251 + e9eabd9 commit c9e728a

File tree

153 files changed

+4751
-10692
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

153 files changed

+4751
-10692
lines changed

.github/CODEOWNERS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ pygsti/algorithms/compilers.py @sandialabs/pygsti-rb @sandialabs/pygsti-gatekeep
3737
pygsti/algorithms/mirroring.py @sandialabs/pygsti-rb @sandialabs/pygsti-gatekeepers
3838
pygsti/algorithms/randomcircuit.py @sandialabs/pygsti-rb @sandialabs/pygsti-gatekeepers
3939
pygsti/algorithms/rbfit.py @sandialabs/pygsti-rb @sandialabs/pygsti-gatekeepers
40-
pygsti/extras/rb.py @sandialabs/pygsti-rb @sandialabs/pygsti-gatekeepers # Should this just be deprecated and removed?
4140
pygsti/protocols/rb.py @sandialabs/pygsti-rb @sandialabs/pygsti-gatekeepers
4241
pygsti/tools/rbtheory.py @sandialabs/pygsti-rb @sandialabs/pygsti-gatekeepers
4342
pygsti/tools/rbtools.py @sandialabs/pygsti-rb @sandialabs/pygsti-gatekeepers

pygsti/algorithms/core.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@
3131
from pygsti.modelmembers import states as _state
3232
from pygsti.circuits.circuitlist import CircuitList as _CircuitList
3333
from pygsti.baseobjs.resourceallocation import ResourceAllocation as _ResourceAllocation
34-
from pygsti.optimize.customlm import CustomLMOptimizer as _CustomLMOptimizer
35-
from pygsti.optimize.customlm import Optimizer as _Optimizer
34+
from pygsti.optimize.simplerlm import Optimizer as _Optimizer, SimplerLMOptimizer as _SimplerLMOptimizer
3635
from pygsti import forwardsims as _fwdsims
3736
from pygsti import layouts as _layouts
3837

@@ -619,7 +618,7 @@ def run_gst_fit_simple(dataset, start_model, circuits, optimizer, objective_func
619618
model : Model
620619
the best-fit model.
621620
"""
622-
optimizer = optimizer if isinstance(optimizer, _Optimizer) else _CustomLMOptimizer.cast(optimizer)
621+
optimizer = optimizer if isinstance(optimizer, _Optimizer) else _SimplerLMOptimizer.cast(optimizer)
623622
objective_function_builder = _objfns.ObjectiveFunctionBuilder.cast(objective_function_builder)
624623
array_types = optimizer.array_types + \
625624
objective_function_builder.compute_array_types(optimizer.called_objective_methods, start_model.sim)
@@ -666,7 +665,7 @@ def run_gst_fit(mdc_store, optimizer, objective_function_builder, verbosity=0):
666665
objfn_store : MDCObjectiveFunction
667666
the objective function and store containing the best-fit model evaluated at the best-fit point.
668667
"""
669-
optimizer = optimizer if isinstance(optimizer, _Optimizer) else _CustomLMOptimizer.cast(optimizer)
668+
optimizer = optimizer if isinstance(optimizer, _Optimizer) else _SimplerLMOptimizer.cast(optimizer)
670669
comm = mdc_store.resource_alloc.comm
671670
profiler = mdc_store.resource_alloc.profiler
672671
printer = VerbosityPrinter.create_printer(verbosity, comm)
@@ -843,7 +842,7 @@ def iterative_gst_generator(dataset, start_model, circuit_lists,
843842
(an "evaluated" model-dataset-circuits store).
844843
"""
845844
resource_alloc = _ResourceAllocation.cast(resource_alloc)
846-
optimizer = optimizer if isinstance(optimizer, _Optimizer) else _CustomLMOptimizer.cast(optimizer)
845+
optimizer = optimizer if isinstance(optimizer, _Optimizer) else _SimplerLMOptimizer.cast(optimizer)
847846
comm = resource_alloc.comm
848847
profiler = resource_alloc.profiler
849848
printer = VerbosityPrinter.create_printer(verbosity, comm)
@@ -1150,8 +1149,6 @@ def find_closest_unitary_opmx(operation_mx):
11501149
# d = _np.sqrt(operation_mx.shape[0])
11511150
# I = _np.identity(d)
11521151

1153-
#def getu_1q(basisVec): # 1 qubit version
1154-
# return _spl.expm( 1j * (basisVec[0]*_tools.sigmax + basisVec[1]*_tools.sigmay + basisVec[2]*_tools.sigmaz) )
11551152
def _get_gate_mx_1q(basis_vec): # 1 qubit version
11561153
return _tools.single_qubit_gate(basis_vec[0],
11571154
basis_vec[1],

pygsti/algorithms/fiducialselection.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -409,13 +409,6 @@ def final_result_test(final_fids, verb_printer):
409409
return prepFidList, measFidList
410410

411411

412-
#def bool_list_to_ind_list(boolList):
413-
# output = _np.array([])
414-
# for i, boolVal in boolList:
415-
# if boolVal == 1:
416-
# output = _np.append(i)
417-
# return output
418-
419412
def xor(*args):
420413
"""
421414
Implements logical xor function for arbitrary number of inputs.

pygsti/algorithms/gaugeopt.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ def gaugeopt_custom(model, objective_fn, gauge_group=None,
290290
gaugeGroupEl = gauge_group.compute_element(x0) # re-used element for evals
291291

292292
def _call_objective_fn(gauge_group_el_vec, oob_check=False):
293-
# Note: oob_check can be True if oob_check_interval>=1 is given to the custom_leastsq below
293+
# Note: oob_check can be True if oob_check_interval>=1 is given to the simplish_leastsq below
294294
gaugeGroupEl.from_vector(gauge_group_el_vec)
295295
return objective_fn(gaugeGroupEl, oob_check)
296296

@@ -309,7 +309,7 @@ def _call_jacobian_fn(gauge_group_el_vec):
309309
assert(_call_jacobian_fn is not None), "Cannot use 'ls' method unless jacobian is available"
310310
ralloc = _baseobjs.ResourceAllocation(comm) # FUTURE: plumb up a resource alloc object?
311311
test_f = _call_objective_fn(x0)
312-
solnX, converged, msg, _, _, _, _, _ = _opt.custom_leastsq(
312+
solnX, converged, msg, _, _, _, _ = _opt.simplish_leastsq(
313313
_call_objective_fn, _call_jacobian_fn, x0, f_norm2_tol=tol,
314314
jac_norm_tol=tol, rel_ftol=tol, rel_xtol=tol,
315315
max_iter=maxiter, resource_alloc=ralloc,

pygsti/algorithms/germselection.py

Lines changed: 87 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from pygsti.baseobjs.statespace import ExplicitStateSpace as _ExplicitStateSpace
2828
from pygsti.baseobjs.statespace import QuditSpace as _QuditSpace
2929
from pygsti.models import ExplicitOpModel as _ExplicitOpModel
30+
from pygsti.forwardsims import MatrixForwardSimulator as _MatrixForwardSimulator
3031

3132
FLOATSIZE = 8 # in bytes: TODO: a better way
3233

@@ -57,10 +58,8 @@ def find_germs(target_model, randomize=True, randomization_strength=1e-2,
5758
5859
Parameters
5960
----------
60-
target_model : Model or list of Model
61-
The model you are aiming to implement, or a list of models that are
62-
copies of the model you are trying to implement (either with or
63-
without random unitary perturbations applied to the models).
61+
target_model : Model
62+
The model you are aiming to implement.
6463
6564
randomize : bool, optional
6665
Whether or not to add random unitary perturbations to the model(s)
@@ -188,8 +187,14 @@ def find_germs(target_model, randomize=True, randomization_strength=1e-2,
188187
A list containing the germs making up the germ set.
189188
"""
190189
printer = _baseobjs.VerbosityPrinter.create_printer(verbosity, comm)
190+
191+
if not isinstance(target_model.sim, _MatrixForwardSimulator):
192+
target_model = target_model.copy()
193+
target_model.sim = 'matrix'
194+
191195
modelList = _setup_model_list(target_model, randomize,
192196
randomization_strength, num_gs_copies, seed)
197+
193198
gates = list(target_model.operations.keys())
194199
availableGermsList = []
195200
if candidate_germ_counts is None: candidate_germ_counts = {6: 'all upto'}
@@ -1351,6 +1356,10 @@ def test_germ_set_finitel(model, germs_to_test, length, weights=None,
13511356
eigenvalues (from small to large) of the jacobian^T * jacobian
13521357
matrix used to determine parameter amplification.
13531358
"""
1359+
if not isinstance(model.sim, _MatrixForwardSimulator):
1360+
model = model.copy()
1361+
model.sim = 'matrix'
1362+
13541363
# Remove any SPAM vectors from model since we only want
13551364
# to consider the set of *gate* parameters for amplification
13561365
# and this makes sure our parameter counting is correct
@@ -3295,80 +3304,81 @@ def symmetric_low_rank_spectrum_update(update, orig_e, U, proj_U, force_rank_inc
32953304
#return the new eigenvalues
32963305
return new_evals, True
32973306

3298-
#Note: This function won't work for our purposes because of the assumptions
3299-
#about the rank of the update on the nullspace of the matrix we're updating,
3300-
#but keeping this here commented for future reference.
3301-
#Function for doing fast calculation of the updated inverse trace:
3302-
#def riedel_style_inverse_trace(update, orig_e, U, proj_U, force_rank_increase=True):
3303-
# """
3304-
# input:
3305-
#
3306-
# update : ndarray
3307-
# symmetric low-rank update to perform.
3308-
# This is the first half the symmetric rank decomposition s.t.
3309-
# [email protected]= the full update matrix.
3310-
#
3311-
# orig_e : ndarray
3312-
# Spectrum of the original matrix. This is a 1-D array.
3313-
#
3314-
# proj_U : ndarray
3315-
# Projector onto the complement of the column space of the
3316-
# original matrix's eigenvectors.
3317-
#
3318-
# output:
3319-
#
3320-
# trace : float
3321-
# Value of the trace of the updated psuedoinverse matrix.
3322-
#
3323-
# updated_rank : int
3324-
# total rank of the updated matrix.
3325-
#
3326-
# rank_increase_flag : bool
3327-
# a flag that is returned to indicate is a candidate germ failed to amplify additional parameters.
3328-
# This indicates things short circuited and so the scoring function should skip this germ.
3329-
# """
3330-
#
3331-
# #First we need to for the matrix P, whose column space
3332-
# #forms an orthonormal basis for the component of update
3333-
# #that is in the complement of U.
3334-
#
3335-
# proj_update= proj_U@update
3336-
#
3337-
# #Next take the RRQR decomposition of this matrix:
3338-
# q_update, r_update, _ = _sla.qr(proj_update, mode='economic', pivoting=True)
3339-
#
3340-
# #Construct P by taking the columns of q_update corresponding to non-zero values of r_A on the diagonal.
3341-
# nonzero_indices_update= _np.nonzero(_np.diag(r_update)>1e-10) #HARDCODED (threshold is hardcoded)
3342-
#
3343-
# #if the rank doesn't increase then we can't use the Riedel approach.
3344-
# #Abort early and return a flag to indicate the rank did not increase.
3345-
# if len(nonzero_indices_update[0])==0 and force_rank_increase:
3346-
# return None, None, False
3347-
#
3348-
# P= q_update[: , nonzero_indices_update[0]]
3349-
#
3350-
# updated_rank= len(orig_e)+ len(nonzero_indices_update[0])
3351-
#
3352-
# #Now form the matrix R_update which is given by P.T @ proj_update.
3353-
# R_update= P.T@proj_update
3354-
#
3355-
# #R_update gets concatenated with U.T@update to form
3356-
# #a block column matrixblock_column= np.concatenate([U.T@update, R_update], axis=0)
3357-
#
3358-
# Uta= U.T@update
3359-
#
3360-
# try:
3361-
# RRRDinv= R_update@_np.linalg.inv(R_update.T@R_update)
3362-
# except _np.linalg.LinAlgError as err:
3363-
# print('Numpy thinks this matrix is singular, condition number is: ', _np.linalg.cond(R_update.T@R_update))
3364-
# print((R_update.T@R_update).shape)
3365-
# raise err
3366-
# pinv_orig_e_mat= _np.diag(1/orig_e)
3367-
#
3368-
# trace= _np.sum(1/orig_e) + _np.trace( RRRDinv@(_np.eye(Uta.shape[1]) + Uta.T@pinv_orig_e_mat@Uta)@RRRDinv.T )
3369-
#
3370-
# return trace, updated_rank, True
3307+
# Note: Th function below won't work for our purposes because of the assumptions
3308+
# about the rank of the update on the nullspace of the matrix we're updating,
3309+
# but keeping this here commented for future reference.
3310+
'''
3311+
def riedel_style_inverse_trace(update, orig_e, U, proj_U, force_rank_increase=True):
3312+
"""
3313+
input:
3314+
3315+
update : ndarray
3316+
symmetric low-rank update to perform.
3317+
This is the first half the symmetric rank decomposition s.t.
3318+
[email protected]= the full update matrix.
3319+
3320+
orig_e : ndarray
3321+
Spectrum of the original matrix. This is a 1-D array.
3322+
3323+
proj_U : ndarray
3324+
Projector onto the complement of the column space of the
3325+
original matrix's eigenvectors.
3326+
3327+
output:
3328+
3329+
trace : float
3330+
Value of the trace of the updated psuedoinverse matrix.
3331+
3332+
updated_rank : int
3333+
total rank of the updated matrix.
3334+
3335+
rank_increase_flag : bool
3336+
a flag that is returned to indicate is a candidate germ failed to amplify additional parameters.
3337+
This indicates things short circuited and so the scoring function should skip this germ.
3338+
"""
33713339
3340+
#First we need to for the matrix P, whose column space
3341+
#forms an orthonormal basis for the component of update
3342+
#that is in the complement of U.
3343+
3344+
proj_update= proj_U@update
3345+
3346+
#Next take the RRQR decomposition of this matrix:
3347+
q_update, r_update, _ = _sla.qr(proj_update, mode='economic', pivoting=True)
3348+
3349+
#Construct P by taking the columns of q_update corresponding to non-zero values of r_A on the diagonal.
3350+
nonzero_indices_update= _np.nonzero(_np.diag(r_update)>1e-10) #HARDCODED (threshold is hardcoded)
3351+
3352+
#if the rank doesn't increase then we can't use the Riedel approach.
3353+
#Abort early and return a flag to indicate the rank did not increase.
3354+
if len(nonzero_indices_update[0])==0 and force_rank_increase:
3355+
return None, None, False
3356+
3357+
P= q_update[: , nonzero_indices_update[0]]
3358+
3359+
updated_rank= len(orig_e)+ len(nonzero_indices_update[0])
3360+
3361+
#Now form the matrix R_update which is given by P.T @ proj_update.
3362+
R_update= P.T@proj_update
3363+
3364+
#R_update gets concatenated with U.T@update to form
3365+
#a block column matrixblock_column= np.concatenate([U.T@update, R_update], axis=0)
3366+
3367+
Uta= U.T@update
3368+
3369+
try:
3370+
RRRDinv= R_update@_np.linalg.inv(R_update.T@R_update)
3371+
except _np.linalg.LinAlgError as err:
3372+
print('Numpy thinks this matrix is singular, condition number is: ', _np.linalg.cond(R_update.T@R_update))
3373+
print((R_update.T@R_update).shape)
3374+
raise err
3375+
pinv_orig_e_mat= _np.diag(1/orig_e)
3376+
3377+
trace= _np.sum(1/orig_e) + _np.trace( RRRDinv@(_np.eye(Uta.shape[1]) + Uta.T@pinv_orig_e_mat@Uta)@RRRDinv.T )
3378+
3379+
return trace, updated_rank, True
3380+
'''
3381+
33723382
def minamide_style_inverse_trace(update, orig_e, U, proj_U, force_rank_increase=False):
33733383
"""
33743384
This function performs a low-rank update to the components of

0 commit comments

Comments
 (0)