Actualización 1: Ahora he utilizado la biblioteca de multiprocesamiento para la paralelización del cálculo, y he actualizado en consecuencia el código de Python.
Actualización 2: Tenemos \nu(7)\le 45 y \nu(8)\le 52, ya que los polinomios \begin{equation} x^{45} + x^{44} + x^{42} + x^{37} + x^{35} + x^{33} + x^{31} + x^{30} + x^{28} + x^{26} + x^{24} + x^{23} + x^{22} + x^{20} + x^{18} + x^{16} + x^{15} + x^{13} + x^{11} + x^{9} + x^{4} + x^{2} + x \end{equation} y \begin{equation} x^{52} + x^{51} + x^{49} + x^{46} + x^{40} + x^{38} + x^{37} + x^{36} + x^{35} + x^{33} + x^{31} + x^{29} + x^{27} + x^{26} + x^{24} + x^{22} + x^{20} + x^{18} + x^{17} + x^{16} + x^{15} + x^{13} + x^{7} + x^{4} + x^{2} + x \end{equation} tienen 7 y 8 raíces reales, respectivamente.
Estos polinomios son los más pequeños lexicográficamente de la forma xh(x), donde h es igual a su recíproco.
A continuación se muestra el código Python que para cada entero suficientemente pequeño n calcula el número máximo de raíces reales distintas de polinomios de grado n con coeficientes 0 y 1 (que es [OEIS A362344][1]) junto con un ejemplo de menor orden lexicográfico. Por ejemplo, vemos en pocos minutos que \nu(6)=28. (Inicialmente, había escrito un script de SageMath usando el Teorema de Sturm, sin embargo la función polsturm de pari/gp es algo más rápida.)
El script de Python hace uso de la paralelización. La línea cpus = 17
indica que se utilizarán 17 núcleos y, por supuesto, se puede ajustar.
El script identifica la expansión binaria p=\sum a_i2^i con el polinomio \sum a_ix^i.
En caso de que alguien quiera buscar un patrón, aquí hay una lista de todos los polinomios 0-1 de grado 28 con 6 raíces reales distintas. Para ahorrar espacio, proporcionamos la lista como los números p (ver arriba): 437545878, 437594646, 437594838, 437619606, 437643798, 440494998, 440875158, 443812758, 443836950, 443837334, 443910678, 443911062, 443916438, 443923062, 443923350, 444033942, 450177558, 462908310. (En SageMath, si K
es un anillo de polinomios, y p
es uno de estos números, K(p.bits())
da como resultado el polinomio correspondiente).
Y aquí está el código Python (que requiere la biblioteca cypari2):
import cypari2
from multiprocessing import Pool
pari = cypari2.Pari()
cpus = 17 ################
def check(i):
best, bestp, bestf = 0, 0, ''
for p in range(2**n + i, 2**(n+1), cpus):
l = []
for j, b in enumerate(bin(p)[-1:1:-1]):
if b == '1':
l.append(f'x^{j}')
s = '+'.join(l)
m = pari(s).polsturm()
if m > best:
best, bestp, bestf = m, p, s
return best, bestp, bestf
n = 1
while True:
n += 1
with Pool(cpus) as P:
res = P.map(check, range(cpus))
best, bestp = 0, 2**(n+1)
for m, p, s in res:
if m > best or (m == best and p < bestp):
best, bestp, bestf = m, p, s
print(f'deg = {n}, m = {best}, p = {bestp}, bestf = {bestf}')