feat(solve): monte_carlo_integral 落地,修掉体积符号真 bug
实现由用户本人写;Codex 只碰工程侧 + 一处纯 bug(决策 31)。 - 真 bug:体积写成 lows - highs,奇数维为负(1D x^2 于 [0,1] 得 -0.3324、3D 得 -0.5005); 2D 因两个负号相乘"看着对"(+0.2499),把 bug 藏住。改成 widths = highs - lows 后 复测 0.3324 / 0.5005 / 1.9971([0,2])全部正确 - docstring:补 func / n / random_state 与 Raises;写清 metrics["mean"] 才是积分估计值、 data 是 n 个样本各自的贡献(决策 51);修掉跑不通的 Examples(data 是数组,bool(数组) 会抛) - tests/test_solve.py:摘 1 条 skip + 新增 4 条(3D 奇数维 / [0,2] 宽度 / 2D+params / 非法 bounds) - 验证:197 收集 / 166 passed / 31 skipped / 0 xfail,ruff 0,pyright 0 - docs:STATUS 决策 51 + 3 条待办 + 下一站 random_walk;CHANGELOG;易错点 22/23,第 3 条复发 +1
This commit is contained in:
1 parent
b0c4b4a413
commit
ed1f9f0c53
5 files changed
+207
-37
No files matched your search
+37
-4
@@ -13,13 +13,48 @@ def _normal_batch(rng, size, **kwargs):
|
||||
return rng.normal(0, 1, size)
|
||||
|
||||
|
||||
@pytest.mark.skip(reason=_NOT_IMPLEMENTED)
|
||||
def test_monte_carlo_integral_converges_to_analytic_value():
|
||||
"""∫₀¹ x² dx = 1/3。n=2e5 时误差应 < 0.01。"""
|
||||
from mcm_toolkit.solve import monte_carlo_integral
|
||||
|
||||
r = monte_carlo_integral(lambda X: X[:, 0] ** 2, bounds=[(0, 1)], n=200_000, random_state=0)
|
||||
assert abs(r.data - 1 / 3) < 0.01
|
||||
assert r.success
|
||||
assert abs(r.metrics["mean"] - 1 / 3) < 0.01 # 体积必须是正的
|
||||
assert len(r.data) == 200_000 # data 是 n 个样本各自的贡献
|
||||
|
||||
|
||||
def test_monte_carlo_integral_odd_dimension_sign():
|
||||
"""∫∫∫ x dV over [0,1]³ = 1/2 —— 奇数维最容易暴露"体积符号写反"。"""
|
||||
from mcm_toolkit.solve import monte_carlo_integral
|
||||
|
||||
r = monte_carlo_integral(lambda X: X[:, 0], bounds=[(0, 1)] * 3, n=200_000, random_state=0)
|
||||
assert abs(r.metrics["mean"] - 0.5) < 0.01
|
||||
|
||||
|
||||
def test_monte_carlo_integral_signed_bounds():
|
||||
"""∫₀² x dx = 2 —— 边界带宽度时,体积算错和符号写反都会现形。"""
|
||||
from mcm_toolkit.solve import monte_carlo_integral
|
||||
|
||||
r = monte_carlo_integral(lambda X: X[:, 0], bounds=[(0, 2)], n=200_000, random_state=0)
|
||||
assert abs(r.metrics["mean"] - 2.0) < 0.02
|
||||
|
||||
|
||||
def test_monte_carlo_integral_2d_and_params():
|
||||
from mcm_toolkit.solve import monte_carlo_integral
|
||||
|
||||
bounds = [(0, 1), (0, 1)]
|
||||
r = monte_carlo_integral(lambda X: X[:, 0] * X[:, 1], bounds=bounds, n=200_000, random_state=0)
|
||||
assert abs(r.metrics["mean"] - 0.25) < 0.01
|
||||
assert r.name == "monte_carlo_integral"
|
||||
assert r.params["dimension"] == 2
|
||||
assert r.params["bounds"] == bounds
|
||||
|
||||
|
||||
def test_monte_carlo_integral_rejects_bad_bounds():
|
||||
from mcm_toolkit.solve import monte_carlo_integral
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
monte_carlo_integral(lambda X: X[:, 0], bounds=[(1, 0)], n=100, random_state=0)
|
||||
|
||||
|
||||
def test_monte_carlo_probability_of_standard_normal():
|
||||
@@ -153,7 +188,6 @@ def test_monte_carlo_rejects_bad_arguments():
|
||||
monte_carlo(_normal_batch, lambda x: x, n=0)
|
||||
|
||||
|
||||
|
||||
def test_monte_carlo_probability_returns_documented_metrics():
|
||||
from mcm_toolkit.solve import monte_carlo_probability
|
||||
|
||||
@@ -198,7 +232,6 @@ def test_monte_carlo_probability_higher_confidence_is_wider():
|
||||
assert width(0.99) > width(0.90)
|
||||
|
||||
|
||||
|
||||
def test_monte_carlo_probability_ci_matches_statsmodels_wilson():
|
||||
"""区间必须对得上独立实现(statsmodels 的 wilson)—— `^` 写成异或那次就靠它拦住。"""
|
||||
from statsmodels.stats.proportion import proportion_confint
|
||||
|
||||
Reference in new issue
Block a user