Suppose I have a list of (complex, in my case) numbers, and I want to construct the coefficients of the monic polynomial of which they are the roots. The obvious way:
poly[n_]:= CoefficientList[Expand[Product[x-list[[i]],{i, 1, n}]], x]
Seems to take quartic time in $n,$ and for $n=5000$ takes about a minute on my MacBook Pro.
The less obvious way:
poly2[n_]:= CoefficientList[CharacteristicPolynomial[DiagonalMatrix[list], x], x]
Is much faster (takes 8 seconds for the same computation) but it's hard to believe that this is optimal. Any ideas?
Edit There is also InterpolatingPolynomial
, but that is slower than the CharacteristicPolynomial
scheme.
More interesting edit Upon meditating on this for a while, I came up with the following:
cfromr[roots_] :=
With[{n = Length[roots],
f = Compile[{{x, _Complex}},
Product[(x - roots[[i]]), {i, 1, Length[roots]}]]},
Module[{fvals = Array[f[Exp[(# - 1) 2 Pi I/(n + 1)]] &, n + 1]},
InverseFourier[fvals]/Sqrt[n + 1]]]
Let's try it:
cfromr[{1}]
{-1., 1.}
cfromr[{1, 1}]
{1., -2., 1.}
cfromr[{1, 2, 3}]
{-6., 11., -6., 1.}
Cool! And of course, it is fast as blazes (orders of magnitude faster than the previous efforts - try it). But, let's just try it for something a little more complicated, and compare it with the boneheaded approach below:
stupidCfromR[roots_] :=
CoefficientList[Product[x - roots[[i]], {i, 1, Length[roots]}], x]
OK,
foo = RandomReal[{0, 1}, 100]
{0.615659, 0.749481, 0.877498, 0.179083, 0.580726, 0.297616, 0.436366, \
0.885845, 0.207169, 0.979251, 0.768706, 0.962705, 0.934818, 0.558659, \
0.810448, 0.578337, 0.880773, 0.0389867, 0.561441, 0.636913, \
0.747634, 0.061617, 0.686383, 0.149683, 0.413282, 0.659633, 0.534624, \
0.266132, 0.16876, 0.29776, 0.156488, 0.678895, 0.287585, 0.192998, \
0.527663, 0.352505, 0.718803, 0.380109, 0.44967, 0.46576, 0.693758, \
0.557772, 0.811107, 0.824323, 0.77316, 0.365756, 0.283581, 0.849779, \
0.0787828, 0.180125, 0.0536948, 0.406494, 0.570083, 0.458642, \
0.209918, 0.0254337, 0.340365, 0.280486, 0.0969694, 0.902567, \
0.311759, 0.445944, 0.734187, 0.556372, 0.968549, 0.722562, 0.885184, \
0.642906, 0.264817, 0.541621, 0.793586, 0.259047, 0.0489964, \
0.183852, 0.499949, 0.0692111, 0.714986, 0.793983, 0.525797, \
0.508116, 0.0739616, 0.0726041, 0.542157, 0.143221, 0.980601, \
0.994549, 0.542997, 0.77058, 0.706582, 0.858526, 0.00312537, \
0.0235296, 0.961969, 0.436431, 0.611778, 0.167991, 0.424293, \
0.0989057, 0.256478, 0.732805}
stupidCfromR[foo]
{6.56546*10^-45, -5.01907*10^-42, 1.56046*10^-39, -2.8729*10^-37,
3.64875*10^-35, -3.47096*10^-33, 2.60308*10^-31, -1.59376*10^-29,
8.17047*10^-28, -3.57511*10^-26, 1.35545*10^-24, -4.50701*10^-23,
1.32751*10^-21, -3.49263*10^-20, 8.2664*10^-19, -1.77082*10^-17,
3.4517*10^-16, -6.15044*10^-15, 1.00596*10^-13, -1.5158*10^-12,
2.11112*10^-11, -2.72564*10^-10, 3.27087*10^-9, -3.65718*10^-8,
3.81829*10^-7, -3.72996*10^-6, 0.0000341544, -0.00029365, \
0.00237425, -0.0180782, 0.129804, -0.879936, 5.63813, -34.1814, \
196.26, -1068.19, 5515.59, -27039.4, 125940., -557668.,
2.34902*10^6, -9.41749*10^6, 3.5953*10^7, -1.30763*10^8,
4.53272*10^8, -1.49802*10^9, 4.72179*10^9, -1.41987*10^10,
4.07431*10^10, -1.11587*10^11, 2.91749*10^11, -7.28283*10^11,
1.73593*10^12, -3.9513*10^12, 8.58888*10^12, -1.78288*10^13,
3.53415*10^13, -6.68947*10^13, 1.20892*10^14, -2.08562*10^14,
3.43421*10^14, -5.39605*10^14, 8.08845*10^14, -1.15627*10^15,
1.57581*10^15, -2.04655*10^15, 2.53174*10^15, -2.98174*10^15,
3.34142*10^15, -3.56063*10^15, 3.60542*10^15, -3.46646*10^15,
3.1619*10^15, -2.73363*10^15, 2.23776*10^15, -1.73254*10^15,
1.26708*10^15, -8.74157*10^14, 5.68038*10^14, -3.47091*10^14,
1.9906*10^14, -1.06931*10^14, 5.36788*10^13, -2.5117*10^13,
1.09229*10^13, -4.40038*10^12, 1.63609*10^12, -5.5903*10^11,
1.74674*10^11, -4.96231*10^10, 1.27307*10^10, -2.92548*10^9,
5.96249*10^8, -1.06468*10^8,
1.63982*10^7, -2.13439*10^6, 228286., -19264.2, 1202.6, -49.3738, 1}
Looks reasonable. Next,
cfromr[foo]
{5.9802 + 0.0792079 I, -8.1594 + 0.0953864 I,
10.3109 + 0.107405 I, -11.2502 - 0.144703 I,
11.7326 + 0.0258995 I, -10.0821 + 0.0336182 I,
8.24025 + 0.123999 I, -5.02346 + 0.598038 I, 0.450765 + 0.232466 I,
4.02386 - 0.0386024 I, -10.1325 - 0.354894 I,
15.4001 + 0.0682209 I, -20.8642 + 0.00860923 I,
25.4178 + 0.0414025 I, -29.7352 - 0.0478316 I,
32.0813 + 0.0872942 I, -34.4719 - 0.186356 I,
34.9878 - 0.140137 I, -34.796 - 0.438696 I,
34.1201 - 0.266264 I, -32.825 - 0.34352 I,
31.1676 + 0.0377669 I, -28.6403 - 0.273897 I,
26.9552 - 0.226578 I, -24.5299 - 0.210857 I,
21.7318 - 0.166584 I, -18.3817 - 0.406169 I,
14.7006 - 0.211768 I, -10.6488 + 0.0218902 I,
5.89532 + 0.0502537 I, -2.43193 + 0.145602 I, -2.29822 + 0.0280126 I,
10.1683 + 0.0739904 I, -41.196 + 0.297882 I,
204.612 + 0.22332 I, -1077.32 + 0.356418 I,
5524.19 - 0.0830177 I, -27046.6 - 0.241576 I,
125945. - 0.265022 I, -557670. + 0.314207 I,
2.34902*10^6 + 0.110874 I, -9.41749*10^6 + 0.0519993 I,
3.5953*10^7 - 0.0733092 I, -1.30763*10^8 - 0.0274269 I,
4.53272*10^8 + 0.136665 I, -1.49802*10^9 + 0.139398 I,
4.72179*10^9 - 0.00431823 I, -1.41987*10^10 - 0.0238292 I,
4.07431*10^10 - 0.0859524 I, -1.11587*10^11 + 0.413876 I,
2.91749*10^11 - 0.124791 I, -7.28283*10^11 + 0.0234331 I,
1.73593*10^12 - 0.0233547 I, -3.9513*10^12 + 0.137854 I,
8.58888*10^12 - 0.0113619 I, -1.78288*10^13 + 0.328116 I,
3.53415*10^13 - 0.310418 I, -6.68947*10^13 + 0.0321282 I,
1.20892*10^14 - 0.197183 I, -2.08562*10^14 + 0.314149 I,
3.43421*10^14 - 0.127756 I, -5.39605*10^14 + 0.0133408 I,
8.08845*10^14 + 0.0230662 I, -1.15627*10^15 - 0.272123 I,
1.57581*10^15 - 0.192791 I, -2.04655*10^15 - 0.0992356 I,
2.53174*10^15 + 0.342712 I, -2.98174*10^15 - 0.448979 I,
3.34142*10^15 - 0.382704 I, -3.56063*10^15 - 0.161659 I,
3.60542*10^15 - 0.245491 I, -3.46646*10^15 + 0.181787 I,
3.1619*10^15 + 0.53769 I, -2.73363*10^15 + 0.379394 I,
2.23776*10^15 + 0.0504824 I, -1.73254*10^15 + 0.3809 I,
1.26708*10^15 + 0.062272 I, -8.74157*10^14 + 0.230549 I,
5.68038*10^14 - 0.115016 I, -3.47091*10^14 + 0.317305 I,
1.9906*10^14 - 0.0884983 I, -1.06931*10^14 - 0.00104238 I,
5.36788*10^13 - 0.25693 I, -2.5117*10^13 + 0.218549 I,
1.09229*10^13 + 0.26878 I, -4.40038*10^12 - 0.140603 I,
1.63609*10^12 + 0.0812383 I, -5.5903*10^11 + 0.14043 I,
1.74674*10^11 - 0.402052 I, -4.96231*10^10 + 0.272428 I,
1.27307*10^10 - 0.0000964737 I, -2.92548*10^9 - 0.0669364 I,
5.96249*10^8 - 0.168353 I, -1.06468*10^8 + 0.42484 I,
1.63982*10^7 - 0.511921 I, -2.13439*10^6 - 0.268171 I,
228291. - 0.242538 I, -19266.8 + 0.125755 I,
1203.94 + 0.0223555 I, -48.8476 + 0.0424496 I, -1.905 - 0.0992187 I}
Notice that this is complete nonsense. The numbers are not real, and their magnitude is completely off. Either I am insane, or Mathematica is. Any suggestions?
Expand
in your first approach? $\endgroup$Expand[]
is implicit, but the system clearly does it, because removing theExpand[]
does not speed things up. $\endgroup$