slime/research/README.md

8 KiB

Slime pattern reverse-search prototype

当前范围测速 CLI 见 bench/README.md,共用算法实现见 include/。本目录保留研究入口与历史路径;近期实验见 实验导航。

This directory retains fixed-coordinate seed solvers and fixed-seed coordinate scanners. It is not a complete all-seed world-border catalog generator.

  • slime_pattern_prototype.py: readable reference/oracle.
  • slime_pattern_cpp.cpp, slime_pattern_cuda.cu: fixed-coordinate seed search.
  • slime_position_cuda.cu: direct vs tiled outer-sum coordinate scans.
  • slime_position_residue_cuda.cu: fixed-seed coordinate-residue filtering.
  • slime_bruteforce_cpp_bench.cpp, slime_bruteforce_cuda_bench.cu: baseline benchmarks.
  • slime_solver_core.hpp: shared arithmetic and upper13 solver.

See 优化摘要 and BENCHMARK.md. The independent X/Z filter/join route and its middle-bit experiments have been removed; method, historical results and stopping reasons are consolidated in X/Z 筛轴试错报告.

What is implemented

  • Minecraft/Java-compatible coordinate overflow and Random.nextInt(10) verification.
  • Arbitrary patterns using # (slime), . (non-slime), and ? (ignored).
  • Lower-seed 2-adic lifting from 18 bits toward the 35-bit boundary.
  • The analytic 35 + 13 split. For seed = lower35 + m * 2^35, all pattern cells share the same upper-state displacement. Substituting n = 1645*m mod 8192 turns each required-slime cell into a piecewise n mod 5 constraint with one threshold. Sorting those thresholds solves all upper 13 bits without scanning 8192 values.
  • The position outer-sum identity modulo 2^32, used to reuse coordinate arithmetic in fixed-seed scans.
  • A full-world fixed-seed position search: filter the 2^36 pairs (x mod 2^18, z mod 2^18) on CUDA, expand only surviving residue classes, then perform exact Java verification.

Run it

The known public 5x5 sample is:

python3 research/slime_pattern_prototype.py verify \
  --seed 61692151016558 --x 51069 --z 419124 -n 5

Recover the 12 upper-bit solutions belonging to one known lower-35-bit value:

python3 research/slime_pattern_prototype.py upper \
  --lower35 16420645998 --x 51069 --z 419124 -n 5

Show the 18-to-24-bit lifting counts:

python3 research/slime_pattern_prototype.py roots \
  --x 51069 --z 419124 -n 5 --bits 24

Use a custom pattern (rows are separated by /):

python3 research/slime_pattern_prototype.py verify \
  --seed 61692151016558 --x 51069 --z 419124 \
  --pattern '##?/..#/#?#'

Check and print the outer-sum position signature:

python3 research/slime_pattern_prototype.py signature \
  --x 51069 --z 419124 -n 5

Run the tests:

python3 -m unittest discover -s research -p 'test_*.py'

C++ and CUDA

Build both native implementations:

make -C research

The CPU CLI exposes the same important stages as the Python oracle:

research/slime_pattern_cpp verify \
  --seed 61692151016558 --x 51069 --z 419124 -n 5

research/slime_pattern_cpp roots \
  --x 51069 --z 419124 -n 5 --bits 24

research/slime_pattern_cpp upper \
  --lower35 16420645998 --x 51069 --z 419124 -n 5

search performs the complete fixed-position pipeline. For the public 5x5 sample it expands 84 lower-18 roots into 11,010,048 lower-35-bit values and recovers all 24 known seeds:

research/slime_pattern_cpp search \
  --x 51069 --z 419124 -n 5 -p 16 --max-results 32

On the development machine this CPU run took about 0.68 seconds with 16 worker threads. Treat that as a local sanity benchmark, not a portable performance claim.

The CUDA program performs the same complete fixed-position search and accepts the same compact arbitrary-pattern syntax:

research/slime_pattern_cuda \
  --x 51069 --z 419124 -n 5 --threads 128 --max-results 32

research/slime_pattern_cuda \
  --x 0 --z 0 --pattern '##?/..#/#?#' --threads 128

CUDA 12 compilation was verified, and the solver was subsequently benchmarked on an RTX 3060 Laptop GPU. See BENCHMARK.md for the old/new CPU and CUDA comparison, methodology, commands, and limitations. GPU execution from a sandboxed session may still require host GPU permission.

Coordinate-side outer-sum experiment

For a fixed world seed, compare a direct position scan against a tiled outer-sum scan over an inclusive rectangle:

research/slime_position_cuda \
  --seed 61692151016558 \
  --x0 46973 --x1 55165 --z0 415028 --z1 423220 \
  -n 5 --repeats 5

Both kernels run on every invocation. Their sorted hit lists must be exactly equal or the program fails. The direct kernel recomputes the full coordinate term at each tested cell. The outer kernel assigns a 16x16 position tile to a CUDA block and shares the expanded F(x+i) and G(z+j) axis arrays across the block. On the development RTX 3060 Laptop GPU, the 67,125,249-position command above took 1.608 ms direct versus 1.332 ms outer-sum (median of five), a 1.21x kernel speedup, and found only (51069, 419124).

This result is intentionally modest. A solid pattern rejects almost every position on its first one or two chunks, so the direct kernel seldom evaluates all 25 coordinate polynomials. Outer-sum removes duplicated coordinate work, but does not change the asymptotic rectangle area. It remains a fixed-seed arithmetic-reuse baseline; full seed/coordinate catalog generation is unresolved.

The low output parity used by the seed lifting depends on coordinates only modulo 2^18. The residue solver checks that fixed 2^36 space once, then expands the surviving residue pairs into the requested world rectangle:

research/slime_position_residue_cuda --seed 61692151016558 -n 5

The default bounds are [-1875000, 1874999] on both axes. For the public seed on the development RTX 3060 Laptop GPU, the residue kernel took 1.93 seconds, retained 180,476 of 68,719,476,736 residue pairs, and expanded them into 36,937,048 exact candidates out of 14,062,500,000,000 world positions. Exact CPU verification took another 284 ms and found only (51069, 419124).

Across four tested seeds, the kernel stayed between 1.92 and 1.94 seconds and retained 175,992--195,672 residue pairs. Including axis-table preparation and exact verification, a full run took about 2.5 seconds. A measured 2^34 direct-position CUDA run projects to about 429 seconds over the same world, so the residue method is about 170x faster end-to-end for this fixed-seed 5x5 workload.

Removed experiments

Failed and inferior approaches are not part of the active build. Their data, failure reasons, and key implementation snippets are preserved in REJECTED_EXPERIMENTS.md.

Prototype limitations

  1. The upper-bit candidate generator describes the first next(31) draw. Java rejects only the final eight of the 2^31 possible values before drawing again. Every emitted seed is checked with the exact rejection loop, so there are no false positives, but a solution whose first draw is rejected and whose later draw succeeds can be missed. An exhaustive catalog builder must add a tiny exceptional-state branch.
  2. Ordinary lifting is weak after the output parity becomes known: modulo 5 can still be repaired by unknown binary bits. A solid 5x5 sample has 84 roots at 18 bits and 5,376 at 24 bits, then grows to roughly 11 million lower-35 low-bit values. The CLI therefore has a candidate safety limit.
  3. Full-world position enumeration is implemented only for a fixed seed and a solid square of size 1--8. Joint unknown (seed, x, z) catalog generation is still unresolved; the X/Z independent-filter route was retired; see the trial report.
  4. The residue parity filter shares the first-draw rejection-tail caveat from item 1. Exact verification prevents false positives, but the rare solution whose first draw is rejected can be filtered out before verification.