A list of objective values in an empirical Pareto front, meaning that no point strictly domminates another one in all objectives.

>>> from nondominatedarchive import NonDominatedList
>>> a = NonDominatedList([[1,0.9], [0,1], [0,2]], [2, 2])
Method __init__ elements of list_of_f_tuples not in the empirical front are pruned away reference_point is also used to compute the hypervolume, with the hv module of Simon Wessing.
Method add add f_tuple in self if it is not dominated in all objectives.
Method remove remove element f_pair.
Method add_list add list of f_tuples, not using the add method to avoid calling self.prune() several times.
Method prune remove point dominated by another one in all objectives.
Method dominates return True if any element of self dominates or is equal to f_tuple.
Method dominates_with return True if self[idx] dominates or is equal to f_tuple.
Method dominates_with_old deprecated code, now taken over by dominates_wit_for
Method dominates_with_for returns true if self[idx] weakly dominates f_tuple
Method dominators return the list of all f_tuple-dominating elements in self,
Method in_domain return True if f_tuple is dominating the reference point,
Method kink_points Create the 'kink' points from elements of self. If f_tuple is not None, also add the projections of f_tuple to the empirical front, with respect to the axes
Method hypervolume hypervolume of the entire list w.r.t. the "initial" reference point.
Method contributing_hypervolume Hypervolume improvement of f_tuple with respect to self. TODO: the argument should be an index, as in moarchiving.
Method distance_to_pareto_front Compute the distance of a dominated f_tuple to the empirical Pareto front.
Method hypervolume_improvement return how much f_tuple would improve the hypervolume.
Method _strictly_dominates return True if any element of self strictly dominates f_tuple.
Method _strictly_dominates_with return True if self[idx] strictly dominates f_tuple.
Method _projection Undocumented
Method _projection_to_empirical_front return the orthogonal projections of f_tuple on the empirical front, with respect to the coodinates axis.
Static Method _random_archive Undocumented
Static Method _random_archive_many Undocumented
Method _asserts make all kind of consistency assertions.
def __init__(self, list_of_f_tuples=None, reference_point=None):
elements of list_of_f_tuples not in the empirical front are pruned away reference_point is also used to compute the hypervolume, with the hv module of Simon Wessing.
def add(self, f_tuple):
add f_tuple in self if it is not dominated in all objectives.
def remove(self, f_tuple):

remove element f_pair.

Raises a ValueError (like list) if f_pair is not in self. To avoid the error, checking if f_pair is in self first is a possible coding solution, like

>>> from moarchiving import BiobjectiveNondominatedSortedList
>>> nda = BiobjectiveNondominatedSortedList([[2, 3]])
>>> f_pair = [1, 2]
>>> assert [2, 3] in nda and f_pair not in nda
>>> if f_pair in nda:
...     nda.remove(f_pair)
>>> nda = BiobjectiveNondominatedSortedList._random_archive(p_ref_point=1)
>>> for pair in list(nda):
...     len_ = len(nda)
...     state = nda._state()
...     nda.remove(pair)
...     assert len(nda) == len_ - 1
...     if 100 * pair[0] - int(100 * pair[0]) < 0.7:
...         res = nda.add(pair)
...         assert all(state[i] == nda._state()[i] for i in [0, 2, 3])

Return None (like list.remove).

def add_list(self, list_of_f_tuples):
add list of f_tuples, not using the add method to avoid calling self.prune() several times.
def prune(self):
remove point dominated by another one in all objectives.
def dominates(self, f_tuple):

return True if any element of self dominates or is equal to f_tuple.

Otherwise return False.

>>> from nondominatedarchive import NonDominatedList as NDA
>>> a = NDA([[0.39, 0.075], [0.0087, 0.14]])
>>> a.dominates(a[0])  # is always True if `a` is not empty
True
>>> a.dominates([-1, 33]) or a.dominates([33, -1])
False
>>> a._asserts()
def dominates_with(self, idx, f_tuple):

return True if self[idx] dominates or is equal to f_tuple.

Otherwise return False or None if idx is out-of-range.

>>> from nondominatedarchive import NonDominatedList as NDA
>>> NDA().dominates_with(0, [1, 2]) is None  # empty NDA
True
Unknown Field: todoadd more doctests that actually test the functionality and not only whether the return value is correct if empty
def dominates_with_old(self, idx, f_tuple):
deprecated code, now taken over by dominates_wit_for
def dominates_with_for(self, idx, f_tuple):

returns true if self[idx] weakly dominates f_tuple

replaces dominates_with_old because it turned out to run quicker

def dominators(self, f_tuple, number_only=False):

return the list of all f_tuple-dominating elements in self,

including an equal element. len(....dominators(...)) is hence the number of dominating elements which can also be obtained without creating the list with number_only=True.

>>> from nondominatedarchive import NonDominatedList as NDA
>>> a = NDA([[1.2, 0.1], [0.5, 1]])
>>> len(a)
2
>>> a.dominators([2, 3]) == a
True
>>> a.dominators([0.5, 1])
[(0.5, 1)]
>>> len(a.dominators([0.6, 3])), a.dominators([0.6, 3], number_only=True)
(1, 1)
>>> a.dominators([0.5, 0.9])
[]
def in_domain(self, f_tuple, reference_point=None):

return True if f_tuple is dominating the reference point,

False otherwise. True means that f_tuple contributes to the hypervolume if not dominated by other elements.

f_tuple may also be an index in self in which case self[f_tuple] is tested to be in-domain.

>>> from nondominatedarchive import NonDominatedList as NDA
>>> a = NDA([[2.2, 0.1], [0.5, 1]], reference_point=[2, 2])
>>> assert len(a) == 1
>>> a.in_domain([0, 0])
True
>>> a.in_domain([2, 1])
False
>>> all(a.in_domain(ai) for ai in a)
True
>>> a.in_domain(0)
True

TODO: improve name?

def _strictly_dominates(self, f_tuple):

return True if any element of self strictly dominates f_tuple.

Otherwise return False.

>>> from nondominatedarchive import NonDominatedList as NDA
>>> a = NDA([[0.39, 0.075], [0.0087, 0.14]])
>>> a.dominates(a[0])  # is always True if `a` is not empty
True
>>> a.dominates([-1, 33]) or a.dominates([33, -1])
False
>>> a._asserts()
def _strictly_dominates_with(self, idx, f_tuple):

return True if self[idx] strictly dominates f_tuple.

Otherwise return False or None if idx is out-of-range.

>>> from nondominatedarchive import NonDominatedList as NDA
>>> NDA()._strictly_dominates_with(0, [1, 2]) is None  # empty NDA
True
def _projection(self, f_tuple, i, x):
Undocumented
def _projection_to_empirical_front(self, f_tuple):
return the orthogonal projections of f_tuple on the empirical front, with respect to the coodinates axis.
@property
def kink_points(self):
Create the 'kink' points from elements of self. If f_tuple is not None, also add the projections of f_tuple to the empirical front, with respect to the axes
@property
def hypervolume(self):

hypervolume of the entire list w.r.t. the "initial" reference point.

Raise ValueError when no reference point was given initially.

>>> from nondominatedarchive import NonDominatedList as NDA
>>> a = NDA([[0.5, 0.4], [0.3, 0.7]], [2, 2.1])
>>> a._asserts()
>>> a.reference_point == [2, 2.1]
True
>>> a._asserts()
def contributing_hypervolume(self, f_tuple):
Hypervolume improvement of f_tuple with respect to self. TODO: the argument should be an index, as in moarchiving.
def distance_to_pareto_front(self, f_tuple):
Compute the distance of a dominated f_tuple to the empirical Pareto front.
def hypervolume_improvement(self, f_tuple):

return how much f_tuple would improve the hypervolume.

If dominated, return the distance to the empirical pareto front multiplied by -1. Else if not in domain, return distance to the reference point dominating area times -1.

@staticmethod
def _random_archive(max_size=500, p_ref_point=0.5):
Undocumented
@staticmethod
def _random_archive_many(k, max_size=500, p_ref_point=0.5):
Undocumented
def _asserts(self):

make all kind of consistency assertions.

>>> import nondominatedarchive
>>> a = nondominatedarchive.NonDominatedList(
...    [[-0.749, -1.188], [-0.557, 1.1076],
...    [0.2454, 0.4724], [-1.146, -0.110]], [10, 10])
>>> a._asserts()
>>> for p in list(a):
...     a.remove(p)
>>> assert len(a) == 0
>>> try: a.remove([0, 0])
... except ValueError: pass
... else: raise AssertionError("remove did not raise ValueError")
>>> from numpy.random import rand
>>> for _ in range(120):
...     a = nondominatedarchive.NonDominatedList._random_archive()
...     if a.reference_point:
...         for f_tuple in rand(10, 2):
...             h0 = a.hypervolume
...             hi = a.hypervolume_improvement(list(f_tuple))
...             assert a.hypervolume == h0  # works OK with Fraction
>>> for _ in range(10):
...     for k in range(3,10):
...         a = nondominatedarchive.NonDominatedList._random_archive_many(k)
...         if a.reference_point:
...             for f_tuple in rand(10, k):
...                 h0 = a.contributing_hypervolume(list(f_tuple))
...                 hi = a.hypervolume_improvement(list(f_tuple))
...                 assert h0 >= 0
...                 assert h0 == hi or (h0 == 0 and hi < 0)
API Documentation for comocma, generated by pydoctor at 2020-04-18 16:47:06.