2
$\begingroup$

I would like to dynamically create nested sums with a dynamic number of parameters aswell. We do know the number of variables. Lets say we have 3 Variables with S being an array: $$ i=(1,\dots,m), j=(1,\dots,n),k=(1,\dots,l) $$ Therefore we have two nested Sums each: $$ f_i=\sum_{j=1}^n\sum_{k=1}^l S(i,j,k)\\ g_j=\sum_{i=1}^m\sum_{k=1}^l S(i,j,k)\\ h_k=\sum_{i=1}^m\sum_{j=1}^n S(i,j,k) $$

With a different set of data we might have 4 variables: $$ i=(1,\dots,m), j=(1,\dots,n),k=(1,\dots,l),o=(1,\dots,t) $$

with 3 nested sums each:

$$ f_i=\sum_{j=1}^n\sum_{k=1}^l\sum_{o=1}^t S(i,j,k,o)\\ g_j=\sum_{i=1}^m\sum_{k=1}^l\sum_{o=1}^t S(i,j,k,o)\\ h_k=\sum_{j=1}^n\sum_{i=1}^m\sum_{o=1}^t S(i,j,k,o)\\ r_o=\sum_{j=1}^n\sum_{k=1}^l\sum_{i=1}^m S(i,j,k,o) $$ Is there any way to create these nested sums dynamically considering we know the number of parameters? This is what I've gotten so far but I don't know how to get the list part S[[k[1],k[2],k[3]]] dynamically:

varrange={4,4,4};
numbervars=Length[varrange];
iterator = Table[{k[m], 1, varrange[[m]]}, {m, numbervars}]
{{k[1], 1, 4}, {k[2], 1, 4}, {k[3], 1, 4}}

Sum[S[[k[1], k[2], k[3]]], Evaluate[Sequence @@ iterator]]

Any suggestions?

$\endgroup$
2
$\begingroup$

You were almost there ...

If

ind = First/@iterator;
(*{k[1], k[2], k[3]} *)

then

if S is a function S[...]

Sum[S[Sequence @@ ind], Evaluate[Sequence @@ iterator]]

or the equivalent but more elegant and compact form

Sum[S @@ ind, ##] & @@ iterator
Sum[S @@ First /@ {##}, ##] & @@ iterator

give

enter image description here

If S is an array, S[[...]]

just replace S[...] by S[[...]] :

Sum[S[[Sequence @@ ind]], Evaluate[Sequence @@ iterator]]

or use the equivalent compact form :

Sum[S[[##]] & @@ ind, ##] & @@ iterator
Sum[S[[##]] & @@ First /@ {##}, ##] & @@ iterator

or also :

s[i__]:=S[[i]];
Sum[s[[##]] & @@ ind, ##] & @@ iterator

or this might be useful to visually check the summation before evaluation :

check = Sum[foo[[##]] & @@ ind, ##] & @@ iterator
check  /. foo[x__] :> S[[x]]
$\endgroup$
  • $\begingroup$ i'm not sure how this accesses the list? dont i need dbl brackets S[[1,1,1]] + S[[1,1,2]] + ... $\endgroup$ – Ocin Nov 7 '14 at 9:15
  • $\begingroup$ If S is a function, then use S[...], If S is an array use S[[...]]. $\endgroup$ – SquareOne Nov 7 '14 at 9:20
  • $\begingroup$ oh wow i'm stupid :) ye great that works. highly appreciated $\endgroup$ – Ocin Nov 7 '14 at 9:22
  • 1
    $\begingroup$ @SquareOne you could also do second line as Sum[S @@ ind, ##] & @@ iterator $\endgroup$ – ubpdqn Nov 7 '14 at 9:48
  • $\begingroup$ @ubpdqn And Sum[S[[##]] & @@ ind, ##] & @@ iterator when S is an array ;) -> i will include these in the post ;) $\endgroup$ – SquareOne Nov 7 '14 at 10:04
1
$\begingroup$
fun[list_, f_] := Total[f @@@ Tuples[list]]

For example:

fun[{Range[3], Range[4], Range[5]}, S]

yields:

(* S[1, 1, 1] + S[1, 1, 2] + S[1, 1, 3] + S[1, 1, 4] + S[1, 1, 5] + 
 S[1, 2, 1] + S[1, 2, 2] + S[1, 2, 3] + S[1, 2, 4] + S[1, 2, 5] + 
 S[1, 3, 1] + S[1, 3, 2] + S[1, 3, 3] + S[1, 3, 4] + S[1, 3, 5] + 
 S[1, 4, 1] + S[1, 4, 2] + S[1, 4, 3] + S[1, 4, 4] + S[1, 4, 5] + 
 S[2, 1, 1] + S[2, 1, 2] + S[2, 1, 3] + S[2, 1, 4] + S[2, 1, 5] + 
 S[2, 2, 1] + S[2, 2, 2] + S[2, 2, 3] + S[2, 2, 4] + S[2, 2, 5] + 
 S[2, 3, 1] + S[2, 3, 2] + S[2, 3, 3] + S[2, 3, 4] + S[2, 3, 5] + 
 S[2, 4, 1] + S[2, 4, 2] + S[2, 4, 3] + S[2, 4, 4] + S[2, 4, 5] + 
 S[3, 1, 1] + S[3, 1, 2] + S[3, 1, 3] + S[3, 1, 4] + S[3, 1, 5] + 
 S[3, 2, 1] + S[3, 2, 2] + S[3, 2, 3] + S[3, 2, 4] + S[3, 2, 5] + 
 S[3, 3, 1] + S[3, 3, 2] + S[3, 3, 3] + S[3, 3, 4] + S[3, 3, 5] + 
 S[3, 4, 1] + S[3, 4, 2] + S[3, 4, 3] + S[3, 4, 4] + S[3, 4, 5] *)

UPDATE after clarification (see comment):

funa[list_, array_] := Total[array[[##]] & @@@ Tuples[list]]

For examples:

 mat={{{8, 8, 8, 10}, {8, 7, 9, 4}, {6, 9, 3, 6}}, {{3, 5, 9, 6}, {2, 3, 5,
    9}, {8, 1, 6, 7}}}

testing:

funa[#, mat] & /@ {{Range[2]}, {Range[2], Range[3]}, {Range[2], 
   Range[3], Range[4]}}

yields:

{{{11, 13, 17, 16}, {10, 10, 14, 13}, {14, 10, 9, 13}}, {35, 33, 40, 
  42}, 150}

Noting the accepted answer (in which the Part comment appears irrelevant but nicely assists in getting code to work, you could also do:

func[varr_, f_] := With[{lst = Range /@ varr},
  Total[f @@@ Tuples[lst]]]

with the test example: func[{4,4,4},S]

$\endgroup$
  • $\begingroup$ not sure if that works when S is a 3-dimensional array so it would have to be accessed S[[1,1,1]]? $\endgroup$ – Ocin Nov 7 '14 at 9:02
  • $\begingroup$ @Ocin from your question I erroneously assumed that S is a function of multiple arguments rather than an array. It is a small to change. $\endgroup$ – ubpdqn Nov 7 '14 at 9:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.