From 67aa70edfa45f33f5aceb228744fec093f86cc99 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Thu, 9 Jun 2022 15:14:03 +0200 Subject: [PATCH] master > master: code py - verbose/display mode als enum --- code/python/src/main.py | 9 ++- .../python/src/string_alignment/hirschberg.py | 77 +++++++++---------- 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/code/python/src/main.py b/code/python/src/main.py index 87ecea2..2da3148 100644 --- a/code/python/src/main.py +++ b/code/python/src/main.py @@ -41,8 +41,8 @@ def enter(): # verbose=True, # ); ## Beispiel für Seminarwoche 10 (Blatt 9): - # hirschberg_algorithm_once( - hirschberg_algorithm( + hirschberg_algorithm_once( + # hirschberg_algorithm( # Y = 'ANSPANNEN', # X = 'ANSTRENGEN', # Y = 'AGAT', @@ -51,8 +51,9 @@ def enter(): X = 'happily ever, lol', # Y = 'apple', # X = 'happily', - verbose = True, - just_moves = False, + mode = DisplayMode.COSTS, + # mode = DisplayMode.MOVES, + # mode = DisplayMode.COSTS_AND_MOVES, ); return; diff --git a/code/python/src/string_alignment/hirschberg.py b/code/python/src/string_alignment/hirschberg.py index c347789..5c27c33 100644 --- a/code/python/src/string_alignment/hirschberg.py +++ b/code/python/src/string_alignment/hirschberg.py @@ -18,12 +18,19 @@ from src.local.maths import *; __all__ = [ 'hirschberg_algorithm', 'hirschberg_algorithm_once', + 'DisplayMode' ]; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # CONSTANTS / SETUP # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class DisplayMode(Enum): + NONE = -1; + COSTS = 0; + MOVES = 1; + COSTS_AND_MOVES = 2; + class Directions(Enum): UNSET = -1; # Prioritäten hier setzen @@ -44,14 +51,13 @@ def missmatch_penalty(x: str, y: str): def hirschberg_algorithm_once( X: str, Y: str, - verbose: bool = False, - just_moves: bool = False, + mode: DisplayMode = DisplayMode.NONE, ) -> Tuple[str, str]: 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 verbose: - repr = display_cost_matrix(Costs=Costs, path=path, X = '-' + X, Y = '-' + Y, just_moves=just_moves); + if mode != DisplayMode.NONE: + repr = display_cost_matrix(Costs=Costs, path=path, X = '-' + X, Y = '-' + Y, mode=mode); print(f'\n{repr}'); print(f'\n\x1b[1mOptimales Alignment:\x1b[0m'); print(''); @@ -64,13 +70,12 @@ def hirschberg_algorithm_once( def hirschberg_algorithm( X: str, Y: str, - verbose: bool = False, - just_moves: bool = False, + mode: DisplayMode = DisplayMode.NONE, ) -> Tuple[str, str]: - alignments_x, alignments_y = hirschberg_algorithm_step(X=X, Y=Y, depth=1, verbose=verbose, just_moves=just_moves); + alignments_x, alignments_y = hirschberg_algorithm_step(X=X, Y=Y, depth=1, mode=mode); word_x = ''.join(alignments_x); word_y = ''.join(alignments_y); - if verbose: + if mode != DisplayMode.NONE: display_x = f'[{"][".join(alignments_x)}]'; display_y = f'[{"][".join(alignments_y)}]'; print(f'\n\x1b[1mOptimales Alignment:\x1b[0m'); @@ -85,8 +90,7 @@ def hirschberg_algorithm_step( X: str, Y: str, depth: int = 0, - verbose: bool = False, - just_moves: bool = False, + mode: DisplayMode = DisplayMode.NONE, ) -> Tuple[List[str], List[str]]: n = len(Y); if n == 1: @@ -112,7 +116,7 @@ def hirschberg_algorithm_step( Costs1, Moves1 = compute_cost_matrix(X = '-' + X1, Y = '-' + Y1); Costs2, Moves2 = compute_cost_matrix(X = '-' + X2, Y = '-' + Y2); - if verbose: + if mode != DisplayMode.NONE: path1, path2 = reconstruct_optimal_path_halves(Costs1=Costs1, Costs2=Costs2, Moves1=Moves1, Moves2=Moves2); repr = display_cost_matrix_halves( Costs1 = Costs1, @@ -123,7 +127,7 @@ def hirschberg_algorithm_step( X2 = '-' + X2, Y1 = '-' + Y1, Y2 = '-' + Y2, - just_moves = just_moves, + mode = mode, ); print(f'\n\x1b[1mRekursionstiefe: {depth}\x1b[0m\n\n{repr}') @@ -131,8 +135,8 @@ def hirschberg_algorithm_step( coord1, coord2 = get_optimal_transition(Costs1=Costs1, Costs2=Costs2); p = coord1[0]; # Divide and Conquer ausführen: - alignments_x_1, alignments_y_1 = hirschberg_algorithm_step(X=X[:p], Y=Y[:n], depth=depth+1, verbose=verbose, just_moves=just_moves); - alignments_x_2, alignments_y_2 = hirschberg_algorithm_step(X=X[p:], Y=Y[n:], depth=depth+1, verbose=verbose, just_moves=just_moves); + alignments_x_1, alignments_y_1 = hirschberg_algorithm_step(X=X[:p], Y=Y[:n], depth=depth+1, verbose=verbose, mode=mode); + alignments_x_2, alignments_y_2 = hirschberg_algorithm_step(X=X[p:], Y=Y[n:], depth=depth+1, verbose=verbose, mode=mode); # Resultate zusammensetzen: alignments_x = alignments_x_1 + alignments_x_2; @@ -355,8 +359,9 @@ def represent_cost_matrix( path: List[Tuple[int, int]], X: str, Y: str, + mode: DisplayMode, pad: bool = False, -) -> Tuple[NDArray[(Any, Any), Any], NDArray[(Any, Any), Any]]: +) -> NDArray[(Any, Any), Any]: m = len(X); # display vertically n = len(Y); # display horizontally @@ -379,22 +384,25 @@ def represent_cost_matrix( table[-3, 3:(3+n)] = '--'; table[3:(3+m), -1] = '|'; - table_costs = table.copy(); - table_moves = table.copy(); - table_costs[3:(3+m), 3:(3+n)] = Costs.copy(); - table_moves[3:(3+m), 3:(3+n)] = '·'; - for (i, j) in path: - table_costs[3 + i, 3 + j] = f'{{{table_costs[3 + i, 3 + j]}}}'; - table_moves[3 + i, 3 + j] = '*'; + match mode: + case DisplayMode.MOVES: + table[3:(3+m), 3:(3+n)] = '.'; + for (i, j) in path: + table[3 + i, 3 + j] = '*'; + case DisplayMode.COSTS | DisplayMode.COSTS_AND_MOVES: + table[3:(3+m), 3:(3+n)] = Costs.copy(); + if mode == DisplayMode.COSTS_AND_MOVES: + for (i, j) in path: + table[3 + i, 3 + j] = f'{{{table[3 + i, 3 + j]}}}'; - return table_costs, table_moves; + return table; def display_cost_matrix( Costs: NDArray[(Any, Any), int], path: List[Tuple[int, int]], X: str, Y: str, - just_moves: bool = False, + mode: DisplayMode, ) -> str: ''' Zeigt Kostenmatrix + optimalen Pfad. @@ -407,13 +415,7 @@ def display_cost_matrix( @returns - eine 'printable' Darstellung der Matrix mit den Strings X, Y + Indexes. ''' - table_costs, table_moves = represent_cost_matrix(Costs=Costs, path=path, X=X, Y=Y); - # benutze pandas-Dataframe, um schöner darzustellen: - if just_moves: - table = table_moves; - else: - table = table_costs; - + table = represent_cost_matrix(Costs=Costs, path=path, X=X, Y=Y, mode=mode); # benutze pandas-Dataframe + tabulate, um schöner darzustellen: repr = tabulate(pd.DataFrame(table), showindex=False, stralign='center', tablefmt='plain'); return repr; @@ -427,7 +429,7 @@ def display_cost_matrix_halves( X2: str, Y1: str, Y2: str, - just_moves: bool = False, + mode: DisplayMode, ) -> str: ''' Zeigt Kostenmatrix + optimalen Pfad für Schritt im D & C Hirschberg-Algorithmus @@ -440,16 +442,11 @@ def display_cost_matrix_halves( @returns - eine 'printable' Darstellung der Matrix mit den Strings X, Y + Indexes. ''' - table_costs1, table_moves1 = represent_cost_matrix(Costs=Costs1, path=path1, X=X1, Y=Y1, pad=True); - table_costs2, table_moves2 = represent_cost_matrix(Costs=Costs2, path=path2, X=X2, Y=Y2, pad=True); + table1 = represent_cost_matrix(Costs=Costs1, path=path1, X=X1, Y=Y1, mode=mode, pad=True); + table2 = represent_cost_matrix(Costs=Costs2, path=path2, X=X2, Y=Y2, mode=mode, pad=True); # merge Taellen: - table_costs = np.concatenate([table_costs1[:, :-1], table_costs2[::-1, ::-1]], axis=1); - table_moves = np.concatenate([table_moves1[:, :-1], table_moves2[::-1, ::-1]], axis=1); - if just_moves: - table = table_moves; - else: - table = table_costs; + table = np.concatenate([table1[:, :-1], table2[::-1, ::-1]], axis=1); # benutze pandas-Dataframe + tabulate, um schöner darzustellen: repr = tabulate(pd.DataFrame(table), showindex=False, stralign='center', tablefmt='plain');