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

Reply via email to