Conversion methods for PauliString#507
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #507 +/- ##
==========================================
- Coverage 89.65% 89.62% -0.03%
==========================================
Files 48 48
Lines 7015 7047 +32
==========================================
+ Hits 6289 6316 +27
- Misses 726 731 +5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
thierry-martinez
left a comment
There was a problem hiding this comment.
LGTM! I've added a few comments, but they're mainly nit-picking.
| if len(ps) < 2: | ||
| raise ValueError("Input string must have at least 2 characters (a sign followed by operators).") |
There was a problem hiding this comment.
Should we disallow empty Pauli strings?
Should the default sign be +?
For comparison:
>>> stim.PauliString("X")
stim.PauliString("+X")
>>> stim.PauliString("")
stim.PauliString("+")In addition, PauliString.from_str(str(PauliString(0, {}))) now raises an exception. I'm not sure whether this behavior is intentional.
| raise ValueError("Input string must have at least 2 characters (a sign followed by operators).") | ||
|
|
||
| References | ||
| sign_char, ops = ps[0], ps[1:] # Mypy disallows string unpacking |
There was a problem hiding this comment.
In Python, string unpacking is just a particular case of iterable unpacking. For example,
sign_char, ops = ps[0], ps[1:]uses slicing, so ops becomes a string. In contrast,
sign_char, *ops = psproduces a list of characters for ops. For the rest of the code, the difference is irrelevant.
If you prefer the more declarative string-unpacking style, you can be explicit about using iterable unpacking; mypy accepts this:
| sign_char, ops = ps[0], ps[1:] # Mypy disallows string unpacking | |
| sign_char, *ops = iter(ps) |
| sign_char, ops = ps[0], ps[1:] # Mypy disallows string unpacking | ||
|
|
||
| _sign_map = {"+": Sign.PLUS, "-": Sign.MINUS} | ||
| _axis_map = {"X": Axis.X, "Y": Axis.Y, "Z": Axis.Z} |
There was a problem hiding this comment.
The class Axis itself behaves much like a dictionary: Axis["X"] returns Axis.X. However, the expression "X" in Axis returns False. The proper mapping is Axis.__members__: "X" in Axis.__members__ returns True.
| """Return a string representation of the Pauli string.""" | ||
| pauli_str = ( | ||
| str(self.sign), | ||
| *(getattr(self.axes.get(node), "name", "I") for node in range(self.dim)), |
There was a problem hiding this comment.
I would prefer to avoid getattr because it isn't type-safe. Moreover, it's clearer to test explicitly whether an axis exists or not rather than relying on the fact that there is no field name in None.
| *(getattr(self.axes.get(node), "name", "I") for node in range(self.dim)), | |
| *(axis.name if (axis := self.axes.get(node)) else "I" for node in range(self.dim)), |
| ) | ||
|
|
||
| tab = MatGF2(np.zeros((2 * n, 2 * n + 1))) | ||
| return MatGF2(np.vstack((*(ps.to_tableau() for ps in self.x_map), *(ps.to_tableau() for ps in self.z_map)))) |
There was a problem hiding this comment.
| return MatGF2(np.vstack((*(ps.to_tableau() for ps in self.x_map), *(ps.to_tableau() for ps in self.z_map)))) | |
| return MatGF2(np.vstack([ps.to_tableau() for psmap in (self.x_map, self.z_map) for ps in psmap])) |
This commit introduces new methods for the
PauliStringclass:__str__andfrom_strprovide an interface with strings to simplify debugging,to_tableauandfrom_tableauprovide an interface with the_linalgmodule to facilitate implementing algorithms based on the stabilizer formalism.Additionally, the static method
PauliString.from_measured_nodeis subsumed by the functionextraction_ps_from_corrected_node. This follows from the observation that the returned Pauli string is truly specific to the circuit extraction algorithm, and it's not the canonical stabilizer given by a flow's correction function. The latter readswhereas the
extraction_ps_from_corrected_nodereturns a Pauli string acting on the output nodes only. Work on MBQC fidelity shows thatPauliStringobjects are useful beyond the circuit extraction routine, so this refactor aims at giving thePauliStringclass more independence.TODO
Up changelog