From 759ec98cbff8832ae23f9d40c2199a345920fa8c Mon Sep 17 00:00:00 2001 From: peyman Date: Thu, 30 Jun 2022 12:22:48 +0200 Subject: [PATCH 1/6] do optimization and visualize the log --- test_ga_opt.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 test_ga_opt.py diff --git a/test_ga_opt.py b/test_ga_opt.py new file mode 100644 index 0000000..801f278 --- /dev/null +++ b/test_ga_opt.py @@ -0,0 +1,40 @@ +from ga_opt import GA + +# objective function +#def objective(x): +# return -(x[0]**2.0 + x[1]**2.0) + + +# f(x,y) = - ((x+2y-7)^² + (2x+y-5)^2) +# Optimmum point f(x=1, y= 3) = 0 +def objective_2(x): + return -((x[0]+2*x[1]-7)**2+(2*x[0]+x[1]-5)**2) + +# define range for input +bounds = [[-5.0, 5.0], [-5.0, 5.0]] + +# define the total iterations +n_iter = 100 + +# bits per variable +n_bits = 16 + +# define the population size +n_pop = 100 + +# crossover rate +r_cross = 0.9 + +# mutation rate +r_mut = 1.0 / (float(n_bits) * len(bounds)) + +# perform the genetic algorithm search +ga_engine = GA(objective_2, bounds, n_bits, n_iter, n_pop, r_cross, r_mut) + +# output of ga_engine.run will give two output, the first is list of best result, second is the log +best_res, record = ga_engine.run() + + +# visulize the record +ga_engine.visualize_log(ga_record=record) + -- GitLab From 8dcb335197538f717624b844e1aeca124dd2fba0 Mon Sep 17 00:00:00 2001 From: peyman Date: Thu, 30 Jun 2022 12:23:23 +0200 Subject: [PATCH 2/6] visualize log and optimze instead of minimzation --- ga_opt.py | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 ga_opt.py diff --git a/ga_opt.py b/ga_opt.py new file mode 100644 index 0000000..8f90426 --- /dev/null +++ b/ga_opt.py @@ -0,0 +1,118 @@ +import numpy as np +import matplotlib.pyplot as plt +from numpy.random import randint +from numpy.random import rand + +class GA: + + def __init__(self, objective, bounds, n_bits, n_iter, n_pop, r_cross, r_mut): + self.objective = objective + self.bounds = bounds + self.n_bits = n_bits + self.n_iter = n_iter + self.n_pop = n_pop + self.r_cross = r_cross + self.r_mut = r_mut + + # decode bitstring to numbers + def decode(self, bitstring): + decoded = list() + largest = 2**self.n_bits + for i in range(len(self.bounds)): + # extract the substring + start, end = i * self.n_bits, (i * self.n_bits)+self.n_bits + substring = bitstring[start:end] + # convert bitstring to a string of chars + chars = ''.join([str(s) for s in substring]) + # convert string to integer + integer = int(chars, 2) + # scale integer to desired range + value = self.bounds[i][0] + (integer/largest) * (self.bounds[i][1] - self.bounds[i][0]) + # store + decoded.append(value) + return decoded + + # tournament selection + def selection(self, pop, scores, k=3): + # first random selection + selection_ix = randint(len(pop)) + for ix in randint(0, len(pop), k-1): + # check if better (e.g. perform a tournament) + if scores[ix] > scores[selection_ix]: + selection_ix = ix + return pop[selection_ix] + + # crossover two parents to create two children + def crossover(self, p1, p2): + # children are copies of parents by default + c1, c2 = p1.copy(), p2.copy() + # check for recombination + if rand() < self.r_cross: + # select crossover point that is not on the end of the string + pt = randint(1, len(p1)-2) + # perform crossover + c1 = p1[:pt] + p2[pt:] + c2 = p2[:pt] + p1[pt:] + return [c1, c2] + + # mutation operator + def mutation(self, bitstring): + for i in range(len(bitstring)): + # check for a mutation + if rand() < self.r_mut: + # flip the bit + bitstring[i] = 1 - bitstring[i] + + def run(self): + # initial population of random bitstring + pop = [randint(0, 2, self.n_bits*len(self.bounds)).tolist() for _ in range(self.n_pop)] + # keep track of best solution + best, best_eval = 0, self.objective(self.decode(pop[0])) + # enumerate generations + score = [] + list_best = [] + for gen in range(self.n_iter): + # decode population + decoded = [self.decode(p) for p in pop] + # evaluate all candidates in the population + scores = [self.objective(d) for d in decoded] + # check for new best solution + for i in range(self.n_pop): + if scores[i] > best_eval: + best, best_eval = pop[i], scores[i] + print(">%d, new best f(%s) = %f" % (gen, decoded[i], scores[i])) + + # recording the best individual in each iteration + + list_best.append([gen, self.decode(best),best_eval]) + + # select parents + selected = [self.selection(pop, scores) for _ in range(self.n_pop)] + # create the next generation + children = list() + for i in range(0, self.n_pop, 2): + # get selected parents in pairs + p1, p2 = selected[i], selected[i+1] + # crossover and mutation + for c in self.crossover(p1, p2): + # mutation + self.mutation(c) + # store for next generation + children.append(c) + # replace population + pop = children + print('Done!') + decoded = self.decode(best) + print('f(%s) = %f' % (decoded, best_eval)) + return [decoded, best_eval], list_best + + def visualize_log(self, ga_record): + + best_value_list = np.zeros(self.n_iter) + + for i, each_gene in enumerate(ga_record): + + best_value_list[i] = each_gene[2] + + plt.plot(np.arange(self.n_iter), best_value_list) + plt.show() -- GitLab From 409a86525cadd42f7684b33afa875055d9a295a1 Mon Sep 17 00:00:00 2001 From: peyman Date: Thu, 30 Jun 2022 16:47:05 +0200 Subject: [PATCH 3/6] transfered to ga --- ga_opt.py | 118 ------------------------------------------------------ 1 file changed, 118 deletions(-) delete mode 100644 ga_opt.py diff --git a/ga_opt.py b/ga_opt.py deleted file mode 100644 index 8f90426..0000000 --- a/ga_opt.py +++ /dev/null @@ -1,118 +0,0 @@ -import numpy as np -import matplotlib.pyplot as plt -from numpy.random import randint -from numpy.random import rand - -class GA: - - def __init__(self, objective, bounds, n_bits, n_iter, n_pop, r_cross, r_mut): - self.objective = objective - self.bounds = bounds - self.n_bits = n_bits - self.n_iter = n_iter - self.n_pop = n_pop - self.r_cross = r_cross - self.r_mut = r_mut - - # decode bitstring to numbers - def decode(self, bitstring): - decoded = list() - largest = 2**self.n_bits - for i in range(len(self.bounds)): - # extract the substring - start, end = i * self.n_bits, (i * self.n_bits)+self.n_bits - substring = bitstring[start:end] - # convert bitstring to a string of chars - chars = ''.join([str(s) for s in substring]) - # convert string to integer - integer = int(chars, 2) - # scale integer to desired range - value = self.bounds[i][0] + (integer/largest) * (self.bounds[i][1] - self.bounds[i][0]) - # store - decoded.append(value) - return decoded - - # tournament selection - def selection(self, pop, scores, k=3): - # first random selection - selection_ix = randint(len(pop)) - for ix in randint(0, len(pop), k-1): - # check if better (e.g. perform a tournament) - if scores[ix] > scores[selection_ix]: - selection_ix = ix - return pop[selection_ix] - - # crossover two parents to create two children - def crossover(self, p1, p2): - # children are copies of parents by default - c1, c2 = p1.copy(), p2.copy() - # check for recombination - if rand() < self.r_cross: - # select crossover point that is not on the end of the string - pt = randint(1, len(p1)-2) - # perform crossover - c1 = p1[:pt] + p2[pt:] - c2 = p2[:pt] + p1[pt:] - return [c1, c2] - - # mutation operator - def mutation(self, bitstring): - for i in range(len(bitstring)): - # check for a mutation - if rand() < self.r_mut: - # flip the bit - bitstring[i] = 1 - bitstring[i] - - def run(self): - # initial population of random bitstring - pop = [randint(0, 2, self.n_bits*len(self.bounds)).tolist() for _ in range(self.n_pop)] - # keep track of best solution - best, best_eval = 0, self.objective(self.decode(pop[0])) - # enumerate generations - score = [] - list_best = [] - for gen in range(self.n_iter): - # decode population - decoded = [self.decode(p) for p in pop] - # evaluate all candidates in the population - scores = [self.objective(d) for d in decoded] - # check for new best solution - for i in range(self.n_pop): - if scores[i] > best_eval: - best, best_eval = pop[i], scores[i] - print(">%d, new best f(%s) = %f" % (gen, decoded[i], scores[i])) - - # recording the best individual in each iteration - - list_best.append([gen, self.decode(best),best_eval]) - - # select parents - selected = [self.selection(pop, scores) for _ in range(self.n_pop)] - # create the next generation - children = list() - for i in range(0, self.n_pop, 2): - # get selected parents in pairs - p1, p2 = selected[i], selected[i+1] - # crossover and mutation - for c in self.crossover(p1, p2): - # mutation - self.mutation(c) - # store for next generation - children.append(c) - # replace population - pop = children - print('Done!') - decoded = self.decode(best) - print('f(%s) = %f' % (decoded, best_eval)) - return [decoded, best_eval], list_best - - def visualize_log(self, ga_record): - - best_value_list = np.zeros(self.n_iter) - - for i, each_gene in enumerate(ga_record): - - best_value_list[i] = each_gene[2] - - plt.plot(np.arange(self.n_iter), best_value_list) - plt.show() -- GitLab From 3254522ea9274f317fd4679f34d0aafa0b759f69 Mon Sep 17 00:00:00 2001 From: peyman Date: Thu, 30 Jun 2022 16:47:44 +0200 Subject: [PATCH 4/6] import packages and log visulize --- ga.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/ga.py b/ga.py index 18ab38e..44c5142 100644 --- a/ga.py +++ b/ga.py @@ -1,5 +1,7 @@ from numpy.random import randint from numpy.random import rand +import numpy as np +import matplotlib.pyplot as plt """NB: started from the example published by Jason Brownlee (2021), on the machinelearningmastery.com blog""" @@ -42,7 +44,7 @@ class GA: selection_ix = randint(len(pop)) for ix in randint(0, len(pop), k-1): # check if better (e.g. perform a tournament) - if scores[ix] < scores[selection_ix]: + if scores[ix] > scores[selection_ix]: selection_ix = ix return pop[selection_ix] @@ -81,7 +83,7 @@ class GA: scores = [self.objective(d) for d in decoded] # check for new best solution for i in range(self.n_pop): - if scores[i] < best_eval: + if scores[i] > best_eval: best, best_eval = pop[i], scores[i] print(">%d, new best f(%s) = %f" % (gen, decoded[i], scores[i])) # select parents @@ -102,4 +104,15 @@ class GA: print('Done!') decoded = self.decode(best) print('f(%s) = %f' % (decoded, best_eval)) - return [best, best_eval] \ No newline at end of file + return [best, best_eval] + + def visualize_log(self, ga_record): + + best_value_list = np.zeros(self.n_iter) + + for i, each_gene in enumerate(ga_record): + + best_value_list[i] = each_gene[2] + + plt.plot(np.arange(self.n_iter), best_value_list) + plt.show() \ No newline at end of file -- GitLab From d8cd65d98890553aa8f21430056d1e00e7fb49eb Mon Sep 17 00:00:00 2001 From: peyman Date: Thu, 30 Jun 2022 16:54:21 +0200 Subject: [PATCH 5/6] removed --- test_ga_opt.py | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 test_ga_opt.py diff --git a/test_ga_opt.py b/test_ga_opt.py deleted file mode 100644 index 801f278..0000000 --- a/test_ga_opt.py +++ /dev/null @@ -1,40 +0,0 @@ -from ga_opt import GA - -# objective function -#def objective(x): -# return -(x[0]**2.0 + x[1]**2.0) - - -# f(x,y) = - ((x+2y-7)^² + (2x+y-5)^2) -# Optimmum point f(x=1, y= 3) = 0 -def objective_2(x): - return -((x[0]+2*x[1]-7)**2+(2*x[0]+x[1]-5)**2) - -# define range for input -bounds = [[-5.0, 5.0], [-5.0, 5.0]] - -# define the total iterations -n_iter = 100 - -# bits per variable -n_bits = 16 - -# define the population size -n_pop = 100 - -# crossover rate -r_cross = 0.9 - -# mutation rate -r_mut = 1.0 / (float(n_bits) * len(bounds)) - -# perform the genetic algorithm search -ga_engine = GA(objective_2, bounds, n_bits, n_iter, n_pop, r_cross, r_mut) - -# output of ga_engine.run will give two output, the first is list of best result, second is the log -best_res, record = ga_engine.run() - - -# visulize the record -ga_engine.visualize_log(ga_record=record) - -- GitLab From e04032bd08022c1e715a41c80921ac06970a0587 Mon Sep 17 00:00:00 2001 From: peyman Date: Thu, 30 Jun 2022 16:54:34 +0200 Subject: [PATCH 6/6] new test --- test_ga.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/test_ga.py b/test_ga.py index 7473a78..55816d8 100644 --- a/test_ga.py +++ b/test_ga.py @@ -1,7 +1,7 @@ from ga import GA def test_constructor_works(): - paraboloid = lambda x: x[0]**2.0 + x[1]**2.0 + paraboloid = lambda x: -(x[0]**2.0 + x[1]**2.0) bounds = [[-5.0, 5.0], [-5.0, 5.0]] n_iter = 100 n_bits = 16 @@ -9,11 +9,11 @@ def test_constructor_works(): r_cross = 0.9 r_mut = 1.0 / (float(n_bits) * len(bounds)) ga_engine = GA(paraboloid, bounds, n_bits, n_iter, n_pop, r_cross, r_mut) - assert ga_engine.objective([1,2]) == 5 + assert ga_engine.objective([1,2]) == -5 ga_engine.bounds def test_run_with_paraboloid(): - paraboloid = lambda x: x[0]**2.0 + x[1]**2.0 + paraboloid = lambda x: -(x[0]**2.0 + x[1]**2.0) bounds = [[-5.0, 5.0], [-5.0, 5.0]] n_iter = 100 n_bits = 16 @@ -27,7 +27,7 @@ def test_run_with_paraboloid(): assert 0.0 - 1e5 <= solution[1] <= 0.0 + 1e5 def test_run_with_goldstein_prince(): - gp = lambda x: (1 + (x[0]+x[1]+1)**2 * (19-14*x[0] + 3*x[0]**2 -14*x[1] + 6*x[0]*x[1]+3*x[1]**2)) * (30 + (2*x[0] -3*x[1])**2 * (18 - 32*x[0] + 12*x[0]**2 + 48*x[1] -36*x[0]*x[1] + 27*x[1]**2)) + gp = lambda x: -(1 + (x[0]+x[1]+1)**2 * (19-14*x[0] + 3*x[0]**2 -14*x[1] + 6*x[0]*x[1]+3*x[1]**2)) * (30 + (2*x[0] -3*x[1])**2 * (18 - 32*x[0] + 12*x[0]**2 + 48*x[1] -36*x[0]*x[1] + 27*x[1]**2)) bounds = [[-2.0, 2.0], [-2.0, 2.0]] n_iter = 100 n_bits = 16 @@ -36,9 +36,50 @@ def test_run_with_goldstein_prince(): r_mut = 1.0 / (float(n_bits) * len(bounds)) ga_engine = GA(gp, bounds, n_bits, n_iter, n_pop, r_cross, r_mut) solution, obj_val = ga_engine.run() - assert 3.0 - 1e5 <= obj_val <= 3.0 + 1e5 + assert -3.0 - 1e5 <= obj_val <= -3.0 + 1e5 assert 0.0 - 1e5 <= solution[0] <= 0.0 + 1e5 assert -1.0 - 1e5 <= solution[1] <= -1.0 + 1e5 # Optimization problem -# https://en.wikipedia.org/wiki/Test_functions_for_optimization \ No newline at end of file +# https://en.wikipedia.org/wiki/Test_functions_for_optimizationy + +""" from ga import GA + +# objective function +#def objective(x): +# return -(x[0]**2.0 + x[1]**2.0) + + +# f(x,y) = - ((x+2y-7)^² + (2x+y-5)^2) +# Optimmum point f(x=1, y= 3) = 0 +def objective_2(x): + return -((x[0]+2*x[1]-7)**2+(2*x[0]+x[1]-5)**2) + +# define range for input +bounds = [[-5.0, 5.0], [-5.0, 5.0]] + +# define the total iterations +n_iter = 100 + +# bits per variable +n_bits = 16 + +# define the population size +n_pop = 100 + +# crossover rate +r_cross = 0.9 + +# mutation rate +r_mut = 1.0 / (float(n_bits) * len(bounds)) + +# perform the genetic algorithm search +ga_engine = GA(objective_2, bounds, n_bits, n_iter, n_pop, r_cross, r_mut) + +# output of ga_engine.run will give two output, the first is list of best result, second is the log +best_res, record = ga_engine.run() + + +# visulize the record +ga_engine.visualize_log(ga_record=record) """ + -- GitLab