From 50cd292174cd645b0f6986a845a9a40feb064819 Mon Sep 17 00:00:00 2001 From: LucasWaelti Date: Thu, 11 Aug 2022 13:04:28 +0200 Subject: [PATCH] Implemented options to hotstart training --- pyswarms/backend/generators.py | 24 +++++++++++++++++++++--- pyswarms/base/base_discrete.py | 15 +++++++++++++++ pyswarms/base/base_single.py | 15 +++++++++++++++ pyswarms/single/general_optimizer.py | 10 ++++++++++ pyswarms/single/global_best.py | 10 ++++++++++ pyswarms/single/local_best.py | 10 ++++++++++ 6 files changed, 81 insertions(+), 3 deletions(-) diff --git a/pyswarms/backend/generators.py b/pyswarms/backend/generators.py index 4a8ab114..0786fb65 100644 --- a/pyswarms/backend/generators.py +++ b/pyswarms/backend/generators.py @@ -22,7 +22,7 @@ def generate_swarm( - n_particles, dimensions, bounds=None, center=1.00, init_pos=None + n_particles, dimensions, bounds=None, center=1.00, init_pos=None, init_best=None ): """Generate a swarm @@ -43,6 +43,10 @@ def generate_swarm( option to explicitly set the particles' initial positions. Set to :code:`None` if you wish to generate the particles randomly. Default is :code:`None`. + init_best : numpy.ndarray, optional + option to explicitly set a particle to the previously obtained global best. Set to + :code:`None` if you wish to generate the particles randomly. + Default is :code:`None`. Returns ------- @@ -81,6 +85,8 @@ def generate_swarm( pos = center * np.random.uniform( low=min_bounds, high=max_bounds, size=(n_particles, dimensions) ) + if init_best is not None: + pos[0] = init_best except ValueError: msg = "Bounds and/or init_pos should be of size ({},)" rep.logger.exception(msg.format(dimensions)) @@ -193,6 +199,8 @@ def create_swarm( bounds=None, center=1.0, init_pos=None, + init_vel=None, + init_best=None, clamp=None, ): """Abstract the generate_swarm() and generate_velocity() methods @@ -218,6 +226,12 @@ def create_swarm( init_pos : numpy.ndarray, optional option to explicitly set the particles' initial positions. Set to :code:`None` if you wish to generate the particles randomly. + init_vel : numpy.ndarray, optional + option to explicitly set the particles' initial velocities. Set to + :code:`None` if you wish to generate the velocities randomly. + init_best : numpy.ndarray, optional + option to explicitly set a particle to the previously obtained global best. Set to + :code:`None` if you wish to generate the particles randomly. clamp : tuple of floats, optional a tuple of size 2 where the first entry is the minimum velocity and the second entry is the maximum velocity. It @@ -230,7 +244,7 @@ def create_swarm( """ if discrete: position = generate_discrete_swarm( - n_particles, dimensions, binary=binary, init_pos=init_pos + n_particles, dimensions, binary=binary, init_pos=init_pos # TODO add init_best ) else: position = generate_swarm( @@ -239,7 +253,11 @@ def create_swarm( bounds=bounds, center=center, init_pos=init_pos, + init_best=init_best, ) - velocity = generate_velocity(n_particles, dimensions, clamp=clamp) + if init_vel is None: + velocity = generate_velocity(n_particles, dimensions, clamp=clamp) + else: + velocity = init_vel return Swarm(position, velocity, options=options) diff --git a/pyswarms/base/base_discrete.py b/pyswarms/base/base_discrete.py index 7436ffc5..634bbdf4 100644 --- a/pyswarms/base/base_discrete.py +++ b/pyswarms/base/base_discrete.py @@ -48,6 +48,8 @@ def __init__( options, velocity_clamp=None, init_pos=None, + init_vel=None, + init_best=None, ftol=-np.inf, ftol_iter=1, ): @@ -81,6 +83,15 @@ def __init__( a tuple of size 2 where the first entry is the minimum velocity and the second entry is the maximum velocity. It sets the limits for velocity clamping. + init_pos : numpy.ndarray, optional + option to explicitly set the particles' initial positions. Set to + :code:`None` if you wish to generate the particles randomly. + init_vel : numpy.ndarray, optional + option to explicitly set the particles' initial velocities. Set to + :code:`None` if you wish to generate the velocities randomly. + init_best : numpy.ndarray, optional + option to explicitly set a particle to the previously obtained global best. Set to + :code:`None` if you wish to generate the particles randomly. ftol : float, optional relative error in objective_func(best_pos) acceptable for convergence. Default is :code:`-np.inf`. @@ -100,6 +111,8 @@ def __init__( self.swarm_size = (n_particles, dimensions) self.options = options self.init_pos = init_pos + self.init_vel = init_vel + self.init_best = init_best self.ftol = ftol try: @@ -208,6 +221,8 @@ def reset(self): dimensions=self.dimensions, discrete=True, init_pos=self.init_pos, + init_vel=self.init_vel, + init_best=self.init_best, binary=self.binary, clamp=self.velocity_clamp, options=self.options, diff --git a/pyswarms/base/base_single.py b/pyswarms/base/base_single.py index ad6d27dc..e5b5f75f 100644 --- a/pyswarms/base/base_single.py +++ b/pyswarms/base/base_single.py @@ -52,6 +52,8 @@ def __init__( ftol=-np.inf, ftol_iter=1, init_pos=None, + init_vel=None, + init_best=None, ): """Initialize the swarm @@ -89,6 +91,15 @@ def __init__( number of iterations over which the relative error in objective_func(best_pos) is acceptable for convergence. Default is :code:`1` + init_pos : numpy.ndarray, optional + option to explicitly set the particles' initial positions. Set to + :code:`None` if you wish to generate the particles randomly. + init_vel : numpy.ndarray, optional + option to explicitly set the particles' initial velocities. Set to + :code:`None` if you wish to generate the velocities randomly. + init_best : numpy.ndarray, optional + option to explicitly set a particle to the previously obtained global best. Set to + :code:`None` if you wish to generate the particles randomly. """ # Initialize primary swarm attributes self.n_particles = n_particles @@ -109,6 +120,8 @@ def __init__( self.ftol_iter = ftol_iter self.init_pos = init_pos + self.init_vel = init_vel + self.init_best = init_best # Initialize named tuple for populating the history list self.ToHistory = namedtuple( "ToHistory", @@ -207,6 +220,8 @@ def reset(self): bounds=self.bounds, center=self.center, init_pos=self.init_pos, + init_vel=self.init_vel, + init_best=self.init_best, clamp=self.velocity_clamp, options=self.options, ) diff --git a/pyswarms/single/general_optimizer.py b/pyswarms/single/general_optimizer.py index a46d3ed6..f003f765 100644 --- a/pyswarms/single/general_optimizer.py +++ b/pyswarms/single/general_optimizer.py @@ -88,6 +88,8 @@ def __init__( ftol=-np.inf, ftol_iter=1, init_pos=None, + init_vel=None, + init_best=None, ): """Initialize the swarm @@ -166,6 +168,12 @@ def __init__( init_pos : numpy.ndarray, optional option to explicitly set the particles' initial positions. Set to :code:`None` if you wish to generate the particles randomly. + init_vel : numpy.ndarray, optional + option to explicitly set the particles' initial velocities. Set to + :code:`None` if you wish to generate the velocities randomly. + init_best : numpy.ndarray, optional + option to explicitly set a particle to the previously obtained global best. Set to + :code:`None` if you wish to generate the particles randomly. """ super(GeneralOptimizerPSO, self).__init__( n_particles, @@ -177,6 +185,8 @@ def __init__( ftol=ftol, ftol_iter=ftol_iter, init_pos=init_pos, + init_vel=init_vel, + init_best=init_best, ) if oh_strategy is None: oh_strategy = {} diff --git a/pyswarms/single/global_best.py b/pyswarms/single/global_best.py index 3392bfb3..e81532b6 100644 --- a/pyswarms/single/global_best.py +++ b/pyswarms/single/global_best.py @@ -86,6 +86,8 @@ def __init__( ftol=-np.inf, ftol_iter=1, init_pos=None, + init_vel=None, + init_best=None, ): """Initialize the swarm @@ -130,6 +132,12 @@ def __init__( init_pos : numpy.ndarray, optional option to explicitly set the particles' initial positions. Set to :code:`None` if you wish to generate the particles randomly. + init_vel : numpy.ndarray, optional + option to explicitly set the particles' initial velocities. Set to + :code:`None` if you wish to generate the velocities randomly. + init_best : numpy.ndarray, optional + option to explicitly set a particle to the previously obtained global best. Set to + :code:`None` if you wish to generate the particles randomly. """ super(GlobalBestPSO, self).__init__( n_particles=n_particles, @@ -141,6 +149,8 @@ def __init__( ftol=ftol, ftol_iter=ftol_iter, init_pos=init_pos, + init_vel=init_vel, + init_best=init_best, ) if oh_strategy is None: diff --git a/pyswarms/single/local_best.py b/pyswarms/single/local_best.py index 146442d7..43d2109a 100644 --- a/pyswarms/single/local_best.py +++ b/pyswarms/single/local_best.py @@ -95,6 +95,8 @@ def __init__( ftol=-np.inf, ftol_iter=1, init_pos=None, + init_vel=None, + init_best=None, static=False, ): """Initialize the swarm @@ -147,6 +149,12 @@ def __init__( init_pos : numpy.ndarray, optional option to explicitly set the particles' initial positions. Set to :code:`None` if you wish to generate the particles randomly. + init_vel : numpy.ndarray, optional + option to explicitly set the particles' initial velocities. Set to + :code:`None` if you wish to generate the velocities randomly. + init_best : numpy.ndarray, optional + option to explicitly set a particle to the previously obtained global best. Set to + :code:`None` if you wish to generate the particles randomly. static: bool a boolean that decides whether the Ring topology used is static or dynamic. Default is `False` @@ -168,6 +176,8 @@ def __init__( ftol=ftol, ftol_iter=ftol_iter, init_pos=init_pos, + init_vel=init_vel, + init_best=init_best, ) # Initialize logger self.rep = Reporter(logger=logging.getLogger(__name__))