eyeling 1.16.2 → 1.16.4

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.
Files changed (51) hide show
  1. package/HANDBOOK.md +4 -0
  2. package/README.md +0 -1
  3. package/examples/ershov-mixed-computation.n3 +106 -0
  4. package/examples/output/ershov-mixed-computation.n3 +15 -0
  5. package/eyeling.js +510 -263
  6. package/lib/cli.js +22 -12
  7. package/lib/engine.js +488 -251
  8. package/package.json +2 -3
  9. package/arctifacts/README.md +0 -59
  10. package/arctifacts/ackermann.html +0 -678
  11. package/arctifacts/auroracare.html +0 -1297
  12. package/arctifacts/bike-trip.html +0 -752
  13. package/arctifacts/binomial-theorem.html +0 -631
  14. package/arctifacts/bmi.html +0 -511
  15. package/arctifacts/building-performance.html +0 -750
  16. package/arctifacts/clinical-care.html +0 -726
  17. package/arctifacts/collatz.html +0 -403
  18. package/arctifacts/complex.html +0 -321
  19. package/arctifacts/control-system.html +0 -482
  20. package/arctifacts/delfour.html +0 -849
  21. package/arctifacts/earthquake-epicenter.html +0 -982
  22. package/arctifacts/eco-route.html +0 -662
  23. package/arctifacts/euclid-infinitude.html +0 -564
  24. package/arctifacts/euler-identity.html +0 -667
  25. package/arctifacts/exoplanet-transit.html +0 -1000
  26. package/arctifacts/faltings-theorem.html +0 -1046
  27. package/arctifacts/fibonacci.html +0 -299
  28. package/arctifacts/fundamental-theorem-arithmetic.html +0 -398
  29. package/arctifacts/godel-numbering.html +0 -743
  30. package/arctifacts/gps-bike.html +0 -759
  31. package/arctifacts/gps-clinical-bench.html +0 -792
  32. package/arctifacts/graph-french.html +0 -449
  33. package/arctifacts/grass-molecular.html +0 -592
  34. package/arctifacts/group-theory.html +0 -740
  35. package/arctifacts/health-info.html +0 -833
  36. package/arctifacts/kaprekar-constant.html +0 -576
  37. package/arctifacts/lee.html +0 -805
  38. package/arctifacts/linked-lists.html +0 -502
  39. package/arctifacts/lldm.html +0 -612
  40. package/arctifacts/matrix-multiplication.html +0 -502
  41. package/arctifacts/matrix.html +0 -651
  42. package/arctifacts/newton-raphson.html +0 -944
  43. package/arctifacts/peano-factorial.html +0 -456
  44. package/arctifacts/pi.html +0 -363
  45. package/arctifacts/polynomial.html +0 -646
  46. package/arctifacts/prime.html +0 -366
  47. package/arctifacts/pythagorean-theorem.html +0 -468
  48. package/arctifacts/rest-path.html +0 -469
  49. package/arctifacts/roots-of-unity.html +0 -363
  50. package/arctifacts/turing.html +0 -409
  51. package/arctifacts/wind-turbines.html +0 -726
@@ -1,449 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1" />
6
- <title>Graph reachability (French cities)</title>
7
- <style>
8
- :root {
9
- --bg: #ffffff;
10
- --ink: #111827;
11
- --muted: #6b7280;
12
- --panel: #f8fafc;
13
- --border: #e5e7eb;
14
- --accent: #0ea5e9;
15
- --good: #16a34a;
16
- --cyan: #06b6d4;
17
- --indigo: #6366f1;
18
- --warn: #dc2626;
19
- --mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;
20
- --ui:
21
- system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', 'Apple Color Emoji',
22
- 'Segoe UI Emoji';
23
- }
24
- html,
25
- body {
26
- height: 100%;
27
- }
28
- body {
29
- margin: 0;
30
- background: var(--bg);
31
- color: var(--ink);
32
- font: 15px/1.55 var(--ui);
33
- }
34
- .wrap {
35
- max-width: 980px;
36
- margin: 28px auto;
37
- padding: 0 14px;
38
- }
39
- header {
40
- display: flex;
41
- align-items: center;
42
- justify-content: space-between;
43
- margin-bottom: 14px;
44
- }
45
- h1 {
46
- font-size: 20px;
47
- margin: 0;
48
- letter-spacing: 0.2px;
49
- }
50
- .pill {
51
- display: inline-flex;
52
- align-items: center;
53
- gap: 8px;
54
- padding: 6px 10px;
55
- border: 1px solid var(--border);
56
- border-radius: 999px;
57
- color: var(--muted);
58
- background: #fff;
59
- }
60
- .card {
61
- width: 100%;
62
- background: var(--panel);
63
- border: 1px solid var(--border);
64
- border-radius: 14px;
65
- overflow: hidden;
66
- margin-bottom: 14px;
67
- }
68
- .head {
69
- display: flex;
70
- align-items: center;
71
- justify-content: space-between;
72
- padding: 10px 12px;
73
- border-bottom: 1px solid var(--border);
74
- }
75
- .head h2 {
76
- font-size: 13px;
77
- text-transform: uppercase;
78
- letter-spacing: 0.08em;
79
- color: var(--muted);
80
- margin: 0;
81
- }
82
- .body {
83
- padding: 12px;
84
- }
85
- pre {
86
- white-space: pre-wrap;
87
- background: #fff;
88
- border: 1px solid var(--border);
89
- border-radius: 10px;
90
- padding: 12px;
91
- overflow: auto;
92
- font-family: var(--mono);
93
- font-size: 13px;
94
- margin: 0;
95
- }
96
- button {
97
- all: unset;
98
- background: #fff;
99
- border: 1px solid var(--border);
100
- padding: 9px 13px;
101
- border-radius: 10px;
102
- cursor: pointer;
103
- }
104
- button:hover {
105
- border-color: #cbd5e1;
106
- }
107
- .warn {
108
- color: var(--warn);
109
- }
110
- .accent {
111
- color: var(--accent);
112
- }
113
- .btns {
114
- display: flex;
115
- gap: 8px;
116
- flex-wrap: wrap;
117
- }
118
- .kv {
119
- font-family: var(--mono);
120
- background: #fff;
121
- border: 1px solid var(--border);
122
- border-radius: 10px;
123
- padding: 10px;
124
- font-size: 13px;
125
- }
126
- .muted {
127
- color: var(--muted);
128
- }
129
-
130
- /* ARC boxes with thick colored left borders */
131
- .arcbox {
132
- background: #fff;
133
- border: 1px solid var(--border);
134
- border-radius: 12px;
135
- padding: 10px;
136
- margin: 10px 0;
137
- }
138
- .arcbox.answer {
139
- border-left: 10px solid var(--good);
140
- }
141
- .arcbox.reason {
142
- border-left: 10px solid var(--cyan);
143
- }
144
- .arcbox.check {
145
- border-left: 10px solid var(--indigo);
146
- }
147
- .arclabel {
148
- font-size: 11px;
149
- text-transform: uppercase;
150
- letter-spacing: 0.08em;
151
- color: var(--muted);
152
- margin-bottom: 6px;
153
- }
154
- </style>
155
- </head>
156
- <body>
157
- <div class="wrap">
158
- <header>
159
- <h1>Graph reachability</h1>
160
- <div class="pill" id="status">Ready</div>
161
- </header>
162
-
163
- <div class="card">
164
- <div class="body">
165
- <p>
166
- <strong>What this is?</strong> A self‑contained, browser‑only demo that answers the query
167
- <code>?- path(X, nantes)</code> over a small directed graph of French cities using two Horn clauses:
168
- </p>
169
- <pre class="kv">
170
- C1: path(U,V) :- oneway(U,V).
171
- C2: path(U,V) :- oneway(U,Z), path(Z,V).</pre
172
- >
173
- <p class="muted">
174
- Answer lists every city X that reaches <code>nantes</code> with one shortest chain. Reason shows a
175
- backward‑chaining proof for <code>X = paris</code>. Check validates the results by independent forward
176
- search and shortest‑path minimality.
177
- </p>
178
- </div>
179
- </div>
180
-
181
- <!-- Vertical layout: all cards stacked -->
182
- <div class="card">
183
- <div class="head"><h2>Graph (fixed)</h2></div>
184
- <div class="body">
185
- <pre class="kv" id="graphBox"></pre>
186
- <div class="btns" style="margin-top: 10px">
187
- <button onclick="run()">▶ Run</button>
188
- <button onclick="copyARC()">Copy ARC</button>
189
- <button onclick="downloadTxt()">⬇ Export .txt</button>
190
- </div>
191
- </div>
192
- </div>
193
-
194
- <div class="card">
195
- <div class="head"><h2>Query & Goal</h2></div>
196
- <div class="body">
197
- <pre class="kv" id="caseBox"></pre>
198
- </div>
199
- </div>
200
-
201
- <div class="card">
202
- <div class="head">
203
- <h2>ARC Output</h2>
204
- <div class="muted">Cards with left borders</div>
205
- </div>
206
- <div class="body">
207
- <div class="arcbox answer">
208
- <div class="arclabel">Answer</div>
209
- <pre id="ans">(no run yet)</pre>
210
- </div>
211
- <div class="arcbox reason">
212
- <div class="arclabel">Reason why</div>
213
- <pre id="why">(no run yet)</pre>
214
- </div>
215
- <div class="arcbox check">
216
- <div class="arclabel">Check (harness)</div>
217
- <pre id="chk">(no run yet)</pre>
218
- </div>
219
- </div>
220
- </div>
221
- </div>
222
-
223
- <script>
224
- // ----- 0) Data -----
225
- const EDGES = [
226
- ['paris', 'orleans'],
227
- ['paris', 'chartres'],
228
- ['paris', 'amiens'],
229
- ['orleans', 'blois'],
230
- ['orleans', 'bourges'],
231
- ['blois', 'tours'],
232
- ['chartres', 'lemans'],
233
- ['lemans', 'angers'],
234
- ['lemans', 'tours'],
235
- ['angers', 'nantes'],
236
- ];
237
- const GOAL = 'nantes';
238
-
239
- // Build succs, preds, nodes
240
- const oneway = new Set(EDGES.map((e) => JSON.stringify(e)));
241
- const succs = new Map();
242
- const preds = new Map();
243
- const NODES = new Set();
244
- for (const [u, v] of EDGES) {
245
- if (!succs.has(u)) succs.set(u, new Set());
246
- succs.get(u).add(v);
247
- if (!preds.has(v)) preds.set(v, new Set());
248
- preds.get(v).add(u);
249
- NODES.add(u);
250
- NODES.add(v);
251
- }
252
-
253
- // ----- 1) Reverse BFS from goal -----
254
- function bfsParentsAndDist(goal) {
255
- const parent = {}; // parent[u] = next hop towards goal
256
- const dist = { [goal]: 0 };
257
- const dq = [goal];
258
- let head = 0;
259
- while (head < dq.length) {
260
- const v = dq[head++];
261
- const Ps = [...(preds.get(v) || [])].sort(); // deterministic
262
- for (const u of Ps) {
263
- if (!(u in dist)) {
264
- dist[u] = dist[v] + 1;
265
- parent[u] = v;
266
- dq.push(u);
267
- }
268
- }
269
- }
270
- return { parent, dist };
271
- }
272
- const { parent: PARENT, dist: DIST } = bfsParentsAndDist(GOAL);
273
- function shortestPath(src, goal) {
274
- const chain = [src];
275
- while (chain[chain.length - 1] !== goal) {
276
- const cur = chain[chain.length - 1];
277
- chain.push(PARENT[cur]);
278
- }
279
- return chain;
280
- }
281
-
282
- // ----- 2) Tiny backward chainer (trace only) -----
283
- function bc_path(u, v, depth, seenEdges, stepCounter) {
284
- const indent = ' '.repeat(depth);
285
- logWhy(`${indent}Step ${String(stepCounter()).padStart(2, '0')}: prove path(${u}, ${v})`);
286
- // C1
287
- if (oneway.has(JSON.stringify([u, v]))) {
288
- logWhy(`${indent} ✓ by fact oneway(${u}, ${v})`);
289
- return true;
290
- }
291
- // C2
292
- const succ = [...(succs.get(u) || [])].sort();
293
- for (const z of succ) {
294
- if (seenEdges.has(u + '→' + z)) continue;
295
- logWhy(`${indent} → try oneway(${u}, ${z}), then prove path(${z}, ${v})`);
296
- const ok = bc_path(z, v, depth + 1, new Set([...seenEdges, u + '→' + z]), stepCounter);
297
- if (ok) return true;
298
- }
299
- return false;
300
- }
301
-
302
- // ----- 3) ARC writers -----
303
- function setText(id, s) {
304
- const el = document.getElementById(id);
305
- if (el) el.textContent = s;
306
- }
307
- function status(msg, warn = false) {
308
- const el = document.getElementById('status');
309
- if (!el) return;
310
- el.textContent = msg;
311
- el.classList.toggle('warn', !!warn);
312
- }
313
- let WHY_BUFFER = [];
314
- function logWhy(line) {
315
- WHY_BUFFER.push(line);
316
- }
317
-
318
- function run() {
319
- WHY_BUFFER = [];
320
- // Boxes
321
- const Gtxt = EDGES.map(([u, v]) => `oneway(${u}, ${v}).`).join('\n');
322
- setText('graphBox', Gtxt);
323
- setText(
324
- 'caseBox',
325
- `Query : ?- path(X, ${GOAL})
326
- Goal : ${GOAL}
327
- Rules : C1, C2 (see above)`,
328
- );
329
-
330
- // Answer
331
- let A = 'Answer\n======\n';
332
- A += `Query: ?- path(X, ${GOAL})\n\n`;
333
- const solutions = Object.keys(PARENT).sort();
334
- if (!solutions.length) {
335
- A += 'No solutions.';
336
- } else {
337
- A += 'All solutions (with one shortest chain each):\n';
338
- for (const src of solutions) {
339
- const chain = shortestPath(src, GOAL);
340
- const hops = chain.length - 1;
341
- A += ` X = ${src.padEnd(9, ' ')} path: ${chain.join(' → ')} (hops = ${hops})\n`;
342
- }
343
- A += `\nTotal solutions: ${solutions.length}`;
344
- }
345
- setText('ans', A);
346
-
347
- // Reason
348
- let R = '\nReason why\n==========\n';
349
- R += 'We use two Horn clauses:\n';
350
- R += ' C1 path(U,V) :- oneway(U,V).\n';
351
- R += ' C2 path(U,V) :- oneway(U,Z), path(Z,V).\n';
352
- R += 'Backward-chaining tries C1 (a fact) or applies C2 by choosing a\n';
353
- R += 'successor Z of U and recursively proving path(Z,V).\n\n';
354
- const demo_src = 'paris';
355
- if (!(demo_src in PARENT)) {
356
- R += `(Demo: ${demo_src} does not reach ${GOAL} in this graph.)`;
357
- } else {
358
- R += `Demo proof for X = ${demo_src}:\n`;
359
- let step = 0;
360
- const stepper = () => ++step;
361
- const ok = bc_path(demo_src, GOAL, 0, new Set(), stepper);
362
- R += WHY_BUFFER.join('\n') + '\n';
363
- R += ok ? ' ✔ PROVED\n' : ' ✗ NOT PROVED\n';
364
- R += `Shortest chain: ${shortestPath(demo_src, GOAL).join(' → ')}`;
365
- }
366
- setText('why', R);
367
-
368
- // Check
369
- let C = '\nCheck (harness)\n===============\n';
370
- // A) independent forward search from each node
371
- function reaches_goal_forward(u) {
372
- if (u === GOAL) return false; // by convention exclude the goal as X
373
- const seen = new Set([u]);
374
- const dq = [u];
375
- let head = 0;
376
- while (head < dq.length) {
377
- const x = dq[head++];
378
- for (const y of succs.get(x) || []) {
379
- if (y === GOAL) return true;
380
- if (!seen.has(y)) {
381
- seen.add(y);
382
- dq.push(y);
383
- }
384
- }
385
- }
386
- return false;
387
- }
388
- const forward_reach = [...NODES].filter(reaches_goal_forward).sort();
389
- const solver_reach = Object.keys(PARENT).sort();
390
- const same = JSON.stringify(forward_reach) === JSON.stringify(solver_reach);
391
- C += `Forward search nodes == solver nodes ? ${same}\n`;
392
- if (!same) {
393
- C += ` forward: ${JSON.stringify(forward_reach)}\n`;
394
- C += ` solver : ${JSON.stringify(solver_reach)}\n`;
395
- }
396
- // B) Validate each shortest path
397
- function is_valid_chain(chain) {
398
- for (let i = 0; i < chain.length - 1; i++)
399
- if (!oneway.has(JSON.stringify([chain[i], chain[i + 1]]))) return false;
400
- return true;
401
- }
402
- let all_valid = true,
403
- all_minimal = true;
404
- for (const src of solver_reach) {
405
- const chain = shortestPath(src, GOAL);
406
- if (!is_valid_chain(chain)) {
407
- all_valid = false;
408
- }
409
- if (chain.length - 1 !== DIST[src]) {
410
- all_minimal = false;
411
- }
412
- }
413
- C += `All chains follow oneway edges? ${all_valid}\n`;
414
- C += `All chains are hop-minimal? ${all_minimal}`;
415
- setText('chk', C);
416
-
417
- status('Done');
418
- }
419
-
420
- function copyARC() {
421
- const txt = [
422
- document.getElementById('ans').textContent,
423
- document.getElementById('why').textContent,
424
- document.getElementById('chk').textContent,
425
- ].join('\n\n');
426
- navigator.clipboard?.writeText(txt).catch(() => {});
427
- }
428
- function downloadTxt() {
429
- const blob = new Blob(
430
- [
431
- document.getElementById('ans').textContent,
432
- '\n\n',
433
- document.getElementById('why').textContent,
434
- '\n\n',
435
- document.getElementById('chk').textContent,
436
- ],
437
- { type: 'text/plain' },
438
- );
439
- const a = document.createElement('a');
440
- a.href = URL.createObjectURL(blob);
441
- a.download = 'graph_french_output.txt';
442
- a.click();
443
- }
444
-
445
- // auto-run
446
- window.addEventListener('DOMContentLoaded', run);
447
- </script>
448
- </body>
449
- </html>