Pythonfiles

This commit is contained in:
2025-12-28 17:47:23 +01:00
parent e21d39844b
commit cd0d60093e
4 changed files with 239 additions and 107 deletions

View File

@@ -1,81 +1,154 @@
import sympy as sp
from typing import List, Iterable, Tuple
from typing import Iterable, List, Sequence, Tuple, Optional
def raenderungsmatrix_G(
x0: sp.Matrix,
idx_X: List[int],
idx_Y: List[int],
idx_Z: List[int],
mit_massstab: bool = True,
class Datumsfestlegung:
@staticmethod
def datumskomponenten(
auswahl: Iterable[Tuple[str, str]],
liste_punktnummern: Sequence[str],
*,
layout: str = "XYZ"
) -> List[int]:
punkt2pos = {str(p): i for i, p in enumerate(liste_punktnummern)}
layout = layout.upper()
if layout != "XYZ":
raise ValueError("Nur layout='XYZ' unterstützt (wie bei euch).")
comp2off = {"X": 0, "Y": 1, "Z": 2}
aktive: List[int] = []
for pt, comp in auswahl:
spt = str(pt)
c = comp.upper()
if spt not in punkt2pos:
raise KeyError(f"Punkt '{pt}' nicht in liste_punktnummern.")
if c not in comp2off:
raise ValueError(f"Komponente '{comp}' ungültig. Nur X,Y,Z.")
p = punkt2pos[spt]
aktive.append(3 * p + comp2off[c])
# Duplikate entfernen
out, seen = [], set()
for i in aktive:
if i not in seen:
seen.add(i)
out.append(i)
return out
@staticmethod
def auswahlmatrix_E(u: int, aktive_unbekannte_indices: Iterable[int]) -> sp.Matrix:
E = sp.zeros(u, u)
for idx in aktive_unbekannte_indices:
i = int(idx)
if not (0 <= i < u):
raise IndexError(f"Aktiver Index {i} außerhalb [0,{u-1}]")
E[i, i] = 1
return E
@staticmethod
def raenderungsmatrix_G(
x0: sp.Matrix,
liste_punktnummern: Sequence[str],
*,
mit_massstab: bool = True,
layout: str = "XYZ",
) -> sp.Matrix:
if x0.cols != 1:
raise ValueError("x0 muss Spaltenvektor sein.")
layout = layout.upper()
if layout != "XYZ":
raise ValueError("Nur layout='XYZ' unterstützt (wie bei euch).")
u = x0.rows
d = 7 if mit_massstab else 6
G = sp.zeros(u, d)
nP = len(liste_punktnummern)
u = x0.rows
d = 7 if mit_massstab else 6
G = sp.zeros(u, d)
# --- Translationen ---
for i in idx_X:
G[i, 0] = 1
for i in idx_Y:
G[i, 1] = 1
for i in idx_Z:
G[i, 2] = 1
for p in range(nP):
ix, iy, iz = 3*p, 3*p+1, 3*p+2
xi, yi, zi = x0[ix, 0], x0[iy, 0], x0[iz, 0]
# --- Rotationen ---
# Rotation um X-Achse
for iy, iz in zip(idx_Y, idx_Z):
zi = x0[iz, 0]
yi = x0[iy, 0]
G[iy, 3] = -zi
G[iz, 3] = yi
# Translationen
G[ix, 0] = 1
G[iy, 1] = 1
G[iz, 2] = 1
# Rotation um Y-Achse
for ix, iz in zip(idx_X, idx_Z):
zi = x0[iz, 0]
xi = x0[ix, 0]
G[ix, 4] = zi
G[iz, 4] = -xi
# Rotationen
G[iy, 3] = -zi; G[iz, 3] = yi # Rx
G[ix, 4] = zi; G[iz, 4] = -xi # Ry
G[ix, 5] = -yi; G[iy, 5] = xi # Rz
# Rotation um Z-Achse
for ix, iy in zip(idx_X, idx_Y):
yi = x0[iy, 0]
xi = x0[ix, 0]
G[ix, 5] = -yi
G[iy, 5] = xi
# Maßstab
if mit_massstab:
G[ix, 6] = xi
G[iy, 6] = yi
G[iz, 6] = zi
# --- Maßstab ---
if mit_massstab:
for ix, iy, iz in zip(idx_X, idx_Y, idx_Z):
xi = x0[ix, 0]
yi = x0[iy, 0]
zi = x0[iz, 0]
G[ix, 6] = xi
G[iy, 6] = yi
G[iz, 6] = zi
return G
return G
@staticmethod
def berechne_dx_geraendert(N: sp.Matrix, n: sp.Matrix, Gi: sp.Matrix) -> sp.Matrix:
if N.rows != N.cols:
raise ValueError("N muss quadratisch sein.")
if n.cols != 1:
raise ValueError("n muss Spaltenvektor sein.")
if Gi.rows != N.rows:
raise ValueError("Gi hat falsche Zeilenzahl.")
def auswahlmatrix_E(u: int, aktive_unbekannte_indices: Iterable[int]) -> sp.Matrix:
E = sp.zeros(u, u)
for idx in aktive_unbekannte_indices:
E[int(idx), int(idx)] = 1
return E
u = N.rows
d = Gi.cols
K = N.row_join(Gi)
K = K.col_join(Gi.T.row_join(sp.zeros(d, d)))
rhs = n.col_join(sp.zeros(d, 1))
sol = K.LUsolve(rhs)
return sol[:u, :]
@staticmethod
def weiches_datum(
A: sp.Matrix,
dl: sp.Matrix,
Q_ll: sp.Matrix,
x0: sp.Matrix,
anschluss_indices: Sequence[int],
anschluss_werte: sp.Matrix,
Sigma_AA: Optional[sp.Matrix] = None,
) -> Tuple[sp.Matrix, sp.Matrix, sp.Matrix]:
if dl.cols != 1 or x0.cols != 1:
raise ValueError("dl und x0 müssen Spaltenvektoren sein.")
if A.rows != dl.rows:
raise ValueError("A.rows muss dl.rows entsprechen.")
if A.cols != x0.rows:
raise ValueError("A.cols muss x0.rows entsprechen.")
if Q_ll.rows != Q_ll.cols or Q_ll.rows != A.rows:
raise ValueError("Q_ll muss (n×n) sein und zu A.rows passen.")
def teilspurminimierung_Gi(G: sp.Matrix, E: sp.Matrix) -> sp.Matrix:
Gi = E * G
return Gi
u = A.cols
idx = [int(i) for i in anschluss_indices]
m = len(idx)
if anschluss_werte.cols != 1 or anschluss_werte.rows != m:
raise ValueError("anschluss_werte muss (m×1) sein.")
if Sigma_AA is None:
Sigma_AA = sp.eye(m)
if Sigma_AA.rows != m or Sigma_AA.cols != m:
raise ValueError("Sigma_AA muss (m×m) sein.")
def berechne_dx_geraendert(N: sp.Matrix, n: sp.Matrix, Gi: sp.Matrix) -> sp.Matrix:
u = N.rows
d = Gi.shape[1]
A_A = sp.zeros(m, u)
for r, j in enumerate(idx):
if not (0 <= j < u):
raise IndexError(f"Anschluss-Index {j} außerhalb [0,{u-1}]")
A_A[r, j] = 1
K = N.row_join(Gi)
K = K.col_join(Gi.T.row_join(sp.zeros(d, d)))
x0_A = sp.Matrix([[x0[j, 0]] for j in idx])
dl_A = anschluss_werte - x0_A
rhs = n.col_join(sp.zeros(d, 1))
A_ext = A.col_join(A_A)
dl_ext = dl.col_join(dl_A)
sol = K.LUsolve(rhs)
dx = sol[:u, :]
return dx
Q_ext = sp.zeros(Q_ll.rows + m, Q_ll.cols + m)
Q_ext[:Q_ll.rows, :Q_ll.cols] = Q_ll
Q_ext[Q_ll.rows:, Q_ll.cols:] = Sigma_AA
return A_ext, dl_ext, Q_ext