Commit 8064d27
Rewrite QPY
* Rewrite QPY `ParameterExpression` handling in pure Polish form
This patch is a fairly invasive change, but one that fixes the known
edge cases of replay generation from `ParameterExpression` itself. This
fixes several `pickle`, `copy`/`deepcopy` and QPY bugs around
`ParameterExpression`.
The Python-space QPY loader is modified in a small way to allow it to
handle QPY-format permitted "replay" elements that act between two bare
values; this was always allowed by the QPY spec, but couldn't be
generated by Python-space QPY/`ParameterExpression`. Doing so actually
significantly simplifies the loading logic, since it no longer needs to
reflect certain arithmetic operations. The new Rust-space
`ParameterExpression` uses binary operations with two numeric operands
(e.g. `Add(2, 0)`) to safely propagate bare values through the QPY
replay. This was not previously necessary in Python space because there
was no public interface to create a bare-numeric `ParameterExpression`
without replayable expressions having been tracked. Similarly,
cancelled-out symbols are propagated in the replay with `Sub(x, x)`
operations, which already must work across all compliant QPY loaders,
and both Rust- and Python-space `ParameterExpression.
History
-------
The QPY replay was _intended_ to be a pure Polish-notation
representation of the operations to take to rebuild the expression.
This mostly worked fine at the time, but the patch was written under a
lot of stress and without full CI tooling, due to it being in response
to a security bug. This led to some less-than-ideal parts of the format
specification, such as the start/end recursion opcodes in the QPY format
not actually being necessary; they are actually zero-operand no-ops to
the stack, but this wasn't noticed during the patch due to time
pressure.
Further, as `ParameterExpression` moved to Rust, the tracked internal
"replay" list disappeared, since we could now reliably walk the
expression tree and issue rebuild commands directly. This generated
replay, however, _only_ examined the expression and not potentially
cancelled-out parameters.
All together, there were several problems affecting QPY (both Rust and
Python), and `ParameterExpression`'s interaction with `pickle` and the
copy module, mostly relating to situations where the resulting
expression had cancelled-out parameters or had degraded to be a bare
value. For example, expressions like `x - x` (or `0*x + 3`, or
arbitrarily complex extensions of these) are supposed to retain a
reference to `x` for binding purposes, but failed to do so after pickle
or QPY roundtrips. Several of these expressions failed during QPY
deserialisation, as the replay stack handling failed to cope with bare
values.
* Credit Gadi
Gadi did much of the exploratory work of the previous commit, and wrote
several of the test cases I pulled in - I forgot to include the line
before.
Co-authored-by: Gadi Aleksandrowicz <gadial@gmail.com>
* Correct handling of vector-symbol names in map
I was misled by `Symbol::name` not returning the complete name. We
should probably rename that method in a follow-up.
* Avoid symbol cloning in QPY replay output
Using `Mul(sym, 0)` also cancels out the symbol, and doesn't require an
internal clone.
Co-authored-by: Julien Gacon <jul@zurich.ibm.com>
* Make inner-worker recursive call clearer
* Add hasher to `IndexSet`
* Update comments
* Expand `ParameterExpression` backwards-compatibility testing
* Skip backwards-compatibility tests for broken Qiskit versions
All versions of Qiskit that have Rust-space `ParameterExpression`
(introduced in v2.2) up to (excluding) the roll-up commit of this PR
(intended release in v2.4.0rc3) produce invalid QPY for expressions with
cancellations. Here, we skip the known-bad versions, since there is no
way to completely recover from such files; the cancelled-out expression
_might_ be zero, or might truly have been an arbitrary numeric value
(e.g. in the case `0*x + 1.5`, the `1.5` is completely lost in the
broken versions of Qiskit).
The previous version-handling mechanisms in the QPY
backwards compatibility tests couldn't cope with an `rc` being an upper
bound in a version range (since it only dealt with the "release"
component), so here we also update the checking system to use the
complete version of `packing.version` comparisons.
* Add known-issue release note
* Add missing dependency installation
* Separate conditional test into separate file
---------
Co-authored-by: Gadi Aleksandrowicz <gadial@gmail.com>
Co-authored-by: Julien Gacon <jul@zurich.ibm.com>ParameterExpression handling in pure Polish form (#15934)1 parent 6be537f commit 8064d27
13 files changed
Lines changed: 532 additions & 439 deletions
File tree
- crates
- circuit/src/parameter
- qpy/src
- qiskit/qpy/binary_io
- releasenotes/notes
- test
- python
- circuit
- qpy
- qpy_compat
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| 15 | + | |
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
| |||
134 | 135 | | |
135 | 136 | | |
136 | 137 | | |
137 | | - | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
138 | 194 | | |
139 | 195 | | |
140 | 196 | | |
| |||
188 | 244 | | |
189 | 245 | | |
190 | 246 | | |
191 | | - | |
192 | | - | |
193 | | - | |
194 | | - | |
195 | | - | |
| 247 | + | |
196 | 248 | | |
197 | 249 | | |
198 | 250 | | |
199 | 251 | | |
200 | 252 | | |
201 | 253 | | |
202 | | - | |
203 | | - | |
204 | | - | |
205 | | - | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
206 | 257 | | |
207 | 258 | | |
208 | 259 | | |
| |||
257 | 308 | | |
258 | 309 | | |
259 | 310 | | |
260 | | - | |
261 | | - | |
262 | | - | |
263 | | - | |
| 311 | + | |
264 | 312 | | |
265 | 313 | | |
266 | | - | |
267 | | - | |
268 | | - | |
269 | | - | |
270 | | - | |
| 314 | + | |
271 | 315 | | |
272 | 316 | | |
273 | 317 | | |
| |||
312 | 356 | | |
313 | 357 | | |
314 | 358 | | |
315 | | - | |
316 | | - | |
317 | | - | |
318 | | - | |
319 | | - | |
320 | | - | |
321 | | - | |
322 | | - | |
323 | | - | |
324 | 359 | | |
325 | 360 | | |
326 | 361 | | |
| |||
1370 | 1405 | | |
1371 | 1406 | | |
1372 | 1407 | | |
1373 | | - | |
1374 | | - | |
1375 | | - | |
1376 | | - | |
1377 | | - | |
1378 | | - | |
1379 | | - | |
1380 | | - | |
1381 | | - | |
1382 | | - | |
1383 | | - | |
1384 | | - | |
1385 | | - | |
1386 | | - | |
1387 | | - | |
1388 | | - | |
1389 | | - | |
1390 | | - | |
1391 | | - | |
| 1408 | + | |
| 1409 | + | |
1392 | 1410 | | |
1393 | 1411 | | |
1394 | | - | |
1395 | | - | |
1396 | | - | |
1397 | | - | |
1398 | | - | |
1399 | | - | |
1400 | | - | |
1401 | | - | |
1402 | | - | |
1403 | | - | |
1404 | | - | |
1405 | | - | |
1406 | | - | |
1407 | | - | |
| 1412 | + | |
| 1413 | + | |
1408 | 1414 | | |
1409 | 1415 | | |
1410 | 1416 | | |
1411 | 1417 | | |
1412 | | - | |
1413 | | - | |
1414 | | - | |
1415 | | - | |
| 1418 | + | |
| 1419 | + | |
1416 | 1420 | | |
1417 | 1421 | | |
1418 | 1422 | | |
| |||
1872 | 1876 | | |
1873 | 1877 | | |
1874 | 1878 | | |
| 1879 | + | |
| 1880 | + | |
| 1881 | + | |
| 1882 | + | |
| 1883 | + | |
| 1884 | + | |
| 1885 | + | |
1875 | 1886 | | |
1876 | 1887 | | |
1877 | 1888 | | |
| |||
1880 | 1891 | | |
1881 | 1892 | | |
1882 | 1893 | | |
1883 | | - | |
1884 | | - | |
1885 | | - | |
1886 | | - | |
1887 | | - | |
1888 | | - | |
1889 | | - | |
1890 | | - | |
1891 | | - | |
1892 | | - | |
1893 | | - | |
1894 | | - | |
1895 | | - | |
1896 | | - | |
| 1894 | + | |
1897 | 1895 | | |
1898 | 1896 | | |
1899 | 1897 | | |
| |||
2075 | 2073 | | |
2076 | 2074 | | |
2077 | 2075 | | |
2078 | | - | |
| 2076 | + | |
2079 | 2077 | | |
2080 | 2078 | | |
2081 | 2079 | | |
| 2080 | + | |
2082 | 2081 | | |
2083 | 2082 | | |
2084 | | - | |
2085 | | - | |
| 2083 | + | |
| 2084 | + | |
| 2085 | + | |
| 2086 | + | |
| 2087 | + | |
2086 | 2088 | | |
2087 | 2089 | | |
2088 | 2090 | | |
| |||
2103 | 2105 | | |
2104 | 2106 | | |
2105 | 2107 | | |
2106 | | - | |
| 2108 | + | |
2107 | 2109 | | |
2108 | 2110 | | |
2109 | 2111 | | |
| |||
2129 | 2131 | | |
2130 | 2132 | | |
2131 | 2133 | | |
2132 | | - | |
2133 | | - | |
| 2134 | + | |
| 2135 | + | |
2134 | 2136 | | |
2135 | 2137 | | |
2136 | 2138 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
| |||
123 | 124 | | |
124 | 125 | | |
125 | 126 | | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
126 | 133 | | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
132 | 138 | | |
133 | 139 | | |
134 | 140 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
661 | 661 | | |
662 | 662 | | |
663 | 663 | | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
664 | 669 | | |
665 | 670 | | |
666 | 671 | | |
| |||
0 commit comments