Add verified heart pattern example

This commit is contained in:
Yaossg 2026-10-17 00:04:47 +08:00
parent 7952207735
commit f71985c0c3
5 changed files with 97 additions and 1 deletions

View file

@ -16,6 +16,30 @@ mkdir -p artifacts
默认编译 `sm_86` 并附带 PTX,适合本机 RTX 3060 Laptop。换架构时用 `-B` 强制重建;仅改变 Make 变量不会使已有文件自动过期。
## 已验证实例:5×5 爱心
种子 **`22428888508636`**,左上角区块 **`(-5,-147)`**(方块原点 `(-80,-2352)`)。每格一个区块,向右为 `+X`、向下为 `+Z`;16 格 `#` 必须是史莱姆,9 格 `.` 必须不是:
```text
.#.#.
#####
#####
.###.
..#..
```
```sh
./bench/bin/slime-bench --radius 256 \
--pattern-file bench/patterns/heart-5x5.txt \
--position-batch 256 --max-results 1000
# 单点复查,收集全部普通分支匹配:应得到 1,181 个种子
./bench/bin/slime-bench --x -5 --z -147 --radius 0 \
--pattern-file bench/patterns/heart-5x5.txt --max-results 2000
```
RTX 3060 Laptop 实测:131,585 个锚点,普通分支共找到 1,456 个种子/位置匹配,扫描约 2.439 秒(含设备初始化的端到端约 2.620 秒)。保存的 1,000 个搜索样本,以及单点复查的全部 1,181 个种子,都通过独立 Python 实现的 Java 整数回绕及 `Random.nextInt(10)` 精确逐格验证。已知种子及计时见 [results/heart-5x5-example.json](results/heart-5x5-example.json)。GPU 回归检查单点计数、已知种子及全部样本,搜索计数不包含拒绝重抽补扫。
## 自定义图案:6×6 苦力怕
`--pattern` 接受 `/` 分隔的行,或用 `--pattern-file` 读取每行一排的文本文件。`#` 必须是史莱姆区块,`.` 必须不是,`?` 不限制。支持非正方形,宽、高分别为 1~64,至少含一个 `#`;不能与 `--size` 同时指定。不自动旋转或镜像。

View file

@ -0,0 +1,5 @@
.#.#.
#####
#####
.###.
..#..

View file

@ -0,0 +1,52 @@
{
"pattern": [
".#.#.",
"#####",
"#####",
".###.",
"..#.."
],
"seed48": 22428888508636,
"chunk_x": -5,
"chunk_z": -147,
"block_origin": [
-80,
-2352
],
"verified_rows": [
".#.#.",
"#####",
"#####",
".###.",
"..#.."
],
"verification": {
"method": "independent Python implementation of Java int overflow and Random.nextInt(10) rejection loop",
"verified_search_sample_count": 1000,
"verified_single_anchor_count": 1181,
"slime_cells": 16,
"non_slime_cells": 9
},
"search": {
"center": [
0,
0
],
"radius_chunks": 256,
"anchors": 131585,
"matches": 1456,
"scan_wall_ms": 2438.534811,
"elapsed_ms": 2619.994137,
"gpu": "NVIDIA GeForce RTX 3060 Laptop GPU",
"rejection_tail_included": false
},
"single_anchor": {
"matches": 1181,
"root_jobs": 405
},
"source_sha256": {
"bench/slime_bench.cu": "3c70cbe2e5babc3e737199fb5e62b78ea9c5daadc0020af77292c2d59516259e",
"include/slime/solver_core.hpp": "feb1200518716b4d796fb60f60a83b6b798155bbd4e795531793181a5c7f9eba",
"include/slime/upper_interval.hpp": "af3fddf7705295d91ffd6e2190f542004a3ecff847fce9d4c9b13125bdbdc2d5"
}
}

View file

@ -40,8 +40,23 @@ def main():
with tempfile.TemporaryDirectory() as tmp:
path=Path(tmp)/'pattern.txt';path.write_bytes(b'?##.\r\n#..?\r\n..#?\r\n')
assert run('--radius',0,'--pattern-file',path,'--dry-run')['pattern']==pattern.split('/')
heart_fixture=json.loads((HERE/'results/heart-5x5-example.json').read_text())
assert (HERE/'patterns/heart-5x5.txt').read_text().splitlines()==heart_fixture['pattern']
assert all(slime(heart_fixture['seed48'],heart_fixture['chunk_x']+dx,heart_fixture['chunk_z']+dz)==(ch=='#')
for dz,row in enumerate(heart_fixture['pattern']) for dx,ch in enumerate(row))
summary={'cli_scope_and_errors':True,'pattern_inputs':True}
if args.gpu:
heart_poc=run('--x',heart_fixture['chunk_x'],'--z',heart_fixture['chunk_z'],'--radius',0,
'--pattern-file',HERE/'patterns/heart-5x5.txt','--max-results',2000)
heart_hits=heart_poc['rounds'][0]
assert heart_hits['matches']==heart_fixture['single_anchor']['matches']
assert heart_hits['root_jobs']==heart_fixture['single_anchor']['root_jobs']
assert not heart_hits['sample_truncated'] and len(heart_hits['sample'])==heart_hits['matches']
assert len(set(map(tuple,heart_hits['sample'])))==heart_hits['matches']
assert [heart_fixture['seed48'],heart_fixture['chunk_x'],heart_fixture['chunk_z']] in heart_hits['sample']
for seed,x,z in heart_hits['sample']:
assert all(slime(seed,x+dx,z+dz)==(ch=='#') for dz,row in enumerate(heart_fixture['pattern']) for dx,ch in enumerate(row))
summary['heart_pattern_verified_matches']=heart_hits['matches']
# A mixed-mask regression fixture; this is not the target creeper pattern.
fixture=json.loads((HERE/'testdata/mixed-mask-regression.json').read_text())
face=run('--x',fixture['chunk_x'],'--z',fixture['chunk_z'],'--radius',0,