Efficiently Evaluate a Multivariable Function on a List of Tuples

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
2
down vote

favorite












So I have a function which I call 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_] :=
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



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$?










share|improve this question





















  • Try G @@@ Tup[10]; or G @@ Transpose[Tup[10]];. The latter should be faster but may not always work.
    – Henrik Schumacher
    58 mins ago















up vote
2
down vote

favorite












So I have a function which I call 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_] :=
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



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$?










share|improve this question





















  • Try G @@@ Tup[10]; or G @@ Transpose[Tup[10]];. The latter should be faster but may not always work.
    – Henrik Schumacher
    58 mins ago













up vote
2
down vote

favorite









up vote
2
down vote

favorite











So I have a function which I call 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_] :=
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



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$?










share|improve this question













So I have a function which I call 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_] :=
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



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$?







list-manipulation functions






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 1 hour ago









Benighted

537211




537211











  • Try G @@@ Tup[10]; or G @@ Transpose[Tup[10]];. The latter should be faster but may not always work.
    – Henrik Schumacher
    58 mins ago

















  • Try G @@@ Tup[10]; or G @@ Transpose[Tup[10]];. The latter should be faster but may not always work.
    – Henrik Schumacher
    58 mins ago
















Try G @@@ Tup[10]; or G @@ Transpose[Tup[10]];. The latter should be faster but may not always work.
– Henrik Schumacher
58 mins ago





Try G @@@ Tup[10]; or G @@ Transpose[Tup[10]];. The latter should be faster but may not always work.
– Henrik Schumacher
58 mins ago











2 Answers
2






active

oldest

votes

















up vote
2
down vote













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:



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



True







share|improve this answer





























    up vote
    2
    down vote













    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







    share|improve this answer




















    • wow, the compilation really does rule! any insight on why a and b have such differing runtimes?
      – Ben Kalziqi
      31 mins ago







    • 1




      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
      – Henrik Schumacher
      25 mins ago











    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "387"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f182011%2fefficiently-evaluate-a-multivariable-function-on-a-list-of-tuples%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    2
    down vote













    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:



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



    True







    share|improve this answer


























      up vote
      2
      down vote













      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:



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



      True







      share|improve this answer
























        up vote
        2
        down vote










        up vote
        2
        down vote









        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:



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



        True







        share|improve this answer














        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:



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



        True








        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 42 mins ago

























        answered 47 mins ago









        kglr

        160k8184384




        160k8184384




















            up vote
            2
            down vote













            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







            share|improve this answer




















            • wow, the compilation really does rule! any insight on why a and b have such differing runtimes?
              – Ben Kalziqi
              31 mins ago







            • 1




              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
              – Henrik Schumacher
              25 mins ago















            up vote
            2
            down vote













            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







            share|improve this answer




















            • wow, the compilation really does rule! any insight on why a and b have such differing runtimes?
              – Ben Kalziqi
              31 mins ago







            • 1




              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
              – Henrik Schumacher
              25 mins ago













            up vote
            2
            down vote










            up vote
            2
            down vote









            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







            share|improve this answer












            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








            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 33 mins ago









            Henrik Schumacher

            38.1k250110




            38.1k250110











            • wow, the compilation really does rule! any insight on why a and b have such differing runtimes?
              – Ben Kalziqi
              31 mins ago







            • 1




              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
              – Henrik Schumacher
              25 mins ago

















            • wow, the compilation really does rule! any insight on why a and b have such differing runtimes?
              – Ben Kalziqi
              31 mins ago







            • 1




              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
              – Henrik Schumacher
              25 mins ago
















            wow, the compilation really does rule! any insight on why a and b have such differing runtimes?
            – Ben Kalziqi
            31 mins ago





            wow, the compilation really does rule! any insight on why a and b have such differing runtimes?
            – Ben Kalziqi
            31 mins ago





            1




            1




            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
            – Henrik Schumacher
            25 mins ago





            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
            – Henrik Schumacher
            25 mins ago


















             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f182011%2fefficiently-evaluate-a-multivariable-function-on-a-list-of-tuples%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            Long meetings (6-7 hours a day): Being “babysat” by supervisor

            Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

            Confectionery