universal-physics-tensor 10.0.0 → 12.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 +39 -36
- package/bin/upt.mjs +13 -1
- package/data/applied-cases.json +1892 -0
- package/data/applied-cases.schema.json +194 -0
- 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 +389 -230
- package/data/bridge-catalog.schema.json +45 -7
- package/data/units.json +6 -25
- 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 +9 -15
- 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 +35 -25
- package/dist/atlas/physjs-entries.generated.d.ts.map +1 -1
- package/dist/atlas/physjs-entries.generated.js +37 -25
- 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/catalog-checks.d.ts +10 -0
- package/dist/cases/catalog-checks.d.ts.map +1 -0
- package/dist/cases/catalog-checks.js +241 -0
- package/dist/cases/catalog-checks.js.map +1 -0
- package/dist/cases/catalog.d.ts +83 -0
- package/dist/cases/catalog.d.ts.map +1 -0
- package/dist/cases/catalog.js +118 -0
- package/dist/cases/catalog.js.map +1 -0
- package/dist/cases/engine.d.ts +13 -0
- package/dist/cases/engine.d.ts.map +1 -0
- package/dist/cases/engine.js +179 -0
- package/dist/cases/engine.js.map +1 -0
- package/dist/cases/index.d.ts.map +1 -1
- package/dist/cases/index.js +5 -7
- package/dist/cases/index.js.map +1 -1
- package/dist/cases/methods.d.ts +215 -0
- package/dist/cases/methods.d.ts.map +1 -0
- package/dist/cases/methods.js +743 -0
- package/dist/cases/methods.js.map +1 -0
- 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/types.d.ts +12 -0
- package/dist/cases/types.d.ts.map +1 -1
- package/dist/cases/types.js.map +1 -1
- package/dist/cli/args.d.ts +25 -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 +11 -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 +1 -0
- package/dist/cli/commands/_discovery-opts.d.ts.map +1 -1
- package/dist/cli/commands/_discovery-opts.js +9 -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 +122 -73
- 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 +67 -39
- 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 +24 -3
- 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 +7 -1
- 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 +84 -11
- 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/determination.d.ts +1 -0
- package/dist/cli/determination.d.ts.map +1 -1
- package/dist/cli/determination.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/flag-help.d.ts +1 -0
- package/dist/cli/flag-help.d.ts.map +1 -1
- package/dist/cli/flag-help.js +1 -0
- package/dist/cli/flag-help.js.map +1 -1
- package/dist/cli/graphs.d.ts +2 -0
- package/dist/cli/graphs.d.ts.map +1 -1
- package/dist/cli/graphs.js +1 -0
- package/dist/cli/graphs.js.map +1 -1
- package/dist/cli/main.d.ts +8 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +19 -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 +28 -0
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +23 -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 +12 -9
- 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 +1 -0
- package/dist/cli/version.d.ts.map +1 -1
- package/dist/cli/version.js +8 -5
- package/dist/cli/version.js.map +1 -1
- package/dist/cli-api.d.ts +36 -5
- package/dist/cli-api.d.ts.map +1 -1
- package/dist/cli-api.js +30 -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 +3 -3
- package/dist/composition/canonical-graph.d.ts.map +1 -1
- package/dist/composition/canonical-graph.js +11 -38
- 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/consequence.d.ts +15 -5
- package/dist/composition/consequence.d.ts.map +1 -1
- package/dist/composition/consequence.js +6 -4
- package/dist/composition/consequence.js.map +1 -1
- package/dist/composition/discovery.d.ts +129 -9
- package/dist/composition/discovery.d.ts.map +1 -1
- package/dist/composition/discovery.js +171 -67
- 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 +1 -1
- package/dist/composition/expr-eval.d.ts.map +1 -1
- package/dist/composition/expr-eval.js +6 -15
- package/dist/composition/expr-eval.js.map +1 -1
- package/dist/composition/expr-simplify.d.ts +26 -14
- package/dist/composition/expr-simplify.d.ts.map +1 -1
- package/dist/composition/expr-simplify.js +64 -72
- 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/grounding.d.ts.map +1 -1
- package/dist/composition/grounding.js +19 -7
- package/dist/composition/grounding.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 +7 -8
- package/dist/composition/mathts-quiet.d.ts.map +1 -1
- package/dist/composition/mathts-quiet.js +7 -16
- 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/own-equation-magnitude.d.ts +95 -0
- package/dist/composition/own-equation-magnitude.d.ts.map +1 -0
- package/dist/composition/own-equation-magnitude.js +270 -0
- package/dist/composition/own-equation-magnitude.js.map +1 -0
- package/dist/composition/probe/backend-protocol.d.ts +3 -0
- package/dist/composition/probe/backend-protocol.d.ts.map +1 -1
- package/dist/composition/probe/backend-protocol.js.map +1 -1
- package/dist/composition/probe/candidate-store.d.ts +1 -0
- package/dist/composition/probe/candidate-store.d.ts.map +1 -1
- package/dist/composition/probe/candidate-store.js +1 -0
- package/dist/composition/probe/candidate-store.js.map +1 -1
- package/dist/composition/probe/corpus.d.ts +8 -4
- package/dist/composition/probe/corpus.d.ts.map +1 -1
- package/dist/composition/probe/corpus.js +23 -12
- package/dist/composition/probe/corpus.js.map +1 -1
- package/dist/composition/probe/dataset.d.ts +18 -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 +7 -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 +2 -0
- 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 +7 -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 +30 -1
- package/dist/composition/probe/generator.d.ts.map +1 -1
- package/dist/composition/probe/generator.js +58 -36
- 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 +25 -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 +5 -0
- package/dist/composition/probe/pipeline.d.ts.map +1 -1
- package/dist/composition/probe/pipeline.js +73 -24
- 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 +251 -0
- package/dist/composition/probe/power-law.js.map +1 -0
- package/dist/composition/probe/problem.d.ts +8 -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 +7 -1
- package/dist/composition/probe/residual.d.ts.map +1 -1
- package/dist/composition/probe/residual.js +10 -7
- package/dist/composition/probe/residual.js.map +1 -1
- package/dist/composition/probe/run-manifest.d.ts +1 -0
- package/dist/composition/probe/run-manifest.d.ts.map +1 -1
- package/dist/composition/probe/run-manifest.js.map +1 -1
- package/dist/composition/probe/scalar-search.d.ts +50 -0
- package/dist/composition/probe/scalar-search.d.ts.map +1 -0
- package/dist/composition/probe/scalar-search.js +169 -0
- package/dist/composition/probe/scalar-search.js.map +1 -0
- package/dist/composition/probe/scoring.d.ts +1 -0
- package/dist/composition/probe/scoring.d.ts.map +1 -1
- package/dist/composition/probe/scoring.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 +235 -184
- package/dist/composition/probe/study.js.map +1 -1
- package/dist/composition/probe/t-tail.d.ts +16 -0
- package/dist/composition/probe/t-tail.d.ts.map +1 -0
- package/dist/composition/probe/t-tail.js +29 -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 +52 -12
- package/dist/composition/proposed-bridges.d.ts.map +1 -1
- package/dist/composition/proposed-bridges.js +107 -60
- 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 +29 -0
- package/dist/composition/representative-values.js.map +1 -1
- package/dist/composition/retrodiction.d.ts +15 -0
- package/dist/composition/retrodiction.d.ts.map +1 -1
- package/dist/composition/retrodiction.js +12 -4
- package/dist/composition/retrodiction.js.map +1 -1
- package/dist/composition/user-equation.d.ts +1 -0
- package/dist/composition/user-equation.d.ts.map +1 -1
- package/dist/composition/user-equation.js +3 -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 +42 -41
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +71 -51
- 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-ast-gradient.d.ts +27 -23
- package/dist/diff/bridge-ast-gradient.d.ts.map +1 -1
- package/dist/diff/bridge-ast-gradient.js +75 -173
- package/dist/diff/bridge-ast-gradient.js.map +1 -1
- 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/ast-types.d.ts +15 -0
- package/dist/dimensional/ast-types.d.ts.map +1 -1
- package/dist/dimensional/ast-types.js.map +1 -1
- 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/curvature-composite.d.ts +1 -1
- package/dist/dimensional/curvature-composite.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 +24 -11
- package/dist/dimensional/exact-scale.d.ts.map +1 -1
- package/dist/dimensional/exact-scale.js +122 -130
- 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/mathts-unit-delegation.d.ts +29 -0
- package/dist/dimensional/mathts-unit-delegation.d.ts.map +1 -0
- package/dist/dimensional/mathts-unit-delegation.js +187 -0
- package/dist/dimensional/mathts-unit-delegation.js.map +1 -0
- package/dist/dimensional/mathts-unit-wrapper.d.ts +33 -0
- package/dist/dimensional/mathts-unit-wrapper.d.ts.map +1 -0
- package/dist/dimensional/mathts-unit-wrapper.js +190 -0
- package/dist/dimensional/mathts-unit-wrapper.js.map +1 -0
- 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/scalar-lowering.d.ts +21 -0
- package/dist/dimensional/scalar-lowering.d.ts.map +1 -0
- package/dist/dimensional/scalar-lowering.js +45 -0
- package/dist/dimensional/scalar-lowering.js.map +1 -0
- 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.d.ts +5 -1
- package/dist/dimensional/unit-data.d.ts.map +1 -1
- package/dist/dimensional/unit-data.js +30 -6
- package/dist/dimensional/unit-data.js.map +1 -1
- package/dist/dimensional/units.d.ts +2 -0
- package/dist/dimensional/units.d.ts.map +1 -1
- package/dist/dimensional/units.js +59 -3
- package/dist/dimensional/units.js.map +1 -1
- package/dist/dimensional/validator.d.ts +2 -0
- package/dist/dimensional/validator.d.ts.map +1 -1
- package/dist/dimensional/validator.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/connection-lowering-helpers.d.ts +3 -1
- package/dist/numerical/connection-lowering-helpers.d.ts.map +1 -1
- package/dist/numerical/connection-lowering-helpers.js +11 -15
- package/dist/numerical/connection-lowering-helpers.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/pderiv.d.ts.map +1 -1
- package/dist/numerical/pderiv.js +2 -6
- package/dist/numerical/pderiv.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 +11 -13
- 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/strides.d.ts +3 -2
- package/dist/numerical/strides.d.ts.map +1 -1
- package/dist/numerical/strides.js +3 -10
- package/dist/numerical/strides.js.map +1 -1
- 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 +9 -12
- package/dist/cases/brownian-sphere.d.ts +0 -68
- package/dist/cases/brownian-sphere.d.ts.map +0 -1
- package/dist/cases/brownian-sphere.js +0 -354
- package/dist/cases/brownian-sphere.js.map +0 -1
- package/dist/cases/damped-resonator.d.ts +0 -23
- package/dist/cases/damped-resonator.d.ts.map +0 -1
- package/dist/cases/damped-resonator.js +0 -224
- package/dist/cases/damped-resonator.js.map +0 -1
- package/dist/cases/kepler-rv.d.ts +0 -13
- package/dist/cases/kepler-rv.d.ts.map +0 -1
- package/dist/cases/kepler-rv.js +0 -172
- package/dist/cases/kepler-rv.js.map +0 -1
- package/dist/cases/lumped-cooling.d.ts +0 -46
- package/dist/cases/lumped-cooling.d.ts.map +0 -1
- package/dist/cases/lumped-cooling.js +0 -261
- package/dist/cases/lumped-cooling.js.map +0 -1
- package/dist/cases/resistor-noise.d.ts +0 -14
- package/dist/cases/resistor-noise.d.ts.map +0 -1
- package/dist/cases/resistor-noise.js +0 -215
- package/dist/cases/resistor-noise.js.map +0 -1
- package/dist/cases/skin-depth.d.ts +0 -21
- package/dist/cases/skin-depth.d.ts.map +0 -1
- package/dist/cases/skin-depth.js +0 -174
- package/dist/cases/skin-depth.js.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Symbolic simplification of a scalar `ExprNode`
|
|
3
|
-
*
|
|
2
|
+
* Symbolic simplification of a scalar `ExprNode` through MathTS, a supplement
|
|
3
|
+
* to symbolic composition.
|
|
4
4
|
*
|
|
5
5
|
* Composing two bridges' symbolic forms leaves an UNSIMPLIFIED AST — CT-1 is
|
|
6
6
|
* `k_B·(ℏc³/8πG·mass·k_B)·ln2`, with `k_B` uncancelled. This folds it to the
|
|
7
7
|
* canonical `ℏc³·ln2/(8πG·mass)` using `@danielsimonjr/mathts-functions`'
|
|
8
|
-
* `simplify
|
|
8
|
+
* `simplify`, a required dependency.
|
|
9
9
|
*
|
|
10
10
|
* Pipeline (Adam+Eve-vetted — docs/planning/v0.12.0-Symbolic-Simplification-
|
|
11
11
|
* Design.md): GENSYM every non-exponent leaf to a mathjs-safe identifier
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* 3. numeric — `evalExpr` agrees over ≥2 finite synthesized probes at
|
|
20
20
|
* rel tol 1e-9 (Adam CRITICAL-2 / EVE-C).
|
|
21
21
|
* A representable result that DISAGREES dimensionally/numerically THROWS (a
|
|
22
|
-
* bug to surface); anything we cannot represent
|
|
22
|
+
* bug to surface); anything we cannot represent or verify degrades to a
|
|
23
23
|
* graceful no-op (return the original, `simplified:false`).
|
|
24
24
|
*
|
|
25
25
|
* INTERNAL — surfaced via `upt symbolic --simplify`.
|
|
@@ -30,10 +30,12 @@ import { validate } from '../dimensional/validator.js';
|
|
|
30
30
|
import { equals } from '../dimensional/algebra.js';
|
|
31
31
|
import { DIMENSIONLESS } from '../dimensional/types.js';
|
|
32
32
|
import { evalExpr } from './expr-eval.js';
|
|
33
|
-
import {
|
|
33
|
+
import { forEachScalarLeaf, isDecimalLiteral } from '../dimensional/ast-leaves.js';
|
|
34
|
+
import { isRegisteredConstant } from '../dimensional/symbolic-constants.js';
|
|
34
35
|
import { makeObservable } from './compose-symbolic.js';
|
|
35
36
|
import { renderScalarLeaf } from './mathts-scalar-symbols.js';
|
|
36
|
-
import {
|
|
37
|
+
import { parse as mathtsParse, simplify as mathtsSimplify } from '@danielsimonjr/mathts-functions';
|
|
38
|
+
import { quietlySync } from './mathts-quiet.js';
|
|
37
39
|
/** A simplification completed but produced a dimensionally/numerically wrong
|
|
38
40
|
* result (a real bug — not a graceful no-op). @internal */
|
|
39
41
|
class SimplificationError extends Error {
|
|
@@ -47,37 +49,29 @@ class SimplificationError extends Error {
|
|
|
47
49
|
class Unsupported extends Error {
|
|
48
50
|
}
|
|
49
51
|
// ---------------------------------------------------------------------------
|
|
50
|
-
//
|
|
51
|
-
// formula-registry.ts).
|
|
52
|
+
// The MathTS simplifier: a static import, bound once after a smoke test.
|
|
52
53
|
// ---------------------------------------------------------------------------
|
|
53
54
|
let cached;
|
|
54
|
-
/**
|
|
55
|
-
*
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// the smoke below is that first use. Later calls run with the console
|
|
62
|
-
// untouched.
|
|
63
|
-
return await quietly(async () => {
|
|
64
|
-
const mod = (await import('@danielsimonjr/mathts-functions'));
|
|
65
|
-
if (typeof mod.parse !== 'function' || typeof mod.simplify !== 'function') {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
// Smoke: g0 must cancel out of (g0)*((g1)/(g0)) → only g1 remains.
|
|
69
|
-
const s = mod.simplify(mod.parse('(g0)*((g1)/(g0))'));
|
|
70
|
-
const names = new Set();
|
|
71
|
-
collectMathSymbols(s, names);
|
|
72
|
-
return names.size === 1 && names.has('g1') ? mod : null;
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
55
|
+
/**
|
|
56
|
+
* `parse` and `simplify`, bound once after a smoke test that `simplify`
|
|
57
|
+
* CANCELS (`(g0)*((g1)/(g0))` must come back as `g1` alone). The smoke is the
|
|
58
|
+
* first use, so it runs inside the one console window (`mathts-quiet.ts`).
|
|
59
|
+
* MathTS is a required dependency, so a failed smoke is a defect of that
|
|
60
|
+
* dependency and throws; it is not read as an absent simplifier.
|
|
61
|
+
*/
|
|
79
62
|
function loadSimplifier() {
|
|
80
|
-
cached
|
|
63
|
+
if (cached !== undefined)
|
|
64
|
+
return cached;
|
|
65
|
+
const mod = {
|
|
66
|
+
parse: (text) => mathtsParse(text),
|
|
67
|
+
simplify: (node) => mathtsSimplify(node),
|
|
68
|
+
};
|
|
69
|
+
const names = new Set();
|
|
70
|
+
quietlySync(() => collectMathSymbols(mod.simplify(mod.parse('(g0)*((g1)/(g0))')), names));
|
|
71
|
+
if (names.size !== 1 || !names.has('g1')) {
|
|
72
|
+
throw new Error(`expr-simplify: MathTS simplify did not cancel g0 in the smoke test (left ${[...names].join(', ')})`);
|
|
73
|
+
}
|
|
74
|
+
cached = mod;
|
|
81
75
|
return cached;
|
|
82
76
|
}
|
|
83
77
|
function collectMathSymbols(n, out) {
|
|
@@ -88,11 +82,17 @@ function collectMathSymbols(n, out) {
|
|
|
88
82
|
for (const a of n.args ?? [])
|
|
89
83
|
collectMathSymbols(a, out);
|
|
90
84
|
}
|
|
91
|
-
const isLiteral =
|
|
92
|
-
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
|
|
85
|
+
const isLiteral = isDecimalLiteral;
|
|
86
|
+
/**
|
|
87
|
+
* Render a scalar ExprNode to a mathjs-safe, fully-parenthesized string,
|
|
88
|
+
* gensym'ing each non-literal leaf by NAME (so repeats share an identifier
|
|
89
|
+
* and can cancel). Throws on a non-scalar arm and on a non-literal exponent;
|
|
90
|
+
* `algebraic-equivalence.ts` renders both sides of a quotient through one
|
|
91
|
+
* gensym table with it.
|
|
92
|
+
*
|
|
93
|
+
* @internal
|
|
94
|
+
*/
|
|
95
|
+
export function renderGensym(expr, gensymOf, meta) {
|
|
96
96
|
switch (expr.kind) {
|
|
97
97
|
case 'symbol':
|
|
98
98
|
return renderScalarLeaf(expr, gensymOf, meta);
|
|
@@ -106,6 +106,13 @@ function renderGensym(expr, gensymOf, meta) {
|
|
|
106
106
|
}
|
|
107
107
|
if (expr.args.length === 0)
|
|
108
108
|
throw new Unsupported();
|
|
109
|
+
if (expr.args.length === 1) {
|
|
110
|
+
const arg = renderGensym(expr.args[0], gensymOf, meta);
|
|
111
|
+
if (expr.op === '-')
|
|
112
|
+
return `(-(${arg}))`;
|
|
113
|
+
if (expr.op === '+')
|
|
114
|
+
return `(${arg})`;
|
|
115
|
+
}
|
|
109
116
|
const parts = expr.args.map((a) => `(${renderGensym(a, gensymOf, meta)})`);
|
|
110
117
|
return `(${parts.join(expr.op)})`;
|
|
111
118
|
}
|
|
@@ -153,10 +160,12 @@ function walkBack(node, meta) {
|
|
|
153
160
|
args: [walkBack(args[0], meta), lit(exp.value)],
|
|
154
161
|
};
|
|
155
162
|
}
|
|
156
|
-
if (
|
|
163
|
+
if (op === '-' && args.length === 1) {
|
|
157
164
|
// unary minus → (-1) * arg
|
|
158
165
|
return { kind: 'op', op: '*', args: [lit(-1), walkBack(args[0], meta)] };
|
|
159
166
|
}
|
|
167
|
+
if (op === '+' && args.length === 1)
|
|
168
|
+
return walkBack(args[0], meta); // unary plus is the argument
|
|
160
169
|
if (op === '+' || op === '-' || op === '*' || op === '/') {
|
|
161
170
|
if (args.length < 2)
|
|
162
171
|
throw new Unsupported();
|
|
@@ -172,19 +181,7 @@ function walkBack(node, meta) {
|
|
|
172
181
|
// Guards.
|
|
173
182
|
// ---------------------------------------------------------------------------
|
|
174
183
|
function symbolNames(expr, out = []) {
|
|
175
|
-
|
|
176
|
-
out.push(expr.name);
|
|
177
|
-
else if (expr.kind === 'op')
|
|
178
|
-
for (const a of expr.args)
|
|
179
|
-
symbolNames(a, out);
|
|
180
|
-
else if (expr.kind === 'integral') {
|
|
181
|
-
symbolNames(expr.over, out);
|
|
182
|
-
symbolNames(expr.integrand, out);
|
|
183
|
-
}
|
|
184
|
-
else if (expr.kind === 'derivative') {
|
|
185
|
-
symbolNames(expr.of, out);
|
|
186
|
-
symbolNames(expr.wrt, out);
|
|
187
|
-
}
|
|
184
|
+
forEachScalarLeaf(expr, (leaf) => out.push(leaf.name), { integral: 'over+integrand', derivative: true });
|
|
188
185
|
return out;
|
|
189
186
|
}
|
|
190
187
|
const nonNumericSymbols = (expr) => symbolNames(expr).filter((n) => !isLiteral(n));
|
|
@@ -195,7 +192,7 @@ const PROBE_MULTIPLIERS = [1, 1.7, 0.41, 2.9];
|
|
|
195
192
|
* avoid accidental cancellation. <2 finite probes ⇒ 'insufficient' (cannot
|
|
196
193
|
* verify — EVE-C). */
|
|
197
194
|
function numericAgreement(original, candidate) {
|
|
198
|
-
const leaves = [...new Set(nonNumericSymbols(original))].filter((n) => !(n
|
|
195
|
+
const leaves = [...new Set(nonNumericSymbols(original))].filter((n) => !isRegisteredConstant(n));
|
|
199
196
|
let finiteProbes = 0;
|
|
200
197
|
for (const mult of PROBE_MULTIPLIERS) {
|
|
201
198
|
const values = {};
|
|
@@ -220,46 +217,41 @@ function numericAgreement(original, candidate) {
|
|
|
220
217
|
return finiteProbes >= 2 ? 'agree' : 'insufficient';
|
|
221
218
|
}
|
|
222
219
|
/**
|
|
223
|
-
* Whether the
|
|
224
|
-
* smoke test.
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
* and when it is present but could not reduce the expression, so a caller that
|
|
228
|
-
* must report WHY nothing happened (the atlas witness runner's `peer-absent`
|
|
229
|
-
* versus `not-simplified`) needs this separate signal. Shares the same cached
|
|
230
|
-
* detection, so it costs nothing after the first call.
|
|
220
|
+
* Whether the MathTS simplifier is usable. MathTS is a required dependency, so
|
|
221
|
+
* the answer is true; a simplifier that fails its smoke test throws instead.
|
|
222
|
+
* The atlas witness runner reads it to choose between the simplifier and its
|
|
223
|
+
* `peer-absent` path, which a caller still reaches by passing `null`.
|
|
231
224
|
*
|
|
232
225
|
* @internal
|
|
233
226
|
*/
|
|
234
227
|
export async function isSimplifierAvailable() {
|
|
235
|
-
|
|
228
|
+
loadSimplifier();
|
|
229
|
+
return true;
|
|
236
230
|
}
|
|
237
231
|
/**
|
|
238
232
|
* Simplify a scalar `ExprNode` via MathTS, guarded. Returns the original
|
|
239
|
-
* unchanged (`simplified:false`) when the
|
|
240
|
-
*
|
|
233
|
+
* unchanged (`simplified:false`) when the result cannot be represented or
|
|
234
|
+
* verified; THROWS {@link SimplificationError} only when a
|
|
241
235
|
* representable result disagrees dimensionally/numerically. See module docs.
|
|
242
236
|
*
|
|
243
237
|
* @internal
|
|
244
238
|
*/
|
|
245
239
|
export async function simplifyExpr(expr) {
|
|
246
|
-
const mod =
|
|
247
|
-
if (!mod)
|
|
248
|
-
return { expr, simplified: false };
|
|
240
|
+
const mod = loadSimplifier();
|
|
249
241
|
const gensymOf = new Map();
|
|
250
242
|
const meta = new Map();
|
|
251
243
|
let candidate;
|
|
252
244
|
try {
|
|
253
245
|
const str = renderGensym(expr, gensymOf, meta);
|
|
254
|
-
//
|
|
246
|
+
// MathTS can THROW on some forms (e.g. a known mathts `simplify` BigInt
|
|
255
247
|
// bug on nested `a/(b/c²)`); that, like an unsupported node, is a graceful
|
|
256
|
-
// no-op, not an error. The console is not touched here: the
|
|
257
|
-
//
|
|
248
|
+
// no-op, not an error. The console is not touched here: the first use
|
|
249
|
+
// already ran inside `loadSimplifier`'s window.
|
|
258
250
|
const simplifiedNode = mod.simplify(mod.parse(str));
|
|
259
251
|
candidate = walkBack(simplifiedNode, meta);
|
|
260
252
|
}
|
|
261
253
|
catch {
|
|
262
|
-
return { expr, simplified: false }; // unsupported / unrepresentable /
|
|
254
|
+
return { expr, simplified: false }; // unsupported / unrepresentable / MathTS threw
|
|
263
255
|
}
|
|
264
256
|
// Guard 1 — dimensional. Inability to validate ⇒ no-op; a CHANGED dimension
|
|
265
257
|
// is a representable disagreement ⇒ throw.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expr-simplify.js","sourceRoot":"","sources":["../../src/composition/expr-simplify.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Symbolic simplification of a scalar `ExprNode` via MathTS (v0.12 — optional\n * supplement to symbolic composition).\n *\n * Composing two bridges' symbolic forms leaves an UNSIMPLIFIED AST — CT-1 is\n * `k_B·(ℏc³/8πG·mass·k_B)·ln2`, with `k_B` uncancelled. This folds it to the\n * canonical `ℏc³·ln2/(8πG·mass)` using `@danielsimonjr/mathts-functions`'\n * `simplify` (the same OPTIONAL peer the Path-A formula parser loads).\n *\n * Pipeline (Adam+Eve-vetted — docs/planning/v0.12.0-Symbolic-Simplification-\n * Design.md): GENSYM every non-exponent leaf to a mathjs-safe identifier\n * (shared by name, so repeated leaves cancel), render FULLY-PARENTHESIZED\n * (EVE-A — no precedence ambiguity), `parse`+`simplify`, walk the result back\n * (un-gensym, INTEGER-exponent-strict — EVE/Adam HIGH-1). Three guards make a\n * black-box CAS safe to trust:\n * 1. dimensional — `validate(simplified)` dim `equals` the original's;\n * 2. structural — non-numeric symbols of the result ⊆ those of the original\n * (no leaf invented — Adam HIGH-2 / EVE-B);\n * 3. numeric — `evalExpr` agrees over ≥2 finite synthesized probes at\n * rel tol 1e-9 (Adam CRITICAL-2 / EVE-C).\n * A representable result that DISAGREES dimensionally/numerically THROWS (a\n * bug to surface); anything we cannot represent / verify / load degrades to a\n * graceful no-op (return the original, `simplified:false`).\n *\n * INTERNAL — surfaced via `upt symbolic --simplify`.\n *\n * @module composition/expr-simplify\n */\n\nimport type { ExprNode } from '../dimensional/validator.js';\nimport { validate } from '../dimensional/validator.js';\nimport { equals } from '../dimensional/algebra.js';\nimport type { Dimension } from '../dimensional/types.js';\nimport { DIMENSIONLESS } from '../dimensional/types.js';\nimport { evalExpr } from './expr-eval.js';\nimport { CONSTANTS } from '../dimensional/symbolic-constants.js';\nimport type { Observable } from './compose-symbolic.js';\nimport { makeObservable } from './compose-symbolic.js';\nimport { renderScalarLeaf } from './mathts-scalar-symbols.js';\nimport { quietly } from './mathts-quiet.js';\n\n/** A simplification completed but produced a dimensionally/numerically wrong\n * result (a real bug — not a graceful no-op). @internal */\nclass SimplificationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SimplificationError';\n }\n}\n\n/** The bits of a MathTS (mathjs-style) AST node the walk-back reads — pinned\n * + runtime-verified (Adam CRITICAL-1). */\ninterface MathNode {\n readonly type?: string;\n readonly op?: string;\n readonly name?: string;\n readonly value?: unknown;\n readonly args?: MathNode[];\n readonly content?: MathNode;\n toString(): string;\n}\ninterface MathtsSimplifyModule {\n parse(expr: string): MathNode;\n simplify(node: MathNode): MathNode;\n}\n\n/** Thrown internally when a node cannot be rendered/walked — caught and turned\n * into a graceful no-op (never escapes the module). */\nclass Unsupported extends Error {}\n\n// ---------------------------------------------------------------------------\n// Optional-peer load — cache + quietly + simplify-smoke (mirrors\n// formula-registry.ts).\n// ---------------------------------------------------------------------------\n\nlet cached: Promise<MathtsSimplifyModule | null> | undefined;\n\n/** Load + smoke-test the peer. A peer with `parse` but a missing/broken\n * `simplify` (it must actually CANCEL) is rejected → null (graceful no-op). */\nasync function detect(): Promise<MathtsSimplifyModule | null> {\n try {\n // Import AND smoke-test inside the ONE suppression window this module\n // opens (`mathts-quiet.ts` states the invariant): the WASM-fallback\n // chatter fires lazily on first parse/simplify, not only at import, and\n // the smoke below is that first use. Later calls run with the console\n // untouched.\n return await quietly(async () => {\n const mod = (await import(\n '@danielsimonjr/mathts-functions'\n )) as unknown as MathtsSimplifyModule;\n if (typeof mod.parse !== 'function' || typeof mod.simplify !== 'function') {\n return null;\n }\n // Smoke: g0 must cancel out of (g0)*((g1)/(g0)) → only g1 remains.\n const s = mod.simplify(mod.parse('(g0)*((g1)/(g0))'));\n const names = new Set<string>();\n collectMathSymbols(s, names);\n return names.size === 1 && names.has('g1') ? mod : null;\n });\n } catch {\n return null;\n }\n}\n\nfunction loadSimplifier(): Promise<MathtsSimplifyModule | null> {\n cached ??= detect();\n return cached;\n}\n\nfunction collectMathSymbols(n: MathNode, out: Set<string>): void {\n if (n.type === 'SymbolNode' && n.name) out.add(n.name);\n if (n.content) collectMathSymbols(n.content, out);\n for (const a of n.args ?? []) collectMathSymbols(a, out);\n}\n\n// ---------------------------------------------------------------------------\n// ExprNode → gensym string (fully parenthesized) and back.\n// ---------------------------------------------------------------------------\n\ninterface LeafMeta {\n readonly name: string;\n readonly dim: Dimension;\n}\n\nconst isLiteral = (name: string): boolean => Number.isFinite(Number(name));\n\n/** Render a scalar ExprNode to a mathjs-safe, fully-parenthesized string,\n * gensym'ing each non-literal leaf by NAME (so repeats share an identifier\n * and can cancel). Throws `Unsupported` on non-scalar arms. */\nfunction renderGensym(\n expr: ExprNode,\n gensymOf: Map<string, string>,\n meta: Map<string, LeafMeta>,\n): string {\n switch (expr.kind) {\n case 'symbol':\n return renderScalarLeaf(expr, gensymOf, meta);\n case 'op': {\n if (expr.op === '^') {\n const exp = expr.args[1];\n if (!exp || exp.kind !== 'symbol' || !isLiteral(exp.name)) {\n throw new Unsupported();\n }\n return `(${renderGensym(expr.args[0], gensymOf, meta)})^${Number(exp.name)}`;\n }\n if (expr.args.length === 0) throw new Unsupported();\n const parts = expr.args.map((a) => `(${renderGensym(a, gensymOf, meta)})`);\n return `(${parts.join(expr.op)})`;\n }\n default:\n throw new Unsupported(); // integral / derivative / tensor arms\n }\n}\n\nconst lit = (v: number): ExprNode => ({ kind: 'symbol', name: String(v), dim: DIMENSIONLESS });\n\n/** Walk a simplified MathTS node back to an ExprNode, un-gensym'ing leaves and\n * rejecting anything outside UPT's integer-exponent scalar model (→ throws\n * `Unsupported`, a graceful no-op). */\nfunction walkBack(node: MathNode, meta: Map<string, LeafMeta>): ExprNode {\n switch (node.type) {\n case 'ConstantNode': {\n if (typeof node.value !== 'number' || !Number.isFinite(node.value)) {\n throw new Unsupported();\n }\n return lit(node.value);\n }\n case 'SymbolNode': {\n const m = node.name !== undefined ? meta.get(node.name) : undefined;\n if (!m) throw new Unsupported(); // a symbol we did not issue\n return { kind: 'symbol', name: m.name, dim: m.dim };\n }\n case 'ParenthesisNode':\n if (!node.content) throw new Unsupported();\n return walkBack(node.content, meta);\n case 'OperatorNode': {\n const op = node.op;\n const args = node.args ?? [];\n if (op === '^') {\n if (args.length !== 2) throw new Unsupported();\n const exp = args[1];\n if (\n exp.type !== 'ConstantNode' ||\n typeof exp.value !== 'number' ||\n !Number.isInteger(exp.value)\n ) {\n throw new Unsupported(); // non-integer exponent — not in ℤ⁷ model\n }\n return {\n kind: 'op',\n op: '^',\n args: [walkBack(args[0], meta), lit(exp.value)],\n };\n }\n if ((op === '+' || op === '-') && args.length === 1) {\n // unary minus → (-1) * arg\n return { kind: 'op', op: '*', args: [lit(-1), walkBack(args[0], meta)] };\n }\n if (op === '+' || op === '-' || op === '*' || op === '/') {\n if (args.length < 2) throw new Unsupported();\n return { kind: 'op', op, args: args.map((a) => walkBack(a, meta)) };\n }\n throw new Unsupported();\n }\n default:\n throw new Unsupported(); // FunctionNode (sqrt/cbrt/…) etc.\n }\n}\n\n// ---------------------------------------------------------------------------\n// Guards.\n// ---------------------------------------------------------------------------\n\nfunction symbolNames(expr: ExprNode, out: string[] = []): string[] {\n if (expr.kind === 'symbol') out.push(expr.name);\n else if (expr.kind === 'op') for (const a of expr.args) symbolNames(a, out);\n else if (expr.kind === 'integral') {\n symbolNames(expr.over, out);\n symbolNames(expr.integrand, out);\n } else if (expr.kind === 'derivative') {\n symbolNames(expr.of, out);\n symbolNames(expr.wrt, out);\n }\n return out;\n}\n\nconst nonNumericSymbols = (expr: ExprNode): string[] =>\n symbolNames(expr).filter((n) => !isLiteral(n));\n\nconst PROBE_VALUES = [2.3, 3.7, 5.1, 7.9, 11.3, 13.1, 17.9, 19.3];\nconst PROBE_MULTIPLIERS = [1, 1.7, 0.41, 2.9];\n\n/** Numeric agreement of `original` and `candidate` over synthesized probes.\n * Free (non-constant) leaves get distinct, mutually-incommensurate values to\n * avoid accidental cancellation. <2 finite probes ⇒ 'insufficient' (cannot\n * verify — EVE-C). */\nfunction numericAgreement(\n original: ExprNode,\n candidate: ExprNode,\n): 'agree' | 'disagree' | 'insufficient' {\n const leaves = [...new Set(nonNumericSymbols(original))].filter(\n (n) => !(n in CONSTANTS),\n );\n let finiteProbes = 0;\n for (const mult of PROBE_MULTIPLIERS) {\n const values: Record<string, number> = {};\n leaves.forEach((leaf, i) => {\n values[leaf] = PROBE_VALUES[i % PROBE_VALUES.length] * mult;\n });\n let a: number;\n let b: number;\n try {\n a = evalExpr(original, values);\n b = evalExpr(candidate, values);\n } catch {\n continue; // a probe drove evalExpr non-finite — skip it\n }\n if (!Number.isFinite(a) || !Number.isFinite(b)) continue;\n finiteProbes++;\n if (Math.abs(a - b) / Math.abs(b || 1) > 1e-9) return 'disagree';\n }\n return finiteProbes >= 2 ? 'agree' : 'insufficient';\n}\n\n// ---------------------------------------------------------------------------\n// Public entry points.\n// ---------------------------------------------------------------------------\n\n/** The result of attempting to simplify an expression. */\ninterface SimplifyResult {\n readonly expr: ExprNode;\n /** True iff MathTS was present AND produced a guard-passing, distinct form. */\n readonly simplified: boolean;\n}\n\n/**\n * Whether the optional MathTS simplifier peer is installed AND passes its\n * smoke test.\n *\n * {@link simplifyExpr} returns `simplified: false` both when the peer is absent\n * and when it is present but could not reduce the expression, so a caller that\n * must report WHY nothing happened (the atlas witness runner's `peer-absent`\n * versus `not-simplified`) needs this separate signal. Shares the same cached\n * detection, so it costs nothing after the first call.\n *\n * @internal\n */\nexport async function isSimplifierAvailable(): Promise<boolean> {\n return (await loadSimplifier()) !== null;\n}\n\n/**\n * Simplify a scalar `ExprNode` via MathTS, guarded. Returns the original\n * unchanged (`simplified:false`) when the peer is absent or the result cannot\n * be represented/verified; THROWS {@link SimplificationError} only when a\n * representable result disagrees dimensionally/numerically. See module docs.\n *\n * @internal\n */\nexport async function simplifyExpr(expr: ExprNode): Promise<SimplifyResult> {\n const mod = await loadSimplifier();\n if (!mod) return { expr, simplified: false };\n\n const gensymOf = new Map<string, string>();\n const meta = new Map<string, LeafMeta>();\n let candidate: ExprNode;\n try {\n const str = renderGensym(expr, gensymOf, meta);\n // The peer can THROW on some forms (e.g. a known mathts `simplify` BigInt\n // bug on nested `a/(b/c²)`); that, like an unsupported node, is a graceful\n // no-op, not an error. The console is not touched here: the peer's first\n // use already ran inside `detect`'s load window.\n const simplifiedNode = mod.simplify(mod.parse(str));\n candidate = walkBack(simplifiedNode, meta);\n } catch {\n return { expr, simplified: false }; // unsupported / unrepresentable / peer threw\n }\n\n // Guard 1 — dimensional. Inability to validate ⇒ no-op; a CHANGED dimension\n // is a representable disagreement ⇒ throw.\n const origDim = validate(expr).inferredDimension;\n // A literal ZERO carries every dimension: `x − x` with `x` a length is a zero\n // LENGTH, but the CAS hands back a bare dimensionless `0`. Re-stamp it with\n // the original dimension, or this guard would reject every exact\n // cancellation of a dimensioned expression as a \"changed dimension\".\n if (\n origDim !== null &&\n candidate.kind === 'symbol' &&\n candidate.name.trim() !== '' &&\n Number(candidate.name) === 0\n ) {\n candidate = { kind: 'symbol', name: '0', dim: origDim };\n }\n const newResult = validate(candidate);\n if (origDim === null || !newResult.ok || newResult.inferredDimension === null) {\n return { expr, simplified: false };\n }\n if (!equals(origDim, newResult.inferredDimension)) {\n throw new SimplificationError(\n `simplifyExpr: the simplified form changed dimension — a CAS or ` +\n `walk-back error.`,\n );\n }\n\n // Guard 2 — structural subset (no non-numeric leaf invented).\n const origSyms = new Set(nonNumericSymbols(expr));\n for (const s of nonNumericSymbols(candidate)) {\n if (!origSyms.has(s)) return { expr, simplified: false }; // suspicious ⇒ no-op\n }\n\n // Guard 3 — numeric agreement.\n const verdict = numericAgreement(expr, candidate);\n if (verdict === 'disagree') {\n throw new SimplificationError(\n `simplifyExpr: the simplified form disagrees numerically with the ` +\n `original — a CAS or walk-back error.`,\n );\n }\n if (verdict === 'insufficient') return { expr, simplified: false };\n\n // Identical-structure ⇒ nothing gained; report not simplified.\n const changed = symbolNames(candidate).length !== symbolNames(expr).length;\n return { expr: candidate, simplified: changed };\n}\n\n/**\n * Simplify a composed {@link Observable}: returns a freshly-RECONSTRUCTED\n * Observable (new strict `evaluate` closure over the simplified `expr` +\n * recomputed `leaves`) when simplification succeeds, else the original\n * unchanged. See module docs.\n *\n * @internal\n */\nexport async function simplifyObservable(obs: Observable): Promise<Observable> {\n const { expr, simplified } = await simplifyExpr(obs.expr);\n if (!simplified) return obs;\n return makeObservable(obs.name, obs.symbol, obs.dim, expr);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"expr-simplify.js","sourceRoot":"","sources":["../../src/composition/expr-simplify.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Symbolic simplification of a scalar `ExprNode` through MathTS, a supplement\n * to symbolic composition.\n *\n * Composing two bridges' symbolic forms leaves an UNSIMPLIFIED AST — CT-1 is\n * `k_B·(ℏc³/8πG·mass·k_B)·ln2`, with `k_B` uncancelled. This folds it to the\n * canonical `ℏc³·ln2/(8πG·mass)` using `@danielsimonjr/mathts-functions`'\n * `simplify`, a required dependency.\n *\n * Pipeline (Adam+Eve-vetted — docs/planning/v0.12.0-Symbolic-Simplification-\n * Design.md): GENSYM every non-exponent leaf to a mathjs-safe identifier\n * (shared by name, so repeated leaves cancel), render FULLY-PARENTHESIZED\n * (EVE-A — no precedence ambiguity), `parse`+`simplify`, walk the result back\n * (un-gensym, INTEGER-exponent-strict — EVE/Adam HIGH-1). Three guards make a\n * black-box CAS safe to trust:\n * 1. dimensional — `validate(simplified)` dim `equals` the original's;\n * 2. structural — non-numeric symbols of the result ⊆ those of the original\n * (no leaf invented — Adam HIGH-2 / EVE-B);\n * 3. numeric — `evalExpr` agrees over ≥2 finite synthesized probes at\n * rel tol 1e-9 (Adam CRITICAL-2 / EVE-C).\n * A representable result that DISAGREES dimensionally/numerically THROWS (a\n * bug to surface); anything we cannot represent or verify degrades to a\n * graceful no-op (return the original, `simplified:false`).\n *\n * INTERNAL — surfaced via `upt symbolic --simplify`.\n *\n * @module composition/expr-simplify\n */\n\nimport type { ExprNode } from '../dimensional/validator.js';\nimport { validate } from '../dimensional/validator.js';\nimport { equals } from '../dimensional/algebra.js';\nimport type { Dimension } from '../dimensional/types.js';\nimport { DIMENSIONLESS } from '../dimensional/types.js';\nimport { evalExpr } from './expr-eval.js';\nimport { forEachScalarLeaf, isDecimalLiteral } from '../dimensional/ast-leaves.js';\nimport { isRegisteredConstant } from '../dimensional/symbolic-constants.js';\nimport type { Observable } from './compose-symbolic.js';\nimport { makeObservable } from './compose-symbolic.js';\nimport { renderScalarLeaf } from './mathts-scalar-symbols.js';\nimport { parse as mathtsParse, simplify as mathtsSimplify } from '@danielsimonjr/mathts-functions';\nimport { quietlySync } from './mathts-quiet.js';\n\n/** A simplification completed but produced a dimensionally/numerically wrong\n * result (a real bug — not a graceful no-op). @internal */\nclass SimplificationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SimplificationError';\n }\n}\n\n/** The bits of a MathTS (mathjs-style) AST node the walk-back reads — pinned\n * + runtime-verified (Adam CRITICAL-1). */\ninterface MathNode {\n readonly type?: string;\n readonly op?: string;\n readonly name?: string;\n readonly value?: unknown;\n readonly args?: MathNode[];\n readonly content?: MathNode;\n toString(): string;\n}\ninterface MathtsSimplifyModule {\n parse(expr: string): MathNode;\n simplify(node: MathNode): MathNode;\n}\n\n/** Thrown internally when a node cannot be rendered/walked — caught and turned\n * into a graceful no-op (never escapes the module). */\nclass Unsupported extends Error {}\n\n// ---------------------------------------------------------------------------\n// The MathTS simplifier: a static import, bound once after a smoke test.\n// ---------------------------------------------------------------------------\n\nlet cached: MathtsSimplifyModule | undefined;\n\n/**\n * `parse` and `simplify`, bound once after a smoke test that `simplify`\n * CANCELS (`(g0)*((g1)/(g0))` must come back as `g1` alone). The smoke is the\n * first use, so it runs inside the one console window (`mathts-quiet.ts`).\n * MathTS is a required dependency, so a failed smoke is a defect of that\n * dependency and throws; it is not read as an absent simplifier.\n */\nfunction loadSimplifier(): MathtsSimplifyModule {\n if (cached !== undefined) return cached;\n const mod: MathtsSimplifyModule = {\n parse: (text) => mathtsParse(text) as unknown as MathNode,\n simplify: (node) => mathtsSimplify(node as never) as unknown as MathNode,\n };\n const names = new Set<string>();\n quietlySync(() => collectMathSymbols(mod.simplify(mod.parse('(g0)*((g1)/(g0))')), names));\n if (names.size !== 1 || !names.has('g1')) {\n throw new Error(`expr-simplify: MathTS simplify did not cancel g0 in the smoke test (left ${[...names].join(', ')})`);\n }\n cached = mod;\n return cached;\n}\n\nfunction collectMathSymbols(n: MathNode, out: Set<string>): void {\n if (n.type === 'SymbolNode' && n.name) out.add(n.name);\n if (n.content) collectMathSymbols(n.content, out);\n for (const a of n.args ?? []) collectMathSymbols(a, out);\n}\n\n// ---------------------------------------------------------------------------\n// ExprNode → gensym string (fully parenthesized) and back.\n// ---------------------------------------------------------------------------\n\n/** The leaf a gensym stands for: its name and dimension. @internal */\nexport interface LeafMeta {\n readonly name: string;\n readonly dim: Dimension;\n}\n\nconst isLiteral = isDecimalLiteral;\n\n/**\n * Render a scalar ExprNode to a mathjs-safe, fully-parenthesized string,\n * gensym'ing each non-literal leaf by NAME (so repeats share an identifier\n * and can cancel). Throws on a non-scalar arm and on a non-literal exponent;\n * `algebraic-equivalence.ts` renders both sides of a quotient through one\n * gensym table with it.\n *\n * @internal\n */\nexport function renderGensym(\n expr: ExprNode,\n gensymOf: Map<string, string>,\n meta: Map<string, LeafMeta>,\n): string {\n switch (expr.kind) {\n case 'symbol':\n return renderScalarLeaf(expr, gensymOf, meta);\n case 'op': {\n if (expr.op === '^') {\n const exp = expr.args[1];\n if (!exp || exp.kind !== 'symbol' || !isLiteral(exp.name)) {\n throw new Unsupported();\n }\n return `(${renderGensym(expr.args[0], gensymOf, meta)})^${Number(exp.name)}`;\n }\n if (expr.args.length === 0) throw new Unsupported();\n if (expr.args.length === 1) {\n const arg = renderGensym(expr.args[0]!, gensymOf, meta);\n if (expr.op === '-') return `(-(${arg}))`;\n if (expr.op === '+') return `(${arg})`;\n }\n const parts = expr.args.map((a) => `(${renderGensym(a, gensymOf, meta)})`);\n return `(${parts.join(expr.op)})`;\n }\n default:\n throw new Unsupported(); // integral / derivative / tensor arms\n }\n}\n\nconst lit = (v: number): ExprNode => ({ kind: 'symbol', name: String(v), dim: DIMENSIONLESS });\n\n/** Walk a simplified MathTS node back to an ExprNode, un-gensym'ing leaves and\n * rejecting anything outside UPT's integer-exponent scalar model (→ throws\n * `Unsupported`, a graceful no-op). */\nfunction walkBack(node: MathNode, meta: Map<string, LeafMeta>): ExprNode {\n switch (node.type) {\n case 'ConstantNode': {\n if (typeof node.value !== 'number' || !Number.isFinite(node.value)) {\n throw new Unsupported();\n }\n return lit(node.value);\n }\n case 'SymbolNode': {\n const m = node.name !== undefined ? meta.get(node.name) : undefined;\n if (!m) throw new Unsupported(); // a symbol we did not issue\n return { kind: 'symbol', name: m.name, dim: m.dim };\n }\n case 'ParenthesisNode':\n if (!node.content) throw new Unsupported();\n return walkBack(node.content, meta);\n case 'OperatorNode': {\n const op = node.op;\n const args = node.args ?? [];\n if (op === '^') {\n if (args.length !== 2) throw new Unsupported();\n const exp = args[1];\n if (\n exp.type !== 'ConstantNode' ||\n typeof exp.value !== 'number' ||\n !Number.isInteger(exp.value)\n ) {\n throw new Unsupported(); // non-integer exponent — not in ℤ⁷ model\n }\n return {\n kind: 'op',\n op: '^',\n args: [walkBack(args[0], meta), lit(exp.value)],\n };\n }\n if (op === '-' && args.length === 1) {\n // unary minus → (-1) * arg\n return { kind: 'op', op: '*', args: [lit(-1), walkBack(args[0], meta)] };\n }\n if (op === '+' && args.length === 1) return walkBack(args[0], meta); // unary plus is the argument\n if (op === '+' || op === '-' || op === '*' || op === '/') {\n if (args.length < 2) throw new Unsupported();\n return { kind: 'op', op, args: args.map((a) => walkBack(a, meta)) };\n }\n throw new Unsupported();\n }\n default:\n throw new Unsupported(); // FunctionNode (sqrt/cbrt/…) etc.\n }\n}\n\n// ---------------------------------------------------------------------------\n// Guards.\n// ---------------------------------------------------------------------------\n\nfunction symbolNames(expr: ExprNode, out: string[] = []): string[] {\n forEachScalarLeaf(expr, (leaf) => out.push(leaf.name), { integral: 'over+integrand', derivative: true });\n return out;\n}\n\nconst nonNumericSymbols = (expr: ExprNode): string[] =>\n symbolNames(expr).filter((n) => !isLiteral(n));\n\nconst PROBE_VALUES = [2.3, 3.7, 5.1, 7.9, 11.3, 13.1, 17.9, 19.3];\nconst PROBE_MULTIPLIERS = [1, 1.7, 0.41, 2.9];\n\n/** Numeric agreement of `original` and `candidate` over synthesized probes.\n * Free (non-constant) leaves get distinct, mutually-incommensurate values to\n * avoid accidental cancellation. <2 finite probes ⇒ 'insufficient' (cannot\n * verify — EVE-C). */\nfunction numericAgreement(\n original: ExprNode,\n candidate: ExprNode,\n): 'agree' | 'disagree' | 'insufficient' {\n const leaves = [...new Set(nonNumericSymbols(original))].filter(\n (n) => !isRegisteredConstant(n),\n );\n let finiteProbes = 0;\n for (const mult of PROBE_MULTIPLIERS) {\n const values: Record<string, number> = {};\n leaves.forEach((leaf, i) => {\n values[leaf] = PROBE_VALUES[i % PROBE_VALUES.length] * mult;\n });\n let a: number;\n let b: number;\n try {\n a = evalExpr(original, values);\n b = evalExpr(candidate, values);\n } catch {\n continue; // a probe drove evalExpr non-finite — skip it\n }\n if (!Number.isFinite(a) || !Number.isFinite(b)) continue;\n finiteProbes++;\n if (Math.abs(a - b) / Math.abs(b || 1) > 1e-9) return 'disagree';\n }\n return finiteProbes >= 2 ? 'agree' : 'insufficient';\n}\n\n// ---------------------------------------------------------------------------\n// Public entry points.\n// ---------------------------------------------------------------------------\n\n/** The result of attempting to simplify an expression. */\ninterface SimplifyResult {\n readonly expr: ExprNode;\n /** True iff MathTS was present AND produced a guard-passing, distinct form. */\n readonly simplified: boolean;\n}\n\n/**\n * Whether the MathTS simplifier is usable. MathTS is a required dependency, so\n * the answer is true; a simplifier that fails its smoke test throws instead.\n * The atlas witness runner reads it to choose between the simplifier and its\n * `peer-absent` path, which a caller still reaches by passing `null`.\n *\n * @internal\n */\nexport async function isSimplifierAvailable(): Promise<boolean> {\n loadSimplifier();\n return true;\n}\n\n/**\n * Simplify a scalar `ExprNode` via MathTS, guarded. Returns the original\n * unchanged (`simplified:false`) when the result cannot be represented or\n * verified; THROWS {@link SimplificationError} only when a\n * representable result disagrees dimensionally/numerically. See module docs.\n *\n * @internal\n */\nexport async function simplifyExpr(expr: ExprNode): Promise<SimplifyResult> {\n const mod = loadSimplifier();\n\n const gensymOf = new Map<string, string>();\n const meta = new Map<string, LeafMeta>();\n let candidate: ExprNode;\n try {\n const str = renderGensym(expr, gensymOf, meta);\n // MathTS can THROW on some forms (e.g. a known mathts `simplify` BigInt\n // bug on nested `a/(b/c²)`); that, like an unsupported node, is a graceful\n // no-op, not an error. The console is not touched here: the first use\n // already ran inside `loadSimplifier`'s window.\n const simplifiedNode = mod.simplify(mod.parse(str));\n candidate = walkBack(simplifiedNode, meta);\n } catch {\n return { expr, simplified: false }; // unsupported / unrepresentable / MathTS threw\n }\n\n // Guard 1 — dimensional. Inability to validate ⇒ no-op; a CHANGED dimension\n // is a representable disagreement ⇒ throw.\n const origDim = validate(expr).inferredDimension;\n // A literal ZERO carries every dimension: `x − x` with `x` a length is a zero\n // LENGTH, but the CAS hands back a bare dimensionless `0`. Re-stamp it with\n // the original dimension, or this guard would reject every exact\n // cancellation of a dimensioned expression as a \"changed dimension\".\n if (\n origDim !== null &&\n candidate.kind === 'symbol' &&\n candidate.name.trim() !== '' &&\n Number(candidate.name) === 0\n ) {\n candidate = { kind: 'symbol', name: '0', dim: origDim };\n }\n const newResult = validate(candidate);\n if (origDim === null || !newResult.ok || newResult.inferredDimension === null) {\n return { expr, simplified: false };\n }\n if (!equals(origDim, newResult.inferredDimension)) {\n throw new SimplificationError(\n `simplifyExpr: the simplified form changed dimension — a CAS or ` +\n `walk-back error.`,\n );\n }\n\n // Guard 2 — structural subset (no non-numeric leaf invented).\n const origSyms = new Set(nonNumericSymbols(expr));\n for (const s of nonNumericSymbols(candidate)) {\n if (!origSyms.has(s)) return { expr, simplified: false }; // suspicious ⇒ no-op\n }\n\n // Guard 3 — numeric agreement.\n const verdict = numericAgreement(expr, candidate);\n if (verdict === 'disagree') {\n throw new SimplificationError(\n `simplifyExpr: the simplified form disagrees numerically with the ` +\n `original — a CAS or walk-back error.`,\n );\n }\n if (verdict === 'insufficient') return { expr, simplified: false };\n\n // Identical-structure ⇒ nothing gained; report not simplified.\n const changed = symbolNames(candidate).length !== symbolNames(expr).length;\n return { expr: candidate, simplified: changed };\n}\n\n/**\n * Simplify a composed {@link Observable}: returns a freshly-RECONSTRUCTED\n * Observable (new strict `evaluate` closure over the simplified `expr` +\n * recomputed `leaves`) when simplification succeeds, else the original\n * unchanged. See module docs.\n *\n * @internal\n */\nexport async function simplifyObservable(obs: Observable): Promise<Observable> {\n const { expr, simplified } = await simplifyExpr(obs.expr);\n if (!simplified) return obs;\n return makeObservable(obs.name, obs.symbol, obs.dim, expr);\n}\n"]}
|
|
@@ -9,14 +9,33 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @module composition/formula-shape
|
|
11
11
|
*/
|
|
12
|
+
import { Fraction } from '@danielsimonjr/mathts-core';
|
|
12
13
|
import type { ExprNode } from '../dimensional/ast-types.js';
|
|
13
14
|
/** `monomial` is a product of powers. `dimensional-sum` adds dimensionful terms. */
|
|
14
15
|
type FormulaShape = 'monomial' | 'dimensional-sum';
|
|
15
16
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* The rational a literal exponent stands for: a bounded-denominator scan at
|
|
18
|
+
* the fit's tolerance reads `0.3333333333333333` as `1/3`; a decimal that
|
|
19
|
+
* is no such rational (`0.3333`) is kept as the exact decimal it spells.
|
|
20
|
+
*
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
export declare function rationalExponentOf(name: string): Fraction | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Exact exponents of every symbol in a product, quotient, or literal power,
|
|
26
|
+
* as core `Fraction`s. Undefined for a sum or any node that is not that
|
|
27
|
+
* monomial. A cancellation is an exact zero: `(x^(1/3))^3 / x` carries `x`
|
|
28
|
+
* at `0`, not at `2.2e-16`.
|
|
29
|
+
*
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
export declare function monomialExponentsExact(node: ExprNode | undefined): Map<string, Fraction> | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Exponents of every symbol in a product, quotient, or literal power, as
|
|
35
|
+
* numbers: the projection of {@link monomialExponentsExact}. Undefined for a
|
|
36
|
+
* sum or any node that is not that monomial. The canonical graph reads a
|
|
37
|
+
* count's exponent from it, and a composed edge reads the junction's
|
|
38
|
+
* exponent from it.
|
|
20
39
|
*
|
|
21
40
|
* @internal
|
|
22
41
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formula-shape.d.ts","sourceRoot":"","sources":["../../src/composition/formula-shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"formula-shape.d.ts","sourceRoot":"","sources":["../../src/composition/formula-shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAO5D,oFAAoF;AACpF,KAAK,YAAY,GAAG,UAAU,GAAG,iBAAiB,CAAC;AAEnD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAWrE;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,CAiCpG;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAI7F;AAuFD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,YAAY,CAEzD"}
|
|
@@ -9,44 +9,69 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @module composition/formula-shape
|
|
11
11
|
*/
|
|
12
|
+
import { Fraction } from '@danielsimonjr/mathts-core';
|
|
13
|
+
import { isDecimalLiteral } from '../dimensional/ast-leaves.js';
|
|
12
14
|
import { divide, equals, multiply, power } from '../dimensional/algebra.js';
|
|
13
15
|
import { DIMENSIONLESS } from '../dimensional/types.js';
|
|
14
|
-
|
|
16
|
+
import { fractionToNumber, rationalize } from './rational-exponent.js';
|
|
15
17
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* from it, and a composed edge reads the junction's exponent from it.
|
|
18
|
+
* The rational a literal exponent stands for: a bounded-denominator scan at
|
|
19
|
+
* the fit's tolerance reads `0.3333333333333333` as `1/3`; a decimal that
|
|
20
|
+
* is no such rational (`0.3333`) is kept as the exact decimal it spells.
|
|
20
21
|
*
|
|
21
22
|
* @internal
|
|
22
23
|
*/
|
|
23
|
-
export function
|
|
24
|
+
export function rationalExponentOf(name) {
|
|
25
|
+
if (!isDecimalLiteral(name))
|
|
26
|
+
return undefined;
|
|
27
|
+
const value = Number(name);
|
|
28
|
+
if (!Number.isFinite(value))
|
|
29
|
+
return undefined;
|
|
30
|
+
const scanned = rationalize(value);
|
|
31
|
+
if (scanned !== undefined)
|
|
32
|
+
return scanned;
|
|
33
|
+
try {
|
|
34
|
+
return Fraction.parse(name);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return Fraction.fromNumber(value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Exact exponents of every symbol in a product, quotient, or literal power,
|
|
42
|
+
* as core `Fraction`s. Undefined for a sum or any node that is not that
|
|
43
|
+
* monomial. A cancellation is an exact zero: `(x^(1/3))^3 / x` carries `x`
|
|
44
|
+
* at `0`, not at `2.2e-16`.
|
|
45
|
+
*
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
export function monomialExponentsExact(node) {
|
|
24
49
|
if (node === undefined)
|
|
25
50
|
return undefined;
|
|
26
51
|
if (node.kind === 'symbol')
|
|
27
|
-
return new Map([[node.name, 1]]);
|
|
52
|
+
return new Map([[node.name, new Fraction(1)]]);
|
|
28
53
|
if (node.kind !== 'op')
|
|
29
54
|
return undefined;
|
|
30
55
|
if (node.op === '*') {
|
|
31
56
|
const acc = new Map();
|
|
32
57
|
for (const arg of node.args) {
|
|
33
|
-
const part =
|
|
58
|
+
const part = monomialExponentsExact(arg);
|
|
34
59
|
if (part === undefined)
|
|
35
60
|
return undefined;
|
|
36
61
|
for (const [name, exp] of part)
|
|
37
|
-
acc.set(name, (acc.get(name) ?? 0)
|
|
62
|
+
acc.set(name, (acc.get(name) ?? new Fraction(0)).add(exp));
|
|
38
63
|
}
|
|
39
64
|
return acc;
|
|
40
65
|
}
|
|
41
66
|
if (node.op === '/') {
|
|
42
67
|
if (node.args.length !== 2)
|
|
43
68
|
return undefined;
|
|
44
|
-
const numerator =
|
|
45
|
-
const denominator =
|
|
69
|
+
const numerator = monomialExponentsExact(node.args[0]);
|
|
70
|
+
const denominator = monomialExponentsExact(node.args[1]);
|
|
46
71
|
if (numerator === undefined || denominator === undefined)
|
|
47
72
|
return undefined;
|
|
48
73
|
for (const [name, exp] of denominator)
|
|
49
|
-
numerator.set(name, (numerator.get(name) ?? 0)
|
|
74
|
+
numerator.set(name, (numerator.get(name) ?? new Fraction(0)).sub(exp));
|
|
50
75
|
return numerator;
|
|
51
76
|
}
|
|
52
77
|
if (node.op === '^') {
|
|
@@ -54,21 +79,36 @@ export function monomialExponents(node) {
|
|
|
54
79
|
const expNode = node.args[1];
|
|
55
80
|
if (base === undefined || expNode === undefined || expNode.kind !== 'symbol')
|
|
56
81
|
return undefined;
|
|
57
|
-
const exp =
|
|
58
|
-
if (
|
|
82
|
+
const exp = rationalExponentOf(expNode.name);
|
|
83
|
+
if (exp === undefined)
|
|
59
84
|
return undefined;
|
|
60
|
-
const inner =
|
|
85
|
+
const inner = monomialExponentsExact(base);
|
|
61
86
|
if (inner === undefined)
|
|
62
87
|
return undefined;
|
|
63
88
|
for (const [name, innerExp] of inner)
|
|
64
|
-
inner.set(name, innerExp
|
|
89
|
+
inner.set(name, innerExp.multiply(exp));
|
|
65
90
|
return inner;
|
|
66
91
|
}
|
|
67
92
|
return undefined;
|
|
68
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Exponents of every symbol in a product, quotient, or literal power, as
|
|
96
|
+
* numbers: the projection of {@link monomialExponentsExact}. Undefined for a
|
|
97
|
+
* sum or any node that is not that monomial. The canonical graph reads a
|
|
98
|
+
* count's exponent from it, and a composed edge reads the junction's
|
|
99
|
+
* exponent from it.
|
|
100
|
+
*
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
export function monomialExponents(node) {
|
|
104
|
+
const exact = monomialExponentsExact(node);
|
|
105
|
+
if (exact === undefined)
|
|
106
|
+
return undefined;
|
|
107
|
+
return new Map([...exact].map(([name, exp]) => [name, fractionToNumber(exp)]));
|
|
108
|
+
}
|
|
69
109
|
/** A dimensionless symbol whose name is a number, the way a literal exponent is written. */
|
|
70
110
|
function numericExponent(node) {
|
|
71
|
-
if (node.kind !== 'symbol' || !
|
|
111
|
+
if (node.kind !== 'symbol' || !isDecimalLiteral(node.name))
|
|
72
112
|
return undefined;
|
|
73
113
|
if (!equals(node.dim, DIMENSIONLESS))
|
|
74
114
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formula-shape.js","sourceRoot":"","sources":["../../src/composition/formula-shape.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Whether an encoded formula is a product of powers, or a sum of dimensionful terms.\n *\n * Buckingham-π returns a monomial. A formula that adds dimensionful terms is\n * not that monomial, even when a unique monomial exists in the same variables\n * (fast magnetosonic speed: the monomial is the sound speed; the formula is\n * √(c_s² + v_A²)). A sum whose every addend is dimensionless is still a\n * factor in a monomial: (1+R), (1−e²), (1 + E/(kT)).\n *\n * @module composition/formula-shape\n */\n\nimport type { ExprNode } from '../dimensional/ast-types.js';\nimport { divide, equals, multiply, power } from '../dimensional/algebra.js';\nimport type { Dimension } from '../dimensional/types.js';\nimport { DIMENSIONLESS } from '../dimensional/types.js';\n\n/** `monomial` is a product of powers. `dimensional-sum` adds dimensionful terms. */\ntype FormulaShape = 'monomial' | 'dimensional-sum';\n\nconst NUMERIC_NAME = /^[+-]?(?:\\d+(?:\\.\\d+)?|\\.\\d+)$/;\n\n/**\n * Exponents of every symbol in a product, quotient, or literal integer power.\n * Undefined for a sum or any node that is not that monomial. The one reader\n * of a monomial's exponents: the canonical graph reads a count's exponent\n * from it, and a composed edge reads the junction's exponent from it.\n *\n * @internal\n */\nexport function monomialExponents(node: ExprNode | undefined): Map<string, number> | undefined {\n if (node === undefined) return undefined;\n if (node.kind === 'symbol') return new Map([[node.name, 1]]);\n if (node.kind !== 'op') return undefined;\n if (node.op === '*') {\n const acc = new Map<string, number>();\n for (const arg of node.args) {\n const part = monomialExponents(arg);\n if (part === undefined) return undefined;\n for (const [name, exp] of part) acc.set(name, (acc.get(name) ?? 0) + exp);\n }\n return acc;\n }\n if (node.op === '/') {\n if (node.args.length !== 2) return undefined;\n const numerator = monomialExponents(node.args[0]);\n const denominator = monomialExponents(node.args[1]);\n if (numerator === undefined || denominator === undefined) return undefined;\n for (const [name, exp] of denominator) numerator.set(name, (numerator.get(name) ?? 0) - exp);\n return numerator;\n }\n if (node.op === '^') {\n const base = node.args[0];\n const expNode = node.args[1];\n if (base === undefined || expNode === undefined || expNode.kind !== 'symbol') return undefined;\n const exp = Number(expNode.name);\n if (!Number.isFinite(exp)) return undefined;\n const inner = monomialExponents(base);\n if (inner === undefined) return undefined;\n for (const [name, innerExp] of inner) inner.set(name, innerExp * exp);\n return inner;\n }\n return undefined;\n}\n\n/** A dimensionless symbol whose name is a number, the way a literal exponent is written. */\nfunction numericExponent(node: ExprNode): number | undefined {\n if (node.kind !== 'symbol' || !NUMERIC_NAME.test(node.name)) return undefined;\n if (!equals(node.dim, DIMENSIONLESS)) return undefined;\n const n = Number(node.name);\n return Number.isFinite(n) ? n : undefined;\n}\n\n/**\n * Dimension of a scalar node this classifier understands. `undefined` means\n * the node is not a product of powers of dimensioned symbols. A sum that\n * cannot be dimensioned is treated as dimensionful.\n */\nfunction dimOf(node: ExprNode): Dimension | undefined {\n if (node.kind === 'symbol') return node.dim;\n if (node.kind === 'abs') return dimOf(node.arg);\n if (node.kind === 'transcendental') {\n const arg = dimOf(node.arg);\n if (arg === undefined || !equals(arg, DIMENSIONLESS)) return undefined;\n return DIMENSIONLESS;\n }\n if (node.kind !== 'op') return undefined;\n if (node.op === '+' || node.op === '-') {\n if (node.args.length === 0) return undefined;\n const dims = node.args.map(dimOf);\n if (dims.some((d) => d === undefined)) return undefined;\n const first = dims[0]!;\n if (!dims.every((d) => equals(d!, first))) return undefined;\n return first;\n }\n if (node.op === '*') {\n let acc: Dimension = DIMENSIONLESS;\n for (const arg of node.args) {\n const d = dimOf(arg);\n if (d === undefined) return undefined;\n acc = multiply(acc, d);\n }\n return acc;\n }\n if (node.op === '/') {\n if (node.args.length !== 2) return undefined;\n const num = dimOf(node.args[0]!);\n const den = dimOf(node.args[1]!);\n if (num === undefined || den === undefined) return undefined;\n return divide(num, den);\n }\n if (node.op === '^') {\n if (node.args.length !== 2) return undefined;\n const base = dimOf(node.args[0]!);\n const exp = numericExponent(node.args[1]!);\n if (base === undefined || exp === undefined) return undefined;\n return power(base, exp);\n }\n return undefined;\n}\n\n/** Scalar children. A tensor node this walker does not understand contributes none. */\nfunction children(node: ExprNode): readonly ExprNode[] {\n if (node.kind === 'op') return node.args;\n if (node.kind === 'abs' || node.kind === 'transcendental' || node.kind === 'dirac-delta') return [node.arg];\n if (node.kind === 'integral') {\n return [node.over, node.integrand, ...(node.lower === undefined ? [] : [node.lower]), ...(node.upper === undefined ? [] : [node.upper])];\n }\n if (node.kind === 'derivative') return [node.of, node.wrt];\n if (node.kind === 'variational-derivative') return [node.functional, node.field, node.over];\n return [];\n}\n\n/**\n * True when `node` adds terms that are not all dimensionless. An addend whose\n * dimension cannot be read counts as dimensionful: a sum we cannot see is not\n * reported as a monomial.\n */\nfunction isDimensionalSum(node: ExprNode): boolean {\n if (node.kind !== 'op' || (node.op !== '+' && node.op !== '-')) return false;\n const dims = node.args.map(dimOf);\n if (dims.some((d) => d === undefined)) return true;\n return dims.some((d) => !equals(d!, DIMENSIONLESS));\n}\n\nfunction hasDimensionalSum(node: ExprNode): boolean {\n if (isDimensionalSum(node)) return true;\n return children(node).some(hasDimensionalSum);\n}\n\n/**\n * Classify `expr`. A node this walker does not understand, and that is not\n * itself a sum, stays a monomial so an unread tensor equation is not\n * reclassified.\n */\nexport function formulaShape(expr: ExprNode): FormulaShape {\n return hasDimensionalSum(expr) ? 'dimensional-sum' : 'monomial';\n}\n"]}
|
|
1
|
+
{"version":3,"file":"formula-shape.js","sourceRoot":"","sources":["../../src/composition/formula-shape.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Whether an encoded formula is a product of powers, or a sum of dimensionful terms.\n *\n * Buckingham-π returns a monomial. A formula that adds dimensionful terms is\n * not that monomial, even when a unique monomial exists in the same variables\n * (fast magnetosonic speed: the monomial is the sound speed; the formula is\n * √(c_s² + v_A²)). A sum whose every addend is dimensionless is still a\n * factor in a monomial: (1+R), (1−e²), (1 + E/(kT)).\n *\n * @module composition/formula-shape\n */\n\nimport { Fraction } from '@danielsimonjr/mathts-core';\nimport type { ExprNode } from '../dimensional/ast-types.js';\nimport { isDecimalLiteral } from '../dimensional/ast-leaves.js';\nimport { divide, equals, multiply, power } from '../dimensional/algebra.js';\nimport type { Dimension } from '../dimensional/types.js';\nimport { DIMENSIONLESS } from '../dimensional/types.js';\nimport { fractionToNumber, rationalize } from './rational-exponent.js';\n\n/** `monomial` is a product of powers. `dimensional-sum` adds dimensionful terms. */\ntype FormulaShape = 'monomial' | 'dimensional-sum';\n\n/**\n * The rational a literal exponent stands for: a bounded-denominator scan at\n * the fit's tolerance reads `0.3333333333333333` as `1/3`; a decimal that\n * is no such rational (`0.3333`) is kept as the exact decimal it spells.\n *\n * @internal\n */\nexport function rationalExponentOf(name: string): Fraction | undefined {\n if (!isDecimalLiteral(name)) return undefined;\n const value = Number(name);\n if (!Number.isFinite(value)) return undefined;\n const scanned = rationalize(value);\n if (scanned !== undefined) return scanned;\n try {\n return Fraction.parse(name);\n } catch {\n return Fraction.fromNumber(value);\n }\n}\n\n/**\n * Exact exponents of every symbol in a product, quotient, or literal power,\n * as core `Fraction`s. Undefined for a sum or any node that is not that\n * monomial. A cancellation is an exact zero: `(x^(1/3))^3 / x` carries `x`\n * at `0`, not at `2.2e-16`.\n *\n * @internal\n */\nexport function monomialExponentsExact(node: ExprNode | undefined): Map<string, Fraction> | undefined {\n if (node === undefined) return undefined;\n if (node.kind === 'symbol') return new Map([[node.name, new Fraction(1)]]);\n if (node.kind !== 'op') return undefined;\n if (node.op === '*') {\n const acc = new Map<string, Fraction>();\n for (const arg of node.args) {\n const part = monomialExponentsExact(arg);\n if (part === undefined) return undefined;\n for (const [name, exp] of part) acc.set(name, (acc.get(name) ?? new Fraction(0)).add(exp));\n }\n return acc;\n }\n if (node.op === '/') {\n if (node.args.length !== 2) return undefined;\n const numerator = monomialExponentsExact(node.args[0]);\n const denominator = monomialExponentsExact(node.args[1]);\n if (numerator === undefined || denominator === undefined) return undefined;\n for (const [name, exp] of denominator) numerator.set(name, (numerator.get(name) ?? new Fraction(0)).sub(exp));\n return numerator;\n }\n if (node.op === '^') {\n const base = node.args[0];\n const expNode = node.args[1];\n if (base === undefined || expNode === undefined || expNode.kind !== 'symbol') return undefined;\n const exp = rationalExponentOf(expNode.name);\n if (exp === undefined) return undefined;\n const inner = monomialExponentsExact(base);\n if (inner === undefined) return undefined;\n for (const [name, innerExp] of inner) inner.set(name, innerExp.multiply(exp));\n return inner;\n }\n return undefined;\n}\n\n/**\n * Exponents of every symbol in a product, quotient, or literal power, as\n * numbers: the projection of {@link monomialExponentsExact}. Undefined for a\n * sum or any node that is not that monomial. The canonical graph reads a\n * count's exponent from it, and a composed edge reads the junction's\n * exponent from it.\n *\n * @internal\n */\nexport function monomialExponents(node: ExprNode | undefined): Map<string, number> | undefined {\n const exact = monomialExponentsExact(node);\n if (exact === undefined) return undefined;\n return new Map([...exact].map(([name, exp]) => [name, fractionToNumber(exp)]));\n}\n\n/** A dimensionless symbol whose name is a number, the way a literal exponent is written. */\nfunction numericExponent(node: ExprNode): number | undefined {\n if (node.kind !== 'symbol' || !isDecimalLiteral(node.name)) return undefined;\n if (!equals(node.dim, DIMENSIONLESS)) return undefined;\n const n = Number(node.name);\n return Number.isFinite(n) ? n : undefined;\n}\n\n/**\n * Dimension of a scalar node this classifier understands. `undefined` means\n * the node is not a product of powers of dimensioned symbols. A sum that\n * cannot be dimensioned is treated as dimensionful.\n */\nfunction dimOf(node: ExprNode): Dimension | undefined {\n if (node.kind === 'symbol') return node.dim;\n if (node.kind === 'abs') return dimOf(node.arg);\n if (node.kind === 'transcendental') {\n const arg = dimOf(node.arg);\n if (arg === undefined || !equals(arg, DIMENSIONLESS)) return undefined;\n return DIMENSIONLESS;\n }\n if (node.kind !== 'op') return undefined;\n if (node.op === '+' || node.op === '-') {\n if (node.args.length === 0) return undefined;\n const dims = node.args.map(dimOf);\n if (dims.some((d) => d === undefined)) return undefined;\n const first = dims[0]!;\n if (!dims.every((d) => equals(d!, first))) return undefined;\n return first;\n }\n if (node.op === '*') {\n let acc: Dimension = DIMENSIONLESS;\n for (const arg of node.args) {\n const d = dimOf(arg);\n if (d === undefined) return undefined;\n acc = multiply(acc, d);\n }\n return acc;\n }\n if (node.op === '/') {\n if (node.args.length !== 2) return undefined;\n const num = dimOf(node.args[0]!);\n const den = dimOf(node.args[1]!);\n if (num === undefined || den === undefined) return undefined;\n return divide(num, den);\n }\n if (node.op === '^') {\n if (node.args.length !== 2) return undefined;\n const base = dimOf(node.args[0]!);\n const exp = numericExponent(node.args[1]!);\n if (base === undefined || exp === undefined) return undefined;\n return power(base, exp);\n }\n return undefined;\n}\n\n/** Scalar children. A tensor node this walker does not understand contributes none. */\nfunction children(node: ExprNode): readonly ExprNode[] {\n if (node.kind === 'op') return node.args;\n if (node.kind === 'abs' || node.kind === 'transcendental' || node.kind === 'dirac-delta') return [node.arg];\n if (node.kind === 'integral') {\n return [node.over, node.integrand, ...(node.lower === undefined ? [] : [node.lower]), ...(node.upper === undefined ? [] : [node.upper])];\n }\n if (node.kind === 'derivative') return [node.of, node.wrt];\n if (node.kind === 'variational-derivative') return [node.functional, node.field, node.over];\n return [];\n}\n\n/**\n * True when `node` adds terms that are not all dimensionless. An addend whose\n * dimension cannot be read counts as dimensionful: a sum we cannot see is not\n * reported as a monomial.\n */\nfunction isDimensionalSum(node: ExprNode): boolean {\n if (node.kind !== 'op' || (node.op !== '+' && node.op !== '-')) return false;\n const dims = node.args.map(dimOf);\n if (dims.some((d) => d === undefined)) return true;\n return dims.some((d) => !equals(d!, DIMENSIONLESS));\n}\n\nfunction hasDimensionalSum(node: ExprNode): boolean {\n if (isDimensionalSum(node)) return true;\n return children(node).some(hasDimensionalSum);\n}\n\n/**\n * Classify `expr`. A node this walker does not understand, and that is not\n * itself a sum, stays a monomial so an unread tensor equation is not\n * reclassified.\n */\nexport function formulaShape(expr: ExprNode): FormulaShape {\n return hasDimensionalSum(expr) ? 'dimensional-sum' : 'monomial';\n}\n"]}
|