Source code for

# -*- coding: utf-8 -*-
# Copyright 2021 IRT Saint Exupéry,
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License version 3 as published by the Free Software Foundation.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

# Contributors:
#    INITIAL AUTHORS - API and implementation and/or documentation
#        :author: Francois Gallard
#        :author: Damien Guenot
Plot the derivatives of the functions
from __future__ import absolute_import, division, unicode_literals

from future import standard_library
from matplotlib import pyplot
from numpy import arange, atleast_2d

from import OptPostProcessor


from gemseo import LOGGER

[docs]class GradientSensitivity(OptPostProcessor): """ The **GradientSensitivity** post processing builds histograms of derivatives of objective and constraints The plot method considers the derivatives at the last iteration. The iteration can be changed in option. The x- and y- figure sizes can also be modified in option. It is possible either to save the plot, to show the plot or both. """ def _plot( self, iteration=-1, figsize_x=10, figsize_y=10, save=False, show=False, file_path="gradient_sensitivity", extension="pdf", ): """ Plots the GradientSensitivity graph :param iteration: the iteration to plot sensitivities, if negative, use optimum :type iteration: int :param figsize_x: size of figure in horizontal direction (inches) :type figsize_x: int :param figsize_y: size of figure in vertical direction (inches) :type figsize_y: int :param show: if True, displays the plot windows :type show: bool :param save: if True, exports plot to pdf :type save: bool :param file_path: the base paths of the files to export :type file_path: str :param extension: file extension :type extension: str """ all_funcs = self.opt_problem.get_all_functions_names() if iteration == -1: x_ref = self.opt_problem.solution.x_opt else: x_ref = self.opt_problem.database.get_x_by_iter(iteration) grad_dict = {} for func in all_funcs: grad = self.database.get_f_of_x("@" + func, x_ref) if grad is not None: if len(grad.shape) == 1: grad_dict[func] = grad else: n_f, _ = grad.shape for i in range(n_f): grad_dict[func + "_" + str(i)] = grad[i, :] fig = self.__generate_subplots(x_ref, grad_dict, figsize_x, figsize_y) self._save_and_show( fig, save=save, show=show, file_path=file_path, extension=extension ) @staticmethod def __generate_subplots(x_ref, grad_dict, figsize_x=10, figsize_y=10): """ Generates the gradient sub plots from the data :param x_ref: reference value for x :param grad_dict : dict of gradients to plot :param figsize_x : size of figure in horizontal direction (inches) :param figsize_y : size of figure in vertical direction (inches) """ n_funcs = len(grad_dict) if n_funcs == 0: raise ValueError("No gradients to plot at current iteration !") nrows = n_funcs // 2 if 2 * nrows < n_funcs: nrows += 1 ncols = 2 fig, axes = pyplot.subplots( nrows=nrows, ncols=2, sharex=True, sharey=False, figsize=(figsize_x, figsize_y), ) i = 0 j = -1 axes = atleast_2d(axes) n_subplots = len(axes) * len(axes[0]) abscissa = arange(len(x_ref)) x_labels = [r"$x_{" + str(x_id) + "}$" for x_id in abscissa] for func, grad in sorted(grad_dict.items()): j += 1 if j == ncols: j = 0 i += 1 axe = axes[i][j], grad, color="blue", align="center") axe.set_title(func) axe.set_xticklabels(x_labels, fontsize=14) axe.set_xticks(abscissa) # Update y labels spacing vis_labels = [ label for label in axe.get_yticklabels() if label.get_visible() is True ] pyplot.setp(vis_labels[::2], visible=False) if len(grad_dict) < n_subplots: # xlabel must be written with the same fontsize on the 2 columns j += 1 # if j == ncols: Seems impossible to reach # j = 0 # i += 1 axe = axes[i][j] axe.set_xticklabels(x_labels, fontsize=14) axe.set_xticks(abscissa) fig.suptitle( "Derivatives of objective and constraints" + " with respect to design variables", fontsize=14, ) return fig