cbrowser 20.2.2 → 21.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 +2 -2
- package/dist/analysis/accessibility-empathy.d.ts +29 -1
- package/dist/analysis/accessibility-empathy.d.ts.map +1 -1
- package/dist/analysis/accessibility-empathy.js +69 -35
- package/dist/analysis/accessibility-empathy.js.map +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +11 -7
- package/dist/browser.js.map +1 -1
- package/dist/cif-score.d.ts +56 -5
- package/dist/cif-score.d.ts.map +1 -1
- package/dist/cif-score.js +595 -346
- package/dist/cif-score.js.map +1 -1
- package/dist/cli.js +10 -8
- package/dist/cli.js.map +1 -1
- package/dist/cognitive/default-traits.d.ts +14 -0
- package/dist/cognitive/default-traits.d.ts.map +1 -0
- package/dist/cognitive/default-traits.js +36 -0
- package/dist/cognitive/default-traits.js.map +1 -0
- package/dist/cognitive/emotions.d.ts.map +1 -1
- package/dist/cognitive/emotions.js +104 -174
- package/dist/cognitive/emotions.js.map +1 -1
- package/dist/cognitive/index.d.ts +28 -0
- package/dist/cognitive/index.d.ts.map +1 -1
- package/dist/cognitive/index.js +353 -287
- package/dist/cognitive/index.js.map +1 -1
- package/dist/cognitive/temporal.d.ts +0 -24
- package/dist/cognitive/temporal.d.ts.map +1 -1
- package/dist/cognitive/temporal.js +45 -35
- package/dist/cognitive/temporal.js.map +1 -1
- package/dist/data/ctc-reference-v2-2026-10-24.d.ts +16 -0
- package/dist/data/ctc-reference-v2-2026-10-24.d.ts.map +1 -0
- package/dist/data/ctc-reference-v2-2026-10-24.js +1004 -0
- package/dist/data/ctc-reference-v2-2026-10-24.js.map +1 -0
- package/dist/ideal-profiles-gap.d.ts +1 -0
- package/dist/ideal-profiles-gap.d.ts.map +1 -1
- package/dist/ideal-profiles-gap.js +9 -1
- package/dist/ideal-profiles-gap.js.map +1 -1
- package/dist/ideal-profiles.d.ts +8 -0
- package/dist/ideal-profiles.d.ts.map +1 -1
- package/dist/ideal-profiles.js +28 -24
- package/dist/ideal-profiles.js.map +1 -1
- package/dist/mcp-server-remote.d.ts.map +1 -1
- package/dist/mcp-server-remote.js +7 -8
- package/dist/mcp-server-remote.js.map +1 -1
- package/dist/mcp-tools/account-personas.d.ts.map +1 -1
- package/dist/mcp-tools/account-personas.js +3 -1
- package/dist/mcp-tools/account-personas.js.map +1 -1
- package/dist/mcp-tools/base/answer-provenance.d.ts +28 -0
- package/dist/mcp-tools/base/answer-provenance.d.ts.map +1 -0
- package/dist/mcp-tools/base/answer-provenance.js +32 -0
- package/dist/mcp-tools/base/answer-provenance.js.map +1 -0
- package/dist/mcp-tools/base/audit-tools.d.ts +0 -3
- package/dist/mcp-tools/base/audit-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/audit-tools.js +152 -84
- package/dist/mcp-tools/base/audit-tools.js.map +1 -1
- package/dist/mcp-tools/base/capture-tools.js +1 -1
- package/dist/mcp-tools/base/capture-tools.js.map +1 -1
- package/dist/mcp-tools/base/chain-values.d.ts +38 -0
- package/dist/mcp-tools/base/chain-values.d.ts.map +1 -0
- package/dist/mcp-tools/base/chain-values.js +85 -0
- package/dist/mcp-tools/base/chain-values.js.map +1 -0
- package/dist/mcp-tools/base/cognitive-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/cognitive-tools.js +126 -120
- package/dist/mcp-tools/base/cognitive-tools.js.map +1 -1
- package/dist/mcp-tools/base/gif-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/gif-tools.js +23 -5
- package/dist/mcp-tools/base/gif-tools.js.map +1 -1
- package/dist/mcp-tools/base/persona-comparison-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/persona-comparison-tools.js +229 -172
- package/dist/mcp-tools/base/persona-comparison-tools.js.map +1 -1
- package/dist/mcp-tools/base/site-familiarity.d.ts +31 -0
- package/dist/mcp-tools/base/site-familiarity.d.ts.map +1 -0
- package/dist/mcp-tools/base/site-familiarity.js +30 -0
- package/dist/mcp-tools/base/site-familiarity.js.map +1 -0
- package/dist/mcp-tools/base/site-knowledge-tools.js +1 -1
- package/dist/mcp-tools/base/site-knowledge-tools.js.map +1 -1
- package/dist/mcp-tools/base/story-narrative.d.ts +50 -0
- package/dist/mcp-tools/base/story-narrative.d.ts.map +1 -0
- package/dist/mcp-tools/base/story-narrative.js +88 -0
- package/dist/mcp-tools/base/story-narrative.js.map +1 -0
- package/dist/mcp-tools/base/values-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/values-tools.js +19 -5
- package/dist/mcp-tools/base/values-tools.js.map +1 -1
- package/dist/mcp-tools/base/visual-testing-tools.d.ts +5 -5
- package/dist/mcp-tools/base/visual-testing-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/visual-testing-tools.js +38 -11
- package/dist/mcp-tools/base/visual-testing-tools.js.map +1 -1
- package/dist/mcp-tools/persona-creation-tools.js +6 -6
- package/dist/mcp-tools/persona-creation-tools.js.map +1 -1
- package/dist/mcp-tools/persona-lifecycle-tools.d.ts.map +1 -1
- package/dist/mcp-tools/persona-lifecycle-tools.js +5 -1
- package/dist/mcp-tools/persona-lifecycle-tools.js.map +1 -1
- package/dist/mcp-tools/tier-gate.js +1 -1
- package/dist/mcp-tools/tool-result-saver.d.ts +7 -0
- package/dist/mcp-tools/tool-result-saver.d.ts.map +1 -1
- package/dist/mcp-tools/tool-result-saver.js +11 -0
- package/dist/mcp-tools/tool-result-saver.js.map +1 -1
- package/dist/mcp-tools/trait-provenance.d.ts +109 -0
- package/dist/mcp-tools/trait-provenance.d.ts.map +1 -0
- package/dist/mcp-tools/trait-provenance.js +187 -0
- package/dist/mcp-tools/trait-provenance.js.map +1 -0
- package/dist/mcp-tools/ui-resources.d.ts +6 -7
- package/dist/mcp-tools/ui-resources.d.ts.map +1 -1
- package/dist/mcp-tools/ui-resources.js +162 -12
- package/dist/mcp-tools/ui-resources.js.map +1 -1
- package/dist/mcp-tools/widget-kit.d.ts +129 -3
- package/dist/mcp-tools/widget-kit.d.ts.map +1 -1
- package/dist/mcp-tools/widget-kit.js +507 -28
- package/dist/mcp-tools/widget-kit.js.map +1 -1
- package/dist/performance/metrics.d.ts.map +1 -1
- package/dist/performance/metrics.js +4 -1
- package/dist/performance/metrics.js.map +1 -1
- package/dist/persona-questionnaire.js +1 -1
- package/dist/persona-questionnaire.js.map +1 -1
- package/dist/personas.d.ts.map +1 -1
- package/dist/personas.js +133 -82
- package/dist/personas.js.map +1 -1
- package/dist/recording/engine.d.ts.map +1 -1
- package/dist/recording/engine.js +5 -2
- package/dist/recording/engine.js.map +1 -1
- package/dist/recording/saliency-overlay.d.ts +8 -3
- package/dist/recording/saliency-overlay.d.ts.map +1 -1
- package/dist/recording/saliency-overlay.js +14 -5
- package/dist/recording/saliency-overlay.js.map +1 -1
- package/dist/recording/types.js +1 -1
- package/dist/testing/nl-test-suite.d.ts.map +1 -1
- package/dist/testing/nl-test-suite.js +2 -1
- package/dist/testing/nl-test-suite.js.map +1 -1
- package/dist/trait-reference.d.ts +19 -2
- package/dist/trait-reference.d.ts.map +1 -1
- package/dist/trait-reference.js +19 -2
- package/dist/trait-reference.js.map +1 -1
- package/dist/types.d.ts +32 -21
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +62 -52
- package/dist/types.js.map +1 -1
- package/dist/values/persona-completeness.js +1 -1
- package/dist/values/persona-completeness.js.map +1 -1
- package/dist/visual/ab-comparison.d.ts.map +1 -1
- package/dist/visual/ab-comparison.js +4 -1
- package/dist/visual/ab-comparison.js.map +1 -1
- package/dist/visual/attention-quality.d.ts +1 -1
- package/dist/visual/attention-quality.js +1 -1
- package/dist/visual/attention-transport.d.ts +74 -10
- package/dist/visual/attention-transport.d.ts.map +1 -1
- package/dist/visual/attention-transport.js +353 -193
- package/dist/visual/attention-transport.js.map +1 -1
- package/dist/visual/cognitive-models.d.ts +77 -55
- package/dist/visual/cognitive-models.d.ts.map +1 -1
- package/dist/visual/cognitive-models.js +231 -104
- package/dist/visual/cognitive-models.js.map +1 -1
- package/dist/visual/cognitive-transport-chain.d.ts +328 -30
- package/dist/visual/cognitive-transport-chain.d.ts.map +1 -1
- package/dist/visual/cognitive-transport-chain.js +576 -353
- package/dist/visual/cognitive-transport-chain.js.map +1 -1
- package/dist/visual/cognitive-transport.d.ts +446 -13
- package/dist/visual/cognitive-transport.d.ts.map +1 -1
- package/dist/visual/cognitive-transport.js +1085 -245
- package/dist/visual/cognitive-transport.js.map +1 -1
- package/dist/visual/cross-browser.d.ts.map +1 -1
- package/dist/visual/cross-browser.js +8 -6
- package/dist/visual/cross-browser.js.map +1 -1
- package/dist/visual/ctc-bands.d.ts +91 -0
- package/dist/visual/ctc-bands.d.ts.map +1 -0
- package/dist/visual/ctc-bands.js +117 -0
- package/dist/visual/ctc-bands.js.map +1 -0
- package/dist/visual/ctc-reference.d.ts +287 -0
- package/dist/visual/ctc-reference.d.ts.map +1 -0
- package/dist/visual/ctc-reference.js +376 -0
- package/dist/visual/ctc-reference.js.map +1 -0
- package/dist/visual/demand-laws.d.ts +145 -0
- package/dist/visual/demand-laws.d.ts.map +1 -0
- package/dist/visual/demand-laws.js +220 -0
- package/dist/visual/demand-laws.js.map +1 -0
- package/dist/visual/distance-metrics.d.ts +23 -1
- package/dist/visual/distance-metrics.d.ts.map +1 -1
- package/dist/visual/distance-metrics.js +49 -18
- package/dist/visual/distance-metrics.js.map +1 -1
- package/dist/visual/dro-bound.d.ts +220 -0
- package/dist/visual/dro-bound.d.ts.map +1 -0
- package/dist/visual/dro-bound.js +341 -0
- package/dist/visual/dro-bound.js.map +1 -0
- package/dist/visual/exact-w1.d.ts +60 -0
- package/dist/visual/exact-w1.d.ts.map +1 -0
- package/dist/visual/exact-w1.js +247 -0
- package/dist/visual/exact-w1.js.map +1 -0
- package/dist/visual/human-input.d.ts.map +1 -1
- package/dist/visual/human-input.js +45 -41
- package/dist/visual/human-input.js.map +1 -1
- package/dist/visual/index.d.ts +2 -0
- package/dist/visual/index.d.ts.map +1 -1
- package/dist/visual/index.js +2 -0
- package/dist/visual/index.js.map +1 -1
- package/dist/visual/law-times-report.d.ts +49 -0
- package/dist/visual/law-times-report.d.ts.map +1 -0
- package/dist/visual/law-times-report.js +38 -0
- package/dist/visual/law-times-report.js.map +1 -0
- package/dist/visual/model-provenance.d.ts +151 -0
- package/dist/visual/model-provenance.d.ts.map +1 -0
- package/dist/visual/model-provenance.js +334 -0
- package/dist/visual/model-provenance.js.map +1 -0
- package/dist/visual/normal-cdf.d.ts +14 -0
- package/dist/visual/normal-cdf.d.ts.map +1 -0
- package/dist/visual/normal-cdf.js +26 -0
- package/dist/visual/normal-cdf.js.map +1 -0
- package/dist/visual/perceptual-transport.d.ts +28 -4
- package/dist/visual/perceptual-transport.d.ts.map +1 -1
- package/dist/visual/perceptual-transport.js +66 -32
- package/dist/visual/perceptual-transport.js.map +1 -1
- package/dist/visual/provenance/attention.d.ts +55 -0
- package/dist/visual/provenance/attention.d.ts.map +1 -0
- package/dist/visual/provenance/attention.js +188 -0
- package/dist/visual/provenance/attention.js.map +1 -0
- package/dist/visual/provenance/chain.d.ts +41 -0
- package/dist/visual/provenance/chain.d.ts.map +1 -0
- package/dist/visual/provenance/chain.js +66 -0
- package/dist/visual/provenance/chain.js.map +1 -0
- package/dist/visual/provenance/cif.d.ts +42 -0
- package/dist/visual/provenance/cif.d.ts.map +1 -0
- package/dist/visual/provenance/cif.js +116 -0
- package/dist/visual/provenance/cif.js.map +1 -0
- package/dist/visual/provenance/ctc-reference.d.ts +36 -0
- package/dist/visual/provenance/ctc-reference.d.ts.map +1 -0
- package/dist/visual/provenance/ctc-reference.js +96 -0
- package/dist/visual/provenance/ctc-reference.js.map +1 -0
- package/dist/visual/provenance/distance.d.ts +10 -0
- package/dist/visual/provenance/distance.d.ts.map +1 -0
- package/dist/visual/provenance/distance.js +72 -0
- package/dist/visual/provenance/distance.js.map +1 -0
- package/dist/visual/provenance/dro.d.ts +10 -0
- package/dist/visual/provenance/dro.d.ts.map +1 -0
- package/dist/visual/provenance/dro.js +2 -0
- package/dist/visual/provenance/dro.js.map +1 -0
- package/dist/visual/provenance/emotion.d.ts +26 -0
- package/dist/visual/provenance/emotion.d.ts.map +1 -0
- package/dist/visual/provenance/emotion.js +99 -0
- package/dist/visual/provenance/emotion.js.map +1 -0
- package/dist/visual/provenance/human-input.d.ts +19 -0
- package/dist/visual/provenance/human-input.d.ts.map +1 -0
- package/dist/visual/provenance/human-input.js +84 -0
- package/dist/visual/provenance/human-input.js.map +1 -0
- package/dist/visual/provenance/journey-group.d.ts +15 -0
- package/dist/visual/provenance/journey-group.d.ts.map +1 -0
- package/dist/visual/provenance/journey-group.js +15 -0
- package/dist/visual/provenance/journey-group.js.map +1 -0
- package/dist/visual/provenance/journey-mcp.d.ts +24 -0
- package/dist/visual/provenance/journey-mcp.d.ts.map +1 -0
- package/dist/visual/provenance/journey-mcp.js +54 -0
- package/dist/visual/provenance/journey-mcp.js.map +1 -0
- package/dist/visual/provenance/journey.d.ts +34 -0
- package/dist/visual/provenance/journey.d.ts.map +1 -0
- package/dist/visual/provenance/journey.js +184 -0
- package/dist/visual/provenance/journey.js.map +1 -0
- package/dist/visual/provenance/laws.d.ts +38 -0
- package/dist/visual/provenance/laws.d.ts.map +1 -0
- package/dist/visual/provenance/laws.js +40 -0
- package/dist/visual/provenance/laws.js.map +1 -0
- package/dist/visual/provenance/page-metrics.d.ts +42 -0
- package/dist/visual/provenance/page-metrics.d.ts.map +1 -0
- package/dist/visual/provenance/page-metrics.js +79 -0
- package/dist/visual/provenance/page-metrics.js.map +1 -0
- package/dist/visual/provenance/perceptual.d.ts +63 -0
- package/dist/visual/provenance/perceptual.d.ts.map +1 -0
- package/dist/visual/provenance/perceptual.js +115 -0
- package/dist/visual/provenance/perceptual.js.map +1 -0
- package/dist/visual/provenance/persona-rates.d.ts +84 -0
- package/dist/visual/provenance/persona-rates.d.ts.map +1 -0
- package/dist/visual/provenance/persona-rates.js +112 -0
- package/dist/visual/provenance/persona-rates.js.map +1 -0
- package/dist/visual/provenance/personas.d.ts +122 -0
- package/dist/visual/provenance/personas.d.ts.map +1 -0
- package/dist/visual/provenance/personas.js +298 -0
- package/dist/visual/provenance/personas.js.map +1 -0
- package/dist/visual/provenance/profiles.d.ts +39 -0
- package/dist/visual/provenance/profiles.d.ts.map +1 -0
- package/dist/visual/provenance/profiles.js +37 -0
- package/dist/visual/provenance/profiles.js.map +1 -0
- package/dist/visual/provenance/temporal.d.ts +21 -0
- package/dist/visual/provenance/temporal.d.ts.map +1 -0
- package/dist/visual/provenance/temporal.js +56 -0
- package/dist/visual/provenance/temporal.js.map +1 -0
- package/dist/visual/provenance/visual-distance.d.ts +22 -0
- package/dist/visual/provenance/visual-distance.d.ts.map +1 -0
- package/dist/visual/provenance/visual-distance.js +30 -0
- package/dist/visual/provenance/visual-distance.js.map +1 -0
- package/dist/visual/regression.d.ts.map +1 -1
- package/dist/visual/regression.js +14 -9
- package/dist/visual/regression.js.map +1 -1
- package/dist/visual/responsive.d.ts.map +1 -1
- package/dist/visual/responsive.js +4 -1
- package/dist/visual/responsive.js.map +1 -1
- package/dist/visual/scope-prose.js +2 -2
- package/dist/visual/scope-prose.js.map +1 -1
- package/dist/visual/seeded-random.d.ts +16 -0
- package/dist/visual/seeded-random.d.ts.map +1 -0
- package/dist/visual/seeded-random.js +25 -0
- package/dist/visual/seeded-random.js.map +1 -0
- package/dist/visual/stored-accessibility-traits.d.ts +27 -0
- package/dist/visual/stored-accessibility-traits.d.ts.map +1 -0
- package/dist/visual/stored-accessibility-traits.js +35 -0
- package/dist/visual/stored-accessibility-traits.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Wasserstein distributionally robust bound on the cognitive transport cost.
|
|
3
|
+
*
|
|
4
|
+
* What it answers. A population of users is a distribution P over capacity
|
|
5
|
+
* vectors x in [0, 1]^30 (one coordinate per DEMAND_DIMENSION, read exactly as
|
|
6
|
+
* the chain reads a persona: capacityVector()). The true population is not
|
|
7
|
+
* known; assume only that it lies within Wasserstein-1 distance epsilon of P,
|
|
8
|
+
* with the ground metric |x - y|_1. Then for every such population Q
|
|
9
|
+
*
|
|
10
|
+
* E_Q[rawCTC] <= E_P[rawCTC] + epsilon * L
|
|
11
|
+
*
|
|
12
|
+
* where L is a Lipschitz constant of rawCTC(x) in the L1 metric on x
|
|
13
|
+
* (Kantorovich-Rubinstein duality: W1 is the supremum of E_Q f - E_P f over
|
|
14
|
+
* 1-Lipschitz f). The bound is also capped at rawMax, the largest raw cost the
|
|
15
|
+
* derivation allows on this page.
|
|
16
|
+
*
|
|
17
|
+
* Why rawCTC. totalCTC is a percentile of rawCTC against real pages
|
|
18
|
+
* (cognitive-transport-chain.ts, ctc-reference.ts), so the chain's own
|
|
19
|
+
* behaviour is in rawCTC and the percentile is a fixed monotone map on top.
|
|
20
|
+
* Through 21.0 totalCTC was a logistic of rawCTC and this bound carried the
|
|
21
|
+
* logistic's slope as a factor; that factor is gone with the logistic.
|
|
22
|
+
*
|
|
23
|
+
* The percentile, too. The interpolated percentile curve is piecewise linear,
|
|
24
|
+
* so it is Lipschitz with constant s = its largest slope over [0, rawMax] (the
|
|
25
|
+
* only raw costs this page can produce). totalCTC(x) = F(rawCTC(x)) is then
|
|
26
|
+
* Lipschitz with L * s, and the same duality gives
|
|
27
|
+
*
|
|
28
|
+
* E_Q[totalCTC] <= E_P[totalCTC] + epsilon * L * s, capped at 1.
|
|
29
|
+
*
|
|
30
|
+
* Sound, and loose: s is the steepest segment of a curve through thousands of
|
|
31
|
+
* samples, so two close samples make it large. percentileLipschitzBound reports
|
|
32
|
+
* s beside the product so the looseness is visible rather than inferred.
|
|
33
|
+
*
|
|
34
|
+
* What it does NOT answer. This is a property of the MODEL: how far the
|
|
35
|
+
* model's own output can move when the population moves. It says nothing about
|
|
36
|
+
* whether the model predicts people. The chain's constants are hand-set
|
|
37
|
+
* hypotheses (see provenance/chain.ts) and CTC has not been tested against
|
|
38
|
+
* human data; a bound around such a function is not evidence about users and
|
|
39
|
+
* must never be reported as such.
|
|
40
|
+
*
|
|
41
|
+
* epsilon has no default. No data fixes how far a real population sits from a
|
|
42
|
+
* persona roster, so the radius is the caller's assumption and must be named
|
|
43
|
+
* by the caller.
|
|
44
|
+
*
|
|
45
|
+
* How L is derived (sound, not sampled). For each input coordinate s the code
|
|
46
|
+
* below bounds sup |d rawCTC / d x_s| by walking the chain's own structure:
|
|
47
|
+
*
|
|
48
|
+
* - layer k's cost is c_k * sum_t w_t (d_t - cap_t)^2, with c_k the content
|
|
49
|
+
* gate (a function of demand alone, except in readingAttention, see below);
|
|
50
|
+
* |d cost / d cap_t| <= c_k * 2 * max(w_def * d_t, w_sur(t) * (1 - d_t)),
|
|
51
|
+
* because a deficit gap is at most d_t and a surplus gap at most 1 - d_t;
|
|
52
|
+
* - except for an exposure-priced trait (EXPOSURE_DIMENSIONS, asymmetric
|
|
53
|
+
* mode), whose term is w_sur * cap_t * d_t: |d cost / d cap_t| = c_k *
|
|
54
|
+
* w_sur * d_t, and the term is at most w_sur * d_t (capacities are <= 1);
|
|
55
|
+
* - the layers' trait sets are disjoint, so a coordinate reaches a later
|
|
56
|
+
* layer only through the indirect drawdown cap *= 1 - min(m, rho*sigma*L_j)
|
|
57
|
+
* of every gated earlier layer, whose derivative in L_j is at most
|
|
58
|
+
* rho*sigma (capacities are <= 1); the drawdown of a layer's own traits
|
|
59
|
+
* is never read again on the same page;
|
|
60
|
+
* - readingTendency enters through demand: it scales sustainedAttention
|
|
61
|
+
* demand by atSkim + x * range, which moves both the gap and the content
|
|
62
|
+
* gate of readingAttention, the last layer (so its depletion gate cannot
|
|
63
|
+
* feed back into anything on the page);
|
|
64
|
+
* - interaction terms w_p * L_a * L_b are bounded by the product rule with
|
|
65
|
+
* each layer's maximum attainable cost.
|
|
66
|
+
*
|
|
67
|
+
* Every piece of the chain is continuous in x (the deficit/surplus switch
|
|
68
|
+
* meets at gap 0, min/max clamps are continuous, and the only x-dependent gate
|
|
69
|
+
* sits after the last layer), so a bound on the partial derivatives where they
|
|
70
|
+
* exist is a Lipschitz constant. Each partial is bounded separately and the
|
|
71
|
+
* L1 constant is their maximum, which is the dual norm of L1.
|
|
72
|
+
*
|
|
73
|
+
* Schwartz value modulation of demand is not supported here (it would add
|
|
74
|
+
* further demand-dependence on options); no shipped caller passes it.
|
|
75
|
+
*
|
|
76
|
+
* Preconditions. The steps above hold only for a chain of a certain shape, and
|
|
77
|
+
* the chain's layout and constants are edited independently of this file. So
|
|
78
|
+
* every call checks them against the live chain and throws, naming the broken
|
|
79
|
+
* assumption, rather than return a constant the derivation does not cover
|
|
80
|
+
* (droPreconditionViolations):
|
|
81
|
+
*
|
|
82
|
+
* - layer names are unique (interaction terms look layers up by name);
|
|
83
|
+
* - every layer lists at least one trait, and no trait is listed twice,
|
|
84
|
+
* within a layer or across layers (disjoint trait sets: a later layer would
|
|
85
|
+
* otherwise read capacity drawn at the full depletion rate);
|
|
86
|
+
* - the layer listing sustainedAttention, whose demand moves with
|
|
87
|
+
* readingTendency, is the last layer (its depletion gate switches with
|
|
88
|
+
* readingTendency, so a later layer would make CTC discontinuous in x) and
|
|
89
|
+
* lists no other trait (its content-gate term counts that gap alone);
|
|
90
|
+
* - interaction weights are finite and >= 0, when interactions are on;
|
|
91
|
+
* - every demand is a finite number >= 0 (the gap bounds);
|
|
92
|
+
* - no option beyond asymmetric and interactions (Schwartz values and a
|
|
93
|
+
* carried capacity change the demand and the starting capacity);
|
|
94
|
+
* - the chain constants are finite, with deficit and surplus weights, the
|
|
95
|
+
* content-scale gain, depletion rate, indirect share, drawdown cap and
|
|
96
|
+
* engagement range >= 0, and the capacity floor in [0, 1].
|
|
97
|
+
*
|
|
98
|
+
* @copyright 2026 Alexandria Eden alexandria.shai.eden@gmail.com https://cbrowser.ai
|
|
99
|
+
* @license MIT
|
|
100
|
+
*/
|
|
101
|
+
import { type DemandDistribution } from "./cognitive-transport-chain.js";
|
|
102
|
+
import { type MetricScope } from "./cognitive-transport.js";
|
|
103
|
+
export interface DroOptions {
|
|
104
|
+
/** Same meaning as computeSequentialCTC's options. Default true. */
|
|
105
|
+
asymmetric?: boolean;
|
|
106
|
+
/** Same meaning as computeSequentialCTC's options. Default true. */
|
|
107
|
+
interactions?: boolean;
|
|
108
|
+
}
|
|
109
|
+
export interface LipschitzBound {
|
|
110
|
+
/** Lipschitz constant of rawCTC(x) in the L1 metric on capacity vectors. */
|
|
111
|
+
lipschitz: number;
|
|
112
|
+
/** The coordinate whose partial derivative bound attains it. */
|
|
113
|
+
worstDimension: string;
|
|
114
|
+
/** Per-coordinate bounds on |d rawCTC / d x_s|. */
|
|
115
|
+
perDimension: Record<string, number>;
|
|
116
|
+
/** Upper bound on rawCTC over the whole capacity cube for this demand. */
|
|
117
|
+
rawMax: number;
|
|
118
|
+
}
|
|
119
|
+
export interface PercentileLipschitzBound {
|
|
120
|
+
/** Lipschitz constant of totalCTC(x), the percentile, in the L1 metric: raw.lipschitz * curveSlope. */
|
|
121
|
+
lipschitz: number;
|
|
122
|
+
/** The bound on rawCTC it is built on. */
|
|
123
|
+
raw: LipschitzBound;
|
|
124
|
+
/** Largest slope of the percentile curve over [0, raw.rawMax]: the curve's Lipschitz constant on every raw cost this page can produce. */
|
|
125
|
+
curveSlope: number;
|
|
126
|
+
/** The reference the percentile is read against (the demand's scope, viewport when it has none). */
|
|
127
|
+
referenceScope: MetricScope;
|
|
128
|
+
}
|
|
129
|
+
export interface PopulationMember {
|
|
130
|
+
/** Persona traits; read through capacityVector exactly as the chain reads them. */
|
|
131
|
+
traits: Record<string, number | string>;
|
|
132
|
+
/** Non-negative weight. Weights are normalised; default 1. */
|
|
133
|
+
weight?: number;
|
|
134
|
+
}
|
|
135
|
+
export interface WorstCaseBound {
|
|
136
|
+
/** Which output the bound is on. */
|
|
137
|
+
quantity: "rawCTC" | "totalCTC";
|
|
138
|
+
/** E_P of the quantity over the given population. */
|
|
139
|
+
nominal: number;
|
|
140
|
+
/** epsilon as passed. */
|
|
141
|
+
epsilon: number;
|
|
142
|
+
lipschitz: number;
|
|
143
|
+
/** The largest value the quantity can take here: rawMax for rawCTC, 1 for the percentile. `upper` is capped at it. */
|
|
144
|
+
ceiling: number;
|
|
145
|
+
/** min(ceiling, nominal + epsilon * lipschitz): no population within W1 epsilon can have a higher mean. */
|
|
146
|
+
upper: number;
|
|
147
|
+
/** max(0, nominal - epsilon * lipschitz). */
|
|
148
|
+
lower: number;
|
|
149
|
+
metric: "W1 over capacity vectors in [0,1]^30 with ground metric |x - y|_1";
|
|
150
|
+
note: string;
|
|
151
|
+
}
|
|
152
|
+
declare function readChainParams(): {
|
|
153
|
+
weightDeficit: number;
|
|
154
|
+
weightSurplus: number;
|
|
155
|
+
contentScaleGain: number;
|
|
156
|
+
depletionGate: number;
|
|
157
|
+
depletionRate: number;
|
|
158
|
+
indirectShare: number;
|
|
159
|
+
maxDrawdown: number;
|
|
160
|
+
capacityEpsilon: number;
|
|
161
|
+
atSkim: number;
|
|
162
|
+
range: number;
|
|
163
|
+
};
|
|
164
|
+
/** The chain constants the derivation reads. */
|
|
165
|
+
export type DroChainParams = ReturnType<typeof readChainParams>;
|
|
166
|
+
/** The chain's structure as the derivation reads it: layers in order, and the interaction pairs with their weights. */
|
|
167
|
+
export interface ChainLayout {
|
|
168
|
+
layers: ReadonlyArray<{
|
|
169
|
+
name: string;
|
|
170
|
+
traits: readonly string[];
|
|
171
|
+
}>;
|
|
172
|
+
pairs: ReadonlyArray<{
|
|
173
|
+
a: string;
|
|
174
|
+
b: string;
|
|
175
|
+
weight: number;
|
|
176
|
+
}>;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Every precondition of the derivation (module comment) that does not hold,
|
|
180
|
+
* as one sentence each; empty when the derivation covers the input. `chain`
|
|
181
|
+
* replaces the live layout or some of the live constants; that is for tests
|
|
182
|
+
* showing each check fires. The bound itself is only computed for the chain.
|
|
183
|
+
*/
|
|
184
|
+
export declare function droPreconditionViolations(demand: DemandDistribution, options?: DroOptions, chain?: {
|
|
185
|
+
layout?: ChainLayout;
|
|
186
|
+
params?: Partial<DroChainParams>;
|
|
187
|
+
}): string[];
|
|
188
|
+
/**
|
|
189
|
+
* A sound Lipschitz constant of rawCTC in the capacity vector, for one demand
|
|
190
|
+
* distribution. See the module comment for the derivation. Throws when one of
|
|
191
|
+
* its preconditions does not hold for the live chain or this input.
|
|
192
|
+
*/
|
|
193
|
+
export declare function ctcLipschitzBound(demand: DemandDistribution, options?: DroOptions): LipschitzBound;
|
|
194
|
+
/**
|
|
195
|
+
* A sound Lipschitz constant of totalCTC, the percentile, in the capacity
|
|
196
|
+
* vector: the rawCTC constant times the largest slope of the percentile curve
|
|
197
|
+
* over [0, rawMax]. Sound because rawCTC never leaves [0, rawMax] on this page
|
|
198
|
+
* and the curve is piecewise linear with that slope as its constant there.
|
|
199
|
+
* Same preconditions as ctcLipschitzBound.
|
|
200
|
+
*/
|
|
201
|
+
export declare function percentileLipschitzBound(demand: DemandDistribution, options?: DroOptions): PercentileLipschitzBound;
|
|
202
|
+
/** rawCTC of one capacity vector (numbers over DEMAND_DIMENSIONS): the quantity ctcLipschitzBound bounds. */
|
|
203
|
+
export declare function rawCTCOfCapacity(x: Record<string, number>, demand: DemandDistribution, options?: DroOptions): number;
|
|
204
|
+
/** totalCTC (the percentile) of one capacity vector: the quantity percentileLipschitzBound bounds. */
|
|
205
|
+
export declare function ctcOfCapacity(x: Record<string, number>, demand: DemandDistribution, options?: DroOptions): number;
|
|
206
|
+
/**
|
|
207
|
+
* Worst-case mean rawCTC over every population within W1 distance `epsilon` of
|
|
208
|
+
* the given one. `epsilon` is required: it is the caller's assumption about
|
|
209
|
+
* how far real users can sit from the personas, in mean L1 change of the
|
|
210
|
+
* capacity vector.
|
|
211
|
+
*/
|
|
212
|
+
export declare function worstCaseCTCBound(population: PopulationMember[], demand: DemandDistribution, epsilon: number, options?: DroOptions): WorstCaseBound;
|
|
213
|
+
/**
|
|
214
|
+
* Worst-case mean totalCTC (the percentile) over every population within W1
|
|
215
|
+
* distance `epsilon` of the given one. Sound and loose: see
|
|
216
|
+
* percentileLipschitzBound and the module comment.
|
|
217
|
+
*/
|
|
218
|
+
export declare function worstCasePercentileBound(population: PopulationMember[], demand: DemandDistribution, epsilon: number, options?: DroOptions): WorstCaseBound;
|
|
219
|
+
export {};
|
|
220
|
+
//# sourceMappingURL=dro-bound.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dro-bound.d.ts","sourceRoot":"","sources":["../../src/visual/dro-bound.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Wasserstein distributionally robust bound on the cognitive transport cost.
|
|
3
|
+
*
|
|
4
|
+
* What it answers. A population of users is a distribution P over capacity
|
|
5
|
+
* vectors x in [0, 1]^30 (one coordinate per DEMAND_DIMENSION, read exactly as
|
|
6
|
+
* the chain reads a persona: capacityVector()). The true population is not
|
|
7
|
+
* known; assume only that it lies within Wasserstein-1 distance epsilon of P,
|
|
8
|
+
* with the ground metric |x - y|_1. Then for every such population Q
|
|
9
|
+
*
|
|
10
|
+
* E_Q[rawCTC] <= E_P[rawCTC] + epsilon * L
|
|
11
|
+
*
|
|
12
|
+
* where L is a Lipschitz constant of rawCTC(x) in the L1 metric on x
|
|
13
|
+
* (Kantorovich-Rubinstein duality: W1 is the supremum of E_Q f - E_P f over
|
|
14
|
+
* 1-Lipschitz f). The bound is also capped at rawMax, the largest raw cost the
|
|
15
|
+
* derivation allows on this page.
|
|
16
|
+
*
|
|
17
|
+
* Why rawCTC. totalCTC is a percentile of rawCTC against real pages
|
|
18
|
+
* (cognitive-transport-chain.ts, ctc-reference.ts), so the chain's own
|
|
19
|
+
* behaviour is in rawCTC and the percentile is a fixed monotone map on top.
|
|
20
|
+
* Through 21.0 totalCTC was a logistic of rawCTC and this bound carried the
|
|
21
|
+
* logistic's slope as a factor; that factor is gone with the logistic.
|
|
22
|
+
*
|
|
23
|
+
* The percentile, too. The interpolated percentile curve is piecewise linear,
|
|
24
|
+
* so it is Lipschitz with constant s = its largest slope over [0, rawMax] (the
|
|
25
|
+
* only raw costs this page can produce). totalCTC(x) = F(rawCTC(x)) is then
|
|
26
|
+
* Lipschitz with L * s, and the same duality gives
|
|
27
|
+
*
|
|
28
|
+
* E_Q[totalCTC] <= E_P[totalCTC] + epsilon * L * s, capped at 1.
|
|
29
|
+
*
|
|
30
|
+
* Sound, and loose: s is the steepest segment of a curve through thousands of
|
|
31
|
+
* samples, so two close samples make it large. percentileLipschitzBound reports
|
|
32
|
+
* s beside the product so the looseness is visible rather than inferred.
|
|
33
|
+
*
|
|
34
|
+
* What it does NOT answer. This is a property of the MODEL: how far the
|
|
35
|
+
* model's own output can move when the population moves. It says nothing about
|
|
36
|
+
* whether the model predicts people. The chain's constants are hand-set
|
|
37
|
+
* hypotheses (see provenance/chain.ts) and CTC has not been tested against
|
|
38
|
+
* human data; a bound around such a function is not evidence about users and
|
|
39
|
+
* must never be reported as such.
|
|
40
|
+
*
|
|
41
|
+
* epsilon has no default. No data fixes how far a real population sits from a
|
|
42
|
+
* persona roster, so the radius is the caller's assumption and must be named
|
|
43
|
+
* by the caller.
|
|
44
|
+
*
|
|
45
|
+
* How L is derived (sound, not sampled). For each input coordinate s the code
|
|
46
|
+
* below bounds sup |d rawCTC / d x_s| by walking the chain's own structure:
|
|
47
|
+
*
|
|
48
|
+
* - layer k's cost is c_k * sum_t w_t (d_t - cap_t)^2, with c_k the content
|
|
49
|
+
* gate (a function of demand alone, except in readingAttention, see below);
|
|
50
|
+
* |d cost / d cap_t| <= c_k * 2 * max(w_def * d_t, w_sur(t) * (1 - d_t)),
|
|
51
|
+
* because a deficit gap is at most d_t and a surplus gap at most 1 - d_t;
|
|
52
|
+
* - except for an exposure-priced trait (EXPOSURE_DIMENSIONS, asymmetric
|
|
53
|
+
* mode), whose term is w_sur * cap_t * d_t: |d cost / d cap_t| = c_k *
|
|
54
|
+
* w_sur * d_t, and the term is at most w_sur * d_t (capacities are <= 1);
|
|
55
|
+
* - the layers' trait sets are disjoint, so a coordinate reaches a later
|
|
56
|
+
* layer only through the indirect drawdown cap *= 1 - min(m, rho*sigma*L_j)
|
|
57
|
+
* of every gated earlier layer, whose derivative in L_j is at most
|
|
58
|
+
* rho*sigma (capacities are <= 1); the drawdown of a layer's own traits
|
|
59
|
+
* is never read again on the same page;
|
|
60
|
+
* - readingTendency enters through demand: it scales sustainedAttention
|
|
61
|
+
* demand by atSkim + x * range, which moves both the gap and the content
|
|
62
|
+
* gate of readingAttention, the last layer (so its depletion gate cannot
|
|
63
|
+
* feed back into anything on the page);
|
|
64
|
+
* - interaction terms w_p * L_a * L_b are bounded by the product rule with
|
|
65
|
+
* each layer's maximum attainable cost.
|
|
66
|
+
*
|
|
67
|
+
* Every piece of the chain is continuous in x (the deficit/surplus switch
|
|
68
|
+
* meets at gap 0, min/max clamps are continuous, and the only x-dependent gate
|
|
69
|
+
* sits after the last layer), so a bound on the partial derivatives where they
|
|
70
|
+
* exist is a Lipschitz constant. Each partial is bounded separately and the
|
|
71
|
+
* L1 constant is their maximum, which is the dual norm of L1.
|
|
72
|
+
*
|
|
73
|
+
* Schwartz value modulation of demand is not supported here (it would add
|
|
74
|
+
* further demand-dependence on options); no shipped caller passes it.
|
|
75
|
+
*
|
|
76
|
+
* Preconditions. The steps above hold only for a chain of a certain shape, and
|
|
77
|
+
* the chain's layout and constants are edited independently of this file. So
|
|
78
|
+
* every call checks them against the live chain and throws, naming the broken
|
|
79
|
+
* assumption, rather than return a constant the derivation does not cover
|
|
80
|
+
* (droPreconditionViolations):
|
|
81
|
+
*
|
|
82
|
+
* - layer names are unique (interaction terms look layers up by name);
|
|
83
|
+
* - every layer lists at least one trait, and no trait is listed twice,
|
|
84
|
+
* within a layer or across layers (disjoint trait sets: a later layer would
|
|
85
|
+
* otherwise read capacity drawn at the full depletion rate);
|
|
86
|
+
* - the layer listing sustainedAttention, whose demand moves with
|
|
87
|
+
* readingTendency, is the last layer (its depletion gate switches with
|
|
88
|
+
* readingTendency, so a later layer would make CTC discontinuous in x) and
|
|
89
|
+
* lists no other trait (its content-gate term counts that gap alone);
|
|
90
|
+
* - interaction weights are finite and >= 0, when interactions are on;
|
|
91
|
+
* - every demand is a finite number >= 0 (the gap bounds);
|
|
92
|
+
* - no option beyond asymmetric and interactions (Schwartz values and a
|
|
93
|
+
* carried capacity change the demand and the starting capacity);
|
|
94
|
+
* - the chain constants are finite, with deficit and surplus weights, the
|
|
95
|
+
* content-scale gain, depletion rate, indirect share, drawdown cap and
|
|
96
|
+
* engagement range >= 0, and the capacity floor in [0, 1].
|
|
97
|
+
*
|
|
98
|
+
* @copyright 2026 Alexandria Eden alexandria.shai.eden@gmail.com https://cbrowser.ai
|
|
99
|
+
* @license MIT
|
|
100
|
+
*/
|
|
101
|
+
import { computeSequentialCTC, ctcReferenceCurve, capacityVector, DEMAND_DIMENSIONS, LAYER_DEFINITIONS, INTERACTION_PAIRS, SURPLUS_FREE_DIMENSIONS, EXPOSURE_DIMENSIONS, } from "./cognitive-transport-chain.js";
|
|
102
|
+
import { buildOTCognitiveProfile } from "./cognitive-transport.js";
|
|
103
|
+
import { curveSlope } from "./ctc-reference.js";
|
|
104
|
+
import { param } from "./model-provenance.js";
|
|
105
|
+
function readChainParams() {
|
|
106
|
+
return {
|
|
107
|
+
weightDeficit: param("chain.weightDeficit"),
|
|
108
|
+
weightSurplus: param("chain.weightSurplus"),
|
|
109
|
+
contentScaleGain: param("chain.contentScaleGain"),
|
|
110
|
+
depletionGate: param("chain.depletionGate"),
|
|
111
|
+
depletionRate: param("chain.depletionRate"),
|
|
112
|
+
indirectShare: param("chain.indirectDepletionShare"),
|
|
113
|
+
maxDrawdown: param("chain.maxDrawdownFraction"),
|
|
114
|
+
capacityEpsilon: param("chain.capacityEpsilon"),
|
|
115
|
+
atSkim: param("chain.engagement.atSkim"),
|
|
116
|
+
range: param("chain.engagement.range"),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function chainLayout() {
|
|
120
|
+
return { layers: LAYER_DEFINITIONS, pairs: INTERACTION_PAIRS.map((p) => ({ a: p.a, b: p.b, weight: param(p.weight) })) };
|
|
121
|
+
}
|
|
122
|
+
const SA = "sustainedAttention";
|
|
123
|
+
const RT = "readingTendency";
|
|
124
|
+
/**
|
|
125
|
+
* Every precondition of the derivation (module comment) that does not hold,
|
|
126
|
+
* as one sentence each; empty when the derivation covers the input. `chain`
|
|
127
|
+
* replaces the live layout or some of the live constants; that is for tests
|
|
128
|
+
* showing each check fires. The bound itself is only computed for the chain.
|
|
129
|
+
*/
|
|
130
|
+
export function droPreconditionViolations(demand, options = {}, chain = {}) {
|
|
131
|
+
const layout = chain.layout ?? chainLayout();
|
|
132
|
+
const params = { ...readChainParams(), ...chain.params };
|
|
133
|
+
const broken = [];
|
|
134
|
+
for (const [k, v] of Object.entries(options ?? {}))
|
|
135
|
+
if (k !== "asymmetric" && k !== "interactions" && v !== undefined)
|
|
136
|
+
broken.push(`option "${k}" is not modelled: the derivation holds demand and the starting capacity fixed, and Schwartz values or a carried capacity change them`);
|
|
137
|
+
for (const [t, v] of Object.entries(demand?.demands ?? {}))
|
|
138
|
+
if (typeof v !== "number" || !Number.isFinite(v) || v < 0)
|
|
139
|
+
broken.push(`demand ${t} = ${String(v)} is not a finite number >= 0: the deficit and surplus gap bounds assume it is`);
|
|
140
|
+
const names = new Set();
|
|
141
|
+
const owner = new Map();
|
|
142
|
+
for (const l of layout.layers) {
|
|
143
|
+
if (names.has(l.name))
|
|
144
|
+
broken.push(`layer name "${l.name}" repeats: interaction terms look layers up by name`);
|
|
145
|
+
names.add(l.name);
|
|
146
|
+
if (l.traits.length === 0)
|
|
147
|
+
broken.push(`layer "${l.name}" lists no trait: its content gate is a mean over its traits`);
|
|
148
|
+
for (const t of l.traits) {
|
|
149
|
+
const prev = owner.get(t);
|
|
150
|
+
if (prev === undefined)
|
|
151
|
+
owner.set(t, l.name);
|
|
152
|
+
else
|
|
153
|
+
broken.push(`trait "${t}" is listed in ${prev === l.name ? `layer "${l.name}" twice` : `layers "${prev}" and "${l.name}"`}: layer trait sets must be disjoint, or a later layer reads capacity drawn at the full depletion rate rather than the indirect share`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const iSA = layout.layers.findIndex((l) => l.traits.includes(SA));
|
|
157
|
+
if (iSA >= 0) {
|
|
158
|
+
const l = layout.layers[iSA];
|
|
159
|
+
if (iSA !== layout.layers.length - 1)
|
|
160
|
+
broken.push(`layer "${l.name}" (${SA}, whose demand moves with ${RT}) is not the last layer: its depletion gate switches with ${RT}, so a layer after it would make CTC discontinuous`);
|
|
161
|
+
if (l.traits.some((t) => t !== SA))
|
|
162
|
+
broken.push(`layer "${l.name}" lists traits besides ${SA}: the ${RT} term bounds its content-gate derivative by the ${SA} gap alone`);
|
|
163
|
+
}
|
|
164
|
+
if (options?.interactions !== false)
|
|
165
|
+
for (const p of layout.pairs)
|
|
166
|
+
if (!(Number.isFinite(p.weight) && p.weight >= 0))
|
|
167
|
+
broken.push(`interaction weight ${p.a}x${p.b} = ${p.weight} is not finite and >= 0: the product-rule bound adds each term with its sign`);
|
|
168
|
+
const nonNegative = ["weightDeficit", "weightSurplus", "contentScaleGain", "depletionRate", "indirectShare", "maxDrawdown", "range"];
|
|
169
|
+
for (const k of nonNegative)
|
|
170
|
+
if (!(Number.isFinite(params[k]) && params[k] >= 0))
|
|
171
|
+
broken.push(`chain constant ${k} = ${params[k]} is not finite and >= 0`);
|
|
172
|
+
for (const k of ["depletionGate", "atSkim"])
|
|
173
|
+
if (!Number.isFinite(params[k]))
|
|
174
|
+
broken.push(`chain constant ${k} = ${params[k]} is not finite`);
|
|
175
|
+
if (!(params.capacityEpsilon >= 0 && params.capacityEpsilon <= 1))
|
|
176
|
+
broken.push(`chain constant capacityEpsilon = ${params.capacityEpsilon} is not in [0, 1]: the depletion bound assumes capacities stay <= 1`);
|
|
177
|
+
return broken;
|
|
178
|
+
}
|
|
179
|
+
const clamp01 = (v) => Math.max(0, Math.min(1, v));
|
|
180
|
+
/**
|
|
181
|
+
* A sound Lipschitz constant of rawCTC in the capacity vector, for one demand
|
|
182
|
+
* distribution. See the module comment for the derivation. Throws when one of
|
|
183
|
+
* its preconditions does not hold for the live chain or this input.
|
|
184
|
+
*/
|
|
185
|
+
export function ctcLipschitzBound(demand, options = {}) {
|
|
186
|
+
const P = readChainParams();
|
|
187
|
+
const layout = chainLayout();
|
|
188
|
+
const broken = droPreconditionViolations(demand, options, { layout, params: P });
|
|
189
|
+
if (broken.length)
|
|
190
|
+
throw new Error(`ctcLipschitzBound: the derivation does not cover this input: ${broken.join("; ")}`);
|
|
191
|
+
const asym = options.asymmetric !== false;
|
|
192
|
+
const useInter = options.interactions !== false;
|
|
193
|
+
const d0 = (t) => demand.demands[t] ?? 0;
|
|
194
|
+
const wDef = asym ? P.weightDeficit : 1;
|
|
195
|
+
const wSur = (t) => (asym ? (SURPLUS_FREE_DIMENSIONS.has(t) ? 0 : P.weightSurplus) : 1);
|
|
196
|
+
// sustainedAttention demand ranges with readingTendency in [0, 1].
|
|
197
|
+
const saLo = clamp01(d0(SA) * P.atSkim);
|
|
198
|
+
const saHi = clamp01(d0(SA) * (P.atSkim + P.range));
|
|
199
|
+
const saSlope = d0(SA) * P.range; // |d demand_sa / d x_rt| where unclamped
|
|
200
|
+
const layers = layout.layers.map((def) => {
|
|
201
|
+
const dep = def.traits.includes(SA);
|
|
202
|
+
const dHi = (t) => (t === SA ? saHi : Math.max(0, d0(t)));
|
|
203
|
+
const dLo = (t) => (t === SA ? saLo : Math.max(0, d0(t)));
|
|
204
|
+
const mean = def.traits.reduce((s, t) => s + dHi(t), 0) / def.traits.length;
|
|
205
|
+
const gate = Math.min(1, mean * P.contentScaleGain);
|
|
206
|
+
// Depletion gating depends on demand only, except in a layer whose demand
|
|
207
|
+
// moves with x; treat such a layer as gated (an upper bound on coupling).
|
|
208
|
+
const meanLo = def.traits.reduce((s, t) => s + dLo(t), 0) / def.traits.length;
|
|
209
|
+
const gated = dep ? true : Math.min(1, meanLo * P.contentScaleGain) > P.depletionGate;
|
|
210
|
+
const g = {};
|
|
211
|
+
let A = 0, maxCost = 0;
|
|
212
|
+
for (const t of def.traits) {
|
|
213
|
+
const defGap = dHi(t);
|
|
214
|
+
const surGap = Math.max(0, 1 - dLo(t));
|
|
215
|
+
if (asym && EXPOSURE_DIMENSIONS.has(t)) {
|
|
216
|
+
// Exposure, w_sur * cap * d: linear in cap, slope w_sur * d, at most w_sur * d.
|
|
217
|
+
g[t] = gate * P.weightSurplus * defGap;
|
|
218
|
+
A += g[t];
|
|
219
|
+
maxCost += P.weightSurplus * defGap;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
g[t] = gate * 2 * Math.max(wDef * defGap, wSur(t) * surGap);
|
|
223
|
+
A += g[t];
|
|
224
|
+
maxCost += Math.max(wDef * defGap * defGap, wSur(t) * surGap * surGap);
|
|
225
|
+
}
|
|
226
|
+
return { name: def.name, traits: def.traits, gate, gated, g, A, maxCost: gate * maxCost };
|
|
227
|
+
});
|
|
228
|
+
const rhoSigma = P.depletionRate * P.indirectShare;
|
|
229
|
+
const pairs = useInter ? layout.pairs.map((p) => ({ a: p.a, b: p.b, w: p.weight })) : [];
|
|
230
|
+
const maxCostOf = (name) => layers.find((l) => l.name === name)?.maxCost ?? 0;
|
|
231
|
+
let rawMax = layers.reduce((s, l) => s + l.maxCost, 0);
|
|
232
|
+
for (const p of pairs)
|
|
233
|
+
rawMax += p.w * maxCostOf(p.a) * maxCostOf(p.b);
|
|
234
|
+
const perDimension = {};
|
|
235
|
+
let lipschitz = 0, worstDimension = DEMAND_DIMENSIONS[0];
|
|
236
|
+
for (const s of DEMAND_DIMENSIONS) {
|
|
237
|
+
const D = {};
|
|
238
|
+
let earlier = 0; // sum over earlier gated layers of D_j(s)
|
|
239
|
+
let rawPartial = 0;
|
|
240
|
+
for (const l of layers) {
|
|
241
|
+
let dk = (l.g[s] ?? 0) + l.A * rhoSigma * earlier;
|
|
242
|
+
if (s === RT && l.traits.includes(SA)) {
|
|
243
|
+
// readingTendency moves this layer's demand: gap and content gate.
|
|
244
|
+
const wMax = Math.max(wDef, wSur(SA));
|
|
245
|
+
const gapMax = Math.max(saHi, 1 - saLo);
|
|
246
|
+
dk += saSlope * (P.contentScaleGain * wMax * gapMax * gapMax + 2 * l.gate * wMax * gapMax);
|
|
247
|
+
}
|
|
248
|
+
D[l.name] = dk;
|
|
249
|
+
rawPartial += dk;
|
|
250
|
+
if (l.gated)
|
|
251
|
+
earlier += dk;
|
|
252
|
+
}
|
|
253
|
+
for (const p of pairs)
|
|
254
|
+
rawPartial += p.w * ((D[p.a] ?? 0) * maxCostOf(p.b) + maxCostOf(p.a) * (D[p.b] ?? 0));
|
|
255
|
+
const bound = rawPartial;
|
|
256
|
+
perDimension[s] = bound;
|
|
257
|
+
if (bound > lipschitz) {
|
|
258
|
+
lipschitz = bound;
|
|
259
|
+
worstDimension = s;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return { lipschitz, worstDimension, perDimension, rawMax };
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* A sound Lipschitz constant of totalCTC, the percentile, in the capacity
|
|
266
|
+
* vector: the rawCTC constant times the largest slope of the percentile curve
|
|
267
|
+
* over [0, rawMax]. Sound because rawCTC never leaves [0, rawMax] on this page
|
|
268
|
+
* and the curve is piecewise linear with that slope as its constant there.
|
|
269
|
+
* Same preconditions as ctcLipschitzBound.
|
|
270
|
+
*/
|
|
271
|
+
export function percentileLipschitzBound(demand, options = {}) {
|
|
272
|
+
const raw = ctcLipschitzBound(demand, options);
|
|
273
|
+
const referenceScope = demand.scope ?? "viewport";
|
|
274
|
+
const slope = curveSlope(ctcReferenceCurve(referenceScope, options).curve, 0, raw.rawMax);
|
|
275
|
+
return { lipschitz: raw.lipschitz * slope, raw, curveSlope: slope, referenceScope };
|
|
276
|
+
}
|
|
277
|
+
function chainOptions(options) {
|
|
278
|
+
return { asymmetric: options.asymmetric !== false, interactions: options.interactions !== false };
|
|
279
|
+
}
|
|
280
|
+
/** rawCTC of one capacity vector (numbers over DEMAND_DIMENSIONS): the quantity ctcLipschitzBound bounds. */
|
|
281
|
+
export function rawCTCOfCapacity(x, demand, options = {}) {
|
|
282
|
+
return computeSequentialCTC(buildOTCognitiveProfile("dro", x), demand, chainOptions(options)).rawCTC;
|
|
283
|
+
}
|
|
284
|
+
/** totalCTC (the percentile) of one capacity vector: the quantity percentileLipschitzBound bounds. */
|
|
285
|
+
export function ctcOfCapacity(x, demand, options = {}) {
|
|
286
|
+
return computeSequentialCTC(buildOTCognitiveProfile("dro", x), demand, chainOptions(options)).totalCTC;
|
|
287
|
+
}
|
|
288
|
+
/** E_P[f] with the weights normalised, after checking epsilon and the weights. */
|
|
289
|
+
function populationMean(who, population, epsilon, f) {
|
|
290
|
+
if (typeof epsilon !== "number" || !Number.isFinite(epsilon) || epsilon < 0)
|
|
291
|
+
throw new Error(`${who}: epsilon must be a finite number >= 0 (no default; it is the caller's assumption)`);
|
|
292
|
+
if (!population.length)
|
|
293
|
+
throw new Error(`${who}: population is empty`);
|
|
294
|
+
let total = 0, mean = 0;
|
|
295
|
+
for (const m of population) {
|
|
296
|
+
const w = m.weight ?? 1;
|
|
297
|
+
if (!(w >= 0) || !Number.isFinite(w))
|
|
298
|
+
throw new Error(`${who}: weights must be finite and >= 0`);
|
|
299
|
+
total += w;
|
|
300
|
+
}
|
|
301
|
+
if (!(total > 0))
|
|
302
|
+
throw new Error(`${who}: weights sum to 0`);
|
|
303
|
+
for (const m of population)
|
|
304
|
+
mean += ((m.weight ?? 1) / total) * f(capacityVector(m.traits));
|
|
305
|
+
return mean;
|
|
306
|
+
}
|
|
307
|
+
function worstCase(quantity, nominal, epsilon, lipschitz, ceiling) {
|
|
308
|
+
return {
|
|
309
|
+
quantity,
|
|
310
|
+
nominal,
|
|
311
|
+
epsilon,
|
|
312
|
+
lipschitz,
|
|
313
|
+
ceiling,
|
|
314
|
+
upper: Math.min(ceiling, nominal + epsilon * lipschitz),
|
|
315
|
+
lower: Math.max(0, nominal - epsilon * lipschitz),
|
|
316
|
+
metric: "W1 over capacity vectors in [0,1]^30 with ground metric |x - y|_1",
|
|
317
|
+
note: `A property of the model, not of people: how far the model's mean ${quantity} can move when the population moves by epsilon. The chain's constants are hand-set hypotheses.`,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Worst-case mean rawCTC over every population within W1 distance `epsilon` of
|
|
322
|
+
* the given one. `epsilon` is required: it is the caller's assumption about
|
|
323
|
+
* how far real users can sit from the personas, in mean L1 change of the
|
|
324
|
+
* capacity vector.
|
|
325
|
+
*/
|
|
326
|
+
export function worstCaseCTCBound(population, demand, epsilon, options = {}) {
|
|
327
|
+
const mean = populationMean("worstCaseCTCBound", population, epsilon, (x) => rawCTCOfCapacity(x, demand, options));
|
|
328
|
+
const { lipschitz, rawMax } = ctcLipschitzBound(demand, options);
|
|
329
|
+
return worstCase("rawCTC", mean, epsilon, lipschitz, rawMax);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Worst-case mean totalCTC (the percentile) over every population within W1
|
|
333
|
+
* distance `epsilon` of the given one. Sound and loose: see
|
|
334
|
+
* percentileLipschitzBound and the module comment.
|
|
335
|
+
*/
|
|
336
|
+
export function worstCasePercentileBound(population, demand, epsilon, options = {}) {
|
|
337
|
+
const mean = populationMean("worstCasePercentileBound", population, epsilon, (x) => ctcOfCapacity(x, demand, options));
|
|
338
|
+
const { lipschitz } = percentileLipschitzBound(demand, options);
|
|
339
|
+
return worstCase("totalCTC", mean, epsilon, lipschitz, 1);
|
|
340
|
+
}
|
|
341
|
+
//# sourceMappingURL=dro-bound.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dro-bound.js","sourceRoot":"","sources":["../../src/visual/dro-bound.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exact Wasserstein-1 (earth mover's) distance between two discrete
|
|
3
|
+
* distributions over the same n points, under an arbitrary non-negative cost
|
|
4
|
+
* matrix.
|
|
5
|
+
*
|
|
6
|
+
* Solves the transportation problem
|
|
7
|
+
*
|
|
8
|
+
* min sum_ij C[i][j] * P[i][j]
|
|
9
|
+
* s.t. sum_j P[i][j] = a[i], sum_i P[i][j] = b[j], P >= 0
|
|
10
|
+
*
|
|
11
|
+
* as a min-cost flow on the bipartite graph source -> i -> j -> sink with
|
|
12
|
+
* successive shortest paths (Dijkstra with Johnson potentials, so reverse edges
|
|
13
|
+
* with negative reduced cost never break the search). Every augmentation ships
|
|
14
|
+
* the bottleneck mass along a shortest source-to-sink path in the residual
|
|
15
|
+
* graph; the plan it leaves behind is optimal by the standard SSP argument
|
|
16
|
+
* (each augmentation is along a shortest path, so no negative cycle is ever
|
|
17
|
+
* created in the residual graph).
|
|
18
|
+
*
|
|
19
|
+
* Complexity: one Dijkstra is O(V^2) on this dense graph, V = 2n + 2. The number
|
|
20
|
+
* of augmentations K is bounded by the number of edges whose residual capacity
|
|
21
|
+
* can be exhausted (each augmentation saturates a supply edge, a demand edge or
|
|
22
|
+
* cancels a reverse edge), so the total is O(K * n^2) with K = O(n^2) in the
|
|
23
|
+
* worst case. cognitiveDistance now calls it on 30 points (29 traits plus the
|
|
24
|
+
* slack bin of the generalized distance). Measured across all 300 roster pairs
|
|
25
|
+
* in the canonical order cognitiveDistance uses (2026-10-21, after the end-node
|
|
26
|
+
* fix below): K = 41 min, 51 median, 57 max on the 30-point problem (the
|
|
27
|
+
* 29-point simplex problem it replaced: 48 / 57 / 57; 54 / 72 / 161 with the
|
|
28
|
+
* old end-node rule), i.e. roughly 1.5n to 2n, and a 25 x 25 distance matrix
|
|
29
|
+
* takes ~62 ms median (research/latency/bench-ctc.ts; ~73 ms before).
|
|
30
|
+
* Mass is floating point, so "saturated" means residual <= EPS and the loop
|
|
31
|
+
* stops once every supply point or every demand point is at or below EPS.
|
|
32
|
+
*
|
|
33
|
+
* `cognitiveDistance` used to call its result "W1" while computing a weighted
|
|
34
|
+
* L1 sum (|a_i - b_i| times the mean ground distance of trait i), which is not
|
|
35
|
+
* optimal transport and does not respect the ground metric. This module is the
|
|
36
|
+
* exact replacement. Its oracle test (tests/cognitive-distance-w1.test.ts)
|
|
37
|
+
* checks it against an independent dense two-phase simplex on the same LP, and,
|
|
38
|
+
* with a slack bin, against the Piccoli-Rossi unbalanced LP it stands in for.
|
|
39
|
+
*
|
|
40
|
+
* @copyright 2026 Alexandria Eden alexandria.shai.eden@gmail.com https://cbrowser.ai
|
|
41
|
+
* @license MIT
|
|
42
|
+
*/
|
|
43
|
+
export interface TransportResult {
|
|
44
|
+
/** Optimal transport cost, i.e. the exact W1 distance. */
|
|
45
|
+
cost: number;
|
|
46
|
+
/** Optimal plan: plan[i][j] = mass moved from point i to point j (diagonal included). */
|
|
47
|
+
plan: number[][];
|
|
48
|
+
/** Number of augmenting paths the solver used (diagnostic, for the complexity claim). */
|
|
49
|
+
augmentations: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Exact W1 between distributions `a` and `b` (same length n, both summing to
|
|
53
|
+
* the same total up to EPS) under cost matrix `cost` (n x n, non-negative).
|
|
54
|
+
*
|
|
55
|
+
* Throws if the shapes disagree or the masses differ by more than 1e-9: unequal
|
|
56
|
+
* mass is an unbalanced problem and W1 is undefined for it. (cognitiveDistance
|
|
57
|
+
* balances its measures first with a slack bin; see traitsToLevelMeasure.)
|
|
58
|
+
*/
|
|
59
|
+
export declare function exactW1(a: ArrayLike<number>, b: ArrayLike<number>, cost: ArrayLike<ArrayLike<number>>): TransportResult;
|
|
60
|
+
//# sourceMappingURL=exact-w1.d.ts.map
|