Compare commits
4 Commits
4001551c9c
...
a7c7179edb
Author | SHA1 | Date | |
---|---|---|---|
a7c7179edb | |||
5c43419890 | |||
c2cb11a141 | |||
01ef8c5758 |
@ -170,9 +170,21 @@ components:
|
|||||||
$ref: '#/components/schemas/DataTypeLandscapeGeometry'
|
$ref: '#/components/schemas/DataTypeLandscapeGeometry'
|
||||||
optimise:
|
optimise:
|
||||||
$ref: '#/components/schemas/EnumOptimiseMode'
|
$ref: '#/components/schemas/EnumOptimiseMode'
|
||||||
|
coords-init:
|
||||||
|
description: Initial co-ordinates to start the algorithm.
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
minItems: 1
|
||||||
|
temperature-init:
|
||||||
|
type: float
|
||||||
|
default: 1.
|
||||||
annealing:
|
annealing:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
one-based:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
# Algorithm: Genetic Algorithm
|
# Algorithm: Genetic Algorithm
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -243,10 +255,16 @@ components:
|
|||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- neighbourhoods
|
- neighbourhoods
|
||||||
|
- labels
|
||||||
- values
|
- values
|
||||||
properties:
|
properties:
|
||||||
neighbourhoods:
|
neighbourhoods:
|
||||||
$ref: '#/components/schemas/DataTypeLandscapeNeighbourhoods'
|
$ref: '#/components/schemas/DataTypeLandscapeNeighbourhoods'
|
||||||
|
labels:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
minItems: 1
|
||||||
values:
|
values:
|
||||||
$ref: '#/components/schemas/DataTypeLandscapeValues'
|
$ref: '#/components/schemas/DataTypeLandscapeValues'
|
||||||
DataTypeLandscapeNeighbourhoods:
|
DataTypeLandscapeNeighbourhoods:
|
||||||
|
@ -32,14 +32,50 @@ __all__ = [
|
|||||||
def adaptive_walk_algorithm(
|
def adaptive_walk_algorithm(
|
||||||
landscape: Landscape,
|
landscape: Landscape,
|
||||||
r: float,
|
r: float,
|
||||||
|
coords_init: tuple,
|
||||||
optimise: EnumOptimiseMode,
|
optimise: EnumOptimiseMode,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
):
|
):
|
||||||
'''
|
'''
|
||||||
Führt den Adapative-Walk Algorithmus aus, um ein lokales Minimum zu bestimmen.
|
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
|
# METHOD gradient walk
|
||||||
@ -48,14 +84,56 @@ def adaptive_walk_algorithm(
|
|||||||
def gradient_walk_algorithm(
|
def gradient_walk_algorithm(
|
||||||
landscape: Landscape,
|
landscape: Landscape,
|
||||||
r: float,
|
r: float,
|
||||||
|
coords_init: tuple,
|
||||||
optimise: EnumOptimiseMode,
|
optimise: EnumOptimiseMode,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
):
|
):
|
||||||
'''
|
'''
|
||||||
Führt den Gradient-Descent (bzw. Ascent) Algorithmus aus, um ein lokales Minimum zu bestimmen.
|
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
|
# METHOD metropolis walk
|
||||||
@ -64,6 +142,8 @@ def gradient_walk_algorithm(
|
|||||||
def metropolis_walk_algorithm(
|
def metropolis_walk_algorithm(
|
||||||
landscape: Landscape,
|
landscape: Landscape,
|
||||||
r: float,
|
r: float,
|
||||||
|
coords_init: tuple,
|
||||||
|
T: float,
|
||||||
annealing: bool,
|
annealing: bool,
|
||||||
optimise: EnumOptimiseMode,
|
optimise: EnumOptimiseMode,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
@ -71,5 +151,56 @@ def metropolis_walk_algorithm(
|
|||||||
'''
|
'''
|
||||||
Führt den Metropolis-Walk Algorithmus aus, um ein lokales Minimum zu bestimmen.
|
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);
|
||||||
|
@ -27,15 +27,28 @@ __all__ = [
|
|||||||
|
|
||||||
@run_safely()
|
@run_safely()
|
||||||
def endpoint_random_walk(command: CommandRandomWalk) -> Result[CallResult, CallError]:
|
def endpoint_random_walk(command: CommandRandomWalk) -> Result[CallResult, CallError]:
|
||||||
|
# Compute landscape (fitness fct + topology) + initial co-ordinates:
|
||||||
|
one_based = command.one_based;
|
||||||
landscape = Landscape(
|
landscape = Landscape(
|
||||||
values = command.landscape.values,
|
values = command.landscape.values,
|
||||||
|
labels = command.landscape.labels,
|
||||||
metric = command.landscape.neighbourhoods.metric,
|
metric = command.landscape.neighbourhoods.metric,
|
||||||
|
one_based = one_based,
|
||||||
);
|
);
|
||||||
|
if isinstance(command.coords_init, list):
|
||||||
|
coords_init = tuple(command.coords_init);
|
||||||
|
if one_based:
|
||||||
|
coords_init = tuple(xx - 1 for xx in coords_init);
|
||||||
|
assert len(coords_init) == landscape.dim, 'Dimension of initial co-ordinations inconsistent with landscape!';
|
||||||
|
else:
|
||||||
|
coords_init = landscape.coords_middle;
|
||||||
|
|
||||||
match command.algorithm:
|
match command.algorithm:
|
||||||
case EnumWalkMode.adaptive:
|
case EnumWalkMode.adaptive:
|
||||||
result = adaptive_walk_algorithm(
|
result = adaptive_walk_algorithm(
|
||||||
landscape = landscape,
|
landscape = landscape,
|
||||||
r = command.landscape.neighbourhoods.radius,
|
r = command.landscape.neighbourhoods.radius,
|
||||||
|
coords_init = coords_init,
|
||||||
optimise = command.optimise,
|
optimise = command.optimise,
|
||||||
verbose = config.OPTIONS.random_walk.verbose
|
verbose = config.OPTIONS.random_walk.verbose
|
||||||
);
|
);
|
||||||
@ -43,6 +56,7 @@ def endpoint_random_walk(command: CommandRandomWalk) -> Result[CallResult, CallE
|
|||||||
result = gradient_walk_algorithm(
|
result = gradient_walk_algorithm(
|
||||||
landscape = landscape,
|
landscape = landscape,
|
||||||
r = command.landscape.neighbourhoods.radius,
|
r = command.landscape.neighbourhoods.radius,
|
||||||
|
coords_init = coords_init,
|
||||||
optimise = command.optimise,
|
optimise = command.optimise,
|
||||||
verbose = config.OPTIONS.random_walk.verbose
|
verbose = config.OPTIONS.random_walk.verbose
|
||||||
);
|
);
|
||||||
@ -50,6 +64,8 @@ def endpoint_random_walk(command: CommandRandomWalk) -> Result[CallResult, CallE
|
|||||||
result = metropolis_walk_algorithm(
|
result = metropolis_walk_algorithm(
|
||||||
landscape = landscape,
|
landscape = landscape,
|
||||||
r = command.landscape.neighbourhoods.radius,
|
r = command.landscape.neighbourhoods.radius,
|
||||||
|
coords_init = coords_init,
|
||||||
|
T = command.temperature_init,
|
||||||
annealing = command.annealing,
|
annealing = command.annealing,
|
||||||
optimise = command.optimise,
|
optimise = command.optimise,
|
||||||
verbose = config.OPTIONS.random_walk.verbose
|
verbose = config.OPTIONS.random_walk.verbose
|
||||||
|
@ -27,16 +27,23 @@ __all__ = [
|
|||||||
|
|
||||||
class Landscape():
|
class Landscape():
|
||||||
_fct: np.ndarray;
|
_fct: np.ndarray;
|
||||||
|
_labels: list[str];
|
||||||
_metric: EnumLandscapeMetric;
|
_metric: EnumLandscapeMetric;
|
||||||
_radius: float;
|
_radius: float;
|
||||||
|
_one_based: bool;
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
values: DataTypeLandscapeValues,
|
values: DataTypeLandscapeValues,
|
||||||
|
labels: List[str],
|
||||||
metric: EnumLandscapeMetric = EnumLandscapeMetric.maximum,
|
metric: EnumLandscapeMetric = EnumLandscapeMetric.maximum,
|
||||||
|
one_based: bool = False,
|
||||||
):
|
):
|
||||||
self._fct = convert_to_nparray(values);
|
self._fct = convert_to_nparray(values);
|
||||||
|
assert len(labels) == self.dim, 'A label is required for each axis/dimension!';
|
||||||
|
self._labels = labels;
|
||||||
self._metric = metric;
|
self._metric = metric;
|
||||||
|
self._one_based = one_based;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -47,14 +54,27 @@ class Landscape():
|
|||||||
def dim(self) -> int:
|
def dim(self) -> int:
|
||||||
return len(self._fct.shape);
|
return len(self._fct.shape);
|
||||||
|
|
||||||
|
@property
|
||||||
|
def coords_middle(self) -> tuple:
|
||||||
|
return tuple(math.floor(s/2) for s in self.shape);
|
||||||
|
|
||||||
def fitness(self, *x: int) -> float:
|
def fitness(self, *x: int) -> float:
|
||||||
return self._fct[x];
|
return self._fct[x];
|
||||||
|
|
||||||
|
def label(self, *x: int) -> str:
|
||||||
|
if self._one_based:
|
||||||
|
x = tuple(xx + 1 for xx in x);
|
||||||
|
expr = ','.join([ f'{name}{xx}' for name, xx in zip(self._labels, x)]);
|
||||||
|
if self.dim > 1:
|
||||||
|
expr = f'({expr})';
|
||||||
|
return expr;
|
||||||
|
|
||||||
def neighbourhood(self, *x: int, r: float, strict: bool = False) -> List[tuple]:
|
def neighbourhood(self, *x: int, r: float, strict: bool = False) -> List[tuple]:
|
||||||
|
r = int(r);
|
||||||
sides = [
|
sides = [
|
||||||
[ xx - j for j in range(1,r+1) if xx - j in range(s) ]
|
[ xx - j for j in range(1, r+1) if xx - j in range(s) ]
|
||||||
+ ([ xx ] if xx in range(s) else [])
|
+ ([ xx ] if xx in range(s) else [])
|
||||||
+ [ xx + j for j in range(1,r+1) if xx + j in range(s) ]
|
+ [ xx + j for j in range(1, r+1) if xx + j in range(s) ]
|
||||||
for xx, s in zip(x, self.shape)
|
for xx, s in zip(x, self.shape)
|
||||||
];
|
];
|
||||||
match self._metric:
|
match self._metric:
|
||||||
|
4
code/python/src/thirdparty/maths.py
vendored
4
code/python/src/thirdparty/maths.py
vendored
@ -10,6 +10,8 @@ import math;
|
|||||||
import numpy as np;
|
import numpy as np;
|
||||||
import pandas as pd;
|
import pandas as pd;
|
||||||
import random;
|
import random;
|
||||||
|
from random import uniform;
|
||||||
|
from random import choice as uniform_random_choice;
|
||||||
from tabulate import tabulate;
|
from tabulate import tabulate;
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -22,5 +24,7 @@ __all__ = [
|
|||||||
'np',
|
'np',
|
||||||
'pd',
|
'pd',
|
||||||
'random',
|
'random',
|
||||||
|
'uniform',
|
||||||
|
'uniform_random_choice',
|
||||||
'tabulate',
|
'tabulate',
|
||||||
];
|
];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user