Sorting Networks
Optimal Network Generation
1from deap_er import creator
2from deap_er import tools
3from deap_er import base
4import random
5import numpy
6
7
8random.seed(1234) # disables randomization
9
10INPUTS = 6
11NGEN = 100
12CX_PROB = 0.5
13MUT_PROB = 0.2
14ADD_PROB = 0.01
15DEL_PROB = 0.01
16
17
18def eval_network(individual, dimension):
19 network = tools.SortingNetwork(dimension, individual)
20 return network.evaluate(), network.length, network.depth
21
22
23def gen_wire(dimension):
24 wire1 = random.randrange(dimension)
25 wire2 = random.randrange(dimension)
26 return wire1, wire2
27
28
29def gen_network(dimension, min_size, max_size):
30 size = random.randint(min_size, max_size)
31 network = [gen_wire(dimension) for _ in range(size)]
32 return network
33
34
35def mut_wire(individual, dimension, mut_prob):
36 for index, elem in enumerate(individual):
37 if random.random() < mut_prob:
38 individual[index] = gen_wire(dimension)
39
40
41def mut_add_wire(individual, dimension):
42 index = random.randint(0, len(individual))
43 individual.insert(index, gen_wire(dimension))
44
45
46def mut_del_wire(individual):
47 index = random.randrange(len(individual))
48 del individual[index]
49
50
51def setup():
52 creator.create("FitnessMin", base.Fitness, weights=(-1.0, -1.0, -1.0))
53 creator.create("Individual", list, fitness=creator.FitnessMin)
54
55 toolbox = base.Toolbox()
56 toolbox.register("network", gen_network, dimension=INPUTS, min_size=9, max_size=12)
57 toolbox.register("individual", tools.init_iterate, creator.Individual, toolbox.network)
58 toolbox.register("population", tools.init_repeat, list, toolbox.individual)
59
60 toolbox.register("evaluate", eval_network, dimension=INPUTS)
61 toolbox.register("mate", tools.cx_two_point)
62 toolbox.register("mutate", mut_wire, dimension=INPUTS, mut_prob=0.05)
63 toolbox.register("addwire", mut_add_wire, dimension=INPUTS)
64 toolbox.register("delwire", mut_del_wire)
65 toolbox.register("select", tools.sel_nsga_2)
66
67 stats = tools.Statistics(lambda ind: ind.fitness.values)
68 stats.register("avg", numpy.mean, axis=0)
69 stats.register("std", numpy.std, axis=0)
70 stats.register("min", numpy.min, axis=0)
71 stats.register("max", numpy.max, axis=0)
72
73 logbook = tools.Logbook()
74 logbook.header = "gen", "evals", "std", "min", "avg", "max"
75
76 return toolbox, stats, logbook
77
78
79def print_results(best_network):
80 print('\nBest sorting network schematic:')
81 print(best_network.draw())
82 print(f'\nEvolution converged correctly.')
83
84
85def main():
86 toolbox, stats, logbook = setup()
87 population = toolbox.population(size=300)
88 hof = tools.ParetoFront()
89
90 def log_stats(ngen=0):
91 hof.update(population)
92 record = stats.compile(population)
93 logbook.record(gen=ngen, evals=len(population), **record)
94 print(logbook.stream)
95
96 fitness = toolbox.map(toolbox.evaluate, population)
97 for ind, fit in zip(population, fitness):
98 ind.fitness.values = fit
99
100 log_stats()
101
102 for generation in range(1, NGEN):
103 offspring = [toolbox.clone(ind) for ind in population]
104
105 for ind1, ind2 in zip(offspring[::2], offspring[1::2]):
106 if random.random() < CX_PROB:
107 toolbox.mate(ind1, ind2)
108 del ind1.fitness.values
109 del ind2.fitness.values
110
111 for ind in offspring:
112 if random.random() < MUT_PROB:
113 toolbox.mutate(ind)
114 del ind.fitness.values
115 if random.random() < ADD_PROB:
116 toolbox.addwire(ind)
117 del ind.fitness.values
118 if random.random() < DEL_PROB:
119 toolbox.delwire(ind)
120 del ind.fitness.values
121
122 invalid_ind = [ind for ind in offspring if not ind.fitness.is_valid()]
123 fitness = toolbox.map(toolbox.evaluate, invalid_ind)
124 for ind, fit in zip(invalid_ind, fitness):
125 ind.fitness.values = fit
126
127 population = toolbox.select(population+offspring, len(offspring))
128
129 log_stats(generation)
130
131 best_network = tools.SortingNetwork(INPUTS, hof[0])
132 print_results(best_network)
133
134
135if __name__ == "__main__":
136 main()
Hillis Cooperative Co-Evolution
1from deap_er import creator
2from deap_er import tools
3from deap_er import base
4import random
5import numpy
6
7
8random.seed(1234) # disables randomization
9
10INPUTS = 12
11MAXGEN = 100
12H_CX_PROB, H_MUT_PROB = 0.6, 0.3
13P_CX_PROB, P_MUT_PROB = 0.6, 0.3
14
15
16def gen_wire(dimension):
17 wire1 = random.randrange(dimension)
18 wire2 = random.randrange(dimension)
19 return wire1, wire2
20
21
22def gen_network(dimension, min_size, max_size):
23 size = random.randint(min_size, max_size)
24 network = [gen_wire(dimension) for _ in range(size)]
25 return network
26
27
28def eval_network(host, parasite, dimension):
29 network = tools.SortingNetwork(dimension, host)
30 return network.evaluate(parasite), # The comma is essential here.
31
32
33def mut_network(individual, dimension, mutpb, addpb, delpb, indpb):
34 if random.random() < mutpb:
35 for index, elem in enumerate(individual):
36 if random.random() < indpb:
37 individual[index] = gen_wire(dimension)
38 if random.random() < addpb:
39 index = random.randint(0, len(individual))
40 individual.insert(index, gen_wire(dimension))
41 if random.random() < delpb:
42 index = random.randrange(len(individual))
43 del individual[index]
44 return individual, # The comma is essential here.
45
46
47def clone_network(individual):
48 clone = individual.__class__(individual)
49 clone.fitness.values = individual.fitness.values
50 return clone
51
52
53def gen_parasite(dimension):
54 return [random.choice((0, 1)) for _ in range(dimension)]
55
56
57def mut_parasite(individual, mut_prob):
58 for i in individual:
59 if random.random() < mut_prob:
60 tools.mut_flip_bit(i, mut_prob)
61 return individual, # The comma is essential here.
62
63
64def clone_parasite(individual):
65 clone = individual.__class__(list(seq) for seq in individual)
66 clone.fitness.values = individual.fitness.values
67 return clone
68
69
70def setup():
71 creator.create("FitnessMax", base.Fitness, weights=(1.0,))
72 creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
73 creator.create("Host", list, fitness=creator.FitnessMin)
74 creator.create("Parasite", list, fitness=creator.FitnessMax)
75
76 h_toolbox = base.Toolbox()
77 h_toolbox.register("host", gen_network, dimension=INPUTS, min_size=9, max_size=12)
78 h_toolbox.register("individual", tools.init_iterate, creator.Host, h_toolbox.host)
79 h_toolbox.register("population", tools.init_repeat, list, h_toolbox.individual)
80 h_toolbox.register("evaluate", eval_network, dimension=INPUTS)
81 h_toolbox.register("mate", tools.cx_two_point)
82 h_toolbox.register("mutate", mut_network, dimension=INPUTS, mutpb=0.2, addpb=0.01, delpb=0.01, indpb=0.05)
83 h_toolbox.register("select", tools.sel_tournament, contestants=3)
84 h_toolbox.register("clone", clone_network)
85
86 p_toolbox = base.Toolbox()
87 p_toolbox.register("parasite", gen_parasite, dimension=INPUTS)
88 p_toolbox.register("individual", tools.init_repeat, creator.Parasite, p_toolbox.parasite, 20)
89 p_toolbox.register("population", tools.init_repeat, list, p_toolbox.individual)
90 p_toolbox.register("mate", tools.cx_two_point)
91 p_toolbox.register("mutate", mut_parasite, mut_prob=0.05)
92 p_toolbox.register("select", tools.sel_tournament, contestants=3)
93 p_toolbox.register("clone", clone_parasite)
94
95 stats = tools.Statistics(lambda ind: ind.fitness.values)
96 stats.register("avg", numpy.mean)
97 stats.register("std", numpy.std)
98 stats.register("min", numpy.min)
99 stats.register("max", numpy.max)
100
101 logbook = tools.Logbook()
102 logbook.header = "gen", "evals", "std", "min", "avg", "max"
103
104 return h_toolbox, p_toolbox, stats, logbook
105
106
107def print_results(best_network):
108 print('\nBest sorting network schematic:')
109 print(best_network.draw())
110 print(f'\nEvolution converged correctly.')
111
112
113def main():
114 h_toolbox, p_toolbox, stats, logbook = setup()
115 hof = tools.HallOfFame(1)
116
117 def evaluate_fitness():
118 fits = h_toolbox.map(h_toolbox.evaluate, hosts, parasites)
119 for host, parasite, fit in zip(hosts, parasites, fits):
120 host.fitness.values = parasite.fitness.values = fit
121
122 def log_stats(ngen=0):
123 hof.update(hosts)
124 record = stats.compile(hosts)
125 logbook.record(gen=ngen, evals=len(hosts), **record)
126 print(logbook.stream)
127
128 hosts = h_toolbox.population(size=300)
129 parasites = p_toolbox.population(size=300)
130
131 evaluate_fitness()
132 log_stats()
133
134 for gen in range(1, MAXGEN):
135 hosts = h_toolbox.select(hosts, len(hosts))
136 parasites = p_toolbox.select(parasites, len(parasites))
137
138 hosts = tools.var_and(h_toolbox, hosts, H_CX_PROB, H_MUT_PROB)
139 parasites = tools.var_and(p_toolbox, parasites, P_CX_PROB, P_MUT_PROB)
140
141 evaluate_fitness()
142 log_stats(gen)
143
144 best_network = tools.SortingNetwork(INPUTS, hof[0])
145 print_results(best_network)
146
147
148if __name__ == "__main__":
149 main()