# -*- coding: utf-8 -*-
# =============================================================================
# qopt
# Copyright (C) 2020 Julian Teske, Forschungszentrum Juelich
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Contact email: j.teske@fz-juelich.de
# =============================================================================
""" Plotting functions.
The function `plot_bloch_vector_evolution` can be used to plot the evolution
under a series of propagators on the bloch sphere. It uses QuTiP and is only
available if QuTiP is installed in the environment. (See installation
instructions on https://github.com/qutech/qopt)
Functions
---------
:func:`plot_bloch_vector_evolution`
Plots the evolution of the forward propagators of the initial state on the
bloch sphere.
Notes
-----
The implementation was adapted from the filter_functions package.
"""
import numpy as np
import matplotlib.pyplot as plt
from unittest import mock
from warnings import warn
from typing import Sequence
from qopt.matrix import OperatorMatrix
__all__ = []
try:
import qutip as qt
__all__.append('plot_bloch_vector_evolution')
except ImportError:
warn('Qutip not installed. plot_bloch_vector_evolution() is not available')
qt = mock.Mock()
[docs]def plot_bloch_vector_evolution(
forward_propagators: Sequence[OperatorMatrix],
initial_state: OperatorMatrix,
return_bloch: bool = False,
**bloch_kwargs):
"""
Plots the evolution of the forward propagators of the initial state on the
bloch sphere.
Parameters
----------
forward_propagators: list of DenseOperators
The forward propagators whose evolution shall be plotted on the Bloch
sphere.
initial_state: DenseOperator
The initial state aka. beginning point of the plotting.
return_bloch: bool, optional
If True, the Bloch sphere is returned as object.
bloch_kwargs: dict, optional
Plotting parameters for the Bloch sphere.
Returns
-------
bloch_sphere:
Only returned if return_bloch is set to true.
"""
try:
import qutip as qt
except ImportError as err:
raise RuntimeError(
'Requirements not fulfilled. Please install Qutip') from err
if not forward_propagators[0].shape[0] == 2:
raise ValueError('Plotting Bloch sphere evolution only implemented '
'for one-qubit case!')
figsize = bloch_kwargs.pop('figsize', [5, 5])
view = bloch_kwargs.pop('view', [-60, 30])
fig = plt.figure(figsize=figsize)
axes = fig.add_subplot(projection='3d', azim=view[0], elev=view[1])
bloch_kwargs.setdefault('view', [-150, 30])
b = qt.Bloch(fig=fig, axes=axes, **bloch_kwargs)
# https://github.com/qutip/qutip/issues/1385
if hasattr(b.axes, 'set_box_aspect'):
b.axes.set_box_aspect([1, 1, 1])
b.xlabel = [r'$|+\rangle$', '']
b.ylabel = [r'$|+_i\rangle$', '']
states = [
qt.Qobj((prop * initial_state).data) for prop in forward_propagators
]
a = np.empty((3, len(states)))
x, y, z = qt.sigmax(), qt.sigmay(), qt.sigmaz()
for i, state in enumerate(states):
a[:, i] = [qt.expect(x, state),
qt.expect(y, state),
qt.expect(z, state)]
b.add_points(a.real, meth='l')
b.make_sphere()
if return_bloch:
return b