Thank you all !
Yoel
On Jan 15, 2008 6:40 PM, Dan Bron <[EMAIL PROTECTED]> wrote:
> Yoel,
>
> My solution wouldn't differ much from yours. The first thing that occurs to
> me is to use multiple assignment, rather than picking indices from a matrix.
> For example:
>
> 'foo bar baz'=.'hello';12;i.2 2
>
> foo
> hello
>
> bar
> 12
>
> baz
> 0 1
> 2 3
>
> The next thing that occurs to me is a couple of extra features of dyad {. :
>
> (A) The left rank is 1; that is, we can change several dimensions
> simultaneously. For example, 2 2 {. i. 4 4 is 0 1 ,: 2 3 .
>
> (B) Infinite elements of x in x{.y select the entire corresponding
> dimension. That is, _ {. 1 2 3 is just 1 2 3 . This feature is not
> documented.
>
> So, I might rewrite your code like this:
>
> 'a b c'=.dgesvd ...
> a =. (_,M){.a
> b =. (M,M){.b
> c =. (M,_){.c
> approx =. a mp b mp c
>
> In "real life", I might stop there. The code is readable and maintainable.
> But, because you're new, we can take it a little further, to see the power of
> J.
>
> In the rewritten code, the first thing that sticks out at me is that one line
> of code is repeated 3 times (kinda). What we have in each case is a {. ;
> the only thing that changes is its argument. Similarly in the last line; we
> mention mp more than once, but the only thing that changed was its
> arguments.
>
> That indicates to me that maybe we don't need to break the SVD matrix up in
> the first place. Maybe we can use J's array processing power to treat it as
> a unit.
>
> First, let's get rid of those three {. :
>
> ] SVD =. i.&.> 5 5 ; 5 6 ; 6 6
> +--------------+-----------------+-----------------+
> | 0 1 2 3 4| 0 1 2 3 4 5| 0 1 2 3 4 5|
> | 5 6 7 8 9| 6 7 8 9 10 11| 6 7 8 9 10 11|
> |10 11 12 13 14|12 13 14 15 16 17|12 13 14 15 16 17|
> |15 16 17 18 19|18 19 20 21 22 23|18 19 20 21 22 23|
> |20 21 22 23 24|24 25 26 27 28 29|24 25 26 27 28 29|
> | | |30 31 32 33 34 35|
> +--------------+-----------------+-----------------+
>
> M =. 3
>
> ] mSVD =: SVD {. L:0"_1~ (#:1 0 2) { M,_
> +--------------+--------+--------+
> | 0 1 2 3 4| 0 1 2| 0 1 2|
> | 5 6 7 8 9| 6 7 8| 6 7 8|
> |10 11 12 13 14|12 13 14|12 13 14|
> | | |18 19 20|
> | | |24 25 26|
> | | |30 31 32|
> +--------------+--------+--------+
>
> To break that down:
>
> #:1 0 2
>
> is just short way to write:
>
> 0 1 , 0 0 ,: 1 0
>
> we use those zeroes and ones to select from M,_ , which results in
>
> 3 _ , 3 3 ,: _ 3
>
> Each pair of those numbers will become a left argument to {. . We partner
> each pair with its corresponding matrix from SVD by using the rank
> conjunction:
>
> SVD (...)"_1~ 3 _ , 3 3 ,: _ 3
>
> The ~ just flips the arguments, so we're really dealing with:
>
> (3 _ , 3 3 ,: _ 3) (...)"_1 SVD
>
> The "_1 uses the rank conjunction to pair of each set of numbers with its
> corresponding matrix from SVD. Specicially, it pairs the items of the left
> with the items of the right. The items on the right are the (boxed) SVD
> matrices, and the items on the left are those pairs of numbers. So the
> function I elided (...) will be passed 3 sets of arguments, a pair of
> numbers on the left, and a boxed SVD matrix on the right.
>
> The elided function is actually {. L: 0 . Because each SVD matrix is
> boxed, I couldn't use just {. . Skipping the details, in this case, you
> can think of x {.L:0 y as < x {. > y .
>
> That takes care of the repeated {. . Now let's address that repeated mp :
>
> ] approx =. > mp&.>/ |. mSVD
> 525 624 723 822 921
> 2595 3072 3549 4026 4503
> 4665 5520 6375 7230 8085
> 6735 7968 9201 10434 11667
> 8805 10416 12027 13638 15249
> 10875 12864 14853 16842 18831
>
> To break down that line:
>
> |. mSVD
>
> reverses the matricies in mSVD and:
>
> mp&.>/
>
> applies the matrix product between them, from right-to-left (that's why we
> had reverse the order).
>
> The final > merely opens the results. Because mSVD is defined to have 3
> matricies, you could elide the > by writing mp&:>/ |. mSVD instead. But
> >f&.>/y is more general than f&:>/y and the latter only saves you one
> character.
>
> So now we have no duplicate logic. But did you notice something else? With
> the duplicate logic, the variable names disappeared too. The only variables
> mentioned are SVD , which is the input, and mSVD , the output of the {.
> logic. But the output of the {. logic is just the input to the mp
> logic. I only gave it a name for the sake of this email; I wanted to break
> up the two steps.
>
> In fact, we could write the whole thing on one line:
>
> > mp&.>/ |. (dgesvd ... ) {. L:0"_1~ (#:1 0 2) { M,_
>
> Notice there are no variables, barring M . This is pure function. In
> fact, we could rewrite the whole thing as a single function; a dyad, whose
> left argument would be M and the right argument is the input to dgesvd :
>
> approxSVD =: [: mp&:>/ [: |. dgesvd@:] {. L:0"_1~ (#:1 0 2) { _ ,~
> [
>
> And that's why we use J. Did this help?
>
> -Dan
>
>
>
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
>
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm