moonaqueousspec

    Joint sample-handling history reconciliation and zero-net-transfer checks for shared-source Ca-carbonate-Na-Cl water aliquots

    chemistry
    geochemistry
    aliquot
    sample-handling
    alkalinity
    moonbit
    Download zip
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    8 days ago
    Downloads
    20

    No dependencies

    #MoonAqueousSpec:同源分样处理历史核对与零净转移检验

    核对同一原水分样后的检测值,检验它们能否来自同一个处理历史。 面向 Ca–碳酸盐–Na–Cl–水的有限、显式模型:样瓶分配、稀释/蒸发、CO₂ 净转移、方解石净转移和带 Na/Cl 反离子的加酸/加碱。检测值绑定到实际样瓶,原水和上游剂量在所有后代中保持同一个未知量。

    例如:A、B 两瓶分别都能解释,不代表能来自同一原水;体积校正后 TA 没变,不代表没有等量加酸/加碱。程序同时核对 Ca、DIC、TA、Na、Cl,输出一段共同可行历史,或可用原始检测约束复算的矛盾;证据不足和计算资源不足各有明确结果。

    主要贡献落实在跨样瓶的共同原水/处理约束,以及“指定处理步骤净转移为零”的解释检验。质量守恒、碳酸盐计量、精确分数、Fourier–Motzkin、Farkas 证书均为已有基础。当前公开源码审查尚未确认完整同职责实现;不声称全球唯一、零相似或赛事免判重,见 近邻与贡献边界。

    #核心职责与可复核证据

    目标用户是核对受控水样配制、分样与处理记录的人。核心问题是:多个实际样瓶的检测结果,能否由同一原水和同一组处理参数共同解释?若指定步骤的净转移全为零,现有检测是否仍允许这样的历史?

    核心职责实现与证据
    实际样瓶谱系与体积分配lineage.mbt 记录父子状态,检查兄弟分样总体积及处理顺序。
    跨瓶共享原水与上游剂量同一次上游未知处理在所有后代中保持同一个变量;联合测试 覆盖各瓶独立可行但共同冲突。
    检测绑定具体样瓶联合使用 Ca/DIC/TA/Na/Cl 检测区间与实际体积,不把 pH 当作可加检测量。
    基线后的联合零净转移检验claims.mbt 先检查共同历史,再检验所选步骤是否能同时为零;反例 展示增加检测后结论变化。
    可复核输出和明确未决reconcile.mbt 返回共同历史或原始约束的矛盾证书;独立验证器 重算,超预算返回 ResourceLimit。

    这五项构成当前专用工作流的差异化重点;每项所用的化学与数学基础均有先例,组合也没有被证明绝对独有。

    #安装 MoonBit 库

    Mooncakes 包名为 alicedhaha/moonaqueousspec:

    moon add alicedhaha/moonaqueousspec

    在使用方的 moon.pkg 中导入 alicedhaha/moonaqueousspec,即可调用下文列出的根包 API。文件命令行示例需要检出本仓库后运行。

    #先运行三个核心反例

    需要 MoonBit 和 Python 3.9+。Python 适配器只做 JSON 文件读写;全部判断在 MoonBit 主库中执行。已有项目本地 .moon 时自动使用它,否则使用 PATH 的 moon。

    python3 scripts/aliquots.py reconcile --input examples/aliquots/common-source-conflict.json python3 scripts/aliquots.py challenge --input examples/aliquots/masked-acid-base.claim.json python3 scripts/aliquots.py challenge --input examples/aliquots/mineral-acid.claim.json

    核心反例实际判断增加了什么判断能力
    同源分瓶冲突完整输入为 Conflict;分别保留单瓶检测时各为 Compatible阻止把各瓶独立选择的原水值拼成不存在的共同历史。
    酸碱效应在 TA 上抵消完整输入为 ZeroTransferRuledOut;删去 Na/Cl 后为 ZeroTransferPossible显示反离子检测能排除 TA 单独无法排除的解释。
    方解石/酸效应在 TA 上抵消Ca/Cl 证据排除“矿物和酸都为零”;CO₂ 为零仍可行区分明确的净计量解释;不从 SI 推断沉淀,也不把联合排除解释为每一步必然非零。

    完整输入的单次运行只产生表中的完整输入结果。下述独立验证命令会实际构造单瓶子例、删去 Na/Cl 或 Ca/Cl 的对照,以及单独 CO₂ 零转移假设,并逐条复算结果:

    python3 scripts/verify_aliquots.py

    另外两个例子展示共享上游剂量和证据不足的边界:

    python3 scripts/aliquots.py reconcile --input examples/aliquots/acidified-split.json python3 scripts/aliquots.py challenge --input examples/aliquots/underdetermined-gas.claim.json

    前者返回共享原水与酸剂量的一段 Compatible 历史;后者返回 ZeroTransferPossible,保留零气体净转移解释。以上均为合成案例,无实测水样或实验准确性主张。详见 场景与对照。

    #与近邻的具体边界

    相关项目承认的共同基础当前主任务的区别
    moonbit-biogeochemDIC、TA、碳酸盐和 CO₂所查源码为海洋箱模型与气海交换;当前处理样瓶谱系、共享上游量和跨瓶检测的共同历史。
    moonkinetics化学计量与守恒所查项目演化反应网络;当前检验有限处理记录与检测是否相容。
    membrane物料网络、并联流与可行设计当前输入是分样及检测,不进行膜分离工艺设计。
    moonopt可行性与 Farkas 不可行核验当前只接受有限水样处理模型,证书方法本身不是新增贡献。
    moonbit-vle、moonbit_extractor活度、平衡、物料衡算当前主任务不求相平衡或萃取;保留平衡支持包仍有领域交集。

    对化工报告、分数库和一般约束求解器的交集也已列入 贡献与近邻说明。截至 2026-10-27 17:36(北京时间)的 公开发布包审查 尚未确认完整同职责实现;这不是其他项目都没有该能力的证明,也不是赛事判定。全量筛查、重点人工读源和覆盖缺口分别记录,不能把扫描数量解释为原创性证书。

    #API 与状态

    根包仅提供 reconcile_aliquots、challenge_zero_transfer、replay_handling 及对应 JSON 函数。公开类型和准确签名在 生成接口。

    • Compatible:存在一段同时满足所有包含端点的检测范围的共同历史,不代表历史唯一或真实发生。
    • Conflict:声明模型下不存在共同历史;返回原始约束的非负权重,精确合并得到 0 <= 负数。
    • ZeroTransferPossible / ZeroTransferRuledOut:一组指定步骤可以/不可以同时净转移为零;后一状态只说明其中至少一项非零。
    • BaseConflict:未加零转移假设的基线已经矛盾,不据此推断过程必然发生。
    • ResourceLimit:计算未决,不能解释为可行、冲突或通过核验。

    文件适配器退出码:有效完成的分析为 0(包括 Conflict,需读取状态);模型拒绝为 1;文件/运行失败为 2;资源不足未决为 3。--output FILE 保存完整 JSON。回放接收 {"study": ..., "parameters": [...]},用 replay 命令检查指定历史。

    #验证与复查

    export MOON_HOME="$PWD/.moon" # 系统工具链使用者跳过这两行 export PATH="$MOON_HOME/bin:$PATH" moon check --deny-warn moon test --deny-warn python3 scripts/verify_aliquots.py python3 scripts/generate_aliquot_examples.py --check python3 scripts/verify_local.py

    独立验证器使用 Python Fraction 直接计算各瓶物质量,从单位基向量重建输入约束,并用高斯消元/有界多面体顶点枚举独立判定最多三个未知量的案例;它不调用 MoonBit 的仿射编译或消元实现。共同历史逐瓶核对,矛盾逐约束复算;另做体积、计量系数、反离子、样瓶身份、权重与截断输出的错误注入。资源上限另由 MoonBit 测试验证。报告位于 audit/differentiation/verification/aliquots/report.json。

    每个可独立审查的功能批次完成后都刷新 Mooncakes 在线清单、重新读取发布包并人工复核近邻,记录在 逐批证据。哈希和扫描数量只说明检查范围,不能证明没有语义等价实现。

    #有限模型与职责边界

    只接受 Ca–碳酸盐–Na–Cl–水;须声明全部离子、体积和可能过程。源样强离子/碱度关系为 2 Ca + Na - Cl - TA = 0。输入使用整数 µL、nmol/L、neq/L 和 nmol,输出精确分数;pH 不作为可加分析量。未知 JSON 字段拒绝。最多 16 步、32 个检测范围和 10 个不确定量;消元预算超出即未决。方程、符号和边界见 模型、输入契约 和 单位。

    根包不提供通用水相物种分配、任意电解质平衡、相平衡 flash、一般反应网络 ODE/SSA/CME、沉淀动力学或通用 LP/SMT/任意矩阵优化 API。当前模型也未提供盐水/天然水的完整组分、未知体积、误差概率、最优实验设计或真实反应归因。方解石和 CO₂ 的值是声明的净转移,不是自动求出的沉淀量或气体平衡量。未知过程可以使结论失效。

    早期物种分配、活度、矿物 SI、敏感性与 PHREEQC 数据核验保存在 equilibrium/ 独立支持包;根包及默认 CLI 不依赖它。旧工作流使用 scripts/aqueous.py 或 moon run equilibrium/cmd/main,见 支持包职责说明 与 操作指南。这些保留功能仍与既有科学软件及 Mooncakes 项目有交集,不能通过移动目录消除其先例。

    代码 Apache-2.0。支持包的 PHREEQC 数据保留 第三方许可。申报草稿 需要本人改写和审核;本地验证不代表公开发布、报名、提交或评审通过。

    #项目结构与申报范围

    路径职责
    lineage.mbt、reconcile.mbt、claims.mbt当前主任务:处理谱系、共同历史与联合零净转移检验。
    cmd/main/、scripts/aliquots.py默认 MoonBit 入口与文件适配器。
    examples/aliquots/、docs/scenarios.md当前主任务的五个合成场景及对照说明。
    equilibrium/、scripts/aqueous.py独立保留的水相平衡支持功能,有自己的入口和已知先例。
    docs/equilibrium-*.md、根目录早期规划书支持包文档与历史规划,不作为主任务新增承诺。

    申报草稿 以根包的样品处理历史核对为核心交付,主动披露支持包和近邻。保留支持包仍属于仓库,参赛范围说明不能替代组委会对完整提交内容的审查。

    AliquotAssessment

    pub(all) struct AliquotAssessment {
    status : String
    history : HandlingHistory?
    conflict : Array[ConflictTerm]
    parameter_count : Int
    constraint_count : Int
    diagnostics : Array[String]
    } derive(ToJson,
    Debug
    )

    Compatible includes one joint history. Conflict includes a checkable linear contradiction. ResourceLimit is undecided and never means compatible.

    AliquotAssessment::to_json

    AliquotStudy

    pub(all) struct AliquotStudy {
    schema : String
    source : SourceWater
    steps : Array[HandlingStep]
    assays : Array[BottleAssay]
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    BottleAssay

    pub(all) struct BottleAssay {
    id : String
    node : String
    analyte : String
    bounds : Bounds
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    An assay at its actual preparation state. analyte is Ca, DIC, TA, Na or Cl. It is never silently attached to the original bottle; pH is not additive.

    BottleAssay::to_json

    fn BottleAssay::to_json(BottleAssay) -> Json

    Bounds

    pub(all) struct Bounds {
    lower : Int
    upper : Int
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    Integer nanomolar bounds; TA uses nanoequivalents/L. All are inclusive.

    Bounds::to_json

    fn Bounds::to_json(Bounds) -> Json

    Bounds::to_repr

    ClaimAssessment

    pub(all) struct ClaimAssessment {
    status : String
    zero_steps : Array[String]
    base : AliquotAssessment
    assumed_zero : AliquotAssessment?
    diagnostics : Array[String]
    } derive(ToJson,
    Debug
    )

    ClaimAssessment::to_json

    ConflictTerm

    pub(all) struct ConflictTerm {
    constraint : String
    weight : Exact
    } derive(ToJson,
    Debug
    )

    Nonnegative multipliers of input-derived chemical constraints. Their exact combination is 0 <= a negative number, so the declared study has no history.

    ConflictTerm::to_json

    Exact

    pub(all) struct Exact {
    numerator : String
    denominator : String
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    Exact rational output avoids rounding an assay boundary into agreement.

    Exact::to_json

    fn Exact::to_json(Exact) -> Json

    Exact::to_repr

    HandlingHistory

    pub(all) struct HandlingHistory {
    model : String
    parameters : Array[ParameterValue]
    samples : Array[PreparedSample]
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    HandlingStep

    pub(all) struct HandlingStep {
    id : String
    parent : String
    kind : String
    volume_ul : Int
    amount_nmol : Bounds
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    A child preparation state. take/dilute/evaporate use volume_ul and zero amount; co2/calcite use signed amount_nmol and zero volume; hcl/naoh use nonnegative reagent moles and added solution volume. Parents precede children.

    HandlingStep::to_json

    ParameterValue

    pub(all) struct ParameterValue {
    parameter : String
    value : Exact
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    PreparedSample

    pub(all) struct PreparedSample {
    id : String
    volume_ul : Int
    calcium_nmol_l : Exact
    dic_nmol_l : Exact
    ta_neq_l : Exact
    sodium_nmol_l : Exact
    chloride_nmol_l : Exact
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    SourceWater

    pub(all) struct SourceWater {
    id : String
    volume_ul : Int
    calcium_nmol_l : Bounds
    dic_nmol_l : Bounds
    ta_neq_l : Bounds
    sodium_nmol_l : Bounds
    chloride_nmol_l : Bounds
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    One Ca-carbonate-Na-Cl-water source, with no untracked strong ions.

    SourceWater::to_json

    fn SourceWater::to_json(SourceWater) -> Json

    ZeroTransferClaim

    pub(all) struct ZeroTransferClaim {
    study : AliquotStudy
    zero_steps : Array[String]
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    Ask whether all the named chemical steps could have zero net transfer. This is a joint hypothesis: ruling it out requires at least one of them, not every named step, to be nonzero within the declared model.

    ZeroTransferClaim::to_json

    challenge_json

    fn challenge_json(input : String) -> String

    challenge_zero_transfer

    fn challenge_zero_transfer(claim : ZeroTransferClaim) -> Result[ClaimAssessment, String]

    Challenge a specific sample-handling explanation. An inconsistent baseline never proves that a process occurred; a possible history never proves it did.

    reconcile_aliquots

    fn reconcile_aliquots(study : AliquotStudy) -> Result[AliquotAssessment, String]

    Reconcile every bottle simultaneously, retaining the same uncertain source and upstream dose in all descendants. Marginal interval agreement is weaker.

    reconcile_json

    fn reconcile_json(input : String) -> String

    replay_handling

    fn replay_handling(study : AliquotStudy, choices : Array[ParameterValue]) -> Result[HandlingHistory, String]

    Replay one complete shared preparation history, including all assay and nonnegative-inventory checks. Missing/extra choices are rejected.

    replay_json

    fn replay_json(input : String) -> String