@lapxo/obligations 0.3.4 → 0.4.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 +12 -135
- package/TARGET.bound +574 -503
- package/dist/measures/error-events.d.ts +27 -0
- package/dist/measures/error-events.js +43 -0
- package/dist/measures/experiments.d.ts +15 -0
- package/dist/measures/experiments.js +53 -0
- package/dist/measures/fitting.d.ts +243 -0
- package/dist/measures/fitting.js +115 -0
- package/dist/measures/identification.d.ts +156 -0
- package/dist/measures/identification.js +107 -0
- package/dist/measures/index.d.ts +18 -0
- package/dist/measures/index.js +9 -0
- package/dist/measures/m3-experiment.d.ts +69 -0
- package/dist/measures/m3-experiment.js +70 -0
- package/dist/measures/m3.d.ts +139 -0
- package/dist/measures/m3.js +181 -0
- package/dist/measures/model.d.ts +14 -0
- package/dist/measures/model.js +67 -0
- package/dist/measures/rational.d.ts +19 -0
- package/dist/measures/rational.js +53 -0
- package/dist/measures/spectrum.d.ts +22 -0
- package/dist/measures/spectrum.js +84 -0
- package/docs/measures.md +149 -0
- package/package.json +1 -93
- package/receipts.bound +75 -0
- package/samples/measures/descent.json +92 -0
- package/samples/measures/m3-reader.mjs +732 -0
- package/samples/measures/m3.json +3126 -0
- package/samples/measures/observations.json +212 -0
- package/samples/measures/reader.mjs +424 -0
- package/samples/measures/spectrum.json +6530 -0
- package/samples/measures/unanimity.json +76 -0
- package/samples/no/installed-artifact.json +302 -0
- package/samples/yes/algebra-is-closed.json +17 -0
- package/samples/yes/field-uses-price-and-debit.json +9 -0
- package/samples/yes/installed-artifact.json +397 -0
- package/samples/yes/three-theories-one-algebra.json +5 -0
- package/src/field/motion.ts +59 -0
- package/src/lattice/index.ts +79 -0
- package/vectors/measures/descent.cli.json +148 -0
- package/vectors/measures/installed-artifact.cli.json +43 -0
- package/vectors/measures/m3.cli.json +148 -0
- package/vectors/measures/observations.cli.json +148 -0
- package/vectors/measures/spectrum.cli.json +148 -0
- package/vectors/measures/unanimity.cli.json +148 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
function valid({ c, p, n }) {
|
|
2
|
+
if (!Number.isFinite(c) || c < 0 || c > 1 || !Number.isFinite(p) || p < 0 || p > 1 || !Number.isSafeInteger(n) || n < 2)
|
|
3
|
+
throw new Error('REFUSE·measure invalid unanimity model');
|
|
4
|
+
}
|
|
5
|
+
function logSum(a, b) { const high = Math.max(a, b); return high === -Infinity ? high : high + Math.log(Math.exp(a - high) + Math.exp(b - high)); }
|
|
6
|
+
export function unanimityFloor(model, k) {
|
|
7
|
+
valid(model);
|
|
8
|
+
if (!Number.isSafeInteger(k) || k < 1)
|
|
9
|
+
throw new Error('REFUSE·measure invalid witness count');
|
|
10
|
+
const { c, p, n } = model;
|
|
11
|
+
if (c === 1 || p === 1)
|
|
12
|
+
return { status: 'measured', value: 1 };
|
|
13
|
+
if (p === 0)
|
|
14
|
+
return { status: 'measured', value: c };
|
|
15
|
+
const logPrivate = Math.log1p(-c) + k * Math.log(p) + (1 - k) * Math.log(n - 1);
|
|
16
|
+
const logA = logSum(c === 0 ? -Infinity : Math.log(c), logPrivate), logB = Math.log1p(-c) + k * Math.log1p(-p);
|
|
17
|
+
const odds = logA - logB;
|
|
18
|
+
const value = odds >= 0 ? 1 / (1 + Math.exp(-odds)) : Math.exp(odds) / (1 + Math.exp(odds));
|
|
19
|
+
return { status: 'measured', value };
|
|
20
|
+
}
|
|
21
|
+
export function unanimityThreshold(model, searchLimit) {
|
|
22
|
+
valid(model);
|
|
23
|
+
if (!Number.isSafeInteger(searchLimit) || searchLimit < 1)
|
|
24
|
+
throw new Error('REFUSE·measure invalid search budget');
|
|
25
|
+
const { c, p, n } = model, q = p / (n - 1), coefficient = 1 - p - q;
|
|
26
|
+
if (c === 1 || p === 0 || p === 1 || coefficient <= 0)
|
|
27
|
+
return { status: 'measured', value: 1 };
|
|
28
|
+
if (c === 0)
|
|
29
|
+
return { status: 'unmeasured', cause: 'no finite nondecreasing threshold for this model' };
|
|
30
|
+
const right = Math.log(p) + Math.log(c), base = Math.log(coefficient) + Math.log1p(-c) + Math.log(n - 1);
|
|
31
|
+
for (let k = 1; k <= searchLimit; k++)
|
|
32
|
+
if (base + k * Math.log(q) <= right)
|
|
33
|
+
return { status: 'measured', value: k };
|
|
34
|
+
return { status: 'unmeasured', cause: 'threshold outside declared search budget' };
|
|
35
|
+
}
|
|
36
|
+
export function descentCount(graph, cell) {
|
|
37
|
+
const nodes = new Map();
|
|
38
|
+
for (const node of graph) {
|
|
39
|
+
if (!node.scope || nodes.has(node.scope))
|
|
40
|
+
throw new Error('REFUSE·measure duplicate or absent graph scope');
|
|
41
|
+
nodes.set(node.scope, [...new Set(node.restsOn)]);
|
|
42
|
+
}
|
|
43
|
+
if (!nodes.has(cell) || [...nodes.values()].some(parents => parents.some(parent => !nodes.has(parent))))
|
|
44
|
+
return { status: 'unmeasured', cause: 'incomplete declared descent graph' };
|
|
45
|
+
const seen = new Map(), visiting = new Set();
|
|
46
|
+
function reaches(scope) {
|
|
47
|
+
if (visiting.has(scope))
|
|
48
|
+
throw new Error('REFUSE·measure cyclic descent at ' + scope);
|
|
49
|
+
if (seen.has(scope))
|
|
50
|
+
return seen.get(scope);
|
|
51
|
+
visiting.add(scope);
|
|
52
|
+
let result = false;
|
|
53
|
+
for (const parent of nodes.get(scope)) {
|
|
54
|
+
const nested = reaches(parent);
|
|
55
|
+
result = result || parent === cell || nested;
|
|
56
|
+
}
|
|
57
|
+
visiting.delete(scope);
|
|
58
|
+
seen.set(scope, result);
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
let count = 0;
|
|
62
|
+
for (const scope of nodes.keys())
|
|
63
|
+
if (reaches(scope) && scope !== cell)
|
|
64
|
+
count++;
|
|
65
|
+
return { status: 'measured', value: count };
|
|
66
|
+
}
|
|
67
|
+
export const modelRequired = (measure) => ({ status: 'unmeasured', cause: 'declared model required for ' + measure });
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type Rational = Readonly<{
|
|
2
|
+
numerator: string;
|
|
3
|
+
denominator: string;
|
|
4
|
+
}>;
|
|
5
|
+
export type RationalInput = string | Rational;
|
|
6
|
+
export type Q = readonly [bigint, bigint];
|
|
7
|
+
export declare const zero: Q, one: Q;
|
|
8
|
+
export declare const refuse: (cause: string) => never;
|
|
9
|
+
export declare function q(a: bigint, b?: bigint): Q;
|
|
10
|
+
export declare function rational(input: RationalInput): Q;
|
|
11
|
+
export declare const add: (a: Q, b: Q) => Q;
|
|
12
|
+
export declare const sub: (a: Q, b: Q) => Q;
|
|
13
|
+
export declare const mul: (a: Q, b: Q) => Q;
|
|
14
|
+
export declare const div: (a: Q, b: Q) => Q;
|
|
15
|
+
export declare const pow: (a: Q, n: number) => Q;
|
|
16
|
+
export declare const equal: (a: Q, b: Q) => boolean;
|
|
17
|
+
export declare const pack: (a: Q) => Rational;
|
|
18
|
+
export declare function probability(input: RationalInput): Q;
|
|
19
|
+
export declare function roundHalfEven(input: RationalInput, digits: number): string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export const zero = [0n, 1n], one = [1n, 1n];
|
|
2
|
+
export const refuse = (cause) => { throw new Error('REFUSE·model/M3 ' + cause); };
|
|
3
|
+
const gcd = (a, b) => { a = a < 0n ? -a : a; while (b) {
|
|
4
|
+
const r = a % b;
|
|
5
|
+
a = b;
|
|
6
|
+
b = r;
|
|
7
|
+
} return a; };
|
|
8
|
+
export function q(a, b = 1n) {
|
|
9
|
+
if (b === 0n)
|
|
10
|
+
refuse('zero rational denominator');
|
|
11
|
+
if (b < 0n) {
|
|
12
|
+
a = -a;
|
|
13
|
+
b = -b;
|
|
14
|
+
}
|
|
15
|
+
const d = gcd(a, b);
|
|
16
|
+
return [a / d, b / d];
|
|
17
|
+
}
|
|
18
|
+
export function rational(input) {
|
|
19
|
+
if (typeof input === 'string') {
|
|
20
|
+
if (/^-?\d+\/\d+$/.test(input)) {
|
|
21
|
+
const [a, b] = input.split('/');
|
|
22
|
+
return q(BigInt(a), BigInt(b));
|
|
23
|
+
}
|
|
24
|
+
if (!/^-?\d+(\.\d+)?$/.test(input))
|
|
25
|
+
refuse('invalid exact probability');
|
|
26
|
+
const sign = input.startsWith('-') ? -1n : 1n, text = input.replace(/^-/, '');
|
|
27
|
+
const [whole, part = ''] = text.split('.');
|
|
28
|
+
return q(sign * BigInt(whole + part), 10n ** BigInt(part.length));
|
|
29
|
+
}
|
|
30
|
+
if (!input || typeof input.numerator !== 'string' || typeof input.denominator !== 'string' || !/^[-]?\d+$/.test(input.numerator) || !/^\d+$/.test(input.denominator))
|
|
31
|
+
refuse('invalid rational');
|
|
32
|
+
return q(BigInt(input.numerator), BigInt(input.denominator));
|
|
33
|
+
}
|
|
34
|
+
export const add = (a, b) => q(a[0] * b[1] + b[0] * a[1], a[1] * b[1]);
|
|
35
|
+
export const sub = (a, b) => q(a[0] * b[1] - b[0] * a[1], a[1] * b[1]);
|
|
36
|
+
export const mul = (a, b) => q(a[0] * b[0], a[1] * b[1]);
|
|
37
|
+
export const div = (a, b) => q(a[0] * b[1], a[1] * b[0]);
|
|
38
|
+
export const pow = (a, n) => q(a[0] ** BigInt(n), a[1] ** BigInt(n));
|
|
39
|
+
export const equal = (a, b) => a[0] === b[0] && a[1] === b[1];
|
|
40
|
+
export const pack = (a) => ({ numerator: String(a[0]), denominator: String(a[1]) });
|
|
41
|
+
export function probability(input) { const a = rational(input); if (a[0] < 0n || a[0] > a[1])
|
|
42
|
+
refuse('probability outside 0..1'); return a; }
|
|
43
|
+
export function roundHalfEven(input, digits) {
|
|
44
|
+
if (!Number.isSafeInteger(digits) || digits < 0)
|
|
45
|
+
refuse('invalid decimal digits');
|
|
46
|
+
const [a, b] = rational(input), scale = 10n ** BigInt(digits), absolute = a < 0n ? -a : a;
|
|
47
|
+
let integer = absolute * scale / b;
|
|
48
|
+
const remainder = absolute * scale % b;
|
|
49
|
+
if (2n * remainder > b || (2n * remainder === b && integer % 2n === 1n))
|
|
50
|
+
integer++;
|
|
51
|
+
const text = String(integer).padStart(digits + 1, '0'), prefix = a < 0n && integer !== 0n ? '-' : '';
|
|
52
|
+
return prefix + (digits ? text.slice(0, -digits) + '.' + text.slice(-digits) : text);
|
|
53
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Covariance, Scalar, Unmeasured } from './error-events.ts';
|
|
2
|
+
export type NumericalPolicy = Readonly<{
|
|
3
|
+
absolute: number;
|
|
4
|
+
relative: number;
|
|
5
|
+
maxRotations: number;
|
|
6
|
+
}>;
|
|
7
|
+
export type Spectrum = Readonly<{
|
|
8
|
+
status: 'measured';
|
|
9
|
+
origins: readonly string[];
|
|
10
|
+
values: readonly number[];
|
|
11
|
+
vectors: readonly (readonly number[])[];
|
|
12
|
+
tolerance: number;
|
|
13
|
+
residual: number;
|
|
14
|
+
}>;
|
|
15
|
+
export declare function spectrum(reading: Covariance | Unmeasured, policy: NumericalPolicy): Spectrum | Unmeasured;
|
|
16
|
+
export declare function commonMass(reading: Spectrum | Unmeasured): Scalar;
|
|
17
|
+
export declare function loadings(reading: Spectrum | Unmeasured): Readonly<{
|
|
18
|
+
status: 'measured';
|
|
19
|
+
origins: readonly string[];
|
|
20
|
+
values: readonly number[];
|
|
21
|
+
}> | Unmeasured;
|
|
22
|
+
export declare function commonMassOf(reading: Spectrum | Unmeasured, origins: readonly string[], tau: number): Scalar;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const refuse = (cause) => { throw new Error('REFUSE·measure ' + cause); };
|
|
2
|
+
export function spectrum(reading, policy) {
|
|
3
|
+
if (reading.status === 'unmeasured')
|
|
4
|
+
return reading;
|
|
5
|
+
if (!Number.isFinite(policy.absolute) || policy.absolute <= 0 || !Number.isFinite(policy.relative) || policy.relative < 0 || !Number.isSafeInteger(policy.maxRotations) || policy.maxRotations < 1)
|
|
6
|
+
refuse('invalid numerical policy');
|
|
7
|
+
const n = reading.origins.length, original = reading.matrix;
|
|
8
|
+
if (!n || original.length !== n || original.some(row => row.length !== n || row.some(x => !Number.isFinite(x))))
|
|
9
|
+
refuse('invalid covariance matrix');
|
|
10
|
+
const scale = Math.max(...original.flat().map(Math.abs)), tolerance = policy.absolute + policy.relative * scale;
|
|
11
|
+
for (let i = 0; i < n; i++)
|
|
12
|
+
for (let j = 0; j < n; j++)
|
|
13
|
+
if (original[i][j] !== original[j][i])
|
|
14
|
+
refuse('nonsymmetric covariance');
|
|
15
|
+
const a = original.map(row => [...row]), v = Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => i === j ? 1 : 0));
|
|
16
|
+
for (let step = 0; step < policy.maxRotations; step++) {
|
|
17
|
+
let p = 0, q = 0, largest = 0;
|
|
18
|
+
for (let i = 0; i < n; i++)
|
|
19
|
+
for (let j = i + 1; j < n; j++)
|
|
20
|
+
if (Math.abs(a[i][j]) > largest) {
|
|
21
|
+
largest = Math.abs(a[i][j]);
|
|
22
|
+
p = i;
|
|
23
|
+
q = j;
|
|
24
|
+
}
|
|
25
|
+
if (largest <= tolerance)
|
|
26
|
+
break;
|
|
27
|
+
const theta = .5 * Math.atan2(2 * a[p][q], a[q][q] - a[p][p]), c = Math.cos(theta), s = Math.sin(theta);
|
|
28
|
+
const pp = a[p][p], qq = a[q][q], pq = a[p][q];
|
|
29
|
+
for (let k = 0; k < n; k++)
|
|
30
|
+
if (k !== p && k !== q) {
|
|
31
|
+
const x = a[k][p], y = a[k][q];
|
|
32
|
+
a[k][p] = a[p][k] = c * x - s * y;
|
|
33
|
+
a[k][q] = a[q][k] = s * x + c * y;
|
|
34
|
+
}
|
|
35
|
+
a[p][p] = c * c * pp - 2 * s * c * pq + s * s * qq;
|
|
36
|
+
a[q][q] = s * s * pp + 2 * s * c * pq + c * c * qq;
|
|
37
|
+
a[p][q] = a[q][p] = 0;
|
|
38
|
+
for (let k = 0; k < n; k++) {
|
|
39
|
+
const x = v[k][p], y = v[k][q];
|
|
40
|
+
v[k][p] = c * x - s * y;
|
|
41
|
+
v[k][q] = s * x + c * y;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const order = Array.from({ length: n }, (_, i) => i).sort((i, j) => a[j][j] - a[i][i] || i - j);
|
|
45
|
+
const raw = order.map(i => a[i][i]);
|
|
46
|
+
if (raw.some(x => x < -tolerance))
|
|
47
|
+
refuse('covariance is not positive semidefinite');
|
|
48
|
+
const values = raw.map(x => Math.max(0, x)), vectors = order.map(i => v.map(row => row[i]));
|
|
49
|
+
const residual = Math.max(...vectors.map((vector, i) => Math.hypot(...original.map((row, j) => row.reduce((sum, x, k) => sum + x * vector[k], 0) - values[i] * vector[j]))));
|
|
50
|
+
if (residual > n * tolerance)
|
|
51
|
+
return { status: 'unmeasured', cause: 'eigensolver did not converge within declared budget' };
|
|
52
|
+
return { status: 'measured', origins: reading.origins, values, vectors, tolerance, residual };
|
|
53
|
+
}
|
|
54
|
+
export function commonMass(reading) {
|
|
55
|
+
if (reading.status === 'unmeasured')
|
|
56
|
+
return reading;
|
|
57
|
+
const total = reading.values.reduce((sum, x) => sum + x, 0);
|
|
58
|
+
return total <= reading.tolerance ? { status: 'unmeasured', cause: 'no resolved variation' } : { status: 'measured', value: reading.values[0] / total };
|
|
59
|
+
}
|
|
60
|
+
export function loadings(reading) {
|
|
61
|
+
if (reading.status === 'unmeasured')
|
|
62
|
+
return reading;
|
|
63
|
+
if (reading.values[0] <= reading.tolerance || (reading.values.length > 1 && reading.values[0] - reading.values[1] <= 2 * reading.tolerance))
|
|
64
|
+
return { status: 'unmeasured', cause: 'top eigenspace is unresolved or repeated' };
|
|
65
|
+
return { status: 'measured', origins: reading.origins, values: reading.vectors[0].map(Math.abs) };
|
|
66
|
+
}
|
|
67
|
+
export function commonMassOf(reading, origins, tau) {
|
|
68
|
+
if (reading.status === 'unmeasured')
|
|
69
|
+
return reading;
|
|
70
|
+
if (!Number.isFinite(tau) || tau <= 0 || tau > 1)
|
|
71
|
+
refuse('invalid spectral threshold');
|
|
72
|
+
const selected = [...new Set(origins)].map(origin => reading.origins.indexOf(origin));
|
|
73
|
+
if (!selected.length || selected.some(i => i < 0))
|
|
74
|
+
return { status: 'unmeasured', cause: 'subset not observed' };
|
|
75
|
+
const energy = reading.values.map((value, k) => value * selected.reduce((sum, i) => sum + reading.vectors[k][i] ** 2, 0));
|
|
76
|
+
const total = energy.reduce((sum, x) => sum + x, 0);
|
|
77
|
+
if (total <= reading.tolerance)
|
|
78
|
+
return { status: 'unmeasured', cause: 'no resolved subset variation' };
|
|
79
|
+
const cutoff = tau * reading.values[0];
|
|
80
|
+
if (reading.values.some(value => Math.abs(value - cutoff) <= 2 * reading.tolerance) && tau !== 1)
|
|
81
|
+
return { status: 'unmeasured', cause: 'spectral threshold unresolved at tolerance' };
|
|
82
|
+
const common = energy.reduce((sum, x, k) => sum + (reading.values[k] >= cutoff - 2 * reading.tolerance ? x : 0), 0);
|
|
83
|
+
return { status: 'measured', value: common / total };
|
|
84
|
+
}
|
package/docs/measures.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Measures beside the states
|
|
2
|
+
|
|
3
|
+
The pure API @lapxo/obligations/measures does not change FREE, REQUIRED, FORBIDDEN or CONFLICT. Observed association never establishes independence.
|
|
4
|
+
|
|
5
|
+
## Descriptive contract
|
|
6
|
+
errorMatrix takes explicit binary event/origin/error rows and minCells >= 2. Identical redelivery is idempotent; conflicting observations refuse; incomplete shared events are unmeasured. covariance is population covariance of the handed rows, divided by their event count. participationRatio describes effective rank; zero variation is unmeasured.
|
|
7
|
+
|
|
8
|
+
spectrum requires absolute, relative and maxRotations. Asymmetric or materially non-PSD matrices refuse. commonMass is the largest observed variance fraction, not a probability of false agreement. loadings require an isolated top eigenvalue; repeated eigenspaces have no unique top loading. commonMassOf requires an explicit cutoff and whole eigenspaces. The unanimity no-sample prints observed commonMass >= 0.5 beside FREE, without claiming strength.
|
|
9
|
+
|
|
10
|
+
descentCount counts distinct proper descendants in a declared restsOn graph. Identical edges add nothing. Missing declarations remain unmeasured; duplicate node declarations and cycles refuse. Declared descent is not observed activity or independence.
|
|
11
|
+
|
|
12
|
+
## Controlled procedures
|
|
13
|
+
unanimityFloor and unanimityThreshold implement the declared T1 special case. With P_k=(1-c)p^k(n-1)^(1-k), F_k=(c+P_k)/(c+P_k+(1-c)(1-p)^k). For nondegenerate parameters, F_(k+1) >= F_k iff p*c >= (1-p-p/(n-1))*P_k. The c=.01,p=.1,n=2 no-sample decreases before k=3; its threshold is 3. dissentExperiment and interestExperiment report conditional counts under explicitly handed generators: xorshift32, nonzero seed and trial count. Their denominators are events and falseEvents, and zero events are unmeasured. Interest is an explicitly handed bias toward one wrong value, not inferred from a missing observation. E3: a school answers truth with probability q, otherwise its own wrong value. These are controlled procedures, never laws or state changes.
|
|
14
|
+
|
|
15
|
+
## Native publication evidence
|
|
16
|
+
observations, spectrum, unanimity and descent each have yes/no cases in samples/measures/<group>.json and installed-instrument captures in vectors/measures/<group>.cli.json. M/3 has samples/measures/m3.json and vectors/measures/m3.cli.json. Each vector ran on two independent places, repeated the positive reading byte-for-byte and refused its negative by name. State-preservation tests compare all four actual algebraic states before and after measurements.
|
|
17
|
+
|
|
18
|
+
## Model boundary
|
|
19
|
+
M/3 below is the only reference model. The older descriptive D/commonMass and independence claims are superseded. modelRequired returns unmeasured for an absent model; no measurement silently supplies a causal model. Factor attribution, dissent and probe results are conditional on M/3's handed parameters, not empirical independence certificates.
|
|
20
|
+
|
|
21
|
+
# obligations 0.4.0 — model M/3 (authoritative contract)
|
|
22
|
+
|
|
23
|
+
M/3 is the reference conditional model shipped beside the descriptive measures. Every M/3
|
|
24
|
+
result carries `model=M/3`, its handed parameters and its conditions. The descriptive
|
|
25
|
+
measures are independent of M/3. Nothing changes a state. This document supersedes all
|
|
26
|
+
earlier M/1, M/2 and amendment texts.
|
|
27
|
+
|
|
28
|
+
## 1. Definition
|
|
29
|
+
Witnesses W (unique identifiers); cells with truth t and integer cardinality n ≥ 2;
|
|
30
|
+
factors F, each with unique identifier, sharing set a_f ⊆ W, firing probability c_f and a
|
|
31
|
+
unique declared index (total order); private error probability p_w for every witness
|
|
32
|
+
involved. Per cell, independently:
|
|
33
|
+
1. each factor fires independently with probability c_f;
|
|
34
|
+
2. a witness is governed by the fired factor containing it with the lowest index, if
|
|
35
|
+
any; otherwise its private error fires with probability p_w;
|
|
36
|
+
3. labels: each fired governing factor is a factor label; each privately erring witness
|
|
37
|
+
is a private label (namespaces are distinct: a factor label and a private label can
|
|
38
|
+
never merge even with identical identifier strings); every label draws one wrong
|
|
39
|
+
value uniformly from the n−1 wrong values; draws of distinct labels are mutually
|
|
40
|
+
independent and independent of all firing and private indicators; everyone else says t.
|
|
41
|
+
Singleton factors (|a_f| = 1) are retained in declared order; the generator is never
|
|
42
|
+
normalized.
|
|
43
|
+
|
|
44
|
+
## 2. Validation (refuse by name)
|
|
45
|
+
S ⊆ W and S nonempty; every a_f ⊆ W; unique witness and factor identifiers; unique factor
|
|
46
|
+
indices; c_f, p_w ∈ [0,1]; n integer ≥ 2; an explicitly handed p_w for every witness in
|
|
47
|
+
S and in every sharing set touching S; a sharing set with duplicate members is refused.
|
|
48
|
+
|
|
49
|
+
## 3. Exact evaluator
|
|
50
|
+
Enumerate fired subsets of the factors touching S (2^|touching|) and private patterns of
|
|
51
|
+
ungoverned members of S (2^|free|). In each configuration, erring witnesses are grouped by
|
|
52
|
+
label; L = number of labels; weights = witnesses per label. Collisions of wrong values
|
|
53
|
+
follow set partitions π of the labels with
|
|
54
|
+
P(π) = (n−1)^{↓|π|} / (n−1)^L (falling factorial), and P(π) = 0 when |π| > n−1.
|
|
55
|
+
Each partition yields block totals; unanimity ⇔ no correct witness and one block;
|
|
56
|
+
majority = strictly more than |S|/2 witnesses on one value; ties and pluralities ≤ half
|
|
57
|
+
are "no majority".
|
|
58
|
+
Exactness: all c_f, p_w are handed as rationals (or decimal strings converted exactly);
|
|
59
|
+
accumulation is in rational arithmetic; displayed decimals are rounded half-even to a
|
|
60
|
+
declared number of digits. Budget: before any work, compute
|
|
61
|
+
work = Σ_configurations Bell(L) ≤ `evaluator/budget` (declared); if exceeded, return
|
|
62
|
+
`unmeasured` with cause `evaluator/budget` and no partial accumulation.
|
|
63
|
+
Outputs per (S, x): P_true, P_false (false unanimity), P_fired (false unanimity with some
|
|
64
|
+
touching factor fired), P_dissent = 1 − P_true − P_false (identity, asserted),
|
|
65
|
+
maj_true∧dissent, maj_false∧dissent, maj_none∧dissent (exclusive, sum = P_dissent).
|
|
66
|
+
Closed form admitted only for P_true = Π_{f touches S}(1−c_f) · Π_{w∈S}(1−p_w).
|
|
67
|
+
|
|
68
|
+
## 4. Quantities and denominators
|
|
69
|
+
```
|
|
70
|
+
Φ = P_false / (P_true + P_false) false-unanimity share
|
|
71
|
+
D = P_fired / (P_true + P_false) factor-attribution share
|
|
72
|
+
reliability = 1 − Φ, labelled "P(correct | unanimous) under M/3 with handed parameters"
|
|
73
|
+
P(false maj | dissent) = maj_false∧dissent / P_dissent
|
|
74
|
+
P(false maj | any maj ∧ dissent) = maj_false∧dissent / (maj_true∧dissent + maj_false∧dissent)
|
|
75
|
+
```
|
|
76
|
+
A ratio with zero denominator is `unmeasured` with cause; a zero numerator over a positive
|
|
77
|
+
denominator is a measured 0. Φ − D is private coincidence; 1 − D is never reliability.
|
|
78
|
+
|
|
79
|
+
## 5. Dissent
|
|
80
|
+
Theorem: if a factor covering S fires and no fired factor of lower index touches S
|
|
81
|
+
partially, S is unanimous; disagreement inside S certifies this configuration did not
|
|
82
|
+
occur — nothing more. False majorities under dissent remain possible through partial
|
|
83
|
+
factors and are reported through the two conditionals above. T1 and T5 stay controlled
|
|
84
|
+
experiments with declared PRNG, seed, trials and denominators (T5 uses the second
|
|
85
|
+
conditional).
|
|
86
|
+
|
|
87
|
+
## 6. Probe update
|
|
88
|
+
For a witness u private-only and independent of every factor touching S (or, with its
|
|
89
|
+
total marginal error probability, labelled so):
|
|
90
|
+
```
|
|
91
|
+
a = Φ · p_u/(n−1); b = (1−Φ)·(1−p_u); Φ′ = a/(a+b); unmeasured iff a+b = 0
|
|
92
|
+
```
|
|
93
|
+
Strict improvement Φ′ < Φ holds for 0 < Φ < 1 iff p_u < (n−1)/n; boundary cases are
|
|
94
|
+
valid (Φ=0, p_u=0.2 → 0; Φ=1, p_u=0.2 → 1; p_u=1 → 1).
|
|
95
|
+
|
|
96
|
+
## 7. Identification and fitting
|
|
97
|
+
Let, for each witness w,
|
|
98
|
+
```
|
|
99
|
+
r_w = (1−p_w) · Π_{singleton f ∋ w} (1−c_f) unresolved singleton/private survival
|
|
100
|
+
s_w = r_w · Π_{shared f ∋ w} (1−c_f) total correctness probability
|
|
101
|
+
s_uv = P(e_u = 0 ∧ e_v = 0)
|
|
102
|
+
```
|
|
103
|
+
Population identification (declared sharing sets, s_u > 0 for every involved witness):
|
|
104
|
+
log(s_uv/(s_u·s_v)) = Σ_{shared f ∋ u,v} −log(1−c_f) is linear in −log(1−c_f); if the
|
|
105
|
+
pair × shared-factor system has full column rank, every shared c_f is identified, and then
|
|
106
|
+
r_w from s_w; r_w's decomposition into p_w and singleton c_f is unresolved by error data.
|
|
107
|
+
Structure is never discovered by a measure. Finite-data fitting is a separate declared
|
|
108
|
+
procedure: constrained least squares on the log system, declared budget, residual
|
|
109
|
+
diagnostics against a declared tolerance, bootstrap uncertainty with declared B/seed/PRNG,
|
|
110
|
+
pooling only under declared parameter compatibility; no pseudocounts, no clamping, no
|
|
111
|
+
promotion of fitted structure; zero joint-correct counts or incompatible moments →
|
|
112
|
+
`model/M misfit`, no c_f reported. Φ and D are reported only with handed parameters and
|
|
113
|
+
labelled `handed`, never `fitted`.
|
|
114
|
+
|
|
115
|
+
## 8. Time, stake, commonMass
|
|
116
|
+
Freshness and interest enter only as hypothetical factors with declared firing
|
|
117
|
+
probabilities; otherwise annotations and `unmeasured`. Descriptive commonMass is read as
|
|
118
|
+
excess over 1/|S| only as deviation from the equal-variance independent reference; it
|
|
119
|
+
never identifies dependence.
|
|
120
|
+
|
|
121
|
+
## 9. Captured vectors (exact; rational reference; decimals rounded half-even, 8 digits)
|
|
122
|
+
- two witnesses, covering c=1/20, p=1/5, n=64: P_true 0.608, P_false 0.05060317,
|
|
123
|
+
P_fired 0.05, P_dissent 0.34139683, Φ 0.07683409, D 0.07591825.
|
|
124
|
+
- impossible conditioning (no factors, p_A=0, p_B=1): P_true = P_false = 0, P_dissent 1,
|
|
125
|
+
Φ, D unmeasured (cause: no unanimity mass).
|
|
126
|
+
- three witnesses, covering {A,B,C} c=1/5 idx 0, partial {A,B} c=3/10 idx 1, p=0:
|
|
127
|
+
P_true 0.56, P_false 0.2, P_dissent 0.24, maj_false∧dissent 0.24, Φ = D = 0.26315789,
|
|
128
|
+
P(false maj | dissent) = 1, P(false maj | any maj ∧ dissent) = 1.
|
|
129
|
+
- earlier singleton {A} c=3/10 idx 0, covering {A,B} c=1/5 idx 1, p=1/5: Φ 0.28387293,
|
|
130
|
+
D 0.28316249, P_dissent 0.49953016; merged-singleton no-sample Φ 0.35944805.
|
|
131
|
+
- four witnesses, factors {0,1} and {2,3} each c=1/2, p=0: P_dissent 47/63 = 0.74603175,
|
|
132
|
+
maj_none∧dissent 47/63, P(false maj | dissent) = 0 (measured), P(false maj | any maj ∧
|
|
133
|
+
dissent) unmeasured (no majority mass), Φ = D = 1/64.
|
|
134
|
+
- probe (Φ 0.07683409, n=64): p_u=0.2 → 0.00033; 0.98 → 0.06080; 0.99 → 0.11566; 1 → 1;
|
|
135
|
+
Φ=0,p_u=0.2 → 0; Φ=1,p_u=0.2 → 1.
|
|
136
|
+
- identification: c=1/5, p_A=1/2, p_B=3/8 → c recovered exactly 1/5; (c=1/5,p_A=1,
|
|
137
|
+
p_B=3/8) vs (c=2/5,p_A=1,p_B=1/6) have identical moments → s_A = 0 → unidentified.
|
|
138
|
+
- identity 1 − P_true − P_false = P_dissent holds in every case.
|
|
139
|
+
|
|
140
|
+
## 10. Open, by name
|
|
141
|
+
Partial value sharing (a factor firing without forcing one value) — a future model;
|
|
142
|
+
probe usefulness beyond the private-only case; discovery of sharing structure (never by a
|
|
143
|
+
measure); adequacy policies (min cells, interval widths, budgets) as declared lines.
|
|
144
|
+
|
|
145
|
+
## 11. Acceptance
|
|
146
|
+
TypeScript implementation reproduces every captured vector exactly in rational
|
|
147
|
+
arithmetic; validation refuses by name; budget is computed before work; every result
|
|
148
|
+
carries model, handed parameters and conditions; states identical before and after;
|
|
149
|
+
the descriptive 0.4.0 measures and all algebra hashes unchanged.
|
package/package.json
CHANGED
|
@@ -1,93 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@lapxo/obligations",
|
|
3
|
-
"version": "0.3.4",
|
|
4
|
-
"description": "The algebra of a cell: two poles, origins with phase, eight acts.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"author": "Lapxo",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/Lapxo/obligations.git"
|
|
11
|
-
},
|
|
12
|
-
"keywords": [
|
|
13
|
-
"obligations",
|
|
14
|
-
"lattice",
|
|
15
|
-
"provenance"
|
|
16
|
-
],
|
|
17
|
-
"sideEffects": false,
|
|
18
|
-
"engines": {
|
|
19
|
-
"node": ">=22.12"
|
|
20
|
-
},
|
|
21
|
-
"exports": {
|
|
22
|
-
".": {
|
|
23
|
-
"types": "./dist/lattice/index.d.ts",
|
|
24
|
-
"default": "./dist/lattice/index.js"
|
|
25
|
-
},
|
|
26
|
-
"./debit": {
|
|
27
|
-
"types": "./dist/debit/debit.d.ts",
|
|
28
|
-
"default": "./dist/debit/debit.js"
|
|
29
|
-
},
|
|
30
|
-
"./encounter": {
|
|
31
|
-
"types": "./dist/field/encounter.d.ts",
|
|
32
|
-
"default": "./dist/field/encounter.js"
|
|
33
|
-
},
|
|
34
|
-
"./field": {
|
|
35
|
-
"types": "./dist/field/field.d.ts",
|
|
36
|
-
"default": "./dist/field/field.js"
|
|
37
|
-
},
|
|
38
|
-
"./forms": {
|
|
39
|
-
"types": "./dist/lattice/forms.d.ts",
|
|
40
|
-
"default": "./dist/lattice/forms.js"
|
|
41
|
-
},
|
|
42
|
-
"./lattice": {
|
|
43
|
-
"types": "./dist/lattice/lattice.d.ts",
|
|
44
|
-
"default": "./dist/lattice/lattice.js"
|
|
45
|
-
},
|
|
46
|
-
"./packed": {
|
|
47
|
-
"types": "./dist/debit/packed.d.ts",
|
|
48
|
-
"default": "./dist/debit/packed.js"
|
|
49
|
-
},
|
|
50
|
-
"./present": {
|
|
51
|
-
"types": "./dist/field/present.d.ts",
|
|
52
|
-
"default": "./dist/field/present.js"
|
|
53
|
-
},
|
|
54
|
-
"./price": {
|
|
55
|
-
"types": "./dist/lattice/price/index.d.ts",
|
|
56
|
-
"default": "./dist/lattice/price/index.js"
|
|
57
|
-
},
|
|
58
|
-
"./replay": {
|
|
59
|
-
"types": "./dist/replay.d.ts",
|
|
60
|
-
"default": "./dist/replay.js"
|
|
61
|
-
},
|
|
62
|
-
"./shuffle": {
|
|
63
|
-
"types": "./dist/debit/shuffle.d.ts",
|
|
64
|
-
"default": "./dist/debit/shuffle.js"
|
|
65
|
-
},
|
|
66
|
-
"./signatures": {
|
|
67
|
-
"types": "./dist/field/signatures.d.ts",
|
|
68
|
-
"default": "./dist/field/signatures.js"
|
|
69
|
-
},
|
|
70
|
-
"./views/field": {
|
|
71
|
-
"types": "./dist/views/field.d.ts",
|
|
72
|
-
"default": "./dist/views/field.js"
|
|
73
|
-
},
|
|
74
|
-
"./views/product": {
|
|
75
|
-
"types": "./dist/views/product.d.ts",
|
|
76
|
-
"default": "./dist/views/product.js"
|
|
77
|
-
},
|
|
78
|
-
"./package.json": "./package.json"
|
|
79
|
-
},
|
|
80
|
-
"files": [
|
|
81
|
-
"dist",
|
|
82
|
-
"README.md",
|
|
83
|
-
"LICENSE",
|
|
84
|
-
"TARGET.bound"
|
|
85
|
-
],
|
|
86
|
-
"scripts": {
|
|
87
|
-
"build": "tsc --build"
|
|
88
|
-
},
|
|
89
|
-
"devDependencies": {
|
|
90
|
-
"@types/node": "^22",
|
|
91
|
-
"typescript": "^5.9.3"
|
|
92
|
-
}
|
|
93
|
-
}
|
|
1
|
+
{"name":"@lapxo/obligations","version":"0.4.0","description":"The algebra of a cell: two poles, origins with phase, eight acts.","type":"module","license":"MIT","author":"Lapxo","repository":{"type":"git","url":"git+https://github.com/Lapxo/obligations.git"},"keywords":["obligations","lattice","provenance"],"sideEffects":false,"engines":{"node":">=22.12"},"exports":{".":{"types":"./dist/lattice/index.d.ts","default":"./dist/lattice/index.js"},"./debit":{"types":"./dist/debit/debit.d.ts","default":"./dist/debit/debit.js"},"./encounter":{"types":"./dist/field/encounter.d.ts","default":"./dist/field/encounter.js"},"./field":{"types":"./dist/field/field.d.ts","default":"./dist/field/field.js"},"./forms":{"types":"./dist/lattice/forms.d.ts","default":"./dist/lattice/forms.js"},"./lattice":{"types":"./dist/lattice/lattice.d.ts","default":"./dist/lattice/lattice.js"},"./measures":{"types":"./dist/measures/index.d.ts","default":"./dist/measures/index.js"},"./packed":{"types":"./dist/debit/packed.d.ts","default":"./dist/debit/packed.js"},"./present":{"types":"./dist/field/present.d.ts","default":"./dist/field/present.js"},"./price":{"types":"./dist/lattice/price/index.d.ts","default":"./dist/lattice/price/index.js"},"./replay":{"types":"./dist/replay.d.ts","default":"./dist/replay.js"},"./shuffle":{"types":"./dist/debit/shuffle.d.ts","default":"./dist/debit/shuffle.js"},"./signatures":{"types":"./dist/field/signatures.d.ts","default":"./dist/field/signatures.js"},"./views/field":{"types":"./dist/views/field.d.ts","default":"./dist/views/field.js"},"./views/product":{"types":"./dist/views/product.d.ts","default":"./dist/views/product.js"},"./package.json":"./package.json"},"files":["dist","README.md","LICENSE","TARGET.bound","receipts.bound","docs/measures.md","samples/measures","vectors/measures","samples/yes/algebra-is-closed.json","samples/yes/field-uses-price-and-debit.json","samples/yes/three-theories-one-algebra.json","src/lattice/index.ts","src/field/motion.ts","samples/yes/installed-artifact.json","samples/no/installed-artifact.json","vectors/measures/installed-artifact.cli.json"],"scripts":{"build":"tsc --build","test":"node --import ./test/setup.ts --test --test-concurrency=2 test/*.test.ts test/measures/*.test.ts"},"devDependencies":{"@types/node":"^22","typescript":"^5.9.3"}}
|