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 后端)
This commit is contained in:
guzhujushi committed 2026-10-01 17:43:48 +08:00
commit 5319589dfd
76 files changed
+6812

No files matched your search

+136
View File
@@ -0,0 +1,136 @@
#Requires -Version 5.1
<#
.SYNOPSIS
Create the conda environment "mcm-toolkit".
.DESCRIPTION
Three ways to build the environment, in order of preference:
(default) explicit package list, installed from the "defaults" channel.
Needs internet. Measured on this machine: ~14.5 min, ~3 GB download.
-FromYml same, but driven by environment.yml (better for reproducing later).
-CloneBase mirrors the whole base environment. NOTE: on conda 25.11 this is NOT
a fast local copy -- conda replays base's full package list and
downloads/installs it. Use it only when you want an exact copy of base.
To work offline later, build the environment BEFORE the contest and keep the
conda package cache (D:\anaconda\pkgs) intact.
NOTE: this file is intentionally pure ASCII, UTF-8 without BOM, LF endings.
Windows PowerShell 5.1 parses .ps1 as ANSI when there is no BOM, so non-ASCII
characters (e.g. Chinese) turn into illegal bytes and cause syntax errors.
.PARAMETER Name
conda environment name. Default: mcm-toolkit.
.PARAMETER FromYml
Build from environment.yml instead of the inline package list.
.PARAMETER CloneBase
Clone the base environment instead of installing a explicit package list.
.PARAMETER Force
Remove and recreate the environment if it already exists.
.EXAMPLE
.\scripts\setup-conda.ps1
Create "mcm-toolkit" with the science stack (needs internet).
.EXAMPLE
.\scripts\setup-conda.ps1 -FromYml -Force
Rebuild from environment.yml.
#>
[CmdletBinding()]
param(
[string]$Name = 'mcm-toolkit',
[switch]$FromYml,
[switch]$CloneBase,
[switch]$Force
)
$ErrorActionPreference = 'Stop'
$repoRoot = Split-Path -Parent $PSScriptRoot
# Packages required by pyproject.toml's core deps plus the [ml] / [graph] /
# [symbolic] / [excel] / [dev] extras. SALib, pymoo and pyright are pip-only
# (see install after the conda step).
$packages = @(
'python=3.13',
'numpy', 'scipy', 'pandas', 'matplotlib',
'scikit-learn', 'statsmodels',
'networkx', 'sympy', 'openpyxl',
'pytest', 'ruff',
'pip'
)
$pipOnly = @('SALib', 'pymoo', 'pyright')
function Find-Conda {
$candidates = @(
"$env:USERPROFILE\anaconda3\Scripts\conda.exe",
"$env:USERPROFILE\miniconda3\Scripts\conda.exe",
'D:\anaconda\Scripts\conda.exe',
'C:\ProgramData\Anaconda3\Scripts\conda.exe',
'C:\ProgramData\miniconda3\Scripts\conda.exe'
)
foreach ($c in $candidates) { if (Test-Path -LiteralPath $c) { return $c } }
$onPath = Get-Command conda -ErrorAction SilentlyContinue
if ($onPath) { return $onPath.Source }
throw 'conda not found. Install Anaconda/Miniconda first.'
}
$conda = Find-Conda
Write-Host "[1/5] conda = $conda"
# PITFALL: the Anaconda 25.x ToS plugin fetches channel metadata from
# repo.anaconda.com before every create/install and crashes when offline.
# This env var auto-accepts the ToS: it skips the network call while keeping
# the libmamba solver (unlike --no-plugins, which disables all plugins).
$env:CONDA_PLUGINS_AUTO_ACCEPT_TOS = 'yes'
$env:CONDA_AUTO_UPDATE_CONDA = 'false'
# PITFALL: envs_dirs and pkgs_dirs must be writable, otherwise conda fails with
# NotWritableError or "Error encountered while attempting to create cache directory".
Write-Host '[2/5] current envs_dirs / pkgs_dirs:'
& $conda config --show envs_dirs pkgs_dirs 2>$null | ForEach-Object { Write-Host " $_" }
$existing = (& $conda env list --json | ConvertFrom-Json).envs |
Where-Object { (Split-Path -Leaf $_) -eq $Name }
if ($existing) {
if (-not $Force) {
Write-Host "Environment '$Name' already exists ($existing). Use -Force to rebuild." -ForegroundColor Yellow
exit 0
}
Write-Host "Environment '$Name' exists, -Force given, removing first ..."
& $conda env remove -n $Name -y
}
Write-Host '[3/5] creating the environment (this can take 10-20 minutes) ...'
$sw = [Diagnostics.Stopwatch]::StartNew()
if ($FromYml) {
$yml = Join-Path $repoRoot 'environment.yml'
if (-not (Test-Path -LiteralPath $yml)) { throw "Not found: $yml" }
& $conda env create -n $Name -f $yml
} elseif ($CloneBase) {
& $conda create -n $Name --clone base -y
} else {
& $conda create -n $Name -y @packages
}
if ($LASTEXITCODE -ne 0) { throw "conda create failed (exit code $LASTEXITCODE)" }
Write-Host (" done in {0:N0}s" -f $sw.Elapsed.TotalSeconds)
$envPy = Join-Path (Split-Path -Parent (Split-Path -Parent $conda)) "envs\$Name\python.exe"
if (-not (Test-Path -LiteralPath $envPy)) {
$envsRoot = (& $conda config --show envs_dirs | Select-String -Pattern '\S' | Select-Object -First 1).ToString().Trim()
$envPy = Join-Path $envsRoot "$Name\python.exe"
}
Write-Host '[4/5] installing pip-only extras (SALib, pymoo, pyright) + this project ...'
& $envPy -m pip install --disable-pip-version-check --no-warn-script-location -q @pipOnly
& $envPy -m pip install -e $repoRoot --no-deps --no-build-isolation --disable-pip-version-check -q
Write-Host '[5/5] verifying ...'
& $envPy -c "import numpy, scipy, pandas, matplotlib, sklearn, statsmodels, networkx, sympy, SALib, pymoo, mcm_toolkit; print(' numpy', numpy.__version__, '| pandas', pandas.__version__, '| sklearn', sklearn.__version__); print(' mcm_toolkit', mcm_toolkit.__version__)"
Write-Host ''
Write-Host 'Done. Activate with:' -ForegroundColor Green
Write-Host " conda activate $Name"