text: """Entry point to evolving the neural network. Start here."""
  import logging
  from optimizer import Optimizer
  from tqdm import tqdm
  
  # Setup logging.
  logging.basicConfig(
      format='%(asctime)s - %(levelname)s - %(message)s',
      datefmt='%m/%d/%Y %I:%M:%S %p',
      level=logging.DEBUG,
      filename='log.txt'
  )
  
  def train_networks(networks, dataset):
      """Train each network.
  
      Args:
          networks (list): Current population of networks
          dataset (str): Dataset to use for training/evaluating
      """
      pbar = tqdm(total=len(networks))
      for network in networks:
          network.train(dataset)
          pbar.update(1)
      pbar.close()
  
  def get_average_accuracy(networks):
      """Get the average accuracy for a group of networks.
  
      Args:
          networks (list): List of networks
  
      Returns:
          float: The average accuracy of a population of networks.
  
      """
      total_accuracy = 0
      for network in networks:
          total_accuracy += network.accuracy
  
      return total_accuracy / len(networks)
  
  def generate(generations, population, nn_param_choices, dataset, algoConfig, mutationType):
      """Generate a network with the genetic algorithm.
  
      Args:
          generations (int): Number of times to evole the population
          population (int): Number of networks in each generation
          nn_param_choices (dict): Parameter choices for networks
          dataset (str): Dataset to use for training/evaluating
  
      """
      optimizer = Optimizer(nn_param_choices)
      networks = optimizer.create_population(population)
  
      # Evolve the generation.
      for i in range(generations):
          logging.info("***Doing generation %d of %d***" %
                       (i + 1, generations))
  
          # Train and get accuracy for networks.
          train_networks(networks, dataset)
  
          # Get the average accuracy for this generation.
          average_accuracy = get_average_accuracy(networks)
  
          # Print out the average accuracy each generation.
          logging.info("Generation average: %.2f%%" % (average_accuracy * 100))
          logging.info('-'*80)
  
          # Evolve, except on the last iteration.
          if i != generations - 1:
              # Do the evolution.
              # Use selected evolution configuration, these are the different configurations that will be compared for efficiency in the analysis.
              if algoConfig == "elitism mutate":
                  networks = optimizer.elitismMutate(networks, mutationType)
              elif algoConfig == "elitism crossover mutate":
                  networks = optimizer.elitismCrossoverMutate(networks, mutationType)
              elif algoConfig == "elitism crossover":
                  networks = optimizer.elitismCrossover(networks)
              elif algoConfig == "roulette mutate":
                  networks = optimizer.rouletteMutate(networks, mutationType)
              elif algoConfig == "roulette crossover mutate":
                  networks = optimizer.rouletteCrossoverMutate(networks, mutationType)
              elif algoConfig == "roulette crossover":
                  networks = optimizer.rouletteCrossover(networks)
              elif algoConfig == "":
                  print("No Input")
              else:
                  print("Error: algoConfig is incorrect, please refer to main.py line 74 for configuration options")
  
  
      # Sort our final population.
      networks = sorted(networks, key=lambda x: x.accuracy, reverse=True)
  
      # Print out the top 5 networks.
      print_networks(networks[:5])
  
  def print_networks(networks):
      """Print a list of networks.
  
      Args:
          networks (list): The population of networks
  
      """
      logging.info('-'*80)
      for network in networks:
          network.print_network()
  
  def main():
      """Evolve a network."""
      generations = 10  # Number of times to evolve the population.
      population = 20  # Number of networks in each generation.
      dataset = 'mnist'
  
      nn_param_choices = {
          'nb_neurons': [64, 128, 256, 512, 768, 1024],
          'nb_layers': [1, 2, 3, 4],
          'activation': ['relu', 'elu', 'tanh', 'sigmoid'],
          'optimizer': ['rmsprop', 'adam', 'sgd', 'adagrad',
                        'adadelta', 'adamax', 'nadam'],
      }
      
      # Manas Rajendran
      algoConfig = input("What algorithm configuration would you like? Please enter an integer: ")
  
      if algoConfig == "elitism crossover" or algoConfig == "roulette crossover":
          mutationtype = input("Please enter the mutation configuration you would like to execute: ")
      else:
          mutationtype = 0
  
  
      logging.info("***Evolving %d generations with population %d***" %
                   (generations, population))
  
      generate(generations, population, nn_param_choices, dataset, algoConfig, mutationtype)
  
  
  if __name__ == '__main__':
      main()
  