Package comocma :: Module nondominatedarchive :: Class NonDominatedList
[hide private]
[frames] | no frames]

Class NonDominatedList

source code

object --+    
         |    
      list --+
             |
            NonDominatedList

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])
Instance Methods [hide private]
new empty list
__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.
source code
 
add(self, f_tuple)
add `f_tuple` in `self` if it is not dominated in all objectives.
source code
 
remove(self, f_tuple)
remove element `f_pair`.
source code
 
add_list(self, list_of_f_tuples)
add list of f_tuples, not using the add method to avoid calling self.prune() several times.
source code
 
prune(self)
remove point dominated by another one in all objectives.
source code
 
dominates(self, f_tuple)
return `True` if any element of `self` dominates or is equal to `f_tuple`.
source code
 
dominates_with(self, idx, f_tuple)
return `True` if ``self[idx]`` dominates or is equal to `f_tuple`.
source code
 
dominates_with_old(self, idx, f_tuple)
deprecated code, now taken over by dominates_wit_for
source code
 
dominates_with_for(self, idx, f_tuple)
returns true if self[idx] weakly dominates f_tuple
source code
 
dominators(self, f_tuple, number_only=False)
return the list of all `f_tuple`-dominating elements in `self`,
source code
 
in_domain(self, f_tuple, reference_point=None)
return `True` if `f_tuple` is dominating the reference point,
source code
 
_strictly_dominates(self, f_tuple)
return `True` if any element of `self` strictly dominates `f_tuple`.
source code
 
_strictly_dominates_with(self, idx, f_tuple)
return `True` if ``self[idx]`` strictly dominates `f_tuple`.
source code
 
_projection(self, f_tuple, i, x) source code
 
_projection_to_empirical_front(self, f_tuple)
return the orthogonal projections of f_tuple on the empirical front, with respect to the coodinates axis.
source code
 
contributing_hypervolume(self, f_tuple)
Hypervolume improvement of f_tuple with respect to self.
source code
 
distance_to_pareto_front(self, f_tuple)
Compute the distance of a dominated f_tuple to the empirical Pareto front.
source code
 
hypervolume_improvement(self, f_tuple)
return how much `f_tuple` would improve the hypervolume.
source code
 
_asserts(self)
make all kind of consistency assertions.
source code

Inherited from list: __add__, __contains__, __delitem__, __delslice__, __eq__, __ge__, __getattribute__, __getitem__, __getslice__, __gt__, __iadd__, __imul__, __iter__, __le__, __len__, __lt__, __mul__, __ne__, __new__, __repr__, __reversed__, __rmul__, __setitem__, __setslice__, __sizeof__, append, count, extend, index, insert, pop, reverse, sort

Inherited from object: __delattr__, __format__, __reduce__, __reduce_ex__, __setattr__, __str__, __subclasshook__

Static Methods [hide private]
 
_random_archive(max_size=500, p_ref_point=0.5) source code
 
_random_archive_many(k, max_size=500, p_ref_point=0.5) source code
Class Variables [hide private]

Inherited from list: __hash__

Properties [hide private]
  kink_points
Create the 'kink' points from elements of self.
  hypervolume
hypervolume of the entire list w.r.t.

Inherited from object: __class__

Method Details [hide private]

__init__(self, list_of_f_tuples=None, reference_point=None)
(Constructor)

source code 

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.

Returns: new empty list
Overrides: object.__init__

remove(self, f_tuple)

source code 

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`).

Overrides: list.remove

dominates(self, f_tuple)

source code 

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()

dominates_with(self, idx, f_tuple)

source code 
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

:todo: add more doctests that actually test the functionality and
       not only whether the return value is correct if empty

dominates_with_for(self, idx, f_tuple)

source code 

returns true if self[idx] weakly dominates f_tuple

replaces dominates_with_old because it turned out to run quicker

dominators(self, f_tuple, number_only=False)

source code 

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])
[]

in_domain(self, f_tuple, reference_point=None)

source code 

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?

_strictly_dominates(self, f_tuple)

source code 

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()

_strictly_dominates_with(self, idx, f_tuple)

source code 

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

contributing_hypervolume(self, f_tuple)

source code 

Hypervolume improvement of f_tuple with respect to self. TODO: the argument should be an index, as in moarchiving.

hypervolume_improvement(self, f_tuple)

source code 

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.

_asserts(self)

source code 

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)

Property Details [hide private]

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

Get Method:
unreachable.kink_points(self) - Create the 'kink' points from elements of self.

hypervolume

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()
Get Method:
unreachable.hypervolume(self) - hypervolume of the entire list w.r.t.