Skip to content

Commit 807edf9

Browse files
DanPuzzuolito24toroihincksEric-Arellanoarthurostrauss
authored
Preparing 0.4.1 (#217)
* Temporary upper bound on JAX version <=0.4.6 and update to DynamicsBackend tutorial (#210) * Add links of API reference to tutorials and userguides (#212) * Fix multiset ordering bug in perturbation module (#211) Co-authored-by: Ian Hincks <[email protected]> * Bump Sphinx Theme to 1.11 (#215) * Bump Sphinx Theme to 1.11 * Also activate jquery * Bug fix: Measurement properties automatic padding for DynamicsBackend initialization (#209) Co-authored-by: Daniel Puzzuoli <[email protected]> * bounding ipython version for compatibility with python 3.8 (#216) * Update deploy_documentation.sh to deploy in ecosystem (#219) * Bound Diffrax version (#226) * Bounding diffrax and equinox versions. The latest versions require the latest version of JAX, but due to an unresolved bug in JAX, Dynamics is only compatible with jax<=0.4.6. This commit also adds a release note stating exactly what versions of these packages will work with the latest version of dynamics. * Upgrade to qiskit_sphinx_theme 1.12 (#224) * Update links to repo and documentation (#227) * updating minor comments in pulse sim tutorial to remove confusion (#228) * adding max step size argument to dynamics_backend tutorial, with explanation (#229) * fixing typo --------- Co-authored-by: Kento Ueda <[email protected]> Co-authored-by: Ian Hincks <[email protected]> Co-authored-by: Eric Arellano <[email protected]> Co-authored-by: Arthur Strauss <[email protected]> Co-authored-by: Luciano Bello <[email protected]>
1 parent 27cf27c commit 807edf9

31 files changed

+493
-147
lines changed

.github/workflows/docs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
name: Docs Publish
22
on:
3+
workflow_dispatch:
34
push:
45
tags:
56
- "*"

CITATION.bib

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ @misc{qiskit_dynamics_2021
44
year = {2021},
55
publisher = {GitHub},
66
journal = {GitHub repository},
7-
url = {https://github.com/Qiskit/qiskit-dynamics}
7+
url = {https://github.com/Qiskit-Extensions/qiskit-dynamics}
88
}

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ as:
152152
fixes:
153153
- |
154154
Fixes a race condition in the function ``foo()``. Refer to
155-
`#12345 <https://github.com/Qiskit/qiskit-dynamics/issues/12345>` for more
155+
`#12345 <https://github.com/Qiskit-Extensions/qiskit-dynamics/issues/12345>` for more
156156
details.
157157
```
158158

README.md

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,26 @@
44

55
**This repo is still in the early stages of development, there will be breaking API changes**
66

7-
Qiskit Dynamics is an open-source project for building, transforming, and solving
8-
time-dependent quantum systems in Qiskit.
9-
10-
The goal of Qiskit Dynamics is to provide access to different numerical
11-
methods for solving differential equations, and to automate common processes typically performed by hand,
12-
e.g. applying frame transformations or rotating wave approximations to system and control Hamiltonians.
13-
14-
Qiskit Dynamics can be configured to use either
15-
[NumPy](https://github.com/numpy/numpy) or [JAX](https://github.com/google/jax)
16-
as the backend for array operations. [NumPy](https://github.com/numpy/numpy) is the default,
17-
and [JAX](https://github.com/google/jax) is an optional dependency.
18-
[JAX](https://github.com/google/jax) provides just-in-time compilation, automatic differentiation,
19-
and GPU execution, and therefore is well-suited to tasks involving repeated
20-
evaluation of functions with different parameters; E.g. simulating a model of a quantum system
21-
over a range of parameter values, or optimizing the parameters of control sequence.
22-
23-
Reference documentation may be found [here](https://qiskit.org/documentation/dynamics/),
24-
including [tutorials](https://qiskit.org/documentation/dynamics/tutorials),
25-
[user guide](https://qiskit.org/documentation/dynamics/userguide),
26-
and [API reference](https://qiskit.org/documentation/dynamics/apidocs).
7+
Qiskit Dynamics is an open-source project for building, transforming, and solving time-dependent
8+
quantum systems in Qiskit.
9+
10+
The goal of Qiskit Dynamics is to provide access to different numerical methods for solving
11+
differential equations, and to automate common processes typically performed by hand, e.g. applying
12+
frame transformations or rotating wave approximations to system and control Hamiltonians.
13+
14+
Qiskit Dynamics can be configured to use either [NumPy](https://github.com/numpy/numpy) or
15+
[JAX](https://github.com/google/jax) as the backend for array operations.
16+
[NumPy](https://github.com/numpy/numpy) is the default, and [JAX](https://github.com/google/jax) is
17+
an optional dependency. [JAX](https://github.com/google/jax) provides just-in-time compilation,
18+
automatic differentiation, and GPU execution, and therefore is well-suited to tasks involving
19+
repeated evaluation of functions with different parameters; E.g. simulating a model of a quantum
20+
system over a range of parameter values, or optimizing the parameters of control sequence.
21+
22+
Reference documentation may be found [here](https://qiskit.org/ecosystem/dynamics/), including
23+
[tutorials](https://qiskit.org/ecosystem/dynamics/tutorials/index.html),
24+
[user guide](https://qiskit.org/ecosystem/dynamics/userguide/index.html),
25+
[API reference](https://qiskit.org/ecosystem/dynamics/apidocs/index.html), and
26+
[Discussions](https://qiskit.org/ecosystem/dynamics/discussions/index.html).
2727

2828
## Installation
2929

@@ -46,25 +46,22 @@ Installing JAX with GPU support must be done manually, for instructions refer to
4646

4747
## Contribution Guidelines
4848

49-
If you'd like to contribute to Qiskit Dynamics, please take a look at our
50-
[contribution guidelines](CONTRIBUTING.md). This project adheres to Qiskit's
51-
[code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to
52-
uphold this code.
53-
54-
We use [GitHub issues](https://github.com/Qiskit/qiskit-dynamics/issues) for
55-
tracking requests and bugs. Please
56-
[join the Qiskit Slack community](https://qisk.it/join-slack)
57-
and use our [#qiskit-dynamics](https://qiskit.slack.com/archives/C03E7UVCDEV) channel for discussion and
58-
simple questions.
59-
For questions that are more suited for a forum we use the Qiskit tag in the
49+
If you'd like to contribute to Qiskit Dynamics, please take a look at our
50+
[contribution guidelines](CONTRIBUTING.md). This project adheres to Qiskit's
51+
[code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.
52+
53+
We use [GitHub issues](https://github.com/Qiskit-Extensions/qiskit-dynamics/issues) for tracking
54+
requests and bugs. Please [join the Qiskit Slack community](https://qisk.it/join-slack) and use our
55+
[#qiskit-dynamics](https://qiskit.slack.com/archives/C03E7UVCDEV) channel for discussion and simple
56+
questions. For questions that are more suited for a forum we use the Qiskit tag in the
6057
[Stack Exchange](https://quantumcomputing.stackexchange.com/questions/tagged/qiskit).
6158

6259
## Authors and Citation
6360

64-
Qiskit Dynamics is the work of
65-
[many people](https://github.com/Qiskit/qiskit-dynamics/graphs/contributors) who contribute
66-
to the project at different levels. If you use Qiskit, please cite as per the included
67-
[BibTeX file](https://github.com/Qiskit/qiskit-dynamics/blob/main/CITATION.bib).
61+
Qiskit Dynamics is the work of
62+
[many people](https://github.com/Qiskit-Extensions/qiskit-dynamics/graphs/contributors) who
63+
contribute to the project at different levels. If you use Qiskit, please cite as per the included
64+
[BibTeX file](https://github.com/Qiskit-Extensions/qiskit-dynamics/blob/main/CITATION.bib).
6865

6966
## License
7067

docs/conf.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@
1212

1313
# pylint: disable=invalid-name
1414

15-
"""
16-
Sphinx documentation builder
17-
"""
18-
1915
# General options:
2016

2117
project = 'Qiskit Dynamics'
@@ -25,7 +21,7 @@
2521
# The short X.Y version
2622
version = ''
2723
# The full version, including alpha/beta/rc tags
28-
release = '0.4.0'
24+
release = '0.4.1'
2925

3026
extensions = [
3127
'sphinx.ext.napoleon',
@@ -39,7 +35,8 @@
3935
'reno.sphinxext',
4036
'sphinx.ext.intersphinx',
4137
'nbsphinx',
42-
'sphinxcontrib.bibtex'
38+
'sphinxcontrib.bibtex',
39+
"qiskit_sphinx_theme",
4340
]
4441
templates_path = ["_templates"]
4542

docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ just-in-time compilation, automatic differentiation, and GPU execution of Qiskit
2020
This package is still in the early stages of development and it is very likely
2121
that there will be breaking API changes in future releases.
2222
If you encounter any bugs please open an issue on
23-
`Github <https://github.com/Qiskit/qiskit-dynamics/issues>`_
23+
`Github <https://github.com/Qiskit-Extensions/qiskit-dynamics/issues>`_
2424

2525

2626
.. toctree::

docs/tutorials/Lindblad_dynamics_simulation.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ In the sections below we define a model, solve the dynamics and plot
1414
some observables using the following steps:
1515

1616
1. Define the number of qubits and precompute some matrix operators.
17-
2. Define all relevant parameters and setup a ``Solver`` instance with the model of the system,
17+
2. Define all relevant parameters and setup a :class:`Solver` instance with the model of the system,
1818
consisting of the Hamiltonian and the jump operators of the Lindblad dissipator.
1919
3. Define the initial state and other parameters for the initial value problem,
2020
and evolve the system state.
@@ -110,7 +110,7 @@ used in the rest of this tutorial.
110110
2. Setup the solver
111111
-------------------
112112

113-
In this section we setup a ``Solver`` class that stores and manipulates
113+
In this section we setup a :class:`Solver` class that stores and manipulates
114114
the model to be solved. In the following, we will set :math:`\hbar=1`
115115
and set the driving amplitude to be :math:`\nu_x \equiv 1`. This sets the
116116
time units, with the other frequency
@@ -119,7 +119,7 @@ these free parameters, and then create the Hamiltonian matrix and the
119119
list of dissipator operators. We build the full Hamiltonian matrix by
120120
summing all single-qubit and two-qubit terms. Since there are no
121121
time-dependent terms, and we do not plan to take partial derivatives of
122-
parameters, we do not use the ``Signal`` class in this tutorial. See the other tutorials for various
122+
parameters, we do not use the :class:`Signal` class in this tutorial. See the other tutorials for various
123123
generalizations of this approach supported with ``qiskit-dynamics``.
124124

125125
.. jupyter-execute::

docs/tutorials/Rabi_oscillations.rst

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ decoherence terms modeled by using a Lindblad master equation.
1010
In the sections below we define a model, solve the dynamics and plot the
1111
qubit oscillations using the following steps:
1212

13-
1. Define all relevant parameters and setup a ``Solver`` instance with the Hamiltonian model of
14-
the system.
13+
1. Setup a :class:`.Solver` with the Hamiltonian model
1514
2. Define the initial state and simulation times, and evolve the system state.
1615
3. Plot the qubit state as a function of time and discuss the results.
1716
4. Solve again the the model with jump operators for the Lindblad dissipator, and plot the results.
@@ -20,7 +19,9 @@ In the first step below, we model the time evolution of a qubit’s state
2019
taken as a two-level system, using the Schrödinger equation with a
2120
Hamiltonian containing a diagonal term of frequency :math:`\nu_z` and a
2221
transverse term of amplitude :math:`\nu_x` and harmonic driving
23-
frequency :math:`\nu_d`,
22+
frequency :math:`\nu_d` (see how the Hamiltonians are derived on
23+
`Qiskit Textbook page on Introduction to Transmon Physics
24+
<https://qiskit.org/textbook/ch-quantum-hardware/transmon-physics.html>`_),
2425

2526
.. math:: H = \frac{1}{2} \times 2 \pi \nu_z {Z} + 2 \pi \nu_x \cos(2 \pi \nu_d t){X},
2627

@@ -33,8 +34,8 @@ where :math:`\{X,Y,Z\}` are the Pauli matrices (also written as
3334
In the following, we will set :math:`\hbar=1` and fix some arbitrary
3435
time units, with all frequency parameters scaled accordingly. Below, we
3536
first set a few values for these frequency parameters, and then setup the
36-
``Solver`` class instance that stores and manipulates the model to be
37-
solved, using matrices and ``Signal`` instances. For the
37+
:class:`.Solver` class instance that stores and manipulates the model to be
38+
solved, using matrices and :class:`.Signal` instances. For the
3839
time-independent :math:`z` term we set the signal to a constant, while
3940
for the trasverse driving term we setup a harmonic signal.
4041

@@ -144,8 +145,8 @@ particular this is a realization of the :math:`X` gate.
144145

145146
plot_qubit_dynamics(sol, t_eval, X, Y, Z)
146147

147-
4. Redefine the model with damping and decoherence.
148-
---------------------------------------------------
148+
4. Redefine the model with damping and decoherence
149+
--------------------------------------------------
149150

150151
Now we add to our simulation an environment modeled as a memory-less
151152
(Markovian) bath, solving the Lindblad master equation with the same

docs/tutorials/dynamics_backend.rst

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,16 @@ differential equation. The full list of allowable ``solver_options`` are the arg
143143
:func:`.solve_ode`.
144144

145145
Note that, to enable the internal automatic jit-compilation, we choose a JAX integration method.
146+
Furthermore, note that in the solver options we set the max step size to the pulse sample width
147+
``dt`` via the ``"hmax"`` argument for the method ``"jax_odeint"``. This is important for preventing
148+
variable step solvers from accidentally stepping over pulses in schedules with long idle times.
146149

147150
.. jupyter-execute::
148151

149152
from qiskit_dynamics import DynamicsBackend
150153

151154
# Consistent solver option to use throughout notebook
152-
solver_options = {"method": "jax_odeint", "atol": 1e-6, "rtol": 1e-8}
155+
solver_options = {"method": "jax_odeint", "atol": 1e-6, "rtol": 1e-8, "hmax": dt}
153156

154157
backend = DynamicsBackend(
155158
solver=solver,
@@ -318,8 +321,9 @@ To enable running of the single qubit experiments, we add the following to the `
318321
backend.
319322
- Add definitions of ``RZ`` gates as phase shifts. These instructions control the phase of the drive
320323
channels, as well as any control channels acting on a given qubit.
321-
- Add a ``CX`` gate which applies to all qubits. While this tutorial will not be utilizing it, this
322-
ensures that validation steps checking that the device is fully connected will pass.
324+
- Add a ``CX`` gate between qubits :math:`(0, 1)` and :math:`(1, 0)`. While this tutorial will not
325+
be utilizing it, this ensures that validation steps checking that the device is fully connected
326+
will pass.
323327

324328
.. jupyter-execute::
325329

@@ -336,7 +340,7 @@ To enable running of the single qubit experiments, we add the following to the `
336340
target.add_instruction(XGate(), properties={(0,): None, (1,): None})
337341
target.add_instruction(SXGate(), properties={(0,): None, (1,): None})
338342

339-
target.add_instruction(CXGate())
343+
target.add_instruction(CXGate(), properties={(0, 1): None, (1, 0): None})
340344

341345
# Add RZ instruction as phase shift for drag cal
342346
phi = Parameter("phi")
@@ -472,11 +476,6 @@ values for the single qubit gates calibrated above.
472476

473477
from qiskit_experiments.library import CrossResonanceHamiltonian
474478

475-
backend.target.add_instruction(
476-
instruction=CrossResonanceHamiltonian.CRPulseGate(width=Parameter("width")),
477-
properties={(0, 1): None, (1, 0): None}
478-
)
479-
480479
cr_ham_experiment = CrossResonanceHamiltonian(
481480
qubits=(0, 1),
482481
flat_top_widths=np.linspace(0, 5000, 17),

docs/tutorials/qiskit_pulse.rst

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ ground state we expect that this second pulse will not have any effect
2525
on the qubit. This situation is simulated with the following steps:
2626

2727
1. Create the pulse schedule
28-
2. Converting pulse schedules to Signals
28+
2. Converting pulse schedules to a :class:`.Signal`
2929
3. Create the system model, configured to simulate pulse schedules
3030
4. Simulate the pulse schedule using the model
3131

@@ -48,30 +48,27 @@ First, we use the pulse module in Qiskit to create a pulse schedule.
4848
# Sample rate of the backend in ns.
4949
dt = 1 / 4.5
5050

51-
# Define gaussian envelope function to have a pi rotation.
52-
amp = 1.
53-
area = 1
54-
sig = area*0.399128/r/amp
51+
# Define gaussian envelope function to approximately implement an sx gate.
52+
amp = 1. / 1.75
53+
sig = 0.6985/r/amp
5554
T = 4*sig
5655
duration = int(T / dt)
5756
beta = 2.0
5857

59-
# The 1.75 factor is used to approximately get a sx gate.
60-
# Further "calibration" could be done to refine the pulse amplitude.
61-
with pulse.build(name="sx-sy schedule") as xp:
62-
pulse.play(pulse.Drag(duration, amp / 1.75, sig / dt, beta), pulse.DriveChannel(0))
58+
with pulse.build(name="sx-sy schedule") as sxp:
59+
pulse.play(pulse.Drag(duration, amp, sig / dt, beta), pulse.DriveChannel(0))
6360
pulse.shift_phase(np.pi/2, pulse.DriveChannel(0))
64-
pulse.play(pulse.Drag(duration, amp / 1.75, sig / dt, beta), pulse.DriveChannel(0))
61+
pulse.play(pulse.Drag(duration, amp, sig / dt, beta), pulse.DriveChannel(0))
6562

66-
xp.draw()
63+
sxp.draw()
6764

6865

69-
2. Convert the pulse schedule to a ``Signal``
70-
---------------------------------------------
66+
2. Convert the pulse schedule to a :class:`.Signal`
67+
---------------------------------------------------
7168

7269
Qiskit Dynamics has functionality for converting pulse schedule to instances
73-
of ``Signal``. This is done using the pulse instruction to signal
74-
converter ``InstructionToSignals``. This converter needs to know the
70+
of :class:`.Signal`. This is done using the pulse instruction to signal
71+
converter :class:`.InstructionToSignals`. This converter needs to know the
7572
sample rate of the arbitrary waveform generators creating the signals,
7673
i.e. ``dt``, as well as the carrier frequency of the signals,
7774
i.e. ``w``. The plot below shows the envelopes and the signals resulting
@@ -87,7 +84,7 @@ virtual ``Z`` gate is applied.
8784

8885
converter = InstructionToSignals(dt, carriers={"d0": w})
8986

90-
signals = converter.get_signals(xp)
87+
signals = converter.get_signals(sxp)
9188
fig, axs = plt.subplots(1, 2, figsize=(14, 4.5))
9289
for ax, title in zip(axs, ["envelope", "signal"]):
9390
signals[0].draw(0, 2*T, 2000, title, axis=ax)
@@ -101,7 +98,7 @@ virtual ``Z`` gate is applied.
10198
3. Create the system model
10299
--------------------------
103100

104-
We now setup a ``Solver`` instance with the desired Hamiltonian information,
101+
We now setup a :class:`.Solver` instance with the desired Hamiltonian information,
105102
and configure it to simulate pulse schedules. This requires specifying
106103
which channels act on which operators, channel carrier frequencies, and sample width ``dt``.
107104
Additionally, we setup this solver in the rotating frame and perform the
@@ -146,7 +143,7 @@ and in this case should produce identical behavior.
146143
# Start the qubit in its ground state.
147144
y0 = Statevector([1., 0.])
148145

149-
%time sol = hamiltonian_solver.solve(t_span=[0., 2*T], y0=y0, signals=xp, atol=1e-8, rtol=1e-8)
146+
%time sol = hamiltonian_solver.solve(t_span=[0., 2*T], y0=y0, signals=sxp, atol=1e-8, rtol=1e-8)
150147

151148

152149
.. jupyter-execute::

docs/userguide/how_to_configure_simulations.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ Here we walk through some of these options, covering:
2020
rotating frame to preserve sparsity
2121

2222

23-
Throughout this guide we work at the level of the ``Solver`` interface,
23+
Throughout this guide we work at the level of the :class:`.Solver` interface,
2424
and consider Hamiltonian dynamics for simplicity, however all of the
2525
considerations have their analogs for Lindblad dynamics.
2626

2727
1. How-to set up a simulation in a rotating frame, and its potential benefits
2828
-----------------------------------------------------------------------------
2929

3030
Here we show how to perform a simulation in a rotating frame by setting the
31-
optional ``rotating_frame`` argument when instantiating a ``Solver``, and demonstrate how a
31+
optional ``rotating_frame`` argument when instantiating a :class:`.Solver`, and demonstrate how a
3232
well-chosen frame operator :math:`F = -iH_0` can reduce solving time.
3333
See the :ref:`Rotating frames section of the Models API documentation <Rotating frames>`
3434
for details on rotating frames.
@@ -74,7 +74,7 @@ First, construct the components of the model:
7474
# total simulation time
7575
T = 1. / r
7676

77-
Construct a ``Solver`` for the model as stated, without entering a rotating frame, and solve,
77+
Construct a :class:`.Solver` for the model as stated, without entering a rotating frame, and solve,
7878
timing the solver.
7979

8080
.. jupyter-execute::
@@ -87,7 +87,7 @@ timing the solver.
8787
y0 = np.eye(dim, dtype=complex)
8888
%time results = solver.solve(t_span=[0., T], y0=y0, signals=[drive_signal], atol=1e-10, rtol=1e-10)
8989

90-
Next, define a ``Solver`` in the rotating frame of the static
90+
Next, define a :class:`.Solver` in the rotating frame of the static
9191
Hamiltonian by setting the ``rotating_frame`` kwarg, and solve, again timing the solver.
9292

9393
.. jupyter-execute::
@@ -151,7 +151,7 @@ reducing the number of RHS calls required to solve with a given accuracy.
151151
---------------------------------------------------------------------------
152152

153153
Next we show how to perform a simulation with the rotating wave approximation (RWA)
154-
by setting the ``rwa_cutoff_freq`` argument at ``Solver`` instantiation, and show
154+
by setting the ``rwa_cutoff_freq`` argument at :class:`.Solver` instantiation, and show
155155
how it results in further speed ups at the expense of solution accuracy. See the API
156156
documentation for the :meth:`~qiskit_dynamics.models.rotating_wave_approximation` function
157157
for specific details about the RWA.
@@ -201,7 +201,7 @@ with extra emphasis on the following:
201201
:ref:`evaluation modes section of the Models API documentation <evaluation modes>`,
202202
when using a sparse evaluation mode, to preserve sparsity, it is recommended to
203203
only use *diagonal* rotating frames, which can be specified as a 1d array to the
204-
``rotating_frame`` kwarg of ``Solver`` instantiation.
204+
``rotating_frame`` kwarg of :class:`.Solver` instantiation.
205205

206206
For this section we use JAX as it is more performant. See the
207207
:ref:`userguide on using JAX <how-to use jax>` for a more detailed

0 commit comments

Comments
 (0)