original_docstring: 
      Simple implementation of the GA algorithm
  
      :param array: e.g. cities array
      :param n_gen: total number of generations. np.inf by default
      :param pop_size: size of population
      :param parent_size: how many parents to select. Offsprings will be half of parent_size
      :param fit_fun: fitness function
      :param mut_funs: list of mutation functions to use
      :param mut_perc: percentage of population to mutate
      :param sel_fun: selection function
      :param cross_fun: crossover function
      :param pop_include_zero: whether the permutations in the population should include the point 0
      :param max_no_change: maximum number of iterations with no change of best memeber before convergence
      :param on_subsets: if True, GA is applied to find order of clusters/subsets
      :param verbose:  if True, prints the progress of the algorithm
      :return: best overall permutation
      
docstring: Simple implementation of the GA algorithm
docstring_tokens: Simple implementation of the GA algorithm
code: def GA(array, n_gen, pop_size, parent_size, fit_fun, mut_funs, mut_perc=0.1, sel_fun=roulette_selection,
         cross_fun=two_point_crossover, pop_include_zero=True, max_no_change=100, on_subsets=False, verbose=False, **kwargs):
      """
      Simple implementation of the GA algorithm
  
      :param array: e.g. cities array
      :param n_gen: total number of generations. np.inf by default
      :param pop_size: size of population
      :param parent_size: how many parents to select. Offsprings will be half of parent_size
      :param fit_fun: fitness function
      :param mut_funs: list of mutation functions to use
      :param mut_perc: percentage of population to mutate
      :param sel_fun: selection function
      :param cross_fun: crossover function
      :param pop_include_zero: whether the permutations in the population should include the point 0
      :param max_no_change: maximum number of iterations with no change of best memeber before convergence
      :param on_subsets: if True, GA is applied to find order of clusters/subsets
      :param verbose:  if True, prints the progress of the algorithm
      :return: best overall permutation
      """
      subs = kwargs.get("subs")
      if on_subsets:
          n = len(subs)
      else:
          n = len(array)
  
      # init pop
      pop = pop_gen(n, pop_size, pop_include_zero)
  
      length_fun = kwargs.get("length_fun")
      black_list = kwargs.get("black_list")
  
      scores = pop_eval(array, pop, fit_fun, length_fun=length_fun, black_list=black_list, subs=subs)
  
      ov_best = np.max(scores)  # overall best score init
      best_pop = pop  # overall best pop init
  
      iter_no_change = 0
      i = 0
  
      while i < n_gen:
          # pass n_gen = np.inf to iterate until iter_no_change >= max_no_change
  
          # select best parents
          parents = sel_fun(pop, scores, parent_size)
  
          # generate offsprings
          offs = cross_fun(parents)
  
          # replace worst in pop with offs
          sort = np.argsort(scores)
          pop[sort[:len(offs)]] = offs
  
          # mutate pop
          for fun in mut_funs:
              pop = pop_mutation(pop, fun, mut_perc)
  
          # evaluate
          # scores = pop_eval(array, pop, fit_fun)
          scores = pop_eval(array, pop, fit_fun, length_fun=length_fun, black_list=black_list, subs=subs)
  
          # update traces
          best = np.max(scores)  # new best score
  
          if best > ov_best:
              ov_best = best
              best_pop = pop.copy()
              iter_no_change = 0
  
          if verbose:
              if i % 1000 == 0:
                  print('Iter {}, ItNoChange {}, Best {}'.format(i, iter_no_change, 1 / ov_best))
  
          i += 1
          iter_no_change += 1
          if iter_no_change >= max_no_change:
              break
  
      # best_scores = pop_eval(array, best_pop, fit_fun)
      best_scores = pop_eval(array, best_pop, fit_fun, length_fun=length_fun, black_list=black_list, subs=subs)
      best_perm = best_pop[np.argmax(best_scores)]
  
      return best_perm
code_tokens: def GA ( array , n_gen , pop_size , parent_size , fit_fun , mut_funs , mut_perc = 0.1 , sel_fun = roulette_selection , cross_fun = two_point_crossover , pop_include_zero = True , max_no_change = 100 , on_subsets = False , verbose = False , ** kwargs ) : subs = kwargs . get ( "subs" ) if on_subsets : n = len ( subs ) else : n = len ( array ) pop = pop_gen ( n , pop_size , pop_include_zero ) length_fun = kwargs . get ( "length_fun" ) black_list = kwargs . get ( "black_list" ) scores = pop_eval ( array , pop , fit_fun , length_fun = length_fun , black_list = black_list , subs = subs ) ov_best = np . max ( scores ) best_pop = pop iter_no_change = 0 i = 0 while i < n_gen : parents = sel_fun ( pop , scores , parent_size ) offs = cross_fun ( parents ) sort = np . argsort ( scores ) pop [ sort [ : len ( offs ) ] ] = offs for fun in mut_funs : pop = pop_mutation ( pop , fun , mut_perc ) scores = pop_eval ( array , pop , fit_fun , length_fun = length_fun , black_list = black_list , subs = subs ) best = np . max ( scores ) if best > ov_best : ov_best = best best_pop = pop . copy ( ) iter_no_change = 0 if verbose : if i % 1000 == 0 : print ( 'Iter {}, ItNoChange {}, Best {}' . format ( i , iter_no_change , 1 / ov_best ) ) i += 1 iter_no_change += 1 if iter_no_change >= max_no_change : break best_scores = pop_eval ( array , best_pop , fit_fun , length_fun = length_fun , black_list = black_list , subs = subs ) best_perm = best_pop [ np . argmax ( best_scores ) ] return best_perm
short_docstring: Simple implementation of the GA algorithm
short_docstring_tokens: Simple implementation of the GA algorithm
comment: """
      Simple implementation of the GA algorithm
  
      :param array: e.g. cities array
      :param n_gen: total number of generations. np.inf by default
      :param pop_size: size of population
      :param parent_size: how many parents to select. Offsprings will be half of parent_size
      :param fit_fun: fitness function
      :param mut_funs: list of mutation functions to use
      :param mut_perc: percentage of population to mutate
      :param sel_fun: selection function
      :param cross_fun: crossover function
      :param pop_include_zero: whether the permutations in the population should include the point 0
      :param max_no_change: maximum number of iterations with no change of best memeber before convergence
      :param on_subsets: if True, GA is applied to find order of clusters/subsets
      :param verbose:  if True, prints the progress of the algorithm
      :return: best overall permutation
      """$SEP$# init pop$SEP$# overall best score init$SEP$# overall best pop init$SEP$# pass n_gen = np.inf to iterate until iter_no_change >= max_no_change$SEP$# select best parents$SEP$# generate offsprings$SEP$# replace worst in pop with offs$SEP$# mutate pop$SEP$# evaluate$SEP$# scores = pop_eval(array, pop, fit_fun)$SEP$# update traces$SEP$# new best score$SEP$# best_scores = pop_eval(array, best_pop, fit_fun)