Compute the arithmetic functions for large integer in Mathematica faster?

寵の児 提交于 2019-12-24 08:26:18

问题


Let f be an arithmetic function and A={k1,k2,...,kn} are integers in increasing order.

Now I want to start with k1 and compare f(ki) with f(k1). If f(ki)>f(k1), put ki as k1.

Now start with ki, and compare f(kj) with f(ki), for j>i. If f(kj)>f(ki), put kj as ki, and repeat this procedure.

At the end we will have a sub sequence B={L1,...,Lm} of A by this property:

L1=k1
L2=ki
L3=kj
...

where

f(L(i+1))>f(L(i)), for any 1<=i<=m-1

For example, let f be the divisor function of integers.

I think there should be some way to do more efficient and faster than I did.

Do you know how to write a code for my purpose in Mathematica or Matlab.

Mathematica is preferable.

«««««««««««««««««««««««««««««««

I have written a code for this program with Mathematica, and it take some hours to compute f of ki's or the set B for large numbers.

Here I put some part of my code and this is just a sample and the question in my program could be more larger than these:

the space between g's are product. for example:

g[67757] g[353]=g[67757]*g[353]

««««««««««««««««««««««««««««««««««««

f[n_] := DivisorSigma[0, n];
g[n_] := Product[Prime[i], {i, 1, PrimePi[n]}];

k1 = g[67757] g[353] g[59] g[19] g[11] g[7] g[5]^2 6^3 2^7;
k2 = g[67757] g[353] g[59] g[19] g[11] g[7] g[5] 6^5 2^7;
k3 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5] 6^4 2^7;
k4 = g[67759] g[349] g[53] g[19] g[11] g[7] g[5] 6^5 2^6;
k5 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5] 6^4 2^8;
k6 = g[67759] g[349] g[53] g[19] g[11] g[7] g[5]^2 6^3 2^7;
k7 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5] 6^5 2^6;
k8 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5] 6^4 2^9;
k9 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5]^2 6^3 2^7;
k10 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5] 6^5 2^7;
k11 = g[67759] g[349] g[53] g[19] g[11] g[7] g[5]^2 6^4 2^6;
k12 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5]^2 6^3 2^8;
k13 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5]^2 6^4 2^6;
k14 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5]^2 6^3 2^9;
k15 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5]^2 6^4 2^7;
k16 = g[67757] g[359] g[53] g[23] g[11] g[7] g[5] 6^4 2^8;
k17 = g[67757] g[359] g[59] g[19] g[11] g[7] g[5] 6^4 2^7;
k18 = g[67757] g[359] g[53] g[23] g[11] g[7] g[5] 6^4 2^9;
k19 = g[67759] g[353] g[53] g[19] g[11] g[7] g[5] 6^4 2^6;
k20 = g[67763] g[347] g[53] g[19] g[11] g[7] g[5] 6^4 2^7;

k = Table[k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k20];

i = 1;
count = 0;
For[j = i, j <= 20, j++, 
  If[f[k[[j]]] - f[k[[i]]] > 0, i = j; Print["k",i];
   count = count + 1]];

Print["count= ", count]

««««««««««««««««««««««««««««««««««««


回答1:


DivisorSigma has to factor the numbers (it has no idea how they were constructed). You can speed this substantially by removing the gcd of the list. In detail:

Compute new list as old list / gcd.

Factor the gcd.

Use a function that, given a pair of integers in factored form, merges the factorization (so you have their product in factored form).

Then for any two elements in the reduced list, you compare by merging their factorizations each with that of the gcd, and invoking a function to compute the number of divisors when given the factored form. That last is simply the product of the exponents each increased by one.

In code:

kgcd = GCD @@ k;
newk = k/kgcd;
gcdfacs = FactorInteger[kgcd];

sumDivisors[faclist_] := Times @@ (1 + faclist[[All, 2]])

mergeFactorLists[fl1_, fl2_] := 
 Flatten[GatherBy[Join[fl1, fl2], First] /.
{{p1_Integer,e1_Integer}, {p1_,e2_Integer}} -> {{p1,e1+e2}}, 1]

f2[v1_] := sumDivisors[mergeFactorLists[FactorInteger[v1], gcdfacs]]

Here is your example, with f2 applied to elements of newk.

Timing[i = 1;
  count = 0;
  For[j = i, j <= 20, j++,
    If[f2[newk[[j]]] - f2[newk[[i]]] > 0, i = j; Print["k", i];
      count = count + 1]];
  Print["count= ", count]]

During evaluation of In[140]:= k2

During evaluation of In[140]:= k5

During evaluation of In[140]:= k7

During evaluation of In[140]:= k8

During evaluation of In[140]:= k9

During evaluation of In[140]:= k10

During evaluation of In[140]:= k12

During evaluation of In[140]:= k13

During evaluation of In[140]:= k14

During evaluation of In[140]:= k15

During evaluation of In[140]:= k16

During evaluation of In[140]:= k17

During evaluation of In[140]:= k18

During evaluation of In[140]:= count= 13

Out[140]= {0.539918, Null}

As others commented, you might instead want to do SortBy or perhaps

sortedk = k[[Ordering[newk, All, f2[#1] < f2[#2] &]]];

--update 2011-02-01--

Here are the various requested function, made to operate on integers represented as lists of their prime factors and corresponding powers. We use utility functions to "multiply" two or more such representations, so that they are easily constructed from the definition for g[] above.

logarithm[fl_] := fl[[All,2]] . Log[fl[[All,1]]]

divSigma[k_, fax_] := Times @@
  ((fax[[All, 1]]^(k*(fax[[All, 2]] + 1)) - 1)/(fax[[All, 1]]^k - 1))

mergeFactorLists[f1_,f2_,f3__] := 
  mergeFactorLists[mergeFactorLists[f1,f2],f3]

mergeFactorLists[fl1_, fl2_] := 
  Flatten[GatherBy[Join[fl1, fl2], First] /.
    {{p1_Integer,e1_Integer}, {p1_,e2_Integer}} -> {{p1,e1+e2}}, 1]

eulerPhi[fl_] := 
 Times @@ ((fl[[All, 1]] - 1)*fl[[All, 1]]^(fl[[All, 2]] - 1))

I use factorlist in a manner similar to use of g[] above, but to obtain the factored lists rather than the integer itself. For ease of converting code, you might do as below.

g[n__] := factorList[n]

Then you would construct k1 et al as:

k1 = mergeFactorLists[g[67757], g[353], g[59], g[19], g[11], g[7], 
  g[5, 2], g[4, 3], g[2, 7]];

I remark that it might be better to use indexing e.g. k[1], k[2], etc. This way you can store the index instead of the number (whether represented as a factored list or fully expanded). This was a concern in either your comments or private email, I'm not sure.

Here is a short example to indicate that the functions might be working as advertised.

In[77]:= example = mergeFactorLists[g[59], g[19], g[11], g[7], g[5, 2], g[4, 3], g[2, 7]] Out[77]= {{2, 16}, {3, 9}, {5, 6}, {7, 4}, {11, 3}, {13, 2}, {17, 2}, {19, 2}, {23, 1}, {29, 1}, {31, 1}, {37, 1}, {41, 1}, {43, 1}, {47, 1}, {53, 1}, {59, 1}}

In[83]:= divSigma[2, example] Out[83]= 8309625653259163198663074449058595410045270294408417958734031\ 0136565010401600000000

In[92]:= eulerPhi[example] Out[92]= 30117106786279162451552137484697600000000

In[95]:= examplenumber = Times @@ Map[#[[1]]^#[[2]] &, example] Out[95]= 225123336762006539948611826706656256000000

In[99]:= DivisorSigma[2, examplenumber] Out[99]= 8309625653259163198663074449058595410045270294408417958734031\ 0136565010401600000000

In[100]:= EulerPhi[examplenumber] Out[100]= 30117106786279162451552137484697600000000

--end update--

Daniel Lichtblau Wolfram Research




回答2:


On my version of mathematica, most of the calculation time is spent applying the function f[n]. Even just f[k1] takes a few seconds.

In any case, what you want to do is use SortBy. This will take a list and a function as arguments. It applies the function to every member of the list and sorts them in order from least-to-greatest, so you'll need to swap the list around to greatest-to-least. Remember to use k = List[k1, k2, ... , k20] instead of k = Table[k1, k2, ... , k20] and you should be good.




回答3:


Part of the reason why this is so slow is because you're using for's and if's in Mathematica. Neither are particularly fast.

Ordinarily it's recommended to try doing some list operation, as this is MUCH faster. I'm not sure how you could accomplish this off hand, but you may want to look into it.



来源:https://stackoverflow.com/questions/4830953/compute-the-arithmetic-functions-for-large-integer-in-mathematica-faster

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!