Skip to content

Parameterization-preserving gauge optimization #620

@rileyjmurray

Description

@rileyjmurray

EDIT: versions of the functions below were merged in as part of PR #410. I'm sure work remains on this issue (e.g., points raised by Corey below) so I'm leaving it open.


Consider the following fact.

Let $M_1$ be a model (e.g., an ExplicitOpModel) with parameterization $P_1$ (e.g., "CPTPLND" or "full TP"). Next, let $M_2$ be the representation of $M_1$ under a parameterization $P_2$, where $P_2$ allows for a strictly larger hypothesis class than does $P_1$.

We can't, in general, get confidence intervals for $M_1$ by looking at the likelihood function for $M_2$.

This fact is troublesome for computing confidence intervals of gauge-dependent quantities, since pyGSTi's gauge optimization tends to be performed in an expanded hypothesis class. This is the case even if we do gauge optimization on a CPTP model (CPTPLND parameterization) over the unitary group.

It's nominally straightforward to avoid this issue by gauge optimizing in whatever parameterization we want (e.g., Full), getting the gauge transformation, and then substituting modelmembers with suitably-transformed versions of themselves. The transformation + substitution can be facilitated with ComposedState, ComposedOp, and ComposedPOVM, as shown in the following code.

def transform_composedop_model(mdl : ExplicitOpModel, s : GaugeGroupElement):
    oldmdl = mdl
    mdl = oldmdl.copy()

    U    = StaticArbitraryOp(s.transform_matrix,         basis=oldmdl.basis)
    invU = StaticArbitraryOp(s.transform_matrix_inverse, basis=oldmdl.basis) 

    for key, rho in oldmdl.preps.items():
        assert isinstance(rho, ComposedState)
        static_rho = rho.state_vec
        errmap  = ComposedOp([rho.error_map, invU])
        mdl.preps[key] = ComposedState(static_rho, errmap)

    for key, povm in oldmdl.povms.items():
        assert isinstance(povm, ComposedPOVM)
        static_povm = povm.base_povm
        errmap = ComposedOp([U, povm.error_map])
        mdl.povms[key] = ComposedPOVM(errmap, static_povm, mx_basis=oldmdl.basis)

    for key, op in oldmdl.operations.items():
        op_s = ComposedOp([U, op, invU])
        mdl.operations[key] = op_s

    assert len(oldmdl.factories) == 0
    assert len(oldmdl.instruments) == 0

    mdl._clean_paramvec()  # transform may leave dirty members
    return mdl

A whole gauge optimization pipeline could look something like this.

def add_param_preserving_gauge_opt(results: ModelEstimateResults, est_key: str, gop_params: GSTGaugeOptSuite):
    from pygsti.protocols.gst import _add_gauge_opt
    est = results.estimates[est_key]
    seed_mdl = est.models['final iteration estimate']
    _add_gauge_opt(results, est_key, gop_params, seed_mdl)
    # ^ That can convert to whatever parameterization it wants. It'll write to 
    #   est._gaugeopt_suite.
    gop_params_dict = gop_params.to_dictionary(seed_mdl)  
    # ^ If we modified _add_gauge_opt to accept both GSTGaugeOptSuite objects and
    #   the output of the .to_dictionary(...) method of such objects, then we could avoid
    #   this awkward call to .to_dictionary(...) after the call to _add_gauge_opt.
    for gop_name in gop_params_dict.keys():
        ggel = est._gaugeopt_suite.gaugeopt_argument_dicts[gop_name]['_gaugeGroupEl']
        model_implicit_gauge = transform_composed_model(est.models['final iteration estimate'], ggel)
        est.models[gop_name] = model_implicit_gauge
    return

I want to integrate this into pyGSTi's default gauge optimization procedures that get executed when run(...) is called on a GateSetTomography object. For example, maybe we allow passing gaugeopt_suite='stdgaugeopt-keep-params' to the GateSetTomography constructor, and we get behavior that's just like if we used gaugeopt_suite='stdgaugeopt' without having to accept the change in model parameterization.

Here are some observations for myself as I try to sort this out.

  • GateSetTomography.run calls _add_gaugeopt_and_badfit, which calls _add_gauge_opt and _add_badfit_estimates. Meanwhile, _add_badfit_estimates can call _add_gauge_opt.
  • If we look at _add_gauge_opt we see that it takes in a GSTGaugeOptSuite object, which it immediately converts to a dict representation with a call to the object's .to_dictionary function (note: that function requires that we specify a starting model for gauge optimization, since no models are stored in GSTGaugeOptSuite objects). Then _add_gauge_opt makes calls to the add_gaugeoptimized instance function of Estimate objects from the .estimates field of results (which is a ModelEstimateResults object).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementRequest for a new feature or a change to an existing feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions