枚举 Mathematica 中的所有分区

发布于 2024-09-16 08:31:33 字数 754 浏览 4 评论 0原文

类似于 Select[Tuples[Range[0, n], d], Total[#] == n &],但速度更快?

更新

以下是 3 个解决方案及其时间图,IntegerPartitions 和 Permutations 似乎是最快的。递归、FrobeniusSolve 和 IntegerPartition 解的时序分别为 1、7、0.03

partition[n_, 1] := {{n}};
partition[n_, d_] := 
  Flatten[Table[
    Map[Join[{k}, #] &, partition[n - k, d - 1]], {k, 0, n}], 1];
f[n_, d_, 1] := partition[n, d];
f[n_, d_, 2] := FrobeniusSolve[Array[1 &, d], n];
f[n_, d_, 3] := 
  Flatten[Permutations /@ IntegerPartitions[n, {d}, Range[0, n]], 1];
times = Table[First[Log[Timing[f[n, 8, i]]]], {i, 1, 3}, {n, 3, 8}];
Needs["PlotLegends`"];
ListLinePlot[times, PlotRange -> All, 
 PlotLegend -> {"Recursive", "Frobenius", "IntegerPartitions"}]
Exp /@ times[[All, 6]]

Like Select[Tuples[Range[0, n], d], Total[#] == n &], but faster?

Update

Here are the 3 solutions and plot of their times, IntegerPartitions followed by Permutations seems to be fastest. Timing at 1, 7, 0.03 for recursive, FrobeniusSolve and IntegerPartition solutions respectively

partition[n_, 1] := {{n}};
partition[n_, d_] := 
  Flatten[Table[
    Map[Join[{k}, #] &, partition[n - k, d - 1]], {k, 0, n}], 1];
f[n_, d_, 1] := partition[n, d];
f[n_, d_, 2] := FrobeniusSolve[Array[1 &, d], n];
f[n_, d_, 3] := 
  Flatten[Permutations /@ IntegerPartitions[n, {d}, Range[0, n]], 1];
times = Table[First[Log[Timing[f[n, 8, i]]]], {i, 1, 3}, {n, 3, 8}];
Needs["PlotLegends`"];
ListLinePlot[times, PlotRange -> All, 
 PlotLegend -> {"Recursive", "Frobenius", "IntegerPartitions"}]
Exp /@ times[[All, 6]]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

呆橘 2024-09-23 08:31:33

您的函数:

In[21]:= g[n_, d_] := Select[Tuples[Range[0, n], d], Total[#] == n &]

In[22]:= Timing[g[15, 4];]

Out[22]= {0.219, Null}

尝试 FrobeniusSolve

In[23]:= f[n_, d_] := FrobeniusSolve[ConstantArray[1, d], n]

In[24]:= Timing[f[15, 4];]

Out[24]= {0.031, Null}

结果是相同的:

In[25]:= f[15, 4] == g[15, 4]

Out[25]= True

您可以使其更快与 IntegerPartitions,尽管您没有以相同的顺序获得结果

In[43]:= h[n_, d_] := 
 Flatten[Permutations /@ IntegerPartitions[n, {d}, Range[0, n]], 1]

:排序结果是相同的:

In[46]:= Sort[h[15, 4]] == Sort[f[15, 4]]

Out[46]= True

速度更快:

In[59]:= {Timing[h[15, 4];], Timing[h[23, 5];]}

Out[59]= {{0., Null}, {0., Null}}

感谢 phadej 的快速回答让我再次查看。

请注意,您只需要调用 Permutations (和 Flatten) 如果您实际上想要所有不同顺序的排列,即如果您想要

In[60]:= h[3, 2]

Out[60]= {{3, 0}, {0, 3}, {2, 1}, {1, 2}}

而不是

In[60]:= etc[3, 2]

Out[60]= {{3, 0}, {2, 1}}

Your function:

In[21]:= g[n_, d_] := Select[Tuples[Range[0, n], d], Total[#] == n &]

In[22]:= Timing[g[15, 4];]

Out[22]= {0.219, Null}

Try FrobeniusSolve:

In[23]:= f[n_, d_] := FrobeniusSolve[ConstantArray[1, d], n]

In[24]:= Timing[f[15, 4];]

Out[24]= {0.031, Null}

The results are the same:

In[25]:= f[15, 4] == g[15, 4]

Out[25]= True

You can make it faster with IntegerPartitions, though you don't get the results in the same order:

In[43]:= h[n_, d_] := 
 Flatten[Permutations /@ IntegerPartitions[n, {d}, Range[0, n]], 1]

The sorted results are the same:

In[46]:= Sort[h[15, 4]] == Sort[f[15, 4]]

Out[46]= True

It is much faster:

In[59]:= {Timing[h[15, 4];], Timing[h[23, 5];]}

Out[59]= {{0., Null}, {0., Null}}

Thanks to phadej's fast answer for making me look again.

Note you only need the call to Permutations (and Flatten) if you actually want all the differently ordered permutations, i.e. if you want

In[60]:= h[3, 2]

Out[60]= {{3, 0}, {0, 3}, {2, 1}, {1, 2}}

instead of

In[60]:= etc[3, 2]

Out[60]= {{3, 0}, {2, 1}}
吲‖鸣 2024-09-23 08:31:33
partition[n_, 1] := {{n}}
partition[n_, d_] := Flatten[ Table[ Map[Join[{k}, #] &, partition[n - k, d - 1]], {k, 0, n}], 1]

这甚至比 FrobeniusSolve 还要快:)

编辑:如果用 Haskell 编写,可能会更清楚正在发生的事情 - 功能也是如此:

partition n 1 = [[n]]
partition n d = concat $ map outer [0..n]
  where outer k = map (k:) $ partition (n-k) (d-1)
partition[n_, 1] := {{n}}
partition[n_, d_] := Flatten[ Table[ Map[Join[{k}, #] &, partition[n - k, d - 1]], {k, 0, n}], 1]

This is even quicker than FrobeniusSolve :)

Edit: If written in Haskell, it's probably clearer what is happening - functional as well:

partition n 1 = [[n]]
partition n d = concat $ map outer [0..n]
  where outer k = map (k:) $ partition (n-k) (d-1)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文