Here is a way to permute the axes of an array that you might find easier
to work with:
A =. i. 2 3 4 5
$ ('ijkl'i.'ljik') |: A
5 3 2 4
The idea is that we start with A, which has axes ijkl, and want to
shuffle them around to get ljik. So we look up each of the letters ljik
in ijkl, which gives us a permutation 3 1 0 2 which should be applied to
the axes (you could also just write out the permutation by hand). This
is then used as the left argument to transpose.
Although a matrix product will execute faster, if I want to write tensor
code that is straightforward, and extends to multiple contracted axes, I
would transpose the contracted axes to the end and combine them with
(+/@:*"1). This pairs row vectors from the two arrays and takes their
dot product. For three contracted axes I might write (+/@:,@:*"3), which
differs in that it pairs up rank-3 subarrays, and ravels before summing,
since sum only operates on the first axis.
The idea with (|:~ 1 -.~ i.@(#@$)) is to get the list of indices for
every axis
i.@(#@$) A
0 1 2 3
and then remove a 1
1 -.~ i.@(#@$) A
0 2 3
to obtain a left argument to transpose. Transpose adds missing axes to
the front, so this will move axis 1 to the beginning, for an array of
any shape.
I think this is a weak point for J's array programming style. Just like
tacit code works well for small manipulations but gets confusing and
difficult as the number of arguments increases, J primitives like rank,
transpose, and inner product are excellent for a few axes, but don't
work so well when the number of axes increases and the ways they are
manipulated become more complicated. In J's defense, most programming
languages are pretty awful at this (how many times are you going to
write .map before you just give up?). But it's something that bothers
me. Sure, I can write a bunch of nested rank operators to do what I
want, but why is it so hard to just say which axes correspond to which?
Marshall
On Thu, Feb 06, 2020 at 09:44:32PM +0000, [email protected] wrote:
> Henry Rich <[email protected]> writes:
>
> > It depends on what the '*' means in the definition of the product.
>
> >> C_ijlmnop = sum_k A_ijkl * B_mknop
>
> I really mean the usual multiplication (of numbers).
>
>
> > Have a look at
> >
> > a =. i. 2 3 4 5
> > b =. i. 2 4 3 5 6
> > $ (2 |: a) +/ . * ((|:~ 1 -.~ i.@(#@$)) b)
> > 2 3 5 2 3 5 6
>
> Well, I hoped for seeing something simpler. :)
>
> If I understand your example a bit, you sum along the 4-long axis, and
> you make this axis the last in the case of 'a', ie. by (2 |: a), then
> use the so called dot product (+/ . *), and then something I cannot
> easily decipher, but I guess it must, among other things, make the
> 4-long axis (number 1) the first.
>
> Does one really has to shuffle with the axes?
> Does one really need to use the for me almost incomprehensible
> conjunction . (which no one dares to explain simply enough...)?
>
> Why is it so simple to say what I want mathematically, and so awkward
> to do it programmatically?
>
> Thanks!
> Ruda
>
>
> > On 2/6/2020 2:46 PM, [email protected] wrote:
> >> having two multidimensional matrices A and B,
> >> with some indices, say, A_ijkl and B_mknop,
> >> how can I obtain a matrix C, where
> >>
> >> C_ijlmnop = sum_k A_ijkl * B_mknop
> >>
> >> ie., C has all indices of A and B but for the index k,
> >> which was summed over.
> >>
> >> Thanks for your suggestions.
> >>
> >> Best regards
> >> Ruda
> >> ----------------------------------------------------------------------
> >> For information about J forums see http://www.jsoftware.com/forums.htm
> >
> > ----------------------------------------------------------------------
> > For information about J forums see http://www.jsoftware.com/forums.htm
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm