Ejemplo n.º 1
0
    def _transition_packs(self, agents, n_c):
        """Transits coyotes between packs (Eq. 4).

        Args:
            agents (list): List of agents.
            n_c (int): Number of coyotes per pack.

        """

        # Calculates the eviction probability
        p_e = 0.005 * len(agents)

        # Generates a uniform random number
        r1 = r.generate_uniform_random_number()

        # If random number is smaller than eviction probability
        if r1 < p_e:
            # Gathers two random packs
            p1 = r.generate_integer_random_number(high=self.n_p)
            p2 = r.generate_integer_random_number(high=self.n_p)

            # Gathers two random coyotes
            c1 = r.generate_integer_random_number(high=n_c)
            c2 = r.generate_integer_random_number(high=n_c)

            # Calculates their indexes
            i = n_c * p1 + c1
            j = n_c * p2 + c2

            # Performs a swap betweeh them
            agents[i], agents[j] = copy.deepcopy(agents[j]), copy.deepcopy(
                agents[i])
Ejemplo n.º 2
0
    def _mutation(self, alpha):
        """Performs the mutation over an offspring (s. 3.4).

        Args:
            alpha (Agent): Offspring to be mutated.

        Returns:
            The mutated offspring.

        """

        # Checks if the number of variables is bigger than one
        if alpha.n_variables > 1:
            # Samples a random integer
            r1 = r.generate_integer_random_number(0, alpha.n_variables)

            # Samples the second integer
            r2 = r.generate_integer_random_number(0,
                                                  alpha.n_variables,
                                                  exclude_value=r1)

            # Swaps the randomly selected variables
            alpha.position[r1], alpha.position[r2] = alpha.position[
                r2], alpha.position[r1]

        return alpha
Ejemplo n.º 3
0
    def update(self, space, function):
        """Wraps Symbiotic Organisms Search over all agents and variables.

        Args:
            space (Space): Space containing agents and update-related information.
            function (Function): A Function object that will be used as the objective function.

        """

        # Iterates through all agents
        for i, agent in enumerate(space.agents):
            # Generates a random integer for mutualism and performs it
            j = r.generate_integer_random_number(0,
                                                 len(space.agents),
                                                 exclude_value=i)
            self._mutualism(agent, space.agents[j], space.best_agent, function)

            # Re-generates a random integer for commensalism and performs it
            j = r.generate_integer_random_number(0,
                                                 len(space.agents),
                                                 exclude_value=i)
            self._commensalism(agent, space.agents[j], space.best_agent,
                               function)

            # Re-generates a random integer for parasitism and performs it
            j = r.generate_integer_random_number(0,
                                                 len(space.agents),
                                                 exclude_value=i)
            self._parasitism(agent, space.agents[j], function)
Ejemplo n.º 4
0
    def _update(self, agents, function, n_c):
        """Method that wraps Coyote Optimization Algorithm over all agents and variables.

        Args:
            agents (list): List of agents.
            function (Function): A Function object that will be used as the objective function.
            n_c (int): Number of agents per pack.

        """

        # Iterates through all packs
        for i in range(self.n_p):
            # Gets the agents for the specified pack
            pack_agents = self._get_agents_from_pack(agents, i, n_c)

            # Gathers the alpha coyote (Eq. 5)
            alpha = pack_agents[0]

            # Computes the cultural tendency (Eq. 6)
            tendency = np.median(np.array(
                [agent.position for agent in pack_agents]),
                                 axis=0)

            # Iterates through all coyotes in the pack
            for agent in pack_agents:
                # Makes a deepcopy of current coyote
                a = copy.deepcopy(agent)

                # Generates two random integers
                cr1 = r.generate_integer_random_number(high=len(pack_agents))
                cr2 = r.generate_integer_random_number(high=len(pack_agents))

                # Calculates the alpha and pack influences
                lambda_1 = alpha.position - pack_agents[cr1].position
                lambda_2 = tendency - pack_agents[cr2].position

                # Generates two random uniform numbers
                r1 = r.generate_uniform_random_number()
                r2 = r.generate_uniform_random_number()

                # Updates the social condition (Eq. 12)
                a.position += r1 * lambda_1 + r2 * lambda_2

                # Checks the agent's limits
                a.clip_limits()

                # Evaluates the agent (Eq. 13)
                a.fit = function(a.position)

                # If the new potision is better than current agent's position (Eq. 14)
                if a.fit < agent.fit:
                    # Replaces the current agent's position
                    agent.position = copy.deepcopy(a.position)

                    # Also replaces its fitness
                    agent.fit = copy.deepcopy(a.fit)

            # Performs transition between packs (Eq. 4)
            self._transition_packs(agents, n_c)
Ejemplo n.º 5
0
def test_generate_integer_random_number():
    integer_array = random.generate_integer_random_number(0, 1, None, 5)

    assert integer_array.shape == (5, )

    integer_array = random.generate_integer_random_number(0, 10, 1, 5)

    assert integer_array.shape == (5, )
Ejemplo n.º 6
0
    def _update(self, agents, function, iteration, n_iterations):
        """Method that wraps Artificial Butterfly Optimization over all agents and variables.

        Args:
            agents (list): List of agents.
            function (Function): A Function object that will be used as the objective function.
            iteration (int): Current iteration.
            n_iterations (int): Maximum number of iterations.

        """

        # Sorting agents
        agents.sort(key=lambda x: x.fit)

        # Calculates the number of sunspot butterflies
        n_sunspots = int(self.sunspot_ratio * len(agents))

        # Iterates through all sunspot butterflies
        for agent in agents[:n_sunspots]:
            # Generates the index for a random sunspot butterfly
            k = r.generate_integer_random_number(0, len(agents))

            # Performs a flight mode using sunspot butterflies (eq. 1)
            agent.position, agent.fit, _ = self._flight_mode(agent, agents[k], function)

        # Iterates through all canopy butterflies
        for agent in agents[n_sunspots:]:
            # Generates the index for a random canopy butterfly
            k = r.generate_integer_random_number(0, len(agents) - n_sunspots)

            # Performs a flight mode using canopy butterflies (eq. 1)
            agent.position, agent.fit, is_better = self._flight_mode(agent, agents[k], function)

            # If there was not fitness replacement
            if not is_better:
                # Generates the index for a random butterfly
                k = r.generate_integer_random_number(0, len(agents))

                # Generates random uniform number
                r1 = r.generate_uniform_random_number()

                # Calculates `D` (eq. 4)
                D = np.fabs(2 * r1 * agents[k].position - agent.position)

                # Generates another random uniform number
                r2 = r.generate_uniform_random_number()

                # Linearly decreases `a`
                a = (self.a - self.a * (iteration / n_iterations))

                # Updates the agent's position (eq. 3)
                agent.position = agents[k].position - 2 * a * r2 - a * D

                # Clips its limits
                agent.clip_limits()

                # Re-calculates its fitness
                agent.fit = function(agent.position)
Ejemplo n.º 7
0
    def _crossover(self, agents: List[Agent],
                   trial_agents: List[Agent]) -> None:
        """Performs the crossover operator.

        Args:
            agents: List of agents.
            trial_agents: List of trial agents.

        """

        # Defines the number of agents and variables
        n_agents = len(agents)
        n_variables = agents[0].n_variables

        # Creates a crossover map
        cross_map = np.ones((n_agents, n_variables))

        # Generates the `a` and `b` random uniform numbers
        a = r.generate_uniform_random_number()
        b = r.generate_uniform_random_number()

        # If `a` is smaller than `b`
        if a < b:
            # Iterates through all agents
            for i in range(n_agents):
                # Generates a uniform random number
                r1 = r.generate_uniform_random_number()

                # Calculates the number of non-crosses
                non_crosses = int(self.mix_rate * r1 * n_variables)

                # Iterates through the number of non-crosses
                for _ in range(non_crosses):
                    # Generates a random decision variable index
                    u = r.generate_integer_random_number(high=n_variables)

                    # Turn off the crossing on this specific point
                    cross_map[i][u] = 0

        # If `a` is bigger than `b`
        else:
            # Iterates through all agents
            for i in range(n_agents):
                # Generates a random decision variable index
                j = r.generate_integer_random_number(high=n_variables)

                # Turn off the crossing on this specific point
                cross_map[i][j] = 0

        # Iterates through all agents
        for i in range(n_agents):
            # Iterates through all decision variables
            for j in range(n_variables):
                # If it is supposed to cross according to the map
                if cross_map[i][j]:
                    # Makes a deep copy on such position
                    trial_agents[i].position[j] = copy.deepcopy(
                        agents[i].position[j])
Ejemplo n.º 8
0
    def update(self, space: Space, function: Function) -> None:
        """Wraps Coyote Optimization Algorithm over all agents and variables.

        Args:
            space: Space containing agents and update-related information.
            function: A Function object that will be used as the objective function.

        """

        # Iterates through all packs
        for i in range(self.n_p):
            # Gets the agents for the specified pack
            pack_agents = self._get_agents_from_pack(space.agents, i)

            # Gathers the alpha coyote (eq. 5)
            alpha = pack_agents[0]

            # Computes the cultural tendency (eq. 6)
            tendency = np.median(np.array(
                [agent.position for agent in pack_agents]),
                                 axis=0)

            # Iterates through all coyotes in the pack
            for agent in pack_agents:
                # Makes a deep copy of current coyote
                a = copy.deepcopy(agent)

                # Generates two random integers
                cr1 = r.generate_integer_random_number(high=len(pack_agents))
                cr2 = r.generate_integer_random_number(high=len(pack_agents))

                # Calculates the alpha and pack influences
                lambda_1 = alpha.position - pack_agents[cr1].position
                lambda_2 = tendency - pack_agents[cr2].position

                # Generates two random uniform numbers
                r1 = r.generate_uniform_random_number()
                r2 = r.generate_uniform_random_number()

                # Updates the social condition (eq. 12)
                a.position += r1 * lambda_1 + r2 * lambda_2

                # Checks the agent's limits
                a.clip_by_bound()

                # Evaluates the agent (eq. 13)
                a.fit = function(a.position)

                # If the new potision is better than current agent's position (eq. 14)
                if a.fit < agent.fit:
                    # Replaces the current agent's position and fitness
                    agent.position = copy.deepcopy(a.position)
                    agent.fit = copy.deepcopy(a.fit)

            # Performs transition between packs (eq. 4)
            self._transition_packs(space.agents)
Ejemplo n.º 9
0
    def _update(self, agents, best_agent, function):
        """Method that wraps global and local pollination updates over all agents and variables.

        Args:
            agents (list): List of agents.
            best_agent (Agent): Global best agent.
            function (Function): A Function object that will be used as the objective function.

        """

        # Iterate through all agents
        for agent in agents:
            # Creates a temporary agent
            a = copy.deepcopy(agent)

            # Generating an uniform random number
            r1 = r.generate_uniform_random_number()

            # Check if generated random number is bigger than probability
            if r1 > self.p:
                # Update a temporary position according to global pollination
                a.position = self._global_pollination(agent.position,
                                                      best_agent.position)

            else:
                # Generates an uniform random number
                epsilon = r.generate_uniform_random_number()

                # Generates an index for flower k
                k = r.generate_integer_random_number(0, len(agents))

                # Generates an index for flower l
                l = r.generate_integer_random_number(0,
                                                     len(agents),
                                                     exclude_value=k)

                # Update a temporary position according to local pollination
                a.position = self._local_pollination(agent.position,
                                                     agents[k].position,
                                                     agents[l].position,
                                                     epsilon)

            # Check agent limits
            a.clip_limits()

            # Calculates the fitness for the temporary position
            a.fit = function(a.position)

            # If new fitness is better than agent's fitness
            if a.fit < agent.fit:
                # Copy its position to the agent
                agent.position = copy.deepcopy(a.position)

                # And also copy its fitness
                agent.fit = copy.deepcopy(a.fit)
Ejemplo n.º 10
0
    def update(self, space: Space, function: Function) -> None:
        """Wraps Flower Pollination Algorithm over all agents and variables.

        Args:
            space: Space containing agents and update-related information.
            function: A Function object that will be used as the objective function.

        """

        # Iterates through all agents
        for agent in space.agents:
            # Creates a temporary agent
            a = copy.deepcopy(agent)

            # Generates an uniform random number
            r1 = r.generate_uniform_random_number()

            # Check if generated random number is bigger than probability
            if r1 > self.p:
                # Updates a temporary position according to global pollination
                a.position = self._global_pollination(
                    agent.position, space.best_agent.position)

            else:
                # Generates an uniform random number
                epsilon = r.generate_uniform_random_number()

                # Generates an index for flower `k` and flower `l`
                k = r.generate_integer_random_number(0, len(space.agents))
                l = r.generate_integer_random_number(0,
                                                     len(space.agents),
                                                     exclude_value=k)

                # Updates a temporary position according to local pollination
                a.position = self._local_pollination(
                    agent.position,
                    space.agents[k].position,
                    space.agents[l].position,
                    epsilon,
                )

            # Checks agent's limits
            a.clip_by_bound()

            # Calculates the fitness for the temporary position
            a.fit = function(a.position)

            # If new fitness is better than agent's fitness
            if a.fit < agent.fit:
                # Copies its position and fitness to the agent
                agent.position = copy.deepcopy(a.position)
                agent.fit = copy.deepcopy(a.fit)
Ejemplo n.º 11
0
    def _parasitism_phase(
        self,
        space: Space,
        n_crows: int,
        n_cuckoos: int,
        iteration: int,
        n_iterations: int,
    ):
        """Performs the parasitism phase using the current number of cuckoos.

        Args:
            space: Space containing agents and update-related information.
            n_crows: Number of crows.
            n_cuckoos: Number of cuckoos.
            iteration: Current iteration.
            n_iterations: Maximum number of iterations.

        """

        # Gathers the cuckoos
        cuckoos = space.agents[n_crows:n_crows + n_cuckoos]

        # Calculates a list of cuckoos' fitness
        fitness = [cuckoo.fit for cuckoo in cuckoos]

        # Calculates the probability of selection
        p = iteration / n_iterations

        # Iterates through all cuckoos
        for cuckoo in cuckoos:
            # Selects a cuckoo through tournament selection
            s = g.tournament_selection(fitness, 1)[0]

            # Selects two random agents from the space
            i = r.generate_integer_random_number(high=space.n_agents)
            j = r.generate_integer_random_number(high=space.n_agents,
                                                 exclude_value=i)

            # Creates a bernoulli distribution to preserve or not variables (eq. 12)
            k = d.generate_bernoulli_distribution(1 - p, cuckoo.n_variables)
            k = np.expand_dims(k, -1)

            # Calculates the gaussian-based step distribution (eq. 11)
            rand = r.generate_uniform_random_number()
            S_g = (space.agents[i].position - space.agents[j].position) * rand

            # Updates the cuckoo's position and clips its limits (eq. 10)
            cuckoo.position = space.agents[s].position + S_g * k
            cuckoo.clip_by_bound()
Ejemplo n.º 12
0
    def update(self, space, function):
        """Wraps Wind Driven Optimization over all agents and variables.

        Args:
            space (Space): Space containing agents and update-related information.
            function (Function): A function object.

        """

        # Iterates through all agents
        for i, agent in enumerate(space.agents):
            # Generates a random index based on the number of agents
            index = r.generate_integer_random_number(0, len(space.agents))

            # Updates velocity (eq. 15)
            self.velocity[i] = (1 - self.alpha) * self.velocity[i] - self.g * agent.position + \
                               (self.RT * np.abs(1 / (index + 1) - 1) * (space.best_agent.position - agent.position)) + \
                               (self.c * self.velocity[index] / (index + 1))

            # Clips the velocity values between [-v_max, v_max]
            self.velocity = np.clip(self.velocity, -self.v_max, self.v_max)

            # Updates agent's position (eq. 16)
            agent.position += self.velocity[i]

            # Checks agent limits
            agent.clip_by_bound()

            # Evaluates agent
            agent.fit = function(agent.position)
Ejemplo n.º 13
0
    def _update(self, agents, memory):
        """Method that wraps the Crow Search Algorithm over all agents and variables.

        Args:
            agents (list): List of agents.
            memory (np.array): Array of memories.

        """

        # Iterates through every agent
        for agent in agents:
            # Generates uniform random numbers
            r1 = r.generate_uniform_random_number()
            r2 = r.generate_uniform_random_number()

            # Generates a random integer (e.g. selects the crow)
            j = r.generate_integer_random_number(high=len(agents))

            # Checks if first random number is greater than awareness probability
            if r1 >= self.AP:
                # Updates agent's position (Eq. 2)
                agent.position += r2 * self.fl * (memory[j] - agent.position)

            # If random number is smaller than probability
            else:
                # Generate a random position
                for j, (lb, ub) in enumerate(zip(agent.lb, agent.ub)):
                    # For each decision variable, we generate uniform random numbers
                    agent.position[j] = r.generate_uniform_random_number(lb, ub, size=agent.n_dimensions)
Ejemplo n.º 14
0
    def _send_onlooker(self, agents: List[Agent], function: Function) -> None:
        """Sends onlooker bees to select new food sources (eq. 2.1).

        Args:
            agents: List of agents.
            function: A function object.

        """

        # Calculates the fitness somatory
        total = sum(agent.fit for agent in agents)

        # Defines food sources' counter
        k = 0

        # While counter is less than the amount of food sources
        while k < len(agents):
            # We iterate through every agent
            for i, agent in enumerate(agents):
                # Creates a random uniform number
                r1 = r.generate_uniform_random_number()

                # Calculates the food source's probability
                probs = (agent.fit / (total + c.EPSILON)) + 0.1

                # If the random number is smaller than food source's probability
                if r1 < probs:
                    # We need to increment the counter
                    k += 1

                    # Gathers a random source to be used
                    source = r.generate_integer_random_number(0, len(agents))

                    # Evaluate its location
                    self._evaluate_location(agent, agents[source], function, i)
Ejemplo n.º 15
0
    def _nesting_phase(self, space: Space, n_crows: int):
        """Performs the nesting phase using the current number of crows.

        Args:
            space: Space containing agents and update-related information.
            n_crows: Number of crows.

        """

        # Gathers the crows
        crows = space.agents[:n_crows]

        # Iterates through all crows
        for i, crow in enumerate(crows):
            # Generates a random index
            idx = r.generate_integer_random_number(high=space.n_agents,
                                                   exclude_value=i)

            # Calculates the step from Lévy distribution (eq. 7)
            step = d.generate_levy_distribution(size=crow.n_variables)
            step = np.expand_dims(step, axis=1)

            # Updates the crow's position and clips its bounds (eq. 6 and 8)
            crow.position = 0.01 * step * (space.agents[idx].position -
                                           crow.position)
            crow.clip_by_bound()
Ejemplo n.º 16
0
    def _update(self, agents, function):
        """Method that wraps the update pipeline over all agents and variables.

        Args:
            agents (list): List of agents.
            function (Function): A function object.

        """

        # Calculates a random index
        i = r.generate_integer_random_number(0, len(agents))

        # Generates a new harmony
        agent = self._generate_new_harmony(agents[i])

        # Checking agent limits
        agent.clip_limits()

        # Calculates the new harmony fitness
        agent.fit = function(agent.position)

        # Sorting agents
        agents.sort(key=lambda x: x.fit)

        # If newly generated agent fitness is better
        if agent.fit < agents[-1].fit:
            # Updates the corresponding agent's position
            agents[-1].position = copy.deepcopy(agent.position)

            # And its fitness as well
            agents[-1].fit = copy.deepcopy(agent.fit)
Ejemplo n.º 17
0
    def _parasitism(self, agent_i, agent_j, function):
        """Performs the parasitism operation.

        Args:
            agent_i (Agent): Selected `i` agent.
            agent_j (Agent): Selected `j` agent.
            function (Function): A Function object that will be used as the objective function.

        """

        # Creates a temporary parasite agent
        p = copy.deepcopy(agent_i)

        # Generates a integer random number
        r1 = r.generate_integer_random_number(0, agent_i.n_variables)

        # Updates its position on selected variable with a uniform random number
        p.position[r1] = r.generate_uniform_random_number(p.lb[r1], p.ub[r1])

        # Checks its limits
        p.clip_limits()

        # Evaluates its position
        p.fit = function(p.position)

        # If the new potision is better than agent's `j` position
        if p.fit < agent_j.fit:
            # Replaces the agent's `j` position
            agent_j.position = copy.deepcopy(p.position)

            # Also replaces its fitness
            agent_j.fit = copy.deepcopy(p.fit)
Ejemplo n.º 18
0
    def _crossover(self, agents, idx):
        """Performs the crossover between selected agent and a randomly agent (eq. 21).

        Args:
            agents (list): List of agents.
            idx (int): Selected agent.

        Returns:
            An agent after suffering a crossover operator.

        """

        # Makes a deepcopy of an agent
        a = copy.deepcopy(agents[idx])

        # Samples a random integer
        m = r.generate_integer_random_number(0, len(agents), exclude_value=idx)

        # Calculates the current crossover probability
        Cr = self.Cr * ((agents[idx].fit - agents[0].fit) /
                        (agents[-1].fit - agents[0].fit + c.EPSILON))

        # Iterates through all variables
        for j in range(a.n_variables):
            # Generating a uniform random number
            r1 = r.generate_uniform_random_number()

            # If sampled uniform number if smaller than crossover probability
            if r1 < Cr:
                # Gathers the position from the selected agent
                a.position[j] = copy.deepcopy(agents[m].position[j])

        return a
Ejemplo n.º 19
0
    def update(self, space, function, iteration, n_iterations):
        """Wraps Equilibrium Optimizer over all agents and variables.

        Args:
            space (Space): Space containing agents and update-related information.
            function (Function): A Function object that will be used as the objective function.
            iteration (int): Current iteration.
            n_iterations (int): Maximum number of iterations.

        """

        # Calculates the equilibrium and average concentrations
        self._calculate_equilibrium(space.agents)
        C_avg = self._average_concentration(function)

        # Makes a pool of both concentrations and their average (eq. 7)
        C_pool = self.C + [C_avg]

        # Calculates the time (eq. 9)
        t = (1 - iteration / n_iterations)**(self.a2 * iteration /
                                             n_iterations)

        # Iterates through all agents
        for agent in space.agents:
            # Generates a integer between [0, 5) to select the concentration
            i = rnd.generate_integer_random_number(0, 5)

            # Generates two uniform random vectors (eq. 11)
            r = rnd.generate_uniform_random_number(size=(agent.n_variables,
                                                         agent.n_dimensions))
            lambd = rnd.generate_uniform_random_number(
                size=(agent.n_variables, agent.n_dimensions))

            # Calculates the exponential term (eq. 11)
            F = self.a1 * np.sign(r - 0.5) * (np.exp(-lambd * t) - 1)

            # Generates two uniform random numbers
            r1 = rnd.generate_uniform_random_number()
            r2 = rnd.generate_uniform_random_number()

            # If `r2` is bigger than generation probability (eq. 15)
            if r2 >= self.GP:
                # Defines generation control parameter as 0.5 * r1
                GCP = 0.5 * r1

            # If `r2` is smaller than generation probability
            else:
                # Defines generation control parameter as zero
                GCP = 0

            # Calculates the initial generation value (eq. 14)
            G_0 = GCP * (C_pool[i].position - lambd * agent.position)

            # Calculates the generation value (eq. 13)
            G = G_0 * F

            # Updates agent's position (eq. 16)
            agent.position = C_pool[i].position + (
                agent.position -
                C_pool[i].position) * F + (G / (lambd * self.V)) * (1 - F)
Ejemplo n.º 20
0
    def _update(self, agents, best_agent, function, height, length):
        """Method that wraps Water Wave Optimization over all agents and variables.

        Args:
            agents (list): List of agents.
            best_agent (Agent): Global best agent.
            function (Function): A function object.
            height (np.array): Array of wave heights.
            length (np.array): Array of wave lengths.

        """

        # Iterates through all agents
        for i, agent in enumerate(agents):
            # Propagates a wave into a new temporary one (eq. 6)
            wave = self._propagate_wave(agent, function, length[i])

            # Checks if propagated wave is better than current one
            if wave.fit < agent.fit:
                # Also checks if propagated wave is better than global one
                if wave.fit < best_agent.fit:
                    # Replaces the best agent with propagated wave
                    best_agent.position = copy.deepcopy(wave.position)
                    best_agent.fit = copy.deepcopy(wave.fit)

                    # Generates a `k` number of breaks
                    k = r.generate_integer_random_number(1, self.k_max + 1)

                    # Iterates through every possible break
                    for j in range(k):
                        # Breaks the propagated wave (eq. 10)
                        broken_wave = self._break_wave(wave, function, j)

                        # Checks if broken wave is better than global one
                        if broken_wave.fit < best_agent.fit:
                            # Replaces the best agent with broken wave
                            best_agent.position = copy.deepcopy(
                                broken_wave.position)
                            best_agent.fit = copy.deepcopy(broken_wave.fit)

                # Replaces current agent's with propagated wave
                agent.position = copy.deepcopy(wave.position)
                agent.fit = copy.deepcopy(wave.fit)

                # Sets its height to maximum height
                height[i] = self.h_max

            # If propagated wave is not better than current agent
            else:
                # Decreases its height by one
                height[i] -= 1

                # If its height reaches zero
                if height[i] == 0:
                    # Refracts the wave and generates a new height and wave length (eq. 8-9)
                    height[i], length[i] = self._refract_wave(
                        agent, best_agent, function, length[i])

        # Updates the wave length for all agents (eq. 7)
        self._update_wave_length(agents, length)
Ejemplo n.º 21
0
    def _mutate_agent(self, agent, alpha, beta, gamma):
        """Mutates a new agent based on pre-picked distinct agents (eq. 4).

        Args:
            agent (Agent): Current agent.
            alpha (Agent): 1st picked agent.
            beta (Agent): 2nd picked agent.
            gamma (Agent): 3rd picked agent.

        Returns:
            A mutated agent.

        """

        # Makes a deep copy of agent
        a = copy.deepcopy(agent)

        # Generates a random index for further comparison
        R = r.generate_integer_random_number(0, agent.n_variables)

        # For every decision variable
        for j in range(a.n_variables):
            # Generates a uniform random number
            r1 = r.generate_uniform_random_number()

            # If random number is smaller than crossover or `j` equals to the sampled index
            if r1 < self.CR or j == R:
                # Updates the mutated agent position
                a.position[j] = alpha.position[j] + self.F * (beta.position[j] - gamma.position[j])

        return a
Ejemplo n.º 22
0
    def _update(self, agents, best_agent, function, velocity):
        """Method that wraps velocity and position updates over all agents and variables.

        Args:
            agents (list): List of agents.
            best_agent (Agent): Global best agent.
            function (Function): A function object.
            velocity (np.array): Array of current velocities.

        """

        # Iterate through all agents
        for i, agent in enumerate(agents):
            # Generates a random index based on the number of agents
            index = r.generate_integer_random_number(0, len(agents))

            # Updating velocity
            velocity[i] = self._update_velocity(agent.position,
                                                best_agent.position,
                                                velocity[i], velocity[index],
                                                i + 1)

            # Clips the velocity values between (-v_max, v_max)
            velocity = np.clip(velocity, -self.v_max, self.v_max)

            # Updating agent's position
            agent.position = self._update_position(agent.position, velocity[i])

            # Checks agent limits
            agent.clip_limits()

            # Evaluates agent
            agent.fit = function(agent.position)
Ejemplo n.º 23
0
    def update(self, space: Space) -> None:
        """Wraps Crow Search Algorithm over all agents and variables.

        Args:
            space: Space containing agents and update-related information.

        """

        # Iterates through every agent
        for agent in space.agents:
            # Generates uniform random numbers
            r1 = r.generate_uniform_random_number()
            r2 = r.generate_uniform_random_number()

            # Generates a random integer (e.g. selects the crow)
            j = r.generate_integer_random_number(high=len(space.agents))

            # Checks if first random number is greater than awareness probability
            if r1 >= self.AP:
                # Updates agent's position (eq. 2)
                agent.position += r2 * self.fl * (self.memory[j] -
                                                  agent.position)

            # If random number is smaller than probability
            else:
                # Fills agent with new random positions
                agent.fill_with_uniform()
Ejemplo n.º 24
0
    def update(self, space: Space, function: Function) -> None:
        """Wraps EElectro-Search Algorithm over all agents and variables.

        Args:
            space: Space containing agents and update-related information.
            function: A Function object that will be used as the objective function.

        """

        # Iterates through all agents
        for i, agent in enumerate(space.agents):
            # Makes a deep copy of current agent
            a = copy.deepcopy(agent)

            # Creates a list of electrons
            electrons = [copy.deepcopy(agent) for _ in range(self.n_electrons)]

            # Iterates through all electrons
            for electron in electrons:
                # Generates a random number and the energy level
                r1 = r.generate_uniform_random_number()
                n = r.generate_integer_random_number(2, 6)

                # Updates the electron's position (eq. 3)
                electron.position += (2 * r1 - 1) * (1 - 1 / n**2) / self.D[i]

                # Clips its bounds
                electron.clip_by_bound()

                # Re-evaluates the new position
                electron.fit = function(electron.position)

            # Sorts the electrons
            electrons.sort(key=lambda x: x.fit)

            # Generates both Rydberg constant and acceleration coefficient
            # Original implementation is missing up an informative description
            Re = r.generate_uniform_random_number()
            Ac = r.generate_uniform_random_number()

            # Updates the Orbital radius (eq. 4)
            self.D[i] = (
                electrons[0].position - space.best_agent.position
            ) + Re * (1 / space.best_agent.position**2 - 1 / a.position**2)

            # Updates the temporary agent's position (eq. 5)
            a.position += Ac * self.D[i]

            # Checks agent's limits
            a.clip_by_bound()

            # Calculates the fitness for the temporary position
            a.fit = function(a.position)

            # If new fitness is better than agent's fitness
            if a.fit < agent.fit:
                # Copies its position and fitness to the agent
                agent.position = copy.deepcopy(a.position)
                agent.fit = copy.deepcopy(a.fit)
Ejemplo n.º 25
0
    def _generate_new_harmony(self, agents: List[Agent]) -> Agent:
        """It generates a new harmony.

        Args:
            agents: List of agents.

        Returns:
            (Agent): A new agent (harmony) based on music generation process.

        """

        # Mimics an agent position
        a = copy.deepcopy(agents[0])

        # For every decision variable
        for j, (lb, ub) in enumerate(zip(a.lb, a.ub)):
            # Generates an uniform random number
            r1 = r.generate_uniform_random_number()

            # Using the harmony memory
            if r1 <= self.HMCR:
                # Generates a random index
                k = r.generate_integer_random_number(0, len(agents))

                # Replaces the position with agent `k`
                a.position[j] = agents[k].position[j]

                # Generates a new uniform random number
                r2 = r.generate_uniform_random_number()

                # Checks if it needs a pitch adjusting
                if r2 <= self.PAR:
                    # Generates a random index
                    z = r.generate_integer_random_number(0, a.n_variables)

                    # Updates harmony position
                    a.position[j] = agents[0].position[z]

            # If harmony memory is not used
            else:
                # Generate a uniform random number
                a.position[j] = r.generate_uniform_random_number(
                    lb, ub, size=a.n_dimensions
                )

        return a
Ejemplo n.º 26
0
    def update(self, space: Space, function: Function) -> None:
        """Wraps Water Wave Optimization over all agents and variables.

        Args:
            space: Space containing agents and update-related information.
            function: A function object.

        """

        # Iterates through all agents
        for i, agent in enumerate(space.agents):
            # Propagates a wave into a new temporary one (eq. 6)
            wave = self._propagate_wave(agent, function, i)

            # Checks if propagated wave is better than current one
            if wave.fit < agent.fit:
                # Also checks if propagated wave is better than global one
                if wave.fit < space.best_agent.fit:
                    # Replaces the best agent with propagated wave
                    space.best_agent.position = copy.deepcopy(wave.position)
                    space.best_agent.fit = copy.deepcopy(wave.fit)

                    # Generates a `k` number of breaks
                    k = r.generate_integer_random_number(1, self.k_max + 1)

                    # Iterates through every possible break
                    for j in range(k):
                        # Breaks the propagated wave (eq. 10)
                        broken_wave = self._break_wave(wave, function, j)

                        # Checks if broken wave is better than global one
                        if broken_wave.fit < space.best_agent.fit:
                            # Replaces the best agent with broken wave
                            space.best_agent.position = copy.deepcopy(
                                broken_wave.position)
                            space.best_agent.fit = copy.deepcopy(
                                broken_wave.fit)

                # Replaces current agent's with propagated wave
                agent.position = copy.deepcopy(wave.position)
                agent.fit = copy.deepcopy(wave.fit)

                # Sets its height to maximum height
                self.height[i] = self.h_max

            # If propagated wave is not better than current agent
            else:
                # Decreases its height by one
                self.height[i] -= 1

                # If its height reaches zero
                if self.height[i] == 0:
                    # Refracts the wave and generates a new height and wave length (eq. 8-9)
                    self.height[i], self.length[i] = self._refract_wave(
                        agent, space.best_agent, function, i)

        # Updates the wave length for all agents (eq. 7)
        self._update_wave_length(space.agents)
Ejemplo n.º 27
0
    def update(self, space: Space, function: Function) -> None:
        """Wraps Evolutionary Programming over all agents and variables.

        Args:
            space: Space containing agents and update-related information.
            function: A Function object that will be used as the objective function.

        """

        # Calculates the number of agents
        n_agents = len(space.agents)

        # Creates a list for the produced children
        children = []

        # Iterates through all agents
        for i, agent in enumerate(space.agents):
            # Mutates a parent and generates a new child
            a = self._mutate_parent(agent, i, function)

            # Updates the strategy
            self._update_strategy(i, agent.lb, agent.ub)

            # Appends the mutated agent to the children
            children.append(a)

        # Joins both populations
        space.agents += children

        # Number of individuals to be selected
        n_individuals = int(n_agents * self.bout_size)

        # Creates an empty array of wins
        wins = np.zeros(len(space.agents))

        # Iterates through all agents in the new population
        for i, agent in enumerate(space.agents):
            # Iterate through all tournament individuals
            for _ in range(n_individuals):
                # Gathers a random index
                index = r.generate_integer_random_number(0, len(space.agents))

                # If current agent's fitness is smaller than selected one
                if agent.fit < space.agents[index].fit:
                    # Increases its winning by one
                    wins[i] += 1

        # Sorts agents list based on its winnings
        space.agents = [
            agents
            for _, agents in sorted(
                zip(wins, space.agents), key=lambda pair: pair[0], reverse=True
            )
        ]

        # Gathers the best `n_agents`
        space.agents = space.agents[:n_agents]
Ejemplo n.º 28
0
def kmeans(
    x: np.ndarray,
    n_clusters: Optional[int] = 1,
    max_iterations: Optional[int] = 100,
    tol: Optional[float] = 1e-4,
) -> np.ndarray:
    """Performs the K-Means clustering over the input data.

    Args:
        x: Input array with a shape equal to (n_samples, n_variables, n_dimensions).
        n_clusters: Number of clusters.
        max_iterations: Maximum number of clustering iterations.
        tol: Tolerance value to stop the clustering.

    Returns:
        (np.ndarray): An array holding the assigned cluster per input sample.

    """

    # Gathers the corresponding dimensions
    n_samples, n_variables, n_dimensions = x.shape[0], x.shape[1], x.shape[2]

    # Creates an array of centroids and labels
    centroids = np.zeros((n_clusters, n_variables, n_dimensions))
    labels = np.zeros(n_samples)

    for i in range(n_clusters):
        # Chooses a random sample to compose the centroid
        idx = r.generate_integer_random_number(0, n_samples)
        centroids[i] = x[idx]

    for _ in range(max_iterations):
        # Calculates the euclidean distance between samples and each centroid
        dists = np.squeeze(np.array([np.linalg.norm(x - c, axis=1) for c in centroids]))

        # Gathers the minimum distance as the cluster that conquers the sample
        updated_labels = np.squeeze(np.array(np.argmin(dists, axis=0)))

        # Calculates the difference ratio between old and new labels
        ratio = np.sum(labels != updated_labels) / n_samples

        if ratio <= tol:
            break

        # Updates the old labels with the new ones
        labels = updated_labels

        for i in range(n_clusters):
            # Gathers the samples that belongs to current centroid
            centroid_samples = x[labels == i]

            # If there are samples that belongs to the centroid
            if centroid_samples.shape[0] > 0:
                # Updates the centroid position
                centroids[i] = np.mean(centroid_samples, axis=0)

    return labels
Ejemplo n.º 29
0
    def _update(self, agents, n_agents, function, strategy):
        """Method that wraps evolution over all agents and variables.

        Args:
            agents (list): List of agents.
            n_agents (int): Number of possible agents in the space.
            function (Function): A Function object that will be used as the objective function.
            strategy (np.array): An array of strategies.

        Returns:
            A new population with more fitted individuals.

        """

        # Creating a list for the produced children
        children = []

        # Iterate through all agents
        for i, agent in enumerate(agents):
            # Mutates a parent and generates a new child
            a = self._mutate_parent(agent, function, strategy[i])

            # Updates the strategy
            strategy[i] = self._update_strategy(strategy[i], agent.lb,
                                                agent.ub)

            # Appends the mutated agent to the children
            children.append(a)

        # Joins both populations
        agents += children

        # Number of individuals to be selected
        n_individuals = int(n_agents * self.bout_size)

        # Creates an empty array of wins
        wins = np.zeros(len(agents))

        # Iterate through all agents in the new population
        for i, agent in enumerate(agents):
            # Iterate through all tournament individuals
            for _ in range(n_individuals):
                # Gathers a random index
                index = r.generate_integer_random_number(0, len(agents))

                # If current agent's fitness is smaller than selected one
                if agent.fit < agents[index].fit:
                    # Increases its winning by one
                    wins[i] += 1

        # Sorts the agents list based on its winnings
        agents = [
            agents for _, agents in sorted(
                zip(wins, agents), key=lambda pair: pair[0], reverse=True)
        ]

        return agents[:n_agents]
Ejemplo n.º 30
0
    def _update(self, agents, best_agent, fragrance):
        """Method that wraps global and local pollination updates over all agents and variables.

        Args:
            agents (list): List of agents.
            best_agent (Agent): Global best agent.
            fragrance (np.array): Array of fragrances.

        """

        # Iterates through all agents
        for i, agent in enumerate(agents):
            # Calculates fragrance for current agent (eq. 1)
            fragrance[i] = self.c * agent.fit**self.a

        # Iterates through all agents
        for i, agent in enumerate(agents):
            # Generates a uniform random number
            r1 = r.generate_uniform_random_number()

            # If random number is smaller than switch probability
            if r1 < self.p:
                # Moves current agent towards the best one (eq. 2)
                agent.position = self._best_movement(agent.position,
                                                     best_agent.position,
                                                     fragrance[i], r1)

            # If random number is bigger than switch probability
            else:
                # Generates a `j` index
                j = r.generate_integer_random_number(0, len(agents))

                #  Generates a `k` index
                k = r.generate_integer_random_number(0,
                                                     len(agents),
                                                     exclude_value=j)

                # Moves current agent using a local movement (eq. 3)
                agent.position = self._local_movement(agent.position,
                                                      agents[j].position,
                                                      agents[k].position,
                                                      fragrance[i], r1)