Can this be solved even faster?











up vote
11
down vote

favorite
1












So I would like to solve the following set of equation for $m_i$ given a set of ${M_m,N_m}$.



$$
m_1 +m_2 +m_3 +m_4 =M_m \
|m_1| +|m_2| +|m_3| +|m_4| =N_m
$$



All variables are integers.
Also $N_m ge M_m$ and their maximum value can reach up-to 30.
I only need the total number of possible solution not the solutions themselves. So my first trivial attempt was to just use Solve



dimNM1[Nm_, Mm_] :=
Length[(Solve[m1 + m2 + m3 + m4 == Mm &&
Abs[m1] + Abs[m2] + Abs[m3] + Abs[m4] == Nm, {m1, m2, m3, m4}, Integers])]


My second slightly non-trivial attempt is the following:-



dimNM2[Nm_, Mm_] :=
Which[Nm === Mm,
Length[Partition[
Flatten[Permutations /@ IntegerPartitions[Nm, {4}, Range[0, Nm]]],
4]], True,
Module[{res},
res = Partition[
Flatten[Permutations /@ IntegerPartitions[Mm, {4}, Range[-Nm, Nm]]],
4];
Length[
Select[res, (Abs[#[[1]]] + Abs[#[[2]]] + Abs[#[[3]]] +
Abs[#[[4]]]) == Nm &]]]]


The second method is much faster than the first specially for $N_m=M_m$.
But I would like to increase the speed further for $N_mge M_m$ case if possible.



dimNM1[2, 2] // AbsoluteTiming
(*{0.177768, 10}*)

dimNM2[2, 2] // AbsoluteTiming
(*{0.0000899056, 10}*)


So is there any other way to solve these equation faster?










share|improve this question
























  • Note that N has built-in meanings.
    – Αλέξανδρος Ζεγγ
    Dec 9 at 12:34










  • OK I have changed it.
    – Hubble07
    Dec 9 at 12:46










  • Nice problem. No need to generate candidates... see my reply.
    – ciao
    2 days ago















up vote
11
down vote

favorite
1












So I would like to solve the following set of equation for $m_i$ given a set of ${M_m,N_m}$.



$$
m_1 +m_2 +m_3 +m_4 =M_m \
|m_1| +|m_2| +|m_3| +|m_4| =N_m
$$



All variables are integers.
Also $N_m ge M_m$ and their maximum value can reach up-to 30.
I only need the total number of possible solution not the solutions themselves. So my first trivial attempt was to just use Solve



dimNM1[Nm_, Mm_] :=
Length[(Solve[m1 + m2 + m3 + m4 == Mm &&
Abs[m1] + Abs[m2] + Abs[m3] + Abs[m4] == Nm, {m1, m2, m3, m4}, Integers])]


My second slightly non-trivial attempt is the following:-



dimNM2[Nm_, Mm_] :=
Which[Nm === Mm,
Length[Partition[
Flatten[Permutations /@ IntegerPartitions[Nm, {4}, Range[0, Nm]]],
4]], True,
Module[{res},
res = Partition[
Flatten[Permutations /@ IntegerPartitions[Mm, {4}, Range[-Nm, Nm]]],
4];
Length[
Select[res, (Abs[#[[1]]] + Abs[#[[2]]] + Abs[#[[3]]] +
Abs[#[[4]]]) == Nm &]]]]


The second method is much faster than the first specially for $N_m=M_m$.
But I would like to increase the speed further for $N_mge M_m$ case if possible.



dimNM1[2, 2] // AbsoluteTiming
(*{0.177768, 10}*)

dimNM2[2, 2] // AbsoluteTiming
(*{0.0000899056, 10}*)


So is there any other way to solve these equation faster?










share|improve this question
























  • Note that N has built-in meanings.
    – Αλέξανδρος Ζεγγ
    Dec 9 at 12:34










  • OK I have changed it.
    – Hubble07
    Dec 9 at 12:46










  • Nice problem. No need to generate candidates... see my reply.
    – ciao
    2 days ago













up vote
11
down vote

favorite
1









up vote
11
down vote

favorite
1






1





So I would like to solve the following set of equation for $m_i$ given a set of ${M_m,N_m}$.



$$
m_1 +m_2 +m_3 +m_4 =M_m \
|m_1| +|m_2| +|m_3| +|m_4| =N_m
$$



All variables are integers.
Also $N_m ge M_m$ and their maximum value can reach up-to 30.
I only need the total number of possible solution not the solutions themselves. So my first trivial attempt was to just use Solve



dimNM1[Nm_, Mm_] :=
Length[(Solve[m1 + m2 + m3 + m4 == Mm &&
Abs[m1] + Abs[m2] + Abs[m3] + Abs[m4] == Nm, {m1, m2, m3, m4}, Integers])]


My second slightly non-trivial attempt is the following:-



dimNM2[Nm_, Mm_] :=
Which[Nm === Mm,
Length[Partition[
Flatten[Permutations /@ IntegerPartitions[Nm, {4}, Range[0, Nm]]],
4]], True,
Module[{res},
res = Partition[
Flatten[Permutations /@ IntegerPartitions[Mm, {4}, Range[-Nm, Nm]]],
4];
Length[
Select[res, (Abs[#[[1]]] + Abs[#[[2]]] + Abs[#[[3]]] +
Abs[#[[4]]]) == Nm &]]]]


The second method is much faster than the first specially for $N_m=M_m$.
But I would like to increase the speed further for $N_mge M_m$ case if possible.



dimNM1[2, 2] // AbsoluteTiming
(*{0.177768, 10}*)

dimNM2[2, 2] // AbsoluteTiming
(*{0.0000899056, 10}*)


So is there any other way to solve these equation faster?










share|improve this question















So I would like to solve the following set of equation for $m_i$ given a set of ${M_m,N_m}$.



$$
m_1 +m_2 +m_3 +m_4 =M_m \
|m_1| +|m_2| +|m_3| +|m_4| =N_m
$$



All variables are integers.
Also $N_m ge M_m$ and their maximum value can reach up-to 30.
I only need the total number of possible solution not the solutions themselves. So my first trivial attempt was to just use Solve



dimNM1[Nm_, Mm_] :=
Length[(Solve[m1 + m2 + m3 + m4 == Mm &&
Abs[m1] + Abs[m2] + Abs[m3] + Abs[m4] == Nm, {m1, m2, m3, m4}, Integers])]


My second slightly non-trivial attempt is the following:-



dimNM2[Nm_, Mm_] :=
Which[Nm === Mm,
Length[Partition[
Flatten[Permutations /@ IntegerPartitions[Nm, {4}, Range[0, Nm]]],
4]], True,
Module[{res},
res = Partition[
Flatten[Permutations /@ IntegerPartitions[Mm, {4}, Range[-Nm, Nm]]],
4];
Length[
Select[res, (Abs[#[[1]]] + Abs[#[[2]]] + Abs[#[[3]]] +
Abs[#[[4]]]) == Nm &]]]]


The second method is much faster than the first specially for $N_m=M_m$.
But I would like to increase the speed further for $N_mge M_m$ case if possible.



dimNM1[2, 2] // AbsoluteTiming
(*{0.177768, 10}*)

dimNM2[2, 2] // AbsoluteTiming
(*{0.0000899056, 10}*)


So is there any other way to solve these equation faster?







equation-solving performance-tuning






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 9 at 13:00









Henrik Schumacher

47.2k466134




47.2k466134










asked Dec 9 at 11:40









Hubble07

2,935719




2,935719












  • Note that N has built-in meanings.
    – Αλέξανδρος Ζεγγ
    Dec 9 at 12:34










  • OK I have changed it.
    – Hubble07
    Dec 9 at 12:46










  • Nice problem. No need to generate candidates... see my reply.
    – ciao
    2 days ago


















  • Note that N has built-in meanings.
    – Αλέξανδρος Ζεγγ
    Dec 9 at 12:34










  • OK I have changed it.
    – Hubble07
    Dec 9 at 12:46










  • Nice problem. No need to generate candidates... see my reply.
    – ciao
    2 days ago
















Note that N has built-in meanings.
– Αλέξανδρος Ζεγγ
Dec 9 at 12:34




Note that N has built-in meanings.
– Αλέξανδρος Ζεγγ
Dec 9 at 12:34












OK I have changed it.
– Hubble07
Dec 9 at 12:46




OK I have changed it.
– Hubble07
Dec 9 at 12:46












Nice problem. No need to generate candidates... see my reply.
– ciao
2 days ago




Nice problem. No need to generate candidates... see my reply.
– ciao
2 days ago










3 Answers
3






active

oldest

votes

















up vote
9
down vote



accepted










ClearAll[num];

num[n_, m_] /; OddQ[n + m] = 0;
num[n_, n_] := Binomial[n + 3, 3];
num[n_, m_] /; OddQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 3)/2 + 2 z - (2 z^2)];
num[n_, m_] /; EvenQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 4)/2 - (2 z^2)];


Testing vs fastest answer here at writing (Henrik Schumacher):



stop = 100;

res = Table[{n, m, dimNM3[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First
res2 = Table[{n, m, num[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First

res == res2



169.203



0.0219434



True




Large cases are a non-issue:



num[123423456, 123412348] // AbsoluteTiming



{0.0000247977, 30468069908023290}




Some quick timings:



enter image description here






share|improve this answer



















  • 3




    Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
    – Henrik Schumacher
    2 days ago








  • 3




    @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
    – ciao
    2 days ago






  • 2




    Chapeaux for recognizing the patterns! =D
    – Henrik Schumacher
    2 days ago






  • 2




    @ciao - You Sir are a genius. Thank you.
    – Hubble07
    2 days ago






  • 1




    Answers from ciao are generally great reads, +1.
    – Marius Ladegård Meyer
    yesterday


















up vote
12
down vote













It is more efficient to first pick the integer partitions whose absolute values sum up to n before generating the permutations.



dimNM3[n_, m_] := Total[
Map[
Length@*Permutations,
Pick[#, Abs[#].ConstantArray[1, 4], n] &[
IntegerPartitions[m, {4}, Range[-n, n]
]
]
]
];

m = 20;
n = 40;
dimNM1[n, m] // AbsoluteTiming
dimNM2[n, m] // AbsoluteTiming
dimNM3[n, m] // AbsoluteTiming



{0.116977, 3802}



{0.995365, 3802}



{0.005579, 3802}







share|improve this answer






























    up vote
    2
    down vote













    Sorry for not knowing much Mathematica, but I have a Python solution you might be able to follow. I'm putting this on the community wiki for anyone who wants to translate it.



    def count_solutions(Nm, Mm):
    firsthalves = dict()
    for m1 in range(-Nm,Nm+1):
    for m2 in range(-Nm,Nm+1):
    m = m1+m2
    n = abs(m1)+abs(m2)
    key = (m,n)
    if key in firsthalves:
    firsthalves[key] += 1
    else:
    firsthalves[key] = 1

    solutions = 0
    for m3 in range(-Nm,Nm+1):
    for m4 in range(-Nm,Nm+1):
    m = m3+m4
    n = abs(m3)+abs(m4)
    key = (Mm-m, Nm-n)
    if key in firsthalves:
    solutions += firsthalves[key]
    return solutions


    This is a meet in the middle strategy. I enumerate all the possible $m1,m2$ combinations and record how many times each $m1+m2,|m1|+|m2|$ combination occurs in a dictionary.



    Then I go through all the possible $m3,m4$ combinations and for each combination I calculate the necessary $m1+m2,|m1|+|m2|$ combination to make $Mm,Nm$, and I refer to the dictionary to find out how many $m1,m2$ combinations can make that.



    The difference is that you go through the $m1,m2$ combination then the $m3,m4$ combinations, and the number of operations is roughly a square root of going through every $m1,m2,m3,m4$ combination. You should be able to solve for $Nm = 1000,Mn = 0$ in a few seconds.






    share|improve this answer























      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: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      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%2f187608%2fcan-this-be-solved-even-faster%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      9
      down vote



      accepted










      ClearAll[num];

      num[n_, m_] /; OddQ[n + m] = 0;
      num[n_, n_] := Binomial[n + 3, 3];
      num[n_, m_] /; OddQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 3)/2 + 2 z - (2 z^2)];
      num[n_, m_] /; EvenQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 4)/2 - (2 z^2)];


      Testing vs fastest answer here at writing (Henrik Schumacher):



      stop = 100;

      res = Table[{n, m, dimNM3[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First
      res2 = Table[{n, m, num[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First

      res == res2



      169.203



      0.0219434



      True




      Large cases are a non-issue:



      num[123423456, 123412348] // AbsoluteTiming



      {0.0000247977, 30468069908023290}




      Some quick timings:



      enter image description here






      share|improve this answer



















      • 3




        Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
        – Henrik Schumacher
        2 days ago








      • 3




        @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
        – ciao
        2 days ago






      • 2




        Chapeaux for recognizing the patterns! =D
        – Henrik Schumacher
        2 days ago






      • 2




        @ciao - You Sir are a genius. Thank you.
        – Hubble07
        2 days ago






      • 1




        Answers from ciao are generally great reads, +1.
        – Marius Ladegård Meyer
        yesterday















      up vote
      9
      down vote



      accepted










      ClearAll[num];

      num[n_, m_] /; OddQ[n + m] = 0;
      num[n_, n_] := Binomial[n + 3, 3];
      num[n_, m_] /; OddQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 3)/2 + 2 z - (2 z^2)];
      num[n_, m_] /; EvenQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 4)/2 - (2 z^2)];


      Testing vs fastest answer here at writing (Henrik Schumacher):



      stop = 100;

      res = Table[{n, m, dimNM3[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First
      res2 = Table[{n, m, num[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First

      res == res2



      169.203



      0.0219434



      True




      Large cases are a non-issue:



      num[123423456, 123412348] // AbsoluteTiming



      {0.0000247977, 30468069908023290}




      Some quick timings:



      enter image description here






      share|improve this answer



















      • 3




        Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
        – Henrik Schumacher
        2 days ago








      • 3




        @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
        – ciao
        2 days ago






      • 2




        Chapeaux for recognizing the patterns! =D
        – Henrik Schumacher
        2 days ago






      • 2




        @ciao - You Sir are a genius. Thank you.
        – Hubble07
        2 days ago






      • 1




        Answers from ciao are generally great reads, +1.
        – Marius Ladegård Meyer
        yesterday













      up vote
      9
      down vote



      accepted







      up vote
      9
      down vote



      accepted






      ClearAll[num];

      num[n_, m_] /; OddQ[n + m] = 0;
      num[n_, n_] := Binomial[n + 3, 3];
      num[n_, m_] /; OddQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 3)/2 + 2 z - (2 z^2)];
      num[n_, m_] /; EvenQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 4)/2 - (2 z^2)];


      Testing vs fastest answer here at writing (Henrik Schumacher):



      stop = 100;

      res = Table[{n, m, dimNM3[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First
      res2 = Table[{n, m, num[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First

      res == res2



      169.203



      0.0219434



      True




      Large cases are a non-issue:



      num[123423456, 123412348] // AbsoluteTiming



      {0.0000247977, 30468069908023290}




      Some quick timings:



      enter image description here






      share|improve this answer














      ClearAll[num];

      num[n_, m_] /; OddQ[n + m] = 0;
      num[n_, n_] := Binomial[n + 3, 3];
      num[n_, m_] /; OddQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 3)/2 + 2 z - (2 z^2)];
      num[n_, m_] /; EvenQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 4)/2 - (2 z^2)];


      Testing vs fastest answer here at writing (Henrik Schumacher):



      stop = 100;

      res = Table[{n, m, dimNM3[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First
      res2 = Table[{n, m, num[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First

      res == res2



      169.203



      0.0219434



      True




      Large cases are a non-issue:



      num[123423456, 123412348] // AbsoluteTiming



      {0.0000247977, 30468069908023290}




      Some quick timings:



      enter image description here







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited 2 days ago

























      answered 2 days ago









      ciao

      17.1k137106




      17.1k137106








      • 3




        Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
        – Henrik Schumacher
        2 days ago








      • 3




        @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
        – ciao
        2 days ago






      • 2




        Chapeaux for recognizing the patterns! =D
        – Henrik Schumacher
        2 days ago






      • 2




        @ciao - You Sir are a genius. Thank you.
        – Hubble07
        2 days ago






      • 1




        Answers from ciao are generally great reads, +1.
        – Marius Ladegård Meyer
        yesterday














      • 3




        Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
        – Henrik Schumacher
        2 days ago








      • 3




        @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
        – ciao
        2 days ago






      • 2




        Chapeaux for recognizing the patterns! =D
        – Henrik Schumacher
        2 days ago






      • 2




        @ciao - You Sir are a genius. Thank you.
        – Hubble07
        2 days ago






      • 1




        Answers from ciao are generally great reads, +1.
        – Marius Ladegård Meyer
        yesterday








      3




      3




      Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
      – Henrik Schumacher
      2 days ago






      Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
      – Henrik Schumacher
      2 days ago






      3




      3




      @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
      – ciao
      2 days ago




      @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
      – ciao
      2 days ago




      2




      2




      Chapeaux for recognizing the patterns! =D
      – Henrik Schumacher
      2 days ago




      Chapeaux for recognizing the patterns! =D
      – Henrik Schumacher
      2 days ago




      2




      2




      @ciao - You Sir are a genius. Thank you.
      – Hubble07
      2 days ago




      @ciao - You Sir are a genius. Thank you.
      – Hubble07
      2 days ago




      1




      1




      Answers from ciao are generally great reads, +1.
      – Marius Ladegård Meyer
      yesterday




      Answers from ciao are generally great reads, +1.
      – Marius Ladegård Meyer
      yesterday










      up vote
      12
      down vote













      It is more efficient to first pick the integer partitions whose absolute values sum up to n before generating the permutations.



      dimNM3[n_, m_] := Total[
      Map[
      Length@*Permutations,
      Pick[#, Abs[#].ConstantArray[1, 4], n] &[
      IntegerPartitions[m, {4}, Range[-n, n]
      ]
      ]
      ]
      ];

      m = 20;
      n = 40;
      dimNM1[n, m] // AbsoluteTiming
      dimNM2[n, m] // AbsoluteTiming
      dimNM3[n, m] // AbsoluteTiming



      {0.116977, 3802}



      {0.995365, 3802}



      {0.005579, 3802}







      share|improve this answer



























        up vote
        12
        down vote













        It is more efficient to first pick the integer partitions whose absolute values sum up to n before generating the permutations.



        dimNM3[n_, m_] := Total[
        Map[
        Length@*Permutations,
        Pick[#, Abs[#].ConstantArray[1, 4], n] &[
        IntegerPartitions[m, {4}, Range[-n, n]
        ]
        ]
        ]
        ];

        m = 20;
        n = 40;
        dimNM1[n, m] // AbsoluteTiming
        dimNM2[n, m] // AbsoluteTiming
        dimNM3[n, m] // AbsoluteTiming



        {0.116977, 3802}



        {0.995365, 3802}



        {0.005579, 3802}







        share|improve this answer

























          up vote
          12
          down vote










          up vote
          12
          down vote









          It is more efficient to first pick the integer partitions whose absolute values sum up to n before generating the permutations.



          dimNM3[n_, m_] := Total[
          Map[
          Length@*Permutations,
          Pick[#, Abs[#].ConstantArray[1, 4], n] &[
          IntegerPartitions[m, {4}, Range[-n, n]
          ]
          ]
          ]
          ];

          m = 20;
          n = 40;
          dimNM1[n, m] // AbsoluteTiming
          dimNM2[n, m] // AbsoluteTiming
          dimNM3[n, m] // AbsoluteTiming



          {0.116977, 3802}



          {0.995365, 3802}



          {0.005579, 3802}







          share|improve this answer














          It is more efficient to first pick the integer partitions whose absolute values sum up to n before generating the permutations.



          dimNM3[n_, m_] := Total[
          Map[
          Length@*Permutations,
          Pick[#, Abs[#].ConstantArray[1, 4], n] &[
          IntegerPartitions[m, {4}, Range[-n, n]
          ]
          ]
          ]
          ];

          m = 20;
          n = 40;
          dimNM1[n, m] // AbsoluteTiming
          dimNM2[n, m] // AbsoluteTiming
          dimNM3[n, m] // AbsoluteTiming



          {0.116977, 3802}



          {0.995365, 3802}



          {0.005579, 3802}








          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 2 days ago

























          answered Dec 9 at 13:20









          Henrik Schumacher

          47.2k466134




          47.2k466134






















              up vote
              2
              down vote













              Sorry for not knowing much Mathematica, but I have a Python solution you might be able to follow. I'm putting this on the community wiki for anyone who wants to translate it.



              def count_solutions(Nm, Mm):
              firsthalves = dict()
              for m1 in range(-Nm,Nm+1):
              for m2 in range(-Nm,Nm+1):
              m = m1+m2
              n = abs(m1)+abs(m2)
              key = (m,n)
              if key in firsthalves:
              firsthalves[key] += 1
              else:
              firsthalves[key] = 1

              solutions = 0
              for m3 in range(-Nm,Nm+1):
              for m4 in range(-Nm,Nm+1):
              m = m3+m4
              n = abs(m3)+abs(m4)
              key = (Mm-m, Nm-n)
              if key in firsthalves:
              solutions += firsthalves[key]
              return solutions


              This is a meet in the middle strategy. I enumerate all the possible $m1,m2$ combinations and record how many times each $m1+m2,|m1|+|m2|$ combination occurs in a dictionary.



              Then I go through all the possible $m3,m4$ combinations and for each combination I calculate the necessary $m1+m2,|m1|+|m2|$ combination to make $Mm,Nm$, and I refer to the dictionary to find out how many $m1,m2$ combinations can make that.



              The difference is that you go through the $m1,m2$ combination then the $m3,m4$ combinations, and the number of operations is roughly a square root of going through every $m1,m2,m3,m4$ combination. You should be able to solve for $Nm = 1000,Mn = 0$ in a few seconds.






              share|improve this answer



























                up vote
                2
                down vote













                Sorry for not knowing much Mathematica, but I have a Python solution you might be able to follow. I'm putting this on the community wiki for anyone who wants to translate it.



                def count_solutions(Nm, Mm):
                firsthalves = dict()
                for m1 in range(-Nm,Nm+1):
                for m2 in range(-Nm,Nm+1):
                m = m1+m2
                n = abs(m1)+abs(m2)
                key = (m,n)
                if key in firsthalves:
                firsthalves[key] += 1
                else:
                firsthalves[key] = 1

                solutions = 0
                for m3 in range(-Nm,Nm+1):
                for m4 in range(-Nm,Nm+1):
                m = m3+m4
                n = abs(m3)+abs(m4)
                key = (Mm-m, Nm-n)
                if key in firsthalves:
                solutions += firsthalves[key]
                return solutions


                This is a meet in the middle strategy. I enumerate all the possible $m1,m2$ combinations and record how many times each $m1+m2,|m1|+|m2|$ combination occurs in a dictionary.



                Then I go through all the possible $m3,m4$ combinations and for each combination I calculate the necessary $m1+m2,|m1|+|m2|$ combination to make $Mm,Nm$, and I refer to the dictionary to find out how many $m1,m2$ combinations can make that.



                The difference is that you go through the $m1,m2$ combination then the $m3,m4$ combinations, and the number of operations is roughly a square root of going through every $m1,m2,m3,m4$ combination. You should be able to solve for $Nm = 1000,Mn = 0$ in a few seconds.






                share|improve this answer

























                  up vote
                  2
                  down vote










                  up vote
                  2
                  down vote









                  Sorry for not knowing much Mathematica, but I have a Python solution you might be able to follow. I'm putting this on the community wiki for anyone who wants to translate it.



                  def count_solutions(Nm, Mm):
                  firsthalves = dict()
                  for m1 in range(-Nm,Nm+1):
                  for m2 in range(-Nm,Nm+1):
                  m = m1+m2
                  n = abs(m1)+abs(m2)
                  key = (m,n)
                  if key in firsthalves:
                  firsthalves[key] += 1
                  else:
                  firsthalves[key] = 1

                  solutions = 0
                  for m3 in range(-Nm,Nm+1):
                  for m4 in range(-Nm,Nm+1):
                  m = m3+m4
                  n = abs(m3)+abs(m4)
                  key = (Mm-m, Nm-n)
                  if key in firsthalves:
                  solutions += firsthalves[key]
                  return solutions


                  This is a meet in the middle strategy. I enumerate all the possible $m1,m2$ combinations and record how many times each $m1+m2,|m1|+|m2|$ combination occurs in a dictionary.



                  Then I go through all the possible $m3,m4$ combinations and for each combination I calculate the necessary $m1+m2,|m1|+|m2|$ combination to make $Mm,Nm$, and I refer to the dictionary to find out how many $m1,m2$ combinations can make that.



                  The difference is that you go through the $m1,m2$ combination then the $m3,m4$ combinations, and the number of operations is roughly a square root of going through every $m1,m2,m3,m4$ combination. You should be able to solve for $Nm = 1000,Mn = 0$ in a few seconds.






                  share|improve this answer














                  Sorry for not knowing much Mathematica, but I have a Python solution you might be able to follow. I'm putting this on the community wiki for anyone who wants to translate it.



                  def count_solutions(Nm, Mm):
                  firsthalves = dict()
                  for m1 in range(-Nm,Nm+1):
                  for m2 in range(-Nm,Nm+1):
                  m = m1+m2
                  n = abs(m1)+abs(m2)
                  key = (m,n)
                  if key in firsthalves:
                  firsthalves[key] += 1
                  else:
                  firsthalves[key] = 1

                  solutions = 0
                  for m3 in range(-Nm,Nm+1):
                  for m4 in range(-Nm,Nm+1):
                  m = m3+m4
                  n = abs(m3)+abs(m4)
                  key = (Mm-m, Nm-n)
                  if key in firsthalves:
                  solutions += firsthalves[key]
                  return solutions


                  This is a meet in the middle strategy. I enumerate all the possible $m1,m2$ combinations and record how many times each $m1+m2,|m1|+|m2|$ combination occurs in a dictionary.



                  Then I go through all the possible $m3,m4$ combinations and for each combination I calculate the necessary $m1+m2,|m1|+|m2|$ combination to make $Mm,Nm$, and I refer to the dictionary to find out how many $m1,m2$ combinations can make that.



                  The difference is that you go through the $m1,m2$ combination then the $m3,m4$ combinations, and the number of operations is roughly a square root of going through every $m1,m2,m3,m4$ combination. You should be able to solve for $Nm = 1000,Mn = 0$ in a few seconds.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Dec 9 at 23:42


























                  community wiki





                  2 revs
                  James Hollis































                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Mathematica Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      Use MathJax to format equations. MathJax reference.


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





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


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




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f187608%2fcan-this-be-solved-even-faster%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                      Alcedinidae

                      Origin of the phrase “under your belt”?