q1 — exhaustive search for short straight-line programs
Decides whether an integer has a straight-line program of length (OEIS A173419 / A217032; Smale 1998, Problem 4, integer form).
Files
| file | role |
|---|---|
slp_search.c |
the search (C, OpenMP): count mode, decide mode, endgame test mode |
check.rs |
independent Rust re-implementation: count mode and a brute-force endgame sampler |
targets.txt, targets_core.txt, targets13.txt |
targets: for and primorials to ; the core list for the 11- and 12-step runs; the 13-step list (20!, 21!, 22!, 37#) |
brute_check.py |
Python brute-force cross-check of the three-step endgame at prefix depths 3–6 |
compare_endgame.py |
Rust brute-force sampler versus the C endgame at prefix depths 7–10 (compare_*.txt) |
verify_slp.py |
exact replay of every witness program (stdlib) |
make_tau_table.py, tau_table_10266.txt |
for , C and Rust tables compared, OEIS b-file format |
b173419.txt |
OEIS A173419 b-file (n ≤ 1800) used as a control |
run_all.sh, launch13.sh |
replay driver; launcher for the 13-step decision |
count9.json, count9_10266.json, check_count9_10266.json |
count mode to 9 steps (C twice, Rust once) |
decide11_core.json, decide12.json, decide13.json |
decisions at 11, 12, 13 steps |
make_certificate.py, certificate.json |
summary of every decision |
Definitions
A program is , with and ; is the least with . Subtraction is allowed in either order and is allowed. This is the convention of OEIS A173419, of the 2013 contest, and of Markström; Shub–Smale and Smale use the same one.
Normalisation
If has a program of length , it has one of length at most whose values are pairwise distinct and strictly positive. Replace every value by its absolute value: , and is either or the positive difference of and , so the new sequence is again a program. A zero can only arise as a difference of equal values; a repeated value can be dropped after redirecting later references to its first copy. (Markström, arXiv:1306.3091, Appendix A, states the same.)
Canonical order
Let be the values of a normalised program prefix. The queue lists every positive integer derivable in one step from and not in , in blocks: block 0 holds the values derivable from , block the values first derivable once is present, each block in a fixed generation order and without repetition. Positions in the queue depend only on the prefix.
Rule: the next value must sit in at a position strictly larger than the position of in .
Every normalised program has exactly one valid order that satisfies the rule. Among all orderings of its value set that are programs (each value derivable from the earlier ones), take the one whose sequence of queue positions is lexicographically least. If two consecutive values had non-increasing positions, the later one would lie in an earlier block, hence be derivable without the former; swapping the two gives a program with a smaller position sequence. For an optimal program the target is the only value not used later, so it is last in every ordering. This is the "pending queue" order described by Rokicki in the OEIS A217032 digest; the count mode reproduces Markström's reached-set sizes exactly, which is the empirical check of exhaustiveness.
Endgame
For length the search enumerates prefixes of steps and asks whether is derivable in at most three more steps. Write for the prefix set, for its queue, and for the new values (each new, positive, and used later).
- 0 or 1 step: or .
- 2 steps: with or , so and .
- 3 steps, last step uses : with ; either , or with , which is solved for (for instance gives ).
- 3 steps, last step does not use : with , so is one of at most candidates, and with , . Divisibility is decided from residues and without division.
Any hit is turned into an explicit program and re-verified in Python.
brute_check.py compares the endgame with a direct three-step
expansion on random prefixes.
Filters
- Markström's bound: with steps left, values stay below where is the current maximum.
- Leaf bound: in three steps the only ways to exceed are and . Factorials and primorials are never perfect powers, so a leaf with is skipped for that target.
- Range checks before every lookup: a value must lie between the minimum and maximum of the set it is claimed to belong to.
Arithmetic is exact: values below are native, larger ones use limbs; the arena is asserted, never truncated.
Replay
./run_all.sh # build, controls, decisions at 11 and 12 steps, verify
./run_all.sh --full # also the 13-step decision (hours on 8 threads)