3,038
edits
m (Move link to Roger Hui paper to External Links section) Tags: Mobile edit Mobile web edit |
m (→Differences between dialects: ISO/IEC 13751:2001 link) |
||
(7 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
{{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. | {{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. | ||
== Description == | |||
For each rank-1 cell in the arguments, inner product applies <syntaxhighlight lang=apl inline>⍵⍵</syntaxhighlight> between the two and then applies <syntaxhighlight lang=apl inline>⍺⍺⌿</syntaxhighlight> to the results of those invocations. If the arguments themselves are simply vectors, there is only one rank-1 cell in each argument, so this results in the following application pattern: | |||
<syntaxhighlight lang=apl> | |||
1 2 3 4 F.G 5 6 7 8 | |||
(1 G 5) F (2 G 6) F (3 G 7) F (4 G 8) | |||
</syntaxhighlight> | |||
The second line is an illustration of how the first will be evaluated. Note that this is precisely the [[wikipedia:Dot product|vector dot product]] when used as <syntaxhighlight lang=apl inline>+.×</syntaxhighlight>. (This simple invocation with vector arguments will be referred to as the "vector inner product" below, but it is just a simple case of the general inner product.) | |||
For matrix arguments, there may be more than one rank-1 cell. Considering the case of rank-2 matrices as arguments, if there are N rows in <syntaxhighlight lang=apl inline>⍺</syntaxhighlight> and M columns in <syntaxhighlight lang=apl inline>⍵</syntaxhighlight>, the result will be a matrix with N rows and M columns. Each row of the resulting matrix will correspond to the elements of that same row in <syntaxhighlight lang=apl inline>⍺</syntaxhighlight> being paired up with elements in a column of <syntaxhighlight lang=apl inline>⍵</syntaxhighlight>. Likewise, each column of the resulting matrix will correspond to the elements of that same column of <syntaxhighlight lang=apl inline>⍵</syntaxhighlight> being paired up with elements in a row of <syntaxhighlight lang=apl inline>⍺</syntaxhighlight>. '''Important: This means that the inner product will be applied for each ''row'' of <syntaxhighlight lang=apl inline>⍺</syntaxhighlight> but each ''column'' of <syntaxhighlight lang=apl inline>⍵</syntaxhighlight>!''' | |||
In practice, this means that the upper left element of the resulting matrix will correspond to performing the vector inner product on the first row of <syntaxhighlight lang=apl inline>⍺</syntaxhighlight> and the first column of <syntaxhighlight lang=apl inline>⍵</syntaxhighlight>, the upper right element will correspond to performing the vector inner product on the first row of <syntaxhighlight lang=apl inline>⍺</syntaxhighlight> and the last column of <syntaxhighlight lang=apl inline>⍵</syntaxhighlight>, the lower right element will correspond to the vector inner product on the last row of <syntaxhighlight lang=apl inline>⍺</syntaxhighlight> and the last column of <syntaxhighlight lang=apl inline>⍵</syntaxhighlight>, and so on and so on. Pictorially, then, for a 2x2 result we can represent the resulting matrix as: | |||
<syntaxhighlight lang=apl> | |||
┌──────────────────────────────┬──────────────────────────────┐ | |||
│(Row 1 of ⍺) F.G (Col. 1 of ⍵)│(Row 1 of ⍺) F.G (Col. 2 of ⍵)│ | |||
├──────────────────────────────┼──────────────────────────────┤ | |||
│(Row 2 of ⍺) F.G (Col. 1 of ⍵)│(Row 2 of ⍺) F.G (Col. 2 of ⍵)│ | |||
└──────────────────────────────┴──────────────────────────────┘ | |||
</syntaxhighlight> | |||
Note how the columns of <syntaxhighlight lang=apl inline>⍵</syntaxhighlight> align with the columns of the matrix, and the rows of <syntaxhighlight lang=apl inline>⍺</syntaxhighlight> align with the rows of the matrix. | |||
The concept readily generalizes to matrices of higher rank. | |||
== Examples == | == Examples == | ||
Line 116: | Line 141: | ||
== Differences between dialects == | == Differences between dialects == | ||
Implementations differ on the exact behaviour of inner product when the right operand is not a [[scalar function]]. Page 121 of the ISO/IEC 13751:2001 | Implementations differ on the exact behaviour of inner product when the right operand is not a [[scalar function]]. Page 121 of the [[ISO/IEC 13751:2001]] standard specifies that <syntaxhighlight lang=apl inline>X f.g Y</syntaxhighlight> is equivalent to <syntaxhighlight lang=apl>f/¨ (⊂[⍴⍴x]x)∘.g ⊂[1]y</syntaxhighlight> (assuming [[index origin]] 1). 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> | <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. | 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. | ||
Line 140: | Line 165: | ||
(3 4⍴5)+.×1 5⍴6 ⍝ works in NARS2000 or APL\360, not in Dyalog APL</syntaxhighlight> | (3 4⍴5)+.×1 5⍴6 ⍝ works in NARS2000 or APL\360, not in Dyalog APL</syntaxhighlight> | ||
</blockquote> | </blockquote> | ||
The <syntaxhighlight lang=apl | The <syntaxhighlight lang=apl>⊃⍤0⊢(↓⍺)∘.(⍺⍺/⍵⍵¨)↓(¯1⌽⍳⍴⍴⍵)⍉⍵</syntaxhighlight> line of IP above can be rewritten as <syntaxhighlight lang=apl>⍺(⍺⍺⌿⍵⍵¨⍤¯1)⍤1 99⊢⍵</syntaxhighlight> which uses the more efficient [[item]]-at-a-time algorithm (rather than row-by-column). The ISO/IEC 13751:2001(E) inner product, conversely, can only be calculated row-by-column, as computing the results one item (of the right argument) at a time relies on each application of the right operand being done between two scalars and producing a scalar result—that is, on the [[Each]] operator being applied to the right operand. | ||
Some implementations extend the inner product by implementing Iverson's monadic variant<ref>[[Ken Iverson|K.E. Iverson]]. [https://www.jsoftware.com/papers/satn42.htm Determinant-Like Functions Produced by the Dot Operator.] SHARP APL Technical Note 42. 1982-04-01.</ref>, which takes a single argument and performs the operation of computing the alternant, as modelled by [https://dfns.dyalog.com/n_alt.htm dfns.alt]. | |||
== External links == | == External links == |