1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| import numpy as np from numpy.random import default_rng import random import sys
answer = sys.argv[1] low = 65 high = 123
dawkins = np.array( [ord(x) for x in answer if x != ' '] )
space_position = [x[0] for x in enumerate(answer) if x[1] == ' ']
def chromosomes(): return np.random.randint( low=low, high=high, size=len(dawkins) )
def init_population(r: int): return np.array([ chromosomes() for _ in range(r) ])
def diff(x: np.ndarray): return np.subtract(dawkins, x)
def std(dif: np.ndarray, r=4): return round(np.std(dif), r)
def fitness(population: np.ndarray): return np.array([std(diff(x)) for x in population])
def description(label: str, min_loss: float, master_string: str): print('--------------------------------------------') print(label, 'min loss = ', min_loss) print(label, 'master = ', master_string) print('--------------------------------------------')
def ranking_selection(population: np.ndarray, fargs: np.ndarray, n: int): return population[fargs][:n]
def sex(s1: np.ndarray, s2: np.ndarray, mw: int = 99): p = np.zeros(len(s1), int) d1 = diff(s1) d2 = diff(s2) for i in range(len(s1)): [m] = random.choices(range(0, 2), weights=[mw, 1]) if m == 0: p[i] = s1[i] if abs(d1[i]) < abs(d2[i]) else s2[i] else: p[i] = np.random.randint(low, high) return p
def crossover(selection: np.ndarray, r: int, mw: int = 99): high = len(selection) offspring = np.empty((0, len(selection[0])), int) while r > 0: rng = default_rng() x, y = rng.choice(high, size=2, replace=False) child = sex(selection[x], selection[y], mw) offspring = np.vstack((offspring, child)) r -= 1 return offspring
def ascii_to_str(gene: np.ndarray): a = list(map(chr, gene)) for s in space_position: a.insert(s, ' ') return ''.join(a)
gen = 1 n = 1000 m = 100 mw = 99 population = init_population(n) while True: fit = fitness(population) fargs = np.argsort(fit) master_index = fargs[0] master_string = ascii_to_str(population[master_index]) description(f'Generation {gen}', fit[fargs[0]], master_string) if np.array_equal(population[master_index], dawkins): print(f'Generation {gen} found the answer: {answer}') break else: selection = ranking_selection(population, fargs, m) population = crossover(selection, n, mw) gen += 1
|