WIP: general leakage modeling#707
Conversation
…_leakage_report. Add a correctness test for DirectSumGaugeGroup.
…gaugeopt.py to remove need for n_leak kwarg.
…aise an error if needed). All tests pass!
…ge order ofarguments.
…n, modified eigenvalue_entanglement_fidelity to handle bases with implied leakage modeling, half-baked extension of eigenvalue_fidelity thats work-in-progress.
… II are both absent
|
Todo: add the following function. Maybe not strictly necessary, but I wrote it in another PR where it's distinctly less necessary. def trace_effect(op: _np.ndarray, op_basis: BasisLike, on_space: SpaceT = 'HilbertSchmidt'):
"""
Let `op` be the array representation of a superoperator G in `op_basis`,
where G maps from and to the space of order-d Hermitian operators.
The trace effect of G is the Heritian operator E that satifies
trace(G(ρ)) = trace(E ρ) for all order-d Hermitian matrices ρ.
If on_space='HilbertSchmidt', then this function returns a superket representation
of E in `op_basis`. If on_space='Hilbert', then we return E itself.
"""
d = int(_np.round(op.size ** 0.25))
assert op.shape == (d**2, d**2)
basis = op_basis if isinstance(op_basis, _Basis) else _Basis.cast(op_basis, dim=d**2)
vecI = _bt.stdmx_to_vec(_np.eye(d), basis)
vecE = op.T.conj() @ vecI
if on_space == 'HilbertSchmidt':
return vecE
else:
E = _bt.vec_to_stdmx(vecE, op_basis)
return E |
5664fa5 to
83c21cc
Compare
…:transform_composed_model. Those changes have been moved to PR #643.
|
The test in Original results are shown below. We don't rely on the exact numbers here. What matters is
qualitative aspects of how Gxpi2 and Gypi2 deviate from their respective targets. Since our
data generating model only applied leakage to Gxpi2, a "good" result reports much more error
in Gxpi2 than Gypi2. (It's not clear to me why stdgaugeopt lacks wildcard error.)
Leakage-aware guage optimization.
| Gate | ent. infidelity | 1/2 trace dist | 1/2 diamond dist | Max TOP | Unmodeled error |
|---------|-----------------|----------------|------------------|----------|-----------------|
| [] | 0.000009 | 0.002639 | 0.003724 | 0.000014 | 0.00007 |
| Gxpi2:0 | 0.000965 | 0.030946 | 0.040751 | 0.001629 | 0.000764 |
| Gypi2:0 | 0.000375 | 0.019367 | 0.025308 | 0.000531 | 0.000475 |
Standard gauge optimization
| Gate | ent. infidelity | 1/2 trace dist | 1/2 diamond dist | Max TOP |
|---------|-----------------|----------------|------------------|----------|
| [] | 0.000016 | 0.003644 | 0.005146 | 0.000026 |
| Gxpi2:0 | 0.000620 | 0.024758 | 0.032616 | 0.001000 |
| Gypi2:0 | 0.000611 | 0.024714 | 0.033323 | 0.001001 |
We'll run tests with subspace entanglement infidelity.
* For LAGO, infidelity of Gxpi2 is 2.57x larger than that of Gypi2;
we'll test for a 2x difference.
* For standard gauge optimization, Gxpi2 and Gypi2 have almost identical infidelities;
we'll test for a factor 1.1x there.The issue is that the factor 1.1x is, apparently, not enough to cover the change after merging in develop, using the latest numpy. The tests pass locally when I run with older numpy. I don't know exactly what changes in numpy / develop would cause the changes here, but that's the nature of integration tests. I'll probably regenerate the table and pick a new tolerance. Tests pass as of March 24 with the attached conda environment. Unclear how this is different from what's on CI. |
…move option to pass custom effect in computational_superkets function. Remove leading_dxd_submatrices_basis_vectors function.
|
|
||
|
|
||
| @set_docstring(NOTATION) | ||
| # TODO: document me |
There was a problem hiding this comment.
Must address before merge.
| # TODO: convert labels, ellookup, and elements to properties. | ||
| # Type annotations for Basis objects are of limited use | ||
| # without the Basis class declaring that these members exist. |
There was a problem hiding this comment.
Should open an issue and remove this comment from the PR changes.
| (1) it has a unique element whose label consists of (and only of) one | ||
| or more copies of the character 'I', and | ||
| (2) that element is proportional to a real orthogonal projector on H. |
There was a problem hiding this comment.
Not quite the case. More accurate to say that there is at least one element whose label is a string consisting of one or more copies of I (and no other characters), and that the element with the longest such label is proportional to a real orthogonal projector on H.
| # TODO: figure out where this helper should go. We use its basic functionality | ||
| # a couple of times in this file and we use it once in basis.py. |
There was a problem hiding this comment.
Resolve before merge.
| * The first element is proportional to E. Its label consists only of 'I's, | ||
| and is the longest such label in the basis. | ||
|
|
||
| * The first rank(E)^2 elements span M[C]. Labels of these elements (other | ||
| than the very first) match those of their corresponding elements in `basis`. | ||
|
|
||
| * All subsequent elements span M[H] \\ M[C]. Their labels are of the form | ||
| 'L[ell]', where 'ell' is the label of their corresponding element in `basis`. | ||
|
|
||
| * The final element is proportional to the projector onto C^⟂ | ||
| and is labeled 'L'. |
There was a problem hiding this comment.
Potentially dubious change worth discussing: use the letter 'C' for the first label, then strings of the form 'C[lbl]' with existing labels lbl for the next k^2-1 labels, then strings of the form 'L[lbl]' with exsiting labels lbl, and finally just the letter 'L'.
|
|
||
|
|
||
| def _add_all_hessians(mer: ModelEstimateResults, kwargs_for_projhess=None): | ||
| # NOTE: this function is not leakage-specific. |
There was a problem hiding this comment.
Maybe add a TODO that we should revisit the question of where this lives the next time we're making changes to pygsti.report.factory.py. Could open a GitHub issue about that and point to this line so we don't lose track of it.
| except AssertionError as e: | ||
| assert '`dim` must be a perfect square' in str(e) | ||
| return _np.NaN | ||
| return _np.nan |
There was a problem hiding this comment.
TODO: open a GitHub issue about np.NaN vs np.nan.
There was a problem hiding this comment.
Need close review
There was a problem hiding this comment.
Need close review
There was a problem hiding this comment.
Need close review
This PR promotes
pygsti.tools.leakagefrom a monolithic 616-line module into thetop-level subpackage
pygsti.leakage, and simultaneously generalizes leakage analysisso that the computational subspace is inferred from the basis rather than supplied as
an explicit
n_leak: intparameter.This PR is still WIP. I plan on revisiting the following before merge.
augment_for_leakage_modelingfunction, and the labelsfor elements of its returned Basis. Latest unimplemented thought is that if the i-th element of the new basis is (numerically) equal to the i-th element of the old basis then its label should stay the same.
n_leak > 0is currently used as a flag in some functions to say"activate leakage modeling behavior that you can infer from the basis."
EmbeddedOp._iter_matrix_elements.Subpackage layout
pygsti/tools/leakage.pyis deleted. Its contents are reorganized into five modules:leakage/core.pycomputational_effect,computational_superkets,computational_projector,augment_for_leakage_modelingleakage/metrics.pyleakage/models.pyleaky_qubit_model_from_pspec,promote_bb_to_btleakage/gaugeopt.pylagoified_gopparams_dicts,std_lago_gopsuite,add_lago_modelsleakage/reports.pyconstruct_leakage_reportpygsti/__init__.pynow importsleakage, makingpygsti.leakagea first-classsubpackage alongside
pygsti.algorithms,pygsti.models, etc.pygsti/tools/__init__.pyreplacesfrom .leakage import *with explicit re-exportsfrom
pygsti.leakage, so allpygsti.tools.*leakage names continue to resolve withoutany changes to their callers.
Basis-aware leakage detection
The central design change is a new
Basis.implies_leakage_modelingproperty. A basisimplies leakage modeling when it has a unique element whose label consists entirely of
the character
'I'(e.g.,'I','II','III') and that element is proportional toan orthogonal projector of rank strictly less than the full Hilbert space dimension.
This property drives three new functions in
leakage/core.py:computational_effect(basis)— extracts the Hermitian operator that orthogonallyprojects onto the computational subspace.
computational_superkets(basis)— returns a column-orthonormal matrix whose columnsspan the computational subspace of superoperator space.
computational_projector(basis)— the Hermicity-preserving superoperator thatprojects M[H] onto M[C].
The
n_leak: intkeyword argument is removed fromgaugeopt_to_target,_create_objective_fn, and_legacy_create_scalar_objective. Those functions now callmx_basis.implies_leakage_modelingdirectly, and look up the projector viacomputational_projector(mxBasis)when needed. The signatures ofsubspace_jtracedist,diamond_distance_projection_model,leaky_maximum_trace_dist,and
diamonddist_to_leakfree_cptpare similarly updated.Basis.is_hermitian()is a new method used internally bycomputational_superketstovalidate its input.
Basis construction:
augment_for_leakage_modelingaugment_for_leakage_modeling(basis, E)takes any Hermitian basis and a real orthogonalprojector
E, and returns a newExplicitBasisthat implies leakage modeling withcomputational subspace
C = range(E). Calling this function on the Gell-Mann basiswith
E = np.diag([1, 1, 0])basically gives you the l2p1 built-in basis.The returned basis has these properties (k = rank(E)):
E, labeled with all'I's (longest available).M[C].M[H] \\ M[C]. All are labeled'L[orig_label]', except thefinal element, which is proportional to
I − Eand labeled'L'.Element selection uses
pivot_indices_after_deflation(pivoted QR after orthogonaldeflation of a fixed vector) to prefer the original basis elements that are "most
supported" on each subspace.
Input validation:
Emust be real (‖imag(E)‖ ≤ 1e-10), Hermitian, and (proportionalto) an orthogonal projector; otherwise
ValueErroris raised.Leakage gauge groups and new model functions
leaky_qubit_model_from_pspecnow assigns aDirectSumUnitaryGroupas its defaultgauge group. This group is a block-diagonal subgroup of U(3), decomposed as U(2) ⨁ U(1):
U(2) acts on the 2-dimensional computational subspace and U(1) acts on the 1-dimensional
leakage level. The two summands are specified to
_direct_sum_unitary_groupby theirbases in Hilbert-Schmidt space —
'pp'of dimension 4 for the U(2) factor,'pp'ofdimension 1 for the U(1) factor — rather than by the dimension of the underlying Hilbert
space itself.
Supporting U(1) as a gauge-group factor requires two new classes in
gaugegroup.py:U1Group— a one-parameterGaugeGroupwhose elements are complex phases.U1GroupElement— implementstransform_matrix,transform_matrix_inverse,from_vector,to_vector, andinverse.DirectSumUnitaryGroupandDirectSumUnitaryGroupElementare extended to acceptU1Group/U1GroupElementcomponents alongside the existingUnitaryGaugeGroupandTrivialGaugeGrouptypes.promote_bb_to_bt(qubit ⨂ qutrit) is a new function inleakage/models.py. Given a2-qubit
ExplicitOpModel, it produces a 6-dimensional model in a tensor-product basispp ⨂ l2p1where the second qubit factor has an accessible leakage level. The functionhandles the lifting of 2-qubit unitaries to 2-qudit unitaries and POVM construction with
four effects (
'00','01','10','11'). Its default gauge group is a plainUnitaryGaugeGroupover the full 6-dimensional space.The
Leakage-automagic-2Q.ipynbnotebook is updated to usepromote_bb_to_btanddemonstrates a complete 2-qubit leakage GST workflow.
Other changes
matrixtools.is_projector— new utility function (used incomputational_superketsand
pop_transport_profile).jamiolkowski_iso— adds a fallback whenbasis.create_simple_equivalent()raises,which happens for leakage tensor-product bases.
find_closest_unitary_opmx— gains anop_basisparameter (defaults to'pp').EmbeddedOp— early return in_iter_matrix_elementswhen the embedded op fillsthe full state space, avoiding unnecessary iteration.
UnitaryGaugeGroup.__init__— raisesValueErrorwhenstate_space.udim == 1;callers should use
U1Groupinstead.gaugeopt_to_target— docstring consolidation: the Notes section that was splitacross two separate
"""..."""blocks is merged into one.gaugegroup.pycorrected (_np.array→_np.ndarray,_np.ndarry→_np.ndarray).algorithms/core.pyimport cleanup:BasisLikeimported frombaseobjs.basisdirectly rather than via the star-import chain.
Tests
A new
test/unit/leakage/package adds unit tests for the subpackage's public API:test_core.py—Basis.implies_leakage_modeling,Basis.is_hermitian(),matrixtools.is_projector,computational_effect,computational_superkets, andcomputational_projector(both the 1-arg basis-aware form and the 3-arg explicit form,plus consistency between them);
augment_for_leakage_modeling(structural properties,spanning of
M[C]andM[C]⊥, label format, non-diagonal projector round-tripthrough
computational_effect/computational_superkets, and input validation).test_metrics.py—choi_state(Hermitian and positive-semidefinite output),self-distance = 0 and self-fidelity = 1 for
subspace_jtracedist,subspace_superop_fro_dist, andsubspace_entanglement_fidelity; transport profiles(
gate_leakage_profile,gate_seepage_profile,pop_transport_profile) verifiedagainst identity and explicitly-constructed leaky gates;
subspace_diamonddistguarded with
@needs_cvxpy.test_models.py—leaky_qubit_model_from_pspec(state space dimension,DirectSumUnitaryGroupgauge group, trace-1 prep, POVM completeness) andpromote_bb_to_bt(6-dimensional state space,UnitaryGaugeGroupgauge group,four-effect POVM completeness, gate label preservation).
test_gaugeopt_correctness.pyaddsFindPerfectGauge_DirectSumGaugeGroupTester, which:leaky_qubit_model_from_pspec.the computational subspace, a U(1) phase on the leakage level).
gaugeopt_to_targetwithmethod='L-BFGS-B'over aDirectSumUnitaryGroup.The test runs with both a
U1Groupand aTrivialGaugeGroupfor the leakage factor,confirming that both configurations recover the gauge.
test_gaugegroup.pygainsU1GroupTester, covering construction, the identity transformat angle zero, unitarity for arbitrary angles,
from_vector/to_vectorround-trip, 2πangle wrapping, and the inverse element.
Migration notes
Code that imported directly from
pygsti.tools.leakagewill need to update topygsti.leakage. Anything that accessed leakage names throughpygsti.tools.*requiresno change.
Callers that passed
n_leaktogaugeopt_to_targetwill get aValueErrorat runtimeif the model's basis does not imply leakage modeling. The intended replacement is to use
a leakage basis (e.g.,
'l2p1') and letBasis.implies_leakage_modelingdrive thebehavior automatically.