Files
MCM-ICM_Toolkit/tests/test_solve.py
T
guzhujushi 5319589dfd chore: 初始化 MCM/ICM Toolkit 仓库骨架
审查并精简 ChatGPT 的建库建议后落地的第一版骨架,只定接口不写实现。

- 建议审查:14 个包 → 7 个;约 250 个函数 → 约 40 个;5 个 Result 类 → 1 个
  (docs/01-suggestion-review.md)
- docs/:架构、路线图(含永久不做清单)、环境、Git 工作流、函数卡片模板
- src/mcm_toolkit/:core / data / stats / models / solve / decision / viz
  共 23 个模块,均为签名 + docstring + NotImplementedError
- tests/:9 个文件,其中 test_api_surface.py 已通过(20 passed)
- examples/ problems/ notebooks/ figures/ tables/ 骨架
- pyproject.toml(核心依赖 4 个 + 6 组 extras)、environment.yml
- scripts/:setup-venv.ps1(ASCII + LF)、setup-conda.ps1、doctor.ps1
- 环境:.venv(system-site-packages)与 conda 环境 mcm-toolkit 均已建好,
  数值栈版本与 base 完全对齐(numpy 2.4.6 / scipy 1.18.1 / pandas 3.0.6,MKL 后端)
2026-10-01 17:43:48 +08:00

86 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""solve 包测试。"""
from __future__ import annotations
import numpy as np
import pytest
pytestmark = pytest.mark.skip(reason="未实现:见 docs/03-roadmap.md L0/L1")
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
def test_monte_carlo_probability_of_standard_normal():
"""P(Z > 0) = 0.5,n=5000 时误差应 < 0.05。"""
from mcm_toolkit.solve import monte_carlo_probability
r = monte_carlo_probability(
lambda z: z > 0,
lambda rng, **kw: rng.standard_normal(),
n=5000,
random_state=0,
)
assert abs(r.metrics["probability"] - 0.5) < 0.05
def test_monte_carlo_is_reproducible():
from mcm_toolkit.solve import monte_carlo_probability
args = (lambda z: z > 0, lambda rng, **kw: rng.standard_normal())
a = monte_carlo_probability(*args, n=1000, random_state=9)
b = monte_carlo_probability(*args, n=1000, random_state=9)
assert a.metrics["probability"] == b.metrics["probability"]
def test_markov_steady_state_two_state_chain():
"""P=[[0.9,0.1],[0.2,0.8]] 的平稳分布是 [2/3, 1/3]。"""
from mcm_toolkit.solve import markov_steady_state
r = markov_steady_state(np.array([[0.9, 0.1], [0.2, 0.8]]))
assert np.allclose(r.data, [2 / 3, 1 / 3], atol=1e-6)
def test_knapsack_dp_known_optimum():
from mcm_toolkit.solve import knapsack_dp
r = knapsack_dp(weights=[1, 3, 4, 5], values=[1, 4, 5, 7], capacity=7)
assert np.isclose(r.metrics["total_value"], 9.0)
assert np.isclose(r.metrics["total_weight"], 7.0)
def test_linear_program_basic():
from mcm_toolkit.solve import linear_program
r = linear_program(c=[1, 2], A_ub=[[1, 1]], b_ub=[4], bounds=[(0, None)] * 2)
assert r.success
assert np.isclose(r.metrics["objective"], 4.0)
def test_mm1_metrics_closed_form():
from mcm_toolkit.solve import mm1_metrics
r = mm1_metrics(arrival_rate=2, service_rate=3)
assert np.isclose(r.metrics["rho"], 2 / 3, rtol=1e-6)
assert np.isclose(r.metrics["L"], 2.0, rtol=1e-6)
def test_mm1_rejects_unstable_system():
"""λ >= μ 时系统不稳定,应 success=False 而不是返回 inf。"""
from mcm_toolkit.solve import mm1_metrics
assert mm1_metrics(arrival_rate=3, service_rate=3).success is False
def test_simulated_annealing_finds_quadratic_minimum():
from mcm_toolkit.solve import simulated_annealing
f = lambda v: (v[0] - 3.0) ** 2 + (v[1] + 1.0) ** 2 # noqa: E731
r = simulated_annealing(f, x0=[0.0, 0.0], n_iter=5000, random_state=0)
assert np.allclose(r.params["x"], [3.0, -1.0], atol=0.1)