Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion kernel_tuner/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@
pyatf_strategies,
random_sample,
simulated_annealing,
skopt
skopt,
gen_hybrid_vndx,
gen_adaptive_tabu_greywolf,
)
from kernel_tuner.strategies.wrapper import OptAlgWrapper

Expand All @@ -87,6 +89,8 @@
"firefly_algorithm": firefly_algorithm,
"bayes_opt": bayes_opt,
"pyatf_strategies": pyatf_strategies,
"hybrid_vndx": gen_hybrid_vndx,
"adaptive_tabu_greywolf": gen_adaptive_tabu_greywolf,
}


Expand Down Expand Up @@ -397,6 +401,8 @@ def __deepcopy__(self, _):
* "random_sample" takes a random sample of the search space
* "simulated_annealing" simulated annealing strategy
* "skopt" uses the minimization methods from `skopt`
* "HybridVNDX" a hybrid variable neighborhood descent strategy
* "AdaptiveTabuGreyWolf" an adaptive tabu-guided grey wolf optimization strategy

Strategy-specific parameters and options are explained under strategy_options.

Expand Down
239 changes: 239 additions & 0 deletions kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
"""
Adaptive Tabu-Guided Grey Wolf Optimization.

Check warning on line 2 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the useless trailing whitespaces at the end of this line.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBGp&open=AZ0lj-os1czxk8BIkBGp&pullRequest=368

Algorithm generated as part of the paper "Automated Algorithm Design For Auto-Tuning Optimizers".

Check warning on line 4 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the useless trailing whitespaces at the end of this line.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBGq&open=AZ0lj-os1czxk8BIkBGq&pullRequest=368
"""

import random
import math
from collections import deque

from kernel_tuner.util import StopCriterionReached
from kernel_tuner.strategies import common
from kernel_tuner.strategies.common import CostFunc


_options = dict(
budget=("maximum number of evaluations", 5000),
pack_size=("number of wolves", 8),
tabu_factor=("tabu size multiplier", 3),
shake_rate=("base shaking probability", 0.2),
jump_rate=("random jump probability", 0.15),
stagn_limit=("stagnation limit before restart", 80),
restart_ratio=("fraction of pack to restart", 0.3),
t0=("initial temperature", 1.0),
t_decay=("temperature decay rate", 5.0),
t_min=("minimum temperature", 1e-4),
constraint_aware=("constraint-aware optimization (True/False)", True),
)


def tune(searchspace, runner, tuning_options):

Check warning on line 31 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a docstring to this function.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBGs&open=AZ0lj-os1czxk8BIkBGs&pullRequest=368

options = tuning_options.strategy_options
if "x0" in options:
raise ValueError("Starting point (x0) is not supported for AdaptiveTabuGreyWolf strategy.")
(budget, pack_size, tabu_factor, shake_rate, jump_rate,
stagn_limit, restart_ratio, t0, t_decay, t_min, constraint_aware) = \
common.get_options(options, _options)

cost_func = CostFunc(searchspace, tuning_options, runner)

alg = AdaptiveTabuGreyWolf(
searchspace, cost_func,
budget, pack_size, tabu_factor,
shake_rate, jump_rate,
stagn_limit, restart_ratio,
t0, t_decay, t_min,
constraint_aware,
tuning_options.verbose,
)

try:
alg.run()
except StopCriterionReached as e:
if tuning_options.verbose:
print(e)

return cost_func.results


tune.__doc__ = common.get_strategy_docstring("Adaptive Tabu Grey Wolf", _options)


class AdaptiveTabuGreyWolf:

Check warning on line 64 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a docstring to this class.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBGt&open=AZ0lj-os1czxk8BIkBGt&pullRequest=368

Check warning on line 64 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add inheritance from "object" or some other new-style class.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBGu&open=AZ0lj-os1czxk8BIkBGu&pullRequest=368

def __init__(self, searchspace, cost_func,
budget, pack_size, tabu_factor,
shake_rate, jump_rate,
stagn_limit, restart_ratio,
t0, t_decay, t_min,
constraint_aware, verbose):

Check warning on line 71 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Method "__init__" has 14 parameters, which is greater than the 13 authorized.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBGv&open=AZ0lj-os1czxk8BIkBGv&pullRequest=368

self.searchspace = searchspace
self.cost_func = cost_func
self.budget = budget
self.pack_size = pack_size
self.tabu = deque(maxlen=pack_size * tabu_factor)
self.shake_rate = shake_rate
self.jump_rate = jump_rate
self.stagn_limit = stagn_limit
self.restart_ratio = restart_ratio
self.t0 = t0
self.t_decay = t_decay
self.t_min = t_min
self.constraint_aware = constraint_aware
self.verbose = verbose

def evaluate(self, dna):
return self.cost_func(dna, check_restrictions=not self.constraint_aware)

def sample_valid(self):
while True:
x = list(self.searchspace.get_random_sample(1)[0])
if not self.constraint_aware or self.searchspace.is_param_config_valid(tuple(x)):
return x

def repair(self, sol):
if not self.constraint_aware or self.searchspace.is_param_config_valid(tuple(sol)):
return sol

# try neighbors
for m in ("adjacent", "Hamming", "strictly-adjacent"):
for nb in self.searchspace.get_neighbors(tuple(sol), neighbor_method=m):
if self.searchspace.is_param_config_valid(nb):
return list(nb)

return self.sample_valid()

def run(self):

Check failure on line 109 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Function has a complexity of 21 which is greater than 15 authorized.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBGw&open=AZ0lj-os1czxk8BIkBGw&pullRequest=368

Check failure on line 109 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 63 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBG0&open=AZ0lj-os1czxk8BIkBG0&pullRequest=368

# initialize pack
pack = []
num_evals = 0

for cfg in self.searchspace.get_random_sample(self.pack_size):
sol = list(cfg)

try:
val = self.evaluate(sol)
num_evals += 1
except StopCriterionReached:
raise

Check warning on line 122 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add logic to this except clause or eliminate it and rethrow the exception automatically.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBG1&open=AZ0lj-os1czxk8BIkBG1&pullRequest=368

pack.append((sol, val))
self.tabu.append(tuple(sol))

pack.sort(key=lambda x: x[1])

best_sol, best_val = pack[0]

Check warning on line 129 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace the unused local variable "best_sol" with "_".

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBGz&open=AZ0lj-os1czxk8BIkBGz&pullRequest=368
stagn = 0
iteration = 0

Check warning on line 131 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused local variable "iteration".

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBGy&open=AZ0lj-os1czxk8BIkBGy&pullRequest=368

while num_evals < self.budget:

iteration += 1
frac = num_evals / self.budget

# temperature schedule
T = max(self.t_min, self.t0 * math.exp(-self.t_decay * frac))

# reheating
if stagn and stagn % max(1, (self.stagn_limit // 2)) == 0:
T += self.t0 * 0.2

# adaptive shaking
shake_p = min(0.5, self.shake_rate * (1 + stagn / self.stagn_limit))

pack.sort(key=lambda x: x[1])
alpha, beta, delta = pack[0][0], pack[1][0], pack[2][0]

new_pack = []

for sol, sol_val in pack:

# leaders survive
if sol in (alpha, beta, delta):
new_pack.append((sol, sol_val))
continue

D = len(sol)

# recombination
child = [
random.choice((alpha[i], beta[i], delta[i], sol[i]))
for i in range(D)
]

# shaking
if random.random() < shake_p:
if random.random() < self.jump_rate:
idx = random.randrange(D)
rnd = random.choice(self.searchspace.get_random_sample(1))
child[idx] = rnd[idx]
else:
method = "adjacent" if frac < 0.5 else "strictly-adjacent"
nbrs = list(self.searchspace.get_neighbors(tuple(child), neighbor_method=method))
if nbrs:

Check failure on line 177 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this code to not nest more than 4 "if", "for", "while", "try" and "with" statements.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBGo&open=AZ0lj-os1czxk8BIkBGo&pullRequest=368
child = list(random.choice(nbrs))

# repair
child = self.repair(child)
tchild = tuple(child)

# tabu handling
if tchild in self.tabu:
nbrs = list(self.searchspace.get_neighbors(tchild, neighbor_method="Hamming"))
if nbrs:
child = list(random.choice(nbrs))

try:
fch = self.evaluate(child)
num_evals += 1
except StopCriterionReached:
raise

Check warning on line 194 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add logic to this except clause or eliminate it and rethrow the exception automatically.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBG2&open=AZ0lj-os1czxk8BIkBG2&pullRequest=368

self.tabu.append(tuple(child))

# SA acceptance
dE = fch - sol_val

Check warning on line 199 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable "dE" to match the regular expression ^[_a-z][a-z0-9_]*$.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBGx&open=AZ0lj-os1czxk8BIkBGx&pullRequest=368
if dE <= 0 or random.random() < math.exp(-dE / T):
new_pack.append((child, fch))
else:
new_pack.append((sol, sol_val))

if num_evals >= self.budget:
break

pack = new_pack
pack.sort(key=lambda x: x[1])

# update best
if pack[0][1] < best_val:
best_sol, best_val = pack[0]
stagn = 0
else:
stagn += 1

# restart
if stagn >= self.stagn_limit:
nr = int(math.ceil(self.pack_size * self.restart_ratio))

for i in range(self.pack_size - nr, self.pack_size):
sol = self.sample_valid()

try:
val = self.evaluate(sol)
num_evals += 1
except StopCriterionReached:
raise

Check warning on line 229 in kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add logic to this except clause or eliminate it and rethrow the exception automatically.

See more on https://sonarcloud.io/project/issues?id=KernelTuner_kernel_tuner&issues=AZ0lj-os1czxk8BIkBG3&open=AZ0lj-os1czxk8BIkBG3&pullRequest=368

pack[i] = (sol, val)
self.tabu.append(tuple(sol))

pack.sort(key=lambda x: x[1])
best_sol, best_val = pack[0]
stagn = 0

if self.verbose and num_evals % 50 == 0:
print(f"Evaluations: {num_evals}, best: {best_val}")
Loading
Loading