Add verified diamond and heart pattern examples
This commit is contained in:
parent
7952207735
commit
2eeb2ff0d4
7 changed files with 189 additions and 1 deletions
|
|
@ -16,6 +16,56 @@ 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 回归检查单点计数、已知种子及全部样本,搜索计数不包含拒绝重抽补扫。
|
||||
|
||||
## 已验证实例:4×4 菱形
|
||||
|
||||
种子 **`126066202091224`**,左上角区块 **`(-1,-63)`**(方块原点 `(-16,-1008)`)。每格是一个区块,向右为 `+X`、向下为 `+Z`;`#` 为史莱姆,`.` 必须不是:
|
||||
|
||||
```text
|
||||
.##.
|
||||
####
|
||||
####
|
||||
.##.
|
||||
```
|
||||
|
||||
```sh
|
||||
# 搜索原点周围;这里只限制保存的样本数,仍会完整扫描
|
||||
./bench/bin/slime-bench --radius 64 \
|
||||
--pattern-file bench/patterns/diamond-4x4.txt \
|
||||
--position-batch 128 --max-results 1000
|
||||
|
||||
# 单点复查:普通分支应得到 11,142 个种子
|
||||
./bench/bin/slime-bench --x -1 --z -63 --radius 0 \
|
||||
--pattern-file bench/patterns/diamond-4x4.txt --max-results 64
|
||||
```
|
||||
|
||||
RTX 3060 Laptop 实测:8,321 个锚点,普通分支找到 2,457,370 个种子/位置匹配,扫描约 0.924 秒(含设备初始化的端到端约 1.098 秒)。保存的 1,000 个样本全部通过独立 Python 实现的 Java 整数回绕及 `Random.nextInt(10)` 精确验证,包括四个非史莱姆角。样本顺序由 GPU 调度决定,不保证固定种子在截取的前 64 个样本中。已知种子及验证记录见 [results/diamond-4x4-example.json](results/diamond-4x4-example.json),GPU 回归会核对单点计数并独立验证返回样本。
|
||||
|
||||
此实例证明自定义正负约束搜索可行;搜索计数仍不包含拒绝重抽补扫。
|
||||
|
||||
## 自定义图案:6×6 苦力怕
|
||||
|
||||
`--pattern` 接受 `/` 分隔的行,或用 `--pattern-file` 读取每行一排的文本文件。`#` 必须是史莱姆区块,`.` 必须不是,`?` 不限制。支持非正方形,宽、高分别为 1~64,至少含一个 `#`;不能与 `--size` 同时指定。不自动旋转或镜像。
|
||||
|
|
|
|||
4
bench/patterns/diamond-4x4.txt
Normal file
4
bench/patterns/diamond-4x4.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
.##.
|
||||
####
|
||||
####
|
||||
.##.
|
||||
5
bench/patterns/heart-5x5.txt
Normal file
5
bench/patterns/heart-5x5.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
.#.#.
|
||||
#####
|
||||
#####
|
||||
.###.
|
||||
..#..
|
||||
49
bench/results/diamond-4x4-example.json
Normal file
49
bench/results/diamond-4x4-example.json
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"pattern": [
|
||||
".##.",
|
||||
"####",
|
||||
"####",
|
||||
".##."
|
||||
],
|
||||
"seed48": 126066202091224,
|
||||
"chunk_x": -1,
|
||||
"chunk_z": -63,
|
||||
"block_origin": [
|
||||
-16,
|
||||
-1008
|
||||
],
|
||||
"verified_rows": [
|
||||
".##.",
|
||||
"####",
|
||||
"####",
|
||||
".##."
|
||||
],
|
||||
"verification": {
|
||||
"method": "independent Python implementation of Java int overflow and Random.nextInt(10) rejection loop",
|
||||
"verified_sample_count": 1000,
|
||||
"slime_cells": 12,
|
||||
"non_slime_cells": 4
|
||||
},
|
||||
"search": {
|
||||
"center": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"radius_chunks": 64,
|
||||
"anchors": 8321,
|
||||
"matches": 2457370,
|
||||
"scan_wall_ms": 924.202261,
|
||||
"elapsed_ms": 1097.678503,
|
||||
"gpu": "NVIDIA GeForce RTX 3060 Laptop GPU",
|
||||
"rejection_tail_included": false
|
||||
},
|
||||
"single_anchor": {
|
||||
"matches": 11142,
|
||||
"root_jobs": 235
|
||||
},
|
||||
"source_sha256": {
|
||||
"bench/slime_bench.cu": "3c70cbe2e5babc3e737199fb5e62b78ea9c5daadc0020af77292c2d59516259e",
|
||||
"include/slime/solver_core.hpp": "feb1200518716b4d796fb60f60a83b6b798155bbd4e795531793181a5c7f9eba",
|
||||
"include/slime/upper_interval.hpp": "af3fddf7705295d91ffd6e2190f542004a3ecff847fce9d4c9b13125bdbdc2d5"
|
||||
}
|
||||
}
|
||||
52
bench/results/heart-5x5-example.json
Normal file
52
bench/results/heart-5x5-example.json
Normal 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"
|
||||
}
|
||||
}
|
||||
|
|
@ -40,8 +40,36 @@ 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('/')
|
||||
diamond_fixture=json.loads((HERE/'results/diamond-4x4-example.json').read_text())
|
||||
assert (HERE/'patterns/diamond-4x4.txt').read_text().splitlines()==diamond_fixture['pattern']
|
||||
assert all(slime(diamond_fixture['seed48'],diamond_fixture['chunk_x']+dx,diamond_fixture['chunk_z']+dz)==(ch=='#')
|
||||
for dz,row in enumerate(diamond_fixture['pattern']) for dx,ch in enumerate(row))
|
||||
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']
|
||||
diamond_poc=run('--x',diamond_fixture['chunk_x'],'--z',diamond_fixture['chunk_z'],'--radius',0,
|
||||
'--pattern-file',HERE/'patterns/diamond-4x4.txt','--max-results',64)
|
||||
diamond_hits=diamond_poc['rounds'][0]
|
||||
assert diamond_hits['matches']==diamond_fixture['single_anchor']['matches']
|
||||
assert diamond_hits['root_jobs']==diamond_fixture['single_anchor']['root_jobs']
|
||||
assert len(diamond_hits['sample'])==64
|
||||
for seed,x,z in diamond_hits['sample']:
|
||||
assert all(slime(seed,x+dx,z+dz)==(ch=='#') for dz,row in enumerate(diamond_fixture['pattern']) for dx,ch in enumerate(row))
|
||||
summary['diamond_pattern_verified_matches']=diamond_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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue