Problem 252: add OEIS A307036 and A359060 (k = 3, 4); retain possible flag - #360
Merged
Conversation
Both constants verified against the live OEIS data field to 87 and 81 digits respectively, using truncated rather than rounded comparison. The 'possible' flag is retained because S_5 and S_6 are not in OEIS. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cc8c383e-e43d-4ccd-be8c-1c339d66f08c
Contributor
Author
|
Verification code, reproduced in full so it can be inspected and re-executed. Python 3, standard library only (the OEIS fetch uses """
Erdos problem 252: S_k = sum_{n>=1} sigma_k(n) / n!
Recomputes the constants EXACTLY, reports them TRUNCATED (not rounded), and
re-verifies the four OEIS links through oeis_constant_match, which refuses to
round.
Two independent evaluations are retained as the anti-hallucination cross-check:
(A) direct exact Fraction sum with sigma_k by trial division
(B) rearranged sum_d d^k sum_j 1/(jd)! also as an exact Fraction sum
Both are exact rationals, so agreement is checked as exact equality of the
truncated digit strings rather than to a floating tolerance.
"""
from __future__ import annotations
import json
import time
import urllib.parse
import urllib.request
from fractions import Fraction
from math import factorial
from oeis_constant_match import compare_to_oeis, truncated_digits
N_TERMS = 120 # 120! dwarfs any precision we print
DIGITS_REPORT = 40
LINKS = {1: "A227988", 2: "A227989", 3: "A307036", 4: "A359060"}
UA = {"User-Agent": "erdos-oeis-check/1.0 (manual verification)"}
def sigma_k(n: int, k: int) -> int:
"""Sum of k-th powers of the divisors of n, by trial division."""
total = 0
d = 1
while d * d <= n:
if n % d == 0:
total += d ** k
other = n // d
if other != d:
total += other ** k
d += 1
return total
def method_a(k: int, n_terms: int = N_TERMS) -> Fraction:
"""Direct: sum sigma_k(n) / n!."""
return sum((Fraction(sigma_k(n, k), factorial(n)) for n in range(1, n_terms + 1)),
Fraction(0))
def method_b(k: int, n_terms: int = N_TERMS) -> Fraction:
"""Rearranged: sum_d d^k sum_j 1/(jd)! -- swaps the order of summation."""
total = Fraction(0)
for d in range(1, n_terms + 1):
inner = Fraction(0)
j = 1
while j * d <= n_terms:
inner += Fraction(1, factorial(j * d))
j += 1
total += Fraction(d ** k) * inner
return total
def _oeis_entry(anum: str) -> dict:
url = f"https://oeis.org/search?fmt=json&q={urllib.parse.quote('id:' + anum)}"
req = urllib.request.Request(url, headers=UA)
with urllib.request.urlopen(req, timeout=60) as fh:
payload = json.load(fh)
# The API has returned both a bare list and a {"results": [...]} envelope.
results = payload if isinstance(payload, list) else (payload.get("results") or [])
if not results:
raise RuntimeError(f"no OEIS result for {anum}")
return results[0]
def oeis_data(anum: str) -> str:
return _oeis_entry(anum)["data"]
def oeis_name(anum: str) -> str:
return _oeis_entry(anum)["name"]
def main() -> None:
print("=" * 78)
print("Erdos 252: cross-check of the two independent evaluations")
print("=" * 78)
exact: dict[int, Fraction] = {}
for k in range(1, 7):
a = method_a(k)
b = method_b(k)
da = truncated_digits(a, DIGITS_REPORT)
db = truncated_digits(b, DIGITS_REPORT)
agree = da == db
exact[k] = a
print(f"k={k}: methods agree on {DIGITS_REPORT} truncated digits: {agree}")
if not agree:
raise SystemExit(f"METHODS DISAGREE at k={k}: {da} vs {db}")
print()
print("=" * 78)
print(f"Constants, TRUNCATED to {DIGITS_REPORT} significant digits")
print("=" * 78)
for k in range(1, 7):
digits = truncated_digits(exact[k], DIGITS_REPORT)
intpart = len(str(int(exact[k])))
shown = digits[:intpart] + "." + digits[intpart:]
print(f" k={k}: {shown}")
print()
print("=" * 78)
print("OEIS verification (truncation-aware)")
print("=" * 78)
all_ok = True
for k, anum in LINKS.items():
data = oeis_data(anum)
ok, n, detail = compare_to_oeis(exact[k], data)
all_ok &= ok
print(f" k={k} -> {anum}: {'MATCH' if ok else 'FAIL'} ({n} digits)")
print(f" {detail}")
print(f" name: {oeis_name(anum)}")
time.sleep(2)
print()
print(f"ALL FOUR LINKS VERIFIED: {all_ok}")
if __name__ == "__main__":
main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem #252 concerns the irrationality of$S_k = \sum_{n \ge 1} \sigma_k(n)/n!$ . The entry already links $k = 1$ and $k = 2$ . This adds the $k = 3$ and $k = 4$ constants. The $k \ge 5$ is not covered (see below).
"possible"flag is retained, sincenamefield, quoted verbatimThe
namefields are quoted verbatim so that functional equivalence with the problem statement can be judged without recomputation.Verification
Each constant was computed two independent ways, both as exact rationals over 120 terms:
The two agree exactly on 40 truncated significant digits for every$k \in {1,\dots,6}$ .
Each was then compared against the live OEIS
datafield, comparing truncated rather than rounded digits (see the companion issue #357):An 80-digit agreement rules out coincidence, so identity is settled; the
namequotes above are supplied so that the separate question of functional equivalence of description can be checked directly.Code: stdlib-only apart from an optional
urllibOEIS fetch, and it runs in well under a minute. It is reproduced in a comment below so it can be inspected and re-executed rather than taken on trust.Why
"possible"stayspossiblestring"), the flag should therefore remain: the family is demonstrably incomplete.I am deliberately not proposing an OEIS submission for them, since per the project's AI policy any OEIS submission must be human-originated. Recording the truncated values here only so the gap is visible to anyone who wants to pursue it:
AI disclosure
This PR was prepared with AI assistance (GitHub Copilot CLI). No sequence values were taken from a model: all figures come from code that was written, inspected and executed locally, and every constant was reproduced by two independent methods before being compared to OEIS. Nothing here is proposed for submission to the OEIS.