woche12 > master: code py - rohe implementierung der walks

This commit is contained in:
RD 2022-06-21 19:02:59 +02:00
parent 5c43419890
commit a7c7179edb
1 changed files with 137 additions and 6 deletions

View File

@ -32,14 +32,50 @@ __all__ = [
def adaptive_walk_algorithm(
landscape: Landscape,
r: float,
coords_init: tuple,
optimise: EnumOptimiseMode,
verbose: bool,
):
'''
Führt den Adapative-Walk Algorithmus aus, um ein lokales Minimum zu bestimmen.
'''
log_warn('Noch nicht implementiert!');
return;
# lege Fitness- und Umgebungsfunktionen fest:
match optimise:
case EnumOptimiseMode.max:
f = lambda x: -landscape.fitness(*x);
case _:
f = lambda x: landscape.fitness(*x);
nbhd = lambda x: landscape.neighbourhood(*x, r=r, strict=True);
label = lambda x: landscape.label(*x);
# initialisiere
x = coords_init;
fx = f(x);
fy = fx;
N = nbhd(x);
# führe walk aus:
while True:
# Wähle zufälligen Punkt und berechne fitness-Wert:
y = uniform_random_choice(N);
fy = f(y);
# Nur dann aktualisieren, wenn sich f-Wert verbessert:
if fy < fx:
# Punkt + Umgebung + f-Wert aktualisieren
x = y;
fx = fy;
N = nbhd(x);
else:
# Nichts machen!
pass;
# Nur dann (erfolgreich) abbrechen, wenn f-Wert lokal Min:
if fx <= min([f(y) for y in N], default=fx):
break;
return x;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD gradient walk
@ -48,14 +84,56 @@ def adaptive_walk_algorithm(
def gradient_walk_algorithm(
landscape: Landscape,
r: float,
coords_init: tuple,
optimise: EnumOptimiseMode,
verbose: bool,
):
'''
Führt den Gradient-Descent (bzw. Ascent) Algorithmus aus, um ein lokales Minimum zu bestimmen.
'''
log_warn('Noch nicht implementiert!');
return;
# lege Fitness- und Umgebungsfunktionen fest:
match optimise:
case EnumOptimiseMode.max:
f = lambda x: -landscape.fitness(*x);
case _:
f = lambda x: landscape.fitness(*x);
nbhd = lambda x: landscape.neighbourhood(*x, r=r, strict=True);
label = lambda x: landscape.label(*x);
# initialisiere
x = coords_init;
fx = landscape.fitness(*x);
fy = fx;
N = nbhd(x);
f_values = [f(y) for y in N];
fmin = min(f_values);
Z = [y for y, fy in zip(N, f_values) if fy == fmin];
# führe walk aus:
while True:
# Wähle zufälligen Punkt mit steilstem Abstieg und berechne fitness-Wert:
y = uniform_random_choice(Z);
fy = fmin;
# Nur dann aktualisieren, wenn sich f-Wert verbessert:
if fy < fx:
# Punkt + Umgebung + f-Wert aktualisieren
x = y;
fx = fy;
N = nbhd(y);
f_values = [f(y) for y in N];
fmin = min(f_values);
Z = [y for y, fy in zip(N, f_values) if fy == fmin];
else:
# Nichts machen!
pass;
# Nur dann (erfolgreich) abbrechen, wenn f-Wert lokal Min:
if fx <= min([f(y) for y in N], default=fx):
break;
return x;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD metropolis walk
@ -64,6 +142,8 @@ def gradient_walk_algorithm(
def metropolis_walk_algorithm(
landscape: Landscape,
r: float,
coords_init: tuple,
T: float,
annealing: bool,
optimise: EnumOptimiseMode,
verbose: bool,
@ -71,5 +151,56 @@ def metropolis_walk_algorithm(
'''
Führt den Metropolis-Walk Algorithmus aus, um ein lokales Minimum zu bestimmen.
'''
log_warn('Noch nicht implementiert!');
return;
# lege Fitness- und Umgebungsfunktionen fest:
match optimise:
case EnumOptimiseMode.max:
f = lambda x: -landscape.fitness(*x);
case _:
f = lambda x: landscape.fitness(*x);
nbhd = lambda x: landscape.neighbourhood(*x, r=r, strict=True);
label = lambda x: landscape.label(*x);
# initialisiere
x = coords_init;
fx = f(x);
fy = fx;
nbhd_x = nbhd(x);
# führe walk aus:
k = 0;
while True:
# Wähle zufälligen Punkt und berechne fitness-Wert:
y = uniform_random_choice(nbhd_x);
r = uniform(0,1);
fy = f(y);
# Nur dann aktualisieren, wenn sich f-Wert verbessert:
if fy < fx or r < math.exp(-(fy-fx)/T):
# Punkt + Umgebung + f-Wert aktualisieren
x = y;
fx = fy;
nbhd_x = nbhd(x);
else:
# Nichts machen!
pass;
# »Temperatur« ggf. abkühlen:
if annealing:
T = cool_temperature(T, k);
# Nur dann (erfolgreich) abbrechen, wenn f-Wert lokal Min:
if fx <= min([f(y) for y in nbhd_x], default=fx):
break;
k += 1;
return x;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# AUXILIARY METHODS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def cool_temperature(T: float, k: int, const: float = 1.) -> float:
harm = const*(k + 1);
return T/(1 + T/harm);