The introduction of a custom array type gives us a lot more control over the data format, and we have a few tricks up our sleeve to take advantage of it this year, so stay tuned for even faster simulations! 🏎️
🍾 Migration from the previous version (`v0.2.*`)
There is not much to know, the solver and utility APIs are largely unchanged. We'd love to have your feedback on any bugs you might find when running your existing simulations with the new version. Here are some cool new features:
- You can now use the much awaited `x.dag()` (see the list of other `QArray` methods in the [API documentation](https://www.dynamiqs.org/0.3/python_api/qarrays/qarray/QArray.html)).
- When you create operators with Dynamiqs, they now have their own custom type, data format and representation:
python
>>> a = dq.destroy(5)
>>> a
QArray: shape=(5, 5), dims=(5,), dtype=complex64, layout=dia, ndiags=1
[[ ⋅ 1. +0.j ⋅ ⋅ ⋅ ]
[ ⋅ ⋅ 1.414+0.j ⋅ ⋅ ]
[ ⋅ ⋅ ⋅ 1.732+0.j ⋅ ]
[ ⋅ ⋅ ⋅ ⋅ 2. +0.j]
[ ⋅ ⋅ ⋅ ⋅ ⋅ ]]
>>> a.dag() a + 2 * (a + a.dag())
QArray: shape=(5, 5), dims=(5,), dtype=complex64, layout=dia, ndiags=3
[[ ⋅ 2. +0.j ⋅ ⋅ ⋅ ]
[2. +0.j 1. +0.j 2.828+0.j ⋅ ⋅ ]
[ ⋅ 2.828+0.j 2. +0.j 3.464+0.j ⋅ ]
[ ⋅ ⋅ 3.464+0.j 3. +0.j 4. +0.j]
[ ⋅ ⋅ ⋅ 4. +0.j 4. +0.j]]
Here, Dynamiqs stores only the nonzero diagonal of the operator.
- There are two different layouts for qarrays: dense or sparse DIA. You can choose a global default layout for new operators with [`dq.set_layout()`](https://www.dynamiqs.org/0.3/python_api/utils/global_settings/set_layout.html), or individually by setting the `layout` keyword argument:
python
>>> dq.destroy(5, layout=dq.dense)
QArray: shape=(5, 5), dims=(5,), dtype=complex64, layout=dense
[[0. +0.j 1. +0.j 0. +0.j 0. +0.j 0. +0.j]
[0. +0.j 0. +0.j 1.414+0.j 0. +0.j 0. +0.j]
[0. +0.j 0. +0.j 0. +0.j 1.732+0.j 0. +0.j]
[0. +0.j 0. +0.j 0. +0.j 0. +0.j 2. +0.j]
[0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]]
- All library functions remain compatible with QuTiP Qobjs, NumPy arrays, JAX arrays and Python lists. They now also support the Dynamiqs `QArray` type.
- We added some [qarray utilities](https://www.dynamiqs.org/0.3/python_api/index.html#qarray-utilities) to convert to and from other types, check them out! For example you can use [`dq.asqarray()`](https://www.dynamiqs.org/0.3/python_api/qarrays/utils/asqarray.html) to convert any object to a qarray:
python
>>> dq.asqarray([qt.sigmax(), qt.sigmay(), qt.sigmaz()], layout=dq.dia)
QArray: shape=(3, 2, 2), dims=(2,), dtype=complex64, layout=dia, ndiags=3
[[[ ⋅ 1.+0.j]
[ 1.+0.j ⋅ ]]
[[ ⋅ 0.-1.j]
[ 0.+1.j ⋅ ]]
[[ 1.+0.j ⋅ ]
[ ⋅ -1.+0.j]]]
- `TimeArray` has been renamed to [`TimeQArray`](https://www.dynamiqs.org/0.3/python_api/time_qarray/TimeQArray.html), and has first-class support for qarrays:
python
>>> f = lambda t: jnp.cos(2.0 * jnp.pi * t)
>>> H = dq.modulated(f, dq.sigmax())
>>> H
ModulatedTimeQArray: shape=(2, 2), dims=(2,), dtype=complex64, layout=dia, ndiags=2
>>> H(0.5)
QArray: shape=(2, 2), dims=(2,), dtype=complex64, layout=dia, ndiags=2
[[ ⋅ -1.+0.j]
[-1.+0.j ⋅ ]]
🚀 Features
- New operators [`dq.eye_like()`](https://www.dynamiqs.org/0.3/python_api/utils/operators/eye_like.html) and [`dq.zeros_like()`](https://www.dynamiqs.org/0.3/python_api/utils/operators/zeros_like.html).
- Added GPU support for eig in [`dq.floquet()`](https://www.dynamiqs.org/0.3/python_api/integrators/floquet.html) and [`dq.fidelity()`](https://www.dynamiqs.org/0.3/python_api/utils/general/fidelity.html), following the JAX 0.4.36 release (see [jax.lax.linalg.eig() documentation](https://jax.readthedocs.io/en/latest/_autosummary/jax.lax.linalg.eig.html#jax.lax.linalg.eig)).
- New [`dq.hc`](https://www.dynamiqs.org/0.3/python_api/hermitian_conjugate/hc.html) helper, syntactic sugar for writing hermitian conjugates:
python
two linear drives on two different modes
H = (omega_a * a + dq.hc) + (omega_b * b + dq.hc)
time-dependent linear drive
omega = lambda t: jnp.cos(2.0 * jnp.pi * t)
H = dq.modulated(omega, a) + dq.hc
- [`dq.coherent()`](https://www.dynamiqs.org/0.3/python_api/utils/states/coherent.html) now also accepts a batched displacement (`alpha`) argument for multi-modes.
- New `out_axes` property for result objects for custom vmapping (see 866).
🐛 Bugs
- Fixed [`dq.wigner()`](https://www.dynamiqs.org/0.3/python_api/utils/general/wigner.html) which used to return the wigner transpose, and fixed the missing `.T` in the wigner plotting functions `imshow` which made this bug go unnoticed (thanks to RemiRousseau for finding it, see #849).
- Fixed the definition of [`dq.cd_gate()`](https://www.dynamiqs.org/0.3/python_api/utils/optimal_control/cd_gate.html) to match [`dq.ground()`](https://www.dynamiqs.org/0.3/python_api/utils/states/ground.html) and [`dq.excited()`](https://www.dynamiqs.org/0.3/python_api/utils/states/excited.html).
📖 Documentation
- Added an entry to [The sharp bits 🔪](https://www.dynamiqs.org/0.3/documentation/getting_started/sharp-bits.html) tutorial on [Computing the gradient with respect to complex parameters](https://www.dynamiqs.org/0.3/documentation/getting_started/sharp-bits.html#computing-the-gradient-with-respect-to-complex-parameters) (take the conjugate!).
- Separated the solver [options documentation](https://www.dynamiqs.org/0.3/python_api/options/Options.html) between quantum solvers, to add support for solver-specific options.
- New [Global settings](https://www.dynamiqs.org/0.3/python_api/index.html#global-settings) section in the API to group default global configurations (such as precision, dtype, device and layout).
📦 Other changes
- Renamed `dq.zero()` to [`dq.zeros()`](https://www.dynamiqs.org/0.3/python_api/utils/operators/zeros.html) (to align with NumPy, PyTorch, JAX, etc.).
- Changed minimum supported Python version from 3.9 to 3.10.
**Full Changelog**: https://github.com/dynamiqs/dynamiqs/compare/v0.2.3...v0.3.0