add the bare-ish minimum to get things going

This commit is contained in:
Connor Olding 2023-05-04 08:22:54 -07:00
parent 85754a576e
commit 4829cbb0af
15 changed files with 3234 additions and 0 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
__pycache__/*
*.old
*.bak

69
generate_lists.py Executable file
View File

@ -0,0 +1,69 @@
#!/usr/bin/env python3
from types import ModuleType
import solutions_1680721604
import solutions_1680730206
import solutions_1680730206
import solutions_1680975848
solutions = {}
loaded = []
for local_k in tuple(locals().keys()):
local_v = locals()[local_k]
if local_k.startswith("solutions_") and isinstance(local_v, ModuleType):
loaded.append(local_k)
for k, v in local_v.solutions.items():
solutions.setdefault(k, {})
solutions[k] |= v
dims_seen = set()
totally_fine = {}
too_variable = {}
too_centered = {}
too_far_away = {}
too_positive = {}
for k, v in solutions.items():
fopt = sorted(v)[0]
xopt = v[fopt]
dims = len(xopt)
dims_seen.add(dims)
alpha = [0, 256, 200, 100, 64][dims]
name = k.removeprefix("go_").removesuffix(str(dims)).removesuffix("_on_cube__")
is_too_centered = all(round(x * alpha) == alpha // 2 for x in xopt)
is_too_positive = sum(abs(x - sum(xopt) / dims) for x in xopt) / dims <= 1e-3
is_too_far_away = any(abs(0.5 - x) > 0.49 for x in xopt)
is_inconsistent = name in ("stochastic", "xinsheyang01")
if name == "csendes":
pass # skip; this is basically equivalent to "infinite"
elif is_inconsistent:
too_variable.setdefault(dims, []).append(name)
elif is_too_centered:
too_centered.setdefault(dims, []).append(name)
elif is_too_far_away:
too_far_away.setdefault(dims, []).append(name)
elif is_too_positive:
too_positive.setdefault(dims, []).append(name)
else:
totally_fine.setdefault(dims, []).append(name)
def dump_list(name, rows):
print()
print(f"{name} = [")
for row in rows:
print(f" {repr(row)},")
print("]")
print("# this file was automatically generated by generate_lists.py,")
print("# any changes may be overwritten!")
for name in loaded:
print(f"# loaded {name}.py")
for dims in sorted(dims_seen):
dump_list(f"too_variable_{dims}", too_variable.get(dims, []))
dump_list(f"too_centered_{dims}", too_centered.get(dims, []))
dump_list(f"too_far_away_{dims}", too_far_away.get(dims, []))
dump_list(f"too_positive_{dims}", too_positive.get(dims, []))
dump_list(f"totally_fine_{dims}", totally_fine.get(dims, []))
# print(len(totally_fine))
# print(len(totally_fine) + len(too_centered) + len(too_positive))

497
go_benchmark_it.py Normal file
View File

@ -0,0 +1,497 @@
from go_benchmark_lists import *
from go_benchmarks import problems_2d, problems_3d, problems_4d
from notwacube import book_of_optimizers
from prog80 import prog
from utils import OWrap, COWrap, m1, m33, m36
from utils import perform_another_experimental_scoring_method
import numpy as np
all_problems = {
2: problems_2d,
3: problems_3d,
4: problems_4d,
}
tiny_offset = 1.1102230246251565e-16
def make_transform(lo, hi):
mul = max(lo, hi) - min(lo, hi)
add = min(lo, hi)
return mul, add
def flipit(transformations, flippy):
flip_dim = flippy - 1
mul, add = transformations[flip_dim]
desired_mul, desired_add = -1, 1 # f(g(x)) = f(1 - x)
mul, add = mul * desired_mul, mul * desired_add + add
transformations[flip_dim] = (mul, add)
def make_objective(problem, n_dim, *, fix_stuff=0):
obj = problem(n_dim)
name = problem.__name__
flippy = 0 # when positive, helps removes positive correlations in solutions
trippy = None # when not None, moves solution away from center: (dim, dir)
if fix_stuff >= 0:
if name == "Deb03":
# this problem has the wrong bounds for some reason, so we have to patch it.
obj._bounds = list(zip([0.0] * obj.N, [1.0] * obj.N))
elif name == "Csendes" or name == "Infinity":
# this problem is weird... let's avoid division by zero, okay?
# these problems are duplicates of each other. weird.
replacement = n_dim * (2 + np.sin(1))
_fun = obj.fun
obj.fun = lambda x: replacement if np.any(x == 0.0) else _fun(x)
elif name == "Keane":
# another problem that may attempt to divide by zero.
_fun = obj.fun
obj.fun = lambda x: 0.0 if np.all(x**2 == 0.0) else _fun(x)
elif name == "Kowalik":
# this divide by zero actually approaches infinity when not clipped.
# TODO: there seems to be some confusion about which is `a`
# and which is `b` between the equations and the code.
# hmm it seems like the code is right, judging by this:
# https://www.itl.nist.gov/div898/strd/nls/data/LINKS/DATA/MGH09.dat
helper = lambda x: np.where(x < 0, -1, 1) * (
np.abs(x) + tiny_offset
)
# 1.0 - 1e-16 == 0.9999999999999999
# 1.0 + 1e-16 == 1.0
# 1.0 + 2e-16 == 1.0000000000000002
# 1 / 1.1102230246251565e-16**2 == 8.112963841460668e+31
a, b = obj.a, obj.b
obj.fun = (
lambda x: sum(
b - (x[0] * (a**2 + a * x[1]) / helper(a**2 + a * x[2] + x[3]))
)
** 2
)
elif name == "Gulf":
# just another division by zero.
adjust = np.array([tiny_offset, 0.0, 0.0])
_fun = obj.fun
obj.fun = lambda x: _fun(x + adjust)
if fix_stuff >= 1:
stuff = {2: too_positive_2, 3: too_positive_3, 4: too_positive_4}[n_dim]
if name.lower() in stuff:
# too positively correlated, do some evil.
ind = stuff.index(name.lower())
flippy = ind % n_dim + 1 # uniformly select a dimension to "flip"
if fix_stuff >= 2:
stuff = {2: too_centered_2, 3: too_centered_3, 4: too_centered_4}[n_dim]
if name.lower() in stuff:
# uniformly select offsets to "trip".
ind = stuff.index(name.lower())
trippy = (ind % n_dim, ind // n_dim % n_dim) # (dim, dir)
transformations = [make_transform(lo, hi) for lo, hi in obj.bounds]
if flippy:
flipit(transformations, flippy)
def objective(x):
# assert all(xi >= 0.0 for xi in x), list(float(xi) for xi in x)
# assert all(xi <= 1.0 for xi in x), list(float(xi) for xi in x)
if trippy:
x = list(x) # mostly to create a copy
ind = trippy[0]
x[ind] = 1 - (1 - x[ind]) ** 0.5 if trippy[1] else x[ind] ** 0.5
x = [xi * mul + add for xi, (mul, add) in zip(x, transformations)]
# if problem.__name__.startswith("Deb"): print(x)
return obj.fun(np.array(x, copy=False))
objective.__name__ = f"go_{problem.__name__.lower()}_on_cube"
objective.__realname__ = problem.__name__
# objective.__qualname__ = problem.__name__
return objective
def make_objectives(n_dim, n_trials=None, fix_stuff=0):
problems = all_problems[n_dim]
return [make_objective(problem, n_dim, fix_stuff=fix_stuff) for problem in problems]
def find_objective(query, n_dim=None):
results = []
for p_dim, problems in all_problems.items():
if n_dim is not None and p_dim != n_dim:
continue
for problem in problems:
if problem.__name__.lower() == query.lower():
results.append(problem)
assert results, "no results found for name " + repr(query)
return results[0]
λ = lambda q: make_objective(find_objective(q, 2), 2, fix_stuff=2)
GO_BENCHMARK_2D_PROBLEMS = list(
map(λ, totally_fine_2 + too_positive_2 + too_centered_2)
)
λ = lambda q: make_objective(find_objective(q, 3), 3, fix_stuff=2)
GO_BENCHMARK_3D_PROBLEMS = list(
map(λ, totally_fine_3 + too_positive_3 + too_centered_3)
)
λ = lambda q: make_objective(find_objective(q, 4), 4, fix_stuff=2)
GO_BENCHMARK_4D_PROBLEMS = list(
map(λ, totally_fine_4 + too_positive_4 + too_centered_4)
)
GO_BENCHMARKS = {
2: GO_BENCHMARK_2D_PROBLEMS,
3: GO_BENCHMARK_3D_PROBLEMS,
4: GO_BENCHMARK_4D_PROBLEMS,
}
for problem_list in GO_BENCHMARKS.values():
for problem in problem_list:
# print(problem.__realname__)
assert (
problem.__realname__ != "Csendes"
), "please use Infinity instead; it's basically equivalent"
if __name__ == "__main__":
from tqdm import tqdm
import sys
def fib(n):
return pow(2 << n, n + 1, (4 << 2 * n) - (2 << n) - 1) % (2 << n)
def optimizer_filter(name):
# worst scoring optimizers: (awards=(5, 3, 2, 1)) (obj=146, opt=389) (dims=2, evals=80)
# evosax_pbt with (score: 0, price: 593) -593
# worst scoring optimizers: (awards=(5, 3, 2, 1)) (obj=70, opt=389) (dims=3, evals=1440)
# evosax_pbt with (score: 0, price: 315) -315
return not (
False
# or name.startswith("freelunch_krillherd_") # too buggy
or name == "ng_fcma_cube" # WTF HOW ARE YOU NAN'ING ON HYPERSPHERE
or name == "ngx_fcmas03_cube" # same thing but quintic
or name == "ngx_zero_cube" # 0 score, high price
# or name == "ngx_microcma_cube" # 0 score, high price
# or name == "ng_multiscalecma_cube" # 0 score, high price
or name == "evosax_pbt_cube" # 0 score, high price
or name == "evosax_guidedes_cube" # does get *a little* score...
or name == "freelunch_sa_ps04_cube"
or name == "ngx_microcma_cube"
)
def stfu(please_be_quiet=None):
if please_be_quiet is None:
please_be_quiet = (
"ng_ascmadethird_cube",
"ng_cmabounded_cube",
"ng_cmatuning_cube",
"ng_chaincmapowell_cube",
"ng_chainnaivetbpsacmapowell_cube",
"ng_paraportfolio_cube",
"ng_rescaledcma_cube",
)
for optimizer in optimizers:
name = optimizer.__name__
if any(obnoxious in name for obnoxious in please_be_quiet):
import warnings
from cma.evolution_strategy import InjectionWarning
warnings.simplefilter("ignore", InjectionWarning) # not our fault
break
def mark(opt_name):
return (
"\033[95m@"
if opt_name in ("another_random_cube", "quasirandom_cube")
else "\033[96m!"
if "nelder" in opt_name
else " "
)
def fancy_output(opt_name, score, price):
name = opt_name.removesuffix("_cube")
if type(score) is float:
assert type(price) is float, "type mismatch"
# unweight = 10 # len(optimizers) # sum(place_scores)
unweight = multiple * np.sqrt(len(optimizers))
stats = f"(score:{score * unweight:4.0f}, price:{price * unweight:4.0f})"
else:
stats = f"(score:{score:4}, price:{price:4})"
color = 0
reset = "\033[m"
# this will need adjusting depending on your terminal colors:
gradient = (32, 92, 93, 33, 91) # good to bad
if score == 0 and price == 0:
pass # wat?
elif score < 0 and price < 0:
color = 35 # wat?!
elif score > 0 and price == 0:
color = gradient[0] # good
elif score == 0 and price > 0:
color = gradient[4] # awful
elif score > price:
color = gradient[1] # ok
elif score == price:
color = gradient[2] # meh
elif score < price:
color = gradient[3] # bad
color = f"\033[{color}m"
s = f"{mark(opt_name)} {name:<32}{reset} with {color}{stats}{reset}"
delta = score - price
if type(score) is float:
delta *= unweight
color = 0
if delta > 6:
color = gradient[0]
elif delta < -6:
color = gradient[4]
elif delta > 1:
color = gradient[1]
elif delta < -1:
color = gradient[3]
else:
color = gradient[2]
color = f"\033[{color}m"
s += f" {color}{float(delta):+.0f}{reset}"
# s += f" {color}{delta:+}{reset}"
return s
def prune_results(results, multiple):
# if there are more than `multiple` results for one optimizer+objective pair,
# then trim the bottom and top until there are only `multiple` left.
new_results = {}
for obj_name, obj_res in results.items():
new_res = {}
for fopt, opt_name in sorted(obj_res):
new_res.setdefault(opt_name, []).append(fopt)
for opt_name, fopts in new_res.items():
# in the event that an odd number of results needs to be trimmed,
# prefer trimming from the bottom (i.e. worse solutions get removed first).
down = (len(fopts) - multiple) // 2
up = len(fopts) - (len(fopts) - multiple + 1) // 2
# print("asdf", len(fopts), down, up)
new_res[opt_name] = fopts[down:up]
for opt_name, fopts in new_res.items():
if not no_summary:
assert len(fopts) == multiple, (len(fopts), multiple)
if len(fopts) == multiple:
for fopt in fopts:
new_results.setdefault(obj_name, []).append((fopt, opt_name))
return results
reset = "\033[m"
quieter = True
please_stop_the_spam = True
no_summary = True
if 1:
multiple = 2
run_anyway = 3 # run_anyway = 7
always_run_anyway = True
else:
multiple = 1
run_anyway = 3
always_run_anyway = False
#percents = dict(frugal_percent=0.1, greedy_percent=1.5)
percents = dict(frugal_percent=1.0, greedy_percent=2.0)
book = book_of_optimizers
which = book[sys.argv[1]] if len(sys.argv) > 1 else book["standard"]
n_dim = int(sys.argv[2]) if len(sys.argv) > 2 else -2
n_trials = int(sys.argv[3]) if len(sys.argv) > 3 else fib(abs(n_dim) + 4) * 10
place_names = ("1st", "2nd", "3rd", "4th")
assert n_dim < 0, "unsupported in this version"
n_dim = abs(n_dim)
place_scores = (5, 3, 2, 1)
objectives = GO_BENCHMARKS[n_dim] # * multiple
optimizers = list(which) # copy
before = len(optimizers)
# if which is not book["everything"]:
optimizers = [opt for opt in optimizers if optimizer_filter(opt.__name__)]
after = len(optimizers)
s = "s" if before - after != 1 else ""
print(f"Pruned {before - after} unwanted optimizer{s}.")
ms = f" ({multiple} times)" if multiple != 1 else ""
n_obj = len(objectives)
n_opt = len(optimizers)
print(f"Optimizing {n_obj} objectives{ms} with {n_opt} optimizers...")
stfu()
pseudo_shuffled = lambda stuff: sorted(stuff, key=lambda obj: hash(repr(obj)))
results = {}
for optimizer in prog(pseudo_shuffled(optimizers), pref="m"):
opt_name = optimizer.__name__
wrapped = None
for objective in prog(pseudo_shuffled(objectives), pref="s"):
obj_name = objective.__name__
obj_realname = getattr(objective, "__realname__", obj_name)
if wrapped is None:
wrapped = COWrap(
objective,
optimizer=optimizer,
n_trials=n_trials,
n_dim=n_dim,
**percents,
)
else:
wrapped.objective = objective # 10+ times faster
run = 1
while (cache := wrapped.cached(run)) is not None:
run += 1
fopt, xopt = cache
results.setdefault(obj_name, []).append((fopt, opt_name))
note = (lambda s: None) if quieter else m36
once = False
while (
run <= multiple
or (always_run_anyway or not once)
and run_anyway
and run <= run_anyway
):
# assert run == wrapped._run, (run, wrapped._run)
if run != (_run := wrapped._run):
m33(f"Note: updating local run count from {run} to {_run}.")
run = _run
continue # check conditions again
note(
f"Using {opt_name} to optimize {obj_realname} ({obj_name}) [{run}] ..."
)
_ = optimizer(wrapped, n_trials=n_trials, n_dim=n_dim, with_count=False)
fopt, xopt = wrapped.finish()
results.setdefault(obj_name, []).append((fopt, opt_name))
once = True
run += 1
all_results = results
results = prune_results(results, multiple)
scores, prices = {}, {}
all_opt_names = set()
for obj_name, obj_res in results.items():
if not please_stop_the_spam:
print()
m1(f"{obj_name}:")
all_res = {}
for fopt, opt_name in obj_res:
all_res.setdefault(fopt, []).append(opt_name)
all_opt_names.add(opt_name)
scores.setdefault(opt_name, 0.0)
prices.setdefault(opt_name, 0.0)
sorted_res = sorted(all_res)
score_insignificance = sum(
len(all_res[fopt])
for _, fopt in zip(range(len(place_scores)), sorted_res)
)
price_insignificance = sum(
len(all_res[fopt])
for _, fopt in zip(range(len(place_scores)), reversed(sorted_res))
)
# print("score 1/x:", obj_name, score_insignificance)
# print("price 1/x:", obj_name, price_insignificance)
for i, fopt in enumerate(sorted_res):
# if i >= len(place_scores): # TODO: just make this part of the loop.
# break
mi = len(all_res) - i - 1
if i < len(place_scores):
for opt_name in all_res[fopt]:
scores[opt_name] = (
scores[opt_name] + place_scores[i] / score_insignificance
)
if mi < len(place_scores):
for opt_name in all_res[fopt]:
prices[opt_name] = (
prices[opt_name] + place_scores[mi] / price_insignificance
)
more_scores = perform_another_experimental_scoring_method(results)
for blah, points in zip(("best", "worst"), (scores, prices)):
if not no_summary:
print(
f"\n\033[1m{blah} scoring optimizers:\033[m"
f" (awards={place_scores})"
f" (obj={len(objectives)}, opt={len(optimizers)})"
f" (dims={n_dim}, evals={n_trials})"
)
for opt_name, opt_point in sorted(points.items(), key=lambda t: -t[1]):
# place = place_names[i] if i < len(place_names) else " "
# delta = scores.get(opt_name, 0) - prices.get(opt_name, 0)
if not no_summary:
print(
fancy_output(
opt_name, scores.get(opt_name, 0), prices.get(opt_name, 0)
)
)
positive, negative = [], []
for opt_name in sorted(all_opt_names):
delta = scores.get(opt_name, 0) - prices.get(opt_name, 0)
# note: this intentionally includes delta == 0 in both positive and negative.
if delta >= 0:
if opt_name not in positive:
positive.append(opt_name)
if delta <= 0:
if opt_name not in negative:
negative.append(opt_name)
if no_summary:
print(
f"\n\033[1malternatively scored optimizers:\033[m"
f" (awards={place_scores})"
f" (obj={len(objectives)}, opt={len(optimizers)})"
f" (dims={n_dim}, evals={n_trials})"
)
for opt_name, opt_score in sorted(more_scores.items(), key=lambda t: -t[1]):
# if opt_score < 1: continue
stats = f"{opt_score:18.16f}"
name = opt_name.removesuffix("_cube")
color = "\033[1m" if opt_score > 1.0 else "\033[33m" if opt_score < 1.0 else ""
s = f"{mark(opt_name)} {name:<32}{reset} with {color}{stats}{reset}"
# s += f" {color}{float(delta):+.0f}{reset}"
print(s)
text = "# this file was automatically generated by go_benchmark_it.py,\n"
text += "# any changes may be overwritten!\n"
text += "PREVIOUSLY_POSITIVE = [\n"
text += "".join(f' "{opt_name}",\n' for opt_name in positive)
text += "]\n"
text += "PREVIOUSLY_NEGATIVE = [\n"
text += "".join(f' "{opt_name}",\n' for opt_name in negative)
text += "]\n"
if positive or negative:
try:
__import__("pathlib").Path("previous.py").write_text(text)
except PermissionError:
print("# failed to write previous.py, ignoring...")
if len(sys.argv) > 1 and sys.argv[1] in ("positive", "negative"):
all_old_opt_names = set(opt.__name__ for opt in optimizers)
C = set(("quasirandom_cube", "another_random_cube"))
if sys.argv[1] == "positive" and set(positive) - C == all_old_opt_names - C:
exit(2) # no changes
if sys.argv[1] == "negative" and set(negative) - C == all_old_opt_names - C:
exit(2) # no changes

371
go_benchmark_lists.py Normal file
View File

@ -0,0 +1,371 @@
# this file was automatically generated by generate_lists.py,
# any changes may be overwritten!
# loaded solutions_1680721604.py
# loaded solutions_1680730206.py
# loaded solutions_1680975848.py
too_variable_2 = [
'stochastic',
'xinsheyang01',
]
too_centered_2 = [
'ackley01',
'ackley02',
'bartelsconn',
'bohachevsky2',
'bukin04',
'bukin06',
'cigar',
'deflectedcorrugatedspring',
'dropwave',
'exponential',
'griewank',
'infinity',
'matyas',
'needleeye',
'pathological',
'pinter',
'price02',
'price04',
'qing',
'rotatedellipse01',
'rotatedellipse02',
'salomon',
'sargan',
'schaffer01',
'schaffer02',
'schwefel01',
'schwefel02',
'sphere',
'threehumpcamel',
'treccani',
'trigonometric02',
'ursem04',
'ventersobiezcczanskisobieski',
'wayburnseader02',
'xinsheyang02',
'xinsheyang03',
'xinsheyang04',
'yaoliu04',
'yaoliu09',
]
too_far_away_2 = [
'adjiman',
'brent',
'crosslegtable',
'eggholder',
'katsuura',
'mishra01',
'mishra02',
'mishra03',
'mishra05',
'newfunction01',
'newfunction02',
'rana',
'trigonometric01',
'ursemwaves',
]
too_positive_2 = [
'amgm',
'brown',
'cosinemixture',
'crossintray',
'cube',
'deb01',
'deb03',
'decanomial',
'easom',
'eggcrate',
'giunta',
'jennrichsampson',
'keane',
'levy03',
'mishra04',
'penalty01',
'penalty02',
'penholder',
'price03',
'quintic',
'schwefel04',
'schwefel20',
'schwefel26',
'shubert03',
'step2',
'styblinskitang',
'testtubeholder',
'vincent',
'weierstrass',
'zacharov',
'zettl',
]
totally_fine_2 = [
'ackley03',
'alpine01',
'alpine02',
'beale',
'biggsexp02',
'bird',
'bohachevsky1',
'bohachevsky3',
'branin01',
'branin02',
'bukin02',
'carromtable',
'chichinadze',
'crownedcross',
'damavandi',
'deceptive',
'deckkersaarts',
'dixonprice',
'elattarvidyasagardutta',
'exp2',
'freudensteinroth',
'goldsteinprice',
'hansen',
'himmelblau',
'holdertable',
'hosaki',
'judge',
'langermann',
'leon',
'levy05',
'levy13',
'mccormick',
'michalewicz',
'mishra06',
'mishra07',
'mishra08',
'mishra10',
'mishra11',
'multimodal',
'oddsquare',
'parsopoulos',
'permfunction01',
'permfunction02',
'plateau',
'price01',
'quadratic',
'rastrigin',
'ripple01',
'ripple25',
'rosenbrock',
'rosenbrockmodified',
'schaffer03',
'schaffer04',
'schwefel06',
'schwefel21',
'schwefel22',
'schwefel36',
'shubert01',
'shubert04',
'sineenvelope',
'sixhumpcamel',
'sodp',
'step',
'stretchedv',
'trefethen',
'tripod',
'ursem01',
'ursem03',
'wavy',
'wayburnseader01',
'whitley',
'zerosum',
'zimmerman',
'zirilli',
]
too_variable_3 = [
'stochastic',
'xinsheyang01',
]
too_centered_3 = [
'ackley01',
'alpine01',
'deflectedcorrugatedspring',
'exponential',
'griewank',
'infinity',
'mishra11',
'multimodal',
'pinter',
'qing',
'rastrigin',
'salomon',
'schwefel01',
'schwefel20',
'schwefel21',
'schwefel22',
'sineenvelope',
'sodp',
'trigonometric02',
'wavy',
'weierstrass',
'xinsheyang02',
'xinsheyang03',
'yaoliu04',
'yaoliu09',
'zerosum',
]
too_far_away_3 = [
'cosinemixture',
'katsuura',
'meyer',
'mishra01',
'mishra02',
'rana',
'trigonometric01',
'whitley',
'wolfe',
]
too_positive_3 = [
'amgm',
'brown',
'cigar',
'deb01',
'deb03',
'deceptive',
'needleeye',
'penalty01',
'schwefel04',
'schwefel26',
'sphere',
'stretchedv',
'styblinskitang',
'zacharov',
]
totally_fine_3 = [
'alpine02',
'biggsexp03',
'boxbetts',
'dixonprice',
'eckerle4',
'eggholder',
'gulf',
'hartmann3',
'helicalvalley',
'mishra07',
'mishra09',
'penalty02',
'permfunction01',
'permfunction02',
'plateau',
'quadratic',
'quintic',
'ratkowsky02',
'rosenbrock',
'sargan',
'schwefel02',
'shubert01',
'shubert03',
'shubert04',
'step2',
'step',
'vincent',
'xinsheyang04',
]
too_variable_4 = [
'stochastic',
'xinsheyang01',
]
too_centered_4 = [
'ackley01',
'alpine01',
'cigar',
'exponential',
'griewank',
'infinity',
'pinter',
'qing',
'schwefel01',
'schwefel02',
'schwefel20',
'schwefel21',
'schwefel22',
'sineenvelope',
'sphere',
'step2',
'step',
'stretchedv',
'trigonometric02',
'weierstrass',
'whitley',
'xinsheyang02',
'yaoliu04',
'yaoliu09',
'zerosum',
]
too_far_away_4 = [
'corana',
'cosinemixture',
'devilliersglasser01',
'katsuura',
'mielecantrell',
'mishra01',
'mishra02',
'rana',
'sargan',
'trigonometric01',
'xinsheyang03',
]
too_positive_4 = [
'amgm',
'brown',
'colville',
'deb03',
'penalty01',
'penalty02',
'powell',
'rosenbrock',
'schwefel04',
'shekel05',
'shekel07',
'shekel10',
'shubert03',
'shubert04',
'styblinskitang',
'vincent',
]
totally_fine_4 = [
'alpine02',
'biggsexp04',
'deb01',
'deceptive',
'deflectedcorrugatedspring',
'dixonprice',
'eggholder',
'gear',
'kowalik',
'mishra07',
'mishra11',
'multimodal',
'needleeye',
'permfunction01',
'permfunction02',
'plateau',
'powersum',
'quadratic',
'quintic',
'rastrigin',
'ratkowsky01',
'salomon',
'schwefel26',
'shubert01',
'sodp',
'wavy',
'xinsheyang04',
'zacharov',
]

49
go_benchmarks.py Normal file
View File

@ -0,0 +1,49 @@
from go_benchmark_functions import *
from inspect import getmro, isclass
_looky_here = False
problems = []
for k in list(locals().keys()):
smth = locals()[k]
if isclass(smth) and Benchmark in getmro(smth)[1:]:
problems.append(smth)
counts = {}
vcount = 0
problems_by_dimensions = {}
for cls in problems:
name = cls.__name__
obj = cls()
n = obj.N
if _looky_here:
print(n, name, "(variable)" if obj.change_dimensionality else "(fixed)")
counts[n] = counts.get(n, 0) + 1
if obj.change_dimensionality:
vcount += 1
dimkey = f"{n}+"
else:
dimkey = f"{n}"
problems_by_dimensions.setdefault(dimkey, []).append(cls)
del obj
counts["variable"] = vcount
if _looky_here:
print(sorted(counts.items(), key=lambda x: f"{x[0]:09}" if isinstance(x[0], int) else str(x[0])))
p_by_d = problems_by_dimensions
if _looky_here:
for dims in range(2, 6 + 1):
dimp = f"{dims}+"
print(dims, len(p_by_d.get(str(dims), [])), sep="\t")
print(dimp, len(p_by_d.get(dimp, [])), sep="\t")
at_least_2d = p_by_d.get("2+", [])
at_least_3d = p_by_d.get("3+", []) + at_least_2d
at_least_4d = p_by_d.get("4+", []) + at_least_3d
problems_2d = p_by_d.get("2", []) + at_least_2d
problems_3d = p_by_d.get("3", []) + at_least_3d
problems_4d = p_by_d.get("4", []) + at_least_4d

218
nloptcube2.py Normal file
View File

@ -0,0 +1,218 @@
import nlopt
import numpy as np
NLOPTIMIZERS = {
# "gd_mlsl": nlopt.GD_MLSL,
# "gd_mlsl_lds": nlopt.GD_MLSL_LDS,
# "gd_stogo": nlopt.GD_STOGO,
# "gd_stogo_rand": nlopt.GD_STOGO_RAND,
"gn_ags": nlopt.GN_AGS,
"gn_crs2_lm": nlopt.GN_CRS2_LM,
"gn_direct": nlopt.GN_DIRECT,
"gn_direct_l": nlopt.GN_DIRECT_L,
"gn_direct_l_noscal": nlopt.GN_DIRECT_L_NOSCAL,
"gn_direct_l_rand": nlopt.GN_DIRECT_L_RAND,
"gn_direct_l_rand_noscal": nlopt.GN_DIRECT_L_RAND_NOSCAL,
"gn_direct_noscal": nlopt.GN_DIRECT_NOSCAL,
"gn_esch": nlopt.GN_ESCH,
"gn_isres": nlopt.GN_ISRES,
"gn_mlsl": nlopt.GN_MLSL,
"gn_mlsl_lds": nlopt.GN_MLSL_LDS,
"gn_orig_direct": nlopt.GN_ORIG_DIRECT,
"gn_orig_direct_l": nlopt.GN_ORIG_DIRECT_L,
"g_mlsl": nlopt.G_MLSL,
"g_mlsl_lds": nlopt.G_MLSL_LDS,
# "ld_auglag": nlopt.LD_AUGLAG,
# "ld_auglag_eq": nlopt.LD_AUGLAG_EQ,
# "ld_ccsaq": nlopt.LD_CCSAQ,
# "ld_lbfgs": nlopt.LD_LBFGS,
# "ld_lbfgs_nocedal": nlopt.LD_LBFGS_NOCEDAL,
# "ld_mma": nlopt.LD_MMA,
# "ld_slsqp": nlopt.LD_SLSQP,
# "ld_tnewton": nlopt.LD_TNEWTON,
# "ld_tnewton_precond": nlopt.LD_TNEWTON_PRECOND,
# "ld_tnewton_precond_restart": nlopt.LD_TNEWTON_PRECOND_RESTART,
# "ld_tnewton_restart": nlopt.LD_TNEWTON_RESTART,
# "ld_var1": nlopt.LD_VAR1,
# "ld_var2": nlopt.LD_VAR2,
"ln_auglag": nlopt.LN_AUGLAG,
"ln_auglag_eq": nlopt.LN_AUGLAG_EQ,
"ln_bobyqa": nlopt.LN_BOBYQA,
"ln_cobyla": nlopt.LN_COBYLA,
"ln_neldermead": nlopt.LN_NELDERMEAD,
"ln_newuoa": nlopt.LN_NEWUOA,
"ln_newuoa_bound": nlopt.LN_NEWUOA_BOUND,
"ln_praxis": nlopt.LN_PRAXIS,
"ln_sbplx": nlopt.LN_SBPLX,
}
def nlopt_cube_factory(objective, n_trials, n_dim, with_count, method):
optim = NLOPTIMIZERS[method]
feval_count = 0
best_so_far = None
def _objective(x, grad):
nonlocal feval_count, best_so_far
fx = objective(x)
feval_count += 1
if feval_count <= n_trials:
if best_so_far is None or fx < best_so_far[0]:
best_so_far = (fx, x)
return fx
opt = nlopt.opt(optim, n_dim)
opt.set_lower_bounds([0.0] * n_dim)
opt.set_upper_bounds([1.0] * n_dim)
opt.set_min_objective(_objective)
opt.set_maxeval(n_trials)
try:
opt.optimize([0.5] * n_dim)
except nlopt.RoundoffLimited as e:
print( # FIXME: de-uglify this!
"\033[33m",
"nlopt_" + method,
" exited early (",
type(e).__name__,
")",
"\033[0m",
sep="",
)
assert best_so_far is not None, optimizer.__name__
fopt, xopt = best_so_far
return (fopt, xopt, feval_count) if with_count else (fopt, xopt)
def nlopt_ags_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "gn_ags")
def nlopt_crs2_lm_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "gn_crs2_lm")
def nlopt_direct_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "gn_direct")
def nlopt_direct_l_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "gn_direct_l")
def nlopt_direct_l_noscal_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(
objective, n_trials, n_dim, with_count, "gn_direct_l_noscal"
)
def nlopt_direct_lr_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(
objective, n_trials, n_dim, with_count, "gn_direct_l_rand"
)
def nlopt_direct_lr_noscal_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(
objective, n_trials, n_dim, with_count, "gn_direct_l_rand_noscal"
)
def nlopt_direct_noscal_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(
objective, n_trials, n_dim, with_count, "gn_direct_noscal"
)
def nlopt_esch_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "gn_esch")
def nlopt_isres_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "gn_isres")
def nlopt_mlsl_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "gn_mlsl")
def nlopt_mlsl_lds_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "gn_mlsl_lds")
def nlopt_orig_direct_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "gn_orig_direct")
def nlopt_orig_direct_l_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(
objective, n_trials, n_dim, with_count, "gn_orig_direct_l"
)
def nlopt_auglag_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "ln_auglag")
def nlopt_auglag_eq_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "ln_auglag_eq")
def nlopt_bobyqa_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "ln_bobyqa")
def nlopt_cobyla_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "ln_cobyla")
def nlopt_neldermead_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "ln_neldermead")
def nlopt_newuoa_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "ln_newuoa")
def nlopt_newuoa_bound_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "ln_newuoa_bound")
def nlopt_praxis_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "ln_praxis")
def nlopt_sbplx_cube(objective, n_trials, n_dim, with_count):
return nlopt_cube_factory(objective, n_trials, n_dim, with_count, "ln_sbplx")
NLOPT_OPTIMIZERS = [
# global
# nlopt_ags_cube, # ValueError: nlopt invalid argument
nlopt_crs2_lm_cube,
nlopt_direct_cube,
nlopt_direct_l_cube,
nlopt_direct_l_noscal_cube,
nlopt_direct_lr_cube,
nlopt_direct_lr_noscal_cube,
nlopt_direct_noscal_cube,
nlopt_esch_cube,
nlopt_isres_cube,
# nlopt_mlsl_cube, # FIXME: Segmentation fault
# nlopt_mlsl_lds_cube # FIXME: Segmentation fault,
nlopt_orig_direct_cube,
nlopt_orig_direct_l_cube,
# local
# nlopt_auglag_cube, # FIXME: Segmentation fault
# nlopt_auglag_eq_cube, # FIXME: Segmentation fault
nlopt_bobyqa_cube,
nlopt_cobyla_cube,
nlopt_neldermead_cube,
nlopt_newuoa_cube,
# nlopt_newuoa_bound_cube, # sadly this times out on shekel. however it wins in nlopt_classic_d21_n550_armor
# nlopt_praxis_cube, # AssertionError: x is not finite (NaN or Inf or -Inf)
nlopt_sbplx_cube,
]

12
notwacube.py Normal file
View File

@ -0,0 +1,12 @@
from nloptcube2 import nlopt_neldermead_cube
from randomcube2 import another_random_cube, quasirandom_cube
BASELINE_OPTIMIZERS = [
another_random_cube,
nlopt_neldermead_cube,
quasirandom_cube,
]
book_of_optimizers = dict(
baseline=BASELINE_OPTIMIZERS,
)

442
prog80.py Executable file
View File

@ -0,0 +1,442 @@
import atexit
import sys
import time
# TODO: make this a namedtuple? or one of those newfangles dataclasses.
options = dict(
ascii=False, # TODO
color=True,
flush=True,
patient=True, # TODO: better name?
)
active = []
allocated = 0
DEBUG = False
def get_terminal_size(file=sys.stderr):
from os import get_terminal_size as os_gts
cols, rows = 0, 0
try:
cols, rows = os_gts(file.fileno())
except OSError:
pass
if cols <= 0 or rows <= 0:
from shutil import get_terminal_size as shutil_gts
# NOTE: this uses sys.stdout instead of our file!
cols, rows = shutil_gts()
return cols, rows
def extend72(s, mode=""):
if "t" in mode or "d" in mode or "a" in mode:
s = s[:-1]
return ((s[0] + s[1:-1]) * 72)[:71] + s[-1]
@atexit.register # in the absence of a try-except for KeyboardInterrupt...
def reset(*, file=sys.stderr):
# TODO: flesh this out?
# TODO: fancy backspace "\b" stuff to hide potentially unsupported escape sequences.
s = "\0337\033[J\033[r\0338"
if file is not None:
print(end=s, file=file, flush=True)
else:
return s
def alloc(lines):
# first, perform a reset of whatever scrolling region may already be set.
# the cursor is (almost) always reset after performing a reset command,
# so wrap the command in a cursor-save and cursor-restore.
s = "\0337\033[r\0338"
# now, do some magic to ensure there's enough empty lines for the progress bars
# *without* forcing the screen to scroll if there already is.
# TODO: clear these lines too? hmm, that would overwrite bars though, wouldn't it?
s += "\n" * lines # this part is simple enough; just print some newlines.
s += "\0338" # however, that resets the cursor's column, so restore its position.
# the position might not be on the same row as the line of text it was on before,
s += f"\033[{lines}B\033[{lines}A" # so move it down (clamped) and back up again.
# s += "\0337" # that should be everything, so store the adjusted cursor for later.
return s
class Prog80:
# TODO: use different(-ly placed) delimiters when length < 72?
styles = dict(
# TODO: maybe use namedtuples for these?
# TODO: maybe use a separate field for the "cursor" characters?
# this ought to eliminate the need for "d", "t" and "P" modes.
bar=dict(A=" ", B="█▌", mode="r"),
bar2=dict(A="", B="██", mode="dp"), # TODO: what's the non-'p' version?
bracketed=dict(A="[" + " " * 70 + "]", B="[" + "=" * 70 + "]", mode="P"),
circumslider=dict(A="o", B="", mode="pr"),
crossslider=dict(A="", B="†‡", mode="pr"),
dotslider=dict(A="-", B="", mode="pr"),
dotted=dict(A=".", B="!?", mode="r"),
equally=dict(A=".", B="="),
fractional=dict(
A="·····¬·····¬·····¼·····¬·····¬·····½·····¬·····¬·····¾·····¬·····¬·····!",
B="",
mode="ir",
),
longdotslider=dict(A="", B="—÷", mode="pr"),
meme=dict( # slightly modified
A="According to all known laws of aviation, there is no way a bee should be",
B="able to fly. Its wings are too small to get its fat body off the ground.",
mode="P",
),
middledots=dict(A="", B=""),
money=dict(A="¢", B="$"),
# pacman=dict(A="-", B="#"),
# bracketedpacman=dict(A="[" + "-" * 70 + "]", B="[" + "#" * 70 + "]", mode="P"),
pacman=dict(A="[" + "-" * 70 + "]", B="[" + "#" * 70 + "]", mode="P"),
piping=dict(A="=", B="=|", mode="pr"),
ruler=dict(A="90123456780", B="90123456780", mode="P"),
slider=dict(A="_", B="_⌂", mode="pr"),
smile=dict(A="", B=""),
song=dict(
A=" - ♪ - ♪ - ♪ - ♪",
B=" ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫",
),
sticks=dict(A="/", B="\\|", mode="p"),
virus=dict(A=".▀", B=" TECHNO ▄", mode="ap"), # »Don't touch the keyboard«
)
bands = [ # TODO: come up with a better name for this variable.
("*", -4.94065645841246544177e-324, lambda x: "Waiting"),
("*", 0.0, lambda x: "Running"),
("*", 1.3888888888888887e-08, lambda x: "TooSlow"),
("*", 0.00027776388888888886, lambda x: f"{x * 60 * 60:6.4f}/h"[1:]),
("*", 0.001666583333333333, lambda x: f"{x * 60 * 60:5.3f}/h"),
("s", 0.01666583333333333, lambda x: f"{x * 60:6.4f}/m"[1:]),
("m", 0.01666583333333333, lambda x: f"{x * 60:6.4f}/m"[1:]),
("s", 0.09995, lambda x: f"{x * 60:5.3f}/m"),
("s", 0.9999499999999999, lambda x: f"{x:6.4f}/s"[1:]),
("m", 0.16665833333333332, lambda x: f"{x * 60:5.3f}/m"),
("m", 1.666583333333333, lambda x: f"{x * 60:5.2f}/m"),
("s", 9.999499999999998, lambda x: f"{x:5.3f}/s"),
("s", 12.000833333333333, lambda x: f"{x:5.2f}/s"),
("m", 16.66583333333333, lambda x: f"{x * 60:5.1f}/m"),
("m", 166.6583333333333, lambda x: f"{x * 60:4.0f}./m"),
("*", 0.002777638888888889, lambda x: f"{x * 60 * 60:5.3f}/h"),
("*", 0.027776388888888885, lambda x: f"{x * 60 * 60:5.2f}/h"),
("*", 0.20001388888888888, lambda x: f"{x * 60 * 60:5.1f}/h"),
("h", 0.2777638888888888, lambda x: f"{x * 60 * 60:5.1f}/h"),
("h", 2.7776388888888883, lambda x: f"{x * 60 * 60:4.0f}./h"),
("*", 1.666583333333333, lambda x: f"{x * 60:5.2f}/m"),
("*", 12.000833333333333, lambda x: f"{x * 60:5.1f}/m"),
("*", 99.99499999999999, lambda x: f"{x:5.2f}/s"),
("*", 999.9499999999999, lambda x: f"{x:5.1f}/s"),
("*", 9999.499999999998, lambda x: f"{x:4.0f}./s"),
("*", 1.7976931348623157e308, lambda x: f"TooFast"),
]
# TODO: default to sys.stderr as well!
def __init__(
self,
it,
length,
*,
printer=print,
style=None,
display="elapsed",
preference="*",
):
self.i = 0
self.it = iter(it)
self.length = length
self.printer = printer
self.depth = 0
self.start, self.end = 0, 0
self.cols, self.rows = 0, 0
self.preference = preference
self.previous_update = 0.0
self._state = None
self.state = "initialized"
self.style = style if style in self.styles else "fractional" # TODO: warning
# self.style = style if style in self.styles else "slider" # TODO: warning
# self.style = style if style in self.styles else list(self.styles)[-1]
self.display = display
assert self.display in ("elapsed", "eta", "rate")
@property
def state(self):
return self._state
@state.setter
def state(self, new_state):
if self._state is not None and new_state == self._state:
return # just ignore this
valid = {
"initialized": {None},
"prepared": {"initialized"},
"began": {"prepared", "progressing"},
"progressing": {"began"},
"finished": {"began"},
}
assert new_state in valid, f"unknown state {new_state}"
assert (
self._state in valid[new_state]
), f"invalid state transition from {self._state} to {new_state}"
self._state = new_state
def __len__(self):
return self.length
@property
def unfilled(self):
return extend72(self.styles[self.style]["A"], self.styling)
@property
def filled(self):
return extend72(self.styles[self.style]["B"], self.styling)
@property
def styling(self):
return self.styles[self.style].get("mode", "")
@property
def full(self):
return self.i * 72 // self.length if self.length > 0 else 72
@property
def needs_update(self):
if self.length <= 0:
return True
w = 72 * 3 if "t" in self.styling else 72 * 2 if "d" in self.styling else 72
return self.i * w // self.length != (self.i - 1) * w // self.length
@property
def elapsed(self):
now = self.end if self.state == "finished" else time.time()
return now - self.start
@property
def rate(self):
assert self.state in (
"began",
"progressing",
"finished",
), "invalid state for this"
elapsed = self.elasped
if elapsed == 0.0:
return self.bands[-1][1] # closest thing to infinity
return self.i / elapsed
@property
def eta(self):
raise NotImplementedError("TODO")
@classmethod
def format_rate(cls, rate, preference="*"):
for pref, threshold, formater in cls.bands:
if (pref == "*" or pref == preference) and rate <= threshold:
return formater(rate) + " "
return "????????" # normally unreachable (unless perhaps rate is Inf or NaN?)
@classmethod
def format_time(cls, duration, preference="*"):
o = "-" if duration < 0.0 else "+"
duration = abs(duration)
if duration < 60.0:
o += f"{max(0.0, duration - 0.005):5.2f}s "
elif duration < 3600.0:
x = int(duration)
o += f"{x // 60:2d}m{x % 60:02d}s "
elif duration < 86400.0:
x = int(duration)
o += f"{x // 3600:2d}h{x // 60 % 60:02d}m "
elif duration < 8640000.0:
x = int(duration)
o += f"{x // 86400:2d}d{x // 3600 % 24:02d}h "
else:
o += "TooLong"
return o
@property
def blurb(self): # only the first 8 characters that don't constitute the bar at all
if self.display == "rate":
return self.format_rate(self.rate, self.preference)
elif self.display == "elapsed":
return self.format_time(self.elapsed, self.preference)
elif self.display == "eta":
return self.format_time(-self.eta, self.preference)
@property
def bar(self): # the full 80 characters available in any state
if options["color"]:
color1 = "\033[7m"
color2 = "\033[m\033[1m"
color_reset = "\033[m"
else:
color1 = ""
color2 = ""
color_reset = ""
if self.state in ("began", "finished", "progressing"):
s = self.blurb
if options["color"] and "i" in self.styling:
left = self.unfilled[: self.full]
right = self.unfilled[self.full :]
if self.state == "progressing" or "p" in self.styling:
s += color1 + left + color2 + right[0]
s += color_reset + right[1:]
else:
s += color1 + left
s += color_reset + right
else:
filled = self.filled
style = self.styles[self.style]
progressing = self.state == "progressing" or "p" in self.styling
t = (filled[-1], style["A"][-1], style["B"][-1])
if "t" in self.styling and self.length > 0:
triple = self.i * 72 * 3 // self.length
filled = filled[:-1] + t[triple % 3]
elif "d" in self.styling and self.length > 0:
double = self.i * 72 * 2 // self.length
filled = filled[:-1] + t[double % 2 + 1]
elif "a" in self.styling and self.length > 0:
filled = filled[:-1] + t[self.full % 2 + 1]
s += color2
if progressing:
if "r" in self.styling:
s += filled[-self.full - 1 :]
elif "P" in self.styling:
s += filled[: self.full + 1]
else:
s += filled[: self.full] + filled[-1]
s += color_reset + self.unfilled[self.full + 1 :]
else:
if "r" in self.styling and self.full > 0:
s += filled[-self.full :]
else:
s += filled[: self.full]
s += color_reset + self.unfilled[self.full :]
elif self.state == "prepared":
s = "Ready..." + " " * 72
else:
s = "watdafuk" + "?" * 72
# assert len(s) == 80 + len(color2) + len(color_reset), (self.full, self.state, repr(s))
return s
@property
def row(self):
assert self.state in ("began", "progressing"), "invalid state for this"
return self.rows - allocated + self.depth
def __iter__(self):
# TODO: check env-var override for disabling and colors!
if self.length == 0:
return self.it
if self.i == 0:
self.begin()
for x in self.it:
self.progress(False)
yield x
self.progress(True)
self.progressing = False
self.finish()
# TODO: is there a case where i actually need this?
# def __next__(self):
# pass
def prepare(self):
self.state = "prepared"
return self
def begin(self):
global allocated
self.start = time.time()
assert self not in active, "what"
active.append(self)
self.depth = len(active)
(_cols, _rows) = get_terminal_size()
# propagate terminal size to parents (and self) in case it has since changed:
for pb in active:
pb.cols, pb.rows = _cols, _rows
# TODO: this should be handleable in most cases; hide the top bars for a while.
# need at least 1 blank line for regular output (or just for the cursor to sit)
# i guess just act as though only a subset of `active` are active for a while?
assert self.rows - 1 > self.depth, "ran out of space for progress bars"
s = alloc(self.depth) # TODO: only do this as necessary? (based on allocated)
# keep track of how many lines are available for progress bars.
newly = len(active) - allocated if len(active) > allocated else 0
# TODO: allow the user to allocate many at once.
allocated += newly
self.state = "began"
s += "\0337"
if 1:
for pb in active:
# TODO: respect 30 fps timers?
s += f"\033[{pb.row};1H\033[K{pb.bar}"
else: # this isn't as flexible, but it works...?
# FIXME: progress() is still broken!
for pb in active:
s += f"\n\033[K{pb.bar}"
# prevent the user from accidentally printing over the progress bars.
s += f"\033[1;{self.rows - allocated}r"
s += "\0338" # finally, return to the user's (properly adjusted) line and column.
self.printer(end=s)
# time.sleep(2); exit()
if DEBUG:
print(repr(s).replace("\\x1b", "\\033"))
time.sleep(0.5)
def progress(self, finishing=False):
if finishing:
self.i += 1
self.state = "began"
else:
self.state = "progressing"
if not options["patient"] or self.needs_update:
now = time.time()
if now >= self.previous_update + 0.03333333333333333: # limit to 30 fps
self.previous_update = now
s = f"\0337\033[{self.row};1H\033[K{self.bar}\0338"
self.printer(end=s)
def finish(self):
global allocated
self.end = time.time()
row = self.row # we need this before we transition states
assert self.depth == len(active) and active[-1] is self, "what"
active.pop()
self.state = "finished"
s = ""
if len(active) == 0:
s += "\0337\033[J\033[r\0338"
allocated = 0
else:
s += f"\0337\033[{row};1H\033[K\0338"
self.printer(end=s)
def prog(it, *, file=sys.stderr, pref="*"):
def printy(*args, **kwargs):
# print(repr(kwargs.get("end", "?").replace("\\x1b", "\\033")))
# time.sleep(2.5)
print(*args, **kwargs, file=file, flush=options["flush"])
# time.sleep(2.5)
try:
l = len(it)
except TypeError:
raise TypeError("prog(iterator) only works with iterators with a known length")
return Prog80(it, l, printer=printy, preference=pref).prepare()

41
project.py Normal file
View File

@ -0,0 +1,41 @@
import numpy as np
#def project(a, b): # projects b onto the unit cube, using a as an offset origin
# a = np.asanyarray(a)
# b = np.asanyarray(b)
# d = b - a
# if all(np.abs(d) <= 1e-8):
# return a
# inner = -1 / np.where(np.abs(d) > 1e-8, d, np.where(d >= 0, 1e-8, -1e-8))
# small = np.minimum(1 - a, a - 1)
# large = np.maximum(0 - a, a - 0)
# rescale = np.min(np.maximum(inner * small, inner * large))
# assert np.isfinite(rescale), rescale
# if rescale < 1:
# return a + (rescale - 1e-6) * d
# else:
# return b
def project(p, a, eps=1e-8):
# https://www.desmos.com/calculator/gdcu0ivk0i
p = np.asanyarray(p)
a = np.asanyarray(a)
d = p - a
if all(np.abs(d) <= eps):
# we might still be inching out of bounds, so just to be sure:
a[a <= 0] = 0
a[a >= 1] = 1
return a
inner = 1 / np.where(np.abs(d) > eps, d, np.where(d >= 0, eps, -eps))
small = -np.abs(p - 1) # np.minimum(1 - p, p - 1)
large = np.abs(p) # np.maximum(0 - p, p - 0)
rescale = np.min(np.maximum(inner * small, inner * large))
if rescale <= 1:
b = p - max(0, rescale - 1e-8) * d
return b
else:
return a

35
randomcube2.py Normal file
View File

@ -0,0 +1,35 @@
from utils import phi
import numpy as np
def another_random_cube(objective, n_trials, n_dim, with_count, seed=None):
prng = np.random.default_rng(seed)
fopt = None
xopt = None
for i in range(n_trials):
x = prng.uniform(size=n_dim)
fx = objective(x)
if fopt is None or xopt is None or fx < fopt:
fopt = fx
xopt = x
return (fopt, xopt, n_trials) if with_count else (fopt, xopt)
def quasirandom_cube(objective, n_trials, n_dim, with_count):
# http://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/
magic = phi(n_dim)
alpha = np.zeros(n_dim)
for i in range(n_dim):
alpha[i] = pow(1 / magic, i + 1) % 1
xs = np.zeros((n_trials, n_dim))
xs[0, :] = 0.5 # first point is always dead center
for i in range(1, n_trials):
xs[i] = (xs[i - 1] + alpha) % 1
best_so_far = None
for i, x in zip(range(n_trials), xs):
fx = objective(x)
if best_so_far is None or fx < best_so_far[0]:
best_so_far = (fx, x)
fopt, xopt = best_so_far
return (fopt, xopt, n_trials) if with_count else (fopt, xopt)

485
solutions_1680721604.py Normal file
View File

@ -0,0 +1,485 @@
solutions = {
"go_ackley01_on_cube__2": {
4.440892098500626e-16: [0.5000000000012516, 0.5000000000009395],
},
"go_ackley02_on_cube__2": {
-200.0: [0.5, 0.5],
},
"go_ackley03_on_cube__2": {
-195.62902826227938: [0.4893347317380225, 0.4943640332293448],
},
"go_adjiman_on_cube__2": {
-2.0218067833597875: [0.9999999999999714, 0.5528917033764795],
},
"go_alpine01_on_cube__2": {
0.0: [0.5, 0.9762267885778328],
},
"go_alpine02_on_cube__2": {
-6.129503891130689: [0.4815842302257306, 0.7917052693161503],
},
"go_amgm_on_cube__2": {
0.0: [0.14528557476989837, 0.14528557476989837],
},
"go_bartelsconn_on_cube__2": {
1.0: [0.5, 0.5],
},
"go_beale_on_cube__2": {
0.0: [0.8333333333333334, 0.5555555555555556],
},
"go_biggsexp02_on_cube__2": {
0.0: [0.05017234270730255, 0.5018173197656695],
},
"go_bird_on_cube__2": {
-106.76453674926478: [0.3739033841634505, 0.2508203315071311],
},
"go_bohachevsky1_on_cube__2": {
0.0: [0.440593060336285, 0.5625000000000355],
},
"go_bohachevsky2_on_cube__2": {
0.0: [0.5, 0.5],
},
"go_bohachevsky3_on_cube__2": {
0.0: [0.5, 0.0371852048138242],
},
"go_branin01_on_cube__2": {
0.39788735772973816: [0.12094130784112306, 0.8309013410017676],
},
"go_branin02_on_cube__2": {
5.558914403893816: [0.09015057853516895, 0.8763128943301511],
},
"go_brent_on_cube__2": {
1.3838965267367376e-87: [0.00014895223910016858, 0.00021530390524300317],
},
"go_brown_on_cube__2": {
0.0: [0.20000000000000023, 0.20000000000000012],
},
"go_bukin02_on_cube__2": {
-124.75: [0.14238611093033351, 0.5000000018001576],
},
"go_bukin04_on_cube__2": {
0.0: [0.5, 0.5],
},
"go_bukin06_on_cube__2": {
5.865983528536844e-06: [0.5, 0.5],
},
"go_carromtable_on_cube__2": {
-24.156815547391254: [0.017691616522249504, 0.9823083834798857],
},
"go_chichinadze_on_cube__2": {
-42.94438701899099: [0.6035311135612936, 0.5097635900809587],
},
"go_cigar_on_cube__2": {
0.0: [0.5000000000000002, 0.5],
},
"go_cosinemixture_on_cube__2": {
-1.8: [0.75, 0.75],
},
"go_crossintray_on_cube__2": {
-2.0626118708227397: [0.4325296712598773, 0.43252966716129265],
},
"go_crosslegtable_on_cube__2": {
-1.0: [0.0019232616287467377, 0.501953125],
},
"go_crownedcross_on_cube__2": {
0.0001: [0.3218787362308007, 0.308124995755209],
},
"go_csendes_on_cube__2": {
1.0670199460593143e-95: [0.49999999999999994, 0.49999999999999994],
},
"go_cube_on_cube__2": {
0.0: [0.5499999821185895, 0.5499999821185895],
},
"go_damavandi_on_cube__2": {
-8.548717318273045e-14: [0.14285714236851058, 0.5],
},
"go_deb01_on_cube__2": {
-1.0: [0.7499990498894216, 0.7499999657093407],
},
"go_deb03_on_cube__2": {
-1.0: [0.07969939247253323, 0.07969939211843553],
},
"go_decanomial_on_cube__2": {
0.0: [0.5999969620477643, 0.5999969620477643],
},
"go_deceptive_on_cube__2": {
-1.0: [0.3333395662049635, 0.6666666666666666],
},
"go_deckkersaarts_on_cube__2": {
-24776.518342317697: [0.49999422157482337, 0.8633377885933347],
},
"go_deflectedcorrugatedspring_on_cube__2": {
-1.0: [0.5000000000382508, 0.5000000001114326],
},
"go_dixonprice_on_cube__2": {
2.465190328815662e-30: [0.5500000000000005, 0.5353553390593274],
},
"go_dropwave_on_cube__2": {
-1.0: [0.4999999999807786, 0.50000000007422],
},
"go_easom_on_cube__2": {
-1.0: [0.5157064122321219, 0.5157064122321219],
},
"go_eggcrate_on_cube__2": {
0.0: [0.18428181626851456, 0.18428181626851456],
},
"go_eggholder_on_cube__2": {
-959.6406627208506: [1.0, 0.894767898730016],
},
"go_elattarvidyasagardutta_on_cube__2": {
1.7127803548621996: [0.5170459341098588, 0.48914283482200543],
},
"go_exp2_on_cube__2": {
3.918816046997309e-33: [0.050000088297583685, 0.5000007180480729],
},
"go_exponential_on_cube__2": {
-1.0: [0.5000000013789645, 0.500000001379979],
},
"go_freudensteinroth_on_cube__2": {
0.0: [0.75, 0.7],
},
"go_giunta_on_cube__2": {
0.06447042053690555: [0.2164719678737906, 0.2164719678737906],
},
"go_goldsteinprice_on_cube__2": {
2.999999999999936: [0.5000000000134474, 0.25000000003431383],
},
"go_griewank_on_cube__2": {
0.0: [0.4999999959578959, 0.4999999959578959],
},
"go_hansen_on_cube__2": {
-176.54179313674572: [0.4346646143793226, 0.1760714471446315],
},
"go_himmelblau_on_cube__2": {
0.0: [0.8000000005441553, 0.699999998930247],
},
"go_holdertable_on_cube__2": {
-19.208502567886757: [0.9027539594713605, 0.9832285117561048],
},
"go_hosaki_on_cube__2": {
-2.3458115761013154: [0.8000000052198215, 0.33333333377951074],
},
"go_infinity_on_cube__2": {
1.0670199460593143e-95: [0.500000000000078, 0.5000000000000799],
},
"go_jennrichsampson_on_cube__2": {
124.36218235561478: [0.628912606360244, 0.628912607266392],
},
"go_judge_on_cube__2": {
16.08173013296038: [0.5432393693433495, 0.5617874256124593],
},
"go_katsuura_on_cube__2": {
1.0: [1.0465968369732792e-12, 5.32695415556006e-13],
},
"go_keane_on_cube__2": {
0.0: [0.37101044225030444, 0.37101044225030444],
},
"go_langermann_on_cube__2": {
-5.162126159963984: [0.4247007879960495, 0.5243904060958999],
},
"go_leon_on_cube__2": {
4.979684464207637e-30: [0.5142395223724617, 0.5003219683645784],
},
"go_levy03_on_cube__2": {
1.4997597826618576e-32: [0.55, 0.55],
},
"go_levy05_on_cube__2": {
-176.1375780016295: [0.43465734957884006, 0.42875774788733895],
},
"go_levy13_on_cube__2": {
1.3497838043956716e-31: [0.5500150851792615, 0.5588857050847033],
},
"go_matyas_on_cube__2": {
0.0: [0.5, 0.5],
},
"go_mccormick_on_cube__2": {
-1.9132229549810367: [0.18464510306427817, 0.2463861846869465],
},
"go_michalewicz_on_cube__2": {
-1.8013034100985537: [0.9442092427714985, 0.137930239782405],
},
"go_mishra01_on_cube__2": {
1.9999999976137055: [1.0, 0.45651381229089155],
},
"go_mishra02_on_cube__2": {
1.9999999976137055: [0.9999998753782375, 0.9999999999988338],
},
"go_mishra03_on_cube__2": {
-0.19992970874179772: [0.00017566064782963478, 0.00017567826653813387],
},
"go_mishra04_on_cube__2": {
-0.17771527939061962: [0.055900292323033035, 0.0555232000601078],
},
"go_mishra05_on_cube__2": {
-1.0198295199309433: [0.4496859216030812, 5.052677111002609e-14],
},
"go_mishra06_on_cube__2": {
-2.283949838474759: [0.6443153606209077, 0.5911630166051212],
},
"go_mishra07_on_cube__2": {
0.0: [0.34609320629638907, 0.491495756043251],
},
"go_mishra08_on_cube__2": {
0.0: [0.6, 0.4999999999999505],
},
"go_mishra10_on_cube__2": {
0.0: [0.5624973533886062, 0.4448689469647824],
},
"go_mishra11_on_cube__2": {
0.0: [0.3864490164718726, 0.6606615057516221],
},
"go_multimodal_on_cube__2": {
0.0: [0.2580651476136024, 0.5],
},
"go_needleeye_on_cube__2": {
1.0: [0.5000029697574638, 0.4999988242523547],
},
"go_newfunction01_on_cube__2": {
-0.18466699349665727: [0.0766649450293288, 3.8163916471489756e-17],
},
"go_newfunction02_on_cube__2": {
-0.19941146890593808: [0.0029425599479900697, 6.269061894428091e-09],
},
"go_oddsquare_on_cube__2": {
-1.0084672811394724: [0.5293830040843023, 0.54382826973797],
},
"go_parsopoulos_on_cube__2": {
3.374459510989179e-32: [0.9712388980384691, 0.5],
},
"go_pathological_on_cube__2": {
0.0: [0.49999999999760364, 0.5000000000214441],
},
"go_penalty01_on_cube__2": {
1.570544771786639e-32: [0.48999999999999994, 0.49],
},
"go_penalty02_on_cube__2": {
1.3497838043956716e-31: [0.51, 0.51],
},
"go_penholder_on_cube__2": {
-0.9635348327265058: [0.9401864564627503, 0.9386821449166709],
},
"go_permfunction01_on_cube__2": {
0.0: [0.7519531250381614, 0.6152343749994894],
},
"go_permfunction02_on_cube__2": {
7.099748146989106e-30: [0.578293852394686, 0.5282223006004134],
},
"go_pinter_on_cube__2": {
0.0: [0.49958445065499896, 0.49910744487758496],
},
"go_plateau_on_cube__2": {
30.0: [0.572454495541009, 0.56229500763676],
},
"go_price01_on_cube__2": {
0.0: [0.25499999999999995, 0.745],
},
"go_price02_on_cube__2": {
0.9: [0.4999999996935737, 0.5000000001302558],
},
"go_price03_on_cube__2": {
1.232595164407831e-32: [0.6, 0.5999999999999999],
},
"go_price04_on_cube__2": {
0.0: [0.5000799946500851, 0.49956191788571896],
},
"go_qing_on_cube__2": {
1.050959940980693e-27: [0.499, 0.4985857864376269],
},
"go_quadratic_on_cube__2": {
-3873.7241821862717: [0.5095015478153164, 0.5241747012576643],
},
"go_quintic_on_cube__2": {
0.0: [0.47986860294069383, 0.4798679708433461],
},
"go_rana_on_cube__2": {
-500.80216100356625: [1.0, 0.7236207232318757],
},
"go_rastrigin_on_cube__2": {
0.0: [0.5715218344919186, 0.5511489887028654],
},
"go_ripple01_on_cube__2": {
-2.2: [0.09922161610301354, 0.10142343315723641],
},
"go_ripple25_on_cube__2": {
-2.0: [0.08254001808623358, 0.08702649220076682],
},
"go_rosenbrock_on_cube__2": {
1.135959703518257e-28: [0.5166666666666668, 0.4947701574224009],
},
"go_rosenbrockmodified_on_cube__2": {
34.0402431066405: [0.2726115657051843, 0.26235707188727275],
},
"go_rotatedellipse01_on_cube__2": {
0.0: [0.498801015711877, 0.498801015711877],
},
"go_rotatedellipse02_on_cube__2": {
0.0: [0.5, 0.5],
},
"go_salomon_on_cube__2": {
0.0: [0.5, 0.500000000003638],
},
"go_sargan_on_cube__2": {
0.0: [0.49999999999999994, 0.5],
},
"go_schaffer01_on_cube__2": {
0.0: [0.49999999999999634, 0.49999999999999634],
},
"go_schaffer02_on_cube__2": {
0.0: [0.4999999981621386, 0.4999999986347427],
},
"go_schaffer03_on_cube__2": {
0.001566854526003969: [0.5000000000002823, 0.5035528201669792],
},
"go_schaffer04_on_cube__2": {
0.29257863203598033: [0.5000013136163499, 0.4937343165448773],
},
"go_schwefel01_on_cube__2": {
0.0: [0.5, 0.4999999998835847],
},
"go_schwefel02_on_cube__2": {
0.0: [0.5, 0.5],
},
"go_schwefel04_on_cube__2": {
0.0: [0.1020808914860876, 0.1020808914860876],
},
"go_schwefel06_on_cube__2": {
0.0: [0.505, 0.5150000000000001],
},
"go_schwefel20_on_cube__2": {
0.0: [0.12205247389109272, 0.12205247389109272],
},
"go_schwefel21_on_cube__2": {
0.0: [0.6166298780113924, 0.7130508226020703],
},
"go_schwefel22_on_cube__2": {
0.0: [0.5, 0.49609363079071045],
},
"go_schwefel26_on_cube__2": {
-5.448675892694155e-07: [0.9209687462455439, 0.9209687459329059],
},
"go_schwefel36_on_cube__2": {
-3456.000000000001: [0.024000000147307608, 0.49162499998238574],
},
"go_shubert01_on_cube__2": {
-186.73090883102398: [0.7429028439177817, 0.1458246796260435],
},
"go_shubert03_on_cube__2": {
-24.062498884334293: [0.7895897235076741, 0.7895897236028214],
},
"go_shubert04_on_cube__2": {
-29.016015854390076: [0.14821760462818873, 0.22311218016348278],
},
"go_sineenvelope_on_cube__2": {
0.0: [0.4596149239853102, 0.5030264073322085],
},
"go_sixhumpcamel_on_cube__2": {
-1.0316284534898774: [0.8412902456484702, 0.3984249755872633],
},
"go_sodp_on_cube__2": {
0.0: [0.4999999298520932, 0.4949623459343995],
},
"go_sphere_on_cube__2": {
0.0: [0.5, 0.5],
},
"go_step2_on_cube__2": {
0.5: [0.4962750387667936, 0.4979955154520701],
},
"go_step_on_cube__2": {
0.0: [0.49741917962545434, 0.49952460080066174],
},
"go_stochastic_on_cube__2": {
0.0: [0.5999973641998414, 0.5000000044703483],
},
"go_stretchedv_on_cube__2": {
0.0: [0.23227978992486353, 0.5003909127586422],
},
"go_styblinskitang_on_cube__2": {
-78.33233140754285: [0.2096465967930618, 0.20964659707425057],
},
"go_testtubeholder_on_cube__2": {
-10.872300105622747: [0.4050972481936185, 0.4050972481936185],
},
"go_threehumpcamel_on_cube__2": {
0.0: [0.4999999884956858, 0.500000025238776],
},
"go_treccani_on_cube__2": {
0.0: [0.5000000005096527, 0.49999998234850795],
},
"go_trefethen_on_cube__2": {
-3.3068686474752407: [0.4987798460133582, 0.5105306213572468],
},
"go_trigonometric01_on_cube__2": {
0.0: [0.0, 3.469446951953614e-18],
},
"go_trigonometric02_on_cube__2": {
1.0: [0.5002303123236185, 0.5008999999854868],
},
"go_tripod_on_cube__2": {
0.0: [0.5, 0.25],
},
"go_ursem01_on_cube__2": {
-4.816814063734823: [0.7631157194886242, 0.4999999991819998],
},
"go_ursem03_on_cube__2": {
-3.0: [0.49999999999894734, 0.5064942023957556],
},
"go_ursem04_on_cube__2": {
-1.5: [0.49999999999999994, 0.49999999999999994],
},
"go_ursemwaves_on_cube__2": {
-8.553600000000005: [1.0, 1.0],
},
"go_ventersobiezcczanskisobieski_on_cube__2": {
-400.0: [0.4999999999691136, 0.5000000000649738],
},
"go_vincent_on_cube__2": {
-2.0: [0.7647463840583177, 0.7647463860955502],
},
"go_wavy_on_cube__2": {
0.0: [0.5990111627305801, 0.7166822395492828],
},
"go_wayburnseader01_on_cube__2": {
3.865418435582958e-29: [0.5931930653112957, 0.701088291102508],
},
"go_wayburnseader02_on_cube__2": {
1.1093356479670479e-27: [0.5002001389746917, 0.5009999999999929],
},
"go_weierstrass_on_cube__2": {
0.0: [0.48388671875000094, 0.4838867187500006],
},
"go_whitley_on_cube__2": {
0.0: [0.5004834467831857, 0.39297526505649716],
},
"go_xinsheyang01_on_cube__2": {
0.0: [0.49919291830153395, 0.49919291830153395],
},
"go_xinsheyang02_on_cube__2": {
0.0: [0.5000000000002875, 0.4999999999999388],
},
"go_xinsheyang03_on_cube__2": {
-1.0: [0.4999999986162714, 0.5000000059276509],
},
"go_xinsheyang04_on_cube__2": {
-1.0: [0.49999999999999967, 0.4999999892774735],
},
"go_yaoliu04_on_cube__2": {
0.0: [0.5000000035524891, 0.5000000035524891],
},
"go_yaoliu09_on_cube__2": {
0.0: [0.4999999999409883, 0.4999999999993396],
},
"go_zacharov_on_cube__2": {
0.0: [0.3333333333333333, 0.3333333333333333],
},
"go_zerosum_on_cube__2": {
0.0: [0.24019956025564648, 0.7597811926967968],
},
"go_zettl_on_cube__2": {
-0.0037912372204688986: [0.3313423297689443, 0.3329125985152123],
},
"go_zimmerman_on_cube__2": {
8.881784197001252e-16: [0.024979873370145907, 0.05681725730945934],
},
"go_zirilli_on_cube__2": {
-0.3523860738000365: [0.44782232329859883, 0.5004437701361232],
},
}

242
solutions_1680730206.py Normal file
View File

@ -0,0 +1,242 @@
solutions = {
"go_ackley01_on_cube__3": {
4.440892098500626e-16: [0.5, 0.5, 0.5],
},
"go_alpine01_on_cube__3": {
0.0: [0.49999999999999956, 0.5000000000000002, 0.5000000000000012],
},
"go_alpine02_on_cube__3": {
-17.212450994658354: [0.7917052684142234, 0.7917052676939672, 0.4815842307193425],
},
"go_amgm_on_cube__3": {
0.0: [0.8245598718496522, 0.8245598800645785, 0.8245598774911281],
},
"go_biggsexp03_on_cube__3": {
0.0: [0.05, 0.5, 0.24999999999999997],
},
"go_boxbetts_on_cube__3": {
0.0: [0.3333333333333335, 0.454545454545454, 0.3333333333333334],
},
"go_brown_on_cube__3": {
0.0: [0.20000001930221908, 0.19999995251347022, 0.19999929921954904],
},
"go_cigar_on_cube__3": {
0.0: [0.5950381095427524, 0.5950381095427524, 0.5950381095427524],
},
"go_cosinemixture_on_cube__3": {
-2.7: [3.659195132255668e-06, 1.5076273613395665e-11, 9.543896963247637e-16],
},
"go_csendes_on_cube__3": {
1.6005299190889717e-95: [0.5000002614943283, 0.49999979737945727, 0.4999991373845789],
},
"go_deb01_on_cube__3": {
-1.0: [0.049649550146846286, 0.05000289851470013, 0.05006420897463226],
},
"go_deb03_on_cube__3": {
-1.0: [0.8488416211971612, 0.8488416208778257, 0.8488416211316454],
},
"go_deceptive_on_cube__3": {
-1.0: [0.7499999999714193, 0.7499999999714193, 0.7499999999714193],
},
"go_deflectedcorrugatedspring_on_cube__3": {
-1.0: [0.5000000007403892, 0.5000000012200565, 0.49999999741084855],
},
"go_dixonprice_on_cube__3": {
1.1931521191467804e-29: [0.55, 0.5353553390593274, 0.470269822124932],
},
"go_eckerle4_on_cube__3": {
0.0014635887487274677: [0.08717603638237367, 0.22786082165419722, 0.7482996827664747],
},
"go_eggholder_on_cube__3": {
-1888.321390893595: [0.970181519670115, 0.9266961632465174, 0.9411871032839637],
},
"go_exponential_on_cube__3": {
-1.0: [0.5003591836784682, 0.500348485292889, 0.5001780115493856],
},
"go_griewank_on_cube__3": {
0.0: [0.5000000000113756, 0.5000000000565452, 0.4999999999274707],
},
"go_gulf_on_cube__3": {
5.915132712320822e-31: [0.1348208391857785, 0.5, 0.03],
},
"go_hartmann3_on_cube__3": {
-3.862782147820756: [0.11461434502192798, 0.5556488498282574, 0.8525469537098168],
},
"go_helicalvalley_on_cube__3": {
0.0: [0.5497725561310041, 0.5048351824540244, 0.5076838383564906],
},
"go_infinity_on_cube__3": {
1.6005299190889717e-95: [0.4999999715839852, 0.5000000247025426, 0.5000000016223345],
},
"go_katsuura_on_cube__3": {
1.0: [5.679137715652871e-14, 6.262039498050598e-13, 5.512708345367656e-13],
},
"go_meyer_on_cube__3": {
3718453685.016923: [0.9999999999999996, 0.9999999999999999, 3.122502256758253e-17],
},
"go_mishra01_on_cube__3": {
1.9999999952274108: [1.0, 0.9999999999999999, 0.009829734043015896],
},
"go_mishra02_on_cube__3": {
1.9999999952274108: [0.9999999999999993, 1.0, 0.9999999999999998],
},
"go_mishra07_on_cube__3": {
0.0: [0.5240408900442571, 0.5079805506782411, 0.6569953605954606],
},
"go_mishra09_on_cube__3": {
0.0: [0.5537573946909716, 0.6002010732109465, 0.6409128191691206],
},
"go_mishra11_on_cube__3": {
0.0: [0.5, 0.5, 0.5],
},
"go_multimodal_on_cube__3": {
0.0: [0.5022237648504779, 0.49970052009979826, 0.5005325922218133],
},
"go_needleeye_on_cube__3": {
1.0: [0.39961640034876017, 0.39961640034876017, 0.39961640034875184],
},
"go_penalty01_on_cube__3": {
1.570544771786639e-32: [0.49, 0.49, 0.49000000000000005],
},
"go_penalty02_on_cube__3": {
1.3497838043956716e-31: [0.5133271718479692, 0.5062564318780072, 0.5146267812010901],
},
"go_permfunction01_on_cube__3": {
9.860761315262648e-31: [0.640860903825709, 0.01929983613560043, 0.6044294128164022],
},
"go_permfunction02_on_cube__3": {
2.2186712959340957e-30: [0.5714578794300258, 0.47532015480578127, 0.49894707267621674],
},
"go_pinter_on_cube__3": {
0.0: [0.5, 0.5, 0.5],
},
"go_plateau_on_cube__3": {
30.0: [0.4046704030611626, 0.4976189802302213, 0.3543757372858257],
},
"go_qing_on_cube__3": {
5.3707622579709536e-27: [0.501, 0.4985857864376269, 0.5017320508075689],
},
"go_quadratic_on_cube__3": {
-3873.7241821862717: [0.5096940087870239, 0.5242566945952262, 0.29760349466562863],
},
"go_quintic_on_cube__3": {
0.0: [0.44999999999999996, 0.60941162109375, 0.45],
},
"go_rana_on_cube__3": {
-998.9595261322422: [4.150441195255471e-09, 0.0009301076431260141, 0.0019640025818469242],
},
"go_rastrigin_on_cube__3": {
0.0: [0.4999999997679357, 0.49999999993791394, 0.4999999999832573],
},
"go_ratkowsky02_on_cube__3": {
8.056522933811229: [0.3289191890500581, 0.4706837418911737, 0.1170595919922324],
},
"go_rosenbrock_on_cube__3": {
5.679798517591285e-28: [0.4991978266453091, 0.5000882128754777, 0.4938730426361304],
},
"go_salomon_on_cube__3": {
0.0: [0.49999999999999994, 0.5000000000000001, 0.5],
},
"go_sargan_on_cube__3": {
0.0: [0.4890611845448031, 0.5152469505181654, 0.4890831221795244],
},
"go_schwefel01_on_cube__3": {
0.0: [0.5000000000000001, 0.5, 0.5],
},
"go_schwefel02_on_cube__3": {
0.0: [0.515625, 0.12989525470348404, 0.5],
},
"go_schwefel04_on_cube__3": {
0.0: [0.3928252864281473, 0.3928252864281473, 0.39282528642814735],
},
"go_schwefel20_on_cube__3": {
0.0: [0.5, 0.5, 0.5],
},
"go_schwefel21_on_cube__3": {
0.0: [0.5, 0.49999999999999994, 0.5],
},
"go_schwefel22_on_cube__3": {
0.0: [0.49999998835820214, 0.49999999999999994, 0.49999999999999956],
},
"go_schwefel26_on_cube__3": {
-8.173014975909609e-07: [0.9204820116767811, 0.9204820113041389, 0.9204820116767811],
},
"go_shubert01_on_cube__3": {
-2709.093505572829: [0.44022055084214423, 0.7741432103584681, 0.7429028439073201],
},
"go_shubert03_on_cube__3": {
-36.09374832650144: [0.7895348359272809, 0.9397543606957739, 0.7896478307580592],
},
"go_shubert04_on_cube__3": {
-43.524023781585115: [0.6640013808576284, 0.14582468028277795, 0.7741432091030084],
},
"go_sineenvelope_on_cube__3": {
0.0: [0.5000009025942251, 0.500000893069357, 0.5000003811955986],
},
"go_sodp_on_cube__3": {
0.0: [0.5, 0.5, 0.5],
},
"go_sphere_on_cube__3": {
0.0: [0.4833130709800822, 0.4833130709800822, 0.4833130709800822],
},
"go_step2_on_cube__3": {
0.75: [0.5016868928445066, 0.5061703854573943, 0.5026760176613241],
},
"go_step_on_cube__3": {
0.0: [0.5081581595102049, 0.49675129077493513, 0.5079476141696376],
},
"go_stochastic_on_cube__3": {
1.5938474175637294e-22: [0.5333327585272383, 0.5333327585272383, 0.5499994072312144],
},
"go_stretchedv_on_cube__3": {
0.0: [0.2500000000000284, 0.24999999999997158, 0.2500000000000284],
},
"go_styblinskitang_on_cube__3": {
-117.49849711131428: [0.2096465969993631, 0.2096465972561869, 0.20964659614351272],
},
"go_trigonometric01_on_cube__3": {
0.0: [1.3877787807814457e-17, 6.938893903907228e-18, 0.0],
},
"go_trigonometric02_on_cube__3": {
1.0: [0.5008999999918231, 0.5008999999997376, 0.5008999999924959],
},
"go_vincent_on_cube__3": {
-3.0: [0.6708629450200313, 0.7647463865513029, 0.7647158663337039],
},
"go_wavy_on_cube__3": {
0.0: [0.499999999997531, 0.5000000000621029, 0.5000000003640678],
},
"go_weierstrass_on_cube__3": {
0.0: [0.4999961853027344, 0.49999999999999967, 0.49999999999999967],
},
"go_whitley_on_cube__3": {
0.0: [0.0057694254008727915, 0.9614112930973773, 0.13985557238051557],
},
"go_wolfe_on_cube__3": {
0.0: [0.0, 0.0, 0.0],
},
"go_xinsheyang01_on_cube__3": {
0.0: [0.5, 0.5, 0.5],
},
"go_xinsheyang02_on_cube__3": {
0.0: [0.5, 0.5, 0.5],
},
"go_xinsheyang03_on_cube__3": {
-1.0: [0.49999999997731115, 0.5000000000034495, 0.49999999998913747],
},
"go_xinsheyang04_on_cube__3": {
-1.0: [0.3429203670388802, 0.6570796326524454, 0.3429203673085393],
},
"go_yaoliu04_on_cube__3": {
0.0: [0.5, 0.5, 0.5],
},
"go_yaoliu09_on_cube__3": {
0.0: [0.5000000000269273, 0.4999999999491878, 0.49999999989083205],
},
"go_zacharov_on_cube__3": {
0.0: [0.3333333333333333, 0.3333333333333333, 0.3333333333333333],
},
"go_zerosum_on_cube__3": {
0.0: [0.4999999775192155, 0.5, 0.5],
},
}

251
solutions_1680975848.py Normal file
View File

@ -0,0 +1,251 @@
solutions = {
"go_ackley01_on_cube__4": {
4.440892098500626e-16: [0.5, 0.5, 0.5, 0.5],
},
"go_alpine01_on_cube__4": {
0.0: [0.4952297200093428, 0.4952297200093428, 0.4952297200093428, 0.4952297200093428],
},
"go_alpine02_on_cube__4": {
-48.33482032244272: [0.7917052678377633, 0.7917052674957755, 0.48158423270992656, 0.7917052673588358],
},
"go_amgm_on_cube__4": {
0.0: [0.012306988086844196, 0.012306988086844196, 0.012306988086844196, 0.012306988086844196],
},
"go_biggsexp04_on_cube__4": {
0.0: [0.04996029633691984, 0.04996029633691984, 0.24980148168459912, 0.24980148168459912],
},
"go_brown_on_cube__4": {
0.0: [0.19999999999999812, 0.2000000000000008, 0.20000000000000118, 0.20000000000000062],
},
"go_cigar_on_cube__4": {
0.0: [0.5, 0.5, 0.5, 0.5],
},
"go_colville_on_cube__4": {
0.0: [0.5499999999999998, 0.5500000000000002, 0.5500000000000005, 0.5500000000000003],
},
"go_corana_on_cube__4": {
0.0: [0.16514354301841233, 0.5037790090306642, 0.5812655986635484, 0.9965260213661287],
},
"go_cosinemixture_on_cube__4": {
-3.6: [1.0, 1.0, 1.0, 1.0],
},
"go_csendes_on_cube__4": {
2.1340398921186287e-95: [0.49999999999999994, 0.49999999999999994, 0.49999999999999994, 0.49999999999999994],
},
"go_deb01_on_cube__4": {
-1.0: [0.24998474166810553, 0.2842827054985171, 0.250000000494007, 0.24517076362726262],
},
"go_deb03_on_cube__4": {
-1.0: [0.6814202220739899, 0.6814202214962974, 0.6814202217045495, 0.6814202224584512],
},
"go_deceptive_on_cube__4": {
-1.0: [0.12504729371493664, 0.4, 0.6, 0.8],
},
"go_deflectedcorrugatedspring_on_cube__4": {
-1.0: [0.5293413782227367, 0.4718024985689048, 0.434224546444892, 0.4705267221389782],
},
"go_devilliersglasser01_on_cube__4": {
1.1781353629549932e-24: [0.643599554903393, 0.003164412438938837, 0.021191388101335643, 0.7694639665621702],
},
"go_dixonprice_on_cube__4": {
2.0362472116017367e-29: [0.55, 0.5353553390593274, 0.529730177875068, 0.5272626933166314],
},
"go_eggholder_on_cube__4": {
-2808.1847921823232: [0.9711233598527298, 0.9228135061716958, 0.936490209590872, 0.9652220933524724],
},
"go_exponential_on_cube__4": {
-1.0: [0.5000000247218881, 0.49999998767538123, 0.49999998303134136, 0.5000000097075422],
},
"go_gear_on_cube__4": {
2.7008571488865134e-12: [0.09051675206121865, 0.15129928153389963, 0.6492028326465633, 0.7748019437203442],
},
"go_griewank_on_cube__4": {
0.0: [0.499999999976616, 0.4999999999392863, 0.49999999996604166, 0.4999999988626738],
},
"go_infinity_on_cube__4": {
2.1340398921186287e-95: [0.49804687500000006, 0.49804687500000006, 0.5019531249999999, 0.49804687500000006],
},
"go_katsuura_on_cube__4": {
1.0: [2.646355357072139e-13, 3.995866137973536e-13, 8.982398158607907e-14, 5.381459167175251e-14],
},
"go_kowalik_on_cube__4": {
0.00030748598780560557: [0.5308380971332559, 0.6379070854704445, 0.7895950761936558, 0.5868729032688482],
},
"go_mielecantrell_on_cube__4": {
0.0: [0.5, 1.0, 1.0, 1.0],
},
"go_mishra01_on_cube__4": {
1.9999999928411163: [0.9999999999999993, 0.9999999999999992, 0.9999999999999999, 0.12006013934268739],
},
"go_mishra02_on_cube__4": {
1.9999999928411163: [0.9907412835351275, 0.9172213539800724, 0.9999999999999996, 0.8792695446455677],
},
"go_mishra07_on_cube__4": {
0.0: [0.8727569465722927, 0.9226986283327735, 0.09557227422564515, 0.1391780495360423],
},
"go_mishra11_on_cube__4": {
0.0: [0.49262618729194974, 0.31782158010515016, 0.5494294194887934, 0.43243988862988303],
},
"go_multimodal_on_cube__4": {
0.0: [0.5000000000004408, 0.5000000000000095, 0.6555568806051131, 0.5000000000005456],
},
"go_needleeye_on_cube__4": {
1.0: [0.4999999988366891, 0.4999999979965216, 0.4999999988366891, 0.6747993599890604],
},
"go_penalty01_on_cube__4": {
1.570544771786639e-32: [0.49000000000000216, 0.4900000000045488, 0.49000000000434424, 0.49000000000259214],
},
"go_penalty02_on_cube__4": {
1.3497838043956716e-31: [0.51, 0.51, 0.51, 0.51],
},
"go_permfunction01_on_cube__4": {
0.022942589411403945: [0.5076571662271249, 0.8575457353508119, 0.5843426595258812, 0.8361085666110741],
},
"go_permfunction02_on_cube__4": {
4.525357590326688e-30: [0.5555598137337187, 0.4719642376742956, 0.49939744649300466, 0.4796132767078549],
},
"go_pinter_on_cube__4": {
0.0: [0.5, 0.5, 0.5, 0.5],
},
"go_plateau_on_cube__4": {
30.0: [0.4932734474316645, 0.4932734474316645, 0.4932734474316645, 0.5508581326238648],
},
"go_powell_on_cube__4": {
0.0: [0.44444509150710204, 0.4444437719243386, 0.4444482661673988, 0.4444482661564514],
},
"go_powersum_on_cube__4": {
0.0: [0.6844559265801914, 0.30950792678221917, 0.3343492057195142, 0.6719797392682317],
},
"go_qing_on_cube__4": {
5.3707622579709536e-27: [0.49900000000000005, 0.4985857864376269, 0.49826794919243106, 0.498],
},
"go_quadratic_on_cube__4": {
-3873.7241821862717: [0.5096874319451075, 0.5242667998367262, 0.8136976152333063, 0.18518089676316943],
},
"go_quintic_on_cube__4": {
0.0: [0.5354949699058432, 0.3458348614376502, 0.389003675938885, 0.5867971950589506],
},
"go_rana_on_cube__4": {
-1495.900483081144: [0.19966236719231722, 1.0, 0.001954518905221303, 0.0030862541309490607],
},
"go_rastrigin_on_cube__4": {
0.0: [0.49999999999969436, 0.5000002447154946, 0.549866189132194, 0.5000000000019278],
},
"go_ratkowsky01_on_cube__4": {
8786.404907963095: [0.6996415124695768, 0.22511186067152653, 0.253209795946327, 0.19987261064121364],
},
"go_rosenbrock_on_cube__4": {
1.8427790745962836e-27: [0.5166666666666667, 0.5166666666666668, 0.5166666666666672, 0.5166666666666674],
},
"go_salomon_on_cube__4": {
0.0: [0.4990867028725108, 0.49824612382646793, 0.20357400849962232, 0.5035731475872616],
},
"go_sargan_on_cube__4": {
-35200.00000000005: [0.8999999985946622, 3.469446951953614e-17, 1.0, 0.10000000181447662],
},
"go_schwefel01_on_cube__4": {
0.0: [0.50048828125, 0.5, 0.5, 0.5],
},
"go_schwefel02_on_cube__4": {
0.0: [0.5000005284691311, 0.4999980379339887, 0.50000312482585, 0.4999975956916072],
},
"go_schwefel04_on_cube__4": {
0.0: [0.1, 0.1, 0.1, 0.1],
},
"go_schwefel20_on_cube__4": {
0.0: [0.49999999999999983, 0.5000000000000002, 0.5, 0.49999999995473077],
},
"go_schwefel21_on_cube__4": {
0.0: [0.4999999997893743, 0.49999999985716703, 0.5000000002106256, 0.49999999978937426],
},
"go_schwefel22_on_cube__4": {
0.0: [0.5, 0.5000000000000001, 0.5, 0.5],
},
"go_schwefel26_on_cube__4": {
-1.089735178538831e-06: [0.9305937532533836, 0.9209687464160179, 0.19747734132307387, 0.9209687456292082],
},
"go_shekel05_on_cube__4": {
-10.15319967905823: [0.4000037689925856, 0.4000130672256758, 0.40000279482137596, 0.4000143020086375],
},
"go_shekel07_on_cube__4": {
-10.402940566818666: [0.40005211433664734, 0.4000732914719807, 0.3999500655069954, 0.3999652204984656],
},
"go_shekel10_on_cube__4": {
-10.536409816692046: [0.4000746531076067, 0.400059293286648, 0.39996633980382557, 0.3999509799996026],
},
"go_shubert01_on_cube__4": {
-39303.550054363215: [0.7741440434102077, 0.7741556333290653, 0.7429083697053124, 0.7741396753978015],
},
"go_shubert03_on_cube__4": {
-48.12499776866859: [0.7895897234617342, 0.7895897234965026, 0.7895897234965026, 0.7895897234965026],
},
"go_shubert04_on_cube__4": {
-58.03203170878015: [0.1458246797794856, 0.14582467977948557, 0.14582467959087073, 0.1458246797794856],
},
"go_sineenvelope_on_cube__4": {
0.0: [0.5000000000049838, 0.5000000000180229, 0.4999999999815214, 0.5000000000104797],
},
"go_sodp_on_cube__4": {
0.0: [0.5000003501207233, 0.49934332155107486, 0.5009018689609204, 0.5232120945186667],
},
"go_sphere_on_cube__4": {
0.0: [0.5, 0.5000000000000009, 0.5, 0.5],
},
"go_step2_on_cube__4": {
1.0: [0.5012432021330329, 0.4951491010577182, 0.5059914251045634, 0.502325162192821],
},
"go_step_on_cube__4": {
0.0: [0.4996842002116297, 0.49694494375720955, 0.503280368273251, 0.4951664506412295],
},
"go_stochastic_on_cube__4": {
9.300834900727792e-22: [0.6, 0.3, 0.33684113309205904, 0.5249999995343387],
},
"go_stretchedv_on_cube__4": {
0.0: [0.5, 0.5, 0.5, 0.5],
},
"go_styblinskitang_on_cube__4": {
-156.6646628150857: [0.022117851576171424, 0.022117851595805146, 0.022117851595805146, 0.022117851576171424],
},
"go_trigonometric01_on_cube__4": {
0.0: [0.0, 0.0, 6.938893903907228e-18, 1.734723475976807e-17],
},
"go_trigonometric02_on_cube__4": {
1.0: [0.5009000000000405, 0.5009000000002075, 0.5009000000004369, 0.5008998066497936],
},
"go_vincent_on_cube__4": {
-4.0: [0.3960212450924436, 0.39602124595914034, 0.39602124518164733, 0.39602124530774435],
},
"go_wavy_on_cube__4": {
0.0: [0.49999999994282107, 0.4894464797508772, 0.49999999985754334, 0.5000000001497444],
},
"go_weierstrass_on_cube__4": {
0.0: [0.5000152588472697, 0.5000000000000009, 0.5, 0.5],
},
"go_whitley_on_cube__4": {
0.0: [0.5000697309500134, 0.5000697309500134, 0.5000697309500134, 0.5000697309500134],
},
"go_xinsheyang01_on_cube__4": {
0.0: [0.5000638843834544, 0.499956010089577, 0.5008984704522029, 0.5048778232729327],
},
"go_xinsheyang02_on_cube__4": {
0.0: [0.5, 0.5, 0.5, 0.49999999999999994],
},
"go_xinsheyang03_on_cube__4": {
-1.0: [0.3750000212082758, 1.8722817393679314e-10, 0.9999999995579297, 1.1439725125517164e-08],
},
"go_xinsheyang04_on_cube__4": {
-1.0: [0.344534632972428, 0.3417994205644585, 0.35607999521170186, 0.34602083862333655],
},
"go_yaoliu04_on_cube__4": {
0.0: [0.5, 0.5, 0.5, 0.5],
},
"go_yaoliu09_on_cube__4": {
0.0: [0.5000000008566511, 0.5000000000634754, 0.500000000363694, 0.49999999975360193],
},
"go_zacharov_on_cube__4": {
0.0: [0.4316875852820895, 0.3333333333333333, 0.3333333333333333, 0.3333333333333333],
},
"go_zerosum_on_cube__4": {
0.0: [0.5, 0.5, 0.5, 0.5],
},
}

263
utils.py Normal file
View File

@ -0,0 +1,263 @@
from dataclasses import dataclass
import math
feps = 2.0**-23.0
tiniest = 2.0**-1022.0
check = object() # secret "key" to pass to wrap_untrustworthy to extract feval_count
final = object() # secret "key" to pass to wrap_untrustworthy to extract results
color_factory = lambda color: lambda s: print(f"\033[{color}m{s}\033[m")
m1 = color_factory(1)
m30 = color_factory(30)
m31 = color_factory(31)
m32 = color_factory(32)
m33 = color_factory(33)
m34 = color_factory(34)
m35 = color_factory(35)
m36 = color_factory(36)
m37 = color_factory(37)
m90 = color_factory(90)
m91 = color_factory(91)
m92 = color_factory(92)
m93 = color_factory(93)
m94 = color_factory(94)
m95 = color_factory(95)
m96 = color_factory(96)
m97 = color_factory(97)
class ExhaustedTrialsError(Exception):
pass
def scalar_softplus(x):
if x >= 33.276435657655455:
return float(x)
elif x <= -745.13330078125:
return 0.0
else:
return math.log1p(math.exp(x))
def phi(d):
# phi(1) = golden ratio
# phi(2) = plastic constant
# phi(3) = the positive real root of x**4-x-1
x = 2.0
for i in range(30 if d == 1 else max(10, 28 - d)):
x = pow(1 + x, 1 / (d + 1))
return x
def wrap_untrustworthy(
objective, n_trials, *, raising=False, bounding=None, softplus=False, eps=0.0
):
# also handles bounding now, so it may be used for other purposes as well. whoops.
feval_count = 0
best_so_far = None
def _objective(x):
nonlocal feval_count, best_so_far
if x is check:
return feval_count
if x is final:
assert best_so_far is not None
fopt, xopt = best_so_far
return fopt, xopt, feval_count
if raising and feval_count >= n_trials:
raise ExhaustedTrialsError()
if bounding is not None:
x = do_bounding(x, bounding)
fx = objective(x)
feval_count += 1
if n_trials is None or feval_count <= n_trials:
if best_so_far is None or fx < best_so_far[0]:
best_so_far = (fx, x.copy())
return scalar_softplus(fx) + eps if softplus else fx
return _objective
@dataclass
class KeyData:
key: str
d: int
n: int
opt: str
obj: str
run: int
def decode_key(key, _filtering=False):
# example key:
# COWrap_d03_n130_freelunch_qpso_ps16_cube_go_amgm_on_cube
k, _, run = key.partition("[")
run, _, _ = run.partition("]")
k = k.removeprefix("COWrap_")
d, _, k = k.partition("_")
n, _, k = k.partition("_")
opt, _, k = k.partition("_cube_")
obj, _, k = k.partition("_on_cube")
if not obj:
if opt.endswith("_on_cube"):
return # fcmaes_biteopt was missing the _cube in its name for a while
if _filtering and obj in ("go_stochastic", "go_xinsheyang01"):
return # these are random
assert not k, k
d = int(d.removeprefix("d"), 10)
n = int(n.removeprefix("n"), 10)
run = int(run, 10)
return KeyData(key=key, d=d, n=n, opt=opt, obj=obj, run=run)
class AcquireForWriting:
"""
A context manager that allows for very crude file-locking-like
functionality when the FileLock module is missing.
"""
def __init__(self, filepath, usingfilelock=None):
from pathlib import Path
self.filepath = Path(filepath)
if usingfilelock is None:
try:
from filelock import FileLock
except ModuleNotFoundError:
self._locking = False
self.lock = None
else:
self._locking = True
self.lock = FileLock(self._altpath)
elif usingfilelock:
from filelock import FileLock
self._locking = True
self.lock = FileLock(self._altpath)
else:
self._locking = False
self.lock = None
@property
def _altpath(self):
suffix = ".lock" if self._locking else "~"
return self.filepath.with_suffix(self.filepath.suffix + suffix)
def __enter__(self):
if self._locking:
self.lock.__enter__()
else:
from time import sleep
for _ in range(3):
if self._altpath.exists():
sleep(1)
assert not self._altpath.exists(), f"file is locked: {self.filepath}"
if not self._locking:
self._altpath.write_bytes(b"")
return self.filepath if self._locking else self._altpath
def __exit__(self, *exc):
if self._locking:
self.lock.__exit__(*exc)
elif exc == (None, None, None):
assert self._altpath.exists(), f"file went missing: {self.filepath}"
try:
data = self._altpath.read_bytes()
if data:
self.filepath.write_bytes(data)
finally:
self._altpath.unlink()
# from shutil import move
# move(self._altpath, self.filepath) # assumes os.rename overwrites files
def perform_another_experimental_scoring_method(results):
new_results = {}
all_opt_names = set()
for obj_name, obj_res in results.items():
all_res = {}
for fopt, opt_name in obj_res:
all_res.setdefault(fopt, []).append(opt_name)
all_opt_names.add(opt_name)
new_results[obj_name] = dict(sorted(all_res.items()))
limited_by_floating_point_precision = 53
best_ranks_and_counts = {}
for outer_rank in range(1, limited_by_floating_point_precision + 1):
for obj_name, all_res in new_results.items():
for fopt, opt_names in all_res.items():
dirty = False
for opt_name in set(opt_names):
if opt_name in best_ranks_and_counts:
rank, count = best_ranks_and_counts[opt_name]
if rank == outer_rank:
best_ranks_and_counts[opt_name] = (rank, count + 1)
dirty = True
else:
best_ranks_and_counts[opt_name] = (outer_rank, 1)
dirty = True
if dirty:
break
scores = {k: 0.0 for k in all_opt_names}
for opt_name, (rank, count) in best_ranks_and_counts.items():
points = 2**(1 - rank)
count = min(count, limited_by_floating_point_precision)
scores[opt_name] = score = sum(points / 2**i for i in range(count))
return scores
def needs_rerun(key, value):
n_dim = len(value["xopt"])
ng = []
if value["duration"] > -1683000000.0:
if n_dim == 3:
ng += "go_ackley01 go_alpine01 go_deflectedcorrugatedspring go_exponential go_griewank go_infinity go_mishra11 go_multimodal go_pinter go_qing go_rastrigin go_salomon go_schwefel01 go_schwefel20 go_schwefel21 go_schwefel22 go_sineenvelope go_sodp go_trigonometric02 go_wavy go_weierstrass go_xinsheyang01 go_xinsheyang02 go_xinsheyang03 go_yaoliu04 go_yaoliu09 go_zerosum".split()
ng += "go_amgm go_brown go_cigar go_deb01 go_deb03 go_deceptive go_needleeye go_penalty01 go_schwefel04 go_schwefel26 go_sphere go_stretchedv go_styblinskitang go_zacharov".split()
if n_dim == 4:
ng += "go_ackley01 go_alpine01 go_cigar go_exponential go_griewank go_infinity go_pinter go_qing go_schwefel01 go_schwefel02 go_schwefel20 go_schwefel21 go_schwefel22 go_sineenvelope go_sphere go_step2 go_step go_stretchedv go_trigonometric02 go_weierstrass go_whitley go_xinsheyang01 go_xinsheyang02 go_yaoliu04 go_yaoliu09 go_zerosum".split()
ng += "go_amgm go_brown go_colville go_deb03 go_penalty01 go_penalty02 go_powell go_rosenbrock go_schwefel04 go_shekel05 go_shekel07 go_shekel10 go_shubert03 go_shubert04 go_styblinskitang go_vincent".split()
kd = decode_key(key)
assert kd is not None, key
if kd.obj in ng:
# print("filtered", key, file=__import__("sys").stderr)
return True
return False
def merge_summaries(all_summaries):
# i only needed to write this because i effed up my filenames at one point. oh well.
if len(all_summaries) == 0:
return {}
elif len(all_summaries) == 1:
return {k: v for k, v in all_summaries[0].items() if not needs_rerun(k, v)}
new_summaries = {}
for s in all_summaries:
for key, value in s.items():
if needs_rerun(key, value):
continue
k, _, run = key.partition("[")
run, _, _ = run.partition("]")
for i in range(1, 100):
new_key = f"{k}[{i}]"
if new_key in new_summaries:
if new_summaries[new_key] == value: # this works 'cause it's POD
break # already exists (probably; duration is fucked)
continue
new_summaries[new_key] = value
break
return new_summaries
try:
import numpy
except ModuleNotFoundError:
pass
else:
from utils_np import *

257
utils_np.py Normal file
View File

@ -0,0 +1,257 @@
# i've separated numpy-dependent methods from the rest of the utils.
from project import project
from utils import AcquireForWriting, merge_summaries, feps, m33, m34, m93
import numpy as np
def do_bounding(x, method="clip"):
if method == "clip":
x = np.clip(x, 0, 1)
elif method == "proj":
# projects x back into the unit hypercube, poorly.
if any(x < 0) or any(x > 1):
x = 2 * x - 1
x /= np.max(np.abs(x)) + feps
x = (x + 1) / 2
assert all(x >= 0) and all(x <= 1), x
elif method == "pro2":
# a little more logical.
# FIXME: we need a way to determine the previous (or center) x somehow?
if any(x < 0) or any(x > 1):
x = project(best_so_far[1], x, eps=feps)
elif method == "prcl":
# over-engineered clipping with projection-sliding. (yeah don't ask)
# FIXME: we need a way to determine the previous (or center) x somehow?
from bitten_snes import _project_with
x = _project_with(x, old, np.array([[0.0, 1.0] * n_dim]), clipping=0.5)
elif method == "tria":
hp = np.pi / 2
x = np.abs(np.arcsin(np.sin(x * hp)) / hp)
elif method == "sine":
x = np.square(np.sin(0.5 * np.pi * x))
elif method == "ssin":
x = np.square(np.sin(0.5 * np.pi * (np.arcsinh(x - 0.5) + 0.5)))
elif method == "pycma":
raise Exception("TODO: workaround this like pycma does.") # old ver or new ver?
return x
class OWrap:
def __init__(self, objective, n_trials, frugal_percent=1.0, greedy_percent=2.0):
self.feval_count = 0
self.best_so_far = None
self.warning = None
self.objective = objective
self.n_trials = n_trials
self.__name__ = objective.__name__ # for evolopy
self.frugal_percent = float(frugal_percent)
self.greedy_percent = float(greedy_percent)
def __str__(self):
return (
"<OWrap on "
+ str(getattr(self.objective, "__name__", str(self.objective)))
+ ">"
)
def __call__(self, x, *args, **kwargs):
if getattr(x, "get_x", None): # zoopt
x = x.get_x()
if type(x) is list: # opytimizer
x = np.array(x)
if x.ndim == 2: # flatten column vectors
assert x.shape[1] == 1, x.shape
x = x.T[0]
if not self.warning and (any(x < 0) or any(x > 1.00000001)):
self.warning = "bounds"
# assert False, x
if not all(np.isfinite(x)):
if not self.warning:
m33("x is not finite (NaN or Inf or -Inf)")
self.warning = "finite"
x[~np.isfinite(x)] = 0.5
x = np.clip(x, 0, 1)
# assert all(np.isfinite(x)), "x is not finite (NaN or Inf or -Inf)"
fx = self.objective(x)
assert np.isfinite(fx), "f(x) is not finite (NaN or Inf or -Inf)"
self.feval_count += 1
if self.feval_count <= self.n_trials:
if self.best_so_far is None or fx < self.best_so_far[0]:
self.best_so_far = (fx, x)
return float(fx)
def finish(self, optimizer_name):
if self.warning == "bounds":
m33(f"{optimizer_name} did not abide to bounds")
if self.warning == "finite":
m33(f"{optimizer_name} passed a non-finite value")
if self.feval_count >= self.n_trials * self.greedy_percent:
m33(f"{optimizer_name} got greedy ({self.feval_count}>{self.n_trials})")
# if self.feval_count <= self.n_trials * 0.95:
if self.feval_count < self.n_trials * self.frugal_percent:
m34(f"{optimizer_name} was frugal ({self.feval_count}<{self.n_trials})")
return self.best_so_far
@property
def fopt(self):
return None if self.best_so_far is None else self.best_so_far[0]
@property
def xopt(self):
return None if self.best_so_far is None else self.best_so_far[1]
class COWrap:
def __init__(self, objective, *, optimizer, n_trials, n_dim, **kwargs):
self._objective = objective
self.optimizer = optimizer
self.n_trials = n_trials
self.n_dim = n_dim
self.kwargs = kwargs
self._dirty = False
from pathlib import Path
# self.cache_dir = Path("./cache")
self.cache_dir = Path("~/thursday-cache").expanduser()
self._cached_summaries = None
self.reset_objective()
def __str__(self):
return (
"<COWrap on "
+ str(getattr(self.ow.objective, "__name__", str(self.ow.objective)))
+ ">"
)
def __name__(self):
return str(getattr(self.ow.objective, "__name__", str(self.ow.objective)))
def __call__(self, x, *args, **kwargs):
assert not self._ran, "please run .finish() before continuing!"
result = self.ow.__call__(x, *args, **kwargs)
self._dirty = True
return result
@property
def objective(self):
return self._objective
@objective.setter
def objective(self, new_objective):
# don't do this or it defeats the purpose: self._cached_summaries = None
self._objective = new_objective
self.reset_objective()
@property
def cache_name(self):
opt_name = self.optimizer.__name__
return f"COWrap_d{self.n_dim:02}_n{self.n_trials:03}_{opt_name}"
@property
def cache_key(self):
opt_name = self.optimizer.__name__
obj_name = self._objective.__name__
return f"{self.cache_name}_{obj_name}[{self._run}]"
@property
def cache_file(self):
opt_name = self.optimizer.__name__
return self.cache_dir / f"{self.cache_name}.json"
@property
def cache_file_fucked(self):
opt_name = self.optimizer.__name__
return self.cache_dir / f"{self.cache_name}_{opt_name}.json"
@property # TODO: write a setter as well?
def cached_summaries(self):
if self._cached_summaries is not None:
return self._cached_summaries
from json import loads
if not self.cache_dir.exists() or not (
self.cache_file.exists() or self.cache_file_fucked.exists()
):
return {}
# text = self.cache_file.read_text()
# if not text:
# return {}
# summaries = loads(text)
# self._cached_summaries = summaries
all_summaries = []
for cf in (self.cache_file, self.cache_file_fucked):
if cf.exists(): # at least one exists at this point...
if text := cf.read_text(): # ...but not every file contains anything
all_summaries.append(loads(text))
self._cached_summaries = merge_summaries(all_summaries)
return self._cached_summaries
def reset_objective(self):
self._dirty = False
self.ow = OWrap(self._objective, self.n_trials, **self.kwargs)
self._check_cache()
def _check_cache(self):
# assert not self._dirty # useless for a private method
self._run = 1
self._ran = False
while self.cache_key in self.cached_summaries:
self._run += 1
def cached(self, run):
assert not self._dirty
old_run = self._run
self._run = run
summary = self.cached_summaries.get(self.cache_key, None)
self._run = old_run
if summary is None:
return None
assert "fopt" in summary, summary
assert "xopt" in summary, summary
assert "duration" in summary, summary
fopt = float(summary["fopt"])
xopt = np.array(summary["xopt"], np.float64)
duration = float(summary["duration"])
return fopt, xopt
def finish(self, opt_name=None):
from json import dumps
from time import time
assert self._dirty
self._ran = True
if opt_name is not None and opt_name != self.optimizer.__name__:
m93("Warning: opt_name mistmatch")
assert self.ow.best_so_far is not None
# fopt, xopt = self.ow.best_so_far
fopt, xopt = self.ow.finish(self.optimizer.__name__)
summary = dict(
fopt=float(fopt),
xopt=[float(x) for x in xopt],
# duration=float(-1), # old, bad for uniqueness
duration=float(-time()),
)
with AcquireForWriting(self.cache_file) as fp:
self._cached_summaries = None # force reload
self._check_cache() # refresh ._run and thereby .cache_key
summaries = self.cached_summaries
summaries[self.cache_key] = summary
text = dumps(summaries, separators=(",", ":"))
fp.write_text(text)
if self.cache_file_fucked.exists():
# safe to delete now that i've written and tested merge_summaries.
self.cache_file_fucked.unlink()
self._cached_summaries = None # force reload in case of other writes
self.reset_objective()
return fopt, xopt