126 lines
4.1 KiB
Python
126 lines
4.1 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# IMPORTS
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
from src.thirdparty.types import *;
|
|
from src.thirdparty.maths import *;
|
|
|
|
from src.hirschberg.constants import *;
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# EXPORTS
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
__all__ = [
|
|
'get_optimal_transition',
|
|
'reconstruct_optimal_path',
|
|
'reconstruct_optimal_path_halves',
|
|
'reconstruct_words',
|
|
];
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# METHODS optimaler treffpunkt
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
def get_optimal_transition(
|
|
Costs1: np.ndarray, # NDArray[(Any, Any), int],
|
|
Costs2: np.ndarray, # NDArray[(Any, Any), int],
|
|
) -> Tuple[Tuple[int, int], Tuple[int, int]]:
|
|
'''
|
|
Rekonstruiere »Treffpunkt«, wo die Gesamtkosten minimiert sind.
|
|
Dieser Punkt stellt einen optimal Übergang für den Rekursionsschritt dar.
|
|
'''
|
|
(m, n1) = Costs1.shape;
|
|
(m, n2) = Costs2.shape;
|
|
info = [
|
|
(
|
|
Costs1[i, n1-1] + Costs2[m-1-i, n2-1],
|
|
(i, n1-1),
|
|
(m-1-i, n2-1),
|
|
)
|
|
for i in range(m)
|
|
];
|
|
index = np.argmin([ cost for cost, _, _ in info ]);
|
|
coord1 = info[index][1];
|
|
coord2 = info[index][2];
|
|
return coord1, coord2;
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# METHODS reconstruction von words/paths
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
def reconstruct_optimal_path(
|
|
Moves: np.ndarray, # NDArray[(Any, Any), Directions],
|
|
coord: Optional[Tuple[int, int]] = None,
|
|
) -> List[Tuple[int, int]]:
|
|
'''
|
|
Liest Matrix mit optimalen Schritten den optimalen Pfad aus,
|
|
angenfangen von Endkoordinaten.
|
|
'''
|
|
if coord is None:
|
|
m, n = Moves.shape;
|
|
(i, j) = (m-1, n-1);
|
|
else:
|
|
(i, j) = coord;
|
|
path = [(i, j)];
|
|
while (i, j) != (0, 0):
|
|
match Moves[i, j]:
|
|
case Directions.DIAGONAL:
|
|
(i, j) = (i - 1, j - 1);
|
|
case Directions.HORIZONTAL:
|
|
(i, j) = (i, j - 1);
|
|
case Directions.VERTICAL:
|
|
(i, j) = (i - 1, j);
|
|
case _:
|
|
break;
|
|
path.append((i, j));
|
|
return path[::-1];
|
|
|
|
def reconstruct_optimal_path_halves(
|
|
Costs1: np.ndarray, # NDArray[(Any, Any), int],
|
|
Costs2: np.ndarray, # NDArray[(Any, Any), int],
|
|
Moves1: np.ndarray, # NDArray[(Any, Any), Directions],
|
|
Moves2: np.ndarray, # NDArray[(Any, Any), Directions],
|
|
) -> Tuple[List[Tuple[int, int]], List[Tuple[int, int]]]:
|
|
'''
|
|
Rekonstruiere optimale Pfad für Rekursionsschritt,
|
|
wenn horizontales Wort in 2 aufgeteilt wird.
|
|
'''
|
|
coord1, coord2 = get_optimal_transition(Costs1=Costs1, Costs2=Costs2);
|
|
path1 = reconstruct_optimal_path(Moves1, coord=coord1);
|
|
path2 = reconstruct_optimal_path(Moves2, coord=coord2);
|
|
return path1, path2;
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# METHODS reconstruction von words
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
def reconstruct_words(
|
|
X: str,
|
|
Y: str,
|
|
moves: List[Directions],
|
|
path: List[Tuple[int, int]],
|
|
) -> Tuple[str, str]:
|
|
'''
|
|
Berechnet String-Alignment aus Path.
|
|
'''
|
|
word_x = '';
|
|
word_y = '';
|
|
for ((i, j), move) in zip(path, moves):
|
|
x = X[i];
|
|
y = Y[j];
|
|
match move:
|
|
case Directions.DIAGONAL:
|
|
word_x += x;
|
|
word_y += y;
|
|
case Directions.HORIZONTAL:
|
|
word_x += '-';
|
|
word_y += y;
|
|
case Directions.VERTICAL:
|
|
word_x += x;
|
|
word_y += '-';
|
|
return word_x, word_y;
|