feat(solve): random_walk 落地;修默认采样器真 bug(integers 不收 float)

random_walk 由用户本人写;Codex 改一处真 bug + 工程侧。

- 真 bug:默认采样器 rng.integers(0, 2, size=size, dtype=float) 被 numpy 拒掉
  (Unsupported dtype dtype(float64) for integers),默认路径 100% success=False、
  data=None,连 docstring 的 Examples 都跑不通。改成 integers(size=size) * 2 - 1,
  由后面的 np.asarray(..., dtype=float) 转 float;实测 (5,101)、步长恒 ±1、同种子可复现
- 工程:ruff W293 x2;docstring 补全(n_steps/n_paths/start/random_state + Returns /
  Raises / Notes,写清 step_sampler 收二维 size=(n_paths, n_steps))
- tests:random_walk 首次有测试,新增 6 条(形状 + start、步长恒 ±1、可复现、自定义
  高斯采样器、3 类非法入参、docstring Example)
- monte_carlo_integral:用户第二轮已收 ndarray + 把三行提出 if/else(决策 52)
- 验证:205 收集 / 174 passed / 31 skipped / 0 xfail,ruff 0,pyright 0
- docs:STATUS 决策 53 + random_walk 4 条待办;CHANGELOG;易错点 24/25,第 18 条复发 +1
This commit is contained in:
guzhujushi committed 2026-10-05 17:04:52 +08:00
1 parent dcda080be4
commit 8ec08ea9ce
5 files changed
+254 -32

No files matched your search

+60
View File
@@ -276,6 +276,66 @@ def test_monte_carlo_probability_rejects_bad_confidence():
monte_carlo_probability(lambda z: z > 0, _normal_batch, n=100, confidence=bad)
def test_random_walk_shape_and_start():
"""`data` 形状 (n_paths, n_steps + 1),第 0 列是起点。"""
from mcm_toolkit.solve import random_walk
r = random_walk(n_steps=100, n_paths=5, start=2.5, random_state=0)
assert r.success
assert r.data.shape == (5, 101)
assert np.all(r.data[:, 0] == 2.5)
def test_random_walk_default_steps_are_plus_minus_one():
"""默认是对称随机游走:每一步都恰好是 ±1。"""
from mcm_toolkit.solve import random_walk
r = random_walk(n_steps=200, n_paths=3, random_state=0)
assert set(np.unique(np.diff(r.data, axis=1))) == {-1.0, 1.0}
def test_random_walk_is_reproducible():
from mcm_toolkit.solve import random_walk
a = random_walk(n_steps=50, n_paths=4, random_state=7)
b = random_walk(n_steps=50, n_paths=4, random_state=7)
assert np.array_equal(a.data, b.data)
def test_random_walk_accepts_custom_step_sampler():
"""换成高斯增量就是带漂移的高斯游走 —— 建模差异全在 step_sampler 里。"""
from mcm_toolkit.solve import random_walk
r = random_walk(
n_steps=100,
n_paths=3,
step_sampler=lambda rng, size: rng.normal(0.5, 1.0, size),
random_state=0,
)
assert r.success
assert r.data.shape == (3, 101)
assert abs(r.data[:, -1].mean() - 50.0) < 20.0 # 100 步 × 漂移 0.5
def test_random_walk_rejects_bad_arguments():
from mcm_toolkit.solve import random_walk
with pytest.raises(ValueError):
random_walk(n_steps=0)
with pytest.raises(ValueError):
random_walk(n_steps=10, n_paths=0)
with pytest.raises(TypeError):
random_walk(n_steps=10, start="a") # type: ignore[arg-type] # 就是要传错
def test_random_walk_docstring_example_runs():
from mcm_toolkit.solve import random_walk
r = random_walk(n_steps=100, n_paths=5, random_state=0)
assert r.data.shape == (5, 101)
assert np.all(np.abs(np.diff(r.data, axis=1)) == 1)
@pytest.mark.skip(reason=_NOT_IMPLEMENTED)
def test_markov_steady_state_two_state_chain():
"""P=[[0.9,0.1],[0.2,0.8]] 的平稳分布是 [2/3, 1/3]。"""