Erdős problem #955 — live audit, an exact fibre-tightness reduction, and a finite sharp table
Access date: 2026-07-28 UTC. The requested labels are used throughout:
- (a) elementary-rigorous — a proof is given here.
- (b) rigorous-modulo-named-theorem — the cited primary source was checked,
but its theorem is not reproved here.
- (c) plausible/structural-unverified — heuristic or inference, not used as
a theorem.
- (d) computational-only — exact finite computation or browser metadata,
with no asymptotic inference.
0. Mandatory live-page gate
I fetched the rendered live page, its
/latex/955 view, and its
discussion through the
Bright Data browser route. Direct datacenter curl was not used for the
gate. (d)
The page is OPEN, was last edited 30 September 2025, and shows **2
comments, 0 claimed proofs**, “Interested in collaborating: None”, and
“Currently working on this problem: None”. Thus neither mandatory stop
condition fired. (d)
Verbatim live statement
> Let\[s(n)=\sigma(n)-n=\sum_{\substack{d\mid n\\ d > > If $A\subset \mathbb{N}$ has density $0$ then $s^{-1}(A)$ must also have density $0$. This report takes “density” to mean asymptotic (natural) density, as do the page's cited sources. (b) The page attributes the conjecture to Erdős, Granville, Pomerance, and Spiro [EGPS90]. It notes that the forward image can behave oppositely: the zero-density set of products of two distinct primes has an \(s\)-image of positive density. It also records Erdős's construction of positive-density sets \(A\) for which \(s^{-1}(A)\) is empty. (b) The listed positive results are: 1. Pollack: the conclusion holds when \(A\) is the primes. (b) 2. Troupe: it holds for integers with an unusually large or small number of distinct prime factors. (b) 3. Troupe: it holds for sums of two squares. (b) 4. Pollack--Pomerance--Thompson (PPT): uniformly for every finite set \(\mathcal B\) of at most \(x^{1/2+\epsilon(x)}\) positive integers, where \(\epsilon(x)\to0\), \[
\#\{n\le x:s(n)\in\mathcal B\}=o(x).
\] Consequently the conjecture holds for a fixed \(A\) with counting function \(A(y)\le y^{1/2+o(1)}\). (b) 5. The page mentions untouchable values \(k\), for which \(s(n)=k\) has no solution, and points to Guy's problem B10. (b) The first discussion comment (Alfaiz, 30 September 2025) points to Divisor-sum fibers and calls it a weak form of the conjecture. The second comment (Thomas Bloom, 30 September 2025) says “Updated, thanks!” Neither comment claims a proof of the full conjecture or names a worker. (d) I checked the following primary sources, including their displayed theorem or abstract rather than relying on search-result titles. [*On the normal behavior of the iterates of some arithmetic functions*](https://oeis.org/A000010/a000010_1.pdf), Analytic Number Theory (1990), 165--204. Their Conjecture 4 is stated in the equivalent forward form: every set of positive upper density has an \(s\)-image of positive upper density. The paper also proposed a bounded-local-fibre hypothesis as a sufficient condition. (b) [*Some arithmetic properties of the sum of proper divisors and the sum of prime divisors*](https://pollack.uga.edu/EGPSnote-IJM.pdf), Illinois J. Math. 58 (2014), 125--147. Theorem 1.11 gives \(\#\{n\le x:s(n)\text{ prime}\}=O(x/\log x)\). (b) arXiv:1405.3587, published in J. Number Theory 150 (2015), 120--135. The abstract and Theorem 1.3 give the stated normal-order result for \(\omega(s(n))\). (b) [*Palindromic sums of proper divisors*](https://pollack.uga.edu/palindrome-final.pdf), Integers 15A (2015), A13. Theorem 1 proves another special case absent from the live page: fixed-base palindromes. (b) arXiv:1706.03120, Mathematika 64 (2018), 330--342, DOI Theorem 1.2 is uniform in the target set and proves the \(x^{1/2+o(1)}\) result. Theorem 1.4 disproves the EGPS bounded-local-fibre hypothesis: some values have \(\exp(c\log m/\log\log m)\) preimages in any prescribed proportional interval about \(m\). (b) arXiv:1902.11171, Proc. Amer. Math. Soc. 148 (2020), 4189--4202. The number of \(n\le x\) for which \(s(n)\) is a sum of two squares is \(\asymp x/\sqrt{\log x}\). (b) arXiv:2106.14953, Colloq. Math. 168 (2022), 287--295. They prove an almost-always equivalence between \(k\)-powerfreeness of \(n\) and \(s(n)\) for \(k\ge4\), and explicitly describe PPT's \(x^{1/2+o(1)}\) theorem as the record unrestricted result. (b) arXiv:2307.12859, published in *Women in Numbers Europe IV* (2024), DOI They explicitly say the full conjecture remains open and prove the new special case of fixed-base missing-digit sets, quantitatively: \(O(x\exp(-(\log\log x)^\gamma))\) for every fixed \(0<\gamma<1\) (their displayed theorem assumes base \(g\ge3\)). (b) arXiv:2508.06005v3, revised 18 December 2025. Theorem 1.6 proves a weighted version of Troupe's abnormal-prime- factor special case; it does not treat arbitrary zero-density target sets. (b) arXiv:2607.18981v1, submitted 21 July 2026. This newest directly relevant preprint again says the EGPS conjecture remains open. It includes base \(2\) in the missing-digit result and proves that, for composite inputs, omission of a fixed nonzero digit has count \[
\ll x\exp(-c(g)\sqrt{\log x}).
\] (b) I also checked the arXiv API in descending date order for the exact phrases “sum of proper divisors” and “proper divisors”, and ran exact-phrase searches for “EGPS conjecture” and the four authors' names. These searches found no primary source improving the general \(x^{1/2+o(1)}\) cardinality threshold or claiming the full result. This is a documented search miss, not a proof that no other source exists. (d) For real \(x\ge2\) and \(a\ge1\), define The input \(n=1\), for which \(s(1)=0\), is irrelevant. Arrange the positive fibre sizes in decreasing order and put The equality follows simply by selecting the \(k\) largest fibres. (a) Also define the size-biased heavy-fibre mass The live conjecture is equivalent to either one of the following uniform statements: and Thus the exact missing lemma is: for every \(\varepsilon>0\), there is a fixed \(T\) such that, for all sufficiently large \(x\), fewer than \(\varepsilon x\) inputs \(n\le x\) belong to an \(s\)-fibre of size greater than \(T\). (a) For any \(\mathcal B\) with \(|\mathcal B|\le\delta x\), split its fibres at height \(T\): Hence (UI) implies (U), first choosing \(T\) and then \(\delta\). Conversely, there are fewer than \(x/T\) fibres of size \(>T\), since all fibre sizes sum to at most \(x\). Therefore and (U) implies (UI). (a) First, If \(n\le x\) and \(s(n)>Cx\), then \(\sigma(n)/n>C\). Markov's inequality therefore gives (a) Second, for \(0<\eta<1\), let \(r=\sqrt\eta\). The inputs \(n\le rx\) contribute at most \(rx\). If \(n>rx\) and \(s(n)<\eta x\), then \(s(n)/n the proper divisor \(n/p\) would give \(s(n)/n\ge1/p\ge r\). For fixed \(r\), inclusion--exclusion gives density \(\prod_{p\le1/r}(1-1/p)\) for integers avoiding all those primes. Consequently using Euler's divergence of \(\sum_p1/p\). (a) Let \(A\) have density zero and fix \(C\). Among inputs with \(s(n)\le Cx\), only the set \(A\cap[1,Cx]\), of size \(o(x)\), can be hit. For every fixed \(\delta>0\), this set eventually has at most \(\delta x\) elements, so its preimage count is at most \(M_x(\lfloor\delta x\rfloor)\). Inputs with \(s(n)>Cx\) contribute at most \(\zeta(2)x/C\) by (2.3). Apply (U), then let \(C\to\infty\). (a) Suppose (U) fails. Then there are \(\rho>0\), numbers \(\delta_j\downarrow0\), arbitrarily large \(x_j\), and target sets \(\mathcal B_j\), with Put \(\eta_j=\sqrt{\delta_j}\). Choose a fixed \(C\) so that the upper tail in (2.3) is at most \(\rho x/4\). By (2.4), after discarding finitely many indices and taking the \(x_j\) sufficiently large, the lower tail \(s(n)<\eta_jx_j\) also has at most \(\rho x_j/4\) inputs. Thus still captures at least \(\rho x_j/2\) inputs. (a) Choose the \(x_j\) successively so large that the intervals \([\eta_jx_j,Cx_j]\) are disjoint and increasing and \(A=\bigcup_j\mathcal B'_j\). If \(\eta_jx_j\le y<\eta_{j+1}x_{j+1}\), then Hence \(A\) has density zero. But along \(x_j\), its preimage has upper density at least \(\rho/2\), contradicting the live conjecture. Therefore (U), and equivalently (UI), must hold. (a) PPT's uniform theorem says precisely that The missing range in (U) is much larger: \(k=\delta x\), with a bound that must tend uniformly to zero as \(\delta\downarrow0\). This states the gap without requiring any structure in the target set. (b) An \(L^2\) collision shortcut cannot work without truncation: because \(s(n)=1\) exactly for primes. This is far larger than the \(O(x)\) energy bound that Cauchy--Schwarz would need to handle every \(o(x)\)-sized target set. The condition (UI) correctly tolerates this fibre because its size-biased mass is only \(\pi(x)/x\to0\). **(a) for the fibre identity and collision obstruction; (b) for the prime-number-theorem asymptotic** Nor can one impose a fixed bound on the nonprime fibres: PPT Theorem 1.4 constructs values with \(\exp(c\log m/\log\log m)\) preimages in prescribed proportional intervals. What remains possible, and exactly sufficient, is the aggregate assertion (UI) that all large fibres together contain only vanishing input mass. (b) The prime-factor, residue-class, powerfree, palindrome, two-square, and missing-digit papers exploit special structure of their respective target sets. Their statements do not provide (UI) for arbitrary fibres. (b) For each cutoff, the verifier computes every \(s(n)\), sorts all positive fibre multiplicities, and uses (2.1). Therefore every entry \(M_x(k)\) below is a sharp universal finite bound: every \(\mathcal B\subset\mathbb N\) with \(|\mathcal B|\le k\) has at most \(M_x(k)\) preimages up to \(x\), and equality is attained by choosing \(k\) largest fibres. **(a) for sharpness; (d) for the numerical values** All logarithms in the table are natural. | \(x\) | \(\lfloor\sqrt x\rfloor\) | \(M_x\) | \(\lfloor x/\log^2x\rfloor\) | \(M_x\) | \(\lfloor x/\log x\rfloor\) | \(M_x\) | |---:|---:|---:|---:|---:|---:|---:| | 100 | 10 | 45 | 4 | 33 | 21 | 63 | | 1,000 | 31 | 295 | 20 | 259 | 144 | 559 | | 10,000 | 100 | 2,026 | 117 | 2,121 | 1,085 | 5,126 | | 100,000 | 316 | 14,758 | 754 | 18,547 | 8,685 | 48,337 | | 1,000,000 | 1,000 | 113,818 | 5,239 | 167,414 | 72,382 | 446,711 | | 5,000,000 | 2,236 | 487,831 | 21,014 | 790,980 | 324,150 | 2,136,775 | At \(x=5{,}000{,}000\), these three sharp captured proportions are \(0.0975662\), \(0.1581960\), and \(0.4273550\), respectively. Their decrease over this short range is not asserted to continue asymptotically. (d) Additional exact diagnostics at \(x=5{,}000{,}000\): the value** (d) \(H_x(1000)=H_x(10000)=348{,}513\); (d) \(\sum_{a\ne1}F_x(a)^2=27{,}002{,}756\). (d) No finite row proves a density statement. Its role is an exact small-case measurement of the concentration function that the reduction identifies. (d) The standalone verifier is It uses only the Python standard library and recomputes every value through two independent routes: 1. an additive proper-divisor sieve; 2. an SPF factorisation and the multiplicative product formula for \(\sigma(n)\). It also checks \(s(n)=1\) if and only if \(n\) is prime, reconstructs every table row, and compares the result with embedded exact tuples. (d) Run: The final measured run took about 24 seconds on one core and used about 239 MiB maximum RSS. Straight \(N\log N\) scaling puts the same Python method at \(N=10^8\) near \(0.15\) core-hours and roughly 5 GiB, and at \(N=10^9\) near \(1.7\) core-hours and roughly 50 GiB. I did not run those: larger finite cutoffs cannot supply the uniform \(x\to\infty\) step in (UI). (d) for the measurement; (c) for the extrapolation The precise analytic wall is now (UI), not lack of more samples. One needs a collective estimate for all popular \(s\)-values, strong enough that the fraction of inputs in fibres larger than fixed \(T\) tends uniformly to zero as \(T\to\infty\). PPT reaches arbitrary target sets only through \(x^{1/2+o(1)}\) values; known structured-set arguments do not aggregate over the \(\delta x\) potentially adversarial targets required here. **(a) for the equivalence; (b) for the literature boundary** The following is the exact standalone source used for the certified run. PARTIAL: proved an elementary equivalence with uniform size-biased fibre tightness, isolating the exact missing lemma, and exactly certified the sharp finite concentration function through \(x=5{,}000{,}000\); the unrestricted conjecture remains open.Everything else listed on the live page
1. Primary-source literature check
2. Exact reduction to size-biased fibre tightness
Reduction theorem
Proof that (U) and (UI) are equivalent
Two elementary output-tightness bounds
(U) implies the live conjecture
The live conjecture implies (U)
3. What this isolates, and why standard shortcuts fail
4. Exact finite concentration computation
5. Independent verification and computational wall
runs/erdos955_wave7w_reverify.py, SHA-2563e333279f30b87ddcdfb39256a6fec7fb5da69c0de4aa061d7cfd7de13debad0.python3 runs/erdos955_wave7w_reverify.py
6. Full verifier source
#!/usr/bin/env python3
"""Independent finite verifier for Erdős problem #955.
The script computes s(n) in two independent ways:
1. an additive proper-divisor sieve;
2. factorisation through a smallest-prime-factor sieve and the product
formula for sigma(n).
It then computes the exact finite concentration function
M_x(k) = max_{|B| <= k} #{2 <= n <= x : s(n) in B},
which is the sum of the k largest positive-value fibre sizes.
Only the Python standard library is used.
"""
from __future__ import annotations
import argparse
import math
import time
from array import array
from collections import Counter
DEFAULT_MAX_N = 5_000_000
DEFAULT_CUTOFFS = (
100,
1_000,
10_000,
100_000,
1_000_000,
5_000_000,
)
HEAVY_THRESHOLDS = (10, 100, 1_000, 10_000)
EXPECTED_DEFAULT_ROWS = (
(100, 57, 25, 3, 21, 114, 10, 45, 4, 33, 21, 63, 25, 0, 0, 0),
(
1_000,
524,
168,
6,
49,
1_769,
31,
295,
20,
259,
144,
559,
168,
168,
0,
0,
),
(
10_000,
5_024,
1_229,
15,
169,
24_326,
100,
2_026,
117,
2_121,
1_085,
5_126,
1_420,
1_229,
1_229,
0,
),
(
100_000,
48_748,
9_592,
41,
631,
323_151,
316,
14_758,
754,
18_547,
8_685,
48_337,
14_934,
9_592,
9_592,
0,
),
(
1_000_000,
480_139,
78_498,
92,
1_891,
4_304_997,
1_000,
113_818,
5_239,
167_414,
72_382,
446_711,
153_266,
78_498,
78_498,
78_498,
),
(
5_000_000,
2_383_711,
348_513,
171,
4_411,
27_002_756,
2_236,
487_831,
21_014,
790_980,
324_150,
2_136_775,
780_860,
371_436,
348_513,
348_513,
),
)
def additive_aliquot_sieve(limit: int) -> array:
"""Return s[n] by adding each proper divisor to all larger multiples."""
values = array("Q", [0]) * (limit + 1)
for divisor in range(1, limit // 2 + 1):
for multiple in range(2 * divisor, limit + 1, divisor):
values[multiple] += divisor
return values
def smallest_prime_factors(limit: int) -> array:
"""Return an SPF table; a zero entry at n >= 2 means that n is prime."""
spf = array("I", [0]) * (limit + 1)
for prime in range(2, math.isqrt(limit) + 1):
if spf[prime] != 0:
continue
for multiple in range(prime * prime, limit + 1, prime):
if spf[multiple] == 0:
spf[multiple] = prime
return spf
def aliquot_from_factorisation(n: int, spf: array) -> int:
"""Compute s(n)=sigma(n)-n from the prime factorisation of n."""
remaining = n
sigma = 1
while remaining > 1:
prime = spf[remaining] or remaining
prime_power = 1
geometric_sum = 1
while remaining % prime == 0:
remaining //= prime
prime_power *= prime
geometric_sum += prime_power
sigma *= geometric_sum
return sigma - n
def verify_all_values(values: array) -> None:
"""Recompute every entry independently using multiplicativity."""
limit = len(values) - 1
spf = smallest_prime_factors(limit)
for n in range(1, limit + 1):
independent = aliquot_from_factorisation(n, spf)
if values[n] != independent:
raise AssertionError(
f"s({n}) disagrees: divisor sieve={values[n]}, "
f"factorisation={independent}"
)
is_prime = n >= 2 and spf[n] == 0
if (values[n] == 1) != is_prime:
raise AssertionError(f"the fibre s(n)=1 disagrees with primality at n={n}")
def concentration_summary(x: int, counts: Counter[int]) -> tuple[int, ...]:
"""Return exact fibre and concentration data at x."""
# A is a subset of positive integers, so the irrelevant value s(1)=0 is
# deliberately absent. The caller starts inserting at n=2.
multiplicities = sorted(counts.values(), reverse=True)
prime_fibre = counts[1]
other_max_fibre = max(count for a, count in counts.items() if a != 1)
other_max_target = min(
a for a, count in counts.items() if a != 1 and count == other_max_fibre
)
k_sqrt = math.isqrt(x)
k_log2 = max(1, math.floor(x / math.log(x) ** 2))
k_log = max(1, math.floor(x / math.log(x)))
def top_mass(k: int) -> int:
return sum(multiplicities[:k])
collision_energy_without_prime_fibre = sum(
count * count for a, count in counts.items() if a != 1
)
heavy_masses = tuple(
sum(count for count in multiplicities if count > threshold)
for threshold in HEAVY_THRESHOLDS
)
return (
x,
len(counts),
prime_fibre,
other_max_fibre,
other_max_target,
collision_energy_without_prime_fibre,
k_sqrt,
top_mass(k_sqrt),
k_log2,
top_mass(k_log2),
k_log,
top_mass(k_log),
*heavy_masses,
)
def compute_table(values: array, cutoffs: tuple[int, ...]) -> list[tuple[int, ...]]:
counts: Counter[int] = Counter()
rows: list[tuple[int, ...]] = []
cutoff_set = set(cutoffs)
for n in range(2, cutoffs[-1] + 1):
counts[values[n]] += 1
if n in cutoff_set:
rows.append(concentration_summary(n, counts))
return rows
def print_table(rows: list[tuple[int, ...]]) -> None:
print(
"x distinct f(1) other_max other_target energy_without_1 "
"k_sqrt M_sqrt k_log2 M_log2 k_log M_log "
+ " ".join(f"H_gt_{threshold}" for threshold in HEAVY_THRESHOLDS)
)
for row in rows:
print(" ".join(map(str, row)))
print()
print("Ratios M_x(k)/x:")
for row in rows:
x = row[0]
print(
f"x={x}: sqrt={row[7] / x:.9f}, "
f"x/log^2x={row[9] / x:.9f}, "
f"x/logx={row[11] / x:.9f}"
)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--max-n",
type=int,
default=DEFAULT_MAX_N,
help=f"largest n to verify (default: {DEFAULT_MAX_N})",
)
return parser.parse_args()
def main() -> None:
args = parse_args()
if args.max_n < 2:
raise SystemExit("--max-n must be at least 2")
cutoffs = tuple(x for x in DEFAULT_CUTOFFS if x <= args.max_n)
if not cutoffs or cutoffs[-1] != args.max_n:
cutoffs += (args.max_n,)
started = time.perf_counter()
values = additive_aliquot_sieve(args.max_n)
after_additive = time.perf_counter()
verify_all_values(values)
after_independent = time.perf_counter()
rows = compute_table(values, cutoffs)
finished = time.perf_counter()
if args.max_n == DEFAULT_MAX_N:
if tuple(rows) != EXPECTED_DEFAULT_ROWS:
raise AssertionError("recomputed table differs from the certified table")
print_table(rows)
print(
"PASS: every s(n) was identical under the additive-divisor and "
"multiplicative-factorisation computations; the exact default table "
"matches its embedded certificate; and s(n)=1 exactly at primes."
)
print(
f"Timings: additive={after_additive - started:.3f}s, "
f"independent={after_independent - after_additive:.3f}s, "
f"table={finished - after_independent:.3f}s, "
f"total={finished - started:.3f}s"
)
if __name__ == "__main__":
main()