Graph.wigner_transform(density_matrix, position, momentum, offset=0, *, name=None)

Transform a density matrix into a Wigner function (or a batch of them).

  • density_matrix (Tensor or np.ndarray) – The density matrix \(\rho\) in the Fock basis. Must be of shape (..., D, D).

  • position (list or tuple or np.ndarray) – The dimensionless position vector \(q\). Must be a 1D array of shape (L,).

  • momentum (list or tuple or np.ndarray) – The dimensionless momentum vector \(p\). Must be a 1D array of shape (K,).

  • offset (int, optional) – The lowest Fock state. Defaults to 0.

  • name (str, optional) – The name of the node.


The Wigner function with shape (..., L, K).

Return type



This function currently does not support calculating the gradient with respect to its inputs. Therefore, it cannot be used in a graph for a calculate_optimization or calculate_stochastic_optimization call, which will raise a RuntimeError. Please use gradient-free optimization if you want to perform an optimization task with this function. You can learn more about it in the How to optimize controls using gradient-free optimization user guide.

See also


Create a coherent state (or a batch of them).


Create a Fock state (or a batch of them).


The Wigner transform is defined as:

\[W(q,p) = \frac{1}{2\pi} \int_{-\infty}^{\infty} \mathrm{e}^{\mathrm{i}sp} \langle q - s/2| \rho | q + s/2 \rangle \mathrm{d}s .\]

For more information about the Wigner transform, see Wigner function on Wikipedia.


Create a Wigner function.

>>> graph.wigner_transform(np.array([[1]]), [-1, 0, 1], np.zeros(1), name="wigner")
<Tensor: name="wigner", operation_name="wigner_transform", shape=(3, 1)>
>>> result = qctrl.functions.calculate_graph(graph=graph, output_node_names=["wigner"])
>>> result.output["wigner"]["value"]
array([[ 0.11709966+0.j],
       [ 0.31830989+0.j],
       [ 0.11709966+0.j]])

Create a batch of Wigner function.

>>> graph.wigner_transform(
        np.array([[[1, 0], [0, 0]], [[0, 0], [0, 1]]]),
        np.array([-1, 0, 1]),
<Tensor: name="wigner_batch", operation_name="wigner_transform", shape=(2, 3, 1)>
>>> result = qctrl.functions.calculate_graph(
...     graph=graph, output_node_names=["wigner_batch"]
... )
>>> result.output["wigner_batch"]["value"]
array([[[ 0.11709966+0.j],
        [ 0.31830989+0.j],
        [ 0.11709966+0.j]],
       [[ 0.11709966+0.j],
        [ 0.11709966+0.j]]])