Skip to content

Commit 71e3de8

Browse files
added non-constraint-aware initialization and mutation for comparison
1 parent 54010b4 commit 71e3de8

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

kernel_tuner/strategies/genetic_algorithm.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
_options = dict(
1212
popsize=("population size", 20),
1313
maxiter=("maximum number of generations", 100),
14-
constraint_aware=("constraint-aware optimization (True/False)", False),
14+
constraint_aware=("constraint-aware optimization (True/False)", True),
1515
method=("crossover method to use, choose any from single_point, two_point, uniform, disruptive_uniform", "uniform"),
1616
mutation_chance=("chance to mutate is 1 in mutation_chance", 10),
1717
)
@@ -36,7 +36,8 @@ def tune(searchspace: Searchspace, runner, tuning_options):
3636
weighted_population = []
3737
for dna in population:
3838
try:
39-
time = cost_func(dna, check_restrictions=False)
39+
# if we are not constraint-aware we should check restrictions upon evaluation
40+
time = cost_func(dna, check_restrictions=not constraint_aware)
4041
except util.StopCriterionReached as e:
4142
if tuning_options.verbose:
4243
print(e)
@@ -84,13 +85,24 @@ class GeneticAlgorithm:
8485
def __init__(self, pop_size, searchspace, constraint_aware=False, method="uniform", mutation_chance=10):
8586
self.pop_size = pop_size
8687
self.searchspace = searchspace
88+
self.tune_params = searchspace.tune_params.copy()
8789
self.constraint_aware = constraint_aware
8890
self.crossover_method = supported_methods[method]
8991
self.mutation_chance = mutation_chance
9092

9193
def generate_population(self):
9294
""" Constraint-aware population creation method """
93-
return list(list(p) for p in self.searchspace.get_random_sample(self.pop_size))
95+
if self.constraint_aware:
96+
pop = list(list(p) for p in self.searchspace.get_random_sample(self.pop_size))
97+
else:
98+
pop = []
99+
dna_size = len(self.tune_params)
100+
for _ in range(self.pop_size):
101+
dna = []
102+
for key in self.tune_params:
103+
dna.append(random.choice(self.tune_params[key]))
104+
pop.append(dna)
105+
return pop
94106

95107
def crossover(self, dna1, dna2):
96108
""" Apply selected crossover method, repair dna if constraint-aware """
@@ -135,12 +147,24 @@ def mutate(self, dna, cache=False):
135147
"""Mutate DNA with 1/mutation_chance chance."""
136148
# this is actually a neighbors problem with Hamming distance, choose randomly from returned searchspace list
137149
if int(random.random() * self.mutation_chance) == 0:
138-
if cache:
139-
neighbors = self.searchspace.get_neighbors(tuple(dna), neighbor_method="Hamming")
150+
if self.constraint_aware:
151+
if cache:
152+
neighbors = self.searchspace.get_neighbors(tuple(dna), neighbor_method="Hamming")
153+
else:
154+
neighbors = self.searchspace.get_neighbors_no_cache(tuple(dna), neighbor_method="Hamming")
155+
if len(neighbors) > 0:
156+
return list(random.choice(neighbors))
140157
else:
141-
neighbors = self.searchspace.get_neighbors_no_cache(tuple(dna), neighbor_method="Hamming")
142-
if len(neighbors) > 0:
143-
return list(random.choice(neighbors))
158+
# select a tunable parameter at random
159+
mutate_index = random.randint(0, len(self.tune_params)-1)
160+
mutate_key = list(self.tune_params.keys())[mutate_index]
161+
# get all possible values for this parameter and remove current value
162+
new_val_options = self.tune_params[mutate_key].copy()
163+
new_val_options.remove(dna[mutate_index])
164+
# pick new value at random
165+
if len(new_val_options) > 0:
166+
new_val = random.choice(new_val_options)
167+
dna[mutate_index] = new_val
144168
return dna
145169

146170

0 commit comments

Comments
 (0)