Open Pablovinas opened 2 weeks ago
Hi @Pablovinas, thanks for the detailed report!
This isn't a bug per se, but rather related to a fairly old design choice to make the parameter management for models update lazily. As you've identified above, as currently implemented simply assigning a new value to a model member in one of the Model
object's member dictionaries doesn't actually force a rebuild (i.e. a call to _rebuild_paramvec
) in and of itself. I wasn't around for the original implementation of this, but I imagine it was for performance related considerations (rebuilding the parameter vector is actually a pretty expensive operation). The downside, as you discovered, is unexpected behavior wherein the values returned for certain model attributes can fall out of sync with the correct values depending on when you make the queries. This is not a particularly great behavior to have and it has tripped me up a number of times as well, so I think this is a good opportunity to fix this.
There are a couple options I can think of on how to proceed, so I wanted to open up some discussion on this to see what other folks think.
Model
and add additional rebuild checks for publicly facing properties where we identify a potential for post-assignment inconsistencies.OrderedMemberDict
, adding a call to _rebuild_paramvec
to the __setitem__
method here (https://github.com/sandialabs/pyGSTi/blob/d27e4e688a64914a0b7aaec1de91aa56f7ce70c2/pygsti/models/memberdict.py#L352).I suspect the answer is 3, but am open to thoughts on this. Option 2 would address the particular problem that you encountered above, but it would leave the door open to other possible avenues for desynchronization. As an example, models typically inherit their parameter labels from the parameter labels of the constituent model member objects (though not always strictly so, as in the case of parameter collection which you mentioned using above). With just the fix in option 2 it would be possible to create a desynchronization condition by querying the model's parameter labels immediately after manually updating the parameter labels for one of it's children. Option 1 would address this, but has the potential for non-trivial performance impacts if we aren't careful, so I'd want to check to make sure we aren't calling the parameter_labels
property in any particularly hot loops before committing to that change.
Describe the bug After adding operations to an explicit model constructed via
pygsti.models.ExplicitOpModel()
, the methodparameter_labels()
returns an empty array and does not recognize the model's parameters. If the model has been initially imported frompygsti.modelpacks
, the array is not updated with the new parameters.To Reproduce Steps to reproduce the behavior:
ExplicitModel.ipynb
tutorial. We can additionally define custom operations as in theCustomOperator.ipynb
tutorial and keep track of our parameters after naming them using theparameter_labels(self)
property.mdl.parameter_labels
to get the vector of model member's parameters within the model. It returns an empty array, causing further issues such as thecollect_parameters()
method not working.Expected behavior I would expect the labels and parameters defined in the operations to be automatically recognised and updated in the model containing them.
Environment:
Additional context I have been able to circumvent this issue by explicitly using
mdl._rebuild_paramvec()
. However, I believe this should be done automatically when defining the model.