woche12 > master: code py - random walks ergänzt
- stopkriterien - logging
This commit is contained in:
parent
7b456d177e
commit
2bd07544f3
@ -5,8 +5,9 @@
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.thirdparty.types import *;
|
||||
from src.thirdparty.maths import *;
|
||||
from src.thirdparty.plots import *;
|
||||
from src.thirdparty.types import *;
|
||||
|
||||
from models.generated.config import *;
|
||||
from models.generated.commands import *;
|
||||
@ -25,6 +26,12 @@ __all__ = [
|
||||
'metropolis_walk_algorithm',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
MAX_ITERATIONS = 1000; # um endlose Schleifen zu verhindern
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHOD adaptive walk
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -50,13 +57,15 @@ def adaptive_walk_algorithm(
|
||||
label = lambda x: landscape.label(*x);
|
||||
|
||||
# initialisiere
|
||||
steps = [];
|
||||
x = coords_init;
|
||||
fx = f(x);
|
||||
fy = fx;
|
||||
N = nbhd(x);
|
||||
|
||||
# führe walk aus:
|
||||
while True:
|
||||
k = 0;
|
||||
while k < MAX_ITERATIONS:
|
||||
# Wähle zufälligen Punkt und berechne fitness-Wert:
|
||||
y = uniform_random_choice(N);
|
||||
fy = f(y);
|
||||
@ -67,14 +76,20 @@ def adaptive_walk_algorithm(
|
||||
x = y;
|
||||
fx = fy;
|
||||
N = nbhd(x);
|
||||
step = Step(coords=x, label=label(x), improved=True, changed=True);
|
||||
else:
|
||||
# Nichts machen!
|
||||
pass;
|
||||
# Nichts (außer logging) machen!
|
||||
step = Step(coords=x, label=label(x));
|
||||
|
||||
# Nur dann (erfolgreich) abbrechen, wenn f-Wert lokal Min:
|
||||
if fx <= min([f(y) for y in N], default=fx):
|
||||
step.stopped = True;
|
||||
steps.append(step);
|
||||
break;
|
||||
|
||||
steps.append(step);
|
||||
k += 1;
|
||||
|
||||
return x;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -102,6 +117,7 @@ def gradient_walk_algorithm(
|
||||
label = lambda x: landscape.label(*x);
|
||||
|
||||
# initialisiere
|
||||
steps = [];
|
||||
x = coords_init;
|
||||
fx = landscape.fitness(*x);
|
||||
fy = fx;
|
||||
@ -111,7 +127,8 @@ def gradient_walk_algorithm(
|
||||
Z = [y for y, fy in zip(N, f_values) if fy == fmin];
|
||||
|
||||
# führe walk aus:
|
||||
while True:
|
||||
k = 0;
|
||||
while k < MAX_ITERATIONS:
|
||||
# Wähle zufälligen Punkt mit steilstem Abstieg und berechne fitness-Wert:
|
||||
y = uniform_random_choice(Z);
|
||||
fy = fmin;
|
||||
@ -125,14 +142,20 @@ def gradient_walk_algorithm(
|
||||
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];
|
||||
step = Step(coords=x, label=label(x), improved=True, changed=True);
|
||||
else:
|
||||
# Nichts machen!
|
||||
pass;
|
||||
# Nichts (außer logging) machen!
|
||||
step = Step(coords=x, label=label(x));
|
||||
|
||||
# Nur dann (erfolgreich) abbrechen, wenn f-Wert lokal Min:
|
||||
if fx <= min([f(y) for y in N], default=fx):
|
||||
step.stopped = True;
|
||||
steps.append(step);
|
||||
break;
|
||||
|
||||
steps.append(step);
|
||||
k += 1;
|
||||
|
||||
return x;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -161,46 +184,64 @@ def metropolis_walk_algorithm(
|
||||
nbhd = lambda x: landscape.neighbourhood(*x, r=r, strict=True);
|
||||
label = lambda x: landscape.label(*x);
|
||||
|
||||
# definiere anzahl der hinreichenden Schritt für Stabilität:
|
||||
n_stable = 2*(3**(landscape.dim) - 1);
|
||||
|
||||
# initialisiere
|
||||
x = coords_init;
|
||||
fx = f(x);
|
||||
fy = fx;
|
||||
nbhd_x = nbhd(x);
|
||||
steps = [];
|
||||
step = Step(coords=x, label=label(x));
|
||||
|
||||
# führe walk aus:
|
||||
k = 0;
|
||||
while True:
|
||||
n_unchanged = 0;
|
||||
while k < MAX_ITERATIONS:
|
||||
# Wähle zufälligen Punkt und berechne fitness-Wert:
|
||||
y = uniform_random_choice(nbhd_x);
|
||||
r = uniform(0,1);
|
||||
fy = f(y);
|
||||
p = math.exp(-abs(fy-fx)/T);
|
||||
u = random_binary(p);
|
||||
|
||||
# Nur dann aktualisieren, wenn sich f-Wert verbessert:
|
||||
if fy < fx or r < math.exp(-(fy-fx)/T):
|
||||
# Aktualisieren, wenn sich f-Wert verbessert
|
||||
# oder mit einer Wahrscheinlichkeit von p:
|
||||
if fy < fx or u:
|
||||
# Punkt + Umgebung + f-Wert aktualisieren
|
||||
x = y;
|
||||
fx = fy;
|
||||
nbhd_x = nbhd(x);
|
||||
n_unchanged = 0;
|
||||
step = Step(coords=x, label=label(x), improved=(fy < fx), chance=u, probability=p, changed=True);
|
||||
else:
|
||||
# Nichts machen!
|
||||
pass;
|
||||
# Nichts (außer logging) machen!
|
||||
n_unchanged += 1;
|
||||
step = Step(coords=x, label=label(x));
|
||||
|
||||
# »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):
|
||||
if n_unchanged >= n_stable:
|
||||
step.stopped = True;
|
||||
steps.append(step);
|
||||
break;
|
||||
|
||||
steps.append(step);
|
||||
k += 1;
|
||||
|
||||
if verbose:
|
||||
for step in steps:
|
||||
print(step);
|
||||
|
||||
return x;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# AUXILIARY METHODS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def cool_temperature(T: float, k: int, const: float = 1.) -> float:
|
||||
def cool_temperature(T: float, k: int, const: float = 2.) -> float:
|
||||
harm = const*(k + 1);
|
||||
return T/(1 + T/harm);
|
||||
|
@ -58,9 +58,23 @@ class Landscape():
|
||||
def coords_middle(self) -> tuple:
|
||||
return tuple(math.floor(s/2) for s in self.shape);
|
||||
|
||||
@property
|
||||
def values(self) -> np.ndarray:
|
||||
return self._fct;
|
||||
|
||||
def fitness(self, *x: int) -> float:
|
||||
return self._fct[x];
|
||||
|
||||
def axis_label(self, i: int, x: int) -> str:
|
||||
if self._one_based:
|
||||
x = x + 1;
|
||||
name = self._labels[i];
|
||||
return f'{name}{x}';
|
||||
|
||||
def axis_labels(self, i: int) -> str:
|
||||
s = self.shape[i];
|
||||
return [ self.axis_label(i, x) for x in range(s) ];
|
||||
|
||||
def label(self, *x: int) -> str:
|
||||
if self._one_based:
|
||||
x = tuple(xx + 1 for xx in x);
|
||||
|
Loading…
Reference in New Issue
Block a user