sandialabs / pyGSTi

A python implementation of Gate Set Tomography
http://www.pygsti.info
Apache License 2.0
134 stars 56 forks source link

Evotype dependent serialization bugs #346

Closed coreyostrove closed 10 months ago

coreyostrove commented 1 year ago

Some failing unit tests on the GST checkpointing branch revealed a serialization bug (really a bug that becomes apparent when trying to do serialization) that seems to be related to the use of the 'statevec' evotype. In particular, it looks like when using the 'statevec' evotype the _basis attribute is not always set properly remains initialized to None. We then encounter an error in serialization which expects there to be a basis object present and fails when trying to call the expected basis object's to_nice_serialization method.

Minimal working example for reproducing the bug:

from pygsti.modelpacks import smq1Q_XYI as std
test_model = std.target_model("static unitary", evotype='statevec')
test_model.to_nice_serialization()

Which returns the traceback:

 ---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[5], line 1
----> 1 test_model.to_nice_serialization()

File ~\Documents\pyGSTi_master_branch\pygsti\baseobjs\nicelyserializable.py:164, in NicelySerializable.to_nice_serialization(self)
    154 def to_nice_serialization(self):
    155     """
    156     Serialize this object in a way that adheres to "niceness" rules of common text file formats.
    157 
   (...)
    162         Python type, e.g. a string or list.
    163     """
--> 164     state = self._to_nice_serialization()
    165     if self._dbcoordinates is not None and isinstance(state, dict):
    166         # HACK: the code below adds the special dbcoordinates attribute to `state` when we're serializing to
    167         # something other than a MongoDB (which holds the dbcoordinates intrinsically in the document's
   (...)
    170         # a flag or something else that determines this, but for now we add this fragile HACK that checks the
    171         # caller names for 'add_mongodb_write_ops' (only in the call stack when we're serializing to MongoDB).
    172         import inspect

File ~\Documents\pyGSTi_master_branch\pygsti\models\explicitmodel.py:1603, in ExplicitOpModel._to_nice_serialization(self)
   1584 state.update({'basis': self.basis.to_nice_serialization(),
   1585               'default_gate_type': self.operations.default_param,
   1586               'default_prep_type': self.preps.default_param,
   (...)
   1599                                        if (self._param_interposer is not None) else None)
   1600               })
   1602 mmgraph = self.create_modelmember_graph()
-> 1603 state['modelmembers'] = mmgraph.create_serialization_dict()
   1604 return state

File ~\Documents\pyGSTi_master_branch\pygsti\modelmembers\modelmembergraph.py:181, in ModelMemberGraph.create_serialization_dict(self)
    179 sdict = OrderedDict()
    180 for mm_id, mm_node in self.mm_memo.items():
--> 181     sdict[str(mm_node.serialize_id)] = mm_node.mm.to_memoized_dict(self.mm_memo)
    183 # Tag extra metadata for root nodes
    184 for mm_type, root_nodes in self.mm_nodes.items():

File ~\Documents\pyGSTi_master_branch\pygsti\modelmembers\states\densestate.py:352, in DensePureState.to_memoized_dict(self, mmg_memo)
    349 mm_dict = super().to_memoized_dict(mmg_memo)
    351 mm_dict['dense_state_vector'] = self._encodemx(self.to_dense('Hilbert'))
--> 352 mm_dict['basis'] = self._basis.to_nice_serialization()
    354 return mm_dict

AttributeError: 'NoneType' object has no attribute 'to_nice_serialization'

A few additional notes. This looks to be specifically related to the use of the 'statevec' evotype. Excluding the evotype kwarg (I'm guessing this defaults to 'densitymx' even for a unitarily parameterized model?) we don't encounter the error. This also doesn't look to be related to the use of a statically parameterized model, as the above behavior is reproduced when using 'full unitary' as the parameterization as well (but again only when specifying the 'statevec' evotype). I've also inspected the state prep model members directly and can confirm that the '_basis' attribute is None in the cases where this fails.

Environment:

coreyostrove commented 1 year ago

Related serialization issue from the same unit test log as the one before, and thematically similar enough I am grouping these together. Serialization of implicit models also is encountering an error, but this time when using the 'stabilizer' evotype. Minimal example below:

from pygsti.modelpacks import smq1Q_XYI as std
proc_spec = std.processor_spec()
implicit_model = pygsti.models.modelconstruction.create_cloud_crosstalk_model(proc_spec, evotype='stabilizer')
implicit_model.to_nice_serialization()

Returns:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[31], line 1
----> 1 implicit_model.to_nice_serialization()

File ~\Documents\pyGSTi_master_branch\pygsti\baseobjs\nicelyserializable.py:164, in NicelySerializable.to_nice_serialization(self)
    154 def to_nice_serialization(self):
    155     """
    156     Serialize this object in a way that adheres to "niceness" rules of common text file formats.
    157 
   (...)
    162         Python type, e.g. a string or list.
    163     """
--> 164     state = self._to_nice_serialization()
    165     if self._dbcoordinates is not None and isinstance(state, dict):
    166         # HACK: the code below adds the special dbcoordinates attribute to `state` when we're serializing to
    167         # something other than a MongoDB (which holds the dbcoordinates intrinsically in the document's
   (...)
    170         # a flag or something else that determines this, but for now we add this fragile HACK that checks the
    171         # caller names for 'add_mongodb_write_ops' (only in the call stack when we're serializing to MongoDB).
    172         import inspect

File ~\Documents\pyGSTi_master_branch\pygsti\models\cloudnoisemodel.py:333, in CloudNoiseModel._to_nice_serialization(self)
    332 def _to_nice_serialization(self):
--> 333     state = super()._to_nice_serialization()
    334     state.update({'processor_spec': self.processor_spec.to_nice_serialization(),
    335                   'error_composition_mode': self.errcomp_type,
    336                   })
    337     mmgraph = self.create_modelmember_graph()

File ~\Documents\pyGSTi_master_branch\pygsti\models\implicitmodel.py:346, in ImplicitOpModel._to_nice_serialization(self)
    339 state.update({'basis': self.basis.to_nice_serialization(),
    340               'evotype': str(self.evotype),  # TODO or serialize?
    341               'layer_rules': self._layer_rules.to_nice_serialization(),
    342               'simulator': self.sim.to_nice_serialization()
    343               })
    345 mmgraph = self.create_modelmember_graph()
--> 346 state['modelmembers'] = mmgraph.create_serialization_dict()
    347 return state

File ~\Documents\pyGSTi_master_branch\pygsti\modelmembers\modelmembergraph.py:181, in ModelMemberGraph.create_serialization_dict(self)
    179 sdict = OrderedDict()
    180 for mm_id, mm_node in self.mm_memo.items():
--> 181     sdict[str(mm_node.serialize_id)] = mm_node.mm.to_memoized_dict(self.mm_memo)
    183 # Tag extra metadata for root nodes
    184 for mm_type, root_nodes in self.mm_nodes.items():

File ~\Documents\pyGSTi_master_branch\pygsti\modelmembers\operations\staticcliffordop.py:211, in StaticCliffordOp.to_memoized_dict(self, mmg_memo)
    208 U = self.unitary.to_dense() if isinstance(self.unitary, _LinearOperator) else self.unitary  # as in __init__
    210 mm_dict = super().to_memoized_dict(mmg_memo)
--> 211 mm_dict['smatrix'] = self._encodemx(self.smatrix())
    212 mm_dict['svector'] = self._encodemx(self.svector())
    213 mm_dict['basis'] = self.basis._to_nice_serialization()

TypeError: 'numpy.ndarray' object is not callable

I can confirm that this doesn't occur for the default evotype or the statevec evotype.

sserita commented 11 months ago

I believe I fixed both of these in commit 68564df. These were caught also caught by the serialization tests after the checkpoint merge and my desire for green checkmarks over red Xs got me to look at them. (In hindsight maybe I shouldn't admit that because it could lead to people realizing that breaking things will incentivize me to look at it faster than submitting non-broken things in...)

coreyostrove commented 11 months ago

Awesome! Great work, @sserita!

sserita commented 10 months ago

Closed with release of 0.9.12.