class_docstr: An HHO class, inherited from Optimizer.
  
  This is the designed class to define HHO-related
  variables and methods.
  
  References:
      A. Heidari et al. Harris hawks optimization: Algorithm and applications.
      Future Generation Computer Systems (2019).
docstr: Performs the exploitation phase.
  
  Args:
      energy: Energy coefficient.
      jump: Jump's strength.
      agents: List of agents.
      current_agent: Current agent to be updated (or not).
      best_agent: Best population's agent.
      function: A function object.
  
  Returns:
      (np.ndarray): A location vector containing the updated position.
docstr_tok: ["Performs","the","exploitation","phase",".","Args",":","energy",":","Energy","coefficient",".","jump",":","Jump","'s","strength",".","agents",":","List","of","agents",".","current_agent",":","Current","agent","to","be","updated","(","or","not",")",".","best_agent",":","Best","population","'s","agent",".","function",":","A","function","object",".","Returns",":","(","np.ndarray",")",":","A","location","vector","containing","the","updated","position","."]
code: def _exploitation_phase(
      self,
      energy: float,
      jump: float,
      agents: List[Agent],
      current_agent: Agent,
      best_agent: Agent,
      function: Function,
  ) -> np.ndarray:
      """Performs the exploitation phase.
  
      Args:
          energy: Energy coefficient.
          jump: Jump's strength.
          agents: List of agents.
          current_agent: Current agent to be updated (or not).
          best_agent: Best population's agent.
          function: A function object.
  
      Returns:
          (np.ndarray): A location vector containing the updated position.
  
      """
  
      w = r.generate_uniform_random_number()
      if w >= 0.5:
          # Soft besiege
          if energy >= 0.5:
              delta = best_agent.position - current_agent.position
  
              # Calculates the location vector (eq. 4)
              location_vector = delta - energy * np.fabs(
                  jump * best_agent.position - current_agent.position
              )
  
              return location_vector
  
          # Hard besiege
          else:
              delta = best_agent.position - current_agent.position
  
              # Calculates the location vector (eq. 6)
              location_vector = best_agent.position - energy * np.fabs(
                  delta
              )
  
              return location_vector
  
      # With rapid dives
      # Soft besiege
      if energy >= 0.5:
          # Calculates the `Y` position (eq. 7)
          Y = best_agent.position - energy * np.fabs(
              jump * best_agent.position - current_agent.position
          )
  
          # Generates the Lévy's flight and random array (eq. 9)
          LF = d.generate_levy_distribution(
              1.5,
              (current_agent.n_variables, current_agent.n_dimensions),
          )
          S = r.generate_uniform_random_number(
              size=(
                  current_agent.n_variables,
                  current_agent.n_dimensions,
              )
          )
  
          # Calculates the `Z` position (eq. 8)
          Z = Y + S * LF
  
          Y_fit = function(Y)
          Z_fit = function(Z)
  
          # If `Y` position is better than current agent's one (eq. 10 - part 1)
          if Y_fit < current_agent.fit:
              return Y
  
          # If `Z` position is better than current agent's one (eq. 10 - part 2)
          if Z_fit < current_agent.fit:
              return Z
  
      # Hard besiege
      else:
          average = np.mean([x.position for x in agents], axis=0)
  
          # Calculates the `Y` position (eq. 12)
          Y = best_agent.position - energy * np.fabs(
              jump * best_agent.position - average
          )
  
          # Generates the Lévy's flight and random array (eq. 9)
          LF = d.generate_levy_distribution(
              1.5,
              (current_agent.n_variables, current_agent.n_dimensions),
          )
          S = r.generate_uniform_random_number(
              size=(
                  current_agent.n_variables,
                  current_agent.n_dimensions,
              )
          )
  
          # Calculates the `Z` position (eq. 13)
          Z = Y + S * LF
  
          Y_fit = function(Y)
          Z_fit = function(Z)
  
          # If `Y` position is better than current agent's one (eq. 11 - part 1)
          if Y_fit < current_agent.fit:
              return Y
  
          # If `Z` position is better than current agent's one (eq. 11 - part 2)
          if Z_fit < current_agent.fit:
              return Z
  
      return current_agent.position
  
file_path: opytimizer/opytimizer/optimizers/population/hho.py
imports: from typing import Any, Dict, List, Optional, Tuple
  import numpy
  import opytimizer.math.distribution
  import opytimizer.math.random
  from opytimizer.core import Optimizer
  from opytimizer.core.agent import Agent
  from opytimizer.core.function import Function
  from opytimizer.core.space import Space
  from opytimizer.utils import logging
label_desc: Use image node_id 4 for calling the HHO obj's underlying member method code with example usage: obj._exploitation_phase(energy, jump, agents, current_agent, best_agent, function) and returns: current_agent, location_vector, location_vector, Y, Z, Y, Z