text: """
  
  Programmer: 
  Date of Development: 
  This code has been developed according to the procedures mentioned in the following research article:
  " "
  
  """
  import numpy as np
  import time
  import matplotlib.pyplot as plt
  
  from sklearn.model_selection import train_test_split
  from sklearn import datasets
  
  from Py_FS.wrapper.nature_inspired._utilities import Solution, Data, initialize, sort_agents, display, compute_fitness, compute_accuracy, Conv_plot
  from Py_FS.wrapper.nature_inspired._transfer_functions import get_trans_function
  
  def Name_of_the_wrapper(num_agents, max_iter, train_data, train_label, obj_function=compute_fitness, trans_func_shape='s', save_conv_graph=False):
      
      # Name of the optimizer
      ############################### Parameters ####################################
      #                                                                             #
      #   num_agents: number of agents                                              #
      #   max_iter: maximum number of generations                                   #
      #   train_data: training samples of data                                      #
      #   train_label: class labels for the training samples                        #                
      #   obj_function: the function to maximize while doing feature selection      #
      #   trans_function_shape: shape of the transfer function used                 #
      #   save_conv_graph: boolean value for saving convergence graph               #
      #                                                                             #
      ###############################################################################
      
      short_name = ''
      agent_name = ''
      train_data, train_label = np.array(train_data), np.array(train_label)
      num_features = train_data.shape[1]
      trans_function = get_trans_function(trans_func_shape)
  
      # setting up the objectives
      weight_acc = None
      if(obj_function==compute_fitness):
          weight_acc = float(input('Weight for the classification accuracy [0-1]: '))
      obj = (obj_function, weight_acc)
      compute_accuracy = (compute_fitness, 1) # compute_accuracy is just compute_fitness with accuracy weight as 1
  
      # initialize agents and Leader (the agent with the max fitness)
      agents = initialize(num_agents, num_features)
      fitness = np.zeros(num_agents)
      accuracy = np.zeros(num_agents)
      Leader_agent = np.zeros((1, num_features))
      Leader_fitness = float("-inf")
      Leader_accuracy = float("-inf")
  
      # initialize convergence curves
      convergence_curve = {}
      convergence_curve['fitness'] = np.zeros(max_iter)
      convergence_curve['feature_count'] = np.zeros(max_iter)
  
      # format the data
      data = Data()
      data.train_X, data.val_X, data.train_Y, data.val_Y = train_test_split(
          train_data, train_label, stratify=train_label, test_size=0.2)
  
      # create a solution object
      solution = Solution()
      solution.num_agents = num_agents
      solution.max_iter = max_iter
      solution.num_features = num_features
      solution.obj_function = obj_function
  
      # rank initial agents
      agents, fitness = sort_agents(agents, obj, data)
  
      # start timer
      start_time = time.time()
  
  
      for iter_no in range(max_iter):
          print('\n================================================================================')
          print('                          Iteration - {}'.format(iter_no+1))
          print('================================================================================\n')     
  
          ################ write your main position update code here ################
  
  
  
          ###########################################################################
  
          # update final information
          agents, fitness = sort_agents(agents, obj, data)
          display(agents, fitness, agent_name)
          
          # update Leader (best agent)
          if fitness[0] > Leader_fitness:
              Leader_agent = agents[0].copy()
              Leader_fitness = fitness[0].copy()
  
          convergence_curve['fitness'][iter_no] = Leader_fitness
          convergence_curve['feature_count'][iter_no] = int(np.sum(Leader_agent))
  
      # compute final accuracy
      Leader_agent, Leader_accuracy = sort_agents(Leader_agent, compute_accuracy, data)
      agents, accuracy = sort_agents(agents, compute_accuracy, data)
  
      print('\n================================================================================')
      print('                                    Final Result                                  ')
      print('================================================================================\n')
      print('Leader ' + agent_name + ' Dimension : {}'.format(int(np.sum(Leader_agent))))
      print('Leader ' + agent_name + ' Fitness : {}'.format(Leader_fitness))
      print('Leader ' + agent_name + ' Classification Accuracy : {}'.format(Leader_accuracy))
      print('\n================================================================================\n')
  
      # stop timer
      end_time = time.time()
      exec_time = end_time - start_time
  
      # plot convergence graph
      fig, axes = Conv_plot(convergence_curve)
      if(save_conv_graph):
          plt.savefig('convergence_graph_'+ short_name + '.jpg')
      plt.show()
  
      # update attributes of solution
      solution.best_agent = Leader_agent
      solution.best_fitness = Leader_fitness
      solution.best_accuracy = Leader_accuracy
      solution.convergence_curve = convergence_curve
      solution.final_agents = agents
      solution.final_fitness = fitness
      solution.final_accuracy = accuracy
      solution.execution_time = exec_time
  
      return solution
  
  
  if __name__ == '__main__':
  
      iris = datasets.load_iris()
      Name_of_the_wrapper(10, 20, iris.data, iris.target, save_conv_graph=True)
  