From f584247866bde7f4debc98dfe80258fc557701b8 Mon Sep 17 00:00:00 2001 From: Janis Hutz Date: Tue, 13 Jan 2026 15:21:10 +0100 Subject: [PATCH] [NumCS] Update code in introduction --- semester3/numcs/numcs-summary.pdf | Bin 1455046 -> 1455170 bytes .../02_matrix-multiplication.tex | 15 +++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/semester3/numcs/numcs-summary.pdf b/semester3/numcs/numcs-summary.pdf index b93339743ac4a04eb75aa7a0fb5870be6526c9a8..df58ebd01595f66d56271bd458e49831d0c7bd3d 100644 GIT binary patch delta 13495 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

m#+uYu#i@Sku~LoK~VV|<5bwh1lCBt_Vl4Q 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 delta 13378 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 diff --git a/semester3/numcs/parts/00_introduction/02_matrix-multiplication.tex b/semester3/numcs/parts/00_introduction/02_matrix-multiplication.tex index 369823d..cfc1740 100644 --- a/semester3/numcs/parts/00_introduction/02_matrix-multiplication.tex +++ b/semester3/numcs/parts/00_introduction/02_matrix-multiplication.tex @@ -59,21 +59,24 @@ Sei $A = ab^\top$. Dann gilt $y = Ax \Leftrightarrow y = a(b^\top x)$, was dasse \inlineex Für zwei Matrizen $A, B \in \R^{n \times p}$ mit geringem Rang $p \ll n$, dann kann mithilfe eines Tricks die Rechenzeit von \verb|np.triu(A @ B.T) @ x| von $\tco{pn^2}$ auf $\tco{pn}$ reduziert werden. Die hier beschriebene Operation berechnet $\text{Upper}(AB^\top) x$ wobei $\text{Upper}(X)$ das obere Dreieck der Matrix $X$ zurück gibt. Wir nennen diese Matrix hier $R$. + \innumpy können wir den folgenden Ansatz verwenden, um die Laufzeit zu verringern: -Da die Matrix $R$ eine obere Dreiecksmatrix ist, ist das Ergebnis die Teilsummen von unserem Umgekehrten Vektor $x$, also können wir mit \verb|np.cumsum(x[::-1], axis=0)[::-1]| die Kummulative Summe berechnen. -Das \verb|[::-1]| dient hier lediglich dazu, den Vektor $x$ umzudrehen, sodass das richtige Resultat entsteht. +Da die Matrix $R$ eine obere Dreiecksmatrix ist, ist das Ergebnis die Teilsummen von unserem Umgekehrten Vektor $x$, +also können wir mit \verb|x[::-1].cumsum(axis=0)[::-1]| die Kummulative Summe berechnen. +Das \verb|[::-1]| dient hier lediglich dazu, den Vektor $x$ umzudrehen, sodass das richtige Resultat entsteht und die \texttt{axis=0} muss nur spezifiziert werden, +falls wir nicht den Default von \texttt{None} wollen, welcher die \texttt{cumsum} auf \texttt{x.flat} ausführt. Die vollständige Implementation sieht so aus: \begin{code}{python} def low_rank_matrix_vector_product(A: np.ndarray, B: np.ndarray, x: np.ndarray): - n, _ = A.shape - y = np.zeros(n) + n = A.shape[0] + y = np.zeros(n) # Results vector # Compute B * x with broadcasting (x needs to be reshaped to 2D) v = B * x[:, None] # s is defined as the reverse cummulative sum of our vector # (and we need it reversed again for the final calculation to be correct) - s = np.cumsum(v[::-1], axis=0)[::-1] + s = v[::-1].cumsum(axis=0)[::-1] y = np.sum(A * s) \end{code} @@ -93,7 +96,7 @@ Die vollständige Implementation sieht so aus: \end{bmatrix} \end{align*} -\fancyex{Multiplikation des Kronecker-Produkts mit Vektor} Wenn man $A \otimes B \cdot x$ berechnet, so ist die Laufzeit $\tco{m \times n \times l \times k}$, aber wenn wir den Vektor $x$ in $n$ gleich grosse Blöcke aufteilen (was man je nach gewünschter nachfolgender Operation in NumPy in $\tco{1}$ machen kann mit \verb|x.reshape(n, x.shape[0] / n)|), dann ist es möglich das Ganze in $\tco{m \cdot l \cdot k}$ zu berechnen. +\fancyex{Multiplikation des Kronecker-Produkts mit Vektor} Wenn man $A \otimes B \cdot x$ berechnet, so ist die Laufzeit $\tco{m \times n \times l \times k}$, aber wenn wir den Vektor $x$ in $n$ gleich grosse Blöcke aufteilen (was man je nach gewünschter nachfolgender Operation in NumPy in $\tco{1}$ machen kann mit \verb|x.reshape(n, x.shape[0] / n)|), dann ist es möglich das Ganze in $\tco{m \cdot l \cdot k}$ zu berechnen. Die vollständige Implementation ist auch hier nicht schwer und sieht folgendermassen aus: \begin{code}{python}