Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




На страницу Пред.  1 ... 3, 4, 5, 6, 7, 8  След.
 Re: Точное количество простых чисел в интервале
Yadryara в сообщении #1730148 писал(а):
И если уже давно такая скорость, то почему например, в проекте SPT использовалась primesieve, а не PrimeCount?
Ровно потому же почему для поиска кортежей в PARI не применяют primepi(): потому что для проверки на миллионы разных паттернов нужен список простых чисел, а не только их количество до некоего порога (даже нескольких порогов).
И нет, primecount не генерит простые числа в полном диапазоне даже внутри себя для вычисления $\pi(x)$ (если не принудить ключом -p), потому использовать её как генератор простых чисел не имеет смысла.
За исключением что она умеет генерить простые (лишь до $2^{63}$) многопоточно, в отличие от primesieve. Зато не умеет генерить с произвольной начальной точки, это пришлось бы добавлять самим.
В итоге взяли тот код, который было проще использовать.

 Re: Точное количество простых чисел в интервале
Yadryara в сообщении #1730148 писал(а):
что при правильном подборе параметров аналитическо-комбинаторный метод обгонит комбинаторные primepi и

Как выяснилось, primepi работает по чекпоинтам.
То есть, есть чекпоинты, это предварительно вычисленные primepi в рамках встроенной таблицы простых. Если интервал превышает последний чекпоинт, то primepi просто идёт решетом Эратосфена до конца интервала. Отсюда и скорость.

 Re: Точное количество простых чисел в интервале
Аватара пользователя
Дошли руки поразбираться с Platt_pi, далее просто Platt. Кстати, точно в точке с простой степепью, особенно первой, считает неправильно. Но это ладно, беру пока кратные 10 или 100.

Перечитал:

Dmitriy40 в сообщении #1688573 писал(а):
Если же говорить о достаточности, то для числа n=155922 погрешность суммы от идеального значения (17.483811746221499642489216337689751178) стала меньше 0.7 лишь с 5536 нуля.
...

Dmitriy40 в сообщении #1688626 писал(а):
Yadryara в сообщении #1688585 писал(а):
А можно ли обойтись лишь 5-ю сотнями нулей?
Я не представляю как: на 500-м нуле погрешность составляет -3.6, на 480-м она была -3.99, на 521-м снова -3.83. ну и как из этого понять что сумма потом уйдёт на 3.6 выше текущей ...
И кстати погрешность пересекала 0 на 446450 нуле, и потом ещё много раз. И вообще говоря не факт что после миллиона нулей она не доберётся до +0.5 ... Например до +0.1 она добралась на 744881 нуле, а около 798794 нуля она добралась и до +0.124.
Формально же погрешность нужна менее 0.5 (по модулю), и то, я бы для надежности взял 0.45...0.4.

Да, нынче 5 сотен нулей для таких чисел хватает с огромным запасом.

Код:
     x   Нулей   Лямбда   Сегментов   |Platt - pi(x)|          Время
155000     465   0.0064   11811          0.0000014          6,436 ms
155100     465   0.0064   11815          0.0000000          5,843 ms
155200     466   0.0064   11819          0.0000002          6,025 ms
155300     466   0.0064   11822          0.0000000          5,932 ms
155400     466   0.0064   11826          0.0000001          5,913 ms
155500     467   0.0064   11830          0.0000005          5,940 ms
155600     467   0.0064   11834          0.0000014          6,002 ms
155700     467   0.0064   11838          0.0000005          5,878 ms
155800     467   0.0064   11841          0.0000006          5,982 ms
155900     468   0.0064   11845          0.0000007          5,974 ms
156000     468   0.0063   11849          0.0000009          6,025 ms

                                         0.0000064

1min, 5,956 ms

 Re: Точное количество простых чисел в интервале
Yadryara в сообщении #1730636 писал(а):
Да, нынче 5 сотен нулей для таких чисел хватает с огромным запасом.

Для них хватает 3 (три) нуля, при другом выборе лямбды. :D
Yadryara в сообщении #1730636 писал(а):
Да, нынче 5 сотен нулей для таких чисел хватает с огромным запасом.

Да, но не забывайте про решето, для этих параметров отрезок в 10000 чисел решетится (по ~5000 с каждой стороны от конца интервала).

 Re: Точное количество простых чисел в интервале
Аватара пользователя
Хотели сказать, одного нуля? :-)

Код:
     x   Нулей    Лямбда   Сегментов      |Platt - pi(x)|          Время
155000       1      0.21       50000          0.000396          2,731 ms
155100       1      0.21       50000          0.000398          2,205 ms
155200       1      0.21       50000          0.000399          2,188 ms
155300       1      0.21       50000          0.000400          2,175 ms
155400       1      0.21       50000          0.000402          2,194 ms
155500       1      0.21       50000          0.000404          2,190 ms
155600       1      0.21       50000          0.000405          2,212 ms
155700       1      0.21       50000          0.000408          2,239 ms
155800       1      0.21       50000          0.000410          2,224 ms
155900       1      0.21       50000          0.000413          2,201 ms
156000       1      0.21       50000          0.000415          2,212 ms

                                              0.004450         24,774 ms

 Re: Точное количество простых чисел в интервале
Аватара пользователя
Стата по одному нулю:

Код:
x=10^    Нулей    Лямбда   Сегментов      |Platt - pi(x)|              Время
    5        1     0.200       90000          0.00002               3,282 ms
    6        1     0.220       90000          0.00231               3,664 ms
    7        1     0.160       90000          0.00121               5,938 ms
    8        1     0.170       90000          0.01749              16,599 ms
    9        1     0.172       90000          0.98502        2min, 37,996 ms

Не хватило для ярда одного нуля. Взял второй:

Код:
x=10^    Нулей    Лямбда   Сегментов      |Platt - pi(x)|                Время
    9        1     0.172       90000          0.98502          2min, 37,996 ms
    9        2     0.107       90000          0.19409          1min, 33,747 ms

 Re: Точное количество простых чисел в интервале
Yadryara
А что у вас в столбце "сегментов"?
Если это nseg из моего набора скриптов, то достаточно будет и 100, я думаю.

-- добавлено через 9 минут --

Yadryara в сообщении #1730737 писал(а):
Стата по одному нулю:

Вот это как раз и показывает что именно делал Платт. Он параметром $\lambda$ искал два компромисса:
1. Оставить за своим подходом название "аналитический"
2. Не очень сильно увеличить вычисление решетом.
В итоге он решил подбирать $\lambda$ так, чтобы время потраченное на нули (чисто аналитическая часть) было не меньше времени на решето. При таком подходе, по его мнению, сложность его метода станет меньше сложности комбинаторных методов начиная с интервала 10^31

 Re: Точное количество простых чисел в интервале
Аватара пользователя
wrest в сообщении #1730743 писал(а):
А что у вас в столбце "сегментов"?
Если это nseg из моего набора скриптов, то достаточно будет и 100, я думаю.

Да, чтобы не было недопонимания, стараюсь не просто название сохранить, но и порядок 4-х аргументов функции Platt_pi не менять.

А вот ваш это набор скриптов или нет, я точно не знаю, вы же так и не ответили. Пока считаю что ваш с Квеном.

Я же не с бухты-барахты стараюсь взять nseg побольше. Если взять маленький, он довольно сильно гуляет и мешает понять закономерности.

Да даже при 200 тысячах заметное гуляние есть:

Код:
10000000       1      0.16       200000          0.00122         10,124 ms
10001000       1      0.16       200000          0.00136          9,394 ms
10002000       1      0.16       200000          0.00150          9,356 ms
10003000       1      0.16       200000          0.00164          9,367 ms
10004000       1      0.16       200000          0.00177          9,364 ms
10005000       1      0.16       200000          0.00191          9,374 ms
10006000       1      0.16       200000          0.00205          9,369 ms
10007000       1      0.16       200000          0.00219          9,379 ms
10008000       1      0.16       200000          0.00233          9,388 ms
10009000       1      0.16       200000          0.00247          9,360 ms
10010000       1      0.16       200000          0.00261          9,447 ms

                                                 0.02105   1min, 43,929 ms


wrest в сообщении #1730743 писал(а):
Вот это как раз и показывает что именно делал Платт.

Да, это интересно. Я пока далеко не всё понимаю.

А что думаете насчёт вот этой константы:

Yadryara в сообщении #1691738 писал(а):
Я вот тут уже несколько дней пытаюсь посчитать константу для среднего значения модуля суммы по дзета-нулям. Вроде как она сходится примерно к
$$0.1725\frac{\sqrt{x}}{\ln{x}}$$

Может и 0.1726.

 Re: Точное количество простых чисел в интервале
Yadryara в сообщении #1730749 писал(а):
Да даже при 200 тысячах заметное гуляние есть:

При этих параметрах интервала и лямбды ($x=10^9;\lambda =0,16$) программа перебирает простые числа на отрезке в два раза бОльшем, чем величина интервала. Это не имеет никакого практического смысла.
Касательно "гуляния", увеличение количество сегментов для Тейлора не увеличивает точность вычисления конечного результата.

Такое впечатление, что вы тыкаете в программу палочкой вместо того, чтобы сопоставить её со статьёй Платта и в статье почитать что и для чего делается и как оцениваются ошибки :)
Вы же хотели разобраться в статье :wink:

 Re: Точное количество простых чисел в интервале
Аватара пользователя
wrest в сообщении #1730757 писал(а):
Касательно "гуляния", увеличение количество сегментов для Тейлора не увеличивает точность вычисления конечного результата.

Возможно. Я уже давно заметил, что при увеличении nseg, начиная с какого-то порога, отклонения стабилизируются.

wrest в сообщении #1730757 писал(а):
Такое впечатление, что вы тыкаете в программу палочкой вместо того, чтобы сопоставить её со статьёй Платта и в статье почитать что и для чего делается и как оцениваются ошибки :)

Правильное впечатление. Пока именно что играюсь — смотрю какие параметры на что влияют.

wrest в сообщении #1730757 писал(а):
Вы же хотели разобраться в статье :wink:

Да, но пока ленюсь. Вроде никто не торопит.

 Re: Точное количество простых чисел в интервале
Интересное кино показывают в pari/gp
Допиливаю метод Платта, и вот наткнулся на то, что forprime начинает резко (в 20 раз!) тормозить при переходе через примерно 2^40
Код:
1.00 e8:      8 мс, 54208 простых, 0.15 мкс/простое
3.16 e8:     22 мс, 51136 простых, 0.43 мкс/простое
1.00 e9:     20 мс, 48155 простых, 0.42 мкс/простое
3.16 e9:     20 мс, 45701 простых, 0.44 мкс/простое
1.00 e10:     19 мс, 43427 простых, 0.44 мкс/простое
3.16 e10:     17 мс, 41169 простых, 0.41 мкс/простое
1.00 e11:     17 мс, 39434 простых, 0.43 мкс/простое
3.16 e11:     16 мс, 37669 простых, 0.42 мкс/простое
1.00 e12:     13 мс, 36249 простых, 0.36 мкс/простое
3.16 e12:    240 мс, 34565 простых, 6.94 мкс/простое
1.00 e13:    248 мс, 33456 простых, 7.41 мкс/простое
3.16 e13:    248 мс, 32111 простых, 7.72 мкс/простое
1.00 e14:    255 мс, 30892 простых, 8.25 мкс/простое
3.16 e14:    265 мс, 29921 простых, 8.86 мкс/простое
1.00 e15:    268 мс, 28845 простых, 9.29 мкс/простое
3.16 e15:    273 мс, 27828 простых, 9.81 мкс/простое
time = 1,967 ms.
?

Загадка.
А... ну не загадка. Таблица простых до 2^20, соответственно решетить легко до 2^40

 Re: Точное количество простых чисел в интервале
wrest в сообщении #1730804 писал(а):
А... ну не загадка. Таблица простых до 2^20, соответственно решетить легко до 2^40
Именно.

 Re: Точное количество простых чисел в интервале
Новая версия (platt_v5.gp) набора скриптов подсчёта $\pi(x)$ методом Платта
Немного ускоренная, немного дополненная по математике вычислений.
Главное обновление: добавлена функция platt_opt(x) которая измеряет скорость вычислений на конкретном компе и исходя из результатов рекомендует параметры для запуска главной функции platt_pi() исходя из минимизации времени вычислений путём поиска таких параметров что время на решето и на интегрирование одинаковое и погрешность не превысит 0.5. При расчёте учитывается размер применимости встроенной таблицы простых и замедление forprime за его границами.
В главной функции добавлено два параметра - широта решета c и отключение печати статистики (толькотвозврао результата). Количество сегментов для разложения интеграла вдоль нетривиальных нулей в ряд Тейлора оставлено, но лучше его не менять. Почти не влияет на результаттначиная со 100 сегментов.

(Оффтоп)

Код:
\\ ============================================================
\\  platt.gp — аналитическое pi(x) методом Платта
\\  (явная формула Римана + гауссово сглаживание + обращение Мёбиуса)
\\
\\  Нули берутся из таблицы Одлыжко (zeros1 = 10^5 нулей,
\\  zeros6 = 10^6 нулей). Нулевая часть — рядами (лемма 6.1),
\\  решётная поправка — сегментами с разложением Тейлора (§5).
\\
\\  БЫСТРЫЙ СТАРТ
\\  ---------------
\\    \r platt_v5.gp
\\    \p 50
\\    platt_pi(10^8, 100, 0.04, 100,5,0)   \\ -> 5761455.00...
\\    primepi(10^8)                     \\ сверка: 5761455
\\
\\  ИНТЕРФЕЙС
\\  ---------
\\    platt_pi(x, nzeros, lam, nseg,prime_sieve,verbose)
\\      x      — аргумент pi(x);
\\      nzeros — сколько нулей дзета использовать;
\\      lam    — параметр сглаживания;
\\      nseg   — число сегментов Тейлора в решётной поправке, рекомендуется 100.
\\      prime_sieve — ширина решета в конце интервала для поправки, от 4 до 7
\\      verbose — 1 печатать статистику, 0 просто вернуть результат
\\
\\  ПАРАМЕТРЫ (проверенные ориентиры)
\\  ---------------------------------
\\    x ~ 10^6 : nzeros=12,    lam=0.10,  nseg=100
\\    x ~ 10^8 : nzeros=100,   lam=0.04,  nseg=100
\\    x ~ 10^10: nzeros=8000,  lam=0.001, nseg=100
\\    Правило: нулей нужно до высоты ~6/lam; lam балансирует
\\    длину интеграла главного члена (~1/lam) и ширину решета (~lam).
\\    Функция platt_opt(x) проводит измерение производительности
\\      и ра его основе выдаёт оптимальные по времен вычислений параметры
\\
\\  Точность: погрешность << 0.5, округление platt_pi даёт точное целое.
\\ ============================================================

\\ ================= НУЛИ ДЗЕТА-ФУНКЦИИ =================
\\ должны быть в файле zeros1 (0^5 шт.) и zeros6 (2*10^6 шт.)
\\ напримеринули из таблиц Одлыжко
\\ отсюда: https://www-users.cse.umn.edu/~odlyzko/zeta_tables/index.html
load_zeros(n) = {
  my(filename=if(n>10^5,"zeros6", "zeros1"));
  my(fd, vals, val, i);
    fd = fileopen(filename, "r");
    vals = vector(n);
    for(i = 1, n,
        val = eval(fileread(fd));
        if(val == 0, fileclose(fd);error("Не хватает нулей в файле ", filename," Надо: ",n," Есть:",i));
        vals[i] = val;
    );
    fileclose(fd);
    return(vals);
}

\\ ============ СГЛАЖЕННАЯ НУЛЕВАЯ ЧАСТЬ (Phihat) ============

phihat(s, x, lam) = (x^s/s)*exp(lam^2*s^2/2);

\\ int_0^Del phihat(s0+I*h) dh рядом Тейлора (лемма 6.1)

step_incr(s0, Del, x, lam, K) = {
  my(A = log(x) + s0*lam^2, ph0 = phihat(s0,x,lam));
  my(eD = exp(I*Del*A), invIA = 1/(I*A), Ik = vector(K+1), c, s=0, n, m, k);

  \\ Предвычисление степеней один раз на вызов
  my(pow_s0 = vector(K+1), pow_lam = vector(K\2+1));
  my(inv_s0 = -I/s0, half_lam2 = -lam^2/2);
  pow_s0[1] = 1;
  for(n=1, K, pow_s0[n+1] = pow_s0[n]*inv_s0);
  pow_lam[1] = 1;
  for(m=1, K\2, pow_lam[m+1] = pow_lam[m]*half_lam2/m);

  Ik[1] = (eD - 1)*invIA;
  for(k=1, K, Ik[k+1] = Del^k*eD*invIA - k*invIA*Ik[k]);

  for(k=0, K,
    c = 0;
    for(m=0, k\2,
      n = k - 2*m;
      c += pow_s0[n+1] * pow_lam[m+1];
    );
    s += c*Ik[k+1];
  );
  ph0*s
}

\\ Re Phihat для всех нулей; адаптивный шаг Del = ratio*|1/2+I*t|

Phihat_re_all(x, lam, zeros, K) = {
  my(n=#zeros, GatZ=vector(n), G=0, t=zeros[1], j);
  GatZ[1] = 0;
  for(j=2, n,
    G += step_incr(1/2 + I*t, zeros[j] - t, x, lam, K);
    t = zeros[j];
    GatZ[j] = G;
  );
  vector(n, j, imag(G - GatZ[j]))
}

\\ Re Phihat(1): главный член, адаптивный шаг Del = ratio*|1+I*t|
Phihat_re_at_1(x, lam, ratio, K) = {
  my(T = 8/lam, t=0, tnext, G=0, Del);
  while(t < T,
    Del = ratio*sqrt(1+t^2);
    tnext = min(t + Del, T);
    G += step_incr(1 + I*t, tnext - t, x, lam, K);
    t = tnext;
  );
  imag(G)
}

\\ ============ РЕШЁТНАЯ ПОПРАВКА (§5 Платта) ============

\\ sum_{p^m} (chi-phi)/m; сегменты + Тейлор для phi (erfc один раз в сегмент)
\\ Ширина окна = 2*c*lam*x, c=5 рекомендуется (проверено: c=5,8,10 дают одно и то же)

sieve_corr_taylor(x, lam, nseg, c=5) = {
  my(lo=x*exp(-c*lam), hi=x*exp(c*lam));
  my(sq2lam=sqrt(2)*lam, sqrtpi=sqrt(Pi), invx=1/x);
  my(w=(hi-lo)/nseg);
  my(B=vector(nseg+1, j, round(lo + (j-1)*(hi-lo)/nseg)));
  my(s=0, j, a, b, x0, N, S1, S2, C, d, g, eg, ph0, ph1, ph2, ph3, p);

  \\ Индекс сегмента, содержащего границу x
  my(jx=1);
  while(jx<nseg && B[jx+1]<=x, jx++);

  for(j=1, nseg,
    a=B[j]; b=B[j+1]-1;
    if(b >= a,
      x0=(a+b)/2; N=0; S1=0; S2=0; C=0;
      if(j < jx,
        \\ сегмент целиком ниже x: все простые < x
        forprime(p=a, b, d=x0-p; S1+=d; S2+=d*d; N++);
        C=N;
      , if(j > jx,
          \\ сегмент целиком выше x: ни один простой не < x
          forprime(p=a, b, d=x0-p; S1+=d; S2+=d*d; N++);
          C=0;
        , \\ сегмент содержит x: единственный случай с if
          forprime(p=a, b, if(p<x, C++); d=x0-p; S1+=d; S2+=d*d; N++);
        )
      );
      g=log(x0*invx)/sq2lam; eg=exp(-g*g);
      ph0=0.5*erfc(g);
      ph1=-eg/(sqrtpi*sq2lam*x0);
      ph2=eg/(sqrtpi*sq2lam*x0*x0)*(2*g/sq2lam+1);
      \\ учёт кубическог члена (третьей производной)
      \\ как у Платта
      ph3=eg/(sqrtpi*sq2lam*x0^3)*(2/sq2lam^2 - 2 - (2*g/sq2lam)^2 - 3*(2*g/sq2lam));
      ph1 += ph3*w^2/8;
      s += C - (ph0*N - ph1*S1 + ph2*S2/2);
    );
  );

  my(m=2, q);
  while(2^m<=hi,
    forprime(p=ceil(lo^(1/m)), floor(hi^(1/m)),
      q=p^m;
      if(q>=lo&&q<=hi, s+=((q<x)-0.5*erfc(log(q*invx)/sq2lam))/m);
    );
    m++;
  );
  s
}

\\ ============ ОБРАЩЕНИЕ МЁБИУСА ============

\\ точное f(y)=sum (1/n) pi(y^{1/n}) встроенным primepi
ftarget(y) = sum(n=1, floor(log(y)/log(2)), primepi(sqrtn(y,n))/n);

\\ ============ СБОРКА ============

platt_pi(x, nzeros, lam, nseg=100, c=5, verbose=1) = {
  if(verbose,
    \\ оценка и печать ошибки при выбранных параметрах
    platt_error_estimates(x, nzeros, 4*10^(-9), lam, nseg, c);
  );
  \\ вычисление сглаженной f(x)
  my(s,res,t0);
  if(verbose,
    t0=getwalltime();
    print1("Получаем ", nzeros, " нулей ...");
    );
  \\ загружаем нули
  my(zeros = load_zeros(nzeros));
  if(verbose,
    print(" готово за ", getwalltime()-t0, " мс");
    t0=getwalltime();
    print1("Вычисляем главный член ...        ");
    );
  \\ главный член, вклад полюса при s=1
  my(re1 = Phihat_re_at_1(x, lam, 0.5, 40));
  if(verbose,
    print(strprintf("%.3f",re1), " готово за ", getwalltime()-t0, " мс");
    t0=getwalltime();
    print1("Вычисляем остаток ряда phihat ... ");
  );
  \\ вклад нулей дзета функции
  my(rez = Phihat_re_all(x, lam, zeros, 12));
  my(zsum = sum(j=1, #rez, rez[j]));
  if(verbose,
    print(strprintf("%.3f", -2*zsum),"  (готово за ", getwalltime()-t0, " мс)");
    t0=getwalltime();
    print1("Вычисляем поправку решетом ...    ");
  );
  \\ вклад простых на конце интервала
  res=sieve_corr_taylor(x, lam, nseg, c);
  if(verbose,
    print(strprintf("%.3f",res),"   (старт: ",strprintf("%.4g",x*exp(-c*lam))," длина: ",strprintf("%.4g",x*(exp(c*lam)-exp(-c*lam)))," ) (готово за ", getwalltime()-t0, " мс)");
  );
  \\ общий итог f(x)
  res=re1 - 2*zsum - log(2) + res;
  if(verbose,
    print("Сумма ...                         ",strprintf("%.3f",res));
    t0=getwalltime();
  );
  \\ pi(x) = f(x) + поправки Мёбиуса при n>=2
  s=0;
  if(verbose,
    print1("Поправки Мёбиуса ...              ");
  );
  for(n=2, floor(log(x)/log(2)),
    if(moebius(n)!=0, s += (moebius(n)/n)*ftarget(sqrtn(x,n)));
  );
  if(verbose,
    print(strprintf("%.3f",s)," (готово за ", getwalltime()-t0, " мс)");
  );
  return(res+s);
}

platt_error_estimates(x, nzeros, zero_acc, lam, nseg, c) = {
\\ Оценка составляющих погрешности и суммарной
  my(zeros = load_zeros(nzeros));
  my( T1=zeros[nzeros], T=8/lam);
  my(E1, E2, E3, E4, E5, E6, Etotal);
  \\ эмпирический коэффициент сокращения осцилляций
  my(kE1 = 1/5);


  \\ 1. Хвост нулей (Лемма A.4, консервативная оценка)
  \\ Оценка, может быть с ошибкой
  \\ E1 = kE1*2*exp(lam^2*(1-T1^2)/2) * (sqrt(x)/(T1*log(x)) + 1/(lam^2*T1^2*x)) * (lam^2*T1^2+1);
  \\ 1. Хвост нулей (численное интегрирование, всегда корректно)
  E1 = kE1*2*intnum(t=T1, T, sqrt(x)/t * exp(-lam^2*t^2/2) * log(t)/(2*Pi));
  \\ В print_error_estimates, после вычисления E1:

  \\ 2. Хвост главного члена (Лемма A.2)
  E2 = exp(lam^2*(1-T^2)/2) * (x/(T*log(x)) + 1/(lam^2*T^2*x));

  \\ 3. Интеграл вокруг -1 I_{-1} (Лемма 4.5)
  E3 = exp(lam^2/2)/(2*Pi*x*lam) * (5/sqrt(2*Pi) + 2/lam);

  \\ 4. Хвост решета (вне окна [x*e^{-c*lam}, x*e^{c*lam}])
  E4 = x*lam*sqrt(2)/log(x) * exp(-c^2/2)/(sqrt(Pi)*c^2);

  \\ 5. Проверка нулей по формуле N(T)
  my(N_exp = T1/(2*Pi)*log(T1/(2*Pi)) - T1/(2*Pi) + 7/8);
  my(bound = 0.137*log(T1) + 0.443*log(log(T1)) + 1.588);
  my(diff = abs(N_exp - nzeros));
  E5 = if(diff > bound, diff, 0);

  \\ 6. Ошибка от неточности нулей
  E6 = zero_acc * sum(j=1, nzeros,
    my(g=zeros[j]);
    sqrt(x)/sqrt(1/4+g^2)*exp(lam^2*(1/4-g^2)/2)
  );

  Etotal = E1 + E2 + E3 + E4 + E5 + E6;
 
  print("Составляющие погрешности (хвост нулей может быть больше!):");
  printf("  1. Хвост нулей (оптимистично):  %.3g\n", E1);
  printf("  2. Хвост главн. члена:          %.3g\n", E2);
  printf("  3. I_{-1}:                      %.3g\n", E3);
   print("  4. Размер решета:               ",strprintf("%.4g",x*(exp(c*lam)-exp(-c*lam))));
  printf("  5. Хвост решета:                %.3g\n", E4);
  print("  6. Пропущенные нули:            ", E5);
  printf("  7. Неточность нулей:            %.3g\n", E6);
  printf("  Суммарная:                      %.3g\n", Etotal);
  if(Etotal < 0.5,
    print("  OK: оптимистично погрешность  < 0.5, можно вычислять"),
    print("  ВНИМАНИЕ: погрешность         > 0.5, вероятна ошибка")
  );
}

\\ ===== Измерение стоимостей с использованием реальных функций =====
measure_costs(x, nseg) = {
  my(primelimit = default(primelimit));
  my(threshold = primelimit^2);
  my(width = 10^6);
  my(cost_fast, cost_mid, cost_slow, seg_factor);
  my(cost_zero, cost_load);
  my(t, cnt, a, b, d, S1, S2, x0);
  my(n_test = 2000, test_lam = 1e-4, zeros, sum_test, t0);

  \\ Ограничение на число нулей (zeros6 содержит 10^6)
  n_test = min(n_test, 10^6);

  \\ === Стоимость простых: быстрый режим (до порога таблицы) ===
  x0 = primelimit; a = x0 - width\2; b = x0 + width\2;
  t = gettime(); cnt = 0; S1 = 0; S2 = 0;
  forprime(p=a, b, d=x0-p; S1+=d; S2+=d*d; cnt++);
  t = gettime() - t;
  cost_fast = if(cnt>0 && t>=0, t/cnt*1e-3, 1.3e-6);

  \\ === Стоимость простых: средний режим (за порогом таблицы, до 2^63) ===
  if(threshold * 10 < 2^63,
    x0 = threshold * 10; a = x0 - width\2; b = x0 + width\2;
    t = gettime(); cnt = 0; S1 = 0; S2 = 0;
    forprime(p=a, b, d=x0-p; S1+=d; S2+=d*d; cnt++);
    t = gettime() - t;
    cost_mid = if(cnt>0 && t>=0, t/cnt*1e-3, cost_fast*10);
  ,
    cost_mid = cost_fast * 10;
  );

  \\ === Стоимость простых: медленный режим (за порогом 2^63) ===
  if(2^63 * 2 < 1e30,
    x0 = 2^63 * 2; a = x0 - width\2; b = x0 + width\2;
    t = gettime(); cnt = 0; S1 = 0; S2 = 0;
    forprime(p=a, b, d=x0-p; S1+=d; S2+=d*d; cnt++);
    t = gettime() - t;
    cost_slow = if(cnt>0 && t>=0, t/cnt*1e-3, cost_mid*5);
  ,
    cost_slow = cost_mid * 5;
  );

  \\ Поправка на сегментацию
  seg_factor = 1 + nseg/1000;
  cost_fast *= seg_factor;
  cost_mid *= seg_factor;
  cost_slow *= seg_factor;

  \\ === Стоимость нулей: используем реальные функции ===
  \\ Загрузка нулей
  t0 = gettime();
  zeros = load_zeros(n_test);
  cost_load = (gettime()-t0)/n_test*1e-3;

  \\ Вычисление phihat реальной функцией
  t0 = gettime();
  sum_test = Phihat_re_all(x, test_lam, zeros, 12);
  cost_zero = (gettime()-t0)/n_test*1e-3;

  printf("Измеренные стоимости:\n");
  printf("  primelimit = %d, порог таблицы = %.3g, порог 64 бит = %.3g\n",
    primelimit, threshold, 2^63);
  printf("  Простые (быстрый, < %.3g):   %.2f мкс\n", threshold, cost_fast*1e6);
  printf("  Простые (средний, < 2^63):   %.2f мкс\n", cost_mid*1e6);
  printf("  Простые (медленный, > 2^63): %.2f мкс\n", cost_slow*1e6);
  printf("  Загрузка нуля:               %.2f мкс\n", cost_load*1e6);
  printf("  Вычисление нуля (phihat):    %.2f мкс\n", cost_zero*1e6);

  return([threshold, cost_fast, cost_mid, cost_slow, cost_zero, cost_load]);
}

\\ ===== Подбор оптимальных параметров для метода Платта =====
platt_opt(x) = {
  my(target=0.2, kE1=1/5);
  my(lam, T1, nzeros, c, T);
  my(E1, E2, E3, E4, Etotal);
  my(n_primes, time_total, i, best_time, best_lam, best_nzeros, best_c, best_T1);
  my(lam_min, lam_max, lam_step, T1_new, E1_new, c_new, E4_new);
  my(cost_prime, upper);

  my(costs = measure_costs(x, 500));
  my(threshold=costs[1], cost_fast=costs[2], cost_mid=costs[3], cost_slow=costs[4]);
  my(cost_zero=costs[5], cost_load=costs[6]);

  \\ Начальное приближение lam из баланса времени
  cost_prime = cost_fast;
  lam = 1e-4;
  for(i=1, 10,
    lam = sqrt(3*cost_zero*log(x)/(2*Pi*cost_prime*5*x) * log(6/(2*Pi*lam*exp(1))));
  );
  lam_min = lam/3;
  lam_max = lam*3;
  lam_step = (lam_max - lam_min)/20;

  best_time = 1e30;
  best_lam = 0; best_nzeros = 0; best_c = 0; best_T1 = 0;

  for(k=0, 20,
    lam = lam_min + k*lam_step;
    T = 8/lam;

    \\ Подбор T1 (высота нулей)
    T1 = 6/lam;
    E1 = kE1*2*intnum(t=T1, T, sqrt(x)/t * exp(-lam^2*t^2/2) * log(t)/(2*Pi));
    while(E1 > target && T1 < T,
      T1 = min(T1*1.15, T);
      E1 = kE1*2*intnum(t=T1, T, sqrt(x)/t * exp(-lam^2*t^2/2) * log(t)/(2*Pi));
    );
    while(E1 < target/3 && T1 > 2/lam,
      T1_new = T1/1.05;
      E1_new = kE1*2*intnum(t=T1_new, T, sqrt(x)/t * exp(-lam^2*t^2/2) * log(t)/(2*Pi));
      if(E1_new < target, T1 = T1_new; E1 = E1_new, break);
    );
    nzeros = round(T1/(2*Pi)*log(T1/(2*Pi*exp(1))) + 7/8);

    \\ Подбор c (ширина окна)
    c = 5;
    E4 = x*lam*sqrt(2)/log(x) * exp(-c^2/2)/(sqrt(Pi)*c^2);
    while(E4 > target,
      c += 0.5;
      E4 = x*lam*sqrt(2)/log(x) * exp(-c^2/2)/(sqrt(Pi)*c^2);
    );
    while(E4 < target/3 && c > 3,
      c_new = c - 0.5;
      E4_new = x*lam*sqrt(2)/log(x) * exp(-c_new^2/2)/(sqrt(Pi)*c_new^2);
      if(E4_new < target, c = c_new; E4 = E4_new, break);
    );

    \\ Остальные погрешности
    E2 = exp(lam^2*(1-T^2)/2) * (x/(T*log(x)) + 1/(lam^2*T^2*x));
    E3 = exp(lam^2/2)/(2*Pi*x*lam) * (5/sqrt(2*Pi) + 2/lam);
    Etotal = E1 + E2 + E3 + E4;

    \\ Стоимость простого в зависимости от режима
    upper = x*exp(c*lam);
    if(upper <= threshold,
      cost_prime = cost_fast;
    ,
      if(upper <= 2^63,
        cost_prime = cost_mid;
      ,
        cost_prime = cost_slow;
      )
    );

    \\ Время
    n_primes = 2*c*lam*x/log(x);
    time_total = (cost_load + cost_zero)*nzeros + cost_prime*n_primes + 0.02;

    \\ Обновление минимума
    if(Etotal < 0.5 && time_total < best_time,
      best_time = time_total;
      best_lam = lam;
      best_nzeros = nzeros;
      best_c = c;
      best_T1 = T1;
    );
  );

  if(best_time >= 1e30,
    print("ВНИМАНИЕ: не найдены параметры с погрешностью < 0.5");
    return([0, 0, 0, 0, 0]);
  );

  \\ Пересчёт с оптимальными параметрами для вывода
  lam = best_lam; nzeros = best_nzeros; c = best_c; T1 = best_T1;
  T = 8/lam;
  E1 = kE1*2*intnum(t=T1, T, sqrt(x)/t * exp(-lam^2*t^2/2) * log(t)/(2*Pi));
  E2 = exp(lam^2*(1-T^2)/2) * (x/(T*log(x)) + 1/(lam^2*T^2*x));
  E3 = exp(lam^2/2)/(2*Pi*x*lam) * (5/sqrt(2*Pi) + 2/lam);
  E4 = x*lam*sqrt(2)/log(x) * exp(-c^2/2)/(sqrt(Pi)*c^2);
  Etotal = E1 + E2 + E3 + E4;
  upper = x*exp(c*lam);
  if(upper <= threshold,
    cost_prime = cost_fast;
  ,
    if(upper <= 2^63,
      cost_prime = cost_mid;
    ,
      cost_prime = cost_slow;
    )
  );
  n_primes = 2*c*lam*x/log(x);
  time_total = (cost_load + cost_zero)*nzeros + cost_prime*n_primes + 0.02;

  printf("\nОптимальные параметры для x=%.3g (по времени счёта):\n", x);
  printf("  lam =    %.4g\n", lam);
  printf("  nzeros = %d\n", nzeros);
  printf("  c =      %.1f\n", c);
  printf("\nОценка погрешности:\n");
  printf("  Хвост нулей:        %.3g\n", E1);
  printf("  Хвост главн. члена: %.3g\n", E2);
  printf("  I_{-1}:             %.3g\n", E3);
  printf("  Хвост решета:       %.3g\n", E4);
  printf("  Суммарная:          %.3g\n", Etotal);
  if(Etotal < 0.5,
    print("  OK: погрешность < 0.5"),
    print("  ВНИМАНИЕ: погрешность >= 0.5")
  );
  printf("\nПрогноз времени:\n");
  printf("  Загрузка нулей:   %.1f с\n", cost_load*nzeros);
  printf("  Ряд phihat:       %.1f с\n", cost_zero*nzeros);
  printf("  Решето:           %.1f с\n", cost_prime*n_primes);
  printf("  Сумма:            %.1f с\n", time_total);

  print("Вызов: ");
  print("platt_pi(",x,",",nzeros,",",strprintf("%.4g",lam),",",500,",",strprintf("%.1f",c),")");
  print();

  \\ return([lam, nzeros, c, Etotal, time_total]);
}


Кажется, что уже весь Платт теперь как на ладони.

Так что, Yadryara , буду с нетерпением ждать применения Платта к кортежам :D

 Re: Точное количество простых чисел в интервале
Аватара пользователя
wrest в сообщении #1730757 писал(а):
При этих параметрах интервала и лямбды ($x=10^9;\lambda =0,16$) программа перебирает простые числа на отрезке в два раза бОльшем, чем величина интервала. Это не имеет никакого практического смысла.

Потихоньку разбираюсь. Да, это я учудил :-) Полоса проверки получается слишком широкая. Лямбда ведь умножается примерно на 10. Так что должна быть меньше 0.1.

wrest в сообщении #1730826 писал(а):
Так что, Yadryara , буду с нетерпением ждать применения Платта к кортежам :D

А может вы видите издевательство там где его нет, потому что склонны к подколкам?

Чего же ждать с нетерпением, попробуйте сами применить. Или хотя бы константу 0.1725 — 0.1726 попробуйте посчитать.

Я-то обленился жутко, причём именно в последний год. Сплю много. Может умру скоро. Знаем кто подкрадывается незаметно.

Что-то у меня скомпилированная версия долго считает тот самый триллион:

Код:
x=10^    Нулей      Лямбда   Сегментов      |Platt - pi(x)|                Время

   12    45000     0.00009         200          0.28642          3min, 38,045 ms
   12    60000     0.00009         200          0.09153          3min, 42,238 ms
   12    45000     0.00008         100          0.31946          4min,  1,523 ms
   12    60000     0.00009       90000          0.00522          4min, 44,583 ms
   12   100000     0.00008       90000          0.00421          5min,  4,219 ms

 Re: Точное количество простых чисел в интервале
Yadryara в сообщении #1730858 писал(а):
Что-то у меня скомпилированная версия

Пятая? Которая двумя постами выше?
Yadryara в сообщении #1730858 писал(а):
долго считает тот самый триллион:

Надо параллелить, оно хорошо параллелится. Но мне на планшет без толку, а вам для компа норм будет. Посмотрю потом.
Ну и параметры ставьте какие platt_opt посоветует.

Там, кстати, похоже надо немного точность подтянуть для больших интервалов. До 300 000 нулей 12 ещё норм, а после 500 000 может не хватать членов в разложении в ряд Тейлора при вычислении интеграла вдоль нулей и надо поставить 16.

Вот такую строчку в функции platt_pi
my(rez = Phihat_re_all(x, lam, zeros, 12));
заменить на такую:
my(rez = Phihat_re_all(x, lam, zeros, 16));

И соответственно в функции measure_costs
sum_test = Phihat_re_all(x, test_lam, zeros, 12);
на
sum_test = Phihat_re_all(x, test_lam, zeros, 16);

Yadryara в сообщении #1730858 писал(а):
Или хотя бы константу 0.1725 — 0.1726 попробуйте посчитать.

Я не понял о чём этот вопрос и проигнорировал его.

-- добавлено через 1 минуту --

Yadryara в сообщении #1730858 писал(а):
Чего же ждать с нетерпением, попробуйте сами применить.

У меня ноль идей на этот счёт, и я совершенно не понимаю как вы собирались это делать.

 [ Сообщений: 117 ]  На страницу Пред.  1 ... 3, 4, 5, 6, 7, 8  След.


Соглашение о конфиденциальности | Общие правила

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group