Source code for paref.pareto_reflections.fill_gap_2d
import numpy as np
from paref.pareto_reflections.minimize_weighted_norm_to_utopia import MinimizeWeightedNormToUtopia
[docs]class FillGap2D(MinimizeWeightedNormToUtopia):
"""Fill the gap between two to be specified points in two dimensions
.. warning::
Although this Pareto reflection theoretically closes every gap, if the utopia point is far away from
the gap, algorithms based on this Pareto reflection tend to be numerically unstable.
It is recommended to choose an utopia point which is as close to the gap as possible.
When to use
-----------
This Pareto reflection should be used if a Pareto point is desired which lies between two specified points
.. note::
This function works best if the two points are Pareto optimal.
What it does
------------
The Pareto points of this map are the ones which sit in the middle of the two given points (provided
that such a point exists).
Mathematical formula
--------------------
.. math::
TBA
Examples
--------
TBA: Add
"""
def __init__(self, point_1: np.ndarray,
point_2: np.ndarray,
utopia_point: np.ndarray,
potency: int = 6):
"""Specify the gap and some utopia point
Parameters
----------
point_1 : np.ndarray
first point defining the gap
point_2 : np.ndarray
second point defining the gap
utopia_point : np.ndarray
utopia point
potency : int default 6
potency of underlying weighted norm
"""
if point_1.shape != (self.dimension_domain,) or point_2.shape != (
self.dimension_domain,) or utopia_point.shape != (self.dimension_domain,):
raise ValueError('Both points and utopia points must be 1 dimensional arrays of length 2! Shape of '
f'utopia_point: {utopia_point.shape}'
f'\n point_1: {point_1.shape} '
f'\n point_1: {point_2.shape}')
dimension_domain = self.dimension_domain
m = 1 / 2 * (point_1 + point_2) # middle point
y = point_1 - point_2 # helper
v = np.array([1, -(y[0] / y[1])]) # normal vector
lamb = (utopia_point[0] - m[0]) / v[0] # parameter of utopia point projected to normal
if (utopia_point[1] - m[1]) / v[1] > lamb:
lamb = (utopia_point[1] - m[1]) / v[1]
self.potency = potency * np.ones(dimension_domain)
self.scalar = (1 / v)
self.utopia_point = m + lamb * v # utopia point projected to normal st previous utopia point is dominated
@property
def dimension_codomain(self) -> int:
return 1
@property
def dimension_domain(self) -> int:
return 2