@lapxo/obligations 0.2.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/LICENSE +21 -0
- package/README.md +169 -0
- package/dist/debit/debit.d.ts +3 -0
- package/dist/debit/debit.js +19 -0
- package/dist/debit/graph.d.ts +10 -0
- package/dist/debit/graph.js +57 -0
- package/dist/debit/ideal.d.ts +20 -0
- package/dist/debit/ideal.js +80 -0
- package/dist/debit/masks.d.ts +16 -0
- package/dist/debit/masks.js +95 -0
- package/dist/debit/packed.d.ts +30 -0
- package/dist/debit/packed.js +114 -0
- package/dist/debit/provenance.d.ts +3 -0
- package/dist/debit/provenance.js +8 -0
- package/dist/debit/register.d.ts +7 -0
- package/dist/debit/register.js +17 -0
- package/dist/debit/shuffle.d.ts +3 -0
- package/dist/debit/shuffle.js +30 -0
- package/dist/debit/standing.d.ts +3 -0
- package/dist/debit/standing.js +12 -0
- package/dist/debit/unit-span.d.ts +8 -0
- package/dist/debit/unit-span.js +63 -0
- package/dist/debit/unit.d.ts +22 -0
- package/dist/debit/unit.js +110 -0
- package/dist/debit/vector-move.d.ts +12 -0
- package/dist/debit/vector-move.js +48 -0
- package/dist/debit/vector.d.ts +26 -0
- package/dist/debit/vector.js +68 -0
- package/dist/field/encounter.d.ts +9 -0
- package/dist/field/encounter.js +36 -0
- package/dist/field/field.d.ts +39 -0
- package/dist/field/field.js +79 -0
- package/dist/field/frontier.d.ts +20 -0
- package/dist/field/frontier.js +16 -0
- package/dist/field/motion.d.ts +14 -0
- package/dist/field/motion.js +38 -0
- package/dist/field/present.d.ts +8 -0
- package/dist/field/present.js +18 -0
- package/dist/field/signatures.d.ts +6 -0
- package/dist/field/signatures.js +19 -0
- package/dist/field/yield.d.ts +15 -0
- package/dist/field/yield.js +16 -0
- package/dist/lattice/axioms.d.ts +14 -0
- package/dist/lattice/axioms.js +140 -0
- package/dist/lattice/declaration.d.ts +9 -0
- package/dist/lattice/declaration.js +12 -0
- package/dist/lattice/errors.d.ts +6 -0
- package/dist/lattice/errors.js +11 -0
- package/dist/lattice/forms.d.ts +38 -0
- package/dist/lattice/forms.js +198 -0
- package/dist/lattice/index.d.ts +45 -0
- package/dist/lattice/index.js +29 -0
- package/dist/lattice/lattice.d.ts +18 -0
- package/dist/lattice/lattice.js +14 -0
- package/dist/lattice/obligatory.d.ts +27 -0
- package/dist/lattice/obligatory.js +33 -0
- package/dist/lattice/order.d.ts +6 -0
- package/dist/lattice/order.js +150 -0
- package/dist/lattice/price/attainable.d.ts +22 -0
- package/dist/lattice/price/attainable.js +37 -0
- package/dist/lattice/price/blocks.d.ts +2 -0
- package/dist/lattice/price/blocks.js +26 -0
- package/dist/lattice/price/index.d.ts +7 -0
- package/dist/lattice/price/index.js +5 -0
- package/dist/lattice/price/premium.d.ts +18 -0
- package/dist/lattice/price/premium.js +80 -0
- package/dist/lattice/price/quote.d.ts +30 -0
- package/dist/lattice/price/quote.js +53 -0
- package/dist/lattice/scale-lattice.d.ts +5 -0
- package/dist/lattice/scale-lattice.js +35 -0
- package/dist/lattice/types.d.ts +40 -0
- package/dist/lattice/types.js +1 -0
- package/dist/lattice/vacuity.d.ts +22 -0
- package/dist/lattice/vacuity.js +55 -0
- package/dist/replay.d.ts +2 -0
- package/dist/replay.js +4 -0
- package/dist/views/chain.d.ts +5 -0
- package/dist/views/chain.js +5 -0
- package/dist/views/complement.d.ts +2 -0
- package/dist/views/complement.js +2 -0
- package/dist/views/dual.d.ts +1 -0
- package/dist/views/dual.js +1 -0
- package/dist/views/field/physics.d.ts +13 -0
- package/dist/views/field/physics.js +64 -0
- package/dist/views/field/policy.d.ts +20 -0
- package/dist/views/field/policy.js +68 -0
- package/dist/views/field/self.d.ts +8 -0
- package/dist/views/field/self.js +14 -0
- package/dist/views/field/wave.d.ts +16 -0
- package/dist/views/field/wave.js +34 -0
- package/dist/views/field.d.ts +12 -0
- package/dist/views/field.js +9 -0
- package/dist/views/galois.d.ts +2 -0
- package/dist/views/galois.js +2 -0
- package/dist/views/ideal.d.ts +10 -0
- package/dist/views/ideal.js +10 -0
- package/dist/views/product/design.d.ts +13 -0
- package/dist/views/product/design.js +66 -0
- package/dist/views/product/mould.d.ts +14 -0
- package/dist/views/product/mould.js +55 -0
- package/dist/views/product/polygon.d.ts +10 -0
- package/dist/views/product/polygon.js +65 -0
- package/dist/views/product/reach.d.ts +14 -0
- package/dist/views/product/reach.js +106 -0
- package/dist/views/product/resolution.d.ts +8 -0
- package/dist/views/product/resolution.js +34 -0
- package/dist/views/product.d.ts +12 -0
- package/dist/views/product.js +10 -0
- package/dist/views/quotient.d.ts +2 -0
- package/dist/views/quotient.js +2 -0
- package/dist/views/spectrum.d.ts +4 -0
- package/dist/views/spectrum.js +4 -0
- package/dist/views/valuation.d.ts +9 -0
- package/dist/views/valuation.js +9 -0
- package/package.json +91 -0
- package/receipts.bound +491 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function eq(L, a, b) {
|
|
2
|
+
return L.leq(a, b) && L.leq(b, a);
|
|
3
|
+
}
|
|
4
|
+
export function relate(L, a, b) {
|
|
5
|
+
const ab = L.leq(a, b);
|
|
6
|
+
const ba = L.leq(b, a);
|
|
7
|
+
if (ab && ba)
|
|
8
|
+
return 'equal';
|
|
9
|
+
if (ab)
|
|
10
|
+
return 'narrower';
|
|
11
|
+
if (ba)
|
|
12
|
+
return 'wider';
|
|
13
|
+
return 'incomparable';
|
|
14
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Lattice } from './lattice.ts';
|
|
2
|
+
export interface Claim<T> {
|
|
3
|
+
readonly origin: string;
|
|
4
|
+
readonly span: T;
|
|
5
|
+
readonly id?: string;
|
|
6
|
+
readonly at?: number;
|
|
7
|
+
readonly takes?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface Obligatory<T> {
|
|
10
|
+
readonly at: readonly string[];
|
|
11
|
+
readonly epoch: number;
|
|
12
|
+
readonly seen: readonly Claim<T>[];
|
|
13
|
+
readonly restsOn: readonly string[];
|
|
14
|
+
readonly ceiling?: T;
|
|
15
|
+
readonly witnesses?: readonly string[];
|
|
16
|
+
}
|
|
17
|
+
export declare function cell<T>(at: string, epoch?: number, seen?: readonly Claim<T>[], restsOn?: readonly string[]): Obligatory<T>;
|
|
18
|
+
export declare function meet<T>(lattice: Lattice<T>, one: Obligatory<T>, bounds?: ReadonlyMap<string, T>): T;
|
|
19
|
+
export declare function encounter<T>(lattice: Lattice<T>, one: Obligatory<T>, bounds?: ReadonlyMap<string, T>): {
|
|
20
|
+
readonly origins: number;
|
|
21
|
+
readonly held: T;
|
|
22
|
+
};
|
|
23
|
+
export declare function observe<T>(one: Obligatory<T>, claim: Claim<T>): Obligatory<T>;
|
|
24
|
+
export declare function sign<T>(lattice: Lattice<T>, bounds: ReadonlyMap<string, T>, name: string, span: T): ReadonlyMap<string, T>;
|
|
25
|
+
export declare function sign<T>(lattice: Lattice<T>, world: readonly Obligatory<T>[], name: string, span: T): readonly Obligatory<T>[];
|
|
26
|
+
export declare function join<T>(lattice: Lattice<T>, one: Obligatory<T>, span: T, witness: string): Obligatory<T>;
|
|
27
|
+
export declare function refine<T>(one: Obligatory<T>, steps: number): Obligatory<T>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { coordinate } from "../field/field.js";
|
|
2
|
+
export function cell(at, epoch = 0, seen = [], restsOn = []) {
|
|
3
|
+
return { at: coordinate(at), epoch, seen, restsOn };
|
|
4
|
+
}
|
|
5
|
+
const standing = (one) => {
|
|
6
|
+
const taken = new Set(one.seen.flatMap((claim) => (claim.takes === undefined ? [] : [claim.takes])));
|
|
7
|
+
return one.seen.filter((claim) => claim.takes === undefined && (claim.id === undefined || !taken.has(claim.id)));
|
|
8
|
+
};
|
|
9
|
+
export function meet(lattice, one, bounds = new Map()) {
|
|
10
|
+
const rested = one.restsOn.flatMap((name) => (bounds.has(name) ? [bounds.get(name)] : []));
|
|
11
|
+
const own = one.ceiling === undefined ? [] : [one.ceiling];
|
|
12
|
+
return [...standing(one).map((claim) => claim.span), ...rested, ...own].reduce((held, span) => lattice.meet(held, span), lattice.top);
|
|
13
|
+
}
|
|
14
|
+
export function encounter(lattice, one, bounds) {
|
|
15
|
+
return { origins: new Set(standing(one).map((claim) => claim.origin)).size, held: meet(lattice, one, bounds) };
|
|
16
|
+
}
|
|
17
|
+
export function observe(one, claim) {
|
|
18
|
+
return { ...one, epoch: Math.max(one.epoch, claim.at ?? one.epoch), seen: [...one.seen, claim] };
|
|
19
|
+
}
|
|
20
|
+
export function sign(lattice, held, name, span) {
|
|
21
|
+
if (!(held instanceof Map)) {
|
|
22
|
+
return held.map((one) => (one.restsOn.includes(name) ? { ...one, ceiling: lattice.meet(one.ceiling ?? lattice.top, span) } : one));
|
|
23
|
+
}
|
|
24
|
+
return new Map([...held, [name, lattice.meet(held.get(name) ?? lattice.top, span)]]);
|
|
25
|
+
}
|
|
26
|
+
export function join(lattice, one, span, witness) {
|
|
27
|
+
if (witness === '')
|
|
28
|
+
throw new Error('REFUSE·join a widening lands only with a witness or the signatures of whoever rests on the old bound');
|
|
29
|
+
return { ...one, ceiling: lattice.join(one.ceiling ?? lattice.top, span), witnesses: [...(one.witnesses ?? []), witness] };
|
|
30
|
+
}
|
|
31
|
+
export function refine(one, steps) {
|
|
32
|
+
return { ...one, at: steps >= one.at.length ? one.at : one.at.slice(0, Math.max(1, steps)) };
|
|
33
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Scale, Level } from './types.ts';
|
|
2
|
+
export declare function chain(levels: readonly string[]): Scale;
|
|
3
|
+
export declare function height(c: Scale, level: Level): number;
|
|
4
|
+
export declare function isDistributive(c: Scale): boolean;
|
|
5
|
+
export declare function order(levels: readonly string[], leq: readonly boolean[][]): Scale;
|
|
6
|
+
export declare const BOOLEAN: () => Scale;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { UnitError } from "./errors.js";
|
|
2
|
+
function build(levels, join, meet) {
|
|
3
|
+
const n = levels.length;
|
|
4
|
+
for (let i = 0; i < n; i++) {
|
|
5
|
+
if (levels.indexOf(levels[i]) !== i) {
|
|
6
|
+
throw new UnitError('DUPLICATE_LEVEL', `the level \`${levels[i]}\` is declared twice`, {
|
|
7
|
+
level: levels[i],
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const index = new Map(levels.map((l, i) => [l, i]));
|
|
12
|
+
const leq = (a, b) => join[a][b] === b;
|
|
13
|
+
const total = levels.every((_, i) => levels.every((__, j) => join[i][j] === i || join[i][j] === j));
|
|
14
|
+
let simple = true;
|
|
15
|
+
for (let x = 0; x < n && simple; x++) {
|
|
16
|
+
for (let y = 0; y < n && simple; y++) {
|
|
17
|
+
for (let z = 0; z < n; z++) {
|
|
18
|
+
if (meet[x][join[y][z]] !== join[meet[x][y]][meet[x][z]]) {
|
|
19
|
+
simple = false;
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const all = [...levels.keys()];
|
|
26
|
+
const bottomIx = all.find((i) => all.every((j) => leq(i, j))) ?? 0;
|
|
27
|
+
const topIx = all.find((i) => all.every((j) => leq(j, i))) ?? n - 1;
|
|
28
|
+
const joinIrr = all.filter((j) => j !== bottomIx &&
|
|
29
|
+
all.filter((x) => x !== j && leq(x, j)).reduce((acc, x) => join[acc][x], bottomIx) !== j);
|
|
30
|
+
const meetIrr = all.filter((m) => m !== topIx &&
|
|
31
|
+
all.filter((x) => x !== m && leq(m, x)).reduce((acc, x) => meet[acc][x], topIx) !== m);
|
|
32
|
+
const seen = new Set();
|
|
33
|
+
const allDebits = [];
|
|
34
|
+
for (const x of [...joinIrr, ...meetIrr]) {
|
|
35
|
+
if (!seen.has(x)) {
|
|
36
|
+
seen.add(x);
|
|
37
|
+
allDebits.push(x);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
levels,
|
|
42
|
+
isLadder: total,
|
|
43
|
+
isSimple: simple,
|
|
44
|
+
bottomIx,
|
|
45
|
+
topIx,
|
|
46
|
+
bottom: levels[bottomIx],
|
|
47
|
+
top: levels[topIx],
|
|
48
|
+
leq,
|
|
49
|
+
higher: (a, b) => join[a][b],
|
|
50
|
+
lower: (a, b) => meet[a][b],
|
|
51
|
+
rank(level) {
|
|
52
|
+
const r = index.get(level);
|
|
53
|
+
if (r === undefined) {
|
|
54
|
+
throw new UnitError('UNKNOWN_LEVEL', `no level \`${level}\` in this scale`, {
|
|
55
|
+
level,
|
|
56
|
+
levels,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return r;
|
|
60
|
+
},
|
|
61
|
+
stateOf(floor, ceiling) {
|
|
62
|
+
if (!leq(floor, ceiling))
|
|
63
|
+
return 'CONFLICT';
|
|
64
|
+
if (floor !== bottomIx)
|
|
65
|
+
return 'REQUIRED';
|
|
66
|
+
if (ceiling !== topIx)
|
|
67
|
+
return 'FORBIDDEN';
|
|
68
|
+
return 'FREE';
|
|
69
|
+
},
|
|
70
|
+
joins: () => joinIrr.slice(),
|
|
71
|
+
limits: () => meetIrr.slice(),
|
|
72
|
+
debits: () => allDebits.slice(),
|
|
73
|
+
intervalHeight(lo, hi) {
|
|
74
|
+
if (!leq(lo, hi))
|
|
75
|
+
return null;
|
|
76
|
+
const inside = all.filter((x) => leq(lo, x) && leq(x, hi));
|
|
77
|
+
const covers = (x) => inside.filter((y) => y !== x &&
|
|
78
|
+
leq(x, y) &&
|
|
79
|
+
!inside.some((z) => z !== x && z !== y && leq(x, z) && leq(z, y)));
|
|
80
|
+
const long = new Map([[lo, 0]]);
|
|
81
|
+
const short = new Map([[lo, 0]]);
|
|
82
|
+
const walk = [...inside].sort((a, b) => inside.filter((z) => leq(z, a)).length - inside.filter((z) => leq(z, b)).length);
|
|
83
|
+
for (const x of walk) {
|
|
84
|
+
const lx = long.get(x);
|
|
85
|
+
const sx = short.get(x);
|
|
86
|
+
if (lx === undefined || sx === undefined)
|
|
87
|
+
continue;
|
|
88
|
+
for (const y of covers(x)) {
|
|
89
|
+
long.set(y, Math.max(long.get(y) ?? lx + 1, lx + 1));
|
|
90
|
+
short.set(y, Math.min(short.get(y) ?? sx + 1, sx + 1));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const l = long.get(hi);
|
|
94
|
+
return l !== undefined && l === short.get(hi) ? l : null;
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export function chain(levels) {
|
|
99
|
+
if (!Array.isArray(levels) || levels.length === 0) {
|
|
100
|
+
throw new UnitError('EMPTY_CHAIN', 'a chain needs at least one level');
|
|
101
|
+
}
|
|
102
|
+
const n = levels.length;
|
|
103
|
+
const grid = (f) => [...Array(n)].map((_, i) => [...Array(n)].map((__, j) => f(i, j)));
|
|
104
|
+
return build(levels, grid(Math.max), grid(Math.min));
|
|
105
|
+
}
|
|
106
|
+
export function height(c, level) {
|
|
107
|
+
const r = level;
|
|
108
|
+
const depth = (x) => {
|
|
109
|
+
let d = 0;
|
|
110
|
+
for (let y = 0; y < c.levels.length; y++)
|
|
111
|
+
if (y !== x && c.leq(y, x))
|
|
112
|
+
d++;
|
|
113
|
+
return d;
|
|
114
|
+
};
|
|
115
|
+
let h = 0;
|
|
116
|
+
for (let x = 0; x < c.levels.length; x++)
|
|
117
|
+
if (x !== r && c.leq(x, r))
|
|
118
|
+
h = Math.max(h, depth(x) + 1);
|
|
119
|
+
return h;
|
|
120
|
+
}
|
|
121
|
+
export function isDistributive(c) {
|
|
122
|
+
const n = c.levels.length;
|
|
123
|
+
for (let x = 0; x < n; x++)
|
|
124
|
+
for (let y = 0; y < n; y++)
|
|
125
|
+
for (let z = 0; z < n; z++) {
|
|
126
|
+
const left = c.higher(x, c.lower(y, z));
|
|
127
|
+
const right = c.lower(c.higher(x, y), c.higher(x, z));
|
|
128
|
+
if (left !== right)
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
export function order(levels, leq) {
|
|
134
|
+
if (!Array.isArray(levels) || levels.length === 0) {
|
|
135
|
+
throw new UnitError('EMPTY_CHAIN', 'an order needs at least one level');
|
|
136
|
+
}
|
|
137
|
+
const n = levels.length;
|
|
138
|
+
const bound = (a, b, up) => {
|
|
139
|
+
const bs = [...Array(n).keys()].filter((x) => up ? leq[a][x] && leq[b][x] : leq[x][a] && leq[x][b]);
|
|
140
|
+
const least = bs.filter((x) => bs.every((y) => (up ? leq[x][y] : leq[y][x])));
|
|
141
|
+
if (least.length !== 1) {
|
|
142
|
+
throw new UnitError('MALFORMED', `\`${levels[a]}\` and \`${levels[b]}\` have ${least.length} ` +
|
|
143
|
+
`${up ? 'lowest common' : 'highest common'} bounds, so this is not a usable scale`, { levels: [levels[a], levels[b]] });
|
|
144
|
+
}
|
|
145
|
+
return least[0];
|
|
146
|
+
};
|
|
147
|
+
const grid = (up) => [...Array(n)].map((_, i) => [...Array(n)].map((__, j) => bound(i, j, up)));
|
|
148
|
+
return build(levels, grid(true), grid(false));
|
|
149
|
+
}
|
|
150
|
+
export const BOOLEAN = () => chain(['no', 'yes']);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Scale } from '../types.ts';
|
|
2
|
+
export type Attainability = {
|
|
3
|
+
readonly kind: 'attainable';
|
|
4
|
+
readonly value: string;
|
|
5
|
+
} | {
|
|
6
|
+
readonly kind: 'hole';
|
|
7
|
+
readonly value: string;
|
|
8
|
+
readonly after: string;
|
|
9
|
+
readonly before: string;
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: 'unknown';
|
|
12
|
+
readonly value: string;
|
|
13
|
+
};
|
|
14
|
+
export declare function attainable(c: Scale): {
|
|
15
|
+
readonly values: readonly string[];
|
|
16
|
+
readonly holes: readonly {
|
|
17
|
+
readonly value: string;
|
|
18
|
+
readonly after: string;
|
|
19
|
+
readonly before: string;
|
|
20
|
+
}[];
|
|
21
|
+
};
|
|
22
|
+
export declare function classifyValue(c: Scale, value: string): Attainability;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const trailing = (name) => {
|
|
2
|
+
const m = name.match(/^(.*?)(\d+)$/);
|
|
3
|
+
if (!m)
|
|
4
|
+
return null;
|
|
5
|
+
return { stem: m[1], n: Number(m[2]) };
|
|
6
|
+
};
|
|
7
|
+
export function attainable(c) {
|
|
8
|
+
const holes = [];
|
|
9
|
+
const byStem = new Map();
|
|
10
|
+
for (const name of c.levels) {
|
|
11
|
+
const t = trailing(name);
|
|
12
|
+
if (!t)
|
|
13
|
+
continue;
|
|
14
|
+
const list = byStem.get(t.stem) ?? [];
|
|
15
|
+
list.push({ name, n: t.n });
|
|
16
|
+
byStem.set(t.stem, list);
|
|
17
|
+
}
|
|
18
|
+
for (const [stem, list] of byStem) {
|
|
19
|
+
list.sort((a, b) => a.n - b.n);
|
|
20
|
+
for (let i = 0; i < list.length - 1; i++) {
|
|
21
|
+
const a = list[i];
|
|
22
|
+
const b = list[i + 1];
|
|
23
|
+
for (let n = a.n + 1; n < b.n; n++) {
|
|
24
|
+
holes.push({ value: `${stem}${n}`, after: a.name, before: b.name });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return { values: c.levels, holes };
|
|
29
|
+
}
|
|
30
|
+
export function classifyValue(c, value) {
|
|
31
|
+
if (c.levels.includes(value))
|
|
32
|
+
return { kind: 'attainable', value };
|
|
33
|
+
const found = attainable(c).holes.find((h) => h.value === value);
|
|
34
|
+
if (found)
|
|
35
|
+
return { kind: 'hole', value, after: found.after, before: found.before };
|
|
36
|
+
return { kind: 'unknown', value };
|
|
37
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function meetBlocks(c, u, w) {
|
|
2
|
+
const lo = c.lower(u, w);
|
|
3
|
+
const hi = c.higher(u, w);
|
|
4
|
+
const jis = c.joins().filter((j) => c.leq(lo, j) && c.leq(j, hi));
|
|
5
|
+
if (jis.length === 0)
|
|
6
|
+
return [];
|
|
7
|
+
const parent = jis.map((_, i) => i);
|
|
8
|
+
const find = (x) => (parent[x] === x ? x : (parent[x] = find(parent[x])));
|
|
9
|
+
const union = (a, b) => {
|
|
10
|
+
parent[find(a)] = find(b);
|
|
11
|
+
};
|
|
12
|
+
for (let i = 0; i < jis.length; i++) {
|
|
13
|
+
for (let j = i + 1; j < jis.length; j++) {
|
|
14
|
+
if (c.leq(jis[i], jis[j]) || c.leq(jis[j], jis[i]))
|
|
15
|
+
union(i, j);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const groups = new Map();
|
|
19
|
+
jis.forEach((j, i) => {
|
|
20
|
+
const r = find(i);
|
|
21
|
+
const g = groups.get(r) ?? [];
|
|
22
|
+
g.push(j);
|
|
23
|
+
groups.set(r, g);
|
|
24
|
+
});
|
|
25
|
+
return [...groups.values()];
|
|
26
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { defect, dropTo, price, slack, spectrum } from './quote.ts';
|
|
2
|
+
export type { Price, SpectrumQuantity } from './quote.ts';
|
|
3
|
+
export { best, c_n, collapses, costOfState, gap, isSupermodular, premium, pricesAnything, } from './premium.ts';
|
|
4
|
+
export { meetBlocks } from './blocks.ts';
|
|
5
|
+
export { attainable, classifyValue } from './attainable.ts';
|
|
6
|
+
export type { Attainability } from './attainable.ts';
|
|
7
|
+
export { complexity } from '../../debit/unit.ts';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { defect, dropTo, price, slack, spectrum } from "./quote.js";
|
|
2
|
+
export { best, c_n, collapses, costOfState, gap, isSupermodular, premium, pricesAnything, } from "./premium.js";
|
|
3
|
+
export { meetBlocks } from "./blocks.js";
|
|
4
|
+
export { attainable, classifyValue } from "./attainable.js";
|
|
5
|
+
export { complexity } from "../../debit/unit.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Level, Scale } from '../types.ts';
|
|
2
|
+
type Valuation = (level: Level) => number;
|
|
3
|
+
export declare function c_n(n: number): number;
|
|
4
|
+
export declare function costOfState(c: Scale, value: Valuation, u: Level, w: Level, s: Level): {
|
|
5
|
+
shortfall: number;
|
|
6
|
+
overshoot: number;
|
|
7
|
+
};
|
|
8
|
+
type Search = (c: Scale, value: Valuation, u: Level, w: Level) => {
|
|
9
|
+
cost: number;
|
|
10
|
+
at: Level;
|
|
11
|
+
};
|
|
12
|
+
export declare const best: Search;
|
|
13
|
+
export declare function gap(c: Scale, value: Valuation, u: Level, w: Level): number;
|
|
14
|
+
export declare function premium(c: Scale, value: Valuation, u: Level, w: Level): number;
|
|
15
|
+
export declare function isSupermodular(c: Scale, value: Valuation): boolean;
|
|
16
|
+
export declare function pricesAnything(c: Scale, worth: Valuation): boolean;
|
|
17
|
+
export declare function collapses(c: Scale, value: Valuation, u: Level, w: Level, tol?: number): boolean;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const SLACK = 1e-12;
|
|
2
|
+
export function c_n(n) {
|
|
3
|
+
return Math.log2(n) - 2 + 2 / n;
|
|
4
|
+
}
|
|
5
|
+
export function costOfState(c, value, u, w, s) {
|
|
6
|
+
return {
|
|
7
|
+
shortfall: value(u) - value(c.lower(u, s)),
|
|
8
|
+
overshoot: value(s) - value(c.lower(s, w)),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
const costAt = (c, value, u, w, s) => {
|
|
12
|
+
const { shortfall, overshoot } = costOfState(c, value, u, w, s);
|
|
13
|
+
return shortfall + overshoot;
|
|
14
|
+
};
|
|
15
|
+
function cheapest(c, value, u, w, visit) {
|
|
16
|
+
let cost;
|
|
17
|
+
let at = c.bottomIx;
|
|
18
|
+
visit((s) => {
|
|
19
|
+
const cs = costAt(c, value, u, w, s);
|
|
20
|
+
if (cost === undefined || cs < cost) {
|
|
21
|
+
cost = cs;
|
|
22
|
+
at = s;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return { cost: cost ?? costAt(c, value, u, w, at), at };
|
|
26
|
+
}
|
|
27
|
+
function eachPair(c, u, w, fn) {
|
|
28
|
+
for (let p = 0; p < c.levels.length; p++) {
|
|
29
|
+
if (!c.leq(p, u))
|
|
30
|
+
continue;
|
|
31
|
+
for (let q = 0; q < c.levels.length; q++) {
|
|
32
|
+
if (!c.leq(q, w))
|
|
33
|
+
continue;
|
|
34
|
+
fn(p, q);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export const best = (c, value, u, w) => cheapest(c, value, u, w, (take) => {
|
|
39
|
+
for (let s = 0; s < c.levels.length; s++)
|
|
40
|
+
take(s);
|
|
41
|
+
});
|
|
42
|
+
export function gap(c, value, u, w) {
|
|
43
|
+
const m = c.lower(u, w);
|
|
44
|
+
let mx = value(m);
|
|
45
|
+
eachPair(c, u, w, (p, q) => {
|
|
46
|
+
const v = value(p) + value(q) - value(c.higher(p, q));
|
|
47
|
+
if (v > mx)
|
|
48
|
+
mx = v;
|
|
49
|
+
});
|
|
50
|
+
return mx - value(m);
|
|
51
|
+
}
|
|
52
|
+
export function premium(c, value, u, w) {
|
|
53
|
+
return value(u) - value(c.lower(u, w)) - best(c, value, u, w).cost;
|
|
54
|
+
}
|
|
55
|
+
export function isSupermodular(c, value) {
|
|
56
|
+
for (let x = 0; x < c.levels.length; x++) {
|
|
57
|
+
for (let y = 0; y < c.levels.length; y++) {
|
|
58
|
+
const ri = value(x) + value(y) - value(c.higher(x, y)) - value(c.lower(x, y));
|
|
59
|
+
if (ri > SLACK)
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
function gapVanishes(c, value) {
|
|
66
|
+
for (let a = 0; a < c.levels.length; a++) {
|
|
67
|
+
for (let b = 0; b < c.levels.length; b++) {
|
|
68
|
+
if (c.leq(a, b) && value(a) > value(b) + SLACK)
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return isSupermodular(c, value);
|
|
73
|
+
}
|
|
74
|
+
export function pricesAnything(c, worth) {
|
|
75
|
+
return !gapVanishes(c, worth);
|
|
76
|
+
}
|
|
77
|
+
export function collapses(c, value, u, w, tol = 1e-9) {
|
|
78
|
+
const ri = value(u) + value(w) - value(c.higher(u, w)) - value(c.lower(u, w));
|
|
79
|
+
return Math.abs(premium(c, value, u, w) - ri) <= tol;
|
|
80
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Level, Scale } from '../types.ts';
|
|
2
|
+
type Valuation = (level: Level) => number;
|
|
3
|
+
export declare const dropTo: (value: Valuation, u: Level, m: Level) => number;
|
|
4
|
+
export declare function defect(c: Scale, value: Valuation, a: Level, b: Level): number;
|
|
5
|
+
export interface Price {
|
|
6
|
+
readonly coarse: number;
|
|
7
|
+
readonly gain: number;
|
|
8
|
+
readonly gated: number;
|
|
9
|
+
readonly derived: readonly ['gated'];
|
|
10
|
+
readonly best: number;
|
|
11
|
+
readonly at: Level;
|
|
12
|
+
readonly premium: number;
|
|
13
|
+
readonly licensed: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function price(c: Scale, value: Valuation, u: Level, w: Level): Price;
|
|
16
|
+
export declare function slack(c: Scale, a: Level, b: Level): {
|
|
17
|
+
up: number;
|
|
18
|
+
down: number;
|
|
19
|
+
} | null;
|
|
20
|
+
export type SpectrumQuantity = 'premium' | 'defect';
|
|
21
|
+
export declare function spectrum(c: Scale, worth: Valuation, places?: number, quantity?: SpectrumQuantity): {
|
|
22
|
+
values: number[];
|
|
23
|
+
pairs: number;
|
|
24
|
+
band: {
|
|
25
|
+
low: number;
|
|
26
|
+
high: number;
|
|
27
|
+
};
|
|
28
|
+
degeneracy: number;
|
|
29
|
+
};
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { UnitError } from "../errors.js";
|
|
2
|
+
import { best, premium as premiumOf } from "./premium.js";
|
|
3
|
+
export const dropTo = (value, u, m) => value(u) - value(m);
|
|
4
|
+
export function defect(c, value, a, b) {
|
|
5
|
+
return value(a) + value(b) - value(c.higher(a, b)) - value(c.lower(a, b));
|
|
6
|
+
}
|
|
7
|
+
export function price(c, value, u, w) {
|
|
8
|
+
const coarse = dropTo(value, u, c.lower(u, w));
|
|
9
|
+
const gain = defect(c, value, u, w);
|
|
10
|
+
const found = best(c, value, u, w);
|
|
11
|
+
const prem = coarse - found.cost;
|
|
12
|
+
const gated = coarse - gain;
|
|
13
|
+
return {
|
|
14
|
+
coarse,
|
|
15
|
+
gain,
|
|
16
|
+
gated,
|
|
17
|
+
derived: ['gated'],
|
|
18
|
+
best: found.cost,
|
|
19
|
+
at: found.at,
|
|
20
|
+
premium: prem,
|
|
21
|
+
licensed: Math.abs(gated - found.cost) <= 1e-9,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function slack(c, a, b) {
|
|
25
|
+
const bottom = c.bottomIx;
|
|
26
|
+
const height = (x) => c.intervalHeight(bottom, x);
|
|
27
|
+
const [ha, hb, hj, hm] = [height(a), height(b), height(c.higher(a, b)), height(c.lower(a, b))];
|
|
28
|
+
if (ha === null || hb === null || hj === null || hm === null)
|
|
29
|
+
return null;
|
|
30
|
+
return { up: hj - Math.max(ha, hb), down: Math.min(ha, hb) - hm };
|
|
31
|
+
}
|
|
32
|
+
export function spectrum(c, worth, places = 9, quantity = 'premium') {
|
|
33
|
+
const seen = new Set();
|
|
34
|
+
let pairs = 0;
|
|
35
|
+
for (let a = 0; a < c.levels.length; a++) {
|
|
36
|
+
for (let b = a; b < c.levels.length; b++) {
|
|
37
|
+
const left = quantity === 'defect' ? defect(c, worth, a, b) : premiumOf(c, worth, a, b);
|
|
38
|
+
if (!Number.isFinite(left)) {
|
|
39
|
+
throw new UnitError('NOT_FINITE', 'this way of valuing levels is not finite');
|
|
40
|
+
}
|
|
41
|
+
pairs++;
|
|
42
|
+
const step = 10 ** places;
|
|
43
|
+
seen.add(Math.round(left * step) / step);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const values = [...seen].sort((x, y) => x - y);
|
|
47
|
+
return {
|
|
48
|
+
values,
|
|
49
|
+
pairs,
|
|
50
|
+
band: { low: values[0] ?? 0, high: values[values.length - 1] ?? 0 },
|
|
51
|
+
degeneracy: values.length > 0 ? pairs / values.length : 0,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { WideMask } from '../debit/masks.ts';
|
|
2
|
+
import type { Lattice } from './lattice.ts';
|
|
3
|
+
import type { Scale, Unit } from './types.ts';
|
|
4
|
+
export declare function fromScale(c: Scale): Lattice<Unit>;
|
|
5
|
+
export declare function subsets(tokens: readonly string[]): Lattice<WideMask>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { WideMask } from "../debit/masks.js";
|
|
2
|
+
import { entails, fuse, permitAll, state } from "../debit/unit.js";
|
|
3
|
+
export function fromScale(c) {
|
|
4
|
+
const inhabited = (x) => state(c, x) !== 'CONFLICT';
|
|
5
|
+
return {
|
|
6
|
+
top: permitAll(c, ''),
|
|
7
|
+
bottom: { subject: '', floor: c.levels[c.topIx] ?? '', ceiling: c.levels[c.bottomIx] ?? '' },
|
|
8
|
+
leq: (a, b) => entails(c, a, b),
|
|
9
|
+
meet: (a, b) => fuse(c, [a, b]),
|
|
10
|
+
join: (a, b) => {
|
|
11
|
+
if (!inhabited(a))
|
|
12
|
+
return b;
|
|
13
|
+
if (!inhabited(b))
|
|
14
|
+
return a;
|
|
15
|
+
return {
|
|
16
|
+
subject: a.subject || b.subject,
|
|
17
|
+
floor: c.levels[c.lower(c.rank(a.floor), c.rank(b.floor))] ?? a.floor,
|
|
18
|
+
ceiling: c.levels[c.higher(c.rank(a.ceiling), c.rank(b.ceiling))] ?? a.ceiling,
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
show: (x) => `[${x.floor}, ${x.ceiling}]`,
|
|
22
|
+
inhabited,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function subsets(tokens) {
|
|
26
|
+
return {
|
|
27
|
+
bottom: new WideMask(tokens.length),
|
|
28
|
+
top: WideMask.filled(tokens.length),
|
|
29
|
+
leq: (a, b) => a.subsetOf(b),
|
|
30
|
+
meet: (a, b) => a.and(b),
|
|
31
|
+
join: (a, b) => a.or(b),
|
|
32
|
+
show: (x) => x.members(tokens).join(','),
|
|
33
|
+
inhabited: (x) => x.size() > 0,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export type State = 'FREE' | 'REQUIRED' | 'FORBIDDEN' | 'CONFLICT';
|
|
2
|
+
export type DebitOutcome = State | 'REQUIRED_OR_CONFLICT';
|
|
3
|
+
export type Level = number;
|
|
4
|
+
export interface Scale {
|
|
5
|
+
readonly levels: readonly string[];
|
|
6
|
+
readonly isLadder: boolean;
|
|
7
|
+
readonly isSimple: boolean;
|
|
8
|
+
readonly bottomIx: Level;
|
|
9
|
+
readonly topIx: Level;
|
|
10
|
+
readonly bottom: string;
|
|
11
|
+
readonly top: string;
|
|
12
|
+
leq(a: Level, b: Level): boolean;
|
|
13
|
+
higher(a: Level, b: Level): Level;
|
|
14
|
+
lower(a: Level, b: Level): Level;
|
|
15
|
+
rank(level: string): Level;
|
|
16
|
+
stateOf(floor: Level, ceiling: Level): State;
|
|
17
|
+
joins(): Level[];
|
|
18
|
+
limits(): Level[];
|
|
19
|
+
debits(): Level[];
|
|
20
|
+
intervalHeight(lo: Level, hi: Level): number | null;
|
|
21
|
+
}
|
|
22
|
+
export interface Unit {
|
|
23
|
+
readonly subject: string;
|
|
24
|
+
readonly floor: string;
|
|
25
|
+
readonly ceiling: string;
|
|
26
|
+
}
|
|
27
|
+
export type BoolView = {
|
|
28
|
+
readonly kind: 'exactly';
|
|
29
|
+
readonly value: boolean;
|
|
30
|
+
} | {
|
|
31
|
+
readonly kind: 'lossy';
|
|
32
|
+
readonly value: boolean;
|
|
33
|
+
readonly lost: string;
|
|
34
|
+
} | {
|
|
35
|
+
readonly kind: 'unsayable';
|
|
36
|
+
readonly lost: string;
|
|
37
|
+
};
|
|
38
|
+
export type Method = 'declared' | 'statistics' | 'sample' | 'exact';
|
|
39
|
+
export type MeasureForm = 'ladder' | 'alphabet' | 'continuous';
|
|
40
|
+
export type Edge = readonly [string, string];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Level, Scale } from './types.ts';
|
|
2
|
+
type Valuation = (level: Level) => number;
|
|
3
|
+
export interface Verdict {
|
|
4
|
+
readonly predicate: string;
|
|
5
|
+
readonly structure: string;
|
|
6
|
+
readonly samples: number;
|
|
7
|
+
readonly yes: number;
|
|
8
|
+
readonly no: number;
|
|
9
|
+
readonly verdict: 'CONSTANT' | 'DISCRIMINATES' | 'INDEPENDENT';
|
|
10
|
+
readonly witnesses?: {
|
|
11
|
+
readonly yes: readonly number[];
|
|
12
|
+
readonly no: readonly number[];
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export interface VacuityOptions {
|
|
16
|
+
readonly samples?: number;
|
|
17
|
+
readonly spread?: number;
|
|
18
|
+
readonly monotone?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare function isMonotone(c: Scale, value: Valuation): boolean;
|
|
21
|
+
export declare function vacuityOf(predicate: string, structure: string, c: Scale, test: (c: Scale, value: Valuation) => boolean, opts?: VacuityOptions): Verdict;
|
|
22
|
+
export {};
|