aboutsummaryrefslogtreecommitdiff
path: root/docs/doc/transpose.html
diff options
context:
space:
mode:
authorMarshall Lochbaum <mwlochbaum@gmail.com>2020-07-21 15:45:25 -0400
committerMarshall Lochbaum <mwlochbaum@gmail.com>2020-07-21 15:45:25 -0400
commit16022acd45703772f62ca9ed9f8d8ef9288be9b5 (patch)
tree96aa748d7dce2f804f9447c55018cd170e4c3751 /docs/doc/transpose.html
parent7665fb5a90f783ee5253e71fbdd0573359ca9b88 (diff)
Custom array formatting in the markdown converter
Diffstat (limited to 'docs/doc/transpose.html')
-rw-r--r--docs/doc/transpose.html64
1 files changed, 32 insertions, 32 deletions
diff --git a/docs/doc/transpose.html b/docs/doc/transpose.html
index 51e8b91a..2020a520 100644
--- a/docs/doc/transpose.html
+++ b/docs/doc/transpose.html
@@ -6,51 +6,51 @@
<p>Transposing a matrix exchanges its axes, mirroring it across the diagonal. APL extends the function to any rank by reversing all axes, but this generalization isn't very natural and is almost never used. The main reason for it is to maintain the equivalence <code><span class='Value'>a</span> <span class='Function'>MP</span> <span class='Value'>b</span> <span class='Gets'>←→</span> <span class='Value'>a</span> <span class='Function'>MP</span><span class='Modifier2'>⌾</span><span class='Function'>⍉</span> <span class='Value'>b</span></code>, where <code><span class='Function'>MP</span> <span class='Gets'>←</span> <span class='Paren'>(</span><span class='Function'>+</span><span class='Modifier'>´</span><span class='Function'>&lt;</span><span class='Modifier'>˘</span><span class='Paren'>)</span><span class='Modifier2'>∘</span><span class='Function'>×</span><span class='Modifier2'>⎉</span><span class='Number'>1</span><span class='Ligature'>‿</span><span class='Number'>∞</span></code> is the generalized matrix product. But even here APL's Transpose is suspect. It does much more work than it needs to, as we'll see.</p>
<p>BQN's transpose takes the first axis of its argument and moves it to the end.</p>
<pre> <span class='Function'>≢</span> <span class='Value'>a23456</span> <span class='Gets'>←</span> <span class='Function'>↕</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>5</span><span class='Ligature'>‿</span><span class='Number'>6</span>
-<span class='Value'>[</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Value'>]</span>
+<span class='Bracket'>⟨</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Bracket'>⟩</span>
<span class='Function'>≢</span> <span class='Function'>⍉</span> <span class='Value'>a23456</span>
-<span class='Value'>[</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Number'>2</span> <span class='Value'>]</span>
+<span class='Bracket'>⟨</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Number'>2</span> <span class='Bracket'>⟩</span>
</pre>
<p>On the argument's ravel, this looks like a simple 2-dimensional transpose: one axis is exchanged with a compound axis made up of the other axes. Here we transpose a rank 3 matrix:</p>
<pre> <span class='Value'>a322</span> <span class='Gets'>←</span> <span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Function'>⥊↕</span><span class='Number'>12</span>
<span class='Function'>≍</span><span class='Modifier2'>○</span><span class='Function'>&lt;</span><span class='Modifier2'>⟜</span><span class='Function'>⍉</span> <span class='Value'>a322</span>
-<span class='Value'>┌</span>
- <span class='Value'>┌</span> <span class='Value'>┌</span>
- <span class='Number'>0</span> <span class='Number'>1</span> <span class='Number'>0</span> <span class='Number'>4</span> <span class='Number'>8</span>
- <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>1</span> <span class='Number'>5</span> <span class='Number'>9</span>
-
- <span class='Number'>4</span> <span class='Number'>5</span> <span class='Number'>2</span> <span class='Number'>6</span> <span class='Number'>10</span>
- <span class='Number'>6</span> <span class='Number'>7</span> <span class='Number'>3</span> <span class='Number'>7</span> <span class='Number'>11</span>
- <span class='Value'>┘</span>
- <span class='Number'>8</span> <span class='Number'>9</span>
- <span class='Number'>10</span> <span class='Number'>11</span>
- <span class='Value'>┘</span>
- <span class='Value'>┘</span>
+┌─
+· ┌─ ┌─
+ ╎ 0 1 ╎ 0 4 8
+ 2 3 1 5 9
+
+ 4 5 2 6 10
+ 6 7 3 7 11
+ ┘
+ 8 9
+ 10 11
+ ┘
+ ┘
</pre>
<p>But, reading in ravel order, the argument and result have exactly the same element ordering as for the rank 2 matrix <code><span class='Function'>⥊</span><span class='Modifier'>˘</span> <span class='Value'>a322</span></code>:</p>
<pre> <span class='Function'>≍</span><span class='Modifier2'>○</span><span class='Function'>&lt;</span><span class='Modifier2'>⟜</span><span class='Function'>⍉</span> <span class='Function'>⥊</span><span class='Modifier'>˘</span> <span class='Value'>a322</span>
-<span class='Value'>┌</span>
- <span class='Value'>┌</span> <span class='Value'>┌</span>
- <span class='Number'>0</span> <span class='Number'>1</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>0</span> <span class='Number'>4</span> <span class='Number'>8</span>
- <span class='Number'>4</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Number'>7</span> <span class='Number'>1</span> <span class='Number'>5</span> <span class='Number'>9</span>
- <span class='Number'>8</span> <span class='Number'>9</span> <span class='Number'>10</span> <span class='Number'>11</span> <span class='Number'>2</span> <span class='Number'>6</span> <span class='Number'>10</span>
- <span class='Value'>┘</span> <span class='Number'>3</span> <span class='Number'>7</span> <span class='Number'>11</span>
- <span class='Value'>┘</span>
- <span class='Value'>┘</span>
+┌─
+· ┌─ ┌─
+ ╵ 0 1 2 3 ╵ 0 4 8
+ 4 5 6 7 1 5 9
+ 8 9 10 11 2 6 10
+ ┘ 3 7 11
+ ┘
+ ┘
</pre>
<p>To exchange multiple axes, use the Power modifier. Like Rotate, a negative power will move axes in the other direction. In particular, to move the last axis to the front, use Inverse (as you might expect, this exactly inverts <code><span class='Function'>⍉</span></code>).</p>
<pre> <span class='Function'>≢</span> <span class='Function'>⍉</span><span class='Modifier2'>⍟</span><span class='Number'>3</span> <span class='Value'>a23456</span>
-<span class='Value'>[</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Value'>]</span>
+<span class='Bracket'>⟨</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Bracket'>⟩</span>
<span class='Function'>≢</span> <span class='Function'>⍉</span><span class='Modifier'>⁼</span> <span class='Value'>a23456</span>
-<span class='Value'>[</span> <span class='Number'>6</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Number'>5</span> <span class='Value'>]</span>
+<span class='Bracket'>⟨</span> <span class='Number'>6</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Number'>5</span> <span class='Bracket'>⟩</span>
</pre>
<p>In fact, we have <code><span class='Function'>≢⍉</span><span class='Modifier2'>⍟</span><span class='Value'>k</span> <span class='Value'>a</span> <span class='Gets'>←→</span> <span class='Value'>k</span><span class='Function'>⌽≢</span><span class='Value'>a</span></code> for any number <code><span class='Value'>k</span></code> and array <code><span class='Value'>a</span></code>.</p>
<p>To move axes other than the first, use the Rank modifier in order to leave initial axes untouched. A rank of <code><span class='Value'>k</span><span class='Function'>&gt;</span><span class='Number'>0</span></code> transposes only the last <code><span class='Value'>k</span></code> axes while a rank of <code><span class='Value'>k</span><span class='Function'>&lt;</span><span class='Number'>0</span></code> ignores the first <code><span class='Function'>|</span><span class='Value'>k</span></code> axes.</p>
<pre> <span class='Function'>≢</span> <span class='Function'>⍉</span><span class='Modifier2'>⎉</span><span class='Number'>3</span> <span class='Value'>a23456</span>
-<span class='Value'>[</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Number'>4</span> <span class='Value'>]</span>
+<span class='Bracket'>⟨</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Number'>4</span> <span class='Bracket'>⟩</span>
</pre>
<p>And of course, Rank and Power can be combined to do more complicated transpositions: move a set of contiguous axes with any starting point and length to the end.</p>
<pre> <span class='Function'>≢</span> <span class='Function'>⍉</span><span class='Modifier'>⁼</span><span class='Modifier2'>⎉</span><span class='Number'>¯1</span> <span class='Value'>a23456</span>
-<span class='Value'>[</span> <span class='Number'>2</span> <span class='Number'>6</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Number'>5</span> <span class='Value'>]</span>
+<span class='Bracket'>⟨</span> <span class='Number'>2</span> <span class='Number'>6</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Number'>5</span> <span class='Bracket'>⟩</span>
</pre>
<p>Using these forms, we can state BQN's generalized matrix product swapping rule:</p>
<pre><span class='Value'>a</span> <span class='Function'>MP</span> <span class='Value'>b</span> <span class='Gets'>←→</span> <span class='Function'>⍉</span><span class='Modifier2'>⍟</span><span class='Paren'>(</span><span class='Function'>≠≢</span><span class='Value'>a</span><span class='Paren'>)</span> <span class='Value'>a</span> <span class='Function'>⍉</span><span class='Modifier'>⁼</span><span class='Modifier2'>⊸</span><span class='Function'>MP</span><span class='Modifier2'>⟜</span><span class='Function'>⍉</span> <span class='Value'>b</span>
@@ -58,27 +58,27 @@
<p>Certainly not as concise as APL's version, but not a horror either. BQN's rule is actually more parsimonious in that it only performs the axis exchanges necessary for the computation: it moves the two axes that will be paired with the matrix product into place before the product, and directly exchanges all axes afterwards. Each of these steps is equivalent in terms of data movement to a matrix transpose, the simplest nontrivial transpose to perform. Also remember that for two-dimensional matrices both kinds of transposition are the same, and APL's rule holds in BQN.</p>
<p>Axis permutations of the types we've shown generate the complete permutation group on any number of axes, so you could produce any transposition you want with the right sequence of monadic transpositions with Rank. However, this can be unintuitive and tedious. What if you want to transpose the first three axes, leaving the rest alone? With monadic Transpose you have to send some axes to the end, then bring them back to the beginning. For example [following four or five failed tries]:</p>
<pre> <span class='Function'>≢</span> <span class='Function'>⍉</span><span class='Modifier'>⁼</span><span class='Modifier2'>⎉</span><span class='Number'>¯2</span> <span class='Function'>⍉</span> <span class='Value'>a23456</span> <span class='Comment'># Restrict Transpose to the first three axes
-</span><span class='Value'>[</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Number'>2</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Value'>]</span>
+</span><span class='Bracket'>⟨</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Number'>2</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Bracket'>⟩</span>
</pre>
<p>In a case like this BQN's Dyadic transpose is much easier.</p>
<h2 id="dyadic-transpose">Dyadic Transpose</h2>
<p>Transpose also allows a left argument that specifies a permutation of the right argument's axes. For each index <code><span class='Value'>p</span><span class='Gets'>←</span><span class='Value'>i</span><span class='Function'>⊏</span><span class='Value'>𝕨</span></code> in the left argument, axis <code><span class='Value'>i</span></code> of the argument is used for axis <code><span class='Value'>p</span></code> of the result. Multiple argument axes can be sent to the same result axis, in which case that axis goes along a diagonal of the argument array, and the result will have a lower rank than the argument.</p>
<pre> <span class='Function'>≢</span> <span class='Number'>1</span><span class='Ligature'>‿</span><span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>4</span> <span class='Function'>⍉</span> <span class='Value'>a23456</span>
-<span class='Value'>[</span> <span class='Number'>5</span> <span class='Number'>2</span> <span class='Number'>4</span> <span class='Number'>3</span> <span class='Number'>6</span> <span class='Value'>]</span>
+<span class='Bracket'>⟨</span> <span class='Number'>5</span> <span class='Number'>2</span> <span class='Number'>4</span> <span class='Number'>3</span> <span class='Number'>6</span> <span class='Bracket'>⟩</span>
<span class='Function'>≢</span> <span class='Number'>1</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>0</span> <span class='Function'>⍉</span> <span class='Value'>a23456</span> <span class='Comment'># Don't worry too much about this case though
-</span><span class='Value'>[</span> <span class='Number'>5</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Value'>]</span>
+</span><span class='Bracket'>⟨</span> <span class='Number'>5</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Bracket'>⟩</span>
</pre>
<p>Since this kind of rearrangement can be counterintuitive, it's often easier to use <code><span class='Function'>⍉</span><span class='Modifier'>⁼</span></code> when specifying all axes. If <code><span class='Value'>p</span><span class='Function'>≡</span><span class='Modifier2'>○</span><span class='Function'>≠≢</span><span class='Value'>a</span></code>, then we have <code><span class='Function'>≢</span><span class='Value'>p</span><span class='Function'>⍉</span><span class='Modifier'>⁼</span><span class='Value'>a</span> <span class='Gets'>←→</span> <span class='Value'>p</span><span class='Function'>⊏≢</span><span class='Value'>a</span></code>.</p>
<pre> <span class='Function'>≢</span> <span class='Number'>1</span><span class='Ligature'>‿</span><span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>4</span> <span class='Function'>⍉</span><span class='Modifier'>⁼</span> <span class='Value'>a23456</span>
-<span class='Value'>[</span> <span class='Number'>3</span> <span class='Number'>5</span> <span class='Number'>4</span> <span class='Number'>2</span> <span class='Number'>6</span> <span class='Value'>]</span>
+<span class='Bracket'>⟨</span> <span class='Number'>3</span> <span class='Number'>5</span> <span class='Number'>4</span> <span class='Number'>2</span> <span class='Number'>6</span> <span class='Bracket'>⟩</span>
</pre>
<p>So far, all like APL. BQN makes one little extension, which is to allow only some axes to be specified. The left argument will be matched up with leading axes of the right argument. Those axes are moved according to the left argument, and remaining axes are placed in order into the gaps between them.</p>
<pre> <span class='Function'>≢</span> <span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>4</span> <span class='Function'>⍉</span> <span class='Value'>a23456</span>
-<span class='Value'>[</span> <span class='Number'>2</span> <span class='Number'>5</span> <span class='Number'>3</span> <span class='Number'>6</span> <span class='Number'>4</span> <span class='Value'>]</span>
+<span class='Bracket'>⟨</span> <span class='Number'>2</span> <span class='Number'>5</span> <span class='Number'>3</span> <span class='Number'>6</span> <span class='Number'>4</span> <span class='Bracket'>⟩</span>
</pre>
<p>In particular, the case with only one argument specified is interesting. Here, the first axis ends up at the given location. This gives us a much better solution to the problem at the end of the last section.</p>
<pre> <span class='Function'>≢</span> <span class='Number'>2</span> <span class='Function'>⍉</span> <span class='Value'>a23456</span> <span class='Comment'># Restrict Transpose to the first three axes
-</span><span class='Value'>[</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Number'>2</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Value'>]</span>
+</span><span class='Bracket'>⟨</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Number'>2</span> <span class='Number'>5</span> <span class='Number'>6</span> <span class='Bracket'>⟩</span>
</pre>
<p>Finally, it's worth noting that, as monadic Transpose moves the first axis to the end, it's equivalent to dyadic Transpose with a &quot;default&quot; left argument: <code><span class='Paren'>(</span><span class='Function'>≠</span><span class='Modifier2'>∘</span><span class='Function'>≢-</span><span class='Number'>1</span><span class='Modifier'>˜</span><span class='Paren'>)</span><span class='Modifier2'>⊸</span><span class='Function'>⍉</span></code>.</p>
<h2 id="definitions">Definitions</h2>