diff --git a/Python_codes/Genetic Algorithm/ga.py b/Python_codes/Genetic Algorithm/ga.py new file mode 100644 index 0000000..8f1c2da --- /dev/null +++ b/Python_codes/Genetic Algorithm/ga.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2021 Jude Michael Teves +# +# This file is a modification of the genetic algorithm library made by the same author. +# The link of the original implementation can be found here: https://github.com/Cyntwikip/libraries/blob/master/genetic_algo/ga.py +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . + +import ast, random, itertools + +import numpy as np +import pandas as pd + +from collections.abc import Iterable + +class GeneticAlgo(): + + def __init__(self, genes_dict, debug=False, random_seed=42): + self.debug = debug + self.random_seed = random_seed + self.genes_dict = genes_dict + self.generate_chromosomes() + + def generate_chromosomes(self): + keys = self.genes_dict.keys() + values = self.genes_dict.values() + chromosomes = list(itertools.product(*values)) + c_len = len(chromosomes) + codes = [str(i).zfill(5) for i in range(c_len)] + chromosomes = pd.DataFrame(chromosomes, index=codes, columns=keys) + self.chromosomes = chromosomes + if self.debug: + print('Number of Chromosomes: {}'.format(chromosomes.shape[0])) + + def get_initial_population(self, n): + np.random.seed(self.random_seed) + codes = list(self.chromosomes.index) + return np.random.choice(codes, n, replace=False) + + def get_best_parents(self, fitness): + ''' + fitness - dict {code: score} + ''' + result = sorted(fitness.items(), key=lambda x: x[1], reverse=True)[:2] + result = [i[0] for i in result] # get code + # duplicate single parent + if len(result) == 1: + result = result*2 + return result + + def make_children(self, parent1_code, parent2_code, num_children, mutation_prob=0.1): + # random seed + np.random.seed(self.random_seed) + random.seed(self.random_seed) + + parent_prob = (1 - mutation_prob)/2 + children_chromosomes = [] + for i in range(num_children): + chromosome = [] + for key in self.chromosomes: + choices = [self.chromosomes.loc[parent1_code, key], + self.chromosomes.loc[parent2_code, key], + random.choice(self.genes_dict[key])] + if type(choices[0]) != str and isinstance(choices[0], Iterable): + choices = [str(i) for i in choices] + gene = [np.random.choice(choices, p = [parent_prob, parent_prob, mutation_prob])][0] + gene = ast.literal_eval(gene) + else: + gene = [np.random.choice(choices, p = [parent_prob, parent_prob, mutation_prob])][0] + + chromosome.append(gene) + children_chromosomes.append(chromosome) + + codes = list(map(self.get_chromosome_code, children_chromosomes)) + codes = list(set(codes)) + return codes + + def get_chromosome_code(self, chromosome): + c = self.chromosomes + for key, row in c.iterrows(): + if (row.values.tolist()==chromosome): + break + return key diff --git a/Python_codes/Genetic Algorithm/sample.py b/Python_codes/Genetic Algorithm/sample.py new file mode 100644 index 0000000..c944d71 --- /dev/null +++ b/Python_codes/Genetic Algorithm/sample.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2021 Jude Michael Teves +# +# This file is a modification of the genetic algorithm library made by the same author. +# The link of the original implementation can be found here: https://github.com/Cyntwikip/libraries/blob/master/genetic_algo/sample.py +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . + +import click +from ga import GeneticAlgo as ga + +import numpy as np + +# Pool of genes +pool_scaler = ["MinMax (-1,1)", "MinMax (0,1)", "Std"] +pool_batch_size = [64, 72, 128, 256] +pool_lstm_layers = [[128, 128, 128], + [64, 64, 64], + [32, 32, 32], + [128, 64, 64], + [64, 32, 32], + [128, 64, 32]] +pool_dropout = [0., 0.1, 0.2] +pool_activation = ['tanh', 'sigmoid'] +pool_loss = ['mean_squared_error', 'mae'] +pool_epochs = [5] + +genes_dict = dict( scaler = pool_scaler, + batch_size = pool_batch_size, + lstm_layers = pool_lstm_layers, + dropout = pool_dropout, + activation = pool_activation, + loss = pool_loss, + epochs = pool_epochs + ) + +ga = ga(genes_dict, debug=True) + +@click.group() +def cli(): + pass + +@cli.command(name='make-children') +@click.argument('code1', type=str) +@click.argument('code2', type=str) +@click.option('-n', default=10) +def make_children(code1, code2, n): + codes = ga.make_children(code1, code2, n) + print(codes) + return + +@cli.command(name='chromosomes-head') +@click.option('-n', default=5) +def chromosomes_head(n): + print(ga.chromosomes.head(n)) + +@cli.command(name='get-population') +@click.option('-n', default=10) +def get_population(n): + pop = ga.get_initial_population(n) + print(pop) + +@cli.command(name='get-chromosome') +@click.argument('code', type=str) +def get_chromosome(code): + print(ga.chromosomes.loc[code]) + +@cli.command(name='survival') +@click.option('-n', default=10) +def survival(n): + # n=1 + codes = ga.get_initial_population(n) + np.random.seed(42) + scores = np.random.randint(0,40,n) + fitness = dict(zip(codes, scores)) + print(fitness) + best_parents = ga.get_best_parents(fitness) + print(best_parents) + +@cli.command(name='random') +@click.option('-n', default=5) +def randomizer(n): + np.random.seed(42) + a = [1,2,3,4,5,6,7,8,9,10] + + for i in range(n): + print(np.random.choice(a)) + +@cli.command(name='test1') +def test1(): + import pandas as pd + df = pd.DataFrame({'a':[[0,1,3],[2,3,4]], 'b':['a','b'], 'c':[64, 128]}) + compare = [[0,1,3], 'a', 64] + for key, row in df.iterrows(): + if (row.values==compare).all(): + print(key) + +if __name__ == '__main__': + cli()