       Re: Re: Taking sums across indices of a

• To: mathgroup at smc.vnet.net
• Subject: [mg96002] Re: [mg95961] Re: [mg95926] Taking sums across indices of a
• From: DrMajorBob <btreat1 at austin.rr.com>
• Date: Sat, 31 Jan 2009 06:46:06 -0500 (EST)
• References: <200901301042.FAA06408@smc.vnet.net>

```VERY NICE as usual, Carl.

I probably didn't understand the problem before, since you're collapsing
dimensions differently than I did. Nevertheless, I could duplicate my
results with your method as follows:

s=SparseArray[Table[{Mod[i,7,1],Mod[i^2,11,1],Prime@i,PrimePi@i}->i,{i,2,1000}]];
Dimensions@s

{7,11,7919,168}

s.SparseArray[_->1,168].SparseArray[_->1,7919]

SparseArray[<42>,{7,11}]

It's simple, then, to collapse the first two (or several) dimensions or
the last two (or several) dimensions, without causing sparse arrays to be
expanded.

My earlier method can also be modified to collapse (say) the first and
third dimensions, but I wonder if Dot could do the same thing?

It certainly could, of course, if Transpose will switch indices without
expanding.

And it will!

Transpose[s, {1, 3, 2, 4}]

SparseArray[<999>,{7,7919,11,168}]

So we can, for instance, compute

Transpose[s,{1,3,2,4}].SparseArray[_->1,168].SparseArray[_->1,11]
SparseArray[<999>,{7,7919}]

and then transpose the result, if needed.

Bobby

On Sat, 31 Jan 2009 00:11:31 -0600, Carl Woll <carlw at wolfram.com> wrote:

>
>> Suppose we've got a four-dimensional array:
>>
>> t = Array[Subscript[w, ##] &, {3, 3, 3, 3}]
>>
>> If we want to take the sum across one index of this array (which will
>> reduce its dimension), we can use the Total function:
>>
>> Dimensions@Total[t, {2}]
>> {3, 3, 3}
>>
>> In the problem I'm working on, I've got an array and I need to sum
>> across the first two dimensions.  Using this toy array, I can see that
>> Total[t,{1,2}] gives me exactly the object that I want.  The problem
>> is that I'm working with a four-dimensional sparse array, and Total
>> will apparently always try to convert its first argument to a normal
>> array.  This fails because the array is too big to fit in memory:
>>
>> In:= WAF = Total[W, {1, 2}]; // Timing
>>
>> During evaluation of In:= SparseArray::ntb: Cannot convert the
>> sparse array SparseArray[Automatic,{489,489,489,489},0,{<<1>>}] to an
>> ordinary array because the 57178852641 elements required exceeds the
>> current size limit. >>
>>
>> Out= SystemException[SparseArrayNormalLimit,Normal[SparseArray
>> [<1400152>,{489,489,489,489}]]]
>>
>> I can roll my own function to do this computation just by sorting
>> through the ArrayRules:
>>
>> Timing[
>> WAF =
>>  SparseArray@(
>>    (#[[1, 1, 3 ;; 4]] -> Total[#[[All, 2]]] &) /@
>>     (SplitBy[#, Drop[First@#, 2] &] &)@
>>      (SortBy[#, Drop[First@#, 2] &] &)@
>>       Most@
>>        ArrayRules@
>>         W)]
>>
>> {22.1335,SparseArray[<21122>,{489,489}]}
>>
>> The point is that actually doing the computation isn't particularly
>> memory or time intensive, but I can't find a simple way to do this
>> directly using built-in functions like Total.  Does anyone know if
>> there is a way?  If there isn't, why not?  Thanks a lot!
>>
>> -Daniel
>>
>>
>>
> Another workaround is to use Dot. Here is a toy array:
>
> In:= toy =
>  SparseArray[{i_, j_, k_, l_} -> i + j - k + l, {4, 4, 4, 4}]
>
> Out= SparseArray[<252>,{4,4,4,4}]
>
> In:= Total[toy, {1, 2}]
>
> Out= {{80, 96, 112, 128}, {64, 80, 96, 112}, {48, 64, 80,
>   96}, {32, 48, 64, 80}}
>
> In:= SparseArray[_ -> 1, 4].(SparseArray[_ -> 1, 4].toy)
>
> Out= SparseArray[<16>,{4,4}]
>
> In:= % // Normal
>
> Out= {{80, 96, 112, 128}, {64, 80, 96, 112}, {48, 64, 80,
>   96}, {32, 48, 64, 80}}
>
> Carl Woll
> Wolfram Research
>

--
DrMajorBob at longhorns.com

```

• Prev by Date: Re: Re: O in Mathematica
• Next by Date: Re: Re: ListCurvePathPlot
• Previous by thread: Re: Taking sums across indices of a SparseArray efficiently
• Next by thread: Defining assumptions globally