diff --git a/src/EasyGA.py b/src/EasyGA.py index 92baaac..183487e 100644 --- a/src/EasyGA.py +++ b/src/EasyGA.py @@ -20,10 +20,11 @@ class GA: # Defualt EastGA implimentation structure self.gene_function_impl = random_gene self.gene_input = [] - self.gene_input_type = [] #What if user gives two numbers (i.e. [1,100]) but wants to pick between the two (domain)? + self.gene_input_type = [] + while len(self.gene_input_type) != self.chromosome_length: self.gene_input_type.append(None) - + # Set the GA Configuration self.initialization_impl = random_initialization #self.mutation_impl = PerGeneMutation(Mutation_rate) @@ -36,27 +37,63 @@ class GA: def initialize(self, gene_input): self.gene_input = gene_input - #assuming domain if string (strings can never be range) - for x in range(len(self.gene_input)): - if isinstance(gene_input[x], list) == False: - self.gene_input[x] = [self.gene_input[x], self.gene_input[x]] + #It's possible user may just enter "domain", "float-range", etc. for gene_input_type rather than referring to a specific gene + #In that case, create an array with the same length as the chromosome where each element is just the user's input + if isinstance(self.gene_input_type, str): + gene_input_type_temp = self.gene_input_type + self.gene_input_type = [] + while len(self.gene_input_type) != self.chromosome_length: + self.gene_input_type.append(gene_input_type_temp) - if self.gene_input_type[x] == None: #If it hasn't been hard-set by the user + + #There are two types of gene_input we should expect from the user - "general" or index-dependent + #For example, if a user just enters [1,100], it should be assumed that this is a range/domain that should apply to all genes in the chromosome... + #...rather than assuming that it means gene 1 should be 1 and gene 2 should be 100. + #The check for this is done by checking if any of the values in the user's gene input are lists. + #If lists are included, then values like the ones given above will be converted (i.e. [1, 100, ["up", "left"]] becomes [[1,1], [100,100], ["up", "left"]]) and apply to specific genes + #Else if no lists are included, the gene input will apply to each gene (i.e. for chromosomes with length 3, [1,100] becomes [[1,100],[1,100],[1,100]]) + general_gene_input = True + for n in range(len(self.gene_input)): + if isinstance(self.gene_input[n], list): + general_gene_input = False + break + + #Converting user's input into standardized format - list of lists where each sublist is the range/domain for a specific gene + if general_gene_input == False: + for x in range(len(self.gene_input)): + if isinstance(self.gene_input[x], list) == False: + self.gene_input[x] = [self.gene_input[x], self.gene_input[x]] + else: + gene_input_temp = self.gene_input + self.gene_input = [] + for y in range(self.chromosome_length): + self.gene_input.append(gene_input_temp) + + #Setting up the gene_input_type defaults in the standard format + #values including strings are always domain + #values including floats but no strings is a float-range + #values included neither strings or floats is a normal range + for x in range(len(self.gene_input_type)): + try: + if (self.gene_input[x]): + pass + except IndexError: + self.gene_input.append(None) + + if self.gene_input_type[x] == None and self.gene_input[x] != None: #If it hasn't been hard-set by the user for y in range(len(self.gene_input[x])): - if isinstance(gene_input[x][y], str): + if isinstance(self.gene_input[x][y], str): self.gene_input_type[x] = "domain" break - elif isinstance(gene_input[x][y], float): + elif isinstance(self.gene_input[x][y], float): self.gene_input_type[x] = "float-range" elif y == (len(self.gene_input[x]) -1 and self.gene_input_type[x] != "float-range"): self.gene_input_type[x] = "range" - - # Create the first population self.population = self.initialization_impl( - self.population_size, self.chromosome_length, + self.population_size, self.gene_function_impl, self.gene_input, self.gene_input_type) diff --git a/src/initialization/gene_function/gene_random.py b/src/initialization/gene_function/gene_random.py index af2cdd1..82609d5 100644 --- a/src/initialization/gene_function/gene_random.py +++ b/src/initialization/gene_function/gene_random.py @@ -11,7 +11,7 @@ def check_values(low,high): def random_gene(gene_input, gene_input_type, gene_index): created_gene = None - #Determining if single range/domain or index-dependent + if gene_input_type[gene_index] == "range": created_gene = random.randint(gene_input[gene_index][0], gene_input[gene_index][1]) elif gene_input_type[gene_index] == "domain": diff --git a/src/initialization/random_initialization.py b/src/initialization/random_initialization.py index 72cfbfa..7de1459 100644 --- a/src/initialization/random_initialization.py +++ b/src/initialization/random_initialization.py @@ -13,7 +13,7 @@ def random_initialization(chromosome_length,population_size,gene_function,gene_i for i in range(population_size): chromosome = create_chromosome() #Fill the Chromosome with genes - for j in range(chromosome_length-1): + for j in range(chromosome_length): chromosome.add_gene(create_gene(gene_function(gene_input, gene_input_type, j))) population.add_chromosome(chromosome) return population diff --git a/src/new_initialization_method_testing.py b/src/new_initialization_method_testing.py index 07b1a09..f4d84db 100644 --- a/src/new_initialization_method_testing.py +++ b/src/new_initialization_method_testing.py @@ -10,18 +10,27 @@ import random # Create the Genetic algorithm ga = EasyGA.GA() + test_gene_input = [["left", "right"],[1,100],[5.0,10],[22,"up"]] -#ga.gene_input_type[1] = "domain" -#ga.gene_input_type[1] = "float-range" +ga.gene_input_type[1] = "float-range" +ga.gene_input_type[2] = "domain" + ga.initialize(test_gene_input) ga.population.print_all() +#Example tests +#Note, the following examples assume a chromosome length of 4. +#if the test_gene_input is longer than the chromosomes, it will get truncated at the length of the chromosome +#for example, for chromosomes with length 2, [["left", "right"],[1,100],[5.0,10],[22,"up"]] becomes [["left", "right"],[1,100]] +#if the test_gene_input is shorter than the chromosomes, the remaining elements will be populated with None +#test_gene_input = [1,100] +#test_gene_input = [["left", "right"],[1,100],[5.0,10],[22,"up"]] +#test_gene_input = ["left", "right", "up", "down"] +#test_gene_input = [[1,100],[0,1],[33,35],[5,6]] +#test_gene_input = [["left", "right"], ["up", "down"], ["left", "down"], ["down", "right"]] -#test_range_one = [1,100] -#test_domain_one = ["left", "right", "up", "down"] -#test_range_two = [[1,100],[0,1],[33,35],[5,6]] -#test_domain_two = [["left", "right"], ["up", "down"], ["left", "down"], ["down", "right"]] - -#for index-specific bounds, do list of lists i.e. test_range = [[1, 100], [1, 25], [5, 25]] \ No newline at end of file +#ga.gene_input_type = "float-range" +#ga.gene_input_type[1] = "domain" +#ga.gene_input_type[1] = "float-range" \ No newline at end of file