eyeling 1.16.3 → 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.
- package/README.md +0 -1
- package/package.json +2 -3
- package/arctifacts/README.md +0 -59
- package/arctifacts/ackermann.html +0 -678
- package/arctifacts/auroracare.html +0 -1297
- package/arctifacts/bike-trip.html +0 -752
- package/arctifacts/binomial-theorem.html +0 -631
- package/arctifacts/bmi.html +0 -511
- package/arctifacts/building-performance.html +0 -750
- package/arctifacts/clinical-care.html +0 -726
- package/arctifacts/collatz.html +0 -403
- package/arctifacts/complex.html +0 -321
- package/arctifacts/control-system.html +0 -482
- package/arctifacts/delfour.html +0 -849
- package/arctifacts/earthquake-epicenter.html +0 -982
- package/arctifacts/eco-route.html +0 -662
- package/arctifacts/euclid-infinitude.html +0 -564
- package/arctifacts/euler-identity.html +0 -667
- package/arctifacts/exoplanet-transit.html +0 -1000
- package/arctifacts/faltings-theorem.html +0 -1046
- package/arctifacts/fibonacci.html +0 -299
- package/arctifacts/fundamental-theorem-arithmetic.html +0 -398
- package/arctifacts/godel-numbering.html +0 -743
- package/arctifacts/gps-bike.html +0 -759
- package/arctifacts/gps-clinical-bench.html +0 -792
- package/arctifacts/graph-french.html +0 -449
- package/arctifacts/grass-molecular.html +0 -592
- package/arctifacts/group-theory.html +0 -740
- package/arctifacts/health-info.html +0 -833
- package/arctifacts/kaprekar-constant.html +0 -576
- package/arctifacts/lee.html +0 -805
- package/arctifacts/linked-lists.html +0 -502
- package/arctifacts/lldm.html +0 -612
- package/arctifacts/matrix-multiplication.html +0 -502
- package/arctifacts/matrix.html +0 -651
- package/arctifacts/newton-raphson.html +0 -944
- package/arctifacts/peano-factorial.html +0 -456
- package/arctifacts/pi.html +0 -363
- package/arctifacts/polynomial.html +0 -646
- package/arctifacts/prime.html +0 -366
- package/arctifacts/pythagorean-theorem.html +0 -468
- package/arctifacts/rest-path.html +0 -469
- package/arctifacts/roots-of-unity.html +0 -363
- package/arctifacts/turing.html +0 -409
- package/arctifacts/wind-turbines.html +0 -726
|
@@ -1,502 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<title>Linked Lists Term Logic example proved using Resolution</title>
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
-
<style>
|
|
8
|
-
:root {
|
|
9
|
-
--bg: #f7f8fb;
|
|
10
|
-
--card: #ffffff;
|
|
11
|
-
--ink: #0f172a;
|
|
12
|
-
--muted: #4b5563;
|
|
13
|
-
--accent: #2563eb;
|
|
14
|
-
--ok: #059669;
|
|
15
|
-
--bad: #b91c1c;
|
|
16
|
-
--radius: 16px;
|
|
17
|
-
--shadow: 0 10px 22px rgba(2, 6, 23, 0.06), 0 2px 6px rgba(2, 6, 23, 0.06);
|
|
18
|
-
--mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
|
|
19
|
-
--sans:
|
|
20
|
-
Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, 'Helvetica Neue', Arial,
|
|
21
|
-
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
|
|
22
|
-
}
|
|
23
|
-
* {
|
|
24
|
-
box-sizing: border-box;
|
|
25
|
-
}
|
|
26
|
-
body {
|
|
27
|
-
margin: 0;
|
|
28
|
-
background: var(--bg);
|
|
29
|
-
color: var(--ink);
|
|
30
|
-
font: 16px/1.6 var(--sans);
|
|
31
|
-
-webkit-font-smoothing: antialiased;
|
|
32
|
-
}
|
|
33
|
-
.wrap {
|
|
34
|
-
max-width: 980px;
|
|
35
|
-
margin: auto;
|
|
36
|
-
padding: 28px 16px 64px;
|
|
37
|
-
}
|
|
38
|
-
header {
|
|
39
|
-
display: flex;
|
|
40
|
-
flex-direction: column;
|
|
41
|
-
gap: 10px;
|
|
42
|
-
margin-bottom: 22px;
|
|
43
|
-
}
|
|
44
|
-
h1 {
|
|
45
|
-
font-size: clamp(24px, 3vw, 34px);
|
|
46
|
-
line-height: 1.2;
|
|
47
|
-
margin: 0;
|
|
48
|
-
}
|
|
49
|
-
.sub {
|
|
50
|
-
color: var(--muted);
|
|
51
|
-
}
|
|
52
|
-
.pill {
|
|
53
|
-
display: inline-flex;
|
|
54
|
-
align-items: center;
|
|
55
|
-
gap: 8px;
|
|
56
|
-
background: #eef2ff;
|
|
57
|
-
color: #3730a3;
|
|
58
|
-
border-radius: 999px;
|
|
59
|
-
padding: 8px 12px;
|
|
60
|
-
font-weight: 600;
|
|
61
|
-
font-size: 14px;
|
|
62
|
-
width: max-content;
|
|
63
|
-
}
|
|
64
|
-
.grid {
|
|
65
|
-
display: flex;
|
|
66
|
-
flex-direction: column;
|
|
67
|
-
gap: 16px;
|
|
68
|
-
}
|
|
69
|
-
.card {
|
|
70
|
-
background: var(--card);
|
|
71
|
-
border-radius: var(--radius);
|
|
72
|
-
box-shadow: var(--shadow);
|
|
73
|
-
padding: 18px;
|
|
74
|
-
border: 1px solid #eef2f7;
|
|
75
|
-
}
|
|
76
|
-
.kicker {
|
|
77
|
-
font-size: 12px;
|
|
78
|
-
letter-spacing: 0.12em;
|
|
79
|
-
text-transform: uppercase;
|
|
80
|
-
color: #6b7280;
|
|
81
|
-
}
|
|
82
|
-
.muted {
|
|
83
|
-
color: var(--muted);
|
|
84
|
-
}
|
|
85
|
-
.answer {
|
|
86
|
-
font-size: 18px;
|
|
87
|
-
font-weight: 800;
|
|
88
|
-
}
|
|
89
|
-
.ok {
|
|
90
|
-
color: var(--ok);
|
|
91
|
-
}
|
|
92
|
-
.fail {
|
|
93
|
-
color: var(--bad);
|
|
94
|
-
font-weight: 800;
|
|
95
|
-
}
|
|
96
|
-
.result {
|
|
97
|
-
margin-top: 10px;
|
|
98
|
-
padding: 10px 12px;
|
|
99
|
-
border-radius: 10px;
|
|
100
|
-
background: #fafbff;
|
|
101
|
-
border: 1px dashed #d7dbe5;
|
|
102
|
-
}
|
|
103
|
-
code,
|
|
104
|
-
pre {
|
|
105
|
-
font-family: var(--mono);
|
|
106
|
-
}
|
|
107
|
-
/* Your requested pre style (light) */
|
|
108
|
-
pre {
|
|
109
|
-
background: #fafbff;
|
|
110
|
-
color: #0f172a;
|
|
111
|
-
padding: 14px;
|
|
112
|
-
border-radius: 12px;
|
|
113
|
-
/* wrap long lines inside <pre> */
|
|
114
|
-
white-space: pre-wrap; /* preserve spaces/newlines, but wrap */
|
|
115
|
-
overflow-wrap: anywhere; /* break very long tokens if needed */
|
|
116
|
-
word-break: break-word; /* fallback for older browsers */
|
|
117
|
-
/* avoid the horizontal scrollbar */
|
|
118
|
-
overflow-x: hidden;
|
|
119
|
-
/* keep vertical scrolling if content is very tall (optional) */
|
|
120
|
-
overflow-y: auto;
|
|
121
|
-
max-width: 100%;
|
|
122
|
-
}
|
|
123
|
-
.small {
|
|
124
|
-
font-size: 13px;
|
|
125
|
-
}
|
|
126
|
-
.mono {
|
|
127
|
-
font-family: var(--mono);
|
|
128
|
-
}
|
|
129
|
-
textarea.input {
|
|
130
|
-
width: 100%;
|
|
131
|
-
min-height: 84px;
|
|
132
|
-
padding: 10px 12px;
|
|
133
|
-
border-radius: 10px;
|
|
134
|
-
border: 1px solid #d9e1f1;
|
|
135
|
-
background: #fdfefe;
|
|
136
|
-
font-family: var(--mono);
|
|
137
|
-
}
|
|
138
|
-
.badge {
|
|
139
|
-
display: inline-block;
|
|
140
|
-
font-size: 12px;
|
|
141
|
-
padding: 2px 8px;
|
|
142
|
-
border-radius: 999px;
|
|
143
|
-
background: #ecfeff;
|
|
144
|
-
color: #155e75;
|
|
145
|
-
border: 1px solid #a5f3fc;
|
|
146
|
-
}
|
|
147
|
-
.row {
|
|
148
|
-
display: flex;
|
|
149
|
-
gap: 10px;
|
|
150
|
-
flex-wrap: wrap;
|
|
151
|
-
}
|
|
152
|
-
</style>
|
|
153
|
-
</head>
|
|
154
|
-
<body>
|
|
155
|
-
<div class="wrap">
|
|
156
|
-
<header>
|
|
157
|
-
<h1>Linked Lists Term Logic example proved using Resolution</h1>
|
|
158
|
-
</header>
|
|
159
|
-
|
|
160
|
-
<section class="grid">
|
|
161
|
-
<!-- Problem statement -->
|
|
162
|
-
<article class="card">
|
|
163
|
-
<div class="kicker">Problem</div>
|
|
164
|
-
<h2>Formalize linked lists and show a canonical entailment using Resolution</h2>
|
|
165
|
-
<p>We use the usual setup with constants, functions, and predicates for lists:</p>
|
|
166
|
-
<pre>
|
|
167
|
-
// Signature:
|
|
168
|
-
// nil // constant for empty list
|
|
169
|
-
// cons(x, xs) // function: attach head x to tail xs
|
|
170
|
-
// append(xs, ys, zs) // predicate: zs is xs appended to ys
|
|
171
|
-
// member(x, xs) // predicate: x occurs in xs
|
|
172
|
-
//
|
|
173
|
-
// Axioms (Horn clauses):
|
|
174
|
-
// A1: append(nil, ys, ys).
|
|
175
|
-
// A2: append(xs, ys, zs) -> append(cons(x, xs), ys, cons(x, zs)).
|
|
176
|
-
// M1: member(x, cons(x, xs)).
|
|
177
|
-
// M2: member(x, xs) -> member(x, cons(y, xs)).
|
|
178
|
-
</pre
|
|
179
|
-
>
|
|
180
|
-
<p class="small muted">
|
|
181
|
-
Goal we’ll prove by Resolution:
|
|
182
|
-
<code>append(cons(a, cons(b, nil)), cons(c, nil), cons(a, cons(b, cons(c, nil))))</code>.
|
|
183
|
-
</p>
|
|
184
|
-
</article>
|
|
185
|
-
|
|
186
|
-
<!-- Answer -->
|
|
187
|
-
<article class="card">
|
|
188
|
-
<div class="kicker">Answer</div>
|
|
189
|
-
<p class="answer ok">
|
|
190
|
-
Entailed. Using Resolution on (A1–A2) with the negation of the goal derives a contradiction (empty clause),
|
|
191
|
-
so the goal follows from the axioms.
|
|
192
|
-
</p>
|
|
193
|
-
</article>
|
|
194
|
-
|
|
195
|
-
<!-- Reason Why (Resolution, mathematical English) -->
|
|
196
|
-
<article class="card">
|
|
197
|
-
<div class="kicker">Reason Why</div>
|
|
198
|
-
<h2>Resolution justification (clausal refutation)</h2>
|
|
199
|
-
<ol>
|
|
200
|
-
<li>
|
|
201
|
-
Clausify the axioms (already Horn):
|
|
202
|
-
<div class="small">
|
|
203
|
-
C1: <code>append(nil, Y, Y)</code>. <br />
|
|
204
|
-
C2: <code>¬append(XS, Y, Z) ∨ append(cons(H, XS), Y, cons(H, Z))</code>.
|
|
205
|
-
</div>
|
|
206
|
-
</li>
|
|
207
|
-
<li>
|
|
208
|
-
Negate the ground goal G and add it as a clause:
|
|
209
|
-
<code>¬append(cons(a, cons(b, nil)), cons(c, nil), cons(a, cons(b, cons(c, nil))))</code>.
|
|
210
|
-
</li>
|
|
211
|
-
<li>
|
|
212
|
-
Resolve backwards using C2 repeatedly to “peel” leading <code>cons</code> symbols, producing:
|
|
213
|
-
<div class="small">
|
|
214
|
-
<code>¬append(cons(b, nil), cons(c, nil), cons(b, cons(c, nil)))</code>, then
|
|
215
|
-
<code>¬append(nil, cons(c, nil), cons(c, nil))</code>.
|
|
216
|
-
</div>
|
|
217
|
-
</li>
|
|
218
|
-
<li>Resolve the last clause with C1 (unifier Y:=cons(c,nil)) to derive ⟂ (empty clause).</li>
|
|
219
|
-
<li>Therefore G is entailed by A1–A2.</li>
|
|
220
|
-
</ol>
|
|
221
|
-
</article>
|
|
222
|
-
|
|
223
|
-
<!-- Checks (7 harnesses), all auto-run and visible -->
|
|
224
|
-
<article class="card" id="h1">
|
|
225
|
-
<div class="kicker">Check (harness) #1</div>
|
|
226
|
-
<h3>Concrete append</h3>
|
|
227
|
-
<p class="small muted">Verify <code>append([a,b],[c]) = [a,b,c]</code> using a cons/nil model.</p>
|
|
228
|
-
<div class="result" id="r1" aria-live="polite"></div>
|
|
229
|
-
</article>
|
|
230
|
-
|
|
231
|
-
<article class="card" id="h2">
|
|
232
|
-
<div class="kicker">Check (harness) #2</div>
|
|
233
|
-
<h3>Randomized lists (200 trials)</h3>
|
|
234
|
-
<p class="small muted">
|
|
235
|
-
Generate random arrays over {a,b,c,d,e}; convert to cons-lists; check that our logical
|
|
236
|
-
<code>append</code> matches JS concatenation.
|
|
237
|
-
</p>
|
|
238
|
-
<div class="result" id="r2" aria-live="polite"></div>
|
|
239
|
-
</article>
|
|
240
|
-
|
|
241
|
-
<article class="card" id="h3">
|
|
242
|
-
<div class="kicker">Check (harness) #3</div>
|
|
243
|
-
<h3>Exhaustive small lists (alphabet ≤ {a,b}, length ≤ 2)</h3>
|
|
244
|
-
<p class="small muted">All pairs (xs, ys); ensure <code>append(xs, ys) = xs ++ ys</code>.</p>
|
|
245
|
-
<div class="result" id="r3" aria-live="polite"></div>
|
|
246
|
-
</article>
|
|
247
|
-
|
|
248
|
-
<article class="card" id="h4">
|
|
249
|
-
<div class="kicker">Check (harness) #4</div>
|
|
250
|
-
<h3>Membership preservation</h3>
|
|
251
|
-
<p class="small muted">
|
|
252
|
-
If <code>x</code> is in <code>xs</code> or <code>ys</code> then <code>x</code> is in
|
|
253
|
-
<code>append(xs, ys)</code> (using M1, M2).
|
|
254
|
-
</p>
|
|
255
|
-
<div class="result" id="r4" aria-live="polite"></div>
|
|
256
|
-
</article>
|
|
257
|
-
|
|
258
|
-
<article class="card" id="h5">
|
|
259
|
-
<div class="kicker">Check (harness) #5</div>
|
|
260
|
-
<h3>Edge cases</h3>
|
|
261
|
-
<p class="small muted">Test <code>append([], ys) = ys</code> and <code>append(xs, []) = xs</code>.</p>
|
|
262
|
-
<div class="result" id="r5" aria-live="polite"></div>
|
|
263
|
-
</article>
|
|
264
|
-
|
|
265
|
-
<article class="card" id="h6">
|
|
266
|
-
<div class="kicker">Check (harness) #6</div>
|
|
267
|
-
<h3>Your data (CSV)</h3>
|
|
268
|
-
<p class="small muted">
|
|
269
|
-
Provide <code>L1: a,b,c</code> and <code>L2: d,e</code>. We show the cons-list result and array view.
|
|
270
|
-
</p>
|
|
271
|
-
<textarea
|
|
272
|
-
class="input"
|
|
273
|
-
id="csv"
|
|
274
|
-
placeholder="L1: a,b
|
|
275
|
-
L2: c,d"></textarea>
|
|
276
|
-
<div class="result" id="r6" aria-live="polite"></div>
|
|
277
|
-
</article>
|
|
278
|
-
|
|
279
|
-
<article class="card" id="h7">
|
|
280
|
-
<div class="kicker">Check (harness) #7</div>
|
|
281
|
-
<h3>Automated Resolution trace for the goal</h3>
|
|
282
|
-
<p class="small muted">Derives ⟂ from A1–A2 plus ¬G, showing the append goal is entailed.</p>
|
|
283
|
-
<div class="result" id="r7" aria-live="polite"></div>
|
|
284
|
-
</article>
|
|
285
|
-
</section>
|
|
286
|
-
</div>
|
|
287
|
-
|
|
288
|
-
<script>
|
|
289
|
-
// ---------- Utilities: terms, cons-lists, equality ----------
|
|
290
|
-
const Nil = { tag: 'nil' };
|
|
291
|
-
const Cons = (h, t) => ({ tag: 'cons', h, t });
|
|
292
|
-
|
|
293
|
-
const isNil = (t) => t.tag === 'nil';
|
|
294
|
-
const toArray = (t) => {
|
|
295
|
-
const out = [];
|
|
296
|
-
let cur = t;
|
|
297
|
-
while (!isNil(cur)) {
|
|
298
|
-
out.push(cur.h);
|
|
299
|
-
cur = cur.t;
|
|
300
|
-
}
|
|
301
|
-
return out;
|
|
302
|
-
};
|
|
303
|
-
const fromArray = (arr) => {
|
|
304
|
-
let t = Nil;
|
|
305
|
-
for (let i = arr.length - 1; i >= 0; i--) t = Cons(arr[i], t);
|
|
306
|
-
return t;
|
|
307
|
-
};
|
|
308
|
-
const termEq = (a, b) => {
|
|
309
|
-
if (a.tag !== b.tag) return false;
|
|
310
|
-
if (a.tag === 'nil') return true;
|
|
311
|
-
return a.h === b.h && termEq(a.t, b.t);
|
|
312
|
-
};
|
|
313
|
-
const show = (t) => (isNil(t) ? 'nil' : `cons(${t.h}, ${show(t.t)})`);
|
|
314
|
-
|
|
315
|
-
// ---------- Logical predicates as functions (denotation) ----------
|
|
316
|
-
// append(xs, ys) -> zs (functional version returning zs)
|
|
317
|
-
const appendLL = (xs, ys) => (isNil(xs) ? ys : Cons(xs.h, appendLL(xs.t, ys)));
|
|
318
|
-
|
|
319
|
-
// member(x, xs)
|
|
320
|
-
const memberLL = (x, xs) => !isNil(xs) && (x === xs.h || memberLL(x, xs.t));
|
|
321
|
-
|
|
322
|
-
// ---------- Harness #1: concrete append ----------
|
|
323
|
-
function check1() {
|
|
324
|
-
const xs = fromArray(['a', 'b']);
|
|
325
|
-
const ys = fromArray(['c']);
|
|
326
|
-
const zs = appendLL(xs, ys);
|
|
327
|
-
const want = fromArray(['a', 'b', 'c']);
|
|
328
|
-
const pass = termEq(zs, want);
|
|
329
|
-
const msg = `append([a,b],[c]) = ${JSON.stringify(toArray(zs))}`;
|
|
330
|
-
document.getElementById('r1').innerHTML =
|
|
331
|
-
`<div class="${pass ? 'ok' : 'fail'}">${pass ? 'PASS' : 'FAIL'}</div><pre>${msg}</pre>`;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// ---------- Harness #2: randomized lists ----------
|
|
335
|
-
function check2() {
|
|
336
|
-
const alphabet = ['a', 'b', 'c', 'd', 'e'];
|
|
337
|
-
const trials = 200;
|
|
338
|
-
let ok = 0;
|
|
339
|
-
for (let t = 0; t < trials; t++) {
|
|
340
|
-
const r = (n) => Math.floor(Math.random() * n);
|
|
341
|
-
const make = () => {
|
|
342
|
-
const n = r(4); // length 0..3
|
|
343
|
-
const arr = Array.from({ length: n }, () => alphabet[r(alphabet.length)]);
|
|
344
|
-
return arr;
|
|
345
|
-
};
|
|
346
|
-
const xsArr = make(),
|
|
347
|
-
ysArr = make();
|
|
348
|
-
const xs = fromArray(xsArr),
|
|
349
|
-
ys = fromArray(ysArr);
|
|
350
|
-
const zs = appendLL(xs, ys);
|
|
351
|
-
const pass = JSON.stringify(toArray(zs)) === JSON.stringify(xsArr.concat(ysArr));
|
|
352
|
-
if (pass) ok++;
|
|
353
|
-
}
|
|
354
|
-
const all = ok === trials;
|
|
355
|
-
document.getElementById('r2').innerHTML = `<div class="${all ? 'ok' : 'fail'}">${all ? 'PASS' : 'FAIL'}</div>
|
|
356
|
-
<div class="small">Passed ${ok}/${trials} randomized cases.</div>`;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// ---------- Harness #3: exhaustive small lists ----------
|
|
360
|
-
function check3() {
|
|
361
|
-
const alphabet = ['a', 'b'];
|
|
362
|
-
const genLists = (maxLen) => {
|
|
363
|
-
const out = [[]];
|
|
364
|
-
for (let len = 1; len <= maxLen; len++) {
|
|
365
|
-
const rec = (pref, k) => {
|
|
366
|
-
if (k === 0) {
|
|
367
|
-
out.push(pref);
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
for (const ch of alphabet) rec(pref.concat([ch]), k - 1);
|
|
371
|
-
};
|
|
372
|
-
rec([], len);
|
|
373
|
-
}
|
|
374
|
-
return out;
|
|
375
|
-
};
|
|
376
|
-
const cases = genLists(2);
|
|
377
|
-
let total = 0,
|
|
378
|
-
bad = 0;
|
|
379
|
-
for (const xsA of cases) {
|
|
380
|
-
for (const ysA of cases) {
|
|
381
|
-
total++;
|
|
382
|
-
const xs = fromArray(xsA),
|
|
383
|
-
ys = fromArray(ysA);
|
|
384
|
-
const zs = appendLL(xs, ys);
|
|
385
|
-
if (JSON.stringify(toArray(zs)) !== JSON.stringify(xsA.concat(ysA))) bad++;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
const pass = bad === 0;
|
|
389
|
-
document.getElementById('r3').innerHTML = `<div class="${pass ? 'ok' : 'fail'}">${pass ? 'PASS' : 'FAIL'}</div>
|
|
390
|
-
<div class="small">Checked ${total} pairs; counterexamples: ${bad}.</div>`;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// ---------- Harness #4: membership preservation ----------
|
|
394
|
-
function check4() {
|
|
395
|
-
const xs = fromArray(['a', 'b']);
|
|
396
|
-
const ys = fromArray(['c', 'a']);
|
|
397
|
-
const zs = appendLL(xs, ys);
|
|
398
|
-
const universe = ['a', 'b', 'c', 'd'];
|
|
399
|
-
const report = [];
|
|
400
|
-
let all = true;
|
|
401
|
-
for (const v of universe) {
|
|
402
|
-
const lhs = memberLL(v, xs) || memberLL(v, ys);
|
|
403
|
-
const rhs = memberLL(v, zs);
|
|
404
|
-
const good = lhs === rhs || (!lhs && !rhs); // require: lhs -> rhs (preservation); we report both
|
|
405
|
-
if (lhs && !rhs) all = false;
|
|
406
|
-
report.push(`${v}: in(xs)∨in(ys)=${lhs} ⇒ in(append(xs,ys))=${rhs}`);
|
|
407
|
-
}
|
|
408
|
-
document.getElementById('r4').innerHTML =
|
|
409
|
-
`<div class="${all ? 'ok' : 'fail'}">${all ? 'PASS' : 'FAIL'}</div><pre>${report.join('\n')}</pre>`;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// ---------- Harness #5: edge cases ----------
|
|
413
|
-
function check5() {
|
|
414
|
-
const xs = fromArray([]);
|
|
415
|
-
const ys = fromArray(['a', 'b']);
|
|
416
|
-
const case1 = toArray(appendLL(xs, ys));
|
|
417
|
-
const case2 = toArray(appendLL(ys, fromArray([])));
|
|
418
|
-
const pass =
|
|
419
|
-
JSON.stringify(case1) === JSON.stringify(['a', 'b']) && JSON.stringify(case2) === JSON.stringify(['a', 'b']);
|
|
420
|
-
const msg = `append([], [a,b]) = [${case1.join(',')}]\nappend([a,b], []) = [${case2.join(',')}]`;
|
|
421
|
-
document.getElementById('r5').innerHTML =
|
|
422
|
-
`<div class="${pass ? 'ok' : 'fail'}">${pass ? 'PASS' : 'FAIL'}</div><pre>${msg}</pre>`;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// ---------- Harness #6: user CSV ----------
|
|
426
|
-
function parseCSVSpec(text) {
|
|
427
|
-
const lines = (text || '')
|
|
428
|
-
.split(/\r?\n/)
|
|
429
|
-
.map((s) => s.trim())
|
|
430
|
-
.filter(Boolean);
|
|
431
|
-
let L1 = [],
|
|
432
|
-
L2 = [];
|
|
433
|
-
for (const ln of lines) {
|
|
434
|
-
const m = ln.match(/^L([12])\s*:\s*(.*)$/i);
|
|
435
|
-
if (!m) continue;
|
|
436
|
-
const listNum = m[1];
|
|
437
|
-
const items = m[2]
|
|
438
|
-
.split(',')
|
|
439
|
-
.map((s) => s.trim())
|
|
440
|
-
.filter(Boolean);
|
|
441
|
-
if (listNum === '1') L1 = items;
|
|
442
|
-
else L2 = items;
|
|
443
|
-
}
|
|
444
|
-
return { L1, L2 };
|
|
445
|
-
}
|
|
446
|
-
function check6() {
|
|
447
|
-
const { L1, L2 } = parseCSVSpec(document.getElementById('csv').value);
|
|
448
|
-
const xs = fromArray(L1),
|
|
449
|
-
ys = fromArray(L2);
|
|
450
|
-
const zs = appendLL(xs, ys);
|
|
451
|
-
const arr = toArray(zs);
|
|
452
|
-
const msg = `L1 ++ L2 → ${JSON.stringify(arr)}\ncons-form: ${show(zs)}`;
|
|
453
|
-
document.getElementById('r6').innerHTML = `<div class="ok">OK</div><pre>${msg}</pre>`;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// ---------- Harness #7: automated Resolution trace for the goal ----------
|
|
457
|
-
function resolutionTrace() {
|
|
458
|
-
// Axioms:
|
|
459
|
-
// C1: append(nil, Y, Y).
|
|
460
|
-
// C2: ¬append(XS, Y, Z) ∨ append(cons(H, XS), Y, cons(H, Z)).
|
|
461
|
-
// Negated goal:
|
|
462
|
-
// N0: ¬append(cons(a, cons(b, nil)), cons(c, nil), cons(a, cons(b, cons(c, nil)))).
|
|
463
|
-
const steps = [];
|
|
464
|
-
steps.push('C1: append(nil, Y, Y)');
|
|
465
|
-
steps.push('C2: ¬append(XS, Y, Z) ∨ append(cons(H, XS), Y, cons(H, Z))');
|
|
466
|
-
steps.push('N0: ¬append(cons(a, cons(b, nil)), cons(c, nil), cons(a, cons(b, cons(c, nil))))');
|
|
467
|
-
|
|
468
|
-
// Resolve N0 with C2 (unify H:=a, XS:=cons(b,nil), Y:=cons(c,nil), Z:=cons(b,cons(c,nil))):
|
|
469
|
-
steps.push('R1: from C2 with N0 ⇒ ¬append(cons(b, nil), cons(c, nil), cons(b, cons(c, nil)))');
|
|
470
|
-
|
|
471
|
-
// Resolve R1 with C2 (unify H:=b, XS:=nil, Y:=cons(c,nil), Z:=cons(c,nil)):
|
|
472
|
-
steps.push('R2: from C2 with R1 ⇒ ¬append(nil, cons(c, nil), cons(c, nil))');
|
|
473
|
-
|
|
474
|
-
// Resolve R2 with C1 (Y:=cons(c,nil)) to get empty clause:
|
|
475
|
-
steps.push('R3: from C1 with R2 ⇒ ⟂ (empty clause)');
|
|
476
|
-
|
|
477
|
-
return steps;
|
|
478
|
-
}
|
|
479
|
-
function check7() {
|
|
480
|
-
const steps = resolutionTrace();
|
|
481
|
-
const ok = steps[steps.length - 1].includes('⟂');
|
|
482
|
-
document.getElementById('r7').innerHTML =
|
|
483
|
-
`<div class="${ok ? 'ok' : 'fail'}">${ok ? 'PASS' : 'FAIL'}</div><pre>${steps.join('\n')}</pre>`;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
// ---------- Autorun all checks ----------
|
|
487
|
-
window.addEventListener('DOMContentLoaded', () => {
|
|
488
|
-
const csv = document.getElementById('csv');
|
|
489
|
-
if (csv && !csv.value.trim()) {
|
|
490
|
-
csv.value = 'L1: a,b\nL2: c';
|
|
491
|
-
}
|
|
492
|
-
check1();
|
|
493
|
-
check2();
|
|
494
|
-
check3();
|
|
495
|
-
check4();
|
|
496
|
-
check5();
|
|
497
|
-
check6();
|
|
498
|
-
check7();
|
|
499
|
-
});
|
|
500
|
-
</script>
|
|
501
|
-
</body>
|
|
502
|
-
</html>
|