@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,7 @@
|
|
|
1
|
+
import type { Scale, Unit } from '../lattice/types.ts';
|
|
2
|
+
export interface Register {
|
|
3
|
+
readonly demanded: readonly string[];
|
|
4
|
+
readonly limiting: readonly string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function register(c: Scale, u: Unit): Register;
|
|
7
|
+
export declare function rebuild(c: Scale, reg: Register, subject?: string): Unit;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function register(c, u) {
|
|
2
|
+
const f = c.rank(u.floor);
|
|
3
|
+
const cl = c.rank(u.ceiling);
|
|
4
|
+
return {
|
|
5
|
+
demanded: c.joins().filter((j) => c.leq(j, f)).map((j) => c.levels[j]),
|
|
6
|
+
limiting: c.limits().filter((m) => c.leq(cl, m)).map((m) => c.levels[m]),
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export function rebuild(c, reg, subject = '') {
|
|
10
|
+
let floor = c.bottomIx;
|
|
11
|
+
for (const name of reg.demanded)
|
|
12
|
+
floor = c.higher(floor, c.rank(name));
|
|
13
|
+
let ceiling = c.topIx;
|
|
14
|
+
for (const name of reg.limiting)
|
|
15
|
+
ceiling = c.lower(ceiling, c.rank(name));
|
|
16
|
+
return { subject, floor: c.levels[floor], ceiling: c.levels[ceiling] };
|
|
17
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
function stream(seed) {
|
|
2
|
+
let s = (Math.imul(seed + 1, 2654435761) ^ 0x5f3759df) >>> 0;
|
|
3
|
+
return () => {
|
|
4
|
+
s = (Math.imul(s, 1664525) + 1013904223) >>> 0;
|
|
5
|
+
return s;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export function unitStream(seed) {
|
|
9
|
+
const next = stream(seed);
|
|
10
|
+
return () => next() / 4294967296;
|
|
11
|
+
}
|
|
12
|
+
export function permute(xs, salt) {
|
|
13
|
+
const next = stream(salt);
|
|
14
|
+
const out = xs.slice();
|
|
15
|
+
for (let i = out.length - 1; i > 0; i--) {
|
|
16
|
+
const j = next() % (i + 1);
|
|
17
|
+
const t = out[i];
|
|
18
|
+
out[i] = out[j];
|
|
19
|
+
out[j] = t;
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
export function permutationBlind(values, claim, draws = 8) {
|
|
24
|
+
const want = JSON.stringify(claim(values));
|
|
25
|
+
for (let d = 0; d < draws; d++) {
|
|
26
|
+
if (JSON.stringify(claim(permute(values, d + 1))) !== want)
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { fuse } from "./unit.js";
|
|
2
|
+
export function touches(c, mine, folded) {
|
|
3
|
+
return c.rank(mine.floor) === c.rank(folded.floor) || c.rank(mine.ceiling) === c.rank(folded.ceiling);
|
|
4
|
+
}
|
|
5
|
+
export function holds(c, units, index) {
|
|
6
|
+
if (index < 0 || index >= units.length)
|
|
7
|
+
return false;
|
|
8
|
+
const whole = fuse(c, units);
|
|
9
|
+
const rest = units.filter((_, i) => i !== index);
|
|
10
|
+
const next = fuse(c, rest);
|
|
11
|
+
return next.floor !== whole.floor || next.ceiling !== whole.ceiling;
|
|
12
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Scale, State, Unit } from '../lattice/types.ts';
|
|
2
|
+
export declare function statesPerDebit(c: Scale, u: Unit): [string, State][];
|
|
3
|
+
export declare function anyOf(c: Scale, units: readonly Unit[]): Unit[];
|
|
4
|
+
export declare function missing(c: Scale, have: Unit, want: Unit): {
|
|
5
|
+
raiseFloorTo: string[];
|
|
6
|
+
raiseCeilingTo: string[];
|
|
7
|
+
};
|
|
8
|
+
export declare function complexity(c: Scale, u: Unit): number;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { unitComplexity } from "./ideal.js";
|
|
2
|
+
export function statesPerDebit(c, u) {
|
|
3
|
+
const f = c.rank(u.floor);
|
|
4
|
+
const cl = c.rank(u.ceiling);
|
|
5
|
+
return c.joins().map((j) => {
|
|
6
|
+
const demanded = c.leq(j, f);
|
|
7
|
+
const permitted = c.leq(j, cl);
|
|
8
|
+
return [
|
|
9
|
+
c.levels[j],
|
|
10
|
+
demanded ? (permitted ? 'REQUIRED' : 'CONFLICT') : permitted ? 'FREE' : 'FORBIDDEN',
|
|
11
|
+
];
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export function anyOf(c, units) {
|
|
15
|
+
const rank = (u) => [c.rank(u.floor), c.rank(u.ceiling)];
|
|
16
|
+
const holds = (f, cl, l) => c.leq(f, l) && c.leq(l, cl);
|
|
17
|
+
const levels = [...c.levels.keys()];
|
|
18
|
+
let live = units.filter((u) => {
|
|
19
|
+
const [f, cl] = rank(u);
|
|
20
|
+
return c.leq(f, cl);
|
|
21
|
+
});
|
|
22
|
+
for (let changed = true; changed;) {
|
|
23
|
+
changed = false;
|
|
24
|
+
outer: for (let i = 0; i < live.length; i++) {
|
|
25
|
+
for (let j = i + 1; j < live.length; j++) {
|
|
26
|
+
const [af, ac] = rank(live[i]);
|
|
27
|
+
const [bf, bc] = rank(live[j]);
|
|
28
|
+
const lo = c.lower(af, bf);
|
|
29
|
+
const hi = c.higher(ac, bc);
|
|
30
|
+
const gains = levels.some((l) => holds(lo, hi, l) && !holds(af, ac, l) && !holds(bf, bc, l));
|
|
31
|
+
if (gains)
|
|
32
|
+
continue;
|
|
33
|
+
live = [
|
|
34
|
+
...live.filter((_, k) => k !== i && k !== j),
|
|
35
|
+
{ subject: live[i].subject, floor: c.levels[lo], ceiling: c.levels[hi] },
|
|
36
|
+
];
|
|
37
|
+
changed = true;
|
|
38
|
+
break outer;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return live.sort((x, y) => {
|
|
43
|
+
const [xf, xc] = rank(x);
|
|
44
|
+
const [yf, yc] = rank(y);
|
|
45
|
+
return xf - yf || xc - yc;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
export function missing(c, have, want) {
|
|
49
|
+
const [hf, hc] = [c.rank(have.floor), c.rank(have.ceiling)];
|
|
50
|
+
const [wf, wc] = [c.rank(want.floor), c.rank(want.ceiling)];
|
|
51
|
+
const all = [...c.levels.keys()];
|
|
52
|
+
const weakestOf = (works) => {
|
|
53
|
+
const ok = all.filter(works);
|
|
54
|
+
return ok.filter((l) => !ok.some((o) => o !== l && c.leq(o, l))).map((l) => c.levels[l]);
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
raiseFloorTo: c.leq(wf, hf) ? [] : weakestOf((l) => c.leq(wf, c.higher(hf, l))),
|
|
58
|
+
raiseCeilingTo: c.leq(wc, hc) ? [] : weakestOf((l) => c.leq(wc, c.higher(hc, l))),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export function complexity(c, u) {
|
|
62
|
+
return unitComplexity(c, u);
|
|
63
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BoolView, DebitOutcome, Scale, State, Unit } from '../lattice/types.ts';
|
|
2
|
+
export declare function unit(subject: string, bounds: {
|
|
3
|
+
floor: string;
|
|
4
|
+
ceiling: string;
|
|
5
|
+
}): Unit;
|
|
6
|
+
export declare const permitAll: (c: Scale, subject: string) => Unit;
|
|
7
|
+
export declare function state(c: Scale, u: Unit): State;
|
|
8
|
+
export declare function asBoolean(c: Scale, u: Unit): BoolView;
|
|
9
|
+
export declare function bitLoss(c: Scale): {
|
|
10
|
+
readonly possible: number;
|
|
11
|
+
readonly exactly: number;
|
|
12
|
+
readonly lossy: number;
|
|
13
|
+
readonly unsayable: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function compose(c: Scale, units: readonly Unit[]): Unit;
|
|
16
|
+
export declare function fuse(c: Scale, units: readonly Unit[]): Unit;
|
|
17
|
+
export declare function composeState(c: Scale, units: readonly Unit[]): State;
|
|
18
|
+
export declare function table(a: State, b: State): DebitOutcome;
|
|
19
|
+
export declare function conflictDebits(c: Scale, u: Unit): number;
|
|
20
|
+
export declare function entails(c: Scale, a: Unit, b: Unit): boolean;
|
|
21
|
+
export declare function widen(c: Scale, units: readonly Unit[]): Unit;
|
|
22
|
+
export { anyOf, missing, statesPerDebit, complexity } from './unit-span.ts';
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { UnitError } from "../lattice/errors.js";
|
|
2
|
+
export function unit(subject, bounds) {
|
|
3
|
+
return { subject, floor: bounds.floor, ceiling: bounds.ceiling };
|
|
4
|
+
}
|
|
5
|
+
export const permitAll = (c, subject) => unit(subject, { floor: c.bottom, ceiling: c.top });
|
|
6
|
+
export function state(c, u) {
|
|
7
|
+
return c.stateOf(c.rank(u.floor), c.rank(u.ceiling));
|
|
8
|
+
}
|
|
9
|
+
export function asBoolean(c, u) {
|
|
10
|
+
const s = state(c, u);
|
|
11
|
+
if (s === 'CONFLICT') {
|
|
12
|
+
return {
|
|
13
|
+
kind: 'unsayable',
|
|
14
|
+
lost: 'a boolean has no way to say two promises cannot both hold, so a ' +
|
|
15
|
+
'register of booleans settles it by precedence instead',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (s === 'REQUIRED') {
|
|
19
|
+
return {
|
|
20
|
+
kind: 'lossy',
|
|
21
|
+
value: true,
|
|
22
|
+
lost: 'the floor: a boolean says may, never must, so nothing records that ' +
|
|
23
|
+
'somebody depends on this',
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (s === 'FORBIDDEN') {
|
|
27
|
+
return c.rank(u.ceiling) === c.bottomIx
|
|
28
|
+
? { kind: 'exactly', value: false }
|
|
29
|
+
: { kind: 'lossy', value: true, lost: 'the ceiling: a boolean cannot say how far' };
|
|
30
|
+
}
|
|
31
|
+
return { kind: 'exactly', value: true };
|
|
32
|
+
}
|
|
33
|
+
export function bitLoss(c) {
|
|
34
|
+
let exactly = 0;
|
|
35
|
+
let lossy = 0;
|
|
36
|
+
let unsayable = 0;
|
|
37
|
+
let possible = 0;
|
|
38
|
+
for (const floor of c.levels) {
|
|
39
|
+
for (const ceiling of c.levels) {
|
|
40
|
+
possible++;
|
|
41
|
+
const k = asBoolean(c, { subject: '', floor, ceiling }).kind;
|
|
42
|
+
if (k === 'exactly')
|
|
43
|
+
exactly++;
|
|
44
|
+
else if (k === 'lossy')
|
|
45
|
+
lossy++;
|
|
46
|
+
else
|
|
47
|
+
unsayable++;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return { possible, exactly, lossy, unsayable };
|
|
51
|
+
}
|
|
52
|
+
export function compose(c, units) {
|
|
53
|
+
for (const u of units) {
|
|
54
|
+
if (!c.leq(c.rank(u.floor), c.rank(u.ceiling))) {
|
|
55
|
+
throw new UnitError('MALFORMED', `\`${u.subject}\` cannot be met by anything`, {
|
|
56
|
+
subject: u.subject,
|
|
57
|
+
floor: u.floor,
|
|
58
|
+
ceiling: u.ceiling,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return fuse(c, units);
|
|
63
|
+
}
|
|
64
|
+
function band(c, units, from, onFloor, onCeiling) {
|
|
65
|
+
let floor = from.floor;
|
|
66
|
+
let ceiling = from.ceiling;
|
|
67
|
+
for (const u of units) {
|
|
68
|
+
floor = onFloor(floor, c.rank(u.floor));
|
|
69
|
+
ceiling = onCeiling(ceiling, c.rank(u.ceiling));
|
|
70
|
+
}
|
|
71
|
+
return { subject: units[0].subject, floor: c.levels[floor], ceiling: c.levels[ceiling] };
|
|
72
|
+
}
|
|
73
|
+
export function fuse(c, units) {
|
|
74
|
+
if (units.length === 0)
|
|
75
|
+
return permitAll(c, '');
|
|
76
|
+
return band(c, units, { floor: c.bottomIx, ceiling: c.topIx }, (a, b) => c.higher(a, b), (a, b) => c.lower(a, b));
|
|
77
|
+
}
|
|
78
|
+
export function composeState(c, units) {
|
|
79
|
+
const u = compose(c, units);
|
|
80
|
+
return c.stateOf(c.rank(u.floor), c.rank(u.ceiling));
|
|
81
|
+
}
|
|
82
|
+
const ORDER = ['FREE', 'REQUIRED', 'FORBIDDEN', 'CONFLICT'];
|
|
83
|
+
const RoC = 'REQUIRED_OR_CONFLICT';
|
|
84
|
+
const TABLE = [
|
|
85
|
+
['FREE', 'REQUIRED', 'FORBIDDEN', 'CONFLICT'],
|
|
86
|
+
['REQUIRED', RoC, RoC, 'CONFLICT'],
|
|
87
|
+
['FORBIDDEN', RoC, 'FORBIDDEN', 'CONFLICT'],
|
|
88
|
+
['CONFLICT', 'CONFLICT', 'CONFLICT', 'CONFLICT'],
|
|
89
|
+
];
|
|
90
|
+
export function table(a, b) {
|
|
91
|
+
return TABLE[ORDER.indexOf(a)][ORDER.indexOf(b)];
|
|
92
|
+
}
|
|
93
|
+
export function conflictDebits(c, u) {
|
|
94
|
+
const f = c.rank(u.floor);
|
|
95
|
+
const cl = c.rank(u.ceiling);
|
|
96
|
+
if (c.leq(f, cl))
|
|
97
|
+
return 0;
|
|
98
|
+
return c.joins().filter((j) => c.leq(j, f) && !c.leq(j, cl)).length;
|
|
99
|
+
}
|
|
100
|
+
export function entails(c, a, b) {
|
|
101
|
+
const [af, ac] = [c.rank(a.floor), c.rank(a.ceiling)];
|
|
102
|
+
const [bf, bc] = [c.rank(b.floor), c.rank(b.ceiling)];
|
|
103
|
+
return c.leq(bf, af) && c.leq(ac, bc);
|
|
104
|
+
}
|
|
105
|
+
export function widen(c, units) {
|
|
106
|
+
if (units.length === 0)
|
|
107
|
+
return { subject: '', floor: c.levels[c.topIx], ceiling: c.levels[c.bottomIx] };
|
|
108
|
+
return band(c, units, { floor: c.topIx, ceiling: c.bottomIx }, (a, b) => c.lower(a, b), (a, b) => c.higher(a, b));
|
|
109
|
+
}
|
|
110
|
+
export { anyOf, missing, statesPerDebit, complexity } from "./unit-span.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { State } from '../lattice/types.ts';
|
|
2
|
+
type Quadrants = import('./vector.ts').Quadrants;
|
|
3
|
+
export type Matrix = Readonly<Record<State, Readonly<Record<State, number>>>>;
|
|
4
|
+
export declare const DANGEROUS: readonly (readonly [State, State])[];
|
|
5
|
+
export declare function transitions(before: Quadrants, after: Quadrants, width: number): Matrix;
|
|
6
|
+
export declare function dangerous(m: Matrix): readonly {
|
|
7
|
+
from: State;
|
|
8
|
+
to: State;
|
|
9
|
+
n: number;
|
|
10
|
+
}[];
|
|
11
|
+
export declare function moved(m: Matrix): number;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const STATES = ['REQUIRED', 'FREE', 'FORBIDDEN', 'CONFLICT'];
|
|
2
|
+
function findWithin(runs, s) {
|
|
3
|
+
let n = 0;
|
|
4
|
+
for (const r of runs)
|
|
5
|
+
if (r.within)
|
|
6
|
+
n += r.within[s];
|
|
7
|
+
return n;
|
|
8
|
+
}
|
|
9
|
+
export const DANGEROUS = STATES.filter((s) => s !== 'CONFLICT').map((s) => [s, 'CONFLICT']);
|
|
10
|
+
const zero = () => {
|
|
11
|
+
const m = {};
|
|
12
|
+
for (const a of STATES) {
|
|
13
|
+
m[a] = {};
|
|
14
|
+
for (const b of STATES)
|
|
15
|
+
m[a][b] = 0;
|
|
16
|
+
}
|
|
17
|
+
return m;
|
|
18
|
+
};
|
|
19
|
+
export function transitions(before, after, width) {
|
|
20
|
+
const at = (q, bit) => {
|
|
21
|
+
for (const s of STATES)
|
|
22
|
+
if (q[s].has(bit))
|
|
23
|
+
return s;
|
|
24
|
+
return null;
|
|
25
|
+
};
|
|
26
|
+
const m = zero();
|
|
27
|
+
for (let bit = 0; bit < width; bit++) {
|
|
28
|
+
const a = at(before, bit);
|
|
29
|
+
const b = at(after, bit);
|
|
30
|
+
if (a === null || b === null)
|
|
31
|
+
continue;
|
|
32
|
+
m[a][b] += 1;
|
|
33
|
+
}
|
|
34
|
+
return m;
|
|
35
|
+
}
|
|
36
|
+
export function dangerous(m) {
|
|
37
|
+
return DANGEROUS
|
|
38
|
+
.map(([from, to]) => ({ from, to, n: m[from][to] }))
|
|
39
|
+
.filter((x) => x.n > 0);
|
|
40
|
+
}
|
|
41
|
+
export function moved(m) {
|
|
42
|
+
let n = 0;
|
|
43
|
+
for (const a of STATES)
|
|
44
|
+
for (const b of STATES)
|
|
45
|
+
if (a !== b)
|
|
46
|
+
n += m[a][b];
|
|
47
|
+
return n;
|
|
48
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { WideMask } from './masks.ts';
|
|
2
|
+
import type { State } from '../lattice/types.ts';
|
|
3
|
+
export declare const STATES: readonly ["REQUIRED", "FREE", "FORBIDDEN", "CONFLICT"];
|
|
4
|
+
export interface Quadrants {
|
|
5
|
+
readonly REQUIRED: WideMask;
|
|
6
|
+
readonly FREE: WideMask;
|
|
7
|
+
readonly FORBIDDEN: WideMask;
|
|
8
|
+
readonly CONFLICT: WideMask;
|
|
9
|
+
}
|
|
10
|
+
export declare function quadrants(demanded: WideMask, permitted: WideMask, extent: WideMask): Quadrants;
|
|
11
|
+
export declare function sizes(q: Quadrants): Readonly<Record<State, number>>;
|
|
12
|
+
export declare function stateAt(q: Quadrants, bit: number): State | null;
|
|
13
|
+
export interface Run {
|
|
14
|
+
readonly lo: number;
|
|
15
|
+
readonly hi: number;
|
|
16
|
+
readonly state: State;
|
|
17
|
+
readonly coalesced?: number;
|
|
18
|
+
readonly within?: Readonly<Record<State, number>>;
|
|
19
|
+
}
|
|
20
|
+
export interface Span {
|
|
21
|
+
readonly lo: number;
|
|
22
|
+
readonly hi: number;
|
|
23
|
+
}
|
|
24
|
+
export declare function runQuadrants(demanded: readonly Span[], permitted: Span | null, extent: Span): readonly Run[];
|
|
25
|
+
export type { Matrix } from './vector-move.ts';
|
|
26
|
+
export { DANGEROUS, dangerous, moved, transitions } from './vector-move.ts';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { WideMask } from "./masks.js";
|
|
2
|
+
export const STATES = ['REQUIRED', 'FREE', 'FORBIDDEN', 'CONFLICT'];
|
|
3
|
+
export function quadrants(demanded, permitted, extent) {
|
|
4
|
+
const d = demanded.and(extent);
|
|
5
|
+
const p = permitted.and(extent);
|
|
6
|
+
return {
|
|
7
|
+
REQUIRED: d.and(p),
|
|
8
|
+
FREE: p.difference(d),
|
|
9
|
+
FORBIDDEN: extent.difference(p).difference(d),
|
|
10
|
+
CONFLICT: d.difference(p),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function sizes(q) {
|
|
14
|
+
return {
|
|
15
|
+
REQUIRED: q.REQUIRED.size(),
|
|
16
|
+
FREE: q.FREE.size(),
|
|
17
|
+
FORBIDDEN: q.FORBIDDEN.size(),
|
|
18
|
+
CONFLICT: q.CONFLICT.size(),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function stateAt(q, bit) {
|
|
22
|
+
for (const s of STATES)
|
|
23
|
+
if (q[s].has(bit))
|
|
24
|
+
return s;
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const overlaps = (a, x) => x >= a.lo && x <= a.hi;
|
|
28
|
+
export function runQuadrants(demanded, permitted, extent) {
|
|
29
|
+
if (extent.hi < extent.lo)
|
|
30
|
+
return [];
|
|
31
|
+
const cuts = new Set([extent.lo]);
|
|
32
|
+
const add = (s) => {
|
|
33
|
+
if (s.lo > extent.lo && s.lo <= extent.hi)
|
|
34
|
+
cuts.add(s.lo);
|
|
35
|
+
if (s.hi >= extent.lo && s.hi < extent.hi)
|
|
36
|
+
cuts.add(s.hi + 1);
|
|
37
|
+
};
|
|
38
|
+
for (const s of demanded)
|
|
39
|
+
add(s);
|
|
40
|
+
if (permitted)
|
|
41
|
+
add(permitted);
|
|
42
|
+
const at = (x) => {
|
|
43
|
+
const d = demanded.some((s) => overlaps(s, x));
|
|
44
|
+
const p = permitted !== null && overlaps(permitted, x);
|
|
45
|
+
if (d && p)
|
|
46
|
+
return 'REQUIRED';
|
|
47
|
+
if (d)
|
|
48
|
+
return 'CONFLICT';
|
|
49
|
+
return p ? 'FREE' : 'FORBIDDEN';
|
|
50
|
+
};
|
|
51
|
+
const points = [...cuts].sort((a, b) => a - b);
|
|
52
|
+
const out = [];
|
|
53
|
+
for (let i = 0; i < points.length; i++) {
|
|
54
|
+
const lo = points[i];
|
|
55
|
+
const hi = i + 1 < points.length ? points[i + 1] - 1 : extent.hi;
|
|
56
|
+
if (hi < lo)
|
|
57
|
+
continue;
|
|
58
|
+
const state = at(lo);
|
|
59
|
+
const last = out[out.length - 1];
|
|
60
|
+
if (last && last.state === state && last.hi + 1 === lo) {
|
|
61
|
+
out[out.length - 1] = { lo: last.lo, hi, state };
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
out.push({ lo, hi, state });
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
export { DANGEROUS, dangerous, moved, transitions } from "./vector-move.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Point, Sighting } from './field.ts';
|
|
2
|
+
import type { Interval } from '../lattice/forms.ts';
|
|
3
|
+
export declare function origins(place: Point): number;
|
|
4
|
+
export declare function potential(place: Point): boolean;
|
|
5
|
+
export declare function disagree(place: Point): readonly [Sighting, Sighting] | null;
|
|
6
|
+
export declare function meetAt(place: Point): Interval;
|
|
7
|
+
export declare function latest(places: readonly Point[]): Point | null;
|
|
8
|
+
export declare function verdict(place: Point): string;
|
|
9
|
+
export declare function turned(before: readonly Point[], after: readonly Point[]): readonly Point[];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { witnessesIn } from "../debit/debit.js";
|
|
2
|
+
import { key } from "./field.js";
|
|
3
|
+
import { intervals } from "../lattice/forms.js";
|
|
4
|
+
const spanning = (spans) => intervals(Math.min(...spans.map((one) => one.lo)), Math.max(...spans.map((one) => one.hi)));
|
|
5
|
+
export function origins(place) {
|
|
6
|
+
return new Set(place.seen.map((s) => s.origin)).size;
|
|
7
|
+
}
|
|
8
|
+
export function potential(place) {
|
|
9
|
+
return origins(place) < 2;
|
|
10
|
+
}
|
|
11
|
+
export function disagree(place) {
|
|
12
|
+
const spans = place.seen.map((s) => s.span);
|
|
13
|
+
const split = spans.length ? witnessesIn(spanning(spans), spans) : null;
|
|
14
|
+
if (!split)
|
|
15
|
+
return null;
|
|
16
|
+
const left = place.seen.find((s) => s.span === split[0]);
|
|
17
|
+
const right = place.seen.find((s) => s.span === split[1]);
|
|
18
|
+
return left && right ? [left, right] : null;
|
|
19
|
+
}
|
|
20
|
+
export function meetAt(place) {
|
|
21
|
+
const spans = place.seen.map((s) => s.span);
|
|
22
|
+
if (!spans.length)
|
|
23
|
+
throw new Error('obligations: REFUSE·meet a cell no origin has claimed has no meet of its own: read it against the form it belongs to');
|
|
24
|
+
const form = spanning(spans);
|
|
25
|
+
return spans.reduce((held, span) => form.meet(held, span));
|
|
26
|
+
}
|
|
27
|
+
export function latest(places) {
|
|
28
|
+
return places.reduce((held, place) => (held === null || place.epoch > held.epoch ? place : held), null);
|
|
29
|
+
}
|
|
30
|
+
export function verdict(place) {
|
|
31
|
+
return potential(place) ? 'one' : disagree(place) ? 'apart' : 'together';
|
|
32
|
+
}
|
|
33
|
+
export function turned(before, after) {
|
|
34
|
+
const held = new Map(before.map((p) => [key([{ at: p.at }]), verdict(p)]));
|
|
35
|
+
return after.filter((p) => held.get(key([{ at: p.at }])) !== verdict(p));
|
|
36
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Interval } from '../lattice/forms.ts';
|
|
2
|
+
export interface Sighting {
|
|
3
|
+
readonly origin: string;
|
|
4
|
+
readonly span: Interval;
|
|
5
|
+
}
|
|
6
|
+
export interface Point {
|
|
7
|
+
readonly at: readonly string[];
|
|
8
|
+
readonly epoch: number;
|
|
9
|
+
readonly seen: readonly Sighting[];
|
|
10
|
+
}
|
|
11
|
+
export interface Region {
|
|
12
|
+
readonly at: readonly string[];
|
|
13
|
+
}
|
|
14
|
+
export declare function coordinate(name: string, steps?: string): readonly string[];
|
|
15
|
+
export declare function point(name: string, epoch?: number, seen?: readonly Sighting[], steps?: string): Point;
|
|
16
|
+
export declare function region(name: string, steps?: string): Region;
|
|
17
|
+
export declare function coarsen(place: Point, steps: number): Point;
|
|
18
|
+
export declare function passes(place: Point | Region, step: string): boolean;
|
|
19
|
+
export declare function resolution(place: Point | Region): number;
|
|
20
|
+
export declare function within(inner: Point | Region, outer: Region): boolean;
|
|
21
|
+
export declare function exclusive(mine: readonly Region[], others: readonly (readonly Region[])[]): readonly Region[];
|
|
22
|
+
export declare function contracts(regions: readonly Region[], touched: readonly Point[]): boolean;
|
|
23
|
+
export declare function key(regions: readonly Region[]): string;
|
|
24
|
+
export interface Fold<T> {
|
|
25
|
+
readonly at: string;
|
|
26
|
+
readonly value: T;
|
|
27
|
+
}
|
|
28
|
+
export declare function foldRegion<T>(places: readonly Point[], where: Region, f: (met: readonly Point[]) => T): readonly Fold<T>[];
|
|
29
|
+
export declare function covers(met: readonly Point[], of: {
|
|
30
|
+
readonly where: readonly Region[];
|
|
31
|
+
readonly steps: Interval;
|
|
32
|
+
readonly when: Interval;
|
|
33
|
+
}): boolean;
|
|
34
|
+
export declare function outranks(met: readonly Point[], named: readonly (readonly [string, string])[], order: readonly string[]): string | null;
|
|
35
|
+
export declare function answers(met: readonly Point[], where: readonly Region[]): boolean;
|
|
36
|
+
export declare function verified(met: readonly Point[], green: (place: Point) => boolean): boolean;
|
|
37
|
+
export declare function retracted(met: readonly Point[], by: readonly Region[]): readonly Point[];
|
|
38
|
+
export declare function size(at: readonly string[], steps?: number): number;
|
|
39
|
+
export declare function sufficientResolution<T>(finest: number, verdict: (steps: number) => T, same?: (a: T, b: T) => boolean): number;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export function coordinate(name, steps = '/') {
|
|
2
|
+
const at = name.split(new RegExp(`[${steps.replace(/[.*+?^${}()|[\]\\-]/g, '\\$&')}]`)).filter((s) => s !== '');
|
|
3
|
+
while (at[at.length - 1] === '*' || at[at.length - 1] === '**')
|
|
4
|
+
at.pop();
|
|
5
|
+
return at;
|
|
6
|
+
}
|
|
7
|
+
export function point(name, epoch = 0, seen = [], steps = '/') {
|
|
8
|
+
return { at: coordinate(name, steps), epoch, seen };
|
|
9
|
+
}
|
|
10
|
+
export function region(name, steps = '/') {
|
|
11
|
+
return { at: coordinate(name, steps) };
|
|
12
|
+
}
|
|
13
|
+
export function coarsen(place, steps) {
|
|
14
|
+
return { at: place.at.slice(0, Math.max(0, steps)), epoch: place.epoch, seen: place.seen };
|
|
15
|
+
}
|
|
16
|
+
export function passes(place, step) {
|
|
17
|
+
return step.startsWith('*') ? place.at.some((s) => s.endsWith(step.slice(1))) : place.at.includes(step);
|
|
18
|
+
}
|
|
19
|
+
export function resolution(place) {
|
|
20
|
+
return place.at.length;
|
|
21
|
+
}
|
|
22
|
+
export function within(inner, outer) {
|
|
23
|
+
const refines = (i, j) => j === outer.at.length
|
|
24
|
+
|| (outer.at[j] === '**'
|
|
25
|
+
? refines(i, j + 1) || (i < inner.at.length && refines(i + 1, j))
|
|
26
|
+
: i < inner.at.length && (outer.at[j] === '*' || outer.at[j] === inner.at[i]) && refines(i + 1, j + 1));
|
|
27
|
+
return refines(0, 0);
|
|
28
|
+
}
|
|
29
|
+
export function exclusive(mine, others) {
|
|
30
|
+
return mine.filter((one) => !others.some((other) => other.some((theirs) => resolution(theirs) === resolution(one) && within(one, theirs))));
|
|
31
|
+
}
|
|
32
|
+
export function contracts(regions, touched) {
|
|
33
|
+
return !regions.some((one) => touched.some((p) => within(p, one)));
|
|
34
|
+
}
|
|
35
|
+
export function key(regions) {
|
|
36
|
+
return [...new Set(regions.map((one) => one.at.join('/')))].sort().join('|');
|
|
37
|
+
}
|
|
38
|
+
const inside = (one, of) => one >= of.lo && one <= of.hi;
|
|
39
|
+
export function foldRegion(places, where, f) {
|
|
40
|
+
const gathered = new Map();
|
|
41
|
+
for (const place of places) {
|
|
42
|
+
if (!within(place, where))
|
|
43
|
+
continue;
|
|
44
|
+
const at = place.at.join('/');
|
|
45
|
+
gathered.set(at, [...(gathered.get(at) ?? []), place]);
|
|
46
|
+
}
|
|
47
|
+
return [...gathered].sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0)).map(([at, met]) => ({ at, value: f(met) }));
|
|
48
|
+
}
|
|
49
|
+
export function covers(met, of) {
|
|
50
|
+
return met.every((place) => of.where.some((one) => within(place, one))
|
|
51
|
+
&& inside(resolution(place), of.steps)
|
|
52
|
+
&& inside(place.epoch, of.when));
|
|
53
|
+
}
|
|
54
|
+
export function outranks(met, named, order) {
|
|
55
|
+
const matched = named.filter(([step]) => met.some((place) => passes(place, step))).map(([, kind]) => kind);
|
|
56
|
+
return order.find((kind) => matched.includes(kind)) ?? null;
|
|
57
|
+
}
|
|
58
|
+
export function answers(met, where) {
|
|
59
|
+
return met.length > 0 && met.every((place) => where.some((one) => within(place, one)));
|
|
60
|
+
}
|
|
61
|
+
export function verified(met, green) {
|
|
62
|
+
return met.some((place) => green(place));
|
|
63
|
+
}
|
|
64
|
+
export function retracted(met, by) {
|
|
65
|
+
return met.filter((place) => by.some((one) => within(place, one)));
|
|
66
|
+
}
|
|
67
|
+
export function size(at, steps) {
|
|
68
|
+
return new Set(at.map((name) => {
|
|
69
|
+
const place = point(name);
|
|
70
|
+
return (steps === undefined ? place : coarsen(place, steps)).at.join('/');
|
|
71
|
+
})).size;
|
|
72
|
+
}
|
|
73
|
+
export function sufficientResolution(finest, verdict, same = Object.is) {
|
|
74
|
+
const whole = verdict(finest);
|
|
75
|
+
for (let steps = 1; steps < finest; steps += 1)
|
|
76
|
+
if (same(verdict(steps), whole))
|
|
77
|
+
return steps;
|
|
78
|
+
return finest;
|
|
79
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Point } from './field.ts';
|
|
2
|
+
import type { Level, Scale, Unit } from '../lattice/types.ts';
|
|
3
|
+
export interface Asked {
|
|
4
|
+
readonly at: Point;
|
|
5
|
+
readonly bound: Unit;
|
|
6
|
+
readonly dependents: readonly string[];
|
|
7
|
+
readonly closers: readonly {
|
|
8
|
+
readonly by: string;
|
|
9
|
+
readonly cost: number;
|
|
10
|
+
}[];
|
|
11
|
+
}
|
|
12
|
+
export interface Open {
|
|
13
|
+
readonly at: string;
|
|
14
|
+
readonly resolution: number;
|
|
15
|
+
readonly premium: number;
|
|
16
|
+
readonly dependents: number;
|
|
17
|
+
readonly closer: string | null;
|
|
18
|
+
readonly cost: number | null;
|
|
19
|
+
}
|
|
20
|
+
export declare function frontier(c: Scale, value: (level: Level) => number, asked: readonly Asked[]): readonly Open[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { origins } from "./encounter.js";
|
|
2
|
+
import { resolution } from "./field.js";
|
|
3
|
+
import { premium } from "../lattice/price/premium.js";
|
|
4
|
+
export function frontier(c, value, asked) {
|
|
5
|
+
return asked.filter((one) => origins(one.at) === 0).map((one) => {
|
|
6
|
+
const cheapest = [...one.closers].sort((a, b) => (a.cost === b.cost ? (a.by < b.by ? -1 : 1) : a.cost - b.cost))[0];
|
|
7
|
+
return {
|
|
8
|
+
at: one.at.at.join('/'),
|
|
9
|
+
resolution: resolution(one.at),
|
|
10
|
+
premium: premium(c, value, c.rank(one.bound.floor), c.rank(one.bound.ceiling)),
|
|
11
|
+
dependents: one.dependents.length,
|
|
12
|
+
closer: cheapest?.by ?? null,
|
|
13
|
+
cost: cheapest?.cost ?? null,
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Level, Scale, State, Unit } from '../lattice/types.ts';
|
|
2
|
+
import type { Matrix } from '../debit/vector-move.ts';
|
|
3
|
+
import type { Point } from './field.ts';
|
|
4
|
+
export declare function declarationOf(c: Scale, place: Point): {
|
|
5
|
+
readonly demand: Level;
|
|
6
|
+
readonly limit: Level;
|
|
7
|
+
};
|
|
8
|
+
export declare function unitOf(c: Scale, place: Point): Unit;
|
|
9
|
+
export declare function stateOf(c: Scale, place: Point): State;
|
|
10
|
+
export declare function registerOf(c: Scale, place: Point): readonly [string, State][];
|
|
11
|
+
export declare function premiumOf(c: Scale, value: (level: Level) => number, place: Point): number;
|
|
12
|
+
export declare function degenerate(c: Scale, value: (level: Level) => number): boolean;
|
|
13
|
+
export declare function withdrawsExactly(c: Scale): boolean;
|
|
14
|
+
export declare function movesOf(c: Scale, before: Point, after: Point): Matrix;
|