gdp-wired 0.18.0 → 0.19.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/dist/core/cyclic.d.ts +90 -6
- package/dist/core/cyclic.js +668 -27
- package/dist/core/dsl.js +25 -9
- package/dist/core/translate.d.ts +30 -0
- package/dist/core/translate.js +572 -0
- package/dist/kernel/prove.d.ts +13 -0
- package/dist/kernel/prove.js +112 -10
- package/dist/lean-kernel/emit.d.ts +34 -0
- package/dist/lean-kernel/emit.js +406 -50
- package/dist/lean-kernel/library.js +2 -1
- package/package.json +1 -1
package/dist/kernel/prove.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { add, k, refuteFast, scale, solve, sub, v } from "../core/solver.js";
|
|
2
2
|
import { checkRefutation } from "../core/check.js";
|
|
3
|
-
import {
|
|
3
|
+
import { allowNode, certCyclic, certMs, certOn, certSearch, closingInsts, crossCyclic, cyclicOn, cycLog, hasQuantified, machineNodes, proveCyclic, qflagNodes, reqTS, searchedStepNodes, skMachine, timedKind, withWitness, translatedProof, uncoveredWhy } from "../core/cyclic.js";
|
|
4
4
|
import { assumed, atomOf, boundOf, canon, canonFlip, columnTerm, decided, factorsOf, isCell, isMonomial, stepZone, check, checkLaws, checkStepLaws, historyMachine, leafConstraints, leafConstraintsReusing, reusing, linear, livenessHelpful, livenessParts, obligations, plainKey, progressObligations, stepLawObligations, trueC, truth, unreachable, witnessesOf, withProducts } from "./kernel.js";
|
|
5
5
|
// The atoms the path leaves open, in evaluation order: deciding any of them makes progress.
|
|
6
6
|
function openE(e, path, out) {
|
|
@@ -1362,15 +1362,54 @@ function proveLawsAsGiven(m, laws) {
|
|
|
1362
1362
|
focus: [...(law.forall ? [`${law.forall}#`] : []), ...(law.keys ?? [])],
|
|
1363
1363
|
});
|
|
1364
1364
|
});
|
|
1365
|
-
|
|
1365
|
+
// (GDP_CERT=cyclic: a covered machine's certificate is its cyclic proof, core/cyclic.ts's certCyclic; the usual trees
|
|
1366
|
+
// are its input, not checked again)
|
|
1367
|
+
// (what no instance covers, read only where a cyclic mode is on: the usual route's own proofs, inferLaws' trial ones
|
|
1368
|
+
// among them, do nothing more than before)
|
|
1369
|
+
// A machine with a history: its laws are its plain machine's (historyMachine; the record goals leaf goals beside them).
|
|
1370
|
+
const modes = cyclicOn() || certOn(), hist = modes && m.history ? historyMachine(m) : undefined, mc = hist ? hist.machine : m;
|
|
1371
|
+
const why = modes ? uncoveredWhy(mc, laws) : undefined;
|
|
1372
|
+
// (flags that hold at every key: searched, where GDP_CERT_SEARCH=1)
|
|
1373
|
+
const q = why === 'a flag at every key' && certOn() && certSearch(), cert = certOn() && (!why || q);
|
|
1374
|
+
usualCheck.on = !cert || q;
|
|
1375
|
+
const t0 = performance.now(), out = (() => { try {
|
|
1376
|
+
return proveThinned(m, laws, { ...instances });
|
|
1377
|
+
}
|
|
1378
|
+
finally {
|
|
1379
|
+
usualCheck.on = true;
|
|
1380
|
+
} })(), usualMs = performance.now() - t0;
|
|
1381
|
+
if (out.proof)
|
|
1382
|
+
usualProof.last = { m, laws, proof: out.proof };
|
|
1383
|
+
const inst = out.proof?.instances ?? instances;
|
|
1384
|
+
const searched = () => { const { facts, specs } = q ? qflagNodes(mc, laws, inst) : machineNodes(mc, laws, inst); return proveCyclic(facts, specs); };
|
|
1385
|
+
const translated = !q && out.proof ? ((st) => translatedProof(() => JSON.stringify(['machine', mc, laws, inst]), () => timedKind('instance', 0, () => machineNodes(mc, laws, inst, out.proof, st)), st)) : undefined;
|
|
1366
1386
|
if (cyclicOn()) {
|
|
1367
|
-
if (
|
|
1368
|
-
crossCyclic('machine', m.name, out.proven && out.checked,
|
|
1387
|
+
if (!why)
|
|
1388
|
+
crossCyclic('machine', m.name, out.proven && out.checked, searched, usualMs, translated);
|
|
1369
1389
|
else
|
|
1370
|
-
|
|
1390
|
+
cycLog({ kind: 'machine', name: m.name, usual: out.proven && out.checked, uncovered: true, why });
|
|
1391
|
+
}
|
|
1392
|
+
if (cert && out.proven && out.proof) {
|
|
1393
|
+
const until = performance.now() + certMs(), c = q ? withDeadline(until, () => certCyclic('machine', m.name, undefined, searched, usualMs)) : certCyclic('machine', m.name, translated, searched, usualMs);
|
|
1394
|
+
if (q && !c.checked)
|
|
1395
|
+
uncovered('machine', m.name, `${why}: no cyclic proof found${performance.now() > until ? ` within ${certMs()} ms` : ''}`);
|
|
1396
|
+
else {
|
|
1397
|
+
// (a history's record goals checked as they are: leaf goals)
|
|
1398
|
+
const records = !hist || hist.goals.every(g => out.proof.trees[g.name] !== undefined && check(g, out.proof.trees[g.name]));
|
|
1399
|
+
out.checked = c.checked && records;
|
|
1400
|
+
Object.assign(out.proof, { cyclic: c.proof });
|
|
1401
|
+
}
|
|
1371
1402
|
}
|
|
1403
|
+
else if (certOn() && why && out.proven)
|
|
1404
|
+
cycLog({ kind: 'machine', name: m.name, cert: true, uncovered: true, why });
|
|
1372
1405
|
return out;
|
|
1373
1406
|
}
|
|
1407
|
+
// A proof of a kind no cyclic instance covers, counted (`cyclic: {..., uncovered: true}`).
|
|
1408
|
+
const uncovered = (kind, name, why) => cycLog({ kind, name, uncovered: true, why });
|
|
1409
|
+
// Whether the usual proof's trees are checked (off while GDP_CERT=cyclic makes the certificate a cyclic proof).
|
|
1410
|
+
export const usualCheck = { on: true };
|
|
1411
|
+
// The last machine proof made (core/dsl.ts's recurrences read their machine's, to translate it: core/cyclic.ts).
|
|
1412
|
+
export const usualProof = {};
|
|
1374
1413
|
// Each law with its instances thinned (`triggered`) where that proves it, else with all of them.
|
|
1375
1414
|
function proveThinned(m, laws, instances) {
|
|
1376
1415
|
const trees = {}, fulls = { ...instances };
|
|
@@ -1416,7 +1455,7 @@ function proveThinned(m, laws, instances) {
|
|
|
1416
1455
|
leaves += countLeaves(out.tree);
|
|
1417
1456
|
}
|
|
1418
1457
|
const proof = { instances, trees };
|
|
1419
|
-
return { proven: true, nodes, leaves, checked: checkLaws(m, laws, proof), proof };
|
|
1458
|
+
return { proven: true, nodes, leaves, checked: !usualCheck.on || checkLaws(m, laws, proof), proof };
|
|
1420
1459
|
}
|
|
1421
1460
|
// Every goal of the laws with these instances.
|
|
1422
1461
|
function proveWith(m, laws, instances) {
|
|
@@ -1431,7 +1470,7 @@ function proveWith(m, laws, instances) {
|
|
|
1431
1470
|
leaves += countLeaves(out.tree);
|
|
1432
1471
|
}
|
|
1433
1472
|
const proof = { instances, trees };
|
|
1434
|
-
return { proven: true, nodes, leaves, checked: checkLaws(m, laws, proof), proof };
|
|
1473
|
+
return { proven: true, nodes, leaves, checked: !usualCheck.on || checkLaws(m, laws, proof), proof };
|
|
1435
1474
|
}
|
|
1436
1475
|
export function proveStepLaws(m, given, stepLaws) {
|
|
1437
1476
|
const base = proveLaws(m, given);
|
|
@@ -1451,6 +1490,7 @@ export function proveStepLaws(m, given, stepLaws) {
|
|
|
1451
1490
|
function proveStepLawsAsGiven(m, laws, stepLaws, base) {
|
|
1452
1491
|
if (!base.proof)
|
|
1453
1492
|
return { proven: false, nodes: base.nodes, leaves: base.leaves, checked: false };
|
|
1493
|
+
const t0 = performance.now();
|
|
1454
1494
|
const plain = m.history ? historyMachine(m).machine : m;
|
|
1455
1495
|
// Each step law its own instances, from its own goal: the keys the step and the laws read, and its own (a k-step
|
|
1456
1496
|
// law's later frames read keys no other step law has); where positions shift or a law is about several keys, the
|
|
@@ -1505,12 +1545,44 @@ function proveStepLawsAsGiven(m, laws, stepLaws, base) {
|
|
|
1505
1545
|
leaves += countLeaves(out.tree);
|
|
1506
1546
|
}
|
|
1507
1547
|
const proof = { laws: base.proof, instances, ...(Object.keys(perStep).length ? { perStep } : {}), trees };
|
|
1508
|
-
|
|
1548
|
+
const out = { proven: true, nodes, leaves, checked: checkStepLaws(m, laws, stepLaws, proof), proof };
|
|
1549
|
+
// Step laws of a machine the cyclic instances cover (one step, or several over no map) are translated with the laws
|
|
1550
|
+
// (core/cyclic.ts); the rest are counted as no instance's.
|
|
1551
|
+
if (!cyclicOn() && !certOn())
|
|
1552
|
+
return out;
|
|
1553
|
+
// (a machine with a history: its plain machine's; flags at every key and k-step laws over a map searched, where
|
|
1554
|
+
// GDP_CERT_SEARCH=1)
|
|
1555
|
+
const why = uncoveredWhy(plain, laws), one = stepLaws.filter(sl => (sl.steps ?? 1) === 1 || (!Object.keys(plain.maps ?? {}).length && !plain.inputMaps?.length));
|
|
1556
|
+
if (!why && one.length && out.checked) {
|
|
1557
|
+
const steps = one.map(sl => { const inst = perStep[sl.name] ?? instances, goal = stepLawObligations(m, laws, inst, sl)[0]; return { sl, inst, goal, tree: trees[goal.name] }; });
|
|
1558
|
+
const translated = (st) => translatedProof(() => JSON.stringify(['steps', plain, laws, base.proof.instances, steps.map(x => [x.sl, x.inst])]), reused => timedKind('instance', 0, () => machineNodes(plain, laws, base.proof.instances, { trees: base.proof.trees, steps, lawsMade: reused }, st)), st, () => JSON.stringify(['machine', plain, laws, base.proof.instances]));
|
|
1559
|
+
const usualMs = performance.now() - t0;
|
|
1560
|
+
if (cyclicOn())
|
|
1561
|
+
crossCyclic('step law', m.name, true, undefined, usualMs, translated);
|
|
1562
|
+
if (certOn())
|
|
1563
|
+
out.checked = certCyclic('step law', m.name, translated, undefined, usualMs).checked;
|
|
1564
|
+
}
|
|
1565
|
+
const rest = stepLaws.filter(sl => why || !one.includes(sl));
|
|
1566
|
+
if (certOn() && certSearch() && out.checked && rest.length && (!why || why === 'a flag at every key')) {
|
|
1567
|
+
// The rest searched: the laws' nodes (searched), each step law's node (core/cyclic.ts's stepLawNodes).
|
|
1568
|
+
const searchedSteps = () => {
|
|
1569
|
+
const b = why ? qflagNodes(plain, laws, base.proof.instances) : machineNodes(plain, laws, base.proof.instances);
|
|
1570
|
+
return proveCyclic(b.facts, [...b.specs, ...searchedStepNodes(plain, laws, rest.map(sl => ({ law: sl, instances: perStep[sl.name] ?? instances })), b.facts, b.specs)]);
|
|
1571
|
+
};
|
|
1572
|
+
const until = performance.now() + certMs(), c = withDeadline(until, () => certCyclic('step law', m.name, undefined, searchedSteps, performance.now() - t0));
|
|
1573
|
+
const none = `no cyclic proof found${performance.now() > until ? ` within ${certMs()} ms` : ''}`;
|
|
1574
|
+
for (const sl of c.checked ? [] : rest)
|
|
1575
|
+
uncovered((sl.steps ?? 1) > 1 ? 'k-step law' : 'step law', m.name, `${why ?? `${sl.steps} steps over a map`}: ${none}`);
|
|
1576
|
+
}
|
|
1577
|
+
else if (cyclicOn() || certOn())
|
|
1578
|
+
for (const sl of rest)
|
|
1579
|
+
uncovered((sl.steps ?? 1) > 1 ? 'k-step law' : 'step law', m.name, why ?? `${sl.steps} steps over a map`);
|
|
1580
|
+
return out;
|
|
1509
1581
|
}
|
|
1510
1582
|
// Progress (kernel.ts's progressObligations): the laws proven first, then each goal, the every-key laws assumed at every
|
|
1511
1583
|
// key the goals read a map at.
|
|
1512
1584
|
export function proveProgress(m, laws, p) {
|
|
1513
|
-
const base = proveLaws(m, laws);
|
|
1585
|
+
const t0 = performance.now(), base = proveLaws(m, laws);
|
|
1514
1586
|
if (!base.proven || !base.checked)
|
|
1515
1587
|
return { proven: false, nodes: base.nodes, leaves: base.leaves, ...(base.failed ? { failed: base.failed } : {}), checked: false };
|
|
1516
1588
|
const ls = base.laws ?? laws;
|
|
@@ -1525,12 +1597,42 @@ export function proveProgress(m, laws, p) {
|
|
|
1525
1597
|
nodes += out.nodes;
|
|
1526
1598
|
leaves += countLeaves(out.tree);
|
|
1527
1599
|
}
|
|
1528
|
-
|
|
1600
|
+
const checked = progressObligations(m, ls, instances, p).every(g => check(g, trees[g.name]));
|
|
1601
|
+
// (GDP_CERT=cyclic with GDP_CERT_SEARCH=1: a request allowed whose claim is that alone, over a machine without a history
|
|
1602
|
+
// or carried maps, gets core/cyclic.ts's allowNode after the laws' nodes, BridgeRules.lean's cycAOk: from every
|
|
1603
|
+
// reachable state, every request meeting the region, its terms and the witnesses withWitness finds is allowed)
|
|
1604
|
+
const alone = JSON.stringify(p.then) === JSON.stringify(trueC) && !m.history && !m.inputMaps?.length && m.assume !== undefined;
|
|
1605
|
+
if (certOn() && certSearch() && alone && checked && base.proof) {
|
|
1606
|
+
const until = performance.now() + certMs(), lp = base.proof, q = hasQuantified(m);
|
|
1607
|
+
const allowed = () => {
|
|
1608
|
+
const b = q ? qflagNodes(m, ls, lp.instances) : machineNodes(m, ls, lp.instances, lp);
|
|
1609
|
+
if (b.why || (b.specs[0]?.rank.length ?? 2) < 2)
|
|
1610
|
+
return { proven: false, checked: false, node: m.name, goal: 'allowed', stuck: b.why ?? 'laws ranked by time alone' };
|
|
1611
|
+
let last = { proven: false, checked: false, node: m.name, goal: 'allowed', stuck: 'no witness' };
|
|
1612
|
+
const found = withWitness(m, p.request, wit => {
|
|
1613
|
+
if (performance.now() > until)
|
|
1614
|
+
return undefined;
|
|
1615
|
+
const w = { op: 'and', xs: [p.when, reqTS(Object.entries(p.request)), reqTS(wit)] };
|
|
1616
|
+
const spec = allowNode(skMachine(m), ls, instances, w, b.facts, b.specs, `${m.name}: allowed`, q ? closingInsts(m, b.facts, [instances, ...Object.values(lp.instances)], [{ op: 'var', name: 't$' }], ls) : []);
|
|
1617
|
+
last = proveCyclic(b.facts, [...b.specs, spec]);
|
|
1618
|
+
return last.proven && last.checked ? last : undefined;
|
|
1619
|
+
});
|
|
1620
|
+
return found?.out ?? last;
|
|
1621
|
+
};
|
|
1622
|
+
const c = withDeadline(until, () => certCyclic('progress', m.name, undefined, allowed, performance.now() - t0));
|
|
1623
|
+
if (!c.checked)
|
|
1624
|
+
uncovered('progress', m.name, `a request allowed: no cyclic proof found${performance.now() > until ? ` within ${certMs()} ms` : ''}`);
|
|
1625
|
+
}
|
|
1626
|
+
else if (cyclicOn() || certOn())
|
|
1627
|
+
uncovered('progress', m.name, alone ? 'a request allowed' : 'a request allowed and a claim after it');
|
|
1628
|
+
return { proven: true, nodes, leaves, checked, instances, trees };
|
|
1529
1629
|
}
|
|
1530
1630
|
// Liveness (kernel.ts's livenessParts): its step laws, proven together. The claim needs no more (a run takes the
|
|
1531
1631
|
// request, so it is allowed); but a request never allowed would leave the claim about no run, so where a helpful request
|
|
1532
1632
|
// names every input a client sends and carries no maps, it is proven allowed in its region too.
|
|
1533
1633
|
export function proveLiveness(m, laws, l) {
|
|
1634
|
+
if (cyclicOn() || certOn())
|
|
1635
|
+
uncovered('liveness', m.name, 'a claim about runs that never end');
|
|
1534
1636
|
const { stay, cover, helps } = livenessParts(m, l);
|
|
1535
1637
|
const a = proveStepLaws(m, laws, [stay, cover, ...helps]);
|
|
1536
1638
|
if (!a.proven || !a.checked)
|
|
@@ -101,6 +101,39 @@ export declare function smachineToLean(id: string, given: Machine, laws: Law[],
|
|
|
101
101
|
};
|
|
102
102
|
noFacts?: boolean;
|
|
103
103
|
}): string;
|
|
104
|
+
export declare const cyclicCerts: () => boolean;
|
|
105
|
+
export declare const certReport: {
|
|
106
|
+
cyclic: string[];
|
|
107
|
+
usual: {
|
|
108
|
+
id: string;
|
|
109
|
+
why: string;
|
|
110
|
+
}[];
|
|
111
|
+
translatedSteps: string[];
|
|
112
|
+
};
|
|
113
|
+
export declare function cycMachineToLean(id: string, given: Machine, laws: Law[], opts?: {
|
|
114
|
+
stepLaws?: StepLaw[];
|
|
115
|
+
liveness?: Liveness[];
|
|
116
|
+
simp?: string[];
|
|
117
|
+
free?: string[];
|
|
118
|
+
ghosts?: string[];
|
|
119
|
+
after?: (ix: (name: string) => number) => string;
|
|
120
|
+
loop?: {
|
|
121
|
+
loop: Loop;
|
|
122
|
+
};
|
|
123
|
+
noFacts?: boolean;
|
|
124
|
+
refined?: {
|
|
125
|
+
impl: Machine;
|
|
126
|
+
spec: Machine;
|
|
127
|
+
wit: Record<string, E>;
|
|
128
|
+
stutter: C;
|
|
129
|
+
specPre: number;
|
|
130
|
+
step: StepLaw;
|
|
131
|
+
};
|
|
132
|
+
}): {
|
|
133
|
+
text: string;
|
|
134
|
+
} | {
|
|
135
|
+
why: string;
|
|
136
|
+
};
|
|
104
137
|
type Uses = Record<string, {
|
|
105
138
|
lean?: string;
|
|
106
139
|
recur?: Recurrence;
|
|
@@ -168,6 +201,7 @@ export type LeanItem = {
|
|
|
168
201
|
export declare function toLean(items: LeanItem[], opts?: {
|
|
169
202
|
title?: string;
|
|
170
203
|
native?: boolean;
|
|
204
|
+
cyclic?: boolean;
|
|
171
205
|
}): string;
|
|
172
206
|
export declare function leanProject(file: string, opts?: {
|
|
173
207
|
name?: string;
|