Source code for gemseo.algos.opt_result_multiobj
# Copyright 2022 Airbus SAS
# 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: Gabriel Max DE MENDONÇA ABRANTES
"""Multi-objective optimization result."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Final
from numpy import ndarray
from gemseo.algos.opt_result import OptimizationResult
from gemseo.algos.pareto import ParetoFront
from gemseo.utils.string_tools import MultiLineString
[docs]
@dataclass
class MultiObjectiveOptimizationResult(OptimizationResult):
"""The result of a multi-objective optimization."""
pareto_front: ParetoFront | None = None
"""The Pareto front when the solution is feasible."""
__PARETO_FRONT: Final[str] = "pareto_front"
def __repr__(self) -> str:
msg = MultiLineString()
msg.add("Multi-objective optimization result:")
msg.indent()
msg.add("Design variables: {}", self.x_opt)
msg.add("Objective function: {}", self.f_opt)
msg.add("Feasible solution: {}", self.is_feasible)
if self.pareto_front is not None:
msg.add("Pareto front:")
msg.indent()
msg.add("Number of points: {}", self.pareto_front.f_optima.shape[0])
msg.add("Distance from utopia: {}", self.pareto_front.distance_from_utopia)
msg.dedent()
return str(msg)
def __str__(self) -> str:
parent_string = super().__str__()
if self.pareto_front is not None:
msg = MultiLineString()
msg.indent()
msg.add("Pareto efficient solutions:")
msg.indent()
for line in str(self.pareto_front).split("\n"):
msg.add("{}", line)
return f"{parent_string}\n{msg}"
return parent_string
[docs]
def to_dict(self): # noqa: D102
dict_ = super().to_dict()
pareto_front = dict_.pop(self.__PARETO_FRONT)
if pareto_front is not None:
for attr, value in self.pareto_front.__dict__.items():
if isinstance(value, (int, float, str, bool, list, tuple, ndarray)):
dict_[f"{self.__PARETO_FRONT}:{attr}"] = value
return dict_
@classmethod
def _get_additional_fields(cls, problem):
return {
f"{cls.__PARETO_FRONT}": ParetoFront.from_optimization_problem(problem)
if problem.get_optimum()[2]
else None
}