4,577
edits
m (→Examples) |
(remove Category:Pages that use a deprecated format of the math tags) |
||
(17 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
{{Built-in|Inner Product|<nowiki>.</nowiki>}} | {{Built-in|Inner Product|<nowiki>.</nowiki>}} is a [[dyadic operator]] that produces a [[dyadic function]] when applied with two dyadic functions. It's a generalisation of the [[wikipedia:Matrix multiplication|matrix product]], allowing not just addition-multiplication, but any [[dyadic function]]s given as [[operand]]s. | ||
== Examples == | == Examples == | ||
< | <syntaxhighlight lang=apl> | ||
x ← 1 2 3 | x ← 1 2 3 | ||
y ← 4 5 6 | y ← 4 5 6 | ||
x ,.( | x ,.(⊂,) y ⍝ visualizing of pairing | ||
┌─────────────┐ | ┌─────────────┐ | ||
│┌───┬───┬───┐│ | │┌───┬───┬───┐│ | ||
Line 11: | Line 11: | ||
│└───┴───┴───┘│ | │└───┴───┴───┘│ | ||
└─────────────┘ | └─────────────┘ | ||
x {⊂⍺,'+',⍵}.{⊂⍺,'×',⍵} y ⍝ visualizing function application in matrix multiplication | |||
┌───────────────────────────┐ | |||
│┌─────────────────────────┐│ | |||
││┌─────┬─┬───────────────┐││ | |||
│││1 × 4│+│┌─────┬─┬─────┐│││ | |||
│││ │ ││2 × 5│+│3 × 6││││ | |||
│││ │ │└─────┴─┴─────┘│││ | |||
││└─────┴─┴───────────────┘││ | |||
│└─────────────────────────┘│ | |||
└───────────────────────────┘ | |||
x+.×y ⍝ matrix multiplication | x+.×y ⍝ matrix multiplication | ||
32 | 32 | ||
</ | </syntaxhighlight> | ||
The [[shape]]s of the arguments must be compatible with each other: The last [[axis]] of the left argument must have the same length as the first axis of the right argument, or formally, for <syntaxhighlight lang=apl inline>X f.g Y</syntaxhighlight> it must be that <syntaxhighlight lang=apl inline>(¯1↑⍴X)≡(1↑⍴Y)</syntaxhighlight>. Although this rule differs from [[conformability]], the arguments may also be subject to [[scalar extension|scalar]] or [[singleton extension]]. The shape of the result is <syntaxhighlight lang=apl inline>(¯1↓⍴X),(1↓⍴Y)</syntaxhighlight>. | |||
For example, when applying inner | For example, when applying inner product on two [[matrix|matrices]], the number of columns in the left array must match with number of rows in the right array, otherwise we will get an error. | ||
< | <syntaxhighlight lang=apl> | ||
⎕ ← x ← 2 3⍴⍳10 | ⎕ ← x ← 2 3⍴⍳10 | ||
1 2 3 | 1 2 3 | ||
Line 26: | Line 36: | ||
3 4 | 3 4 | ||
5 6 | 5 6 | ||
7 8 | 7 8 | ||
x+.×y | x+.×y | ||
LENGTH ERROR | LENGTH ERROR | ||
Line 35: | Line 45: | ||
22 28 | 22 28 | ||
49 64 | 49 64 | ||
</ | </syntaxhighlight> | ||
== History == | |||
Inner product appeared in early [[Iverson Notation]] as <math>^f_g</math> and applied even to non-[[scalar function]]s, like [[Compress]], Iverson bringing:<ref>[[Ken Iverson]]. [[A Programming Language]]. §1.11 ''The language''.</ref> | |||
:<math> | |||
\begin{align} | |||
\text{For example, if}\\ | |||
\boldsymbol{A}&=\begin{pmatrix} | |||
1&3&2&0\\ | |||
2&1&0&1\\ | |||
4&0&0&2\\ | |||
\end{pmatrix} | |||
\qquad\text{and}\qquad | |||
\boldsymbol{B}=\begin{pmatrix} | |||
4&1\\ | |||
0&3\\ | |||
0&2\\ | |||
2&0\\ | |||
\end{pmatrix}\\ | |||
\text{then}\qquad\boldsymbol{A}\;^+_\times\,\boldsymbol{B}&=\begin{pmatrix} | |||
4&14\\ | |||
10&5\\ | |||
20&4\\ | |||
\end{pmatrix}, | |||
\quad\boldsymbol{A}\;^\land_=\,\boldsymbol{B}=\begin{pmatrix} | |||
0&1\\ | |||
0&0\\ | |||
1&0\\ | |||
\end{pmatrix}\text{,}\\ | |||
\boldsymbol{A}\;^\lor_\neq\;\boldsymbol{B}&=\begin{pmatrix} | |||
1&0\\ | |||
1&1\\ | |||
0&1\\ | |||
\end{pmatrix}, | |||
\qquad\text{and}\qquad(\boldsymbol{A}\neq0)\;^+_{\,/}\,\boldsymbol{B}=\begin{pmatrix} | |||
4&6\\ | |||
6&4\\ | |||
6&1\\ | |||
\end{pmatrix}\text{.} | |||
\end{align} | |||
</math> | |||
When the inner product notation was linearised (made to fit on a single line of code) the [[glyph]] <syntaxhighlight lang=apl inline>.</syntaxhighlight> was chosed to denote what was previously indicated by positioning the two [[operand]]s vertically aligned. Thus, the above correspond to the following modern APL: | |||
<syntaxhighlight lang=apl> | |||
⍝ For example, if | |||
A←3 4⍴1 3 2 0 2 1 0 1 4 0 0 2 | |||
B←4 2⍴4 1 0 3 0 2 2 0 | |||
⍝ then | |||
A +.× B | |||
4 14 | |||
10 5 | |||
20 4 | |||
A ∧.= B | |||
0 1 | |||
0 0 | |||
1 0 | |||
A ∨.≠ B | |||
1 0 | |||
1 1 | |||
0 1 | |||
(A ≠ 0) +./ B | |||
4 6 | |||
6 4 | |||
6 1 | |||
</syntaxhighlight> | |||
Note that some dialects implement [[Compress]] (<syntaxhighlight lang=apl inline>/</syntaxhighlight>) as a [[monadic operator]] rather than as a function, which means it cannot be an operand in the inner product. Instead, a cover function is necessary: | |||
<syntaxhighlight lang=apl> | |||
∇z←a Compress b | |||
z←a/b | |||
∇ | |||
</syntaxhighlight> | |||
== Differences between dialects == | |||
Implementations differ on the exact behaviour of inner product when the right operand is not a [[scalar function]]. It follows from page 121 of the ISO/IEC 13751:2001(E) [[standard]] specifies that <syntaxhighlight lang=apl inline>X f.g Y</syntaxhighlight> is equivalent to <syntaxhighlight lang=apl inline>f/¨ (⊂[⍴⍴x]x)∘.g ⊂[1]y</syntaxhighlight>. This is indeed what [[APL2]], [[APLX]], [[APL+Win]], and [[ngn/apl]] follow, while [[Dyalog APL]], [[NARS2000]] and [[GNU APL]] differ as described by [[Roger Hui]]:<ref>[[Roger Hui]]. ''inner product''. Internal Dyalog email. 24 July 2020.</ref> | |||
<blockquote> | |||
The following dop models inner product in Dyalog APL, with caveats. If you find a case where <syntaxhighlight lang=apl inline>f.g</syntaxhighlight> differs from <syntaxhighlight lang=apl inline>f IP g</syntaxhighlight>, not covered by the caveats, I'd be interested. | |||
<syntaxhighlight lang=apl> | |||
IP←{ | |||
assert((⊃⌽⍴⍺)≡≢⍵)∨(1=×/⍴⍺)∨1=×/⍴⍵: | |||
⊃⍤0 ⊢ (↓⍺) ∘.(⍺⍺/⍵⍵¨) ↓(¯1⌽⍳⍴⍴⍵)⍉⍵ | |||
} | |||
assert←{⍺←'assertion failure' ⋄ 0∊⍵:⍺ ⎕SIGNAL 8 ⋄ shy←0} | |||
</syntaxhighlight> | |||
(Explanation: What's with the <syntaxhighlight lang=apl inline>⊃⍤0</syntaxhighlight> in <syntaxhighlight lang=apl inline>IP</syntaxhighlight>? It's because <syntaxhighlight lang=apl inline>∘.f</syntaxhighlight> has an implicit each, applying <syntaxhighlight lang=apl inline>⊂</syntaxhighlight> to each item of its result. But the <syntaxhighlight lang=apl inline>⍺⍺/</syntaxhighlight> in <syntaxhighlight lang=apl inline>(⍺⍺/⍵⍵¨)</syntaxhighlight> also has an implicit each. So the <syntaxhighlight lang=apl inline>⊃⍤0</syntaxhighlight> gets rid of one of those encloses.) | |||
Caveats: | |||
* You can not use the hybrid <syntaxhighlight lang=apl inline>/</syntaxhighlight> directly as an operand as it runs afoul of the parser in weird and wonderful ways. Instead, you have to use <syntaxhighlight lang=apl inline>{⍺/⍵}</syntaxhighlight>. The same goes for <syntaxhighlight lang=apl inline>\</syntaxhighlight> and <syntaxhighlight lang=apl inline>{⍺\⍵}</syntaxhighlight> I guess. | |||
* It differs from ISO/IEC 13751:2001(E) in using <syntaxhighlight lang=apl inline>⍵⍵¨</syntaxhighlight> instead of just <syntaxhighlight lang=apl inline>⍵⍵</syntaxhighlight> in the central key expression (i.e. <syntaxhighlight lang=apl inline>(⍺⍺/⍵⍵¨)</syntaxhighlight> instead of <syntaxhighlight lang=apl inline>(⍺⍺/⍵⍵)</syntaxhighlight>). So does the primitive <syntaxhighlight lang=apl inline>f.g</syntaxhighlight>. | |||
* It differs from ISO/IEC 13751:2001(E) in doing full-blown single extension instead of just scalar and 1-element vector extension (as in APL2). So does the primitive <syntaxhighlight lang=apl inline>f.g</syntaxhighlight>. e.g.<syntaxhighlight lang=apl> | |||
(3 4⍴5)+.×1 1 1 1⍴6 ⍝ works in Dyalog, not in ISO or APL2</syntaxhighlight> | |||
* It differs from NARS2000 or APL\360 in not permitting unit axis extension. So does the primitive <syntaxhighlight lang=apl inline>f.g</syntaxhighlight>. e.g.<syntaxhighlight lang=apl> | |||
(3 4⍴5)+.×1 5⍴6 ⍝ works in NARS2000 or APL\360, not in Dyalog APL</syntaxhighlight> | |||
</blockquote> | |||
== External links == | |||
=== Documentation === | |||
* [https://help.dyalog.com/latest/#Language/Primitive%20Operators/Inner%20Product.htm Dyalog] | |||
* [https://microapl.com/apl_help/ch_020_020_880.htm APLX] | |||
* J [https://www.jsoftware.com/help/dictionary/d300.htm Dictionary], [https://code.jsoftware.com/wiki/Vocabulary/dot#dyadic NuVoc] | |||
=== Discussion of differences between dialects === | |||
* [https://groups.google.com/g/comp.lang.apl/c/23LrwRZKmPs Dyalog / APL2000 discrepancy] (Google Groups) | |||
* [https://lists.gnu.org/archive/html/bug-apl/2016-07/msg00020.html multiple inner product] (GNU APL mailing list) | |||
* [https://lists.gnu.org/archive/html/bug-apl/2018-05/msg00003.html an other inner product ,., bug] (GNU APL mailing list) | |||
== References == | |||
<references/> | |||
{{APL built-ins}}[[Category:Primitive operators]] |