Finding the Inverse of Euler Totient Function
Author
Maxim Rytin
Title
Finding the Inverse of Euler Totient Function
Description
Discussion and implementation of an efficient algorithm for finding all the solutions to the equation EulerPhi[n]==m.
Category
Educational Materials
Keywords
URL
http://www.notebookarchive.org/2018-10-10qtft8/
DOI
https://notebookarchive.org/2018-10-10qtft8
Date Added
2018-10-02
Date Last Modified
2018-10-02
File Size
35.73 kilobytes
Supplements
Rights
Redistribution rights reserved




Here we will implement an algorithm for computing the 'inverse' of Euler totient function . is defined as the number of positive integers less than and relatively prime to . The inverse function for a given will return the list of all the numbers such that .
ϕ(n)
ϕ(n)
n
n
m
n
ϕ(n)=m
How can all the solutions to the equation be found? Naturally, let's start by looking at the decomposition of and into primes. Let Euler function can be expressed explicitly via the prime factors of : ( 1 )
ϕ(n)=m
m
n
n=,m=,ϕ(n)=m
r
∏
k=1
a
k
p
k
s
∏
k=1
b
k
q
k
n
ϕ(n)=-1(-1)=m=
r
∏
k=1
a
k
p
k
p
k
s
∏
k=1
b
k
q
k
It immediately follows from (1) that -1 and cannot contain any prime factors that are not in the set . Hence we can rewrite their decompositions thus: and where each belongs to . Allowing the powers to be zero, we can rewrite the last formula including all the in the product:
a
k
p
k
(-1)
p
k
Q=
s
{}
q
k
k=1
∀k==1∨∃=
1,r
a
k
q
i
p
k
∀k==2∨=+1
1,r
p
k
p
k
t
k
∏
i=1
b
k,i
q
k,i
q
k,i
Q
b
k,i
q
k
∀k==+1
1,r
p
k
s
∏
i=1
b
k,i
q
i
Another fact that follows from (1) is that (-1) divides . Therefore, for each we have ≤. This means that we can find all the that can possibly occur in by simply trying all possible products of raised to any power not greater than . And by transforming (1) we get ( 2 )so we can get all the solutions by substituting all possible combinations of into (2). Not all that we get this way will satisfy the equation , but right now it is important to us that no solutions will be lost.
r
∏
1
p
k
m
i,k
b
k,i
b
i
p
k
n
q
i
b
i
ϕ(n)=(-1)=n1-=m
r
∏
1
a
k
p
k
p
k
p
k
r
∏
1
1
p
k
n=m
r
∏
1
-1
1-
1
p
k
n
p
k
n
ϕ(n)=m
Another simple way to find (m) would be to estimate the range containing all the solutions. First, >1, and second, if <, then >. If the total number of is and they are sorted from smallest to largest: <<...<, then ≤n≤mNow we need to estimate the values of . The largest is not greater than because each divides (see above). And if we denote the th prime in the row of natural numbers as , then ≥. Additionally, for all this inequality holds: >kln(k). For equal to one the right side is zero, so we use this inequality for (and explicitly substitute =2), and get The constant is not greater than , the number of divisors of (again, because is divisible by each ), and finally we get
-1
ϕ
-1
1-
1
p
k
p
i
p
j
-1
1-
1
p
i
-1
1-
1
p
j
p
k
R
p
1
p
2
p
R
-1
m1-
1
p
R
R
∏
k=1
-1
1-
1
p
k
p
k
(m+1)
(-1)
p
k
m
k
π
k
p
k
π
k
k
π
k
k
k≥2
π
1
m≤m≤2m
R
∏
k=1
-1
1-
1
p
k
R
∏
k=1
-1
1-
1
π
k
R
∏
k=2
-1
1-
1
kln(k)
R
χ(m)
m
m
(-1)
p
k
m+1≤n≤2m
χ(m)
∏
k=2
-1
1-
1
kln(k)
invphidemo1[m_]:=Module[{Lp,Lq,Lb,Lpow,Lfact,n},{Lq,Lb}=Transpose[FactorInteger[m]];Lpow=MapThread[Table[#1^i,{i,0,#2}]&,{Lq,Lb}];Lp=Outer[Times,Sequence@@Lpow];Lp=Select[Flatten[Lp]+1,PrimeQ];Lfact=Table[(Lp[[i]]/(Lp[[i]]-1))^j,{i,Length[Lp]},{j,0,1}];n=mOuter[Times,Sequence@@Lfact];Select[Flatten[n],EulerPhi[#]m&]]
invphidemo2[m_]:=SelectRangem+1,2m,EulerPhi[#]m&
DivisorSigma[0,m]
∏
k=2
-1
(1-1/(kLog[k]))
invphidemo1[12]invphidemo2[12]
{13,21,26,28,36,42}
{13,21,26,28,36,42}
Of course, these are bad solutions. They are very slow, and the first one requires prodigious amounts of memory. The reason is that if the powers are large, the set of can be many times larger than the set , and creating the table of all the possible products of is nearly impossible. The function still will involve the search for all combinations of that yield solutions but our goal is to make this search more efficient.
b
k
p
k
Q
p
k
invphi
p
k
Let's denote the set of all the that can possibly occur in a solution as . We want to create list ={,,...,}, with elements from , corresponding to one of the solutions . This means that we'll get a solution by applying formula (2) to . Note that denotes the list with elements and not the th element. This notation will be handy for us because is different for each and is not known in advance. Let on some step in the algorithm we already have elements . Then the problem is reduced to deciding adding which to can yield a valid solution, and which needn't be tried, being 'incompatible' with those that are in the list already.
p
k
P=
R
{}
p
k
k=1
L
r
p
i
1
p
i
2
p
i
r
P
n
L
r
L
r
r
r
r
n
t
L
t
p
k
L
t
p
k
p
k
First, as was already shown, the product -1 divides , so their quotient =mis integer. Therefore, before adding to we should check that the resulting quotient is integer, and if it's not, is not added.
r
∏
k=1
p
i
k
m
d
r
r
∏
k=1
-1
-1
p
i
k
p
k
L
t
d
t+1
p
k
Second, contains only prime factors from (because is divided by something). But by formula (1), =-1It follows that only those primes can occur in which belong to and are also members of . So on the step where we have elements we should check if the 'current' quotient contains a factor which is not a member of . If such exists, then it cannot appear in the 'final' quotient unless it belongs to . Therefore, we can add to (possible only if belongs to ) or eliminate from the quotient on the next steps, if we want to arrive to a solution. The elimination can be done by selecting such that is divisible by , so in the next quotient =-1 the power to which appears in it will be lowered (though may still be present in ). How this all benefits the algorithm is that instead of trying to add all the possible that are not in the list yet, we can find out that there is a much smaller subset of such that at least one of its elements should necessarily be appended to , in order to eliminate a . Then we may try building new lists from by adding only from that subset first (adding them separately, thus creating several new 'candidates' from ). This way we can significantly reduce the amount of search without losing any of the solutions.
d
r
Q
d
r
m
d
r
r
∏
k=1
a
i
k
p
i
k
d
r
P⋂Q
L
r
t
d
t
q
k
L
t
q
k
d
r
L
r
q
k
L
t
q
k
P
q
k
p
i
t+1
-1
p
i
t+1
q
k
d
t+1
d
t
p
i
t+1
q
k
q
k
d
t+1
p
k
P
L
t
q
k
L
t
p
k
L
t
Another important consequence is that if want to know whether corresponds to a valid solution or not, it can be checked without computing . The criterion of its validity is exactly the condition discussed above, namely that can contain only those that appear in .
L
t
EulerPhi
d
t
q
k
L
t
The program first finds . and are rearranged so that all their common elements, the number of which is denoted , come in the beginning and have the same positions in both lists. The main structure is a list of solution candidates. Each element of has in turn two elements. The first one defines . It contains an indicator for each from showing if that is already in , can, or can not be added to it (1, 0, -1 respectively). The second element is . On each step we check if there are any factors in the quotient that should be eliminated. If there are, then we see how many can reduce the power to which occurs in , ie how many have the property that is divisible by . (As discussed above, another possibility is =). We always select the for which the number of those is the smallest, thus trying to minimize the number of new candidates that will be added. If no to be eliminated are found, then all members of that are allowed for the current are added to it. For each new element of thus created we find the new quotient , and mark as 'incompatible' those that would make fractional. Also, if we are adding several to , say and , creating two new lists, =Append[,] and =Append[,], then in is marked as 'incompatible' too in order to avoid possible repetitions of the same sets of later. When nothing further can be added to , the final list of solutions is generated by selecting those elements from that yield correct values of . This is done in a similar way; we consider the corresponding quotient, and if no need to be eliminated, then we have a solution.
invphi
P
P
Q
r
0
wrk
wrk
L
t
p
k
P
p
k
L
t
d
t
q
k
d
t
p
i
q
k
d
t
p
i
(-1)
p
i
q
k
p
i
q
k
q
k
p
i
q
k
P
L
t
wrk
d
t+1
p
k
d
t+2
p
k
L
t
p
1
p
2
(1)
L
t+1
L
t
p
1
(2)
L
t+1
L
t
p
2
(2)
L
t+1
p
1
p
k
wrk
wrk
n
q
k
There are some other ways to improve the performance. It can be easily noticed that if we add =2 to the list, then the quotient doesn't change on the next step. We can speed up the search by never considering =2, and only taking into consideration the possible presence of this factor later, when generating solutions from the lists of . Also, for selecting the that can eliminate a given , the structure is created in advance, in which is the list of indices such that divides . Finally, after we have created new lists from , we'll never return to again. When the structure grows large, we can convert those elements to the final result and remove them from . This not only reduces the memory usage, but makes large computations significantly faster, because operations will be performed with smaller lists.
p
k
p
k
p
k
p
i
q
k
Mdiv
Mdiv〚k〛
i
q
k
(-1)
p
i
L
t
L
t
wrk
n
wrk
In Mathematica, . complies with this conventions. Also note that only the list of nonnegative solutions is returned, while in Mathematica .
ϕ(0)=0,ϕ(1)=1
invphi
ϕ(-n)=ϕ(n)
invphi[m_Integer]:=Module[{main,init,genp,bestcand,gencand,addcand,genans,Lp,Lq,r,s,r0,Mdiv},main[]:=Module[{ans={},wrk,threshold=100,Lstate,Ladd,quo,indx,i},wrk={{Table[0,{r}],m}};wrk[[1,1,1]]=-1;For[i=1,i≤Length[wrk],i++,If[ithreshold+1,ans={ans,genans[Take[wrk,threshold]]};wrk=Drop[wrk,threshold];i=1];{Lstate,quo}=wrk[[i]];indx=bestcand[Lstate,quo];Ladd=gencand[Lstate,indx];wrk=Join[wrk,addcand[Lstate,quo,Ladd]]];Flatten[{ans,genans[wrk]}]];init[]:=Module[{Lb,Lpq},{Lq,Lb}=Transpose[FactorInteger[m]];genp[Lb];Lpq=Intersection[Lp,Lq];{Lp,Lq}=Join[Lpq,Complement[#,Lpq]]&/@{Lp,Lq};{r,s,r0}=Length/@{Lp,Lq,Lpq};Mdiv=Cases[Range[r],x_/;Mod[Lp[[x]]-1,#]0]&/@Lq;];genp[Lb_]:=Module[{Lpow,tmp},Lpow=MapThread[Table[#1^i,{i,0,#2}]&,{Lq,Lb}];Lp={};Outer[If[PrimeQ[tmp=Times[##]+1],Lp={Lp,tmp}]&,Sequence@@Lpow];Lp=Flatten[Lp];];bestcand[Lstate_,quo_]:=Module[{len=Infinity,indx=0,cur,i},For[i=1,i≤s,i++,If[((i≤r0&&Lstate[[i]]≠1)||i>r0)&&Mod[quo,Lq[[i]]]0,cur=Length[Mdiv[[i]]];If[cur<len,len=cur;indx=i]]];indx];gencand[Lstate_,indx_]:=Module[{Ladd},Ladd=If[indx≠0,If[indx≤r0,Prepend[Mdiv[[indx]],indx],Mdiv[[indx]]],Range[r]];Select[Ladd,Lstate[[#]]0&]];addcand[Lstate_,quo_,Ladd_]:=Module[{ans={},Lstate2,quo2,len,i},len=Length[Ladd];For[i=1,i≤len,i++,Lstate2=ReplacePart[Lstate,1,Ladd[[i]]];quo2=quo/(Lp[[Ladd[[i]]]]-1);(Lstate2[[Ladd[[#]]]]=-1)&/@Range[i-1];If[Lstate2[[#]]0&&Mod[quo2,Lp[[#]]-1]≠0,Lstate2[[#]]=-1]&/@Range[r];AppendTo[ans,{Lstate2,quo2}]];ans];genans[L_]:=Module[{ans={},Lstate,quo,res,add2,i,j},For[i=1,i≤Length[L],i++,{Lstate,quo}=L[[i]];For[add2=0,add2≤1,add2++,If[add21,Lstate[[1]]=1];For[j=1,j≤s,j++,If[((j≤r0&&Lstate[[j]]≠1)||j>r0)&&Mod[quo,Lq[[j]]]0,Break[]]];If[j≠s+1,Continue[]];res=Cases[Transpose[{Lp,Lstate}],{x_,1}x];res=mTimes@@res/Times@@(res-1);ans={ans,res}]];ans];Switch[m,0,Return[{0}],1,Return[{1,2}],_?(OddQ[#]||Negative[#]&),Return[{}]];init[];main[]]
Here finding all 847 solutions takes only a few seconds.
Timing[Length[invphi[]]]
5
2
5
3
5
5
{6.37Second,847}
In this case, factoring each of the resulting integers would take about 150 seconds, so checking the answer takes many times longer than finding it.
Timing[invphi[]]
3
2
3
31
3
313
3
619
3
1511
3
1733
{6.48Second,{62244230888910733677707758056446080408564,46683173166683050258280818542334560306423,93366346333366100516561637084669120612846}}
Copyright © 1999, Maxim Rytin


Cite this as: Maxim Rytin, "Finding the Inverse of Euler Totient Function" from the Notebook Archive (2002), https://notebookarchive.org/2018-10-10qtft8

Download

