Source code for gemseo.uncertainty.sobol
# -*- coding: utf-8 -*-
# Copyright 2021 IRT Saint Exupéry, https://www.irt-saintexupery.com
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# 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 - initial API and implementation and/or initial
# documentation
# :author: Matthias De Lozzo
# OTHER AUTHORS - MACROSCOPIC CHANGES
"""
Sobol' indices
==============
"""
from __future__ import absolute_import, division, unicode_literals
from future import standard_library
from numpy import array
from openturns import (
JansenSensitivityAlgorithm,
MartinezSensitivityAlgorithm,
MauntzKucherenkoSensitivityAlgorithm,
SaltelliSensitivityAlgorithm,
Sample,
)
from gemseo.core.discipline import MDODiscipline
from gemseo.core.doe_scenario import DOEScenario
from gemseo.utils.data_conversion import DataConversion
standard_library.install_aliases()
from gemseo import LOGGER
[docs]class SobolIndices(object):
""" Sobol' indices. """
ALGOS = {
"Saltelli": SaltelliSensitivityAlgorithm,
"Jansen": JansenSensitivityAlgorithm,
"MauntzKucherenko": MauntzKucherenkoSensitivityAlgorithm,
"Martinez": MartinezSensitivityAlgorithm,
}
def __init__(
self, disciplines, space, n_samples, formulation="MDF", objective_name=None
):
"""Constructor
:param list(MDODiscipline) disciplines: disciplines.
:param ParameterSpace space: parameter space.
:param int n_samples: number of samples.
:param str formulation: MDO formulation. Default: 'MDF'.
:param str objective_name: objective name. If None, use the first
output. Default: None.
"""
if isinstance(disciplines, MDODiscipline):
disciplines = [disciplines]
first_output = next(iter(disciplines[0].get_output_data_names()))
objective_name = objective_name or first_output
scenario = DOEScenario(disciplines, formulation, objective_name, space)
scenario.execute({"algo": "OT_SOBOL_INDICES", "n_samples": n_samples})
opt_problem = scenario.formulation.opt_problem
self.dataset = opt_problem.export_to_dataset("sobol", opt_naming=False)
self.n_samples = len(self.dataset)
[docs] def get_indices(self, algo="Saltelli"):
"""Get Sobol' indices.
:param str algo: method to compute the Sobol' indices,
either 'Saltelli', 'Jansen', 'MauntzKucherenko' or 'Martinez'.
Default: 'Saltelli'.
"""
try:
algo = self.ALGOS[algo]
except Exception:
raise TypeError(
algo + " is not an available algorithm " "to compute Sobol" " indices."
)
array_to_dict = DataConversion.array_to_dict
inputs_names = self.dataset.get_names("inputs")
sizes = self.dataset.sizes
inputs = Sample(self.dataset.get_data_by_group("inputs"))
outputs = Sample(self.dataset.get_data_by_group("outputs"))
dim = self.dataset.dimension[self.dataset.INPUT_GROUP]
n_samples = int(self.n_samples / (dim + 2))
sobol = algo(inputs, outputs, n_samples)
first_order = array(sobol.getFirstOrderIndices())
first_order = array_to_dict(first_order, inputs_names, sizes)
total_order = array(sobol.getTotalOrderIndices())
total_order = array_to_dict(total_order, inputs_names, sizes)
return sobol, first_order, total_order