Sign in

    moondoe

    Bounded experimental design, alias analysis and candidate-set optimal design in pure MoonBit

    experimental-design
    factorial
    identifiability
    d-optimal
    Download zip
    Author
    Version
    0.1.0
    License
    MIT
    Last updated
    9 hours ago
    Downloads
    3

    #MoonDOE

    可复用的有限预算试验设计与模型可辨识性工具箱 · pure MoonBit · MIT

    shangwuxi/moondoe@0.1.0 面向试验工程、仿真参数分析和候选集试验计划。 它把「生成点」连接到「哪些效应可估计、如何解混杂、预算内选哪些点、如何导出执行计划」,而不是 A/B 测试或通用优化器。

    #安装

    使用 MoonBit 2026-10-12 工具链(moonc v0.10.15+943464bfa)。新建项目后:

    moon add shangwuxi/moondoe@0.1.0

    在调用包的 moon.pkg 中配置:

    import {
    "shangwuxi/moondoe" @doe,
    }

    本模块只依赖 MoonBit 标准库;没有 FFI、Python/R 运行时或外部数值库。 完整公开签名见根目录 pkg.generated.mbti,运行时可验证的完整示例见 examples/。

    #最小工作流

    在 main 包启用 options("is-main": true),保存以下 main.mbt:

    ///|
    fn main raise {
    let factors = [@doe.factor("temperature", 20.0, 80.0)]
    let candidates = @doe.factorial(factors, [5])
    let model = @doe.terms(factors, 1)
    let chosen = @doe.d_optimal(candidates, model, 2)
    assert_true(@doe.diagnose(chosen.plan, model).estimable)
    println(@doe.plan_csv(chosen.plan))
    }

    Factor.low/high 定义物理量到编码坐标的线性映射:low→−1、high→+1。 所有 Run.point、约束、模型和 CSV 数值均为编码坐标;用 actual_points 显式转换为物理值。 设计点可以超出 [−1,+1](例如 CCD 轴点),within_bounds 报告越界 run ID,不自动截断。

    #三个端到端示例

    从仓库根目录运行;每个示例包含断言,不只是打印:

    moon run examples/screening moon run examples/response moon run examples/candidates

    1. 试验工程师:有符号二水平分式→分辨率 III 和 alias→选定因素 foldover→8 次试验中辨识主效应与交互项→QR 拟合→物理坐标和诊断报告。
    2. 仿真建模作者:15-run Box–Behnken→10 项二次模型→合成响应与重复点扰动→纯误差/失拟拆分→预测、梯度、单位方差轮廓;另检查 CCD 轴点越界。
    3. 参数规划工具作者:25 点网格→线性可行域过滤→4-run D 交换→保护既有候选索引扩增到6次→两区组随机计划→CSV/JSON 双向校验。

    合成响应仅用于验证算法闭环,不是实际实验结果;例子不声称优化物理工艺。

    #能力索引

    阶段API / 文件行为
    数据边界factor, plan, coded_plan, physical_plan有限值、维度、唯一 ID、复制隔离
    规则设计factorial, two_level, fraction混合水平全因子;有符号二水平生成元
    混杂分析defining_relation, resolution, aliases, effect_nameXOR 定义群、最短非单位词、带符号效应别名
    设计扩增foldover, replicate, add_centers保留区组和来源、生成新的执行 ID
    响应面central_composite, box_behnken, termsCCD/BBD;显式0/1/2阶单项式
    线性代数matrix_rank, information, inverse, log_determinant列均衡秩、加权信息、行缩放求逆、SPD Cholesky
    模型验证least_squares, fit_plan, diagnose, alias_matrix列主元两遍 MGS QR;可估计性和遗漏项投影
    预测predict, gradient, covariance, leverage, variance_profile编码坐标导数和线性模型不确定性
    有限选点d_optimal, augment_optimal, refine_selection秩递增种子、贪心补齐、有限轮单点交换、锁定前缀
    可行性/执行filter_candidates, filter_points, unique_points, randomize, balanced_blocks线性约束、隔离谓词、精确去重、可复现洗牌
    残差拆分partition_error, standardized_residuals区组敏感重复组、纯误差/失拟 SS 和自由度
    交换格式plan_csv, plan_from_csv, plan_json, plan_from_json, diagnostics_json受限文本;严格字段;moondoe/1 模式

    #数值与资源边界

    • 1–16 factors,1–4096 runs;名称/ID 不允许重复;有限数绝对值≤1e100。
    • 矩阵输入≤4096行×128列,QR≤64列、行数≥列数;不返回秩亏拟合的伪逆。
    • 候选交换≤256候选、≤16模型项、模型项数≤选择数≤64、1–16轮;估算分解工作≤1亿,超额抛出 Budget。
    • 默认相对阈值1e-10;可配置范围1e-14..0.01。不同数值例程的阈值含义不同,详见 docs/numerics.md。
    • 输入 CSV/JSON≤200万 UTF-16 单元;CSV字段≤4096单元、≤18列、≤4097行;JSON嵌套≤8。
    • 程序验证结构和资源上限;不承诺实时执行,多个校验为二次复杂度。

    DesignError 区分 Invalid(非法输入/数值范围)、Budget(资源上限)和 Singular(模型不可辨识/求逆失败)。 公开结构的数组可由调用方修改;构造/变换复制数组,并在进入核心操作时重新验证。不要在操作期间并发改写输入。

    D-optimal 是候选集上的局部交换启发式,不保证全局最优;converged=false 表示轮数耗尽,true仅表示完整一轮未发现超过阈值的单点改善。 不含连续坐标交换、重复候选抽样、分类因素、混合物设计、Plackett–Burman、p值、置信区间、贝叶斯/因果推断、仪器控制或安全关键决策。

    #复现检查

    moon info && moon fmt moon fmt --check moon check --deny-warn moon test --deny-warn moon build --deny-warn bash scripts/verify.sh wasm-gc bash scripts/verify.sh wasm bash scripts/verify.sh js CC=gcc bash scripts/verify.sh native python scripts/audit.py

    CI 在 Ubuntu 24.04 用同一官方快照执行四目标的检查、测试、构建及三个示例,检查接口漂移。 安装脚本用官方对象 ETag 固定快照,ETag不是独立签名;对象变化时失败而不自动升级。 Windows 本地不具备 C 编译器时,native 运行以真实 CI 结果为证,不伪称本机通过。

    #验证、来源和邻近项目

    目前38个具名测试覆盖设计/拟合/执行/格式路径,含枚举52个有符号单生成元设计、126个小网格4选组合的独立行列式校验、解析加权解、尺度/奇异/极端计数以及49个随机种子。 这些是自编数学断言,不是与 R/Python 的自动差分测试,也没有性能优势声明。 生产 MoonBit 20个文件共2219物理行(排除测试、示例、生成接口),可用 scripts/audit.py 复核。

    moonbit_extractor 提供提取工程中的 factorial、随机化和回归,属于高度相邻项目。 MoonDOE 的独立价值是领域中立的有符号定义关系、别名/秩诊断、响应面设计以及锁定既有试验的预算选点;全因子/随机化本身不是创新声明。 moon-experiment 面向 A/B 检验,不能当作本项目的 DOE 替代。 检索范围和限制见 docs/competition/duplicate-check.md;不宣称绝对唯一。

    原始实现与测试由本项目编写,未移植上述项目代码。MIT;标准库许可和概念性对标见 ATTRIBUTION.md;AI参与说明见 AI-USE.md。

    DesignError

    pub suberror DesignError {
    Invalid(String)
    Budget(String)
    Singular(String)
    } derive(Eq,
    Debug
    )

    DesignError::equal

    fn DesignError::equal(DesignError, DesignError) -> Bool

    DesignError::not_equal

    fn DesignError::not_equal(x : DesignError, y : DesignError) -> Bool

    AliasPair

    pub(all) struct AliasPair {
    left : String
    right : String
    correlation : Double
    } derive(Eq,
    Debug
    )

    AliasPair::equal

    fn AliasPair::equal(AliasPair, AliasPair) -> Bool

    AliasPair::not_equal

    fn AliasPair::not_equal(x : AliasPair, y : AliasPair) -> Bool

    DefiningWord

    pub(all) struct DefiningWord {
    mask : Int
    sign : Int
    } derive(Eq,
    Debug
    )

    DefiningWord::equal

    DefiningWord::not_equal

    fn DefiningWord::not_equal(x : DefiningWord, y : DefiningWord) -> Bool

    Diagnostics

    pub(all) struct Diagnostics {
    runs : Int
    terms : Int
    rank : Int
    residual_dof : Int
    estimable : Bool
    zero_columns : Array[String]
    exact_aliases : Array[AliasPair]
    max_abs_correlation : Double
    log_determinant : Double?
    } derive(Eq,
    Debug
    )

    Diagnostics::equal

    fn Diagnostics::equal(Diagnostics, Diagnostics) -> Bool

    Diagnostics::not_equal

    fn Diagnostics::not_equal(x : Diagnostics, y : Diagnostics) -> Bool

    ErrorPartition

    pub(all) struct ErrorPartition {
    residual_sse : Double
    pure_error_sse : Double
    lack_of_fit_sse : Double
    pure_error_dof : Int
    lack_of_fit_dof : Int
    f_ratio : Double?
    groups : Int
    } derive(Eq,
    Debug
    )

    ErrorPartition::equal

    ErrorPartition::not_equal

    fn ErrorPartition::not_equal(x : ErrorPartition, y : ErrorPartition) -> Bool

    Factor

    pub(all) struct Factor {
    name : String
    low : Double
    high : Double
    } derive(Eq,
    Debug
    )

    Factor::equal

    fn Factor::equal(Factor, Factor) -> Bool

    Factor::not_equal

    fn Factor::not_equal(x : Factor, y : Factor) -> Bool

    Factor::to_repr

    Fit

    pub(all) struct Fit {
    coefficients : Array[Double]
    fitted : Array[Double]
    residuals : Array[Double]
    sse : Double
    dof : Int
    variance : Double?
    } derive(Eq,
    Debug
    )

    Fit::equal

    fn Fit::equal(Fit, Fit) -> Bool

    Fit::not_equal

    fn Fit::not_equal(x : Fit, y : Fit) -> Bool

    Fit::to_repr

    Generator

    pub(all) struct Generator {
    mask : Int
    sign : Int
    } derive(Eq,
    Debug
    )

    Generator::equal

    fn Generator::equal(Generator, Generator) -> Bool

    Generator::not_equal

    fn Generator::not_equal(x : Generator, y : Generator) -> Bool

    LinearConstraint

    pub(all) struct LinearConstraint {
    name : String
    coefficients : Array[Double]
    upper : Double
    } derive(Eq,
    Debug
    )

    LinearConstraint::equal

    LinearConstraint::not_equal

    fn LinearConstraint::not_equal(x : LinearConstraint, y : LinearConstraint) -> Bool

    OptimalResult

    pub(all) struct OptimalResult {
    plan : Plan
    indices : Array[Int]
    initial_logdet : Double
    final_logdet : Double
    improvements : Array[Double]
    exchanges : Int
    converged : Bool
    } derive(Eq,
    Debug
    )

    OptimalResult::equal

    OptimalResult::not_equal

    fn OptimalResult::not_equal(x : OptimalResult, y : OptimalResult) -> Bool

    Plan

    pub(all) struct Plan {
    factors : Array[Factor]
    runs : Array[Run]
    } derive(Eq,
    Debug
    )

    Plan::equal

    fn Plan::equal(Plan, Plan) -> Bool

    Plan::not_equal

    fn Plan::not_equal(x : Plan, y : Plan) -> Bool

    Plan::to_repr

    Run

    pub(all) struct Run {
    id : String
    block : Int
    point : Array[Double]
    } derive(Eq,
    Debug
    )

    Run::equal

    fn Run::equal(Run, Run) -> Bool

    Run::not_equal

    fn Run::not_equal(x : Run, y : Run) -> Bool

    Run::to_repr

    Term

    pub(all) struct Term {
    name : String
    powers : Array[Int]
    } derive(Eq,
    Debug
    )

    Term::equal

    fn Term::equal(Term, Term) -> Bool

    Term::not_equal

    fn Term::not_equal(x : Term, y : Term) -> Bool

    Term::to_repr

    actual_points

    fn actual_points(p : Plan) -> Array[Array[Double]] raise DesignError

    add_centers

    fn add_centers(p : Plan, count : Int, block? : Int) -> Plan raise DesignError

    alias_matrix

    fn alias_matrix(fitted : Array[Array[Double]], omitted : Array[Array[Double]], tol? : Double) -> Array[Array[Double]] raise DesignError

    aliases

    fn aliases(effect : Int, base : Int, generators : Array[Generator]) -> Array[DefiningWord] raise DesignError

    augment_optimal

    fn augment_optimal(candidates : Plan, model : Array[Term], fixed_indices : Array[Int], total_runs : Int, passes? : Int) -> OptimalResult raise DesignError

    balanced_blocks

    fn balanced_blocks(p : Plan, count : Int, seed : Int) -> Plan raise DesignError

    block_counts

    fn block_counts(p : Plan) -> Array[(Int, Int)] raise DesignError

    box_behnken

    fn box_behnken(factors : Array[Factor], centers? : Int) -> Plan raise DesignError

    central_composite

    fn central_composite(factors : Array[Factor], alpha : Double, centers? : Int) -> Plan raise DesignError

    coded_plan

    fn coded_plan(factors : Array[Factor], points : Array[Array[Double]]) -> Plan raise DesignError

    covariance

    fn covariance(a : Array[Array[Double]], variance : Double, weights? : Array[Double]) -> Array[Array[Double]] raise DesignError

    csv_records

    fn csv_records(text : String) -> Array[Array[String]] raise DesignError

    d_optimal

    fn d_optimal(candidates : Plan, model : Array[Term], count : Int, passes? : Int) -> OptimalResult raise DesignError

    decode

    fn decode(f : Factor, coded : Double) -> Double raise DesignError

    defining_relation

    fn defining_relation(base : Int, generators : Array[Generator]) -> Array[DefiningWord] raise DesignError

    design_matrix

    fn design_matrix(p : Plan, model : Array[Term]) -> Array[Array[Double]] raise DesignError

    diagnose

    fn diagnose(p : Plan, model : Array[Term], tol? : Double) -> Diagnostics raise DesignError

    diagnostics_json

    fn diagnostics_json(p : Plan, model : Array[Term]) -> String raise DesignError

    effect_name

    fn effect_name(mask : Int, names : Array[String]) -> String raise DesignError

    encode

    fn encode(f : Factor, actual : Double) -> Double raise DesignError

    evaluate_terms

    fn evaluate_terms(point : Array[Double], model : Array[Term]) -> Array[Double] raise DesignError

    factor

    fn factor(name : String, low : Double, high : Double) -> Factor raise DesignError

    factorial

    fn factorial(factors : Array[Factor], levels : Array[Int], centers? : Int) -> Plan raise DesignError

    filter_candidates

    fn filter_candidates(p : Plan, constraints : Array[LinearConstraint], tol? : Double) -> Plan raise DesignError

    filter_points

    fn filter_points(p : Plan, predicate : (Array[Double]) -> Bool) -> Plan raise DesignError

    fit_plan

    fn fit_plan(p : Plan, model : Array[Term], responses : Array[Double]) -> Fit raise DesignError

    foldover

    fn foldover(p : Plan, mask : Int, include_original? : Bool) -> Plan raise DesignError

    fraction

    fn fraction(factors : Array[Factor], base : Int, generators : Array[Generator]) -> Plan raise DesignError

    gradient

    fn gradient(coefficients : Array[Double], model : Array[Term], point : Array[Double]) -> Array[Double] raise DesignError

    information

    fn information(a : Array[Array[Double]], weights? : Array[Double]) -> Array[Array[Double]] raise DesignError

    inverse

    fn inverse(a : Array[Array[Double]], tol? : Double) -> Array[Array[Double]] raise DesignError

    least_squares

    fn least_squares(a : Array[Array[Double]], responses : Array[Double], weights? : Array[Double], tol? : Double) -> Fit raise DesignError

    leverage

    fn leverage(a : Array[Array[Double]]) -> Array[Double] raise DesignError

    log_determinant

    fn log_determinant(a : Array[Array[Double]], tol? : Double) -> Double? raise DesignError

    matrix_rank

    fn matrix_rank(a : Array[Array[Double]], tol? : Double) -> Int raise DesignError

    multiply

    fn multiply(a : Array[Array[Double]], b : Array[Array[Double]]) -> Array[Array[Double]] raise DesignError

    partition_error

    fn partition_error(p : Plan, model : Array[Term], responses : Array[Double], separate_blocks? : Bool) -> ErrorPartition raise DesignError

    physical_plan

    fn physical_plan(factors : Array[Factor], points : Array[Array[Double]]) -> Plan raise DesignError

    plan

    fn plan(factors : Array[Factor], runs : Array[Run]) -> Plan raise DesignError

    plan_csv

    fn plan_csv(p : Plan) -> String raise DesignError

    plan_from_csv

    fn plan_from_csv(text : String, factors : Array[Factor]) -> Plan raise DesignError

    plan_from_json

    fn plan_from_json(text : String) -> Plan raise DesignError

    plan_json

    fn plan_json(p : Plan) -> String raise DesignError

    predict

    fn predict(coefficients : Array[Double], model : Array[Term], point : Array[Double]) -> Double raise DesignError

    prediction_variance

    fn prediction_variance(row : Array[Double], covariance : Array[Array[Double]]) -> Double raise DesignError

    randomize

    fn randomize(p : Plan, seed : Int, within_blocks? : Bool) -> Plan raise DesignError

    refine_selection

    fn refine_selection(candidates : Plan, model : Array[Term], initial : Array[Int], locked_prefix? : Int, passes? : Int) -> OptimalResult raise DesignError

    replicate

    fn replicate(p : Plan, copies : Int) -> Plan raise DesignError

    resolution

    fn resolution(base : Int, generators : Array[Generator]) -> Int? raise DesignError

    standardized_residuals

    fn standardized_residuals(a : Array[Array[Double]], fit : Fit) -> Array[Double?] raise DesignError

    terms

    fn terms(factors : Array[Factor], order : Int) -> Array[Term] raise DesignError

    transpose

    fn transpose(a : Array[Array[Double]]) -> Array[Array[Double]] raise DesignError

    two_level

    fn two_level(factors : Array[Factor], centers? : Int) -> Plan raise DesignError

    unique_points

    fn unique_points(p : Plan) -> Plan raise DesignError

    validate_plan

    fn validate_plan(p : Plan) -> Unit raise DesignError

    variance_profile

    fn variance_profile(p : Plan, model : Array[Term], points : Array[Array[Double]]) -> Array[Double] raise DesignError

    within_bounds

    fn within_bounds(p : Plan) -> Array[String] raise DesignError