def test_unmodified_strategy(clamp, velocities_inbound, velocities_out_of_bound): vh = VelocityHandler(strategy="unmodified") inbound_handled = vh(velocities_inbound, clamp) outbound_handled = vh(velocities_out_of_bound, clamp) assert inbound_handled.all() == velocities_inbound.all() assert outbound_handled.all() == velocities_out_of_bound.all()
def test_missing_kwargs(self, swarm, options, vh_strat): """Test if method raises KeyError with missing kwargs""" vh = VelocityHandler(strategy=vh_strat) with pytest.raises(KeyError): swarm.options = options clamp = (0, 1) P.compute_velocity(swarm, clamp, vh)
def test_return_values(self, swarm, clamp): """Test if method gives the expected shape and range""" vh = VelocityHandler(strategy="unmodified") v = P.compute_velocity(swarm, clamp, vh) assert v.shape == swarm.position.shape if clamp is not None: assert (clamp[0] <= v).all() and (clamp[1] >= v).all()
def test_zero_strategy( clamp, velocities_inbound, velocities_out_of_bound, positions_inbound, positions_out_of_bound, bounds, ): vh = VelocityHandler(strategy="zero") # TODO Add strategy specific tests pass
def test_adjust_strategy( clamp, velocities_inbound, velocities_out_of_bound, positions_inbound, positions_out_of_bound, ): vh = VelocityHandler(strategy="adjust") assert_clamp( clamp, velocities_inbound, velocities_out_of_bound, positions_inbound, positions_out_of_bound, vh, ) # TODO Add strategy specific tests pass
def compute_velocity(self, swarm, clamp=None, vh=VelocityHandler(strategy="unmodified"), bounds=None, iter=None): """Compute the velocity matrix This method updates the velocity matrix using the best and current positions of the swarm. The velocity matrix is computed using the cognitive and social terms of the swarm. A sample usage can be seen with the following: .. code-block :: python import pyswarms.backend as P from pyswarms.backend.swarm import Swarm from pyswarms.backend.handlers import VelocityHandler from pyswarms.backend.topology import Star my_swarm = P.create_swarm(n_particles, dimensions) my_topology = Star() my_vh = VelocityHandler(strategy="adjust") for i in range(iters): # Inside the for-loop my_swarm.velocity = my_topology.update_velocity(my_swarm, clamp, my_vh, bounds) Parameters ---------- swarm : pyswarms.backend.swarms.Swarm a Swarm instance clamp : tuple of floats (default is :code:`None`) 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. vh : pyswarms.backend.handlers.VelocityHandler a VelocityHandler instance bounds : tuple of :code:`np.ndarray` or list (default is :code:`None`) a tuple of size 2 where the first entry is the minimum bound while the second entry is the maximum bound. Each array must be of shape :code:`(dimensions,)`. Returns ------- numpy.ndarray Updated velocity matrix """ swarm_size = swarm.position.shape c1 = swarm.options["c1"] c2 = swarm.options["c2"] w = swarm.options["w"] # Compute for cognitive and social terms cognitive = (c1 * np.random.uniform(0, 1, swarm_size) * (swarm.pbest_pos - swarm.position)) social = (c2 * np.random.uniform(0, 1, swarm_size) * (swarm.best_pos - swarm.position)) # Compute temp velocity (subject to clamping if possible) temp_velocity = (w * swarm.velocity) + cognitive + social temp_velocity *= boost_factor(iter - swarm.pbest_iter) updated_velocity = vh(temp_velocity, clamp, position=swarm.position, bounds=bounds) updated_velocity[:, swarm.discrete_index:] = np.rint( updated_velocity[:, swarm.discrete_index:]) return updated_velocity
def __init__( self, n_particles, dimensions, options, bounds=None, bh_strategy="periodic", velocity_clamp=None, vh_strategy="unmodified", center=1.00, ftol=-np.inf, init_pos=None, ): """ A custom optimizer modified from pyswarms.single.global_best https://github.com/ljvmiranda921/pyswarms/blob/master/pyswarms/single/global_best.py Attributes ---------- n_particles : int number of particles in the swarm. dimensions : int number of dimensions in the space. options : dict with keys :code:`{'c1', 'c2', 'w'}` a dictionary containing the parameters for the specific optimization technique. * c1 : float cognitive parameter * c2 : float social parameter * w : float inertia parameter bounds : tuple of numpy.ndarray, optional a tuple of size 2 where the first entry is the minimum bound while the second entry is the maximum bound. Each array must be of shape :code:`(dimensions,)`. bh_strategy : str a strategy for the handling of out-of-bounds particles. velocity_clamp : tuple, optional 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. vh_strategy : str a strategy for the handling of the velocity of out-of-bounds particles. center : list (default is :code:`None`) an array of size :code:`dimensions` ftol : float relative error in objective_func(best_pos) acceptable for convergence. Default is :code:`-np.inf` 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. """ super(PSOoptimizer, self).__init__( n_particles=n_particles, dimensions=dimensions, options=options, bounds=bounds, velocity_clamp=velocity_clamp, center=center, ftol=ftol, init_pos=init_pos, ) # Initialize logger self.rep = Reporter(logger=logging.getLogger(__name__)) # Initialize the resettable attributes self.reset() # Initialize the topology self.top = Star() self.bh = BoundaryHandler(strategy=bh_strategy) self.vh = VelocityHandler(strategy=vh_strategy) self.name = __name__ # Populate memory of the handlers self.bh.memory = self.swarm.position self.vh.memory = self.swarm.position self.swarm.pbest_cost = np.full(self.swarm_size[0], np.inf) # Set reached requirement self.reached_requirement = 0
def __init__( self, n_particles, dimensions_discrete, options, bounds, bh_strategy="periodic", init_pos=None, velocity_clamp=None, vh_strategy="unmodified", ftol=-np.inf, ftol_iter=1, ): """Initialize the swarm Attributes ---------- n_particles : int number of particles in the swarm. dimensions_discrete : int number of discrete dimensions of the search space. options : dict with keys :code:`{'c1', 'c2', 'w', 'k', 'p'}` a dictionary containing the parameters for the specific optimization technique * c1 : float cognitive parameter * c2 : float social parameter * w : float inertia parameter * k : int number of neighbors to be considered. Must be a positive integer less than :code:`n_particles` * p: int {1,2} the Minkowski p-norm to use. 1 is the sum-of-absolute values (or L1 distance) while 2 is the Euclidean (or L2) distance. bounds : tuple of numpy.ndarray a tuple of size 2 where the first entry is the minimum bound while the second entry is the maximum bound. Each array must be of shape :code:`(dimensions,)`. 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. velocity_clamp : tuple, optional 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. vh_strategy : String a strategy for the handling of the velocity of out-of-bounds particles. Only the "unmodified" and the "adjust" strategies are allowed. ftol : float relative error in objective_func(best_pos) acceptable for convergence ftol_iter : int number of iterations over which the relative error in objective_func(best_pos) is acceptable for convergence. Default is :code:`1` """ # Initialize logger self.rep = Reporter(logger=logging.getLogger(__name__)) # Assign k-neighbors and p-value as attributes self.k, self.p = options["k"], options["p"] self.dimensions_discrete = dimensions_discrete self.bits, self.bounds = self.discretePSO_to_binaryPSO( dimensions_discrete, bounds) # Initialize parent class super(BinaryPSO, self).__init__( n_particles=n_particles, dimensions=sum(self.bits), binary=True, options=options, init_pos=init_pos, velocity_clamp=velocity_clamp, ftol=ftol, ftol_iter=ftol_iter, ) # self.bounds = bounds # Initialize the resettable attributes self.reset() # Initialize the topology self.top = Ring(static=False) self.vh = VelocityHandler(strategy=vh_strategy) self.bh = BoundaryHandler(strategy=bh_strategy) self.name = __name__
def test_input_swarm(self, swarm, vh_strat): """Test if method raises AttributeError with wrong swarm""" vh = VelocityHandler(strategy=vh_strat) with pytest.raises(AttributeError): P.compute_velocity(swarm, clamp=(0, 1), vh=vh)