APL 点运算符的语义?

Semantics of APL dot operator?

圆点.可以用来实现不同类型的产品。例如,

1 2 3 +.× 4 5 6

我假设 a f.g b 的语义是:计算 g(a[i], b[i]) 然后减少使用 f。也就是说,

dot f g = f/a g¨ b ⍝ map g between a and b, and then reduce using f

为了验证这一点,我写道:

    ]display  a ← ⍳ 4 ⋄ b ← 4 +⍳ 4 ⋄  I ← { ((⊂ ⍺), (⊂ ⍵))} ⋄ a I.I b
┌─────────────────────────────────────┐
│ ┌→────────────────────────────────┐ │
│ │ ┌→──┐ ┌→──────────────────────┐ │ │
│ │ │1 5│ │ ┌→──┐ ┌→────────────┐ │ │ │
│ │ └~──┘ │ │2 6│ │ ┌→──┐ ┌→──┐ │ │ │ │
│ │       │ └~──┘ │ │3 7│ │4 8│ │ │ │ │
│ │       │       │ └~──┘ └~──┘ │ │ │ │
│ │       │       └∊────────────┘ │ │ │
│ │       └∊──────────────────────┘ │ │
│ └∊────────────────────────────────┘ │
└∊────────────────────────────────────┘

我们可以清楚地看到元素的右折叠,因为它首先映射 I 创建 (1 5) (2 6) (3 7) (4 8) 然后使用 I 折叠创建嵌套结构, 所以我的定义似乎有效!


但是,这不适用于矩阵:

      ]display a ← 2 2 ⍴ ⍳ 4 ⋄ b ← 4 + 2 2 ⍴ ⍳ 4 ⋄   I ← { ((⊂ ⍺), (⊂ ⍵))} ⋄ a I.I b
┌→────────────────────────────────┐
↓ ┌→────────────┐ ┌→────────────┐ │
│ │ ┌→──┐ ┌→──┐ │ │ ┌→──┐ ┌→──┐ │ │
│ │ │1 5│ │2 7│ │ │ │1 6│ │2 8│ │ │
│ │ └~──┘ └~──┘ │ │ └~──┘ └~──┘ │ │
│ └∊────────────┘ └∊────────────┘ │
│ ┌→────────────┐ ┌→────────────┐ │
│ │ ┌→──┐ ┌→──┐ │ │ ┌→──┐ ┌→──┐ │ │
│ │ │3 5│ │4 7│ │ │ │3 6│ │4 8│ │ │
│ │ └~──┘ └~──┘ │ │ └~──┘ └~──┘ │ │
│ └∊────────────┘ └∊────────────┘ │
└∊────────────────────────────────┘

有意思!所以在这种情况下它似乎实际上计算了它的元素之间的某种外积,而不是 "fold"?我对 . 运算符的假设定义不执行 同样的操作:

]display a ← 2 2 ⍴ ⍳ 4 ⋄ b ← 4 + 2 2 ⍴ ⍳ 4 ⋄   I ← { ((⊂ ⍺), (⊂ ⍵))} ⋄ I/a I¨b
┌→────────────────────────────────┐
│ ┌→────────────┐ ┌→────────────┐ │
│ │ ┌→──┐ ┌→──┐ │ │ ┌→──┐ ┌→──┐ │ │
│ │ │1 5│ │2 6│ │ │ │3 7│ │4 8│ │ │
│ │ └~──┘ └~──┘ │ │ └~──┘ └~──┘ │ │
│ └∊────────────┘ └∊────────────┘ │
└∊────────────────────────────────┘

那么,APL.(点)的实际语义是什么?我怎么会自己发现这个?

来自Dyalog help page on "Inner Product"

R←X f.g Y

The result of the derived function has shape (¯1↓⍴X),1↓⍴Y; each item is f/x g¨y where x and y are vectors taken from all the combinations of vectors along the last axis of X and the first axis of Y.

vector f.g vector的情况下,正如您已经观察到的那样,可以将其理解为f/ vector g¨ vector。但是,对于矩阵和高维数组,它变得更加复杂。

对于矩阵,最直接的用法(也是引用最多的用法)是 "matrix product" +.×。在数学上,对于 m×n 矩阵 X 和 n×p 矩阵 Y,X +.× Y 被定义为一个 m×p 矩阵,其在 [i;j] 处的元素是向量点积(和X 的第 i 行和 Y 的第 j 列的逐元素乘积)。有关说明,请参阅 Wikipedia page.

在这种情况下,数组 X(m×n 矩阵)的形状 () 为 m n,而 Y 的形状为 n p。结果的形状为 m p,等于 (¯1↓m n),1↓n p.

如果我们将此定义推广到任意函数 fg,(对于矩阵 X 和 Y),我们可以将 X f.g Y 定义为另一个矩阵,其元素为 "reduction by f" X 的每一行和 Y 的每一列的 "element-wise g"s。这正是文档在提到 f/x g¨ y 时所说的内容。此外,X 有 m 行,Y 有 p 列,因此计算 X 的每一行和 Y 的每一列的 所有组合 将精确地给出 m×p 值。

到目前为止,我们已经涵盖了文档一半以上的句子。那么"vectors along the last axis of X"是什么意思呢?对于形状为 m n 的矩阵 X,最后一个轴的长度为 n,因此矩阵 X 可以看作是 m 个长度为 n 的向量。类似地,"vectors along the first axis of Y" 表示将形状 n p 矩阵 Y 视为长度 np 个向量。然后两个长度-n向量(一个来自X,另一个来自Y)成为的参数,这意味着长度必须匹配。

我们也可以将这个概念推广到高维数组。如果我们有一个 a×b×c 数组 X,它有 a×b 个长度为 c 的向量(最后一个轴)。如果我们有另一个 c×d×e 数组 Y,它有 d×e 个长度为 c 的向量(第一个轴)。然后对向量的所有组合进行计算将得到 a×b×d×e 个元素,这自然会给出形状为 a b d e.

的结果数组

综上所述,X f.g Y相当于提取X的最后一个轴向量和Y的第一个轴向量并计算外积 f/ x g¨ y 在向量上:

a ← 2 3 3⍴⍳4
b ← 3 3 4⍴⍳5
f ← {⍺+⊂⍵}
g ← {⍺⍵}
⎕←(a f.g b) ≡ (↓[≢⍴a]a) ∘.{⊃ f/ ⍺ g¨ ⍵} (↓[1]b)

此程序打印 1,即 true。 Try it online!

内积 (f.g) 的定义实际上在方言之间略有不同。在下文中,我将忽略单例参数,因为它们被视为标量。

Dyalog 的定义

Dyalog's documentation leads to the model {⍺(⍺⍺⌿⍵⍵¨⍤¯1)⍤1 999⊢⍵}. Try it!

IBM 的定义

IBM's documentation leads to the Dyalog APL (!) model {⍺⍺/¨(⊂⍤1⊢⍺)∘.⍵⍵⍉⊂⍤1⍉⍵}. Try it!