Skip to content

Commit 4e6f1ff

Browse files
author
Guen Prawiroatmodjo
authored
docs: Add docs workflow, publish notebooks and readme
2 parents d0b9c09 + f558733 commit 4e6f1ff

11 files changed

Lines changed: 785 additions & 26 deletions

File tree

.github/workflows/cd.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,65 @@ jobs:
3737
cd ./src/js
3838
npm ci
3939
npm run build
40+
# Upload the built JavaScript files as an artifact
41+
- name: Upload JavaScript build artifacts
42+
uses: actions/upload-artifact@v4
43+
with:
44+
name: bundle.js
45+
path: ./src/crumpy/bundle.js
4046

4147
- uses: hynek/build-and-inspect-python-package@v2
4248

49+
build-docs:
50+
needs: [dist]
51+
runs-on: ubuntu-latest
52+
permissions:
53+
contents: read
54+
pages: write
55+
id-token: write
56+
environment:
57+
name: github-pages
58+
url: ${{ steps.deploy-pages.outputs.page_url }}
59+
if: github.ref == 'refs/heads/main'
60+
steps:
61+
- name: Checkout repo
62+
uses: actions/checkout@v4
63+
64+
- name: Set up Python
65+
uses: actions/setup-python@v5
66+
with:
67+
python-version: "3.x"
68+
69+
- name: Set up UV
70+
uses: astral-sh/setup-uv@v6
71+
72+
- name: Install Pandoc
73+
run: |
74+
sudo apt-get update
75+
sudo apt-get install -y pandoc
76+
77+
- name: Download JavaScript build artifacts
78+
uses: actions/download-artifact@v5
79+
with:
80+
name: bundle.js
81+
path: src/crumpy
82+
83+
- name: Build documentation
84+
run: |
85+
uvx nox -s docs
86+
87+
- name: Configure GitHub Pages
88+
uses: actions/configure-pages@v5
89+
90+
- name: Upload Pages artifact
91+
uses: actions/upload-pages-artifact@v3
92+
with:
93+
path: docs/_build/html
94+
95+
- name: Deploy to GitHub Pages
96+
id: deploy-pages
97+
uses: actions/deploy-pages@v4
98+
4399
publish:
44100
needs: [dist]
45101
name: Publish to PyPI

.github/workflows/ci.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,9 @@ jobs:
4444
strategy:
4545
fail-fast: false
4646
matrix:
47-
python-version: ["3.9", "3.13"]
47+
python-version: ["3.11", "3.12", "3.13"]
4848
runs-on: [ubuntu-latest, windows-latest, macos-14]
4949

50-
include:
51-
- python-version: "pypy-3.10"
52-
runs-on: ubuntu-latest
53-
5450
steps:
5551
- uses: actions/checkout@v5
5652
with:

README.md

Lines changed: 159 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,165 @@
1-
# crumpy
1+
<div align="center">
22

3-
[![Actions Status][actions-badge]][actions-link]
4-
[![Documentation Status][rtd-badge]][rtd-link]
3+
# CrumPy
54

6-
[![PyPI version][pypi-version]][pypi-link]
7-
[![Conda-Forge][conda-badge]][conda-link]
8-
[![PyPI platforms][pypi-platforms]][pypi-link]
5+
Visualize quantum circuits with error propagation in a Jupyter widget.
96

10-
[![GitHub Discussion][github-discussions-badge]][github-discussions-link]
7+
<img src="./_static/images/bit_flip_in_jupyter.png" alt="jupyter notebook cell with quantum circuit diagram output" width=400>
8+
9+
---
10+
11+
This package builds off of the existing circuit visualizations of
12+
[Crumble](https://algassert.com/crumble), a stabilizer circuit editor and
13+
sub-project of the open-source stabilizer circuit project
14+
[Stim](https://github.com/quantumlib/Stim).
15+
16+
</div>
17+
18+
---
19+
20+
## Installation
21+
22+
**Requires:** Python 3.11+
23+
24+
```console
25+
pip install crumpy
26+
```
27+
28+
## Usage
29+
30+
CrumPy provides a convenient Jupyter widget that makes use of Crumble's ability
31+
to generate quantum circuit timeline visualizations with Pauli propagation from
32+
[Stim circuit specifications](https://github.com/quantumlib/Stim/blob/main/doc/file_format_stim_circuit.md#the-stim-circuit-file-format-stim).
33+
34+
### Using `CircuitWidget`
35+
36+
`CircuitWidget` takes a
37+
[Stim circuit specification](https://github.com/quantumlib/Stim/blob/main/doc/file_format_stim_circuit.md#the-stim-circuit-file-format-stim)
38+
in the form of a Python `str`. To convert from the official Stim package's
39+
`stim.Circuit`, use `str(stim_circuit)`. If coming from another circuit type, it
40+
is recommended to first convert to a `stim.Circuit` (e.g., with Stim's
41+
[`stimcirq`](https://github.com/quantumlib/Stim/tree/main/glue/cirq) package),
42+
then to `str`. Note that not all circuits may be convertible to Stim.
43+
44+
```python
45+
from crumpy import CircuitWidget
46+
47+
your_circuit = """
48+
H 0
49+
CNOT 0 1
50+
"""
51+
52+
circuit = CircuitWidget(stim=your_circuit)
53+
circuit
54+
```
55+
56+
<img src="./_static/images/circuit_epr_pair.png" alt="quantum circuit that creates EPR pair" width=175>
57+
58+
### Propagating Paulis
59+
60+
A useful feature of Crumble (and CrumPy) is the ability to propagate Paulis
61+
through a quantum circuit. Propagation is done automatically based on the
62+
specified circuit and Pauli markers. From the
63+
[Crumble docs](https://github.com/quantumlib/Stim/tree/main/glue/crumble#readme):
64+
65+
> Propagating Paulis is done by placing markers to indicate where to add terms.
66+
> Each marker has a type (X, Y, or Z) and an index (0-9) indicating which
67+
> indexed Pauli product the marker is modifying.
68+
69+
Define a Pauli X, Y, or Z marker with the `#!pragma MARK_` instruction. Note
70+
that for compatibility with Stim, the '`#!pragma `' is included as `MARK_` is
71+
not considered a standard Stim instruction:
72+
73+
```python
74+
z_error_on_qubit_2 = "#!pragma MARKZ(0) 2"
75+
```
76+
77+
#### Legend
78+
79+
<img src="./_static/images/pauli_legend.svg" alt="jupyter notebook cell with quantum circuit diagram output" width=200>
80+
81+
#### Example
82+
83+
```python
84+
circuit_with_error = """
85+
#!pragma MARKX(0) 0
86+
TICK
87+
CNOT 0 1
88+
TICK
89+
H 0
90+
"""
91+
92+
CircuitWidget(stim=circuit_with_error)
93+
```
94+
95+
<img src="./_static/images/circuit_with_marker.png" alt="quantum circuit with Pauli propagation markers" width=200>
96+
97+
Notice how the single specified Pauli X marker propagates both through the
98+
control and across the connector of the CNOT, and gets transformed into a Pauli
99+
Z error when it encounters an H gate.
100+
101+
## Local Development
102+
103+
See the [contribution guidelines](.github/CONTRIBUTING.md) for a quick start
104+
guide and Python best practices.
105+
106+
### Additional requirements
107+
108+
[npm/Node.js](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
109+
(for bundling JavaScript); versions 11+/22+ recommended
110+
111+
### Project Layout
112+
113+
CrumPy makes use of the widget creation tool
114+
[AnyWidget](https://anywidget.dev/). With AnyWidget, Python classes are able to
115+
take JavaScript and display custom widgets in Jupyter environments. CrumPy
116+
therefore includes both JavaScript and Python subparts:
117+
118+
```text
119+
crumpy/
120+
├── src/
121+
│ ├── crumpy/
122+
│ │ ├── __init__.py # Python code for CircuitWidget
123+
│ │ └── bundle.js # Bundled JavaScript will appear here
124+
│ └── js/
125+
│ ├── crumble/ # Modified Crumble code
126+
│ │ ├── main.js # Main circuit visualization/setup
127+
│ │ └── ...
128+
│ └── package.json # Bundling setup and scripts
129+
├── tests/ # Python tests
130+
└── ...
131+
```
132+
133+
`src/crumpy` contains the main Python package code.
134+
135+
`src/crumpy/__init__.py` contains the main class of the `crumpy` package,
136+
`CircuitWidget`.
137+
138+
`src/js/crumble/` contains the modified Crumble circuit visualization code that
139+
will be rendered in the `CircuitWidget` widget.
140+
141+
`src/js/crumble/main.js` contains the main circuit visualization and setup logic
142+
in the form of the `render` function
143+
[used by AnyWidget](https://anywidget.dev/en/afm/#anywidget-front-end-module-afm).
144+
145+
### Bundling
146+
147+
To create a Jupyter widget, AnyWidget takes in JavaScript as an ECMAScript
148+
Module (ESM). **Any changes made to the JavaScript code that backs the circuit
149+
visualization will require re-bundling** into one optimized ESM file.
150+
151+
To bundle the JavaScript:
152+
153+
1. Navigate to `src/js`
154+
2. If you haven't yet, run `npm install` (this will install the
155+
[esbuild](https://esbuild.github.io/) bundler)
156+
3. Run `npm run build` (or `npm run watch` for watch mode)
157+
158+
A new bundle should appear at `src/crumpy/bundle.js`.
159+
160+
**Note**: If you are working in a Jupyter notebook and re-bundle the JavaScript,
161+
you may need to restart the notebook kernel and rerun any widget-displaying code
162+
for the changes to take effect.
11163

12164
<!-- SPHINX-START -->
13165

15.8 KB
Loading
4.5 KB
Loading
6.01 KB
Loading

_static/images/pauli_legend.svg

Lines changed: 1 addition & 0 deletions
Loading

docs/conf.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"sphinx.ext.napoleon",
1717
"sphinx_autodoc_typehints",
1818
"sphinx_copybutton",
19+
"nbsphinx",
1920
]
2021

2122
source_suffix = [".rst", ".md"]
@@ -30,6 +31,9 @@
3031

3132
html_theme = "furo"
3233

34+
# Static files configuration
35+
html_static_path = ["../_static"]
36+
3337
html_theme_options: dict[str, Any] = {
3438
"footer_icons": [
3539
{
@@ -62,3 +66,14 @@
6266
]
6367

6468
always_document_param_types = True
69+
70+
# Notebooks
71+
72+
nbsphinx_execute = "auto"
73+
74+
nbsphinx_execute_arguments = [
75+
"--InlineBackend.figure_formats={'png2x'}",
76+
"--InlineBackend.rc=figure.dpi=96",
77+
]
78+
79+
nbsphinx_allow_errors = True

docs/index.md

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
1-
# crumpy
2-
31
```{toctree}
42
:maxdepth: 2
53
:hidden:
64
5+
notebooks/getting_started
76
```
87

98
```{include} ../README.md
10-
:start-after: <!-- SPHINX-START -->
11-
```
129
13-
## Indices and tables
14-
15-
- {ref}`genindex`
16-
- {ref}`modindex`
17-
- {ref}`search`
10+
```

0 commit comments

Comments
 (0)