Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
144 commits
Select commit Hold shift + click to select a range
f529155
bugfix for my attemped efficiency improvement
rileyjmurray Feb 15, 2024
d389349
extend basistools to gracefully accomodate objects that derive from L…
rileyjmurray Feb 15, 2024
d7e880e
update function in reportables to indicate API limitation. Bugfix in …
rileyjmurray Feb 22, 2024
9489fbd
update implementation of state fidelity
rileyjmurray Feb 22, 2024
b402562
comments. About to remove.
rileyjmurray Feb 28, 2024
43ce7af
extend implementation to support bases other than pauli-product. Add …
rileyjmurray Feb 28, 2024
a4eca61
remove unused and broken function that I only added for debugging pur…
rileyjmurray Feb 28, 2024
98cae3a
comment clarification
rileyjmurray Feb 28, 2024
f47070b
clean up implementation of ExplicitOpModelCalc.residuals
rileyjmurray Mar 4, 2024
45e6b17
slightly simplify minimize(...) function. There was an unnecessary br…
rileyjmurray Mar 4, 2024
30be140
factor out the logic needed to set up calculation of leaky entangleme…
rileyjmurray Mar 4, 2024
4899bb8
add implementation of leaky jtracedist
rileyjmurray Mar 4, 2024
714f0e1
enable gauge optimization with leakage-aware metrics using non-LS opt…
rileyjmurray Mar 4, 2024
c5e2fe1
support for leakage-aware Frobenius distance with non-LS optimizer. A…
rileyjmurray Mar 4, 2024
b2ca23a
left out a function needed for code in the last commit to work
rileyjmurray Mar 4, 2024
6de1eaf
tests for the leaky_entanglement_fidelity function that Ive had for a…
rileyjmurray Mar 4, 2024
a863ab8
fix syntax mistake
rileyjmurray Mar 4, 2024
d3d427e
rename test_gauageopt.py file to indicate that its contents only test…
rileyjmurray Mar 4, 2024
5b811aa
correctness test for gauge optimization (ls-based and L-BFGS-based)
rileyjmurray Mar 19, 2024
f009923
fix typo
rileyjmurray Mar 19, 2024
9561adc
remove some awkward casting that it turns out wasnt needed
rileyjmurray Mar 19, 2024
a172b11
remove unnecessary comment changes
rileyjmurray Apr 2, 2024
ad01635
change how leakage affects distances between SPAM model members for F…
rileyjmurray Apr 15, 2024
b90923b
keep develop fix for dd[lbl]['SPAM'] instead of what I had on leakage
rileyjmurray Apr 15, 2024
5e16398
support for subspace-restricted error metrics
rileyjmurray May 7, 2024
60fa5a5
de-nest two lines
rileyjmurray Sep 24, 2024
14c1b18
Add utilities for constructing CVXPY models involving (convex) diamon…
rileyjmurray Sep 27, 2024
39a9fde
fix bugs in changes from last commit
rileyjmurray Sep 27, 2024
10518ab
add ability to return labels from leading_dxd_submatrix_basis_vectors
rileyjmurray Sep 28, 2024
ebe5639
define new OuterProductBasis class. Unclear if we'll want to keep this.'
rileyjmurray Sep 28, 2024
18ab100
rollback change in 1c7d5aaf9d2e45888132c1d6995e3d868a039ba2
rileyjmurray Sep 28, 2024
91be20a
remove explicit call to MOSEK
rileyjmurray Sep 28, 2024
e3c4543
update add_gauge_opt so it can accept a dict specifying a gaugeopt su…
rileyjmurray Nov 18, 2024
6533035
REVERT ME
rileyjmurray Nov 18, 2024
5af6795
comments pointing to possible bugs
rileyjmurray Nov 18, 2024
0119978
leave note for myself
rileyjmurray Nov 18, 2024
3afe059
reduce number of options available in non-LS gauge optimization
rileyjmurray Nov 21, 2024
b1e52d5
last commit actually just included comments. Material changes are in …
rileyjmurray Nov 21, 2024
d57ca7f
simplify gaugeopt in the non-LS case
rileyjmurray Nov 21, 2024
7e9a36c
remove non-Frobenius objectives from gauge optimization
rileyjmurray Nov 21, 2024
1376c09
status for notebook 2024-11-21a.ipynb
rileyjmurray Nov 21, 2024
3945bc2
bugfix in leading_dxd_submatrix_basis_vectors helper function
rileyjmurray Nov 22, 2024
75786e5
Revert "status for notebook 2024-11-21a.ipynb"
rileyjmurray Nov 22, 2024
b8bcbcd
Revert "remove non-Frobenius objectives from gauge optimization"
rileyjmurray Nov 22, 2024
8246c28
Revert "simplify gaugeopt in the non-LS case"
rileyjmurray Nov 22, 2024
eff3557
Revert "last commit actually just included comments. Material changes…
rileyjmurray Nov 22, 2024
0eb4fd5
improved HTML reporting when n_leak=1
rileyjmurray Nov 22, 2024
62cf57a
remove EmbeddedBasis class that accidentally was kept during a rebase
rileyjmurray Jan 17, 2025
dba1839
remove function definitions accidentally kept in rebase
rileyjmurray Jan 17, 2025
72d7a5a
revert introduction of bug
rileyjmurray Jan 17, 2025
9abc758
add comments
rileyjmurray Jan 17, 2025
8de0043
demo
rileyjmurray Mar 5, 2025
d023615
make a copy where docs said we were
rileyjmurray Mar 6, 2025
25891da
update report generation so tables with subspace-restricted error met…
rileyjmurray Mar 18, 2025
18631bc
leakage and seepage analysis and reporting
rileyjmurray Apr 3, 2025
5ac3e31
more leakage metrics. A seepage metric.
rileyjmurray Apr 3, 2025
5c4e7d0
attempt to change table title
rileyjmurray Apr 3, 2025
c99cc5d
update message
rileyjmurray Apr 3, 2025
91435a6
add ability to skip named sections in construct_standard_report. Alwa…
rileyjmurray Feb 4, 2025
cf19fdd
make DataSet.gate_labels() robust to circuits whose layers are sequen…
rileyjmurray Jun 12, 2025
68895de
add error handling in deserialization. We will probably want to rever…
rileyjmurray Jun 12, 2025
e2183e5
add option to return basis for computational subspace in leakage_frie…
rileyjmurray Jun 12, 2025
5dc3be1
rename function
rileyjmurray Jun 12, 2025
ce2ddf3
add crude exception catching for POVM metrics
rileyjmurray Jun 12, 2025
58fa2a1
add a dict member to TensorProdBasis so that we can find the position…
rileyjmurray Jun 12, 2025
9f7726b
bugfixes
rileyjmurray Jun 12, 2025
11e3691
improve warning messages
rileyjmurray Jun 12, 2025
5170abc
remove MOSEK hard dependency for diamond norm
rileyjmurray Jun 13, 2025
790dca8
riley fix whoops
dhothem Jun 13, 2025
ef12594
bugfix
rileyjmurray Jun 13, 2025
63a6356
remove rounding of gate metrics that created problems with error bars…
rileyjmurray Jun 18, 2025
641a8aa
new DirectSumUnitaryGroup for gauge optimization, type annotations, r…
rileyjmurray Jul 8, 2025
1af3ef6
take an instance method for GSTGaugeOptSuite that never referenced `s…
rileyjmurray Jul 8, 2025
73da836
update the povm.convert(...) free function to work with CPTPLND param…
rileyjmurray Jul 8, 2025
96c3fe7
factor out functionality for computing the gradient of a ModelFunctio…
rileyjmurray Jul 8, 2025
e21c524
revert hacky change in __hash__. Remove commented-out invalid lines i…
rileyjmurray Jul 24, 2025
50714ce
comments
rileyjmurray Jul 24, 2025
39cc16b
fix undefined variable; update comments
rileyjmurray Jul 24, 2025
d18e07c
revert changes
rileyjmurray Jul 24, 2025
793b155
left out of last commit
rileyjmurray Jul 24, 2025
b03e4ba
remove resolved TODO
rileyjmurray Jul 24, 2025
84839c1
revert one-line change
rileyjmurray Jul 24, 2025
0776b57
remove unused OuterProdBasis class
rileyjmurray Jul 24, 2025
42688ae
remove commented-out code that isnt on develop
rileyjmurray Jul 25, 2025
5b1d324
ModelMemberGraph.load_modelmembers_from_serialization_dict did not ne…
rileyjmurray Jul 25, 2025
2952738
readability
rileyjmurray Jul 25, 2025
f539e91
justify try-catch in DenseState._from_memoized_dict
rileyjmurray Jul 25, 2025
7323e24
fix broken rebase
rileyjmurray Jul 29, 2025
39e4401
have Circuit.__eq__ take less of a speed hit while still fixing prior…
rileyjmurray Jul 29, 2025
721ec35
remove duplicate import
rileyjmurray Jul 29, 2025
82accb3
move notebook infrastructure into a new pygsti file, pygsti/tools/lea…
rileyjmurray Jul 29, 2025
26ec19e
resolve circular imports, remove unused imports, move more functions …
rileyjmurray Jul 29, 2025
72affd4
left out of last commit
rileyjmurray Jul 29, 2025
de254c1
remove the report-generation helper functions from leakage.py. The on…
rileyjmurray Jul 29, 2025
0160477
changes to utilities for leakage-aware gauge optimization
rileyjmurray Jul 30, 2025
cab438f
correct incorrect import statements
rileyjmurray Jul 30, 2025
6a46db8
vaguely user-friendly API
rileyjmurray Jul 30, 2025
7d47cd4
changes for model construction and manipulation in the leakage-friend…
rileyjmurray Jul 30, 2025
06b48a9
revert some changes to _add_gauge_opt
rileyjmurray Jul 30, 2025
480694a
left out
rileyjmurray Jul 30, 2025
9451edb
remove re-introduction of hack that was no longer needed for diamond …
rileyjmurray Jul 31, 2025
eb7b818
Merge branch 'develop' into leakage
rileyjmurray Aug 1, 2025
d89a8f3
revert changes to table captions in standard reports
rileyjmurray Aug 1, 2025
2c4e71d
reformat
rileyjmurray Aug 1, 2025
0adc320
type annotations. Changes to strings used to specify metrics in repor…
rileyjmurray Aug 4, 2025
07d016f
grammar
rileyjmurray Aug 4, 2025
206b0af
improve warning message for idle tomography
rileyjmurray Aug 4, 2025
be16868
type annotations
rileyjmurray Aug 4, 2025
c9b884e
suppress certain MOSEK warning messages when using CVXPY
rileyjmurray Aug 4, 2025
52300e7
streamlined notebook
rileyjmurray Aug 4, 2025
c971b61
built-in leakage basis and changes to report utilities
rileyjmurray Aug 5, 2025
e4c620c
remove output from notebook under version control
rileyjmurray Aug 5, 2025
580612c
add elindlookup to LazyBasis and remove it from TensorProductBasis (t…
rileyjmurray Aug 6, 2025
5232230
comments and types in basisconstructors.py
rileyjmurray Aug 6, 2025
0acec41
type annotation
rileyjmurray Aug 6, 2025
f77de49
remove the leakage_friendly_basis free-function that was living in le…
rileyjmurray Aug 6, 2025
1564b45
revert readability change so as to leave tppovm.py untouched by this PR
rileyjmurray Aug 6, 2025
54805ef
remove unnecessary .flatten() in computing Frobenius norm of a matrix
rileyjmurray Aug 6, 2025
d149bb0
change variable name. Leave comment.
rileyjmurray Aug 6, 2025
ef19093
remove unused import
rileyjmurray Aug 6, 2025
ac7c99f
import formatting
rileyjmurray Aug 6, 2025
d034343
clarifying comment
rileyjmurray Aug 6, 2025
0983337
type annotations
rileyjmurray Aug 6, 2025
886b75a
docs and types for tensorized_with_eye
rileyjmurray Aug 6, 2025
2c1378e
type annotations and docstring fixes (need double-backslash for math)
rileyjmurray Aug 6, 2025
822148a
Merge branch 'develop' into leakage
rileyjmurray Aug 6, 2025
49cfc93
typing and updated comment
rileyjmurray Aug 7, 2025
9378e89
fix import and types
rileyjmurray Aug 7, 2025
a46b33a
fix deprecation warning. style.
rileyjmurray Aug 8, 2025
5dca93c
minor bugfix in leaky_entanglement_fidelity. Variable names
rileyjmurray Aug 8, 2025
0433764
type annotations
rileyjmurray Aug 8, 2025
83678ea
suppress warnings in tests (seems pytest overrides the normal warning…
rileyjmurray Aug 8, 2025
2f83ab8
add IdentityOperator class to matrixtools.py. Simplify gaugeopt.py as…
rileyjmurray Aug 8, 2025
1b818c2
add useful error message
rileyjmurray Aug 8, 2025
77ff35c
caching, documentation, function signatures, variable names
rileyjmurray Aug 8, 2025
eb84b99
finish docs for metrics
rileyjmurray Aug 8, 2025
d951dff
docs for leaky_qubit_model_from_pspec
rileyjmurray Aug 19, 2025
c668f46
doc and type annotation
rileyjmurray Aug 19, 2025
b8da831
mostly just docs
rileyjmurray Aug 19, 2025
4554ad8
move some functions from leakage.py to explicitmodel.py and gst.py. F…
rileyjmurray Aug 19, 2025
43a2d6a
resolve typos identified by Nick
rileyjmurray Aug 19, 2025
1083b33
smoke test
rileyjmurray Aug 19, 2025
68e36af
bugfix
rileyjmurray Aug 19, 2025
8751da3
alternative fix for issue I tried to address in last commit
rileyjmurray Aug 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions jupyter_notebooks/Examples/Leakage-automagic.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pygsti.modelpacks import smq1Q_XY, smq1Q_ZN\n",
"from pygsti.tools.leakage import leaky_qubit_model_from_pspec, construct_leakage_report\n",
"from pygsti.data import simulate_data\n",
"from pygsti.protocols import StandardGST, ProtocolData"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## GST: modeling a leaky qubit as a qutrit\n",
"\n",
"This short notebook shows how (data from) an experiment design for a two-level system can be used to fit a three-level sytem model, and how to generate a special report to provide insights for these models. The report includes special gate error metrics that reflect the distinguished role of the first two levels in the three-level system."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mp = smq1Q_XY\n",
"ed = mp.create_gst_experiment_design(max_max_length=32)\n",
"tm3 = leaky_qubit_model_from_pspec(mp.processor_spec(), mx_basis='l2p1')\n",
"# ^ We could use basis = 'gm' instead of 'l2p1'. We prefer 'l2p1'\n",
"# because it makes process matrices easier to interpret in leakage\n",
"# modeling.\n",
"ds = simulate_data(tm3, ed.all_circuits_needing_data, num_samples=1000, seed=1997)\n",
"gst = StandardGST( modes=('CPTPLND',), target_model=tm3, verbosity=2)\n",
"pd = ProtocolData(ed, ds)\n",
"res = gst.run(pd)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"report_dir = 'example_files/leakage-report-automagic'\n",
"report_object, updated_res = construct_leakage_report(res, title='easy leakage analysis!')\n",
"# ^ Each estimate in updated_res has a new gauge-optimized model.\n",
"# The gauge optimization was done to reflect how our target gates\n",
"# are only _really_ defined on the first two levels of our\n",
"# three-level system.\n",
"# \n",
"report_object.write_html(report_dir)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "leak311",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.13"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
212 changes: 118 additions & 94 deletions pygsti/algorithms/gaugeopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@
from pygsti import tools as _tools
from pygsti.tools import mpitools as _mpit
from pygsti.tools import slicetools as _slct
from pygsti.models.gaugegroup import TrivialGaugeGroupElement as _TrivialGaugeGroupElement
from pygsti.models.gaugegroup import (
TrivialGaugeGroupElement as _TrivialGaugeGroupElement,
GaugeGroupElement as _GaugeGroupElement
)

from typing import Callable, Union, Optional


def gaugeopt_to_target(model, target_model, item_weights=None,
Expand All @@ -29,7 +34,7 @@ def gaugeopt_to_target(model, target_model, item_weights=None,
gauge_group=None, method='auto', maxiter=100000,
maxfev=None, tol=1e-8, oob_check_interval=0,
convert_model_to=None, return_all=False, comm=None,
verbosity=0, check_jac=False):
verbosity=0, check_jac=False, n_leak=0):
"""
Optimize the gauge degrees of freedom of a model to that of a target.

Expand Down Expand Up @@ -170,7 +175,7 @@ def gaugeopt_to_target(model, target_model, item_weights=None,
objective_fn, jacobian_fn = _create_objective_fn(
model, target_model, item_weights,
cptp_penalty_factor, spam_penalty_factor,
gates_metric, spam_metric, method, comm, check_jac)
gates_metric, spam_metric, method, comm, check_jac, n_leak)

result = gaugeopt_custom(model, objective_fn, gauge_group, method,
maxiter, maxfev, tol, oob_check_interval,
Expand Down Expand Up @@ -307,9 +312,6 @@ def _call_jacobian_fn(gauge_group_el_vec):

printer.log("--- Gauge Optimization (%s method, %s) ---" % (method, str(type(gauge_group))), 2)
if method == 'ls':
#minSol = _opt.least_squares(_call_objective_fn, x0, #jac=_call_jacobian_fn,
# max_nfev=maxfev, ftol=tol)
#solnX = minSol.x
assert(_call_jacobian_fn is not None), "Cannot use 'ls' method unless jacobian is available"
ralloc = _baseobjs.ResourceAllocation(comm) # FUTURE: plumb up a resource alloc object?
test_f = _call_objective_fn(x0)
Expand Down Expand Up @@ -354,10 +356,15 @@ def _call_jacobian_fn(gauge_group_el_vec):
return newModel


def _create_objective_fn(model, target_model, item_weights=None,
cptp_penalty_factor=0, spam_penalty_factor=0,
GGElObjective = Callable[[_GaugeGroupElement,bool], Union[float, _np.ndarray]]

GGElJacobian = Union[None, Callable[[_GaugeGroupElement], _np.ndarray]]


def _create_objective_fn(model, target_model, item_weights: Optional[dict[str,float]]=None,
cptp_penalty_factor: float=0.0, spam_penalty_factor: float=0.0,
gates_metric="frobenius", spam_metric="frobenius",
method=None, comm=None, check_jac=False):
method=None, comm=None, check_jac=False, n_leak=0) -> tuple[GGElObjective, GGElJacobian]:
"""
Creates the objective function and jacobian (if available)
for gaugeopt_to_target
Expand Down Expand Up @@ -595,17 +602,32 @@ def _mock_objective_fn(v):
# non-least-squares case where objective function returns a single float
# and (currently) there's no analytic jacobian

assert gates_metric != "frobeniustt"
assert spam_metric != "frobeniustt"
# ^ PR #410 removed support for Frobenius transform-target metrics in this codepath.

dim = int(_np.sqrt(mxBasis.dim))
if n_leak > 0:
B = _tools.leading_dxd_submatrix_basis_vectors(dim - n_leak, dim, mxBasis)
P = B @ B.T.conj()
if _np.linalg.norm(P.imag) > 1e-12:
msg = f"Attempting to run leakage-aware gauge optimization with basis {mxBasis}\n"
msg += "is resulting an orthogonal projector onto the computational subspace that\n"
msg += "is not real-valued. Try again with a different basis, like 'l2p1' or 'gm'."
raise ValueError(msg)
else:
P = P.real
transform_mx_arg = (P, _tools.matrixtools.IdentityOperator())
# ^ The semantics of this tuple are defined by the frobeniusdist function
# in the ExplicitOpModelCalc class.
else:
transform_mx_arg = None
# ^ It would be equivalent to set this to a pair of IdentityOperator objects.

def _objective_fn(gauge_group_el, oob_check):
mdl = _transform_with_oob_check(model, gauge_group_el, oob_check)
ret = 0

if gates_metric == "frobeniustt" or spam_metric == "frobeniustt":
full_target_model = target_model.copy()
full_target_model.convert_members_inplace("full") # so we can gauge-transform the target model.
transformed_target = _transform_with_oob_check(full_target_model, gauge_group_el.inverse(), oob_check)
else:
transformed_target = None

if cptp_penalty_factor > 0:
mdl.basis = mxBasis # set basis for jamiolkowski iso
cpPenaltyVec = _cptp_penalty(mdl, cptp_penalty_factor, mdl.basis)
Expand All @@ -616,84 +638,86 @@ def _objective_fn(gauge_group_el, oob_check):
spamPenaltyVec = _spam_penalty(mdl, spam_penalty_factor, mdl.basis)
ret += _np.sum(spamPenaltyVec)

if target_model is not None:
if gates_metric == "frobenius":
if spam_metric == "frobenius":
ret += mdl.frobeniusdist(target_model, None, item_weights)
else:
wts = item_weights.copy(); wts['spam'] = 0.0
for k in wts:
if k in mdl.preps or \
k in mdl.povms: wts[k] = 0.0
ret += mdl.frobeniusdist(target_model, None, wts)

elif gates_metric == "frobeniustt":
if spam_metric == "frobeniustt":
ret += transformed_target.frobeniusdist(model, None, item_weights)
else:
wts = item_weights.copy(); wts['spam'] = 0.0
for k in wts:
if k in mdl.preps or \
k in mdl.povms: wts[k] = 0.0
ret += transformed_target.frobeniusdist(model, None, wts)

elif gates_metric == "fidelity":
for opLbl in mdl.operations:
wt = item_weights.get(opLbl, opWeight)
ret += wt * (1.0 - _tools.entanglement_fidelity(
target_model.operations[opLbl], mdl.operations[opLbl]))**2

elif gates_metric == "tracedist":
for opLbl in mdl.operations:
wt = item_weights.get(opLbl, opWeight)
ret += opWeight * _tools.jtracedist(
target_model.operations[opLbl], mdl.operations[opLbl])

else: raise ValueError("Invalid gates_metric: %s" % gates_metric)

if spam_metric == "frobenius":
if gates_metric != "frobenius": # otherwise handled above to match normalization in frobeniusdist
wts = item_weights.copy(); wts['gates'] = 0.0
for k in wts:
if k in mdl.operations or \
k in mdl.instruments: wts[k] = 0.0
ret += mdl.frobeniusdist(target_model, None, wts)

elif spam_metric == "frobeniustt":
if gates_metric != "frobeniustt": # otherwise handled above to match normalization in frobeniusdist
wts = item_weights.copy(); wts['gates'] = 0.0
for k in wts:
if k in mdl.operations or \
k in mdl.instruments: wts[k] = 0.0
ret += transformed_target.frobeniusdist(model, None, wts)

elif spam_metric == "fidelity":
for preplabel, prep in mdl.preps.items():
wt = item_weights.get(preplabel, spamWeight)
rhoMx1 = _tools.vec_to_stdmx(prep, mxBasis)
rhoMx2 = _tools.vec_to_stdmx(
target_model.preps[preplabel], mxBasis)
ret += wt * (1.0 - _tools.fidelity(rhoMx1, rhoMx2))**2

for povmlabel, povm in mdl.povms.items():
wt = item_weights.get(povmlabel, spamWeight)
ret += wt * (1.0 - _tools.povm_fidelity(
mdl, target_model, povmlabel))**2

elif spam_metric == "tracedist":
for preplabel, prep in mdl.preps.items():
wt = item_weights.get(preplabel, spamWeight)
rhoMx1 = _tools.vec_to_stdmx(prep, mxBasis)
rhoMx2 = _tools.vec_to_stdmx(
target_model.preps[preplabel], mxBasis)
ret += wt * _tools.tracedist(rhoMx1, rhoMx2)

for povmlabel, povm in mdl.povms.items():
wt = item_weights.get(povmlabel, spamWeight)
ret += wt * (1.0 - _tools.povm_jtracedist(
mdl, target_model, povmlabel))**2

else: raise ValueError("Invalid spam_metric: %s" % spam_metric)
if target_model is None:
return ret

if "frobenius" in gates_metric:
if spam_metric == gates_metric:
val = mdl.frobeniusdist(target_model, transform_mx_arg, item_weights)
else:
wts = item_weights.copy()
wts['spam'] = 0.0
for k in wts:
if k in mdl.preps or k in mdl.povms:
wts[k] = 0.0
val = mdl.frobeniusdist(target_model, transform_mx_arg, wts, n_leak)
if "squared" in gates_metric:
val = val ** 2
ret += val

elif gates_metric == "fidelity":
# If n_leak==0, then subspace_entanglement_fidelity is just entanglement_fidelity
for opLbl in mdl.operations:
wt = item_weights.get(opLbl, opWeight)
top = target_model.operations[opLbl].to_dense()
mop = mdl.operations[opLbl].to_dense()
ret += wt * (1.0 - _tools.subspace_entanglement_fidelity(top, mop, mxBasis, n_leak))**2

elif gates_metric == "tracedist":
# If n_leak==0, then subspace_jtracedist is just jtracedist.
for opLbl in mdl.operations:
wt = item_weights.get(opLbl, opWeight)
top = target_model.operations[opLbl].to_dense()
mop = mdl.operations[opLbl].to_dense()
ret += wt * _tools.subspace_jtracedist(top, mop, mxBasis, n_leak)

else:
raise ValueError("Invalid gates_metric: %s" % gates_metric)

if "frobenius" in spam_metric and gates_metric == spam_metric:
# We already handled SPAM error in this case. Just return.
return ret

if "frobenius" in spam_metric:
# SPAM and gates can have different choices for squared vs non-squared.
wts = item_weights.copy(); wts['gates'] = 0.0
for k in wts:
if k in mdl.operations or k in mdl.instruments:
wts[k] = 0.0
val = mdl.frobeniusdist(target_model, transform_mx_arg, wts)
if "squared" in spam_metric:
val = val ** 2
ret += val

elif spam_metric == "fidelity":
# Leakage-aware metrics NOT available
for preplabel, m_prep in mdl.preps.items():
wt = item_weights.get(preplabel, spamWeight)
rhoMx1 = _tools.vec_to_stdmx(m_prep.to_dense(), mxBasis)
t_prep = target_model.preps[preplabel]
rhoMx2 = _tools.vec_to_stdmx(t_prep.to_dense(), mxBasis)
ret += wt * (1.0 - _tools.fidelity(rhoMx1, rhoMx2))**2

for povmlabel in mdl.povms.keys():
wt = item_weights.get(povmlabel, spamWeight)
fidelity = _tools.povm_fidelity(mdl, target_model, povmlabel)
ret += wt * (1.0 - fidelity)**2

elif spam_metric == "tracedist":
# Leakage-aware metrics NOT available.
for preplabel, m_prep in mdl.preps.items():
wt = item_weights.get(preplabel, spamWeight)
rhoMx1 = _tools.vec_to_stdmx(m_prep.to_dense(), mxBasis)
t_prep = target_model.preps[preplabel]
rhoMx2 = _tools.vec_to_stdmx(t_prep.to_dense(), mxBasis)
ret += wt * _tools.tracedist(rhoMx1, rhoMx2)

for povmlabel in mdl.povms.keys():
wt = item_weights.get(povmlabel, spamWeight)
ret += wt * _tools.povm_jtracedist(mdl, target_model, povmlabel)

else:
raise ValueError("Invalid spam_metric: %s" % spam_metric)

return ret

Expand Down
16 changes: 16 additions & 0 deletions pygsti/baseobjs/basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,22 @@ def ellookup(self):
self._lazy_build_labels()
self._ellookup = {lbl: el for lbl, el in zip(self._labels, self._elements)}
return self._ellookup

@property
def elindlookup(self) -> dict:
"""
A dictionary mapping labels to the index in self.elements that holds
that label's basis element.

Returns
-------
dict
"""
if self._ellookup is None:
if self._labels is None:
self._lazy_build_labels()
self._elindlookup = {lbl: ind for ind, lbl in enumerate(self._labels)}
return self._elindlookup

@property
def elements(self):
Expand Down
Loading
Loading