Using PyGAD Package, how to generate the item of populations with element not duplicate between 1 and 12? It is always has duplicate value in random population. I have no ideal how to avoid that. Or, should I manipulate in callback function when generate new population?
import pandas as pd
import numpy as np
import pygad
xs = [8, 50, 18, 35, 90, 40, 84, 74, 34, 40, 60, 74]
ys = [3, 62, 0, 25, 89, 71, 7, 29, 45, 65, 69, 47]
cities = ['Z', 'P', 'A', 'K', 'O', 'Y', 'N', 'X', 'G', 'Q', 'S', 'J']
locations = list(zip(xs, ys, cities))
def fitness_func(solution, solution_idx):
# Calculating the fitness value of each solution in the current population.
# The fitness function calulates the sum of products between each input and its corresponding weight.
# output = numpy.sum(solution*function_inputs)
# fitness = 1.0 / numpy.abs(output - desired_output)
total_length = 0
itemidx=0
for loc in solution:
if itemidx>0 :
cityidx1 = loc-1
cityidx2 =solution[itemidx-1]-1
total_length +=((xs[cityidx1] - xs[cityidx2]) ** 2 + (ys[cityidx1] - ys[cityidx2]) ** 2) ** (1 / 2)
# print(xs[cityidx1],ys[cityidx1], xs[cityidx1], ys[cityidx2],total_length )
elif itemidx==solution.size :
cityidx1 = loc-1
cityidx2 =solution[itemidx-1]-1
total_length +=((xs[cityidx1] - xs[cityidx2]) ** 2 + (ys[cityidx1] - ys[cityidx2]) ** 2) ** (1 / 2)
if ((xs[cityidx1] - xs[cityidx2]) ** 2 + (ys[cityidx1] - ys[cityidx2]) ** 2) ** (1 / 2) <0:
print('ERROR',((xs[cityidx1] - xs[cityidx2]) ** 2 + (ys[cityidx1] - ys[cityidx2]) ** 2) ** (1 / 2) )
# print(xs[cityidx1],ys[cityidx1], xs[cityidx1], ys[cityidx2],total_length )
cityidx2 =solution[0]
total_length +=((xs[itemidx] - xs[0]) ** 2 + (ys[itemidx] - ys[0]) ** 2) ** (1 / 2)
# print(total_length)
itemidx += 1
#print("fitness_func",total_length,solution,solution_idx)
return total_length*-1 #fitness
fitness_function = fitness_func
num_generations = 50 # Number of generations.
num_parents_mating = 7 # Number of solutions to be selected as parents in the mating pool.
sol_per_pop = 50 # Number of solutions in the population.
num_genes = 12
init_range_low = 1
init_range_high = 12
parent_selection_type = "rank" # Type of parent selection.
keep_parents = 7 # Number of parents to keep in the next population. -1 means keep all parents and 0 means keep nothing.
crossover_type = "single_point" # Type of the crossover operator.
# Parameters of the mutation operation.
mutation_type = "swap" # Type of the mutation operator.
mutation_percent_genes = 10
last_fitness = 0
population_list=[]
gene_space = [i for i in range(1, 13)]
for i in range(sol_per_pop):
nxm_random_num=list(np.random.permutation(gene_space))
population_list.append(nxm_random_num) # add to the population_list
ga_instance = pygad.GA(num_generations=num_generations,
num_parents_mating=num_parents_mating,
fitness_func=fitness_function,
sol_per_pop=sol_per_pop,
initial_population=population_list,
num_genes=num_genes,
gene_space = gene_space, #
# init_range_low=init_range_low,
# init_range_high=init_range_high,
parent_selection_type=parent_selection_type,
keep_parents=keep_parents,
crossover_type=crossover_type,
mutation_type=mutation_type,
mutation_percent_genes=mutation_percent_genes
)
ga_instance.run()
solution, solution_fitness, solution_idx = ga_instance.best_solution()
print("best_solution: {solution}".format(solution =solution))
#best_solution: [ 3 4 12 10 6 9 2 10 12 10 6 9]
#**Is any way to get new gerneration that elements not duplication**
Any help would be highly appreciated!
Update
PyGAD 2.13.0 is released which supports a new bool parameter called allow_duplicate_genes
. If set to False
, then no duplicate genes will exist in the solution. Read more here: https://pygad.readthedocs.io/en/latest/README_pygad_ReadTheDocs.html#prevent-duplicates-in-gene-values
.........................................
Thanks for using PyGAD :)
The feature of rejecting duplicate genes in a solution is not yet supported in PyGAD. So, you may expect duplicate values.
This is a very good feature to support in the next release of PyGAD (2.13.0). Thanks for asking this question.
Until the next release, you can build your own mutation function to reject duplicate values. Just follow these steps:
mutation_type
argument in the constructor of the pygad.GA
class to None
:mutation_type=None
def mut(...):
result = ....
return result
on_crossover()
callback function. This function is called directly after the crossover operation is complete. There, you fetch the array build after crossover [which is passed as an argument automatically to the callback function], apply your own mutation, and save the result back to be used by PyGAD.You can check the Life Cycle of PyGAD for more information about the callback functions.
def on_crossover(ga_instance, offspring_crossover):
# 1) Apply your mutation on the solutions in the offspring_crossover array.
# Assume the mutation offspring is saved in the offspring_mutation array.
offspring_mutation = mut(offspring_crossover)
2) Save the result in the last_generation_offspring_mutation attribute of ga_instance:
ga_instance.last_generation_offspring_mutation = offspring_mutation
# The previous links makes the next population to use your mutation offspring.
on_crossover
argument in the constructor of the pygad.GA class:on_crossover=on_crossover
That is all.