Esempio n. 1
0
    def _best_beta(self, agent: Agent, worst: Agent,
                   best: Agent) -> np.ndarray:
        """Calculates the best attraction (eq. 15).

        Args:
            agent: Selected agent.
            worst: Worst agent.
            best: Best agent.

        Returns:
            (np.ndarray): The best attraction.

        """

        # Calculates the fitness
        fitness = (agent.fit - best.fit) / (worst.fit - best.fit + c.EPSILON)

        # Calculates the positioning
        position = (best.position - agent.position) / (
            g.euclidean_distance(best.position, agent.position) + c.EPSILON)

        # Calculates the food attraction
        beta = fitness * position

        return beta
Esempio n. 2
0
    def _food_beta(self, agent, worst, best, food, C_food):
        """Calculates the food attraction (eq. 13).

        Args:
            agent (Agent): Selected agent.
            worst (Agent): Worst agent.
            best (Agent): Best agent.
            food (Agent): Food location.
            C_food (float): Food coefficient.

        Returns:
            The food attraction.

        """

        # Calculates the fitness
        fitness = (agent.fit - food.fit) / (worst.fit - best.fit + c.EPSILON)

        # Calculates the positioning
        position = (food.position - agent.position) / (
            g.euclidean_distance(food.position, agent.position) + c.EPSILON)

        # Calculates the food attraction
        beta = C_food * fitness * position

        return beta
Esempio n. 3
0
    def _target_alpha(self, agent, worst, best, C_best):
        """Calculates the target alpha (eq. 8).

        Args:
            agent (Agent): Selected agent.
            worst (Agent): Worst agent.
            best (Agent): Best agent.
            C_best (float): Effectiveness coefficient.

        Returns:
            The target alpha.

        """

        # Calculates a list of neighbours' fitness
        fitness = (agent.fit - best.fit) / (worst.fit - best.fit + c.EPSILON)

        # Calculates a list of krills' position based on neighbours
        position = (best.position - agent.position) / (
            g.euclidean_distance(best.position, agent.position) + c.EPSILON)

        # Calculates the target alpha
        alpha = C_best * fitness * position

        return alpha
Esempio n. 4
0
    def _rellocation(self, agent: Agent, best_agent: Agent,
                     function: Function) -> None:
        """Performs the fox rellocation procedure.

        Args:
            agent: Current agent.
            best_agent: Best agent.
            function: A Function object that will be used as the objective function.

        """

        # Creates a temporary agent
        temp = copy.deepcopy(agent)

        # Calculates the square root of euclidean distance between agent and best agent (eq. 1)
        distance = np.sqrt(
            g.euclidean_distance(temp.position, best_agent.position))

        # Randomly selects the scaling hyperparameter
        alpha = r.generate_uniform_random_number(0, distance)

        # Calculates individual reallocation (eq. 2)
        temp.position += alpha * np.sign(best_agent.position - temp.position)

        # Checks agent's limits
        temp.clip_by_bound()

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

        # If new fitness is better than agent's fitness
        if temp.fit < agent.fit:
            # Copies its position and fitness to the agent
            agent.position = copy.deepcopy(temp.position)
            agent.fit = copy.deepcopy(temp.fit)
Esempio n. 5
0
    def _local_alpha(self, agent, worst, best, neighbours):
        """Calculates the local alpha (eq. 4).

        Args:
            agent (Agent): Selected agent.
            worst (Agent): Worst agent.
            best (Agent): Best agent.
            neighbours (list): List of neighbours.

        Returns:
            The local alpha.

        """

        # Calculates a list of neighbours' fitness
        fitness = [
            (agent.fit - neighbour.fit) / (worst.fit - best.fit + c.EPSILON)
            for neighbour in neighbours
        ]

        # Calculates a list of krills' position based on neighbours
        position = [(neighbour.position - agent.position) /
                    (g.euclidean_distance(neighbour.position, agent.position) +
                     c.EPSILON) for neighbour in neighbours]

        # Calculates the local alpha
        alpha = np.sum([fit * pos for (fit, pos) in zip(fitness, position)],
                       axis=0)

        return alpha
Esempio n. 6
0
    def _update(self, agents, n_iterations):
        """Method that wraps Firefly Algorithm over all agents and variables (eq. 3-9).

        Args:
            agents (list): List of agents.
            n_iterations (int): Maximum number of iterations.

        """

        # Calculating current iteration delta
        delta = 1 - ((10e-4) / 0.9) ** (1 / n_iterations)

        # Applying update to alpha parameter
        self.alpha *= (1 - delta)

        # We copy a temporary list for iterating purposes
        temp_agents = copy.deepcopy(agents)

        # Iterating through 'i' agents
        for agent in agents:
            # Iterating through 'j' agents
            for temp in temp_agents:
                # Distance is calculated by an euclidean distance between 'i' and 'j' (eq. 8)
                distance = g.euclidean_distance(agent.position, temp.position)

                # If 'i' fit is bigger than 'j' fit
                if agent.fit > temp.fit:
                    # Recalculate the attractiveness (eq. 6)
                    beta = self.beta * np.exp(-self.gamma * distance)

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

                    # Updates agent's position (eq. 9)
                    agent.position = beta * (temp.position + agent.position) + self.alpha * (r1 - 0.5)
Esempio n. 7
0
    def _calculate_force(self, agents, mass, gravity):
        """Calculates agents' force (eq. 7-9).

        Args:
            agents (list): List of agents.
            mass (np.array): An array of agents' mass.
            gravity (float): Current gravity value.

        Returns:
            The attraction force between all agents.

        """

        # Calculates the force
        force = [[
            gravity * (mass[i] * mass[j]) /
            (g.euclidean_distance(agents[i].position, agents[j].position) +
             c.EPSILON) * (agents[j].position - agents[i].position)
            for j in range(len(agents))
        ] for i in range(len(agents))]

        # Transforms the force into an array
        force = np.asarray(force)

        # Applying a stochastic trait to the force
        force = np.sum(r.generate_uniform_random_number() * force, axis=1)

        return force
Esempio n. 8
0
    def update(self, space: Space, iteration: int, n_iterations: int) -> None:
        """Wraps Owl Search Algorithm over all agents and variables.

        Args:
            space: Space containing agents and update-related information.
            iteration: Current iteration.
            n_iterations: Maximum number of iterations.

        """

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

        # Gathers best and worst agents (eq. 5 and 6)
        best = copy.deepcopy(space.agents[0])
        worst = copy.deepcopy(space.agents[-1])

        # Linearly decreases the `beta` coefficient
        beta = self.beta - ((iteration + 1) / n_iterations) * self.beta

        # Iterates through all agents
        for agent in space.agents:
            # Calculates the normalized intensity (eq. 4)
            intensity = (agent.fit - best.fit) / (worst.fit - best.fit + c.EPSILON)

            # Calculates the distance between owl and prey (eq. 7)
            distance = g.euclidean_distance(agent.position, best.position)

            # Obtains the change in intensity (eq. 8)
            noise = r.generate_uniform_random_number()
            intensity_change = intensity / (distance**2 + c.EPSILON) + noise

            # print(agent.fit, worst.fit, best.fit, intensity, intensity_change)

            # Generates the probability of vole movement and random `alpha`
            p_vm = r.generate_uniform_random_number()
            alpha = r.generate_uniform_random_number(high=0.5)

            # If probability of vole movement is smaller than 0.5
            if p_vm < 0.5:
                # Updates current's owl position (eq. 9 - top)
                agent.position += (
                    beta
                    * intensity_change
                    * np.fabs(alpha * best.position - agent.position)
                )

            # If probability is bigger or equal to 0.5
            else:
                # Updates current's owl position (eq. 9 - bottom)
                agent.position -= (
                    beta
                    * intensity_change
                    * np.fabs(alpha * best.position - agent.position)
                )
Esempio n. 9
0
    def update(self, space):
        """Wraps Magnetic Optimization Algorithm over all agents and variables.

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

        """

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

        # Gathers the best and worst agents and calculates a list of normalized fitness (eq. 2)
        best, worst = space.agents[0], space.agents[-1]
        fitness = [(agent.fit - best.fit) / (worst.fit - best.fit + c.EPSILON)
                   for agent in space.agents]

        # Calculates the masses (eq. 3)
        mass = [self.alpha + self.rho * fit for fit in fitness]

        # Iterates through all agents
        for i, agent in enumerate(space.agents):
            # Gathers the agents neighbours (eq. 4)
            root = np.sqrt(space.n_agents)
            north = int((i - root) % space.n_agents)
            south = int((i + root) % space.n_agents)
            west = int((i - 1) + ((i + root - 1) % root) // (root - 1) * root)
            east = int((i + 1) - (i % root) // (root - 1) * root)
            neighbours = [north, south, west, east]

            # Initializes the force as a zero value
            force = 0

            # Iterates through all neighbours
            for n in neighbours:
                # Calculates the distance between current agent and neighbour (eq. 7)
                distance = g.euclidean_distance(agent.position,
                                                space.agents[n].position)

                # Calculates the force between agents (eq. 5)
                force += (space.agents[n].position -
                          agent.position) * fitness[n] / (distance + c.EPSILON)

            # Calculates the force's mean
            # This increases the performance of algorithm by eliminating addition biases
            force = np.mean(force)

            # Updates the agent's velocity(eq. 9)
            r1 = r.generate_uniform_random_number()
            velocity = force / mass[i] * r1

            # Updates the agent's position (eq. 10)
            agent.position += velocity

            # Clips the agent's limits
            agent.clip_by_bound()
Esempio n. 10
0
    def update(self, space: Space, function: Function, iteration: int,
               n_iterations: int) -> None:
        """Wraps Grasshopper 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.
            iteration: Current iteration.
            n_iterations: Maximum number of iterations.

        """

        # Calculates the comfort coefficient (eq. 2.8)
        comfort = self.c_max - iteration * (
            (self.c_max - self.c_min) / n_iterations)

        # Copies a temporary list for iterating purposes
        temp_agents = copy.deepcopy(space.agents)

        # Iterates through 'i' agents
        for agent in space.agents:
            # Initializes the total comfort as zero
            total_comfort = np.zeros((agent.n_variables, agent.n_dimensions))

            # Iterates through 'j' agents
            for temp in temp_agents:
                # Distance is calculated by an euclidean distance between 'i' and 'j'
                distance = g.euclidean_distance(agent.position, temp.position)

                # Calculates the unitary vector
                unit = (temp.position - agent.position) / (distance +
                                                           c.EPSILON)

                # Calculates the social force between agents
                s = self._social_force(2 + np.fmod(distance, 2))

                # Expands the upper and lower bounds
                ub = np.expand_dims(agent.ub, -1)
                lb = np.expand_dims(agent.lb, -1)

                # Sums the current comfort to the total one
                total_comfort += comfort * ((ub - lb) / 2) * s * unit

            # Updates the agent's position (eq. 2.7)
            agent.position = comfort * total_comfort + space.best_agent.position

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

            # Evaluates the new agent's position
            agent.fit = function(agent.position)
Esempio n. 11
0
    def _update(self, agents, best_agent, function, iteration, n_iterations):
        """Method that wraps the Grasshopper Optimization Algorithm over all agents and variables.

        Args:
            agents (list): List of agents.
            best_agent (Agent): Global best agent.
            function (Function): A function object.
            iteration (int): Current iteration.
            n_iterations (int): Maximum number of iterations.

        """

        # Calculates the comfort coefficient (Eq. 2.8)
        comfort = self.c_max - iteration * (
            (self.c_max - self.c_min) / n_iterations)

        # We copy a temporary list for iterating purposes
        temp_agents = copy.deepcopy(agents)

        # Iterating through 'i' agents
        for agent in agents:
            # Initializes the total comfort as zero
            total_comfort = np.zeros((agent.n_variables, agent.n_dimensions))

            # Iterating through 'j' agents
            for temp in temp_agents:
                # Distance is calculated by an euclidean distance between 'i' and 'j'
                distance = g.euclidean_distance(agent.position, temp.position)

                # Calculates the unitary vector
                unit = (temp.position - agent.position) / (distance +
                                                           c.EPSILON)

                # Calculates the social force between agents
                s = self._social_force(2 + np.fmod(distance, 2))

                # Expands the upper and lower bounds
                ub = np.expand_dims(agent.ub, -1)
                lb = np.expand_dims(agent.lb, -1)

                # Sums the current comfort to the total one
                total_comfort += comfort * ((ub - lb) / 2) * s * unit

            # Updates the agent's position (Eq. 2.7)
            agent.position = comfort * total_comfort + best_agent.position

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

            # Evaluates the new agent's position
            agent.fit = function(agent.position)
Esempio n. 12
0
    def _roaming(self, prides: List[Lion], function: Function) -> None:
        """Performs the roaming procedure (s. 2.2.4).

        Args:
            prides: List of prides holding their corresponding lions.
            function: A Function object that will be used as the objective function.

        """

        # Iterates through all prides
        for pride in prides:
            # Calculates the number of roaming lions
            n_roaming = int(len(pride) * self.P)

            # Selects `n_roaming` lions
            selected = r.generate_integer_random_number(high=len(pride),
                                                        size=n_roaming)

            # Iterates through all agents in pride
            for agent in pride:
                # If agent is male
                if not agent.female:
                    # Iterates through selected roaming lions
                    for s in selected:
                        # Calculates the direction angle
                        theta = r.generate_uniform_random_number(
                            -np.pi / 6, np.pi / 6)

                        # Calculates the distance between selected lion and current one
                        distance = g.euclidean_distance(
                            pride[s].best_position, agent.position)

                        # Generates the step (eq. 10)
                        step = r.generate_uniform_random_number(
                            0, 2 * distance)

                        # Updates the agent's position
                        agent.position += step * np.tan(theta)

                        # Clip the agent's limits
                        agent.clip_by_bound()

                        # Defines the previous fitness and calculates the newer one
                        agent.p_fit = copy.deepcopy(agent.fit)
                        agent.fit = function(agent.position)

                        # If new fitness is better than old one
                        if agent.fit < agent.p_fit:
                            # Updates its best position
                            agent.best_position = copy.deepcopy(agent.position)
Esempio n. 13
0
    def update(self, space: Space, function: Function) -> None:
        """Wraps Red Fox Optimization 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.

        """

        # Defines the scaling parameter
        alpha = r.generate_uniform_random_number(0, 0.2)

        # Iterates through all agents
        for agent in space.agents:
            # Performs the fox rellocation procedure
            self._rellocation(agent, space.best_agent, function)

            # Performs the fox noticing procedure
            self._noticing(agent, function, alpha)

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

        # Calculates the habitat's center and diameter (eq. 6 and 7)
        habitat_center = (space.agents[0].position +
                          space.agents[1].position) / 2
        habitat_diameter = np.sqrt(
            g.euclidean_distance(space.agents[0].position,
                                 space.agents[1].position))

        # Samples a random number
        k = r.generate_uniform_random_number()

        # Iterates through all foxes that will be replaced
        for agent in space.agents[-self.n_replacement:]:
            # If sampled number is bigger than 0.45 (eq. 8 - top)
            if k >= 0.45:
                # Samples new position
                agent.fill_with_uniform()
                agent.position += habitat_center + habitat_diameter / 2

            # If sampled number is smaller than 0.45 (eq. 8 - bottom)
            else:
                # Reproduces parents into a new position (eq. 9)
                agent.position = (
                    k * (space.agents[0].position + space.agents[1].position) /
                    2)

            # Checks agent's limits
            agent.clip_by_bound()
Esempio n. 14
0
    def _moving_safe_place(self, prides: List[Lion]) -> None:
        """Move prides to safe locations (s. 2.2.3).

        Args:
            prides: List of prides holding their corresponding lions.

        """

        # Iterates through all prides
        for pride in prides:
            # Calculates the number of improved lions (eq. 7)
            n_improved = np.sum(
                [1 for agent in pride if agent.fit < agent.p_fit])

            # Calculates the fitness of lions (eq. 8)
            fitnesses = [agent.fit for agent in pride]

            # Calculates the size of tournament (eq. 9)
            tournament_size = np.maximum(2, int(np.ceil(n_improved / 2)))

            # Iterates through all agents in pride
            for agent in pride:
                # If agent is female and belongs to group 0
                if agent.group == 0 and agent.female:
                    # Gathers the winning lion from tournament selection
                    w = g.tournament_selection(fitnesses, 1,
                                               tournament_size)[0]

                    # Calculates the distance between agent and winner
                    distance = g.euclidean_distance(agent.position,
                                                    pride[w].position)

                    # Generates random numbers
                    rand = r.generate_uniform_random_number()
                    u = r.generate_uniform_random_number(-1, 1)
                    theta = r.generate_uniform_random_number(
                        -np.pi / 6, np.pi / 6)

                    # Calculates both `R1` and `R2` vectors
                    R1 = pride[w].position - agent.position
                    R2 = np.random.randn(*R1.T.shape)
                    R2 = R2.T - R2.dot(R1) * R1 / (np.linalg.norm(R1)**2 +
                                                   c.EPSILON)

                    # Updates agent's position (eq. 6)
                    agent.position += (2 * distance * rand * R1 +
                                       u * np.tan(theta) * distance * R2)
Esempio n. 15
0
    def _sensing_distance(self, agents, idx):
        """Calculates the sensing distance for an individual krill (eq. 7).

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

        Returns:
            The sensing distance for an individual krill.

        """

        # Calculates the euclidean distances between selected krill and other krills
        eucl_distance = [g.euclidean_distance(agents[idx].position, agent.position) for agent in agents]

        # Calculates the sensing distance
        distance = np.sum(eucl_distance) / (self.NN * len(agents))

        return distance, eucl_distance
Esempio n. 16
0
    def update(self, space: Space, n_iterations: int) -> None:
        """Wraps Firefly Algorithm over all agents and variables (eq. 3-9).

        Args:
            space: Space containing agents and update-related information.
            n_iterations: Maximum number of iterations.

        """

        # Calculates current iteration delta
        delta = 1 - ((10e-4) / 0.9)**(1 / n_iterations)

        # Applies update to alpha parameter
        self.alpha *= 1 - delta

        # We copy a temporary list for iterating purposes
        temp_agents = copy.deepcopy(space.agents)

        # Iterates through 'i' agents
        for agent in space.agents:
            # Iterates through 'j' agents
            for temp in temp_agents:
                # Distance is calculated by an euclidean distance between 'i' and 'j' (eq. 8)
                distance = g.euclidean_distance(agent.position, temp.position)

                # If 'i' fit is bigger than 'j' fit
                if agent.fit > temp.fit:
                    # Recalculate the attractiveness (eq. 6)
                    beta = self.beta * np.exp(-self.gamma * distance)

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

                    # Updates agent's position (eq. 9)
                    agent.position = beta * (temp.position + agent.position
                                             ) + self.alpha * (r1 - 0.5)
Esempio n. 17
0
def test_euclidean_distance():
    x = np.array([1, 2, 3, 4])

    y = np.array([1, 2, 3, 4])

    assert general.euclidean_distance(x, y) == 0