Skip to content

Commit e774e71

Browse files
committed
Merge branch 'develop' into feature-label-aware-compilation
2 parents 64aeb81 + adb3a87 commit e774e71

180 files changed

Lines changed: 11171 additions & 3281 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/autodeploy.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616

1717
strategy:
1818
matrix:
19-
os: [ubuntu-latest, macos-13, windows-latest]
19+
os: [ubuntu-latest, macos-14, windows-latest]
2020
steps:
2121
- uses: actions/checkout@v4
2222
with:
@@ -81,4 +81,4 @@ jobs:
8181
- name: Publish package on PyPI
8282
uses: pypa/gh-action-pypi-publish@release/v1
8383
# With the use of OIDC, API tokens are no longer needed
84-
# See https://docs.pypi.org/trusted-publishers/using-a-publisher/ for more info
84+
# See https://docs.pypi.org/trusted-publishers/using-a-publisher/ for more info

CHANGELOG

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,64 @@
11
# CHANGELOG
22

3+
## [0.10.1] - 2026-07-06
4+
5+
Bugfix release. The only updates are to pyproject.toml to declare import-time dependencies.
6+
Thanks to @basnijholt for reporting this bug and creating a PR to fix.
7+
8+
## [0.10.0] - 2026-07-03
9+
10+
Major new features: symbolic error generator propagation (error generator polynomials), Lindblad-parameterized instruments, new GST objective functions, a generalized `pygsti.leakage` subpackage, turn-key MPI/SLURM helpers, and JupyterBook/ReadTheDocs documentation. Supported Python versions are now 3.10-3.13.
11+
12+
### Added
13+
* Error generator polynomials: symbolic Magnus/Taylor expansions and polynomial probability/expectation corrections, with a new tutorial (#789)
14+
* Zassenhaus formula (second order) and 20-1000x performance improvements for error generator propagation sensitivities (#687)
15+
* Effect-then-gate Lindblad parameterization for instruments: `Instrument.from_effects` / `Instrument.from_cptr_superops` (#693)
16+
* New GST objective types ('tvd', 'normalized-tvd', Lp^p) and black-box penalty functions (#649); iteration-specific optimizers (#690, @juangmendoza19)
17+
* `pygsti.leakage` subpackage; leakage modeling now inferred from the basis (`Basis.implies_leakage_modeling`), basis-aware report metrics, `U1Group`, `promote_bb_to_bt` (#707); leakage confidence intervals and more robust LAGO (#699)
18+
* `Protocol.run_mpi()` and `Protocol.stage_slurm()` for MPI-accelerated runs (#724)
19+
* Germ selection: `gate_penalty` option (#666) and implicit-model support (#668, @enielse)
20+
* `ImplicitOpModel.to_explicit_model` (#748); unconstrained 'GLNDU' Lindblad coefficient blocks (#755, #801); A/D line-label prefixes (#810, @sserita)
21+
22+
### Fixed
23+
* GST with penalty terms in objective functions (#528)
24+
* Numerous `Circuit` bugs (#765, #767, #772, #738); `Polynomial` commutativity bug (#750, #789)
25+
* Missing `return_basis` support for embedded ops (#592); zero-parameter model derivatives (#796, @yrasool)
26+
* IBMQ result retrieval with extra bits and preliminary MCM support (#679, @pcwysoc)
27+
* Wildcard budgets with `gaugeopt_suite=None` (#710, @enielse); cloud noise models with callable ops (#485, @sserita)
28+
* NumPy 2.x/2.5 compatibility (#703, #792); lazy `cvxpy` import (#803, #807, @basnijholt)
29+
* Many bugfixes surfaced by the revived notebook regression suite (#788, #821)
30+
31+
### Changed
32+
* Python 3.10-3.13 supported; 3.9 dropped (#780)
33+
* Documentation rebuilt as a Jupyter Book on ReadTheDocs (#673, @sserita; #770-#781)
34+
* Default germ selection mode is now 'compactEVD'; `assume_real` removed and `float_type` inferred from the model basis (#812)
35+
* Leakage migration: `pygsti.tools.leakage` -> `pygsti.leakage`; `n_leak` retired in favor of basis-driven inference (#707)
36+
* `Label` modernization: `time` field removed from default subclasses, homogeneous `sslbls` types, round-trippable serialization (#692, #769, @nkoskelo)
37+
* `LindbladCoefficientBlock` parameterization-by-composition refactor; `coefficient_labels` removed (#701, #755, #801)
38+
* `errorgen_gate_contributors` moved to `errgenpolytools` (#789); `torch` moved to the opt-in `pytorch` extra (#788)
39+
* Gauge optimization refactor and fidelity-objective redefinition (#669)
40+
41+
### Developer-Oriented Changes
42+
* CI time-to-green under 20 minutes (#780); parallel Cython build race fixed (#794); notebook regression in CI (#788)
43+
* Characterization/regression suites for `LindbladCoefficientBlock` (#750), `Circuit` (#768), `basis.py` (#790), `label.py` (#769)
44+
* `agent-docs/` orientation docs (#743); test warning burn-down (#739); `scripts/` and dead-code cleanup (#736, #744, #745)
45+
46+
### Expired Deprecations
47+
* `DenseOperatorInterface` / `DenseStateInterface` / `DenseEffectInterface` removed; use `.to_dense()` / `.set_dense()` (#805)
48+
49+
### Deprecations
50+
* The `n_leak` key of `construct_standard_report`'s `advanced_options` is deprecated and ignored; leakage metrics are now shown automatically based on each model's basis (#707)
51+
52+
## [0.9.14.3] - 2025-11-25
53+
54+
This is a bugfix release patching the following issues:
55+
56+
* The benchmarking tool formerly named `bsqale` has been renamed to `scarab` (@ndsieki, #685)
57+
* Bugfix for drift report generation caused by incorrect Plotly syntax. (@liuyichao82 #688)
58+
* Fix for a ReadTheDocs build failure that caused the documentation generation to fail. (#691)
59+
60+
Development-related change: Pushes to the `bugfix` branch no longer trigger automatic merges into `develop`, and these changes will need to be merged in manually going forward.
61+
362
## [0.9.14.2] - 2025-11-08
463

564
This is a bugfix release patching the following issues:

README.md

Lines changed: 45 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
********************************************************************************
2-
pyGSTi 0.9.14.2
2+
pyGSTi 0.10
33
********************************************************************************
44

55
[![master build](https://img.shields.io/github/actions/workflow/status/sandialabs/pyGSTi/beta-master.yml?branch=master&label=master)](https://github.com/sandialabs/pyGSTi/actions/workflows/beta-master.yml)
@@ -8,7 +8,7 @@
88

99
pyGSTi
1010
------
11-
**pyGSTi** is an open-source software for *modeling and characterizing noisy quantum information processors*
11+
**pyGSTi** is open-source software for *modeling and characterizing noisy quantum information processors*
1212
(QIPs), i.e., systems of one or more qubits. It is licensed under the Apache License, Version 2.0.
1313
Copyright information can be found in ``NOTICE``, and the license itself in ``LICENSE``.
1414

@@ -17,9 +17,9 @@ There are three main objects in pyGSTi:
1717
- `Model`: a description of a QIP's gate and SPAM operations (a noise model).
1818
- `DataSet`: a dictionary-like container holding experimental data.
1919

20-
You can do various things by with these objects:
20+
You can do various things with these objects:
2121

22-
- **Circuit simulation**: compute a the outcome probabilities of a `Circuit` using a `Model`.
22+
- **Circuit simulation**: compute the outcome probabilities of a `Circuit` using a `Model`.
2323
- **Data simulation**: simulate experimental data (a `DataSet`) using a `Model`.
2424
- **Model testing**: Test whether a given `Model` fits the data in a `DataSet`.
2525
- **Model estimation**: Estimate a `Model` from a `DataSet` (e.g. using GST).
@@ -32,10 +32,10 @@ In particular, there are a number of characterization protocols currently implem
3232
quality of a QIP in an average sense. PyGSTi implements standard "Clifford" RB
3333
as well as the more scalable "Direct" RB methods.
3434
- **Robust Phase Estimation (RPE)** is a method designed for quickly learning
35-
a few noise parameters of a QIP that particularly useful for tuning up qubits.
35+
a few noise parameters of a QIP that are particularly useful for tuning up qubits.
3636

3737
PyGSTi is designed with a modular structure so as to be highly customizable
38-
and easily integrated to new or existing python software. It runs using
38+
and easily integrated with new or existing python software. It runs using
3939
python 3.10 or higher. To facilitate integration with software for running
4040
cloud-QIP experiments, pyGSTi `Circuit` objects can be converted to IBM's
4141
**OpenQASM** and Rigetti Quantum Computing's **Quil** circuit description languages.
@@ -51,10 +51,7 @@ To install pyGSTi and only its required dependencies run:
5151

5252
``pip install pygsti[complete]``
5353

54-
The disadvantage to these approaches is that the numerous tutorials
55-
included in the package will then be buried within your Python's
56-
`site_packages` directory, which you'll likely want to access later on.
57-
**Alternatively**, you can **locally install** pyGSTi using the following commands:
54+
**Alternatively**, you can install pyGSTi from source using the following commands:
5855

5956
~~~
6057
cd <install_directory>
@@ -63,17 +60,10 @@ cd pyGSTi
6360
pip install -e .[complete]
6461
~~~
6562

66-
As above, you can leave off the `.[complete]` if you only went the minimal
67-
set of dependencies installed. You could also replace the `git clone ...`
68-
command with `unzip pygsti-0.9.x.zip` where the latter file is a downloaded
69-
pyGSTi source archive. Any of the above installations *should* build
70-
the set of optional Cython extension modules if a working C/C++ compiler
71-
and the `Cython` package are present. If, however, compilation fails or
72-
you later decided to add Cython support, you can rebuild the extension
73-
modules (without reinstalling) if you've followed the local installation
74-
approach above using the command:
63+
Any of the above installations *should* build the set of optional Cython extension modules if a working C/C++ compiler and the `Cython` package are present.
7564

76-
`python setup.py build_ext --inplace`
65+
If you installed from source then you have the option of (re)building Cython extensions at any time.
66+
You can do that by running `python setup.py build_ext --inplace`.
7767

7868
Finally, [Jupyter notebook](http://jupyter.org/) is highly recommended as
7969
it is generally convenient and the format of the included tutorials and
@@ -82,14 +72,14 @@ it can be installed separately.
8272

8373
Getting Started
8474
---------------
85-
Here's a couple of simple examples to get you started.
75+
Here are a couple of simple examples to get you started.
8676

8777
#### Circuit simulation
8878
To compute the outcome probabilities of a circuit, you just need to create
8979
a `Circuit` object (describing your circuit) and a `Model` object containing
9080
the operations contained in your circuit. Here we use a "stock" single-qubit `Model`
91-
containing *Idle*, *X(&pi;/2)*, and *Y(&pi;/2)* gates labelled `Gi`, `Gx`,
92-
and `Gy`, respectively:
81+
containing an unlabeled *Idle* gate along with *X(&pi;/2)* and *Y(&pi;/2)* gates
82+
labelled `Gxpi2` and `Gypi2`, respectively:
9383
~~~
9484
import pygsti
9585
from pygsti.modelpacks import smq1Q_XYI
@@ -106,20 +96,20 @@ hardware designed to implement a (small) system of quantum bits (qubits).
10696
Here's the basic idea:
10797

10898
1. you tell pyGSTi what gates you'd ideally like to perform
109-
2. pyGSTi tells you what circuits it want's data for
99+
2. pyGSTi tells you what circuits it wants data for
110100
3. you perform the requested experiments and place the resulting
111-
data (outcome counts) into a text file that looks something like:
101+
data (outcome counts) into a text file that looks something like this:
112102

113103
```
114104
## Columns = 0 count, 1 count
115105
{} 0 100 # the empty sequence (just prep then measure)
116-
Gx 10 90 # prep, do a X(pi/2) gate, then measure
117-
GxGy 40 60 # prep, do a X(pi/2) gate followed by a Y(pi/2), then measure
106+
Gx 10 90 # prep, do an X(pi/2) gate, then measure
107+
GxGy 40 60 # prep, do an X(pi/2) gate followed by a Y(pi/2), then measure
118108
Gx^4 20 80 # etc...
119109
```
120110
121-
4. pyGSTi takes the data file and outputs a "report" - currently a
122-
HTML web page.
111+
4. pyGSTi takes the data file and outputs a "report" - currently
112+
an HTML web page.
123113
124114
In code, running GST looks something like this:
125115
~~~
@@ -154,35 +144,27 @@ report.write_html("myReport", auto_open=True, verbosity=1) # Can also write out
154144
155145
Documentation
156146
-------------
157-
There are numerous tutorials (meant to be pedagogical) and examples (meant to be demonstrate
158-
how to do some particular thing) in the `pyGSTi/docs` directory. These are stored as MyST Markdown
147+
There are numerous tutorials and examples in the `pyGSTi/docs` directory. These are stored as MyST Markdown
159148
for version control convenience, but can be converted to Jupyter notebooks as needed using Jupytext.
160149
161-
#### Viewing the documentation *online*
150+
### Viewing the documentation *online*
162151
The recommended way to view the documentation is on [ReadTheDocs](https://pygsti.readthedocs.io/en/latest/),
163152
although the raw Markdown files can also be looked at on [GitHub](https://github.com/sandialabs/pyGSTi/blob/master/docs/markdown/intro.md).
164153
165154
The site renders the source MyST Markdown without executing notebook cells, so you won't see outputs (plots, tables) inline.
166-
Each rendered page offers two ways to run the notebook yourself:
155+
You can download the notebooks or run them on the cloud with buttons in the upper-right of the given page.
167156
168-
- **Rocket icon → Binder or Colab:** launches a fully-provisioned notebook environment in your browser with no local install.
169-
- **Cloud/download icon → "Download this page" dropdown:** grab the `.ipynb` (or the `.md` source) and run it in your own Jupyter setup.
157+
- **Download icon → ipynb, md, or pdf.** If you just click the `.ipynb` or `.md` options then the source will open as raw text in a new tab.
158+
If you want to save those files you need to **right click the desired format and select `Save Link As ...`**, then enter the file name with the appropriate extension.
159+
Here's a screenshot of what that can look like.
170160
171-
#### Building the documentation *locally*
172-
The docs are built using [Jupyter Book v1](https://jupyterbook.org). Note: v2 is a separate product (MyST Engine + Node.js)
173-
that doesn't support our autodoc-based API reference yet, so we pin `jupyter-book<2`.
161+
<img src="docs/download-notebook-save-as.png" width="250">
174162
175-
To install the build dependencies along with pyGSTi:
176-
``pip install -e .[docs]``
177-
178-
then build:
179-
``jb build docs``
163+
- **Rocket icon → Binder or Colab:** launches a fully-provisioned notebook environment in your browser with no local install. Right now this is clunky and not recommended.
180164
181-
Then open `docs/_build/html/index.html` in a web browser to look through the documentation.
182-
183-
#### Running notebooks *locally*
184-
It can also be convenient to build and run the tutorials locally. We can do this using Jupytext
185-
for conversion and then start a Jupyter notebook or JupyterLab server to run the notebooks.
165+
### Running notebooks *locally*
166+
It can be convenient to just build and run the tutorials locally.
167+
We can do this using Jupytext for conversion and then start a Jupyter notebook or JupyterLab server to run the notebooks.
186168
Assuming you've followed the *local installation* directions above:
187169
188170
* Change to the docs directory, by running:
@@ -199,7 +181,21 @@ where you can start the first `markdown/intro.ipynb` notebook. Note that the ke
199181
command to execute a cell within the Jupyter notebook is ``Shift+Enter``, not
200182
just ``Enter``.
201183
202-
#### Contributing notebook changes
184+
### Building the web documentation *locally*
185+
The web docs are built using [Jupyter Book v1](https://jupyterbook.org). Note: v2 is a separate product that doesn't support our autodoc-based API reference yet, so we pin `jupyter-book<2`.
186+
187+
**WARNING.** Building the web docs takes a LONG TIME, because they include a very large **API Reference**.
188+
If you only want to read or work with the tutorials and examples, don't do a full build — just convert and [run the notebooks directly](#running-notebooks-locally).
189+
190+
To install the build dependencies along with pyGSTi:
191+
``pip install -e .[docs]``
192+
193+
then build:
194+
``jb build docs``
195+
196+
Then open `docs/_build/html/index.html` in a web browser to look through the documentation.
197+
198+
### Contributing notebook changes
203199
**Only the `docs/markdown/*.md` files are version-controlled.** The paired `.ipynb` files — generated next to
204200
each `.md` under `docs/markdown/` — are gitignored build artifacts. The canonical source is the `.md` file, and
205201
edits there "win" on the next sync. So:

agent-docs/known-debt.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,24 @@ The practical issue is therefore *not* "the fallback is slow." It is that silent
140140

141141
**Tracker.** [sandialabs/pyGSTi#715](https://github.com/sandialabs/pyGSTi/issues/715).
142142

143+
## 18. Inconsistent ModelMember copy/deepcopy/pickle semantics around `_parent`
144+
145+
**What it is.** Three distinct code paths handle `_parent` differently when copying a `ModelMember`:
146+
147+
1. **`ModelChild.copy(parent=...)`** (`modelmember.py`) — seeds the deepcopy memo with `memo[id(self.parent)] = None`, so the parent model is *not* copied; caller sets the new parent explicitly.
148+
2. **`ModelChild.__getstate__`** — nulls `_parent` for the pickle/JSON path; `relink_parent` restores it on deserialization.
149+
3. **`_DenseCopyMixin.__deepcopy__`** (`modelmember.py`) — copies `__dict__` verbatim, *including* `_parent`. A bare `copy.deepcopy(dense_member)` therefore deep-copies the entire parent model as a side effect.
150+
151+
Path 3 is *intentionally* inconsistent with paths 1 and 2 because the regression test for [#651](https://github.com/sandialabs/pyGSTi/issues/651) (`test/unit/modelmembers/test_operation.py::test_deepcopy`) requires it: the test calls `copy.deepcopy(op)` where `op._parent` is a live model, then asserts that `o2.parent` is a distinct but equivalent model.
152+
153+
**Where it bites.** Any future maintainer who "normalises" `_DenseCopyMixin.__deepcopy__` to null or drop `_parent` (for consistency with `__getstate__` or `ModelChild.copy`) will silently break the #651 test with `AttributeError: 'NoneType' object has no attribute 'create_modelmember_graph'`. The `_DenseCopyMixin` docstring in `modelmember.py` carries a prominent warning about this, but it is easy to miss during a refactor.
154+
155+
Additionally, the path-3 behaviour is arguably surprising to callers: `copy.deepcopy(op)` has an invisible, potentially expensive side effect (copying the parent model) that `ModelChild.copy()` deliberately avoids.
156+
157+
**Do not change `_DenseCopyMixin.__deepcopy__` without first resolving the tracking issue.**
158+
159+
**Tracker.** [sandialabs/pyGSTi#804](https://github.com/sandialabs/pyGSTi/issues/804)
160+
143161
## 17. POVM inheritance structure refactor
144162

145163
**What it is.** [pygsti/modelmembers/povms/povm.py](../pygsti/modelmembers/povms/povm.py)'s `POVM` base class and `_BasePOVM` have inverted-ish roles: `POVM` actually implements a fully-wired-up zero-parameter POVM, but most concrete subclasses do have parameters. This forces awkward overrides.

docs/_toc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ parts:
9696
- file: markdown/simulation/CircuitSimulation-CHP
9797
- file: markdown/simulation/DataSimulation
9898
- file: markdown/simulation/ErrorGeneratorPropagation
99+
- file: markdown/simulation/ErrorGeneratorPolynomials
99100
- file: markdown/simulation/ForwardSimulationTypes
100101

101102
- file: markdown/Reporting

docs/api.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,22 @@ Circuit/COPA layouts that organize (and distribute) the computation behind forwa
208208
pygsti.layouts.prefixtable
209209
pygsti.layouts.termlayout
210210

211+
``pygsti.leakage``
212+
~~~~~~~~~~~~~~~~~~
213+
214+
Leakage-aware modeling, gauge optimization, metrics, and reporting for QIPs with leakage levels.
215+
216+
.. autosummary::
217+
:toctree: _autosummary
218+
:template: custom-module-template.rst
219+
:recursive:
220+
221+
pygsti.leakage.core
222+
pygsti.leakage.gaugeopt
223+
pygsti.leakage.metrics
224+
pygsti.leakage.models
225+
pygsti.leakage.reports
226+
211227
``pygsti.modelmembers``
212228
~~~~~~~~~~~~~~~~~~~~~~~
213229

docs/download-notebook-save-as.png

154 KB
Loading

docs/markdown/Simulation.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ These tutorials cover how `pyGSTi` simulates circuits — computing the outcome
44

55
- [Circuit simulation](simulation/CircuitSimulation) — compute outcome probabilities for a circuit from a model, including stabilizer/CHP and explicit- vs. implicit-model variants.
66
- [Data simulation](simulation/DataSimulation) — turn model predictions into simulated experimental datasets (finite-shot samples).
7-
- [Error generator propagation](simulation/ErrorGeneratorPropagation) — propagate error generators through the layers of a circuit.
7+
- [Error generator propagation](simulation/ErrorGeneratorPropagation) — propagate error generators through the layers of a circuit to get numerical quantities of interest.
8+
- [Error generator polynomials](simulation/ErrorGeneratorPolynomials) — propagate error generators through the layers of a circuit to get symbolic representations of quantities of interest, like end-of-circuit error generators.
89
- [Forward simulation types](simulation/ForwardSimulationTypes) — the available forward simulators (matrix, map, term, …) and when to use each.

0 commit comments

Comments
 (0)