Skip to content

Commit

Permalink
Merge pull request #342 from bluescarni/pr/fixes
Browse files Browse the repository at this point in the history
Fixes
  • Loading branch information
bluescarni authored Sep 9, 2019
2 parents b05db4e + 8f634ec commit e2784f8
Show file tree
Hide file tree
Showing 22 changed files with 510 additions and 513 deletions.
23 changes: 23 additions & 0 deletions doc/sphinx/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,32 @@ Changelog
2.11.3 (unreleased)
-------------------

New
~~~

- :func:`pygmo.archipelago.push_back()` now also accepts :class:`~pygmo.island`
objects as input arguments (`#342 <https://github.com/esa/pagmo2/pull/342>`__).

Changes
~~~~~~~

- **BREAKING**: the machinery for the translation between C++ and Python
of vectors of unsigned integral types (e.g., sparsity patterns, individual
IDs, etc.) now requires that, on the Python side, NumPy arrays are created
with the appropriate unsigned integral dtype (e.g., ``uint64`` in most
cases). Previously, pagmo would accept also signed integral dtypes
(`#342 <https://github.com/esa/pagmo2/pull/342>`__).

Fix
~~~

- Various improvements, fixes and cleanups in the translation of
C++ vectors to/from Python
(`#342 <https://github.com/esa/pagmo2/pull/342>`__).

- Fix the printing of islands which contain MO problems
(`#342 <https://github.com/esa/pagmo2/pull/342>`__).

- Various doc improvements and fixes (`#340 <https://github.com/esa/pagmo2/pull/340>`__).

2.11.2 (2019-08-21)
Expand Down
35 changes: 31 additions & 4 deletions pygmo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,7 @@ def _archi_init(self, n=0, t=topology(), **kwargs):
setattr(archipelago, "__init__", _archi_init)


def _archi_push_back(self, **kwargs):
def _archi_push_back(self, *args, **kwargs):
"""Add an island.
This method will construct an island from the supplied arguments and add it to the archipelago.
Expand All @@ -699,15 +699,42 @@ def _archi_push_back(self, **kwargs):
the addition of a new island to the archipelago is mirrored by the addition of a new vertex
to the topology.
The keyword arguments accept the same format as explained in the constructor of
:class:`~pygmo.island`.
This method accepts either a single positional argument, or a set of
keyword arguments:
* if no positional arguments are provided, then the keyword arguments will
be used to construct a :class:`~pygmo.island` which will then be added
to the archipelago; otherwise,
* if a single positional argument is provided and no keyword arguments are
provided, then the positional argument is interpreted as an :class:`~pygmo.island`
object to be added to the archipelago.
Any other combination of positional/keyword arguments will result in an error.
Raises:
ValueError: if, when using positional arguments, there are more than 1 positional arguments,
or if keyword arguments are also used at the same time
TypeError: if, when using a single positional argument, the type of that argument
is not :class:`~pygmo.island`
unspecified: any exception thrown by the constructor of :class:`~pygmo.island`,
:func:`pygmo.topology.push_back()` or by the underlying C++ method
"""
self._push_back(island(**kwargs))
from . import island

if len(args) == 0:
self._push_back(island(**kwargs))
else:
if len(args) != 1:
raise ValueError(
"{} positional arguments were provided, but this method accepts only a single positional argument".format(len(args)))
if len(kwargs) != 0:
raise ValueError(
"if a positional argument is passed to this method, then no keyword arguments must be passed, but {} keyword arguments were passed instead".format(len(kwargs)))
if type(args[0]) != island:
raise TypeError(
"the positional argument passed to this method must be an island, but the type of the argument is '{}' instead".format(type(args[0])))
self._push_back(args[0])


setattr(archipelago, "push_back", _archi_push_back)
Expand Down
19 changes: 19 additions & 0 deletions pygmo/_island_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def runTest(self):
self.run_io_tests()
self.run_status_tests()
self.run_stateful_algo_tests()
self.run_mo_sto_repr_bug()

def run_basic_tests(self):
from .core import island, thread_island, null_algorithm, null_problem, de, rosenbrock, r_policy, s_policy, fair_replace, select_best, population
Expand Down Expand Up @@ -399,6 +400,24 @@ def run_evolve(self, algo, pop):
self.assertTrue(isl.extract(object) is None)
self.assertTrue(not isl.extract(thread_island) is None)

def run_mo_sto_repr_bug(self):
# Old bug: printing islands containing MO/sto
# problems would throw due to an error being raised
# when accessing the champion.
from .core import island, de, rosenbrock, zdt, inventory

isl = island(algo=de(), prob=rosenbrock(), size=25)
self.assertTrue("Champion decision vector" in repr(isl))
self.assertTrue("Champion fitness" in repr(isl))

isl = island(algo=de(), prob=zdt(), size=25)
self.assertFalse("Champion decision vector" in repr(isl))
self.assertFalse("Champion fitness" in repr(isl))

isl = island(algo=de(), prob=inventory(), size=25)
self.assertFalse("Champion decision vector" in repr(isl))
self.assertFalse("Champion fitness" in repr(isl))


class mp_island_test_case(_ut.TestCase):
"""Test case for the :class:`~pygmo.mp_island` class.
Expand Down
30 changes: 15 additions & 15 deletions pygmo/_problem_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1120,7 +1120,7 @@ def fitness(self, a):
return [42]

def gradient_sparsity(self):
return array([[0, 0], [0, 1]])
return array([[0, 0], [0, 1]], dtype='uint32')

self.assert_(problem(p()).has_gradient_sparsity())
self.assert_(isinstance(problem(p()).gradient_sparsity(), ndarray))
Expand All @@ -1137,7 +1137,7 @@ def fitness(self, a):
return [42]

def gradient_sparsity(self):
return array([[0, 0], [0, 123]])
return array([[0, 0], [0, 123]], dtype='uint32')

self.assertRaises(ValueError, lambda: problem(p()))

Expand All @@ -1150,7 +1150,7 @@ def fitness(self, a):
return [42]

def gradient_sparsity(self):
return array([[0, 0, 0], [0, 1, 0]])
return array([[0, 0, 0], [0, 1, 0]], dtype='uint32')

self.assertRaises(ValueError, lambda: problem(p()))

Expand All @@ -1163,7 +1163,7 @@ def fitness(self, a):
return [42]

def gradient_sparsity(self):
return array([[[0], [1], [2]]])
return array([[[0], [1], [2]]], dtype='uint32')

self.assertRaises(ValueError, lambda: problem(p()))

Expand All @@ -1189,9 +1189,9 @@ def fitness(self, a):
return [42]

def gradient_sparsity(self):
return array([[0, 0], [0, -1]])
return array([[0, 0], [0, -1]], dtype='int32')

self.assertRaises(OverflowError, lambda: problem(p()))
self.assertRaises(TypeError, lambda: problem(p()))

class p(object):

Expand All @@ -1202,7 +1202,7 @@ def fitness(self, a):
return [42]

def gradient_sparsity(self):
a = array([[0, 0, 0], [0, 1, 0]])
a = array([[0, 0, 0], [0, 1, 0]], dtype='uint32')
return a[:, :2]

self.assert_(problem(p()).has_gradient_sparsity())
Expand Down Expand Up @@ -1627,7 +1627,7 @@ def fitness(self, a):
return [42]

def hessians_sparsity(self):
return [array([[0, 0], [1, 1]])]
return [array([[0, 0], [1, 1]], dtype='uint32')]

self.assert_(problem(p()).has_hessians_sparsity())
self.assert_(isinstance(problem(p()).hessians_sparsity(), list))
Expand All @@ -1645,7 +1645,7 @@ def fitness(self, a):
return [42]

def hessians_sparsity(self):
return array([[0, 0], [0, 123]])
return array([[0, 0], [0, 123]], dtype='uint32')

self.assertRaises(ValueError, lambda: problem(p()))

Expand All @@ -1658,7 +1658,7 @@ def fitness(self, a):
return [42]

def hessians_sparsity(self):
return (array([[0, 0, 0], [0, 1, 0]]),)
return (array([[0, 0, 0], [0, 1, 0]], dtype='uint32'),)

self.assertRaises(ValueError, lambda: problem(p()))

Expand All @@ -1671,7 +1671,7 @@ def fitness(self, a):
return [42]

def hessians_sparsity(self):
return [array([[[0], [1], [2]]])]
return [array([[[0], [1], [2]]], dtype='uint32')]

self.assertRaises(ValueError, lambda: problem(p()))

Expand All @@ -1697,9 +1697,9 @@ def fitness(self, a):
return [42]

def hessians_sparsity(self):
return [array([[0, 0], [0, -1]])]
return [array([[0, 0], [0, -1]], dtype='int32')]

self.assertRaises(OverflowError, lambda: problem(p()))
self.assertRaises(TypeError, lambda: problem(p()))

class p(object):

Expand All @@ -1710,7 +1710,7 @@ def fitness(self, a):
return [42]

def hessians_sparsity(self):
a = array([[0, 0, 0], [1, 1, 0]])
a = array([[0, 0, 0], [1, 1, 0]], dtype='uint32')
return [a[:, :2]]

self.assert_(problem(p()).has_hessians_sparsity())
Expand Down Expand Up @@ -1745,7 +1745,7 @@ def get_nobj(self):
return 2

def hessians_sparsity(self):
return [array([[0, 0], [1, 1]]), array([[0, 0], [1, 0]])]
return [array([[0, 0], [1, 1]], dtype='uint32'), array([[0, 0], [1, 0]], dtype='uint32')]

self.assert_(problem(p()).has_hessians_sparsity())
self.assert_(isinstance(problem(p()).hessians_sparsity(), list))
Expand Down
29 changes: 29 additions & 0 deletions pygmo/_r_policy_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,35 @@ def replace(self, inds, nx, nix, nobj, nec, nic, tol, mig):
r_pol.replace(([1, 2], [[.1, .2], [.3, .4]], [
[1.1], [2.2]]), 2, 0, 1, 0, 0, [], ([], [], []))

class r(object):

def replace(self, inds, nx, nix, nobj, nec, nic, tol, mig):
return (np.array([1], dtype='float64'), [[1, 2]], [[1]])
r_pol = r_policy(r())
with self.assertRaises(RuntimeError) as cm:
r_pol.replace(([1, 2], [[.1, .2], [.3, .4]], [
[1.1], [2.2]]), 2, 0, 1, 0, 0, [], ([], [], []))

# Test construction of array ID from list.
inds = ([1, 2], [[.1, .2], [.3, .4]], [[1.1], [2.2]])

class r(object):

def replace(self, inds, nx, nix, nobj, nec, nic, tol, mig):
return ([1], [[1, 2]], [[1]])
r_pol = r_policy(r())
ret = r_pol.replace(inds, 2, 0, 1, 0, 0, [], inds)
self.assertEqual(ret[0][0], 1)

# Test construction of array ID from numpy array.
class r(object):

def replace(self, inds, nx, nix, nobj, nec, nic, tol, mig):
return (np.array([1], dtype='ulonglong'), [[1, 2]], [[1]])
r_pol = r_policy(r())
ret = r_pol.replace(inds, 2, 0, 1, 0, 0, [], inds)
self.assertEqual(ret[0][0], 1)

# Test that construction from another pygmo.r_policy fails.
with self.assertRaises(TypeError) as cm:
r_policy(r_pol)
Expand Down
30 changes: 30 additions & 0 deletions pygmo/_s_policy_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,36 @@ def select(self, inds, nx, nix, nobj, nec, nic, tol):
s_pol.select(([1, 2], [[.1, .2], [.3, .4]], [
[1.1], [2.2]]), 2, 0, 1, 0, 0, [])

# Test wrong array construction of IDs.
class r(object):

def select(self, inds, nx, nix, nobj, nec, nic, tol):
return (np.array([1], dtype='float64'), [[1, 2]], [[1]])
s_pol = s_policy(r())
with self.assertRaises(RuntimeError) as cm:
s_pol.select(([1, 2], [[.1, .2], [.3, .4]], [
[1.1], [2.2]]), 2, 0, 1, 0, 0, [])

# Test construction of array ID from list.
class r(object):

def select(self, inds, nx, nix, nobj, nec, nic, tol):
return ([1], [[1, 2]], [[1]])
s_pol = s_policy(r())
ret = s_pol.select(([1, 2], [[.1, .2], [.3, .4]], [
[1.1], [2.2]]), 2, 0, 1, 0, 0, [])
self.assertEqual(ret[0][0], 1)

# Test construction of array ID from array.
class r(object):

def select(self, inds, nx, nix, nobj, nec, nic, tol):
return (np.array([1], dtype='ulonglong'), [[1, 2]], [[1]])
s_pol = s_policy(r())
ret = s_pol.select(([1, 2], [[.1, .2], [.3, .4]], [
[1.1], [2.2]]), 2, 0, 1, 0, 0, [])
self.assertEqual(ret[0][0], 1)

# Test that construction from another pygmo.s_policy fails.
with self.assertRaises(TypeError) as cm:
s_policy(s_pol)
Expand Down
2 changes: 1 addition & 1 deletion pygmo/bfe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ std::unique_ptr<bfe_inner_base> bfe_inner<bp::object>::clone() const

vector_double bfe_inner<bp::object>::operator()(const problem &p, const vector_double &dvs) const
{
return pygmo::to_vd(m_value.attr("__call__")(p, pygmo::v_to_a(dvs)));
return pygmo::obj_to_vector<vector_double>(m_value.attr("__call__")(p, pygmo::vector_to_ndarr(dvs)));
}

pagmo::thread_safety bfe_inner<bp::object>::get_thread_safety() const
Expand Down
Loading

0 comments on commit e2784f8

Please sign in to comment.