2010-08-25 13 views
6

Me gusta Select[Tuples[Range[0, n], d], Total[#] == n &], pero más rápido?enumerando todas las particiones en Mathematica

actualización

Estas son las 3 soluciones y parcela de sus tiempos, IntegerPartitions seguido de permutaciones parece ser más rápido. Timing a 1, 7, 0,03 para las soluciones recursivas, FrobeniusSolve y IntegerPartition respectivamente

 
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]] 

Respuesta

7

Su función:

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

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

Out[22]= {0.219, Null} 

Probar FrobeniusSolve:

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

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

Out[24]= {0.031, Null} 

Los resultados son los mismos:

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

Out[25]= True 

Puede que sea más rápido con IntegerPartitions, aunque no obtiene los resultados en el mismo orden:

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

los resultados ordenados son los mismos:

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

Out[46]= True 

Es mucho más rápido:

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

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

Gracias a la rápida respuesta de phadej por hacerme ver de nuevo.

en cuenta que sólo necesita la llamada a Permutations (y Flatten) si realmente se desea que todas las permutaciones de manera diferente ordenada, es decir, si quieres

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

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

en lugar de

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

Out[60]= {{3, 0}, {2, 1}} 
5
partition[n_, 1] := {{n}} 
partition[n_, d_] := Flatten[ Table[ Map[Join[{k}, #] &, partition[n - k, d - 1]], {k, 0, n}], 1] 

Este es incluso más rápido que FrobeniusSolve :)

Editar: Si lo escribe diez en Haskell, probablemente sea más claro lo que está sucediendo, también funcional:

partition n 1 = [[n]] 
partition n d = concat $ map outer [0..n] 
    where outer k = map (k:) $ partition (n-k) (d-1) 
Cuestiones relacionadas