[Jprogramming] Matrix Transformations based on local submatrices
Peter B. Kessler
Peter.B.Kessler at Oracle.COM
Fri Nov 16 22:59:58 UTC 2012
Raul Miller wrote:
> On Thu, Nov 15, 2012 at 7:06 PM, Alex Giannakopoulos <aegean at blueyonder.co.uk>
>> Nice "torus-pad" ([:|:{:,]{.)^:2
>
> Or, more generally:
>
> (0 |:{:,],{.)^:(#@$)
>
> Also, here's a general "fill pad":
>
> ((_1 ["0 $) |. ({.~ 2 +$))
>
> That said: generality can be good for insight, and in utility
> contexts, but can also sometimes be bad in application contexts.
>
> FYI,
I always think Raul Miller's code is worth examining. First I look at the boxed display (after setting (9!:2) 2), to see where the operators fit in the larger picture
(0 |:{:,],{.)^:(#@$)
+----------------------+--+-------+
|+-+--+---------------+|^:|+-+-+-+|
||0||:|+--+-+--------+|| ||#|@|$||
|| | ||{:|,|+-+-+--+||| |+-+-+-+|
|| | || | ||]|,|{.|||| | |
|| | || | |+-+-+--+||| | |
|| | |+--+-+--------+|| | |
|+-+--+---------------+| | |
+----------------------+--+-------+
That's mostly a Power conjuntion (^:) and because the right argument is a verb, the number of times it executes will be computed by applying that verb to the argument to the Power conjunction. I'll make up a sample input
] input=: i. 4 5
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
Looking just at the right-hand verb to the Power conjunction (# @ $), that's an Atop (@) of Tally (#) and Shape ($) and will compute (# ($ input)). Together they compute the rank of input.
($ input) NB. The Shape of the input.
4 5
((# @ $) input) NB. The Tally of the Shape of the input.
2
(# ($ input)) NB. More straightforward (?) monadic application.
2
With the rank as the right-hand argument to the Power conjunction, that means that whatever the left-hand verb to the Power conjunction does, we are going to do it 2 times for this input.
The left-hand verb to the Power conjunction is a noun Fork (0 |: ....), so we don't have to worry so much about what the left tine computes (0). That is, instead of ((f g h) input) meaning ((f input) g (h input)), we just have (0 g (h input)). The right tine of the Fork is also a Fork ({: , ....), where the left tine is a Tail ({:) and the right tine is a Fork of Same (]), Append (,), and Head ({.) Given input as an argument, and working inside out, the right tine of the right tine is
({. input) NB. Right tine of the innermost Fork.
0 1 2 3 4
(] input) NB. Left tine fo the innermost Fork.
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
] rightRightTine=: ((] input) , ({. input))
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
0 1 2 3 4
which appends the Head of input to the input. The left tine of the right tine will compute
] leftRightTine=: ({: input)
15 16 17 18 19
which is the Tail of the input. The right tine of the outer Fork is just the append of the result of the leftRightTine to rightRightTine
] rightTine=: (leftRightTine , rightRightTine)
15 16 17 18 19
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
0 1 2 3 4
which is the input with its Tail prepended and its Head appended. Next we get to the Transpose (|:), which has a constant 0 as its left argument and the right tine as its right argument, so we get
] transposeOnce=: (0 |: rightTine)
15 0 5 10 15 0
16 1 6 11 16 1
17 2 7 12 17 2
18 3 8 13 18 3
19 4 9 14 19 4
But remember that the Power is going to apply the outer Fork twice, so we have to go through the whole process again with transposeOnce as the input, naming intermediate values with a '2' suffix.
] rightRightTine2=: ((] transposeOnce) , ({. transposeOnce))
15 0 5 10 15 0
16 1 6 11 16 1
17 2 7 12 17 2
18 3 8 13 18 3
19 4 9 14 19 4
15 0 5 10 15 0
] leftRightTine2=: ({: transposeOnce)
19 4 9 14 19 4
] rightTine2=: (leftRightTine2 , rightRightTine2)
19 4 9 14 19 4
15 0 5 10 15 0
16 1 6 11 16 1
17 2 7 12 17 2
18 3 8 13 18 3
19 4 9 14 19 4
15 0 5 10 15 0
we get
] transposeTwice=: (0 |: rightTine2)
19 15 16 17 18 19 15
4 0 1 2 3 4 0
9 5 6 7 8 9 5
14 10 11 12 13 14 10
19 15 16 17 18 19 15
4 0 1 2 3 4 0
which is the original input (see it there in the middle of the result?) extended by one cell in each direction, populated with the values of the input as if it were a torus.
Compared with the Raul Miller's original verb applied to our sample input
(0 |:{:,],{.)^:(#@$) input
19 15 16 17 18 19 15
4 0 1 2 3 4 0
9 5 6 7 8 9 5
14 10 11 12 13 14 10
19 15 16 17 18 19 15
4 0 1 2 3 4 0
we let J check if they Match (-:)
transposeTwice -: ((0 |:{:,],{.)^:(#@$) input)
1
I wrote this up mostly for myself, but maybe it will help some other newbie work through similar examples.
What I can't give you is a feeling for how Raul Miller came up with this particular way of producing that result.
... peter
More information about the Programming
mailing list