Strassen 矩阵乘法存储线性方程

Strassen matrix multiplication to store linear equations

我在课本中遇到的其中一个问题是:

In Computer Graphics transformations are applied on many vertices on the screen. Translation, Rotations
and Scaling.
Assume you’re operating on a vertex with 3 values (X, Y, 1). X, Y being the X Y coordinates and 1 is always
constant
A Translation is done on X as X = X + X’ and on Y as Y = Y + Y’
X’ and Y’ being the values to translate by
A scaling is done on X as X = aX and on Y as Y = bY
a and b being the scaling factors
Propose the best way to store these linear equations and an optimal way to calculate them on each vertex

暗示涉及到矩阵乘法和Strassen。但是,我不确定从哪里开始?它不涉及复杂的代码,它声明想出一些简单的东西来展示我的想法,但我遇到的所有 Strassen 实现绝对足够大,不会称为复杂。我的思维过程应该是怎样的?

我的矩阵看起来像这样吗?每个方程 3x3 还是我将它们合并为一个?

[ X X X']
[ Y Y Y']
[ 1 1 1 ]

您要查找的是一个变换矩阵,然后您可以使用它来将某个当前 (x, y) 点变换为下一个 (nx, ny) 点。也就是说,我们要

start = Vec([x, y, 1])
matrix = Matrix(...)

next = start * matrix  // * is matrix multiplication

现在,如果您的 next 应该看起来像 Vec([a * x + x', b * y + y', 1]),我们可以反向计算矩阵。首先,只看 x 组件。我们将有效地获取 start 向量与矩阵最顶行的点积,得到 a * x + x'.

如果我们更明确地写出来,我们想要a * x + 0 * y + x' * 1。希望这能让我们更容易看出我们想要点 start 的矢量是 Vec([a, 0, x'])。我们可以对矩阵的剩余两行重复此操作,并获得以下矩阵:

matrix = Matrix(
  [[a, 0, x'],
   [0, b, y'],
   [0, 0, 1]])

仔细检查这是否有意义并且对您来说似乎合理。如果我们将 start 向量与该矩阵相乘,我们将得到翻译后的向量 next 作为 Vec([a * x + x', b * y + y', 1]).

现在,为了真正的美,矩阵本身根本不关心我们的输入是什么,它是完全独立的。所以,我们可以一遍又一遍地重复应用这个矩阵,通过更多的缩放和平移向前迈进。

next_next_next = start * matrix * matrix * matrix

知道了这一点,我们实际上可以使用一些数学技巧非常快速地计算出前面的许多步骤。乘 matrix n 次等于乘以 matrixn 次方。幸运的是,我们有一种计算矩阵的幂的有效方法 - 它称为 exponentiation by squaring(实际上也适用于常规数字,但这里我们关注的是矩阵相乘,逻辑仍然适用)。简而言之,我们不是将数字或矩阵一遍又一遍地乘以 n 次,而是将其平方并在正确的时间将中间值乘以原始数字/矩阵,以非常快速地接近所需的幂(以对数表示(n) 乘法)。

这几乎可以肯定是您的教授希望您意识到的。您可以在 log(n) 时间内模拟 n 平移/缩放/旋转(是的,也有旋转矩阵)。

加倍努力

更酷的是,使用一些更高级的线性代数,您实际上可以做得更快。您可以对角化您的矩阵(意味着您将矩阵重写为 P * D * P^-1,即某个矩阵 P 与矩阵 D 的乘积,其中唯一的非零元素沿着主对角线,乘以 P 的倒数)。然后,您可以将这个对角化矩阵快速提高到 的幂 ,因为 (P * D * P^-1) * (P * D * P^-1) 简化为 P * D * D * P^-1,并且这概括为:

M^N = (P * D * P^-1)^N = (P * D^N * P^-1)

由于 D 在其对角线上只有非零元素,您可以通过将每个单独的元素提升到那个幂来提升它的任何幂,这只是整数乘法的正常成本,跨越许多元素,因为您的矩阵是 wide/tall。这是非常快的,然后你只需在两边做一个矩阵乘法就可以得到 M^N,然后用你的 start 向量乘以这个,得到你的最终结果。