Efficiently Evaluate a Multivariable Function on a List of Tuples

Efficiently Evaluate a Multivariable Function on a List of Tuples



I have a function G[x,y,z,r,s,t] in the code below. Quite simply, I want to generate a list of all possible tuples $(x,y,z,r,s,t)$ such that all six entries are taken from the set $0,1,2,...,N-1$ where $N$ will be an integer parameter of the problem. I then want to evaluate $G$ on each of these tuples and as efficiently as I can, count the number of the tuples which evaluate to 0 modulo $N$. I at least have the following:


G[x,y,z,r,s,t]



G[x_, y_, z_, r_, s_, t_] :=
x*y*z*(r^3 + s^3 + t^3) - r*s*t*(x^3 + y^3 + z^3);
F[N_] := Range[0, N - 1];
Tup[N_] := Tuples[F[N], 6];


G[x_, y_, z_, r_, s_, t_] :=
x*y*z*(r^3 + s^3 + t^3) - r*s*t*(x^3 + y^3 + z^3);
F[N_] := Range[0, N - 1];
Tup[N_] := Tuples[F[N], 6];



So Tup[N] is a list of all my tuples of interest. I was about to do a "for loop" ranging over the number of tuples and evaluate something like


Tup[N]



G[Tup[2][[4]][[1]], Tup[2][[4]][[2]], Tup[2][[4]][[3]],
Tup[2][[4]][[4]], Tup[2][[4]][[5]], Tup[2][[4]][[6]]]


G[Tup[2][[4]][[1]], Tup[2][[4]][[2]], Tup[2][[4]][[3]],
Tup[2][[4]][[4]], Tup[2][[4]][[5]], Tup[2][[4]][[6]]]



for example, but this seems to be extremely inefficient. I'm sure there must be a smarter way! So given my G[x,y,z,r,s,t] as well as Tup[N] how can I construct a function P[N] which will output the number of tuples which evaluate to 0 modulo $N$?


G[x,y,z,r,s,t]


Tup[N]


P[N]





$begingroup$
Try G @@@ Tup[10]; or G @@ Transpose[Tup[10]];. The latter should be faster but may not always work.
$endgroup$
– Henrik Schumacher
Sep 16 '18 at 21:11



G @@@ Tup[10];


G @@ Transpose[Tup[10]];




2 Answers
2



Here are several ways to perform the computations along with timings:


G2[X_] := X[[1]] X[[2]] X[[3]] (X[[4]]^3 + X[[5]]^3 + X[[6]]^3) -
X[[4]] X[[5]] X[[6]] (X[[1]]^3 + X[[2]]^3 + X[[3]]^3);
cG2 = With[code = G2[Array[Compile`GetElement[X, #] &, 6]],
Compile[X, _Integer, 1,
code,
CompilationTarget -> "C",
RuntimeAttributes -> Listable,
Parallelization -> True,
RuntimeOptions -> "Speed"
]
];


data = Tup[10];
a = G @@@ data; // RepeatedTiming // First
b = G @@ Transpose[data]; // RepeatedTiming // First
c = G2 /@ data; // RepeatedTiming // First
d = cG2[data]; // RepeatedTiming // First
e = Flatten[Outer[G, ## & @@ ConstantArray[F[10], 6]]]; // RepeatedTiming // First
a == b == c == d == e



4.012



0.068



7.30



0.0312



3.80



True





$begingroup$
wow, the compilation really does rule! any insight on why a and b have such differing runtimes?
$endgroup$
– Ben Kalziqi
Sep 16 '18 at 21:37



a


b





$begingroup$
Well, b heavily uses vectorization and d is compiled. So, a and c have to struggle with the fact that Mathematica is an interpreted language, not a compiled one. They are also not parallelized. I am a bit surprised that c is so much slower than a
$endgroup$
– Henrik Schumacher
Sep 16 '18 at 21:44



b


d


a


c


c


a





$begingroup$
Beautiful! Thanks a lot. I appreciate the multiple solutions.
$endgroup$
– Benighted
Sep 16 '18 at 23:11





$begingroup$
You're welcome.
$endgroup$
– Henrik Schumacher
Sep 17 '18 at 4:06


tup1[N_] := Tuples[G @@ F[N], 6]



or


tup2[N_] := Flatten[Outer[G, ## & @@ ConstantArray[F[N], 6]]]



They both give the same result as G @@@ Tup[N] suggested by Henrik:


G @@@ Tup[N]


tup1[7] == tup2[7] == G @@@ Tup[7]



True



Thanks for contributing an answer to Mathematica Stack Exchange!



But avoid



Use MathJax to format equations. MathJax reference.



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




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

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)