master > master: code py - models + config implementiert

This commit is contained in:
RD
2022-06-10 11:50:59 +02:00
parent 67f6caf2d5
commit 0523c68100
21 changed files with 538 additions and 94 deletions

View File

@@ -15,6 +15,4 @@ from src.hirschberg.display import *;
__all__ = [
'hirschberg_algorithm',
'VerboseMode',
'DisplayOptions',
];

View File

@@ -8,6 +8,7 @@
from src.thirdparty.types import *;
from src.thirdparty.maths import *;
from models.generated.commands import *;
from src.hirschberg.constants import *;
from src.hirschberg.display import *;
from src.hirschberg.matrix import *;
@@ -30,8 +31,8 @@ __all__ = [
def simple_algorithm(
X: str,
Y: str,
verb: VerboseMode = VerboseMode.NONE,
show: List[DisplayOptions] = [],
verb: List[EnumHirschbergVerbosity] = [],
show: List[EnumHirschbergShow] = [],
) -> Tuple[str, str]:
'''
Dieser Algorithmus berechnet die Edit-Distanzen + optimale Richtungen ein Mal.
@@ -40,7 +41,7 @@ def simple_algorithm(
Costs, Moves = compute_cost_matrix(X = '-' + X, Y = '-' + Y);
path = reconstruct_optimal_path(Moves=Moves);
word_x, word_y = reconstruct_words(X = '-' + X, Y = '-' + Y, moves=[Moves[coord] for coord in path], path=path);
if verb != VerboseMode.NONE:
if verb != []:
repr = display_cost_matrix(Costs=Costs, path=path, X = '-' + X, Y = '-' + Y, verb=verb);
display = word_y + f'\n{"-"*len(word_x)}\n' + word_x;
print(f'\n{repr}\n\n\x1b[1mOptimales Alignment:\x1b[0m\n\n{display}\n');
@@ -50,8 +51,8 @@ def hirschberg_algorithm(
X: str,
Y: str,
once: bool = False,
verb: VerboseMode = VerboseMode.NONE,
show: List[DisplayOptions] = [],
verb: List[EnumHirschbergVerbosity] = [],
show: List[EnumHirschbergShow] = [],
) -> Tuple[str, str]:
'''
Der Hirschberg-Algorithmus berechnet nur die Edit-Distanzen (Kostenmatrix)
@@ -72,8 +73,8 @@ def hirschberg_algorithm(
word_y = align.as_string2();
# verbose output hier behandeln (irrelevant für Algorithmus):
if verb != VerboseMode.NONE:
if DisplayOptions.TREE in show:
if verb != []:
if EnumHirschbergShow.tree in show:
display = align.astree(braces=True);
else:
display_x = align.as_string1(braces=True);
@@ -87,8 +88,8 @@ def hirschberg_algorithm_step(
X: str,
Y: str,
depth: int = 0,
verb: VerboseMode = VerboseMode.NONE,
show: List[DisplayOptions] = [],
verb: List[EnumHirschbergVerbosity] = [],
show: List[EnumHirschbergShow] = [],
) -> Alignment:
'''
Der rekursive Schritt der Hirschberg-Algorithmus teil eines der Wörter in zwei
@@ -105,7 +106,7 @@ def hirschberg_algorithm_step(
word_x, word_y = reconstruct_words(X = '-' + X, Y = '-' + Y, moves=[Moves[coord] for coord in path], path=path);
# verbose output hier behandeln (irrelevant für Algorithmus):
if verb != VerboseMode.NONE and (DisplayOptions.ATOMS in show):
if verb != [] and (EnumHirschbergShow.atoms in show):
repr = display_cost_matrix(Costs=Costs, path=path, X = '-' + X, Y = '-' + Y, verb=verb);
print(f'\n\x1b[1mRekursionstiefe: {depth}\x1b[0m\n\n{repr}')
@@ -126,7 +127,7 @@ def hirschberg_algorithm_step(
Costs2, Moves2 = compute_cost_matrix(X = '-' + X2, Y = '-' + Y2);
# verbose output hier behandeln (irrelevant für Algorithmus):
if verb != VerboseMode.NONE:
if verb != []:
path1, path2 = reconstruct_optimal_path_halves(Costs1=Costs1, Costs2=Costs2, Moves1=Moves1, Moves2=Moves2);
repr = display_cost_matrix_halves(
Costs1 = Costs1,

View File

@@ -12,8 +12,6 @@ from src.thirdparty.types import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'VerboseMode',
'DisplayOptions',
'Directions',
'gap_penalty',
'missmatch_penalty',
@@ -23,16 +21,6 @@ __all__ = [
# ENUMS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class VerboseMode(Enum):
NONE = -1;
COSTS = 0;
MOVES = 1;
COSTS_AND_MOVES = 2;
class DisplayOptions(Enum):
TREE = 0;
ATOMS = 1;
class Directions(Enum):
UNSET = -1;
# Prioritäten hier setzen

View File

@@ -8,6 +8,7 @@
from src.thirdparty.types import *;
from src.thirdparty.maths import *;
from models.generated.commands import *;
from src.hirschberg.constants import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -29,7 +30,7 @@ def represent_cost_matrix(
path: List[Tuple[int, int]],
X: str,
Y: str,
verb: VerboseMode,
verb: List[EnumHirschbergVerbosity],
pad: bool = False,
) -> np.ndarray: # NDArray[(Any, Any), Any]:
m = len(X); # display vertically
@@ -42,28 +43,27 @@ def represent_cost_matrix(
table = np.full(shape=(3 + m, 3 + n), dtype=object, fill_value='');
# topmost rows:
table[0, 3:(3+n)] = [str(j) for j in range(n)];
table[1, 3:(3+n)] = [y for y in Y];
table[0, 3:(3+n)] = [ f'\x1b[2m{j}\x1b[0m' for j in range(n) ];
table[1, 3:(3+n)] = [ f'\x1b[1m{y}\x1b[0m' for y in Y ];
table[2, 3:(3+n)] = '--';
# leftmost columns:
table[3:(3+m), 0] = [str(i) for i in range(m)];
table[3:(3+m), 1] = [x for x in X];
table[3:(3+m), 0] = [ f'\x1b[2m{i}\x1b[0m' for i in range(m) ];
table[3:(3+m), 1] = [ f'\x1b[1m{x}\x1b[0m' for x in X ];
table[3:(3+m), 2] = '|';
if pad:
table[-3, 3:(3+n)] = '--';
table[3:(3+m), -1] = '|';
match verb:
case VerboseMode.MOVES:
table[3:(3+m), 3:(3+n)] = '\x1b[2m.\x1b[0m';
if EnumHirschbergVerbosity.costs in verb:
table[3:(3+m), 3:(3+n)] = Costs.copy();
if EnumHirschbergVerbosity.moves in verb:
for (i, j) in path:
table[3 + i, 3 + j] = '\x1b[31;1m*\x1b[0m';
case VerboseMode.COSTS | VerboseMode.COSTS_AND_MOVES:
table[3:(3+m), 3:(3+n)] = Costs.copy();
if verb == VerboseMode.COSTS_AND_MOVES:
for (i, j) in path:
table[3 + i, 3 + j] = f'\x1b[31;4;1m{table[3 + i, 3 + j]}\x1b[0m';
table[3 + i, 3 + j] = f'\x1b[31;4;1m{table[3 + i, 3 + j]}\x1b[0m';
elif EnumHirschbergVerbosity.moves in verb:
table[3:(3+m), 3:(3+n)] = '\x1b[2m.\x1b[0m';
for (i, j) in path:
table[3 + i, 3 + j] = '\x1b[31;1m*\x1b[0m';
return table;
@@ -72,7 +72,7 @@ def display_cost_matrix(
path: List[Tuple[int, int]],
X: str,
Y: str,
verb: VerboseMode,
verb: EnumHirschbergVerbosity,
) -> str:
'''
Zeigt Kostenmatrix + optimalen Pfad.
@@ -99,7 +99,7 @@ def display_cost_matrix_halves(
X2: str,
Y1: str,
Y2: str,
verb: VerboseMode,
verb: EnumHirschbergVerbosity,
) -> str:
'''
Zeigt Kostenmatrix + optimalen Pfad für Schritt im D & C Hirschberg-Algorithmus

View File

@@ -0,0 +1,61 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.misc import *;
from src.thirdparty.config import *;
from src.thirdparty.code import *;
from src.thirdparty.types import *;
from models.generated.config import *;
from models.generated.commands import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'INFO',
'OPTIONS',
'COMMANDS',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CONSTANTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PATH_ASSETS_CONFIG: str = 'assets/config.yaml';
PATH_ASSETS_COMMANDS: str = 'assets/commands.yaml';
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# LAZY LOADED RESOURCES
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def load_assets_config(path: str) -> Config: # pragma: no cover
with open(path, 'r') as fp:
assets = yaml_load(fp, Loader=yaml_FullLoader);
assert isinstance(assets, dict);
return Config(**assets);
def create_commands(path: str) -> List[Command]: # pragma: no cover
commands = [];
with open(path, 'r') as fp:
assets = yaml_load(fp, Loader=yaml_FullLoader);
for command in assets:
match Command(**command).name:
case EnumAlgorithmNames.tarjan:
commands.append(CommandTarjan(**command));
case EnumAlgorithmNames.tsp:
commands.append(CommandTsp(**command));
case EnumAlgorithmNames.hirschberg:
commands.append(CommandHirschberg(**command));
return commands;
# use lazy loaing to ensure that values only loaded (once) when used
CONFIG: Config = lazy(load_assets_config, path=PATH_ASSETS_CONFIG);
INFO: Info = lazy(lambda x: x.info, CONFIG);
OPTIONS: AppOptions = lazy(lambda x: x.options, CONFIG);
COMMANDS: List[Command] = lazy(create_commands, path=PATH_ASSETS_COMMANDS);

43
code/python/src/thirdparty/code.py vendored Normal file
View File

@@ -0,0 +1,43 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from functools import wraps;
from functools import partial;
from dataclasses import dataclass;
from dataclasses import field;
from dataclasses import Field;
from dataclasses import asdict;
from dataclasses import MISSING;
from itertools import product as itertools_product;
# cf. https://github.com/mplanchard/safetywrap
from safetywrap import Ok;
from safetywrap import Err;
from safetywrap import Nothing;
from safetywrap import Result;
from safetywrap import Option;
from safetywrap import Some;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'partial',
'wraps',
'asdict',
'dataclass',
'field',
'Field',
'MISSING',
'itertools_product',
'Err',
'Nothing',
'Ok',
'Option',
'Result',
'Some',
];

View File

@@ -6,10 +6,12 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import json;
import jsonschema;
from lazy_load import lazy;
from yaml import add_constructor;
from yaml import load;
from yaml import Loader;
from yaml import FullLoader;
from yaml import load as yaml_load;
from yaml import FullLoader as yaml_FullLoader;
from yaml import add_path_resolver as yaml_add_path_resolver;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
@@ -17,8 +19,10 @@ from yaml import FullLoader;
__all__ = [
'json',
'jsonschema',
'lazy',
'add_constructor',
'load',
'Loader',
'FullLoader',
'yaml_load',
'yaml_FullLoader',
'yaml_add_path_resolver',
];

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.tsp.algorithms import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'tsp_algorithm',
];

View File

@@ -5,7 +5,6 @@
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import annotations;
from src.thirdparty.types import *;
from src.thirdparty.maths import *;
@@ -14,15 +13,15 @@ from src.thirdparty.maths import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'tsp_naive_algorithm',
'tsp_algorithm',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD tsp_naive_algorithm
# METHOD tsp_algorithm
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def tsp_naive_algorithm(
dist: NDArray[(Any, Any), float],
def tsp_algorithm(
dist: np.ndarray, # NDArray[(Any, Any), float],
optimise = min,
verbose: bool = False,
) -> tuple[float, list[list[int]]]: