do w/o a loop? (presumably an each question)

Learning APL or new to Dyalog? Ask "silly" questions here, without fear...
Post Reply
drothman
Posts: 12
Joined: Fri Feb 06, 2015 3:03 pm

do w/o a loop? (presumably an each question)

Post by drothman »

stuck on this abstraction of a bigger problem:

a←4 2 ⍴⍳8
b←3 2⍴1 1 1 2 2 3

i want to generate a×[2]b[i;] where i loops thru the rows of b.

this works: ↑, ⍉(↓a)∘.×↓b

but i gotta believe there's a better way than using split and an outer product. i just haven't been able to figure it out. any help? thanks
Last edited by drothman on Thu Jun 18, 2020 1:07 pm, edited 1 time in total.
User avatar
StefanoLanzavecchia
Posts: 113
Joined: Fri Oct 03, 2008 9:37 am

Re: do w/o a loop? (presumably an each question)

Post by StefanoLanzavecchia »

Code: Select all

     ⎕IO←1
     ,[1 2]a×[2]⍤99 ¯1⊢b


I believe this does the same and unless there are major optimisations in the interpreter it's likely to have the same performance as your version if it's not slower.

As an aside, if ⎕IO needs to die, then the only possibility is to keep it at 1 unless people volunteer to rewrite and test a few millions of lines of code.
User avatar
Phil Last
Posts: 628
Joined: Thu Jun 18, 2009 6:29 pm
Location: Wessex

Re: do w/o a loop? (presumably an each question)

Post by Phil Last »

      ↑,b,.×⍉a
0 1
2 3
4 5
6 7
0 2
2 6
4 10
6 14
0 3
4 9
8 15
12 21
But ravel is redundant with a single axis as the axis spec combines a number of axes as one or adds new axes if fractional.
User avatar
StefanoLanzavecchia
Posts: 113
Joined: Fri Oct 03, 2008 9:37 am

Re: do w/o a loop? (presumably an each question)

Post by StefanoLanzavecchia »

Nice.
drothman
Posts: 12
Joined: Fri Feb 06, 2015 3:03 pm

Re: do w/o a loop? (presumably an each question)

Post by drothman »

thanks to each of you.

Stefano, would u mind walking me through your solution?

Phil, that's more inline with what i was going for.

again, thanks guys
User avatar
StefanoLanzavecchia
Posts: 113
Joined: Fri Oct 03, 2008 9:37 am

Re: do w/o a loop? (presumably an each question)

Post by StefanoLanzavecchia »

The rank operator is a way to change the way functions (be they primitives or user defined) see their arguments. By specifying rank 99 (-1) you are telling the executor that the left argument should be passed in its entirety whereas the right argument should be passed line by line. So times with axis 2 (x[2]) sees the whole of "a" as its left argument and one line of "b" at a time as its right argument.

Code: Select all

   ⍴a {⎕←'⍺'⍺'⍵'⍵⋄ ⍺×[2]⍵}⍤ 99 ¯1⊢b
⍺ 1 2 ⍵ 1 1
  3 4       
  5 6       
  7 8       
⍺ 1 2 ⍵ 1 2
  3 4       
  5 6       
  7 8       
⍺ 1 2 ⍵ 2 3
  3 4       
  5 6       
  7 8       
3 4 2


If you want, it's a "modern" (v14 onward for Dyalog APL, 30 years for Sharp APL) way to write (⊂a)×[2]¨↓b (which I assume is what you implied in your subject line with "each question"). The rank operator, though, does not nest its results, which get flattened much like a "mix" would do. So the only thing left to do at the end is to ravel together the first two dimensions of the rank 3 array.
drothman
Posts: 12
Joined: Fri Feb 06, 2015 3:03 pm

Re: do w/o a loop? (presumably an each question)

Post by drothman »

thanks. got it. yes,

1. (⊂a)×[2]¨↓b was what i had in mind, but i kept trying to make (↓a)×[2]¨↓b because i'm an apl-1 guy at heart (and haven't coded much in the past few years which is the last time i worked thru some of the apl2 stuff).

2. "The same can be achieved using ⊢ e.g. f⍤1⊢Y because ⍤ binds tighter to its right operand than ⊢ does to its left argument, and ⊢ therefore resolves to Identity." Now noted.

3. "If an item k of B is zero or positive it selects k-cells of the corresponding argument. If it is negative, it selects (r+k)-cells where r is the rank of the corresponding argument. A value of ¯1 selects major cells. " Now noted

good stuff...thanks for the detail.
User avatar
Adam|Dyalog
Posts: 143
Joined: Thu Jun 25, 2015 1:13 pm

Re: do w/o a loop? (presumably an each question)

Post by Adam|Dyalog »

While you already have two working solutions, I'd like to make a slight modification to Stefano's code:
      ,[⍳2]a×⍤1⍤99 ¯1⊢b
1 2
3 4
5 6
7 8
1 4
3 8
5 12
7 16
2 6
6 12
10 18
14 24

This one is ⎕IO-independent and avoids one usage of the bracket axis.

It is worth pointing out that, while elegant, Phil's code still uses nested arrays, and so suffers in speed. Let's scale things a bit:
      :For f :In 1 3 10
a←(4 2×f)⍴⍳8×f
b←(3 2×f)⍴(/⍨∘⌽⍨⍳3×f)
'Factor:',f
cmpx '↑,⍉(↓a)∘.×↓b' '↑,b,.×⍉a' ',[1 2]a×[2]⍤99 ¯1⊢b' ',[⍳2]a×⍤1⍤99 ¯1⊢b'
:EndFor
Factor: 1
↑,⍉(↓a)∘.×↓b → 2.1E¯6 | 0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
↑,b,.×⍉a → 4.3E¯6 | +110% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
,[1 2]a×[2]⍤99 ¯1⊢b → 1.6E¯6 | -25% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
,[⍳2]a×⍤1⍤99 ¯1⊢b → 1.7E¯6 | -19% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
Factor: 3
↑,⍉(↓a)∘.×↓b → 1.3E¯5 | 0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
↑,b,.×⍉a → 5.4E¯5 | +311% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
,[1 2]a×[2]⍤99 ¯1⊢b → 3.8E¯6 | -72% ⎕⎕⎕
,[⍳2]a×⍤1⍤99 ¯1⊢b → 4.1E¯6 | -69% ⎕⎕⎕
Factor: 10
↑,⍉(↓a)∘.×↓b → 1.7E¯4 | 0% ⎕⎕⎕
↑,b,.×⍉a → 2.4E¯3 | +1268% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
,[1 2]a×[2]⍤99 ¯1⊢b → 2.3E¯5 | -87%
,[⍳2]a×⍤1⍤99 ¯1⊢b → 2.4E¯5 | -87%
Roger|Dyalog
Posts: 238
Joined: Thu Jul 28, 2011 10:53 am

Re: do w/o a loop? (presumably an each question)

Post by Roger|Dyalog »

There is another equivalent expression:

      ,[⍳2]a×⍤1⍤99 ¯1⊢b
⊃ ⍪⌿ ⊂⍤¯1 ⊢a×⍤1⍤99 ¯1⊢b

This may not seem like an improvement, but had ⍪⌿ been defined differently in Dyalog APL the last expression can be

      ,[⍳2]a×⍤1⍤99 ¯1⊢b
⊃ ⍪⌿ ⊂⍤¯1 ⊢a×⍤1⍤99 ¯1⊢b
⍪⌿ a×⍤1⍤99 ¯1 ⊢b

The ISO Standard for Extended APL ISO/IEC 13751:2001(E) §9.2.1 specifies two different and incompatible definitions for reduction (AKA insert):Enclose-Reduction-Style (what Dyalog APL and APL2 have) versus Insert-Reduction-Style (Iverson). With the latter, in f⌿⍵, the function operand f is inserted between the major cells of the argument ⍵, and makes for terser expressions in generating subgroups and permutations [Hui and Kromberg 2020, §3.2 and §11.3] as well as inner product reduction (in repeated squaring), etc.

The nested versus boxed array differences between APL2 and the Iverson APLs are well-publicized. IMO, Enclose-Reduction-Style versus Insert-Reduction-Style deserve at least as much attention.
User avatar
Adam|Dyalog
Posts: 143
Joined: Thu Jun 25, 2015 1:13 pm

Re: do w/o a loop? (presumably an each question)

Post by Adam|Dyalog »

Even with Enclose-Reduction-Style reduction, if monadic ⍉ been defined as rotating the axes one step instead of reversing them, and we had the Under operator ⍢ then we could also have written:
      ⍪⍢⍉a×⍤1⍤99 ¯1⊢b
Post Reply