universal-physics-tensor 10.0.0 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/bin/upt.mjs +13 -1
- package/data/atlas/atlas.json +25 -25
- package/data/atlas/atlas.jsonld +1 -1
- package/data/atlas/diffusion.json +6 -6
- package/data/atlas/oscillators.json +7 -7
- package/data/atlas/waves.json +14 -14
- package/data/atlas/witness-results.json +11 -11
- package/data/bridge-catalog.json +371 -228
- package/data/bridge-catalog.schema.json +45 -7
- package/dist/atlas/applicability.d.ts.map +1 -1
- package/dist/atlas/applicability.js +21 -15
- package/dist/atlas/applicability.js.map +1 -1
- package/dist/atlas/benchmark/hybrid-retrieval.d.ts +9 -1
- package/dist/atlas/benchmark/hybrid-retrieval.d.ts.map +1 -1
- package/dist/atlas/benchmark/hybrid-retrieval.js +15 -13
- package/dist/atlas/benchmark/hybrid-retrieval.js.map +1 -1
- package/dist/atlas/benchmark/loader.js +2 -2
- package/dist/atlas/benchmark/loader.js.map +1 -1
- package/dist/atlas/benchmark/stats.d.ts +2 -2
- package/dist/atlas/benchmark/stats.d.ts.map +1 -1
- package/dist/atlas/benchmark/stats.js +15 -7
- package/dist/atlas/benchmark/stats.js.map +1 -1
- package/dist/atlas/catalog-formal-ref.d.ts +26 -3
- package/dist/atlas/catalog-formal-ref.d.ts.map +1 -1
- package/dist/atlas/catalog-formal-ref.js +52 -5
- package/dist/atlas/catalog-formal-ref.js.map +1 -1
- package/dist/atlas/chain-pipeline.d.ts.map +1 -1
- package/dist/atlas/chain-pipeline.js +7 -8
- package/dist/atlas/chain-pipeline.js.map +1 -1
- package/dist/atlas/diffusion/bridges-closure.d.ts +0 -4
- package/dist/atlas/diffusion/bridges-closure.d.ts.map +1 -1
- package/dist/atlas/diffusion/bridges-closure.js +8 -12
- package/dist/atlas/diffusion/bridges-closure.js.map +1 -1
- package/dist/atlas/diffusion/bridges.d.ts.map +1 -1
- package/dist/atlas/diffusion/bridges.js +27 -39
- package/dist/atlas/diffusion/bridges.js.map +1 -1
- package/dist/atlas/diffusion/dimensions.d.ts +6 -14
- package/dist/atlas/diffusion/dimensions.d.ts.map +1 -1
- package/dist/atlas/diffusion/dimensions.js +8 -16
- package/dist/atlas/diffusion/dimensions.js.map +1 -1
- package/dist/atlas/diffusion/models.d.ts +3 -3
- package/dist/atlas/diffusion/models.d.ts.map +1 -1
- package/dist/atlas/diffusion/models.js +5 -10
- package/dist/atlas/diffusion/models.js.map +1 -1
- package/dist/atlas/diffusion/numerics.d.ts +16 -4
- package/dist/atlas/diffusion/numerics.d.ts.map +1 -1
- package/dist/atlas/diffusion/numerics.js +38 -24
- package/dist/atlas/diffusion/numerics.js.map +1 -1
- package/dist/atlas/link-prediction.d.ts +106 -3
- package/dist/atlas/link-prediction.d.ts.map +1 -1
- package/dist/atlas/link-prediction.js +212 -66
- package/dist/atlas/link-prediction.js.map +1 -1
- package/dist/atlas/oscillators/bridges-coarse.d.ts.map +1 -1
- package/dist/atlas/oscillators/bridges-coarse.js +7 -11
- package/dist/atlas/oscillators/bridges-coarse.js.map +1 -1
- package/dist/atlas/oscillators/bridges-exact.d.ts.map +1 -1
- package/dist/atlas/oscillators/bridges-exact.js +6 -7
- package/dist/atlas/oscillators/bridges-exact.js.map +1 -1
- package/dist/atlas/oscillators/bridges-limits.d.ts +3 -16
- package/dist/atlas/oscillators/bridges-limits.d.ts.map +1 -1
- package/dist/atlas/oscillators/bridges-limits.js +23 -34
- package/dist/atlas/oscillators/bridges-limits.js.map +1 -1
- package/dist/atlas/oscillators/dimensions.d.ts +9 -21
- package/dist/atlas/oscillators/dimensions.d.ts.map +1 -1
- package/dist/atlas/oscillators/dimensions.js +9 -21
- package/dist/atlas/oscillators/dimensions.js.map +1 -1
- package/dist/atlas/oscillators/limit-witnesses.d.ts +2 -2
- package/dist/atlas/oscillators/limit-witnesses.d.ts.map +1 -1
- package/dist/atlas/oscillators/limit-witnesses.js +17 -15
- package/dist/atlas/oscillators/limit-witnesses.js.map +1 -1
- package/dist/atlas/oscillators/models.d.ts.map +1 -1
- package/dist/atlas/oscillators/models.js +2 -6
- package/dist/atlas/oscillators/models.js.map +1 -1
- package/dist/atlas/oscillators/pendulum-motion.d.ts +29 -6
- package/dist/atlas/oscillators/pendulum-motion.d.ts.map +1 -1
- package/dist/atlas/oscillators/pendulum-motion.js +60 -40
- package/dist/atlas/oscillators/pendulum-motion.js.map +1 -1
- package/dist/atlas/oscillators/phase-translation.d.ts +0 -11
- package/dist/atlas/oscillators/phase-translation.d.ts.map +1 -1
- package/dist/atlas/oscillators/phase-translation.js +3 -4
- package/dist/atlas/oscillators/phase-translation.js.map +1 -1
- package/dist/atlas/oscillators/position-translation.d.ts +68 -7
- package/dist/atlas/oscillators/position-translation.d.ts.map +1 -1
- package/dist/atlas/oscillators/position-translation.js +123 -12
- package/dist/atlas/oscillators/position-translation.js.map +1 -1
- package/dist/atlas/oscillators/rejections.d.ts +0 -2
- package/dist/atlas/oscillators/rejections.d.ts.map +1 -1
- package/dist/atlas/oscillators/rejections.js +0 -7
- package/dist/atlas/oscillators/rejections.js.map +1 -1
- package/dist/atlas/physjs-entries.generated.d.ts +25 -24
- package/dist/atlas/physjs-entries.generated.d.ts.map +1 -1
- package/dist/atlas/physjs-entries.generated.js +25 -24
- package/dist/atlas/physjs-entries.generated.js.map +1 -1
- package/dist/atlas/physjs-ref.d.ts +34 -31
- package/dist/atlas/physjs-ref.d.ts.map +1 -1
- package/dist/atlas/physjs-ref.js +55 -53
- package/dist/atlas/physjs-ref.js.map +1 -1
- package/dist/atlas/physjs-reviewed.d.ts +1 -1
- package/dist/atlas/physjs-reviewed.js +15 -15
- package/dist/atlas/physjs-reviewed.js.map +1 -1
- package/dist/atlas/poster/statements.d.ts +0 -19
- package/dist/atlas/poster/statements.d.ts.map +1 -1
- package/dist/atlas/poster/statements.js +1 -1
- package/dist/atlas/poster/statements.js.map +1 -1
- package/dist/atlas/proof-target.d.ts +1 -1
- package/dist/atlas/proof-target.js +1 -1
- package/dist/atlas/proof-target.js.map +1 -1
- package/dist/atlas/regime.d.ts +1 -1
- package/dist/atlas/regime.d.ts.map +1 -1
- package/dist/atlas/regime.js +1 -1
- package/dist/atlas/regime.js.map +1 -1
- package/dist/atlas/text-overlap.d.ts +23 -0
- package/dist/atlas/text-overlap.d.ts.map +1 -0
- package/dist/atlas/text-overlap.js +41 -0
- package/dist/atlas/text-overlap.js.map +1 -0
- package/dist/atlas/waves/bridges-closure.d.ts.map +1 -1
- package/dist/atlas/waves/bridges-closure.js +2 -6
- package/dist/atlas/waves/bridges-closure.js.map +1 -1
- package/dist/atlas/waves/bridges.d.ts.map +1 -1
- package/dist/atlas/waves/bridges.js +32 -48
- package/dist/atlas/waves/bridges.js.map +1 -1
- package/dist/atlas/waves/models.d.ts +5 -6
- package/dist/atlas/waves/models.d.ts.map +1 -1
- package/dist/atlas/waves/models.js +7 -13
- package/dist/atlas/waves/models.js.map +1 -1
- package/dist/atlas/waves/numerics.d.ts.map +1 -1
- package/dist/atlas/waves/numerics.js +10 -3
- package/dist/atlas/waves/numerics.js.map +1 -1
- package/dist/atlas/witness-numeric.d.ts +30 -0
- package/dist/atlas/witness-numeric.d.ts.map +1 -1
- package/dist/atlas/witness-numeric.js +53 -0
- package/dist/atlas/witness-numeric.js.map +1 -1
- package/dist/atlas/witness-specs.d.ts.map +1 -1
- package/dist/atlas/witness-specs.js +19 -0
- package/dist/atlas/witness-specs.js.map +1 -1
- package/dist/atlas/witness-symbolic.d.ts +75 -3
- package/dist/atlas/witness-symbolic.d.ts.map +1 -1
- package/dist/atlas/witness-symbolic.js +116 -10
- package/dist/atlas/witness-symbolic.js.map +1 -1
- package/dist/bridges/catalog-load.d.ts.map +1 -1
- package/dist/bridges/catalog-load.js +13 -8
- package/dist/bridges/catalog-load.js.map +1 -1
- package/dist/bridges/catalog-types.d.ts +26 -2
- package/dist/bridges/catalog-types.d.ts.map +1 -1
- package/dist/bridges/catalog-types.js +11 -1
- package/dist/bridges/catalog-types.js.map +1 -1
- package/dist/bridges/evaluation-errors.d.ts +31 -1
- package/dist/bridges/evaluation-errors.d.ts.map +1 -1
- package/dist/bridges/evaluation-errors.js +20 -2
- package/dist/bridges/evaluation-errors.js.map +1 -1
- package/dist/bridges/evaluator-inputs.d.ts.map +1 -1
- package/dist/bridges/evaluator-inputs.js +7 -5
- package/dist/bridges/evaluator-inputs.js.map +1 -1
- package/dist/bridges/evaluators.d.ts.map +1 -1
- package/dist/bridges/evaluators.js +27 -12
- package/dist/bridges/evaluators.js.map +1 -1
- package/dist/bridges/expr-parse.d.ts +11 -0
- package/dist/bridges/expr-parse.d.ts.map +1 -1
- package/dist/bridges/expr-parse.js +14 -5
- package/dist/bridges/expr-parse.js.map +1 -1
- package/dist/bridges/holds.d.ts +35 -3
- package/dist/bridges/holds.d.ts.map +1 -1
- package/dist/bridges/holds.js +117 -23
- package/dist/bridges/holds.js.map +1 -1
- package/dist/bridges/notices.d.ts.map +1 -1
- package/dist/bridges/notices.js +5 -5
- package/dist/bridges/notices.js.map +1 -1
- package/dist/bridges/relation-eval.d.ts +4 -4
- package/dist/bridges/relation-eval.d.ts.map +1 -1
- package/dist/bridges/relation-eval.js +15 -16
- package/dist/bridges/relation-eval.js.map +1 -1
- package/dist/bridges/sensitivity.d.ts.map +1 -1
- package/dist/bridges/sensitivity.js +3 -3
- package/dist/bridges/sensitivity.js.map +1 -1
- package/dist/bridges/validity.d.ts +33 -0
- package/dist/bridges/validity.d.ts.map +1 -0
- package/dist/bridges/validity.js +67 -0
- package/dist/bridges/validity.js.map +1 -0
- package/dist/canonical/entries/atomic.js +1 -3
- package/dist/canonical/entries/atomic.js.map +1 -1
- package/dist/canonical/entries/condensed-matter.d.ts.map +1 -1
- package/dist/canonical/entries/condensed-matter.js +4 -5
- package/dist/canonical/entries/condensed-matter.js.map +1 -1
- package/dist/canonical/entries/dimensional-classics.d.ts.map +1 -1
- package/dist/canonical/entries/dimensional-classics.js +3 -4
- package/dist/canonical/entries/dimensional-classics.js.map +1 -1
- package/dist/canonical/entries/electromagnetism.d.ts.map +1 -1
- package/dist/canonical/entries/electromagnetism.js +4 -10
- package/dist/canonical/entries/electromagnetism.js.map +1 -1
- package/dist/canonical/entries/fluids-waves.d.ts.map +1 -1
- package/dist/canonical/entries/fluids-waves.js +3 -7
- package/dist/canonical/entries/fluids-waves.js.map +1 -1
- package/dist/canonical/entries/mechanics.d.ts.map +1 -1
- package/dist/canonical/entries/mechanics.js +4 -6
- package/dist/canonical/entries/mechanics.js.map +1 -1
- package/dist/canonical/entries/nonmonomial.d.ts.map +1 -1
- package/dist/canonical/entries/nonmonomial.js +9 -17
- package/dist/canonical/entries/nonmonomial.js.map +1 -1
- package/dist/canonical/entries/relativity.d.ts.map +1 -1
- package/dist/canonical/entries/relativity.js +6 -6
- package/dist/canonical/entries/relativity.js.map +1 -1
- package/dist/canonical/entries/thermo-nuclear-cosmo.d.ts.map +1 -1
- package/dist/canonical/entries/thermo-nuclear-cosmo.js +6 -10
- package/dist/canonical/entries/thermo-nuclear-cosmo.js.map +1 -1
- package/dist/canonical/fixed-points.d.ts +94 -0
- package/dist/canonical/fixed-points.d.ts.map +1 -0
- package/dist/canonical/fixed-points.js +81 -0
- package/dist/canonical/fixed-points.js.map +1 -0
- package/dist/canonical/linkage.d.ts.map +1 -1
- package/dist/canonical/linkage.js +25 -44
- package/dist/canonical/linkage.js.map +1 -1
- package/dist/canonical/normal-form.d.ts.map +1 -1
- package/dist/canonical/normal-form.js +5 -11
- package/dist/canonical/normal-form.js.map +1 -1
- package/dist/canonical/structural.d.ts +21 -21
- package/dist/canonical/structural.d.ts.map +1 -1
- package/dist/canonical/structural.js +40 -19
- package/dist/canonical/structural.js.map +1 -1
- package/dist/cases/brownian-sphere.d.ts +3 -3
- package/dist/cases/brownian-sphere.d.ts.map +1 -1
- package/dist/cases/brownian-sphere.js +6 -5
- package/dist/cases/brownian-sphere.js.map +1 -1
- package/dist/cases/damped-resonator.d.ts.map +1 -1
- package/dist/cases/damped-resonator.js +6 -9
- package/dist/cases/damped-resonator.js.map +1 -1
- package/dist/cases/kepler-rv.d.ts +1 -1
- package/dist/cases/kepler-rv.d.ts.map +1 -1
- package/dist/cases/kepler-rv.js +3 -2
- package/dist/cases/kepler-rv.js.map +1 -1
- package/dist/cases/lumped-cooling.d.ts +8 -3
- package/dist/cases/lumped-cooling.d.ts.map +1 -1
- package/dist/cases/lumped-cooling.js +21 -23
- package/dist/cases/lumped-cooling.js.map +1 -1
- package/dist/cases/quadrature.d.ts +7 -9
- package/dist/cases/quadrature.d.ts.map +1 -1
- package/dist/cases/quadrature.js +28 -32
- package/dist/cases/quadrature.js.map +1 -1
- package/dist/cases/resistor-noise.js +4 -4
- package/dist/cases/resistor-noise.js.map +1 -1
- package/dist/cases/skin-depth.d.ts +0 -4
- package/dist/cases/skin-depth.d.ts.map +1 -1
- package/dist/cases/skin-depth.js +3 -7
- package/dist/cases/skin-depth.js.map +1 -1
- package/dist/cli/args.d.ts +23 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +30 -8
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/bindings.d.ts.map +1 -1
- package/dist/cli/bindings.js +5 -4
- package/dist/cli/bindings.js.map +1 -1
- package/dist/cli/command.d.ts +8 -1
- package/dist/cli/command.d.ts.map +1 -1
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/commands/_atlas-map.d.ts +0 -9
- package/dist/cli/commands/_atlas-map.d.ts.map +1 -1
- package/dist/cli/commands/_atlas-map.js +8 -18
- package/dist/cli/commands/_atlas-map.js.map +1 -1
- package/dist/cli/commands/_atlas-route.d.ts.map +1 -1
- package/dist/cli/commands/_atlas-route.js +6 -2
- package/dist/cli/commands/_atlas-route.js.map +1 -1
- package/dist/cli/commands/_discovery-opts.d.ts.map +1 -1
- package/dist/cli/commands/_discovery-opts.js +8 -9
- package/dist/cli/commands/_discovery-opts.js.map +1 -1
- package/dist/cli/commands/atlas.d.ts.map +1 -1
- package/dist/cli/commands/atlas.js +8 -5
- package/dist/cli/commands/atlas.js.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +8 -1
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/axes.d.ts.map +1 -1
- package/dist/cli/commands/axes.js +20 -1
- package/dist/cli/commands/axes.js.map +1 -1
- package/dist/cli/commands/confront.d.ts.map +1 -1
- package/dist/cli/commands/confront.js +8 -14
- package/dist/cli/commands/confront.js.map +1 -1
- package/dist/cli/commands/derive.d.ts.map +1 -1
- package/dist/cli/commands/derive.js +22 -22
- package/dist/cli/commands/derive.js.map +1 -1
- package/dist/cli/commands/discover.d.ts.map +1 -1
- package/dist/cli/commands/discover.js +6 -2
- package/dist/cli/commands/discover.js.map +1 -1
- package/dist/cli/commands/eval.d.ts.map +1 -1
- package/dist/cli/commands/eval.js +1 -0
- package/dist/cli/commands/eval.js.map +1 -1
- package/dist/cli/commands/evaluate.d.ts.map +1 -1
- package/dist/cli/commands/evaluate.js +65 -37
- package/dist/cli/commands/evaluate.js.map +1 -1
- package/dist/cli/commands/explain.d.ts.map +1 -1
- package/dist/cli/commands/explain.js +2 -1
- package/dist/cli/commands/explain.js.map +1 -1
- package/dist/cli/commands/ground.d.ts.map +1 -1
- package/dist/cli/commands/ground.js +1 -0
- package/dist/cli/commands/ground.js.map +1 -1
- package/dist/cli/commands/map.d.ts.map +1 -1
- package/dist/cli/commands/map.js +75 -5
- package/dist/cli/commands/map.js.map +1 -1
- package/dist/cli/commands/metric.d.ts.map +1 -1
- package/dist/cli/commands/metric.js +12 -9
- package/dist/cli/commands/metric.js.map +1 -1
- package/dist/cli/commands/path.d.ts +10 -0
- package/dist/cli/commands/path.d.ts.map +1 -1
- package/dist/cli/commands/path.js +25 -3
- package/dist/cli/commands/path.js.map +1 -1
- package/dist/cli/commands/probe.d.ts.map +1 -1
- package/dist/cli/commands/probe.js +59 -16
- package/dist/cli/commands/probe.js.map +1 -1
- package/dist/cli/commands/regime.d.ts.map +1 -1
- package/dist/cli/commands/regime.js +1 -0
- package/dist/cli/commands/regime.js.map +1 -1
- package/dist/cli/commands/retrieve.d.ts.map +1 -1
- package/dist/cli/commands/retrieve.js +1 -0
- package/dist/cli/commands/retrieve.js.map +1 -1
- package/dist/cli/commands/search.d.ts.map +1 -1
- package/dist/cli/commands/search.js +1 -0
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/symbolic.d.ts.map +1 -1
- package/dist/cli/commands/symbolic.js +19 -28
- package/dist/cli/commands/symbolic.js.map +1 -1
- package/dist/cli/commands/testplan.d.ts.map +1 -1
- package/dist/cli/commands/testplan.js +4 -2
- package/dist/cli/commands/testplan.js.map +1 -1
- package/dist/cli/expr-print.d.ts +0 -2
- package/dist/cli/expr-print.d.ts.map +1 -1
- package/dist/cli/expr-print.js +7 -31
- package/dist/cli/expr-print.js.map +1 -1
- package/dist/cli/main.d.ts +7 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +18 -3
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/numeric-flag.d.ts +12 -0
- package/dist/cli/numeric-flag.d.ts.map +1 -0
- package/dist/cli/numeric-flag.js +44 -0
- package/dist/cli/numeric-flag.js.map +1 -0
- package/dist/cli/output.d.ts +20 -0
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +15 -0
- package/dist/cli/output.js.map +1 -1
- package/dist/cli/record-reach.js +2 -2
- package/dist/cli/record-reach.js.map +1 -1
- package/dist/cli/record-tables.d.ts.map +1 -1
- package/dist/cli/record-tables.js +6 -5
- package/dist/cli/record-tables.js.map +1 -1
- package/dist/cli/record.d.ts +1 -5
- package/dist/cli/record.d.ts.map +1 -1
- package/dist/cli/record.js +9 -8
- package/dist/cli/record.js.map +1 -1
- package/dist/cli/search-index.d.ts.map +1 -1
- package/dist/cli/search-index.js +7 -6
- package/dist/cli/search-index.js.map +1 -1
- package/dist/cli/statuses.d.ts +0 -2
- package/dist/cli/statuses.d.ts.map +1 -1
- package/dist/cli/statuses.js +0 -7
- package/dist/cli/statuses.js.map +1 -1
- package/dist/cli/stored-results.d.ts +7 -0
- package/dist/cli/stored-results.d.ts.map +1 -0
- package/dist/cli/stored-results.js +23 -0
- package/dist/cli/stored-results.js.map +1 -0
- package/dist/cli/version.d.ts.map +1 -1
- package/dist/cli/version.js +7 -5
- package/dist/cli/version.js.map +1 -1
- package/dist/cli-api.d.ts +34 -5
- package/dist/cli-api.d.ts.map +1 -1
- package/dist/cli-api.js +28 -4
- package/dist/cli-api.js.map +1 -1
- package/dist/composition/algebraic-equivalence.d.ts +43 -0
- package/dist/composition/algebraic-equivalence.d.ts.map +1 -0
- package/dist/composition/algebraic-equivalence.js +115 -0
- package/dist/composition/algebraic-equivalence.js.map +1 -0
- package/dist/composition/axes.d.ts +0 -6
- package/dist/composition/axes.d.ts.map +1 -1
- package/dist/composition/axes.js +6 -6
- package/dist/composition/axes.js.map +1 -1
- package/dist/composition/axis-audit.d.ts +47 -20
- package/dist/composition/axis-audit.d.ts.map +1 -1
- package/dist/composition/axis-audit.js +82 -9
- package/dist/composition/axis-audit.js.map +1 -1
- package/dist/composition/bridge-analysis.d.ts +17 -0
- package/dist/composition/bridge-analysis.d.ts.map +1 -1
- package/dist/composition/bridge-analysis.js +102 -55
- package/dist/composition/bridge-analysis.js.map +1 -1
- package/dist/composition/canonical-compare.d.ts +40 -0
- package/dist/composition/canonical-compare.d.ts.map +1 -1
- package/dist/composition/canonical-compare.js +122 -24
- package/dist/composition/canonical-compare.js.map +1 -1
- package/dist/composition/canonical-graph.d.ts +1 -1
- package/dist/composition/canonical-graph.d.ts.map +1 -1
- package/dist/composition/canonical-graph.js +9 -36
- package/dist/composition/canonical-graph.js.map +1 -1
- package/dist/composition/canonical-json.js +2 -2
- package/dist/composition/canonical-json.js.map +1 -1
- package/dist/composition/catalog-graph.d.ts.map +1 -1
- package/dist/composition/catalog-graph.js +2 -5
- package/dist/composition/catalog-graph.js.map +1 -1
- package/dist/composition/chain-candidate.d.ts +8 -0
- package/dist/composition/chain-candidate.d.ts.map +1 -1
- package/dist/composition/chain-candidate.js +9 -2
- package/dist/composition/chain-candidate.js.map +1 -1
- package/dist/composition/chain-match.d.ts +6 -3
- package/dist/composition/chain-match.d.ts.map +1 -1
- package/dist/composition/chain-match.js +4 -1
- package/dist/composition/chain-match.js.map +1 -1
- package/dist/composition/chain-result.d.ts.map +1 -1
- package/dist/composition/chain-result.js +2 -14
- package/dist/composition/chain-result.js.map +1 -1
- package/dist/composition/compose-symbolic.d.ts.map +1 -1
- package/dist/composition/compose-symbolic.js +3 -2
- package/dist/composition/compose-symbolic.js.map +1 -1
- package/dist/composition/compose.d.ts.map +1 -1
- package/dist/composition/compose.js +13 -5
- package/dist/composition/compose.js.map +1 -1
- package/dist/composition/composition-recovery.d.ts.map +1 -1
- package/dist/composition/composition-recovery.js +4 -7
- package/dist/composition/composition-recovery.js.map +1 -1
- package/dist/composition/discovery.d.ts +56 -0
- package/dist/composition/discovery.d.ts.map +1 -1
- package/dist/composition/discovery.js +114 -60
- package/dist/composition/discovery.js.map +1 -1
- package/dist/composition/edge.d.ts +21 -2
- package/dist/composition/edge.d.ts.map +1 -1
- package/dist/composition/edge.js +23 -1
- package/dist/composition/edge.js.map +1 -1
- package/dist/composition/enumerate.d.ts.map +1 -1
- package/dist/composition/enumerate.js +18 -3
- package/dist/composition/enumerate.js.map +1 -1
- package/dist/composition/evaluate-relation.d.ts +35 -11
- package/dist/composition/evaluate-relation.d.ts.map +1 -1
- package/dist/composition/evaluate-relation.js +60 -39
- package/dist/composition/evaluate-relation.js.map +1 -1
- package/dist/composition/explain.d.ts +3 -12
- package/dist/composition/explain.d.ts.map +1 -1
- package/dist/composition/explain.js +7 -20
- package/dist/composition/explain.js.map +1 -1
- package/dist/composition/expr-eval.d.ts.map +1 -1
- package/dist/composition/expr-eval.js +2 -11
- package/dist/composition/expr-eval.js.map +1 -1
- package/dist/composition/expr-simplify.d.ts +16 -0
- package/dist/composition/expr-simplify.d.ts.map +1 -1
- package/dist/composition/expr-simplify.js +15 -20
- package/dist/composition/expr-simplify.js.map +1 -1
- package/dist/composition/formula-shape.d.ts +23 -4
- package/dist/composition/formula-shape.d.ts.map +1 -1
- package/dist/composition/formula-shape.js +57 -17
- package/dist/composition/formula-shape.js.map +1 -1
- package/dist/composition/graph-structure.d.ts +98 -0
- package/dist/composition/graph-structure.d.ts.map +1 -0
- package/dist/composition/graph-structure.js +167 -0
- package/dist/composition/graph-structure.js.map +1 -0
- package/dist/composition/graph-viz-svg.d.ts.map +1 -1
- package/dist/composition/graph-viz-svg.js +1 -1
- package/dist/composition/graph-viz-svg.js.map +1 -1
- package/dist/composition/graph-viz.d.ts.map +1 -1
- package/dist/composition/graph-viz.js +8 -37
- package/dist/composition/graph-viz.js.map +1 -1
- package/dist/composition/identifiability.d.ts +91 -4
- package/dist/composition/identifiability.d.ts.map +1 -1
- package/dist/composition/identifiability.js +363 -6
- package/dist/composition/identifiability.js.map +1 -1
- package/dist/composition/index.d.ts +8 -4
- package/dist/composition/index.d.ts.map +1 -1
- package/dist/composition/index.js +3 -2
- package/dist/composition/index.js.map +1 -1
- package/dist/composition/mathts-quiet.d.ts +4 -3
- package/dist/composition/mathts-quiet.d.ts.map +1 -1
- package/dist/composition/mathts-quiet.js +4 -3
- package/dist/composition/mathts-quiet.js.map +1 -1
- package/dist/composition/mathts-scalar-symbols.d.ts.map +1 -1
- package/dist/composition/mathts-scalar-symbols.js +2 -1
- package/dist/composition/mathts-scalar-symbols.js.map +1 -1
- package/dist/composition/probe/corpus.d.ts +4 -2
- package/dist/composition/probe/corpus.d.ts.map +1 -1
- package/dist/composition/probe/corpus.js +20 -9
- package/dist/composition/probe/corpus.js.map +1 -1
- package/dist/composition/probe/dataset.d.ts +17 -0
- package/dist/composition/probe/dataset.d.ts.map +1 -1
- package/dist/composition/probe/dataset.js +95 -50
- package/dist/composition/probe/dataset.js.map +1 -1
- package/dist/composition/probe/experiment-design.d.ts +5 -1
- package/dist/composition/probe/experiment-design.d.ts.map +1 -1
- package/dist/composition/probe/experiment-design.js +44 -24
- package/dist/composition/probe/experiment-design.js.map +1 -1
- package/dist/composition/probe/falsify.d.ts.map +1 -1
- package/dist/composition/probe/falsify.js +2 -0
- package/dist/composition/probe/falsify.js.map +1 -1
- package/dist/composition/probe/fit.d.ts +6 -0
- package/dist/composition/probe/fit.d.ts.map +1 -1
- package/dist/composition/probe/fit.js +46 -22
- package/dist/composition/probe/fit.js.map +1 -1
- package/dist/composition/probe/frontier.d.ts.map +1 -1
- package/dist/composition/probe/frontier.js +33 -15
- package/dist/composition/probe/frontier.js.map +1 -1
- package/dist/composition/probe/generator.d.ts +27 -1
- package/dist/composition/probe/generator.d.ts.map +1 -1
- package/dist/composition/probe/generator.js +53 -30
- package/dist/composition/probe/generator.js.map +1 -1
- package/dist/composition/probe/index.d.ts +14 -0
- package/dist/composition/probe/index.d.ts.map +1 -1
- package/dist/composition/probe/index.js +6 -0
- package/dist/composition/probe/index.js.map +1 -1
- package/dist/composition/probe/limits.d.ts +24 -1
- package/dist/composition/probe/limits.d.ts.map +1 -1
- package/dist/composition/probe/limits.js +53 -11
- package/dist/composition/probe/limits.js.map +1 -1
- package/dist/composition/probe/pipeline.d.ts.map +1 -1
- package/dist/composition/probe/pipeline.js +10 -4
- package/dist/composition/probe/pipeline.js.map +1 -1
- package/dist/composition/probe/power-law.d.ts +121 -0
- package/dist/composition/probe/power-law.d.ts.map +1 -0
- package/dist/composition/probe/power-law.js +255 -0
- package/dist/composition/probe/power-law.js.map +1 -0
- package/dist/composition/probe/problem.d.ts +7 -4
- package/dist/composition/probe/problem.d.ts.map +1 -1
- package/dist/composition/probe/problem.js +177 -49
- package/dist/composition/probe/problem.js.map +1 -1
- package/dist/composition/probe/report.js +1 -1
- package/dist/composition/probe/report.js.map +1 -1
- package/dist/composition/probe/residual.d.ts +6 -1
- package/dist/composition/probe/residual.d.ts.map +1 -1
- package/dist/composition/probe/residual.js +9 -7
- package/dist/composition/probe/residual.js.map +1 -1
- package/dist/composition/probe/structure.d.ts +82 -17
- package/dist/composition/probe/structure.d.ts.map +1 -1
- package/dist/composition/probe/structure.js +129 -55
- package/dist/composition/probe/structure.js.map +1 -1
- package/dist/composition/probe/study.d.ts +31 -9
- package/dist/composition/probe/study.d.ts.map +1 -1
- package/dist/composition/probe/study.js +236 -181
- package/dist/composition/probe/study.js.map +1 -1
- package/dist/composition/probe/t-tail.d.ts +17 -0
- package/dist/composition/probe/t-tail.d.ts.map +1 -0
- package/dist/composition/probe/t-tail.js +32 -0
- package/dist/composition/probe/t-tail.js.map +1 -0
- package/dist/composition/probe/types.d.ts +3 -0
- package/dist/composition/probe/types.d.ts.map +1 -1
- package/dist/composition/probe/types.js.map +1 -1
- package/dist/composition/proposed-bridges.d.ts +41 -10
- package/dist/composition/proposed-bridges.d.ts.map +1 -1
- package/dist/composition/proposed-bridges.js +100 -55
- package/dist/composition/proposed-bridges.js.map +1 -1
- package/dist/composition/quantity-clusters.d.ts +48 -0
- package/dist/composition/quantity-clusters.d.ts.map +1 -0
- package/dist/composition/quantity-clusters.js +98 -0
- package/dist/composition/quantity-clusters.js.map +1 -0
- package/dist/composition/rational-exponent.d.ts +40 -0
- package/dist/composition/rational-exponent.d.ts.map +1 -0
- package/dist/composition/rational-exponent.js +65 -0
- package/dist/composition/rational-exponent.js.map +1 -0
- package/dist/composition/representative-values.d.ts +22 -0
- package/dist/composition/representative-values.d.ts.map +1 -1
- package/dist/composition/representative-values.js +23 -0
- package/dist/composition/representative-values.js.map +1 -1
- package/dist/composition/retrodiction.d.ts.map +1 -1
- package/dist/composition/retrodiction.js +2 -1
- package/dist/composition/retrodiction.js.map +1 -1
- package/dist/composition/user-equation.d.ts.map +1 -1
- package/dist/composition/user-equation.js +2 -2
- package/dist/composition/user-equation.js.map +1 -1
- package/dist/core/assignment.d.ts +19 -0
- package/dist/core/assignment.d.ts.map +1 -0
- package/dist/core/assignment.js +19 -0
- package/dist/core/assignment.js.map +1 -0
- package/dist/core/compare.d.ts +32 -0
- package/dist/core/compare.d.ts.map +1 -0
- package/dist/core/compare.js +46 -0
- package/dist/core/compare.js.map +1 -0
- package/dist/core/constants.d.ts +30 -30
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +47 -30
- package/dist/core/constants.js.map +1 -1
- package/dist/core/data-file.d.ts +7 -0
- package/dist/core/data-file.d.ts.map +1 -1
- package/dist/core/data-file.js +17 -0
- package/dist/core/data-file.js.map +1 -1
- package/dist/core/format.d.ts +36 -0
- package/dist/core/format.d.ts.map +1 -0
- package/dist/core/format.js +39 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/hash.d.ts +14 -0
- package/dist/core/hash.d.ts.map +1 -0
- package/dist/core/hash.js +17 -0
- package/dist/core/hash.js.map +1 -0
- package/dist/core/json-schema.d.ts +2 -0
- package/dist/core/json-schema.d.ts.map +1 -1
- package/dist/core/json-schema.js +14 -13
- package/dist/core/json-schema.js.map +1 -1
- package/dist/core/labeled-tensor.d.ts.map +1 -1
- package/dist/core/labeled-tensor.js +0 -8
- package/dist/core/labeled-tensor.js.map +1 -1
- package/dist/core/mathts-read.d.ts +25 -0
- package/dist/core/mathts-read.d.ts.map +1 -0
- package/dist/core/mathts-read.js +51 -0
- package/dist/core/mathts-read.js.map +1 -0
- package/dist/core/tensor.d.ts.map +1 -1
- package/dist/core/tensor.js +24 -0
- package/dist/core/tensor.js.map +1 -1
- package/dist/core/types.d.ts +5 -5
- package/dist/diff/bridge-gradient.d.ts +19 -6
- package/dist/diff/bridge-gradient.d.ts.map +1 -1
- package/dist/diff/bridge-gradient.js +19 -11
- package/dist/diff/bridge-gradient.js.map +1 -1
- package/dist/diff/bridge-specs.d.ts.map +1 -1
- package/dist/diff/bridge-specs.js +3 -0
- package/dist/diff/bridge-specs.js.map +1 -1
- package/dist/dimensional/algebra.d.ts +18 -0
- package/dist/dimensional/algebra.d.ts.map +1 -1
- package/dist/dimensional/algebra.js +41 -1
- package/dist/dimensional/algebra.js.map +1 -1
- package/dist/dimensional/ast-builders.d.ts +7 -0
- package/dist/dimensional/ast-builders.d.ts.map +1 -1
- package/dist/dimensional/ast-builders.js +11 -0
- package/dist/dimensional/ast-builders.js.map +1 -1
- package/dist/dimensional/ast-leaves.d.ts +81 -0
- package/dist/dimensional/ast-leaves.d.ts.map +1 -0
- package/dist/dimensional/ast-leaves.js +146 -0
- package/dist/dimensional/ast-leaves.js.map +1 -0
- package/dist/dimensional/buckingham.d.ts.map +1 -1
- package/dist/dimensional/buckingham.js +15 -27
- package/dist/dimensional/buckingham.js.map +1 -1
- package/dist/dimensional/constant-rows.js +9 -9
- package/dist/dimensional/constant-rows.js.map +1 -1
- package/dist/dimensional/dimension-inference.d.ts.map +1 -1
- package/dist/dimensional/dimension-inference.js +1 -2
- package/dist/dimensional/dimension-inference.js.map +1 -1
- package/dist/dimensional/errors.d.ts +1 -1
- package/dist/dimensional/errors.d.ts.map +1 -1
- package/dist/dimensional/errors.js +1 -15
- package/dist/dimensional/errors.js.map +1 -1
- package/dist/dimensional/exact-scale.d.ts +0 -17
- package/dist/dimensional/exact-scale.d.ts.map +1 -1
- package/dist/dimensional/exact-scale.js +8 -8
- package/dist/dimensional/exact-scale.js.map +1 -1
- package/dist/dimensional/gauge-field.d.ts.map +1 -1
- package/dist/dimensional/gauge-field.js +2 -2
- package/dist/dimensional/gauge-field.js.map +1 -1
- package/dist/dimensional/hyphen-names.d.ts +12 -2
- package/dist/dimensional/hyphen-names.d.ts.map +1 -1
- package/dist/dimensional/hyphen-names.js +44 -19
- package/dist/dimensional/hyphen-names.js.map +1 -1
- package/dist/dimensional/metric.d.ts.map +1 -1
- package/dist/dimensional/metric.js +0 -1
- package/dist/dimensional/metric.js.map +1 -1
- package/dist/dimensional/symbolic-constants.d.ts +9 -0
- package/dist/dimensional/symbolic-constants.d.ts.map +1 -1
- package/dist/dimensional/symbolic-constants.js +13 -1
- package/dist/dimensional/symbolic-constants.js.map +1 -1
- package/dist/dimensional/types.d.ts +36 -0
- package/dist/dimensional/types.d.ts.map +1 -1
- package/dist/dimensional/types.js +45 -7
- package/dist/dimensional/types.js.map +1 -1
- package/dist/dimensional/unit-data.js +2 -2
- package/dist/dimensional/unit-data.js.map +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/numerical/christoffel-flat.d.ts.map +1 -1
- package/dist/numerical/christoffel-flat.js +3 -2
- package/dist/numerical/christoffel-flat.js.map +1 -1
- package/dist/numerical/covariant-eikonal.d.ts.map +1 -1
- package/dist/numerical/covariant-eikonal.js +34 -11
- package/dist/numerical/covariant-eikonal.js.map +1 -1
- package/dist/numerical/curvature-lowering-helpers.js +3 -2
- package/dist/numerical/curvature-lowering-helpers.js.map +1 -1
- package/dist/numerical/errors.d.ts.map +1 -1
- package/dist/numerical/errors.js +0 -3
- package/dist/numerical/errors.js.map +1 -1
- package/dist/numerical/finite-difference.d.ts +22 -0
- package/dist/numerical/finite-difference.d.ts.map +1 -0
- package/dist/numerical/finite-difference.js +27 -0
- package/dist/numerical/finite-difference.js.map +1 -0
- package/dist/numerical/geodesic-integrator.d.ts.map +1 -1
- package/dist/numerical/geodesic-integrator.js +22 -14
- package/dist/numerical/geodesic-integrator.js.map +1 -1
- package/dist/numerical/geometrized.d.ts.map +1 -1
- package/dist/numerical/geometrized.js +0 -1
- package/dist/numerical/geometrized.js.map +1 -1
- package/dist/numerical/mathts-engine.d.ts.map +1 -1
- package/dist/numerical/mathts-engine.js +10 -24
- package/dist/numerical/mathts-engine.js.map +1 -1
- package/dist/numerical/metric-inverse.d.ts.map +1 -1
- package/dist/numerical/metric-inverse.js +83 -46
- package/dist/numerical/metric-inverse.js.map +1 -1
- package/dist/numerical/null-ray-integrator.d.ts +2 -1
- package/dist/numerical/null-ray-integrator.d.ts.map +1 -1
- package/dist/numerical/null-ray-integrator.js +12 -12
- package/dist/numerical/null-ray-integrator.js.map +1 -1
- package/dist/numerical/painleve-gullstrand-metric.js +2 -2
- package/dist/numerical/painleve-gullstrand-metric.js.map +1 -1
- package/dist/numerical/perihelion-finder.d.ts +0 -36
- package/dist/numerical/perihelion-finder.d.ts.map +1 -1
- package/dist/numerical/perihelion-finder.js +41 -87
- package/dist/numerical/perihelion-finder.js.map +1 -1
- package/dist/numerical/quadrature.d.ts.map +1 -1
- package/dist/numerical/quadrature.js +8 -10
- package/dist/numerical/quadrature.js.map +1 -1
- package/dist/numerical/rk4-trajectory.d.ts +10 -0
- package/dist/numerical/rk4-trajectory.d.ts.map +1 -0
- package/dist/numerical/rk4-trajectory.js +37 -0
- package/dist/numerical/rk4-trajectory.js.map +1 -0
- package/dist/numerical/schwarzschild.d.ts +14 -0
- package/dist/numerical/schwarzschild.d.ts.map +1 -0
- package/dist/numerical/schwarzschild.js +17 -0
- package/dist/numerical/schwarzschild.js.map +1 -0
- package/dist/numerical/spacetime-metrics.d.ts +12 -0
- package/dist/numerical/spacetime-metrics.d.ts.map +1 -1
- package/dist/numerical/spacetime-metrics.js +72 -56
- package/dist/numerical/spacetime-metrics.js.map +1 -1
- package/dist/numerical/statistics.d.ts +24 -0
- package/dist/numerical/statistics.d.ts.map +1 -0
- package/dist/numerical/statistics.js +52 -0
- package/dist/numerical/statistics.js.map +1 -0
- package/dist/numerical/tensor-engine.d.ts +21 -0
- package/dist/numerical/tensor-engine.d.ts.map +1 -1
- package/dist/numerical/tensor-engine.js +12 -0
- package/dist/numerical/tensor-engine.js.map +1 -1
- package/dist/relations/regime.d.ts +10 -0
- package/dist/relations/regime.d.ts.map +1 -1
- package/dist/relations/regime.js +18 -1
- package/dist/relations/regime.js.map +1 -1
- package/package.json +7 -7
|
@@ -26,6 +26,11 @@
|
|
|
26
26
|
*
|
|
27
27
|
* @internal
|
|
28
28
|
*/
|
|
29
|
+
import { pairwiseDot, pairwiseSum } from '@danielsimonjr/mathts-core';
|
|
30
|
+
import { betainc, gammainc, gammaincp, inv, propagateUncertainty } from '@danielsimonjr/mathts-functions';
|
|
31
|
+
import { numberFrom } from '../../core/mathts-read.js';
|
|
32
|
+
import { readJsonFile } from '../../core/data-file.js';
|
|
33
|
+
import { isPlainObject } from '../../core/json-schema.js';
|
|
29
34
|
import { readFileSync } from 'node:fs';
|
|
30
35
|
import { DIMENSIONLESS } from '../../dimensional/types.js';
|
|
31
36
|
import { equals, format } from '../../dimensional/algebra.js';
|
|
@@ -61,14 +66,11 @@ export const MAX_CORRECTION_TERMS = 6;
|
|
|
61
66
|
function refuse(where, why) {
|
|
62
67
|
throw new StudyRefusal(`study refused (${where}): ${why}`);
|
|
63
68
|
}
|
|
64
|
-
function isObject(v) {
|
|
65
|
-
return !!v && typeof v === 'object' && !Array.isArray(v);
|
|
66
|
-
}
|
|
67
69
|
function nonEmptyString(v) {
|
|
68
70
|
return typeof v === 'string' && v.trim().length > 0;
|
|
69
71
|
}
|
|
70
72
|
function quantity(raw, where) {
|
|
71
|
-
if (!
|
|
73
|
+
if (!isPlainObject(raw) || !nonEmptyString(raw.name) || typeof raw.unit !== 'string') {
|
|
72
74
|
refuse(where, 'needs {"name", "unit"} ("unit": "" for a dimensionless quantity)');
|
|
73
75
|
}
|
|
74
76
|
let parsed;
|
|
@@ -111,11 +113,11 @@ function governingQuantity(raw, where) {
|
|
|
111
113
|
return sigma === undefined ? q : { ...q, sigma: positiveSigma(sigma, q, `${where}.sigma`) };
|
|
112
114
|
}
|
|
113
115
|
function parseFamily(raw, governing, where) {
|
|
114
|
-
if (!
|
|
116
|
+
if (!isPlainObject(raw) || !nonEmptyString(raw.input) || !Array.isArray(raw.powers)) {
|
|
115
117
|
refuse(where, 'needs {"input": <dimensionless governing input>, "powers": [p, ...]}');
|
|
116
118
|
}
|
|
117
119
|
for (const k of Object.keys(raw)) {
|
|
118
|
-
if (k !== 'input' && k !== 'powers')
|
|
120
|
+
if (k !== 'input' && k !== 'powers' && k !== 'reference')
|
|
119
121
|
refuse(where, `undeclared key '${k}'`);
|
|
120
122
|
}
|
|
121
123
|
const q = governing.find((g) => g.name === raw.input);
|
|
@@ -133,7 +135,19 @@ function parseFamily(raw, governing, where) {
|
|
|
133
135
|
}
|
|
134
136
|
if (new Set(powers).size !== powers.length)
|
|
135
137
|
refuse(`${where}.powers`, 'must be distinct');
|
|
136
|
-
|
|
138
|
+
if (raw.reference === undefined)
|
|
139
|
+
return { input: q.name, powers };
|
|
140
|
+
if (!isPlainObject(raw.reference))
|
|
141
|
+
refuse(`${where}.reference`, 'must be {"<power>": number}, keyed by a declared power');
|
|
142
|
+
const reference = {};
|
|
143
|
+
for (const [k, v] of Object.entries(raw.reference)) {
|
|
144
|
+
if (!powers.some((p) => String(p) === k))
|
|
145
|
+
refuse(`${where}.reference`, `'${k}' is not a declared power of this family`);
|
|
146
|
+
if (typeof v !== 'number' || !Number.isFinite(v))
|
|
147
|
+
refuse(`${where}.reference`, `'${k}' must be a finite number`);
|
|
148
|
+
reference[k] = v;
|
|
149
|
+
}
|
|
150
|
+
return { input: q.name, powers, reference };
|
|
137
151
|
}
|
|
138
152
|
/** One family `{input, powers}`, or a list of them, each in a different dimensionless input. */
|
|
139
153
|
function parseCorrection(raw, governing) {
|
|
@@ -159,7 +173,7 @@ function parseCorrection(raw, governing) {
|
|
|
159
173
|
/** Provenance text compared without case, spacing or punctuation: "Lab A" and "lab-a" are one source. */
|
|
160
174
|
const provenanceKey = (s) => s.toLowerCase().replace(/[^\p{L}\p{N}]+/gu, ' ').trim();
|
|
161
175
|
function parseProvenance(raw) {
|
|
162
|
-
if (!
|
|
176
|
+
if (!isPlainObject(raw))
|
|
163
177
|
refuse('provenance', 'is required: {"synthetic": true|false, "source": "..."}');
|
|
164
178
|
if (typeof raw.synthetic !== 'boolean') {
|
|
165
179
|
refuse('provenance.synthetic', 'must be declared true or false; it is never inferred');
|
|
@@ -182,7 +196,7 @@ function parseBaselines(raw, target, governing) {
|
|
|
182
196
|
const checker = builtinFormulaDimensionChecker();
|
|
183
197
|
return raw.map((b, i) => {
|
|
184
198
|
const where = `baselines[${i}]`;
|
|
185
|
-
if (!
|
|
199
|
+
if (!isPlainObject(b) || !nonEmptyString(b.name) || !nonEmptyString(b.formula)) {
|
|
186
200
|
refuse(where, 'needs {"name", "formula"}');
|
|
187
201
|
}
|
|
188
202
|
let vars;
|
|
@@ -210,7 +224,7 @@ function parseBaselines(raw, target, governing) {
|
|
|
210
224
|
function parseDesign(raw, governing) {
|
|
211
225
|
if (raw === undefined)
|
|
212
226
|
return undefined;
|
|
213
|
-
if (!
|
|
227
|
+
if (!isPlainObject(raw) || !isPlainObject(raw.variables))
|
|
214
228
|
refuse('design', 'needs {"variables": {name: {"min", "max"}}}');
|
|
215
229
|
const byName = new Map(governing.map((g) => [g.name, g]));
|
|
216
230
|
const out = {};
|
|
@@ -219,7 +233,7 @@ function parseDesign(raw, governing) {
|
|
|
219
233
|
const where = `design.variables.${name}`;
|
|
220
234
|
if (!q)
|
|
221
235
|
refuse(where, 'is not a declared governing input');
|
|
222
|
-
if (!
|
|
236
|
+
if (!isPlainObject(spec))
|
|
223
237
|
refuse(where, 'needs {"min", "max"}');
|
|
224
238
|
const min = toSi(spec.min, q, `${where}.min`, 'absolute');
|
|
225
239
|
const max = toSi(spec.max, q, `${where}.max`, 'absolute');
|
|
@@ -237,9 +251,9 @@ function parseObservations(raw, provenance, target, governing, defaultSigma) {
|
|
|
237
251
|
refuse('observations', 'must be a non-empty array');
|
|
238
252
|
const ids = new Set();
|
|
239
253
|
const rows = raw.map((row, i) => {
|
|
240
|
-
const id =
|
|
254
|
+
const id = isPlainObject(row) && nonEmptyString(row.id) ? row.id : `row-${i + 1}`;
|
|
241
255
|
const where = `observation ${id}`;
|
|
242
|
-
if (!
|
|
256
|
+
if (!isPlainObject(row))
|
|
243
257
|
refuse(where, 'is not an object');
|
|
244
258
|
for (const k of Object.keys(row)) {
|
|
245
259
|
if (!ROW_KEYS.has(k))
|
|
@@ -251,7 +265,7 @@ function parseObservations(raw, provenance, target, governing, defaultSigma) {
|
|
|
251
265
|
if (row.role !== 'exploratory' && row.role !== 'holdout' && row.role !== 'replication') {
|
|
252
266
|
refuse(where, `role must be exploratory, holdout or replication (got '${String(row.role)}')`);
|
|
253
267
|
}
|
|
254
|
-
if (!
|
|
268
|
+
if (!isPlainObject(row.values))
|
|
255
269
|
refuse(where, 'needs "values": {input: value}');
|
|
256
270
|
for (const k of Object.keys(row.values)) {
|
|
257
271
|
if (!governing.some((g) => g.name === k))
|
|
@@ -271,7 +285,7 @@ function parseObservations(raw, provenance, target, governing, defaultSigma) {
|
|
|
271
285
|
refuse(where, 'has no uncertainty: give "sigma" on the row or on the target');
|
|
272
286
|
}
|
|
273
287
|
const sigma = positiveSigma(sigmaRaw, target, `${where} sigma`);
|
|
274
|
-
if (row.inputSigma !== undefined && !
|
|
288
|
+
if (row.inputSigma !== undefined && !isPlainObject(row.inputSigma))
|
|
275
289
|
refuse(where, '"inputSigma" must be {input: σ}');
|
|
276
290
|
const rowInputSigma = (row.inputSigma ?? {});
|
|
277
291
|
for (const k of Object.keys(rowInputSigma)) {
|
|
@@ -329,7 +343,7 @@ function guardLeakage(rows) {
|
|
|
329
343
|
}
|
|
330
344
|
/** Parse and validate a study file. Throws {@link StudyRefusal}. @internal */
|
|
331
345
|
export function parseStudy(raw, source = 'inline') {
|
|
332
|
-
if (!
|
|
346
|
+
if (!isPlainObject(raw))
|
|
333
347
|
refuse(source, 'is not a JSON object');
|
|
334
348
|
for (const k of Object.keys(raw)) {
|
|
335
349
|
if (!TOP_KEYS.has(k))
|
|
@@ -344,7 +358,7 @@ export function parseStudy(raw, source = 'inline') {
|
|
|
344
358
|
const names = [target.name, ...governing.map((g) => g.name)];
|
|
345
359
|
if (new Set(names).size !== names.length)
|
|
346
360
|
refuse('governing', 'names must be distinct from each other and from the target');
|
|
347
|
-
const gapRaw =
|
|
361
|
+
const gapRaw = isPlainObject(raw.gap) ? raw.gap : {};
|
|
348
362
|
const gap = {
|
|
349
363
|
id: nonEmptyString(gapRaw.id) ? gapRaw.id : 'fg-study',
|
|
350
364
|
kind: nonEmptyString(gapRaw.kind) ? gapRaw.kind : 'unexplained-observation',
|
|
@@ -354,7 +368,7 @@ export function parseStudy(raw, source = 'inline') {
|
|
|
354
368
|
refuse('gap.kind', `unknown gap kind '${gap.kind}'`);
|
|
355
369
|
let alpha = DEFAULT_ALPHA;
|
|
356
370
|
if (raw.criterion !== undefined) {
|
|
357
|
-
if (!
|
|
371
|
+
if (!isPlainObject(raw.criterion) || typeof raw.criterion.alpha !== 'number') {
|
|
358
372
|
refuse('criterion', 'needs {"alpha": number}');
|
|
359
373
|
}
|
|
360
374
|
alpha = raw.criterion.alpha;
|
|
@@ -381,18 +395,12 @@ export function parseStudy(raw, source = 'inline') {
|
|
|
381
395
|
}
|
|
382
396
|
/** Load a study JSON file. @internal */
|
|
383
397
|
export function loadStudyFromJson(path) {
|
|
384
|
-
return parseStudy(
|
|
398
|
+
return parseStudy(readJsonFile(path), path);
|
|
385
399
|
}
|
|
386
400
|
function readStudyRaw(path) {
|
|
387
|
-
const text = readFileSync(path, 'utf8');
|
|
388
401
|
if (/\.csv$/i.test(path))
|
|
389
|
-
return studyCsvToRaw(
|
|
390
|
-
|
|
391
|
-
return JSON.parse(text);
|
|
392
|
-
}
|
|
393
|
-
catch (e) {
|
|
394
|
-
throw e instanceof SyntaxError ? new SyntaxError(`${path}: ${e.message}`) : e;
|
|
395
|
-
}
|
|
402
|
+
return studyCsvToRaw(readFileSync(path, 'utf8'), path);
|
|
403
|
+
return readJsonFile(path);
|
|
396
404
|
}
|
|
397
405
|
/**
|
|
398
406
|
* Load a study file (`.csv`, else JSON) and, optionally, a separate
|
|
@@ -414,7 +422,7 @@ const sameDim = (a, b) => a.name === b.name && equals(a.dim, b.dim);
|
|
|
414
422
|
* @internal
|
|
415
423
|
*/
|
|
416
424
|
export function attachReplication(study, raw, source) {
|
|
417
|
-
if (!
|
|
425
|
+
if (!isPlainObject(raw))
|
|
418
426
|
refuse(source, 'is not a JSON object');
|
|
419
427
|
for (const k of Object.keys(raw)) {
|
|
420
428
|
if (!REPLICATION_KEYS.has(k)) {
|
|
@@ -471,23 +479,31 @@ function closeness(chi2, dof, alpha) {
|
|
|
471
479
|
const pLower = chiSquareCdf(chi2, dof);
|
|
472
480
|
return { chi2, dof, pLower, flagged: pLower < alpha / 2 };
|
|
473
481
|
}
|
|
474
|
-
/**
|
|
482
|
+
/**
|
|
483
|
+
* Weighted straight line y = a + b·x with the effective variance σ_y² + b²σ_x², iterated from b = 1.
|
|
484
|
+
* The weighted sums are core `pairwiseDot` and `pairwiseSum` (the stable sums), not a `reduce`.
|
|
485
|
+
*/
|
|
475
486
|
function affineFit(pts) {
|
|
476
487
|
let b = 1;
|
|
477
488
|
let a = 0;
|
|
489
|
+
const xs = pts.map((p) => p.x);
|
|
490
|
+
const ys = pts.map((p) => p.y);
|
|
491
|
+
const variance = (slope) => pts.map((p) => p.sy ** 2 + slope * slope * p.sx ** 2);
|
|
478
492
|
for (let it = 0; it < 6; it++) {
|
|
479
|
-
const w =
|
|
480
|
-
const W = w
|
|
481
|
-
const xm =
|
|
482
|
-
const ym =
|
|
483
|
-
const
|
|
484
|
-
const
|
|
493
|
+
const w = variance(b).map((v) => 1 / v);
|
|
494
|
+
const W = pairwiseSum(w);
|
|
495
|
+
const xm = pairwiseDot(w, xs) / W;
|
|
496
|
+
const ym = pairwiseDot(w, ys) / W;
|
|
497
|
+
const dx = xs.map((x) => x - xm);
|
|
498
|
+
const sxx = pairwiseDot(w, dx.map((d) => d * d));
|
|
499
|
+
const sxy = pairwiseDot(w, dx.map((d, i) => d * (ys[i] - ym)));
|
|
485
500
|
if (!(sxx > 0) || !Number.isFinite(sxy))
|
|
486
501
|
return null;
|
|
487
502
|
b = sxy / sxx;
|
|
488
503
|
a = ym - b * xm;
|
|
489
504
|
}
|
|
490
|
-
const
|
|
505
|
+
const v = variance(b);
|
|
506
|
+
const chi2 = pairwiseSum(pts.map((p, i) => (p.y - a - b * p.x) ** 2 / v[i]));
|
|
491
507
|
return Number.isFinite(chi2) ? { a, b, chi2 } : null;
|
|
492
508
|
}
|
|
493
509
|
/**
|
|
@@ -596,7 +612,7 @@ function setPath(obj, path, value, where) {
|
|
|
596
612
|
for (const k of path.slice(0, -1)) {
|
|
597
613
|
if (at[k] === undefined)
|
|
598
614
|
at[k] = {};
|
|
599
|
-
if (!
|
|
615
|
+
if (!isPlainObject(at[k]))
|
|
600
616
|
refuse(where, `'${k}' is already set to a value`);
|
|
601
617
|
at = at[k];
|
|
602
618
|
}
|
|
@@ -632,7 +648,9 @@ export function studyCsvToRaw(text, source = 'inline.csv') {
|
|
|
632
648
|
const m = /^\s*#\s*([A-Za-z_][\w.()-]*)\s*:\s?(.*)$/.exec(l);
|
|
633
649
|
if (!m)
|
|
634
650
|
refuse(where, "a declaration is '# key: value'");
|
|
635
|
-
|
|
651
|
+
// Both groups are unconditional in the pattern, so a match carries them.
|
|
652
|
+
const key = m[1];
|
|
653
|
+
const valueText = m[2];
|
|
636
654
|
const value = declValue(valueText.trim());
|
|
637
655
|
const path = key.split('.');
|
|
638
656
|
if (key === 'target') {
|
|
@@ -702,13 +720,13 @@ export function studyCsvToRaw(text, source = 'inline.csv') {
|
|
|
702
720
|
if (!governing.some((g) => g.name === k))
|
|
703
721
|
refuse(`${source} governing.${k}.sigma`, `'${k}' is not a governing input column`);
|
|
704
722
|
}
|
|
705
|
-
if (
|
|
723
|
+
if (isPlainObject(raw.target)) {
|
|
706
724
|
for (const k of Object.keys(raw.target)) {
|
|
707
725
|
if (k !== 'sigma')
|
|
708
726
|
refuse(`${source} target.${k}`, "the target's name and unit come from its column; only 'target.sigma' is declared");
|
|
709
727
|
}
|
|
710
728
|
}
|
|
711
|
-
raw.target = { name: targetCol.name, unit: targetCol.unit, ...(
|
|
729
|
+
raw.target = { name: targetCol.name, unit: targetCol.unit, ...(isPlainObject(raw.target) ? raw.target : {}) };
|
|
712
730
|
raw.governing = governing.map((g) => ({
|
|
713
731
|
name: g.name,
|
|
714
732
|
unit: g.unit,
|
|
@@ -744,64 +762,23 @@ export function studyCsvToRaw(text, source = 'inline.csv') {
|
|
|
744
762
|
});
|
|
745
763
|
return raw;
|
|
746
764
|
}
|
|
747
|
-
// --- χ² survival
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
x += LANCZOS[i] / (zz + i);
|
|
759
|
-
const t = zz + 7.5;
|
|
760
|
-
return 0.5 * Math.log(2 * Math.PI) + (zz + 0.5) * Math.log(t) - t + Math.log(x);
|
|
761
|
-
}
|
|
762
|
-
/** The series for the regularized lower incomplete gamma P(a, x); converges fast for x < a + 1. */
|
|
763
|
-
function gammaSeries(a, x) {
|
|
764
|
-
const front = Math.exp(-x + a * Math.log(x) - lnGamma(a));
|
|
765
|
-
let ap = a;
|
|
766
|
-
let del = 1 / a;
|
|
767
|
-
let sum = del;
|
|
768
|
-
for (let n = 0; n < 1000; n++) {
|
|
769
|
-
ap += 1;
|
|
770
|
-
del *= x / ap;
|
|
771
|
-
sum += del;
|
|
772
|
-
if (Math.abs(del) < Math.abs(sum) * 1e-16)
|
|
773
|
-
break;
|
|
774
|
-
}
|
|
775
|
-
return sum * front;
|
|
765
|
+
// --- χ² and F survival functions ------------------------------------------
|
|
766
|
+
//
|
|
767
|
+
// MathTS carries the regularized lower incomplete gamma `gammainc` (the
|
|
768
|
+
// series for x < a + 1, else 1 − Q by continued fraction), the upper one
|
|
769
|
+
// `gammaincp` (from `@danielsimonjr/mathts-functions` 0.68.3 the modified
|
|
770
|
+
// Lentz continued fraction for x ≥ a + 1, computed directly; before that it
|
|
771
|
+
// was `1 − gammainc`, which rounded a far upper tail to 0, and the χ² p-value
|
|
772
|
+
// of a bad fit IS that tail) and the regularized incomplete beta `betainc`.
|
|
773
|
+
/** Regularized lower incomplete gamma P(a, x), MathTS `gammainc`. */
|
|
774
|
+
function gammaP(a, x) {
|
|
775
|
+
return numberFrom('gammainc', gammainc(a, x));
|
|
776
776
|
}
|
|
777
|
-
/** Regularized upper incomplete gamma Q(a, x). */
|
|
777
|
+
/** Regularized upper incomplete gamma Q(a, x), MathTS `gammaincp` (direct in the upper tail). */
|
|
778
778
|
function gammaQ(a, x) {
|
|
779
779
|
if (x <= 0)
|
|
780
780
|
return 1;
|
|
781
|
-
|
|
782
|
-
return Math.max(0, 1 - gammaSeries(a, x));
|
|
783
|
-
const front = Math.exp(-x + a * Math.log(x) - lnGamma(a));
|
|
784
|
-
const tiny = 1e-300;
|
|
785
|
-
let b = x + 1 - a;
|
|
786
|
-
let c = 1 / tiny;
|
|
787
|
-
let d = 1 / b;
|
|
788
|
-
let h = d;
|
|
789
|
-
for (let i = 1; i < 1000; i++) {
|
|
790
|
-
const an = -i * (i - a);
|
|
791
|
-
b += 2;
|
|
792
|
-
d = an * d + b;
|
|
793
|
-
if (Math.abs(d) < tiny)
|
|
794
|
-
d = tiny;
|
|
795
|
-
c = b + an / c;
|
|
796
|
-
if (Math.abs(c) < tiny)
|
|
797
|
-
c = tiny;
|
|
798
|
-
d = 1 / d;
|
|
799
|
-
const del = d * c;
|
|
800
|
-
h *= del;
|
|
801
|
-
if (Math.abs(del - 1) < 1e-16)
|
|
802
|
-
break;
|
|
803
|
-
}
|
|
804
|
-
return front * h;
|
|
781
|
+
return numberFrom('gammaincp', gammaincp(a, x));
|
|
805
782
|
}
|
|
806
783
|
/** P(χ²_ν ≥ chi2): the probability of a χ² at least this large if the model and σ are right. @internal */
|
|
807
784
|
export function chiSquareSurvival(chi2, dof) {
|
|
@@ -812,8 +789,8 @@ export function chiSquareSurvival(chi2, dof) {
|
|
|
812
789
|
return gammaQ(dof / 2, chi2 / 2);
|
|
813
790
|
}
|
|
814
791
|
/**
|
|
815
|
-
* P(χ²_ν ≤ chi2), computed directly in the lower tail
|
|
816
|
-
* round a small probability away. @internal
|
|
792
|
+
* P(χ²_ν ≤ chi2), computed directly in the lower tail (MathTS `gammainc` is
|
|
793
|
+
* the series there), where 1 − Q would round a small probability away. @internal
|
|
817
794
|
*/
|
|
818
795
|
export function chiSquareCdf(chi2, dof) {
|
|
819
796
|
if (!(dof > 0))
|
|
@@ -822,51 +799,15 @@ export function chiSquareCdf(chi2, dof) {
|
|
|
822
799
|
return 0;
|
|
823
800
|
const a = dof / 2;
|
|
824
801
|
const x = chi2 / 2;
|
|
825
|
-
return x < a + 1 ? Math.min(1,
|
|
826
|
-
}
|
|
827
|
-
/** Continued fraction for the incomplete beta function (modified Lentz). */
|
|
828
|
-
function betaCf(a, b, x) {
|
|
829
|
-
const tiny = 1e-300;
|
|
830
|
-
let c = 1;
|
|
831
|
-
let d = 1 - ((a + b) * x) / (a + 1);
|
|
832
|
-
if (Math.abs(d) < tiny)
|
|
833
|
-
d = tiny;
|
|
834
|
-
d = 1 / d;
|
|
835
|
-
let h = d;
|
|
836
|
-
for (let m = 1; m < 1000; m++) {
|
|
837
|
-
const m2 = 2 * m;
|
|
838
|
-
let aa = (m * (b - m) * x) / ((a + m2 - 1) * (a + m2));
|
|
839
|
-
d = 1 + aa * d;
|
|
840
|
-
if (Math.abs(d) < tiny)
|
|
841
|
-
d = tiny;
|
|
842
|
-
c = 1 + aa / c;
|
|
843
|
-
if (Math.abs(c) < tiny)
|
|
844
|
-
c = tiny;
|
|
845
|
-
d = 1 / d;
|
|
846
|
-
h *= d * c;
|
|
847
|
-
aa = (-(a + m) * (a + b + m) * x) / ((a + m2) * (a + m2 + 1));
|
|
848
|
-
d = 1 + aa * d;
|
|
849
|
-
if (Math.abs(d) < tiny)
|
|
850
|
-
d = tiny;
|
|
851
|
-
c = 1 + aa / c;
|
|
852
|
-
if (Math.abs(c) < tiny)
|
|
853
|
-
c = tiny;
|
|
854
|
-
d = 1 / d;
|
|
855
|
-
const del = d * c;
|
|
856
|
-
h *= del;
|
|
857
|
-
if (Math.abs(del - 1) < 1e-16)
|
|
858
|
-
break;
|
|
859
|
-
}
|
|
860
|
-
return h;
|
|
802
|
+
return x < a + 1 ? Math.min(1, gammaP(a, x)) : 1 - gammaQ(a, x);
|
|
861
803
|
}
|
|
862
|
-
/** Regularized incomplete beta I_x(a, b)
|
|
804
|
+
/** Regularized incomplete beta I_x(a, b), MathTS `betainc`. */
|
|
863
805
|
function betaI(a, b, x) {
|
|
864
806
|
if (x <= 0)
|
|
865
807
|
return 0;
|
|
866
808
|
if (x >= 1)
|
|
867
809
|
return 1;
|
|
868
|
-
|
|
869
|
-
return x < (a + 1) / (a + b + 2) ? (front * betaCf(a, b, x)) / a : 1 - (front * betaCf(b, a, 1 - x)) / b;
|
|
810
|
+
return numberFrom('betainc', betainc(a, b, x));
|
|
870
811
|
}
|
|
871
812
|
/** P(F_{d1,d2} ≥ f): the probability of an F ratio at least this large if the extra terms explain nothing. @internal */
|
|
872
813
|
export function fSurvival(f, d1, d2) {
|
|
@@ -880,22 +821,58 @@ export function fSurvival(f, d1, d2) {
|
|
|
880
821
|
}
|
|
881
822
|
/**
|
|
882
823
|
* The effective σ of one row under a model f: σ_eff² = σ_y² + Σ_i (∂f/∂x_i · σ_xi)²
|
|
883
|
-
* over the inputs with a σ,
|
|
884
|
-
*
|
|
824
|
+
* over the inputs with a σ, the GUM first-order propagation of MathTS
|
|
825
|
+
* `propagateUncertainty` (the one uncertainty path of the library, as in
|
|
826
|
+
* `composition/uncertainty.ts`), each partial a central difference with the
|
|
827
|
+
* relative step 1e-6·|x_i| at the recorded inputs. An input that is exactly
|
|
828
|
+
* zero has no relative step, so it is passed to MathTS shifted by
|
|
829
|
+
* c = 1e3·σ_xi and read back as z − c inside the model: the derivative is
|
|
830
|
+
* unchanged and the step is 1e-6·c = 1e-3·σ_xi, the floor the hand-coded
|
|
831
|
+
* difference used before. First order in σ_x: exact for f linear in x_i.
|
|
885
832
|
*
|
|
886
833
|
* @internal
|
|
887
834
|
*/
|
|
888
835
|
export function effectiveSigma(r, predict) {
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
836
|
+
const names = Object.keys(r.inputSigma);
|
|
837
|
+
if (names.length === 0)
|
|
838
|
+
return r.sigma;
|
|
839
|
+
const values = {};
|
|
840
|
+
const shift = {};
|
|
841
|
+
for (const name of names) {
|
|
842
|
+
const x = r.inputs[name] ?? NaN;
|
|
843
|
+
shift[name] = x === 0 ? 1e3 * r.inputSigma[name] : 0;
|
|
844
|
+
values[name] = x + shift[name];
|
|
845
|
+
}
|
|
846
|
+
const unshifted = (v) => {
|
|
847
|
+
const inputs = { ...r.inputs };
|
|
848
|
+
for (const name of names)
|
|
849
|
+
inputs[name] = v[name] - shift[name];
|
|
850
|
+
return inputs;
|
|
851
|
+
};
|
|
852
|
+
const notFinite = (name) => new RangeError(`the model's slope in ${name} is not finite on row ${r.id}`);
|
|
853
|
+
// MathTS varies one input at a time; the input being varied when the model is not finite is
|
|
854
|
+
// the one to name, read from the stencil point itself rather than from MathTS's message.
|
|
855
|
+
let culprit = null;
|
|
856
|
+
const model = (v) => {
|
|
857
|
+
const y = predict(unshifted(v));
|
|
858
|
+
if (!Number.isFinite(y) && culprit === null)
|
|
859
|
+
culprit = names.find((name) => v[name] !== values[name]) ?? names[0];
|
|
860
|
+
return y;
|
|
861
|
+
};
|
|
862
|
+
let u;
|
|
863
|
+
try {
|
|
864
|
+
u = propagateUncertainty(model, values, r.inputSigma, { relativeStep: 1e-6 });
|
|
865
|
+
}
|
|
866
|
+
catch (e) {
|
|
867
|
+
if (culprit !== null)
|
|
868
|
+
throw notFinite(culprit);
|
|
869
|
+
throw e;
|
|
870
|
+
}
|
|
871
|
+
for (const name of names) {
|
|
872
|
+
if (!Number.isFinite(u.partials[name]))
|
|
873
|
+
throw notFinite(name);
|
|
874
|
+
}
|
|
875
|
+
return Math.hypot(r.sigma, u.sigma);
|
|
899
876
|
}
|
|
900
877
|
const hasInputSigma = (rows) => rows.some((r) => Object.keys(r.inputSigma).length > 0);
|
|
901
878
|
function testRows(rows, predict, fitted, alpha) {
|
|
@@ -917,7 +894,42 @@ function testRows(rows, predict, fitted, alpha) {
|
|
|
917
894
|
return { n: rows.length, chi2, dof, p, maxAbsZ, worstRow, pass: p === null ? null : p >= alpha };
|
|
918
895
|
}
|
|
919
896
|
const combine = (basis, coef) => (x) => basis.reduce((s, b, j) => s + coef[j] * b(x), 0);
|
|
920
|
-
/**
|
|
897
|
+
/**
|
|
898
|
+
* The inverse of the equilibrated normal matrix B (k×k, unit diagonal), MathTS `inv`,
|
|
899
|
+
* unscaled back to the covariance of the coefficients: Σ = S⁻¹ B⁻¹ S⁻¹. Null when
|
|
900
|
+
* MathTS refuses the inverse or returns something other than a k×k number matrix.
|
|
901
|
+
*/
|
|
902
|
+
function covarianceOf(B, s) {
|
|
903
|
+
let raw;
|
|
904
|
+
try {
|
|
905
|
+
raw = inv(B.map((row) => [...row]));
|
|
906
|
+
}
|
|
907
|
+
catch {
|
|
908
|
+
return null;
|
|
909
|
+
}
|
|
910
|
+
const k = s.length;
|
|
911
|
+
if (!Array.isArray(raw) || raw.length !== k)
|
|
912
|
+
return null;
|
|
913
|
+
const out = [];
|
|
914
|
+
for (let a = 0; a < k; a++) {
|
|
915
|
+
const row = raw[a];
|
|
916
|
+
if (!Array.isArray(row) || row.length !== k)
|
|
917
|
+
return null;
|
|
918
|
+
const unscaled = [];
|
|
919
|
+
for (let b = 0; b < k; b++) {
|
|
920
|
+
const v = row[b];
|
|
921
|
+
if (typeof v !== 'number' || !Number.isFinite(v))
|
|
922
|
+
return null;
|
|
923
|
+
unscaled.push(v / (s[a] * s[b]));
|
|
924
|
+
}
|
|
925
|
+
out.push(unscaled);
|
|
926
|
+
}
|
|
927
|
+
return out;
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Solve the weighted normal equations for y ≈ Σ a_j·φ_j; null when they are singular.
|
|
931
|
+
* The covariance of the solution is the inverse of the same (equilibrated) matrix.
|
|
932
|
+
*/
|
|
921
933
|
function solveWeighted(phi, y, sigma) {
|
|
922
934
|
const k = phi[0]?.length ?? 0;
|
|
923
935
|
const A = Array.from({ length: k }, () => new Array(k + 1).fill(0));
|
|
@@ -929,8 +941,10 @@ function solveWeighted(phi, y, sigma) {
|
|
|
929
941
|
A[a][k] += w * f[a] * y[i];
|
|
930
942
|
}
|
|
931
943
|
});
|
|
932
|
-
if (k === 1)
|
|
933
|
-
|
|
944
|
+
if (k === 1) {
|
|
945
|
+
const a00 = A[0][0];
|
|
946
|
+
return a00 > 0 ? { coef: [A[0][1] / a00], covariance: [[1 / a00]] } : null;
|
|
947
|
+
}
|
|
934
948
|
// Equilibrate so the pivot test is scale-free, then eliminate with partial pivoting.
|
|
935
949
|
const s = A.map((row, a) => Math.sqrt(row[a]));
|
|
936
950
|
if (!s.every((v) => v > 0))
|
|
@@ -940,6 +954,7 @@ function solveWeighted(phi, y, sigma) {
|
|
|
940
954
|
A[a][b] /= s[a] * s[b];
|
|
941
955
|
A[a][k] /= s[a];
|
|
942
956
|
}
|
|
957
|
+
const covariance = covarianceOf(A.map((row) => row.slice(0, k)), s);
|
|
943
958
|
for (let c = 0; c < k; c++) {
|
|
944
959
|
let p = c;
|
|
945
960
|
for (let r = c + 1; r < k; r++)
|
|
@@ -956,13 +971,14 @@ function solveWeighted(phi, y, sigma) {
|
|
|
956
971
|
A[r][q] -= m * A[c][q];
|
|
957
972
|
}
|
|
958
973
|
}
|
|
959
|
-
return A.map((row, a) => row[k] / row[a] / s[a]);
|
|
974
|
+
return { coef: A.map((row, a) => row[k] / row[a] / s[a]), covariance };
|
|
960
975
|
}
|
|
961
976
|
const EV_ROUNDS = 50;
|
|
962
977
|
/**
|
|
963
978
|
* Weighted least squares y ≈ Σ a_j·φ_j(x), from the exploratory rows only.
|
|
964
979
|
* With input σ the weights are 1/σ_eff² of the current fit, iterated to a
|
|
965
|
-
* fixed point (the effective-variance method)
|
|
980
|
+
* fixed point (the effective-variance method); the covariance is that of the
|
|
981
|
+
* last solve, with the fixed-point weights.
|
|
966
982
|
*/
|
|
967
983
|
function fitLinear(rows, basis) {
|
|
968
984
|
const phi = rows.map((r) => basis.map((b) => {
|
|
@@ -972,20 +988,21 @@ function fitLinear(rows, basis) {
|
|
|
972
988
|
return f;
|
|
973
989
|
}));
|
|
974
990
|
const y = rows.map((r) => r.observed);
|
|
975
|
-
let
|
|
991
|
+
let sol = solveWeighted(phi, y, rows.map((r) => r.sigma));
|
|
976
992
|
if (!hasInputSigma(rows))
|
|
977
|
-
return
|
|
978
|
-
for (let round = 0;
|
|
993
|
+
return sol;
|
|
994
|
+
for (let round = 0; sol !== null && round < EV_ROUNDS; round++) {
|
|
995
|
+
const coef = sol.coef;
|
|
979
996
|
const predict = combine(basis, coef);
|
|
980
997
|
const next = solveWeighted(phi, y, rows.map((r) => effectiveSigma(r, predict)));
|
|
981
998
|
if (next === null)
|
|
982
999
|
return null;
|
|
983
|
-
const settled = next.every((a, j) => Math.abs(a - coef[j]) <= 1e-13 * Math.max(Math.abs(a), 1e-300));
|
|
984
|
-
|
|
1000
|
+
const settled = next.coef.every((a, j) => Math.abs(a - coef[j]) <= 1e-13 * Math.max(Math.abs(a), 1e-300));
|
|
1001
|
+
sol = next;
|
|
985
1002
|
if (settled)
|
|
986
1003
|
break;
|
|
987
1004
|
}
|
|
988
|
-
return
|
|
1005
|
+
return sol;
|
|
989
1006
|
}
|
|
990
1007
|
function split(study) {
|
|
991
1008
|
return {
|
|
@@ -1002,19 +1019,22 @@ function scoreModel(spec, sets, alpha, withheld) {
|
|
|
1002
1019
|
const { id, kind, label } = spec;
|
|
1003
1020
|
const k = spec.fit ? spec.basis.length : 0;
|
|
1004
1021
|
const failed = (error) => ({
|
|
1005
|
-
test: { id, kind, label, fittedParameters: k, prefactor: null, exploratory: null, holdout: null, replication: null, error },
|
|
1022
|
+
test: { id, kind, label, fittedParameters: k, prefactor: null, prefactorStderr: null, exploratory: null, holdout: null, replication: null, error },
|
|
1006
1023
|
predict: null,
|
|
1007
1024
|
coef: null,
|
|
1025
|
+
covariance: null,
|
|
1008
1026
|
});
|
|
1009
1027
|
try {
|
|
1010
|
-
const
|
|
1011
|
-
if (
|
|
1028
|
+
const sol = spec.fit ? fitLinear(sets.exploratory, spec.basis) : { coef: [1], covariance: null };
|
|
1029
|
+
if (sol === null) {
|
|
1012
1030
|
return failed(k === 1
|
|
1013
1031
|
? 'model is zero on every exploratory row; no scale can be fit'
|
|
1014
1032
|
: 'the model\'s terms are degenerate on the exploratory rows; they cannot be fit');
|
|
1015
1033
|
}
|
|
1034
|
+
const { coef, covariance } = sol;
|
|
1016
1035
|
const predict = combine(spec.basis, coef);
|
|
1017
1036
|
const on = (rows) => (withheld && rows.length > 0 ? testRows(rows, predict, 0, alpha) : null);
|
|
1037
|
+
const v00 = covariance?.[0]?.[0];
|
|
1018
1038
|
return {
|
|
1019
1039
|
test: {
|
|
1020
1040
|
id,
|
|
@@ -1022,12 +1042,14 @@ function scoreModel(spec, sets, alpha, withheld) {
|
|
|
1022
1042
|
label,
|
|
1023
1043
|
fittedParameters: k,
|
|
1024
1044
|
prefactor: coef[0],
|
|
1045
|
+
prefactorStderr: v00 !== undefined && v00 >= 0 ? Math.sqrt(v00) : null,
|
|
1025
1046
|
exploratory: sets.exploratory.length > 0 ? testRows(sets.exploratory, predict, k, alpha) : null,
|
|
1026
1047
|
holdout: on(sets.holdout),
|
|
1027
1048
|
replication: on(sets.replication),
|
|
1028
1049
|
},
|
|
1029
1050
|
predict,
|
|
1030
1051
|
coef,
|
|
1052
|
+
covariance,
|
|
1031
1053
|
};
|
|
1032
1054
|
}
|
|
1033
1055
|
catch (e) {
|
|
@@ -1050,8 +1072,8 @@ function correctionBasis(shape, terms) {
|
|
|
1050
1072
|
function admitCorrection(shape, families, rows, alpha) {
|
|
1051
1073
|
const chi2With = (terms) => {
|
|
1052
1074
|
const basis = correctionBasis(shape, terms);
|
|
1053
|
-
const
|
|
1054
|
-
return
|
|
1075
|
+
const sol = fitLinear(rows, basis);
|
|
1076
|
+
return sol === null ? null : testRows(rows, combine(basis, sol.coef), terms.length + 1, alpha).chi2;
|
|
1055
1077
|
};
|
|
1056
1078
|
const steps = [];
|
|
1057
1079
|
const admitted = [];
|
|
@@ -1060,23 +1082,25 @@ function admitCorrection(shape, families, rows, alpha) {
|
|
|
1060
1082
|
for (const power of family.powers) {
|
|
1061
1083
|
if (prev === null)
|
|
1062
1084
|
break families;
|
|
1063
|
-
const
|
|
1085
|
+
const reference = family.reference?.[String(power)];
|
|
1086
|
+
const term = { input: family.input, power, ...(reference !== undefined ? { reference } : {}) };
|
|
1064
1087
|
const trial = [...admitted, term];
|
|
1065
1088
|
const dof = rows.length - (trial.length + 1);
|
|
1066
1089
|
if (dof < 1) {
|
|
1067
|
-
steps.push({
|
|
1090
|
+
steps.push({ input: term.input, power: term.power, F: null, dof, p: null, admitted: false, reason: 'ν < 1: too few exploratory rows to test another term' });
|
|
1068
1091
|
break families;
|
|
1069
1092
|
}
|
|
1070
1093
|
const cur = chi2With(trial);
|
|
1071
1094
|
if (cur === null) {
|
|
1072
|
-
steps.push({
|
|
1095
|
+
steps.push({ input: term.input, power: term.power, F: null, dof, p: null, admitted: false, reason: 'degenerate with the terms before it on the exploratory rows' });
|
|
1073
1096
|
break;
|
|
1074
1097
|
}
|
|
1075
1098
|
const F = cur > 0 ? Math.max(0, prev - cur) / (cur / dof) : Infinity;
|
|
1076
1099
|
const p = fSurvival(F, 1, dof);
|
|
1077
1100
|
const ok = p < alpha;
|
|
1078
1101
|
steps.push({
|
|
1079
|
-
|
|
1102
|
+
input: term.input,
|
|
1103
|
+
power: term.power,
|
|
1080
1104
|
F,
|
|
1081
1105
|
dof,
|
|
1082
1106
|
p,
|
|
@@ -1127,9 +1151,10 @@ function credibility(t, nullTest, alpha) {
|
|
|
1127
1151
|
function designAgainst(study, sets, candidate, baselines) {
|
|
1128
1152
|
if (!candidate.predict)
|
|
1129
1153
|
return { abstained: true, reason: 'no credible candidate to discriminate' };
|
|
1130
|
-
const
|
|
1131
|
-
|
|
1132
|
-
|
|
1154
|
+
const predict = candidate.predict;
|
|
1155
|
+
// A live competitor has a predictor and passed on the exploratory rows; the guard types both.
|
|
1156
|
+
const isLive = (b) => b.predict !== null && b.test.exploratory?.pass === true;
|
|
1157
|
+
const live = baselines.filter(isLive).sort((a, b) => (b.test.exploratory.p ?? 0) - (a.test.exploratory.p ?? 0));
|
|
1133
1158
|
const best = live[0];
|
|
1134
1159
|
if (!best) {
|
|
1135
1160
|
return {
|
|
@@ -1158,7 +1183,7 @@ function designAgainst(study, sets, candidate, baselines) {
|
|
|
1158
1183
|
study.governing.forEach((g, i) => (point[g.name] = grids[i][idx[i]]));
|
|
1159
1184
|
let disc;
|
|
1160
1185
|
try {
|
|
1161
|
-
disc = Math.abs(
|
|
1186
|
+
disc = Math.abs(predict(point) - best.predict(point)) / sigma;
|
|
1162
1187
|
}
|
|
1163
1188
|
catch {
|
|
1164
1189
|
return;
|
|
@@ -1178,7 +1203,8 @@ function designAgainst(study, sets, candidate, baselines) {
|
|
|
1178
1203
|
if (bestPoint === null)
|
|
1179
1204
|
return { abstained: true, reason: 'neither model is finite anywhere in the design bounds' };
|
|
1180
1205
|
const chosen = bestPoint;
|
|
1181
|
-
|
|
1206
|
+
// A reduce, not a spread: a spread of a large row set overflows the call stack.
|
|
1207
|
+
const maxEx = sets.exploratory.reduce((m, r) => Math.max(m, Math.abs(predict(r.inputs) - best.predict(r.inputs)) / r.sigma), 0);
|
|
1182
1208
|
return {
|
|
1183
1209
|
abstained: false,
|
|
1184
1210
|
against: best.test.label,
|
|
@@ -1252,17 +1278,39 @@ export async function runProbeStudy(study, opts = {}) {
|
|
|
1252
1278
|
},
|
|
1253
1279
|
];
|
|
1254
1280
|
});
|
|
1255
|
-
const correctionOf = (s, coef) =>
|
|
1256
|
-
|
|
1281
|
+
const correctionOf = (s, coef, covariance) => {
|
|
1282
|
+
if (!('correction' in s) || !s.correction || !coef)
|
|
1283
|
+
return {};
|
|
1284
|
+
const a0 = coef[0];
|
|
1285
|
+
return {
|
|
1257
1286
|
correction: {
|
|
1258
1287
|
base: s.correction.base,
|
|
1259
|
-
terms: s.correction.terms.map((t, j) =>
|
|
1288
|
+
terms: s.correction.terms.map((t, j) => {
|
|
1289
|
+
const a = coef[j + 1];
|
|
1290
|
+
const coefficient = a / a0;
|
|
1291
|
+
// Delta method on c = a/a₀: Var(c) = Var(a)/a₀² + a²Var(a₀)/a₀⁴ − 2a·Cov(a, a₀)/a₀³.
|
|
1292
|
+
const cov = covariance;
|
|
1293
|
+
const variance = cov
|
|
1294
|
+
? cov[j + 1][j + 1] / a0 ** 2 + (a * a * cov[0][0]) / a0 ** 4 - (2 * a * cov[j + 1][0]) / a0 ** 3
|
|
1295
|
+
: null;
|
|
1296
|
+
const stderr = variance !== null && Number.isFinite(variance) ? Math.sqrt(Math.max(0, variance)) : null;
|
|
1297
|
+
const reference = t.reference;
|
|
1298
|
+
const z = reference !== undefined && stderr !== null && stderr > 0 ? (coefficient - reference) / stderr : undefined;
|
|
1299
|
+
return {
|
|
1300
|
+
input: t.input,
|
|
1301
|
+
power: t.power,
|
|
1302
|
+
coefficient,
|
|
1303
|
+
stderr,
|
|
1304
|
+
...(reference !== undefined ? { reference } : {}),
|
|
1305
|
+
...(z !== undefined ? { z } : {}),
|
|
1306
|
+
};
|
|
1307
|
+
}),
|
|
1260
1308
|
},
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1309
|
+
};
|
|
1310
|
+
};
|
|
1263
1311
|
const scored = specs.map((s) => {
|
|
1264
1312
|
const m = scoreModel(s.spec, sets, alpha, false);
|
|
1265
|
-
return { model: m, spec: s.spec, complexity: s.complexity, extra: correctionOf(s, m.coef), ...credibility(m.test, nullModel, alpha) };
|
|
1313
|
+
return { model: m, spec: s.spec, complexity: s.complexity, extra: correctionOf(s, m.coef, m.covariance), ...credibility(m.test, nullModel, alpha) };
|
|
1266
1314
|
});
|
|
1267
1315
|
const credibleOnes = scored
|
|
1268
1316
|
.filter((s) => s.credible)
|
|
@@ -1462,11 +1510,18 @@ export function formatProbeStudy(r) {
|
|
|
1462
1510
|
}
|
|
1463
1511
|
L.push(` null model (constant ${r.target.name}) — ${setLine('exploratory', r.nullModel.exploratory)}`);
|
|
1464
1512
|
L.push('');
|
|
1513
|
+
const pm = (stderr) => (stderr === null ? '' : ` ± ${stderr.toPrecision(2)}`);
|
|
1465
1514
|
for (const c of r.candidates) {
|
|
1466
|
-
const pre = c.prefactor === null ? '' : `, ĉ = ${c.prefactor.toPrecision(5)} (SI)`;
|
|
1515
|
+
const pre = c.prefactor === null ? '' : `, ĉ = ${c.prefactor.toPrecision(5)}${pm(c.prefactorStderr)} (SI)`;
|
|
1467
1516
|
L.push(` candidate ${c.id}: ${c.label}${pre}`);
|
|
1468
1517
|
if (c.correction) {
|
|
1469
|
-
|
|
1518
|
+
const term = (t, j) => {
|
|
1519
|
+
const against = t.z !== undefined && t.reference !== undefined
|
|
1520
|
+
? ` (z = ${t.z >= 0 ? '+' : ''}${t.z.toFixed(1)} against the declared ${Number(t.reference.toPrecision(4))})`
|
|
1521
|
+
: '';
|
|
1522
|
+
return `c${sub(j + 1)} = ${t.coefficient.toPrecision(4)}${pm(t.stderr)}${against}`;
|
|
1523
|
+
};
|
|
1524
|
+
L.push(` ${c.correction.terms.map(term).join(', ')} (fit on exploratory rows)`);
|
|
1470
1525
|
}
|
|
1471
1526
|
L.push(` ${setLine('exploratory', c.exploratory)}`);
|
|
1472
1527
|
L.push(` ${c.credible ? 'credible' : 'not credible'}: ${c.credibility}`);
|
|
@@ -1481,7 +1536,7 @@ export function formatProbeStudy(r) {
|
|
|
1481
1536
|
L.push('');
|
|
1482
1537
|
L.push(' baselines (declared by the file; same rows, same criterion):');
|
|
1483
1538
|
for (const b of r.baselines) {
|
|
1484
|
-
const how = b.fittedParameters === 0 ? 'fixed, no fitted parameter' : `prefactor fit on exploratory rows = ${b.prefactor?.toPrecision(5)}`;
|
|
1539
|
+
const how = b.fittedParameters === 0 ? 'fixed, no fitted parameter' : `prefactor fit on exploratory rows = ${b.prefactor?.toPrecision(5)}${pm(b.prefactorStderr)}`;
|
|
1485
1540
|
L.push(` ${b.label} [${how}]`);
|
|
1486
1541
|
if (b.error) {
|
|
1487
1542
|
L.push(` not evaluable: ${b.error}`);
|