141 lines
4.6 KiB
Python
141 lines
4.6 KiB
Python
"""
|
|
@package tests.test_swarm
|
|
unit tests for @ref pmsco.optimizers.swarm
|
|
|
|
the purpose of these tests is to help debugging the code.
|
|
|
|
to run the tests, change to the directory which contains the tests directory, and execute =nosetests=.
|
|
|
|
@pre nose must be installed (python-nose package on Debian).
|
|
|
|
@author Matthias Muntwiler, matthias.muntwiler@psi.ch
|
|
|
|
@copyright (c) 2015 by Paul Scherrer Institut @n
|
|
Licensed under the Apache License, Version 2.0 (the "License"); @n
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
"""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
import numpy as np
|
|
import os
|
|
import os.path
|
|
import random
|
|
import shutil
|
|
import tempfile
|
|
import unittest
|
|
|
|
import pmsco.optimizers.swarm as swarm
|
|
import pmsco.project as project
|
|
|
|
POP_SIZE = 5
|
|
|
|
|
|
class TestSwarmPopulation(unittest.TestCase):
|
|
def setUp(self):
|
|
random.seed(0)
|
|
self.test_dir = tempfile.mkdtemp()
|
|
self.model_space = project.ModelSpace()
|
|
|
|
self.model_space.add_param('A', 1.5, 1.0, 2.0, 0.1)
|
|
self.model_space.add_param('B', 2.5, 2.0, 3.0, 0.1)
|
|
self.model_space.add_param('C', 3.5, 3.0, 4.0, 0.1)
|
|
self.expected_names = ('_gen', '_model', '_particle', '_rfac', 'A', 'B', 'C')
|
|
|
|
self.size = POP_SIZE
|
|
self.pop = swarm.SwarmPopulation()
|
|
|
|
self.optimum1 = {'A': 1.045351, 'B': 2.346212, 'C': 3.873627}
|
|
|
|
def tearDown(self):
|
|
# after each test method
|
|
self.pop = None
|
|
shutil.rmtree(self.test_dir)
|
|
|
|
@classmethod
|
|
def setup_class(cls):
|
|
# before any methods in this class
|
|
pass
|
|
|
|
@classmethod
|
|
def teardown_class(cls):
|
|
# teardown_class() after any methods in this class
|
|
pass
|
|
|
|
def rfactor1(self, pos):
|
|
r = (pos['A'] - self.optimum1['A'])**2 \
|
|
+ (pos['B'] - self.optimum1['B'])**2 \
|
|
+ (pos['C'] - self.optimum1['C'])**2
|
|
r /= 3.0
|
|
return r
|
|
|
|
def test_best_friend(self):
|
|
self.pop.setup(self.size, self.model_space)
|
|
self.pop.best['_rfac'] = np.arange(self.size)
|
|
friend = self.pop.best_friend(0)
|
|
self.assertNotIsInstance(friend, np.ndarray)
|
|
self.assertEqual(friend.dtype.names, self.expected_names)
|
|
|
|
def test_advance_particle(self):
|
|
self.pop.setup(self.size, self.model_space)
|
|
|
|
self.pop.pos['A'] = np.linspace(1.0, 2.0, POP_SIZE)
|
|
self.pop.pos['B'] = np.linspace(2.0, 3.0, POP_SIZE)
|
|
self.pop.pos['C'] = np.linspace(3.0, 4.0, POP_SIZE)
|
|
self.pop.pos['_rfac'] = np.linspace(2.0, 1.0, POP_SIZE)
|
|
|
|
self.pop.vel['A'] = np.linspace(-0.1, 0.1, POP_SIZE)
|
|
self.pop.vel['B'] = np.linspace(-0.1, 0.1, POP_SIZE)
|
|
self.pop.vel['C'] = np.linspace(-0.1, 0.1, POP_SIZE)
|
|
|
|
pos0 = self.pop.pos['A'][0]
|
|
self.pop.advance_particle(0)
|
|
pos1 = self.pop.pos['A'][0]
|
|
self.assertNotAlmostEqual(pos0, pos1, delta=0.001)
|
|
|
|
for key in ['A','B','C']:
|
|
for pos in self.pop.pos[key]:
|
|
self.assertGreaterEqual(pos, self.model_space.min[key])
|
|
self.assertLessEqual(pos, self.model_space.max[key])
|
|
|
|
def test_is_converged(self):
|
|
self.pop.setup(self.size, self.model_space)
|
|
self.assertFalse(self.pop.is_converged())
|
|
i_sample = 0
|
|
result = self.pop.pos[i_sample]
|
|
for i in range(POP_SIZE):
|
|
rfac = 1.0 - float(i)/POP_SIZE
|
|
self.pop.add_result(result, rfac)
|
|
self.assertFalse(self.pop.is_converged())
|
|
for i in range(POP_SIZE):
|
|
rfac = (1.0 - float(i)/POP_SIZE) / 1000.0
|
|
self.pop.add_result(result, rfac)
|
|
self.assertTrue(self.pop.is_converged())
|
|
|
|
def test_convergence_1(self):
|
|
self.pop.setup(self.size, self.model_space)
|
|
|
|
self.pop.pos['A'] = np.linspace(1.0, 2.0, POP_SIZE)
|
|
self.pop.pos['B'] = np.linspace(2.0, 3.0, POP_SIZE)
|
|
self.pop.pos['C'] = np.linspace(3.0, 4.0, POP_SIZE)
|
|
self.pop.pos['_rfac'] = np.linspace(2.0, 1.0, POP_SIZE)
|
|
|
|
self.pop.vel['A'] = np.linspace(-0.1, 0.1, POP_SIZE)
|
|
self.pop.vel['B'] = np.linspace(-0.1, 0.1, POP_SIZE)
|
|
self.pop.vel['C'] = np.linspace(-0.1, 0.1, POP_SIZE)
|
|
|
|
for i in range(10):
|
|
self.pop.advance_population()
|
|
for pos in self.pop.pos:
|
|
self.pop.add_result(pos, self.rfactor1(pos))
|
|
|
|
for pos in self.pop.pos:
|
|
self.assertLess(pos['_rfac'], 0.2)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|