eyeling 1.22.4 → 1.22.6
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/HANDBOOK.md +63 -19
- package/dist/browser/eyeling.browser.js +44 -0
- package/examples/arcling/README.md +6 -52
- package/examples/output/sudoku.txt +1 -0
- package/examples/sudoku.n3 +2 -2
- package/eyeling.js +44 -0
- package/lib/builtins.js +44 -0
- package/package.json +1 -1
- package/test/api.test.js +84 -0
package/HANDBOOK.md
CHANGED
|
@@ -2599,19 +2599,23 @@ In that sense, N3 is less a bid to make the web “smarter” than a bid to make
|
|
|
2599
2599
|
|
|
2600
2600
|
<a id="app-c"></a>
|
|
2601
2601
|
|
|
2602
|
-
## Appendix C — N3 beyond Prolog: logic
|
|
2602
|
+
## Appendix C — N3 beyond Prolog: logic that survives the open web
|
|
2603
2603
|
|
|
2604
|
-
Notation3
|
|
2604
|
+
Notation3 and Prolog resemble each other at first glance. Both use variables, unification, and implication-shaped rules. Both can be used to derive consequences from a set of premises. But they were shaped for different native environments. Prolog was designed around executing logic programs. N3 was designed around expressing logic in the same world as RDF: a world of IRIs, triples, graphs, linked documents, and shared vocabularies. That difference in native setting gives N3 a wider built-in reach for web-scale knowledge work.
|
|
2605
2605
|
|
|
2606
|
-
In
|
|
2606
|
+
The first difference is the data model. In Prolog, the basic units are terms and clauses. In N3, the basic units are RDF-style triples and graphs, extended with variables, lists, graph terms, and logical implication. N3 is explicitly defined as an extension of RDF, not as a separate programming language that merely happens to manipulate graphs. That means identifiers, data, and inferred results all live in one interoperable form. A rule consumes graph patterns and produces graph patterns, so the output of reasoning can be published, merged, quoted, exchanged, and reasoned over again without changing representation.
|
|
2607
2607
|
|
|
2608
|
-
-
|
|
2609
|
-
- **Input and output are graphs.** Rules consume graph patterns and produce additional triples, so the result of inference can be represented in the same form as the input data.
|
|
2610
|
-
- **Quoted graphs allow statements-as-data.** N3 can treat a graph (a set of triples) as a term, which makes it possible to represent and reason about assertions (e.g., “this source says …” or “this formula implies …”) as data.
|
|
2611
|
-
- **Rules can be distributed as text artifacts.** Rules can live alongside data, be versioned, and be reused without requiring an external host language to “carry” the meaning.
|
|
2612
|
-
- **Built-ins cover common computations.** Many N3 workflows rely on built-ins for operations such as string handling, list processing, comparisons, and related utilities; some workflows also use IRIs as pointers to retrievable content.
|
|
2608
|
+
The second difference is more profound: N3 can treat graphs as first-class terms. A graph term is a quoted graph. It can appear in subject, predicate, or object position, and it does not automatically assert its contents as true. It is a resource in its own right. This makes it natural to represent claims, reports, beliefs, policies, source snapshots, and provenance. One can say not only “this is true,” but also “this document says this,” “this authority concludes that,” or “this rule applies to that quoted context.” In other words, N3 can reason about statements as statements, not only about the world those statements describe.
|
|
2613
2609
|
|
|
2614
|
-
|
|
2610
|
+
That leads directly to a third advantage: scope is part of the logic. In N3, implicit universal quantification is global, while implicit existential quantification is local to the graph in which it occurs. Once graphs can be nested and quoted, that distinction matters. It allows a reasoner to keep track of what is asserted here, what is asserted inside a quoted subgraph, and what variables belong to which level. This gives N3 a native way to express context-sensitive reasoning that would feel external or encoded-by-convention in classic Prolog.
|
|
2611
|
+
|
|
2612
|
+
A fourth difference is that N3 connects logic to the web inside the language itself. The N3 vocabulary includes `log:semantics` and `log:conclusion` for retrieving and reasoning over local or online sources. It also includes scoped operators such as `log:forAllIn` and `log:notIncludes`, which support scoped universal reasoning and scoped negation-as-failure over a chosen graph or document. So web retrieval, source-bounded reasoning, and reasoning over quoted content are not afterthoughts. They are part of the logic vocabulary. This is one of the clearest senses in which N3 has greater inherent potential: it is not only a language for deriving consequences from facts, but a language for locating, quoting, constraining, and comparing the sources of those facts.
|
|
2613
|
+
|
|
2614
|
+
By contrast, classic Prolog is centered on a proof procedure over definite clauses. In the usual operational reading, Prolog applies a restricted form of SLD-resolution, chooses the leftmost goal, tries clauses top-to-bottom, and searches depth-first. Traditional negation is negation-as-failure, described in the SWI-Prolog glossary as a weak negation. This makes Prolog extremely effective as an executable logic language, but it also means that much of its practical power comes from the operational behavior of the engine, not from a web-native knowledge model.
|
|
2615
|
+
|
|
2616
|
+
This does not make Prolog inferior. Modern Prolog systems add important capabilities beyond the classic core, including tabling, which improves termination behavior and can make Prolog behave more like a bottom-up theorem prover for some classes of problems. But that actually sharpens the comparison: when Prolog needs to work more comfortably in graph-heavy or knowledge-integration settings, it typically gains that power through extensions, libraries, or host-environment choices. N3 starts there. Graphs, quoted formulas, scoped reasoning, and web-connected semantics are part of its native conceptual center.
|
|
2617
|
+
|
|
2618
|
+
So the strongest claim is not that N3 replaces Prolog in every domain. The stronger and more precise claim is this: Prolog is a very strong language for executing logic programs, while N3 has greater inherent potential as a language for publishable, linkable, inspectable, and source-aware logic on the open web. It lets facts, rules, quoted claims, retrieved documents, and derived conclusions all live in one semantic space. For a system like Eyeling, that is not a cosmetic difference. It is the reason the language can scale from local inference to web-shaped reasoning without changing its basic form.
|
|
2615
2619
|
|
|
2616
2620
|
---
|
|
2617
2621
|
|
|
@@ -3131,29 +3135,69 @@ Sometimes that means recomputing a quantity from another angle. Sometimes it mea
|
|
|
3131
3135
|
|
|
3132
3136
|
The point is not to make checks large. The point is to make them real.
|
|
3133
3137
|
|
|
3134
|
-
### F.6
|
|
3138
|
+
### F.6 ARC and the Insight Economy
|
|
3139
|
+
|
|
3140
|
+
One reason ARC matters beyond pedagogy is that it matches a broader way of thinking about data and computation that Ruben Verborgh has called the **Insight Economy**.
|
|
3141
|
+
|
|
3142
|
+
The basic claim is simple: raw data is usually the wrong thing to exchange directly. A better system refines source data into a **specific, purpose-limited, time-bound insight** that is useful in one context, loses much of its value when copied without that context, and can be governed more safely than an unrestricted dump of the original data.
|
|
3143
|
+
|
|
3144
|
+
That fits Eyeling remarkably well. Eyeling can derive narrow conclusions explicitly, show why they follow, and attach checks that make sure a decision still respects policy, scope, thresholds, or consistency constraints. In other words, an Eyeling program can act as a small governed insight refinery rather than as a black box that merely emits a verdict.
|
|
3145
|
+
|
|
3146
|
+
This is also why ARC is a good mental model here. The **Answer** is the bounded insight. The **Reason Why** makes the governing basis visible. The **Check** ensures the result can be trusted for the stated purpose instead of silently drifting beyond it.
|
|
3147
|
+
|
|
3148
|
+
### F.7 ARC-style examples in `examples/`
|
|
3149
|
+
|
|
3150
|
+
The following examples are especially useful if you want to see Eyeling files that derive an answer, expose the key reason, and include meaningful checks. Each entry links to both the source example and the corresponding generated output file in `examples/output/`.
|
|
3151
|
+
|
|
3152
|
+
#### Insight Economy and governed-data cases
|
|
3153
|
+
|
|
3154
|
+
- [`examples/auroracare.n3`](examples/auroracare.n3) · [`examples/output/auroracare.txt`](examples/output/auroracare.txt) — purpose-based medical data exchange with explicit allow/deny reasoning and checks around role, purpose, and conditions.
|
|
3155
|
+
- [`examples/calidor.n3`](examples/calidor.n3) · [`examples/output/calidor.txt`](examples/output/calidor.txt) — heatwave-response case where private household signals become a narrow, expiring cooling-support insight.
|
|
3156
|
+
- [`examples/delfour.n3`](examples/delfour.n3) · [`examples/output/delfour.txt`](examples/output/delfour.txt) — shopping-assistance case where a private condition becomes a bounded “prefer lower-sugar products” insight.
|
|
3157
|
+
- [`examples/flandor.n3`](examples/flandor.n3) · [`examples/output/flandor.txt`](examples/output/flandor.txt) — macro-economic coordination case for Flanders that turns sensitive local signals into a regional retooling insight.
|
|
3158
|
+
- [`examples/medior.n3`](examples/medior.n3) · [`examples/output/medior.txt`](examples/output/medior.txt) — post-discharge care-coordination case that derives a minimal continuity-bundle insight without sharing the full record.
|
|
3159
|
+
- [`examples/parcellocker.n3`](examples/parcellocker.n3) · [`examples/output/parcellocker.txt`](examples/output/parcellocker.txt) — one-time parcel pickup authorization with a clear permit decision, justification, and misuse checks.
|
|
3160
|
+
|
|
3161
|
+
#### Core ARC-style walkthroughs
|
|
3162
|
+
|
|
3163
|
+
- [`examples/bmi.n3`](examples/bmi.n3) · [`examples/output/bmi.txt`](examples/output/bmi.txt) — Body Mass Index calculation with normalization, WHO category assignment, and boundary checks.
|
|
3164
|
+
- [`examples/control-system.n3`](examples/control-system.n3) · [`examples/output/control-system.txt`](examples/output/control-system.txt) — small control-system example that derives actuator commands and explains feedforward and feedback contributions.
|
|
3165
|
+
- [`examples/easter.n3`](examples/easter.n3) · [`examples/output/easter.txt`](examples/output/easter.txt) — Gregorian Easter computus with a readable explanation and date-window checks.
|
|
3166
|
+
- [`examples/french-cities.n3`](examples/french-cities.n3) · [`examples/output/french-cities.txt`](examples/output/french-cities.txt) — graph reachability over French cities with explicit path reasoning.
|
|
3167
|
+
- [`examples/gps.n3`](examples/gps.n3) · [`examples/output/gps.txt`](examples/output/gps.txt) — tiny route-planning example for western Belgium with route comparison and metric checks.
|
|
3168
|
+
- [`examples/resto.n3`](examples/resto.n3) · [`examples/output/resto.txt`](examples/output/resto.txt) — RESTdesc-style service composition from person and date to a concrete restaurant reservation.
|
|
3169
|
+
- [`examples/sudoku.n3`](examples/sudoku.n3) · [`examples/output/sudoku.txt`](examples/output/sudoku.txt) — Sudoku solver and report generator with consistency checks over the solved grid.
|
|
3170
|
+
- [`examples/wind-turbine.n3`](examples/wind-turbine.n3) · [`examples/output/wind-turbine.txt`](examples/output/wind-turbine.txt) — predictive-maintenance example that turns sensor readings into an auditable inspection decision.
|
|
3171
|
+
|
|
3172
|
+
#### Technical and scientific ARC demos
|
|
3173
|
+
|
|
3174
|
+
- [`examples/matrix-mechanics.n3`](examples/matrix-mechanics.n3) · [`examples/output/matrix-mechanics.txt`](examples/output/matrix-mechanics.txt) — small 2×2 matrix example deriving trace, determinant, products, and a non-zero commutator.
|
|
3175
|
+
- [`examples/pn-junction-tunneling.n3`](examples/pn-junction-tunneling.n3) · [`examples/output/pn-junction-tunneling.txt`](examples/output/pn-junction-tunneling.txt) — semiconductor toy model that explains current-proxy behavior across bias points.
|
|
3176
|
+
- [`examples/transistor-switch.n3`](examples/transistor-switch.n3) · [`examples/output/transistor-switch.txt`](examples/output/transistor-switch.txt) — NPN low-side switch model with exact arithmetic and cutoff-versus-saturation checks.
|
|
3177
|
+
|
|
3178
|
+
#### Deep-classification stress tests
|
|
3135
3179
|
|
|
3136
|
-
|
|
3180
|
+
- [`examples/deep-taxonomy-10.n3`](examples/deep-taxonomy-10.n3) · [`examples/output/deep-taxonomy-10.txt`](examples/output/deep-taxonomy-10.txt) — ARC-style deep-taxonomy benchmark at depth 10.
|
|
3181
|
+
- [`examples/deep-taxonomy-100.n3`](examples/deep-taxonomy-100.n3) · [`examples/output/deep-taxonomy-100.txt`](examples/output/deep-taxonomy-100.txt) — ARC-style deep-taxonomy benchmark at depth 100.
|
|
3182
|
+
- [`examples/deep-taxonomy-1000.n3`](examples/deep-taxonomy-1000.n3) · [`examples/output/deep-taxonomy-1000.txt`](examples/output/deep-taxonomy-1000.txt) — ARC-style deep-taxonomy benchmark at depth 1000.
|
|
3183
|
+
- [`examples/deep-taxonomy-10000.n3`](examples/deep-taxonomy-10000.n3) · [`examples/output/deep-taxonomy-10000.txt`](examples/output/deep-taxonomy-10000.txt) — ARC-style deep-taxonomy benchmark at depth 10000.
|
|
3184
|
+
- [`examples/deep-taxonomy-100000.n3`](examples/deep-taxonomy-100000.n3) · [`examples/output/deep-taxonomy-100000.txt`](examples/output/deep-taxonomy-100000.txt) — ARC-style deep-taxonomy benchmark at depth 100000.
|
|
3137
3185
|
|
|
3138
|
-
|
|
3139
|
-
- [`examples/control-system.n3`](examples/control-system.n3) — derives actuator decisions, explains the control basis, and checks the result. Expected output: [`examples/output/control-system.n3`](examples/output/control-system.n3)
|
|
3140
|
-
- [`examples/deep-taxonomy-100000.n3`](examples/deep-taxonomy-100000.n3) — a deep classification stress test whose answer is whether the final goal class is reached. Expected output: [`examples/output/deep-taxonomy-100000.n3`](examples/output/deep-taxonomy-100000.n3)
|
|
3141
|
-
- [`examples/gps.n3`](examples/gps.n3) — route planning with readable route output. Expected output: [`examples/output/gps.n3`](examples/output/gps.n3)
|
|
3142
|
-
- [`examples/sudoku.n3`](examples/sudoku.n3) — solver output plus legality and consistency checks. Expected output: [`examples/output/sudoku.n3`](examples/output/sudoku.n3)
|
|
3186
|
+
These files fit together because they all present reasoning in a recognizably ARC-like way: they derive an answer, make the reason visible in a compact report, and include checks that are meant to catch real mistakes. Some are classical logic or numeric examples; others show how Eyeling can express policy-aware, insight-oriented decision flows without collapsing everything into opaque application code.
|
|
3143
3187
|
|
|
3144
|
-
### F.
|
|
3188
|
+
### F.8 How to read an ARC-style example
|
|
3145
3189
|
|
|
3146
3190
|
A good way to read one of these files is to start with the question in the comments or input facts. Then find the part that gives the answer. Then trace the few rules that explain why that answer follows. Finally, look for the checks: the validation facts, the recomputation, or the `=> false` fuse that would stop the run if something important were wrong.
|
|
3147
3191
|
|
|
3148
3192
|
That reading order keeps the example grounded in observable behavior rather than in source code alone.
|
|
3149
3193
|
|
|
3150
|
-
### F.
|
|
3194
|
+
### F.9 What ARC is not
|
|
3151
3195
|
|
|
3152
3196
|
ARC does not mean wrapping every file in ceremony. It does not mean long prose explanations. It does not mean hiding important assumptions in comments while the executable part stays thin. And it does not mean replacing checks with a confident tone.
|
|
3153
3197
|
|
|
3154
3198
|
A file really follows ARC only when the answer, the explanation, and the validation all live in the program itself.
|
|
3155
3199
|
|
|
3156
|
-
### F.
|
|
3200
|
+
### F.10 Why this style is worth using
|
|
3157
3201
|
|
|
3158
3202
|
This style is worth using because it makes an Eyeling file easier to run, easier to inspect, and easier to trust. The result is visible. The key reason is visible. The check is visible. That makes examples better teaching material, makes policy or computation examples easier to audit, and makes the whole file more reusable as a small reasoning artifact instead of an opaque session transcript.
|
|
3159
3203
|
|
|
@@ -1343,6 +1343,15 @@
|
|
|
1343
1343
|
return null;
|
|
1344
1344
|
}
|
|
1345
1345
|
|
|
1346
|
+
function inferDatatypeForShorthandLexical(lex) {
|
|
1347
|
+
if (typeof lex !== 'string' || isQuotedLexical(lex)) return null;
|
|
1348
|
+
if (lex === 'true' || lex === 'false') return XSD_NS + 'boolean';
|
|
1349
|
+
if (/^[+-]?\d+$/.test(lex)) return XSD_NS + 'integer';
|
|
1350
|
+
if (/^[+-]?(?:\d+\.\d*|\.\d+)$/.test(lex)) return XSD_NS + 'decimal';
|
|
1351
|
+
if (/^[+-]?(?:\d+\.\d*|\.\d+|\d+)(?:[eE][+-]?\d+)$/.test(lex)) return XSD_NS + 'double';
|
|
1352
|
+
return null;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1346
1355
|
// ===========================================================================
|
|
1347
1356
|
// Math builtin helpers
|
|
1348
1357
|
// ===========================================================================
|
|
@@ -3864,6 +3873,7 @@
|
|
|
3864
3873
|
if (oDt === null) {
|
|
3865
3874
|
if (literalHasLangTag(g.o.value)) oDt = RDF_NS + 'langString';
|
|
3866
3875
|
else if (isPlainStringLiteralValue(g.o.value)) oDt = XSD_NS + 'string';
|
|
3876
|
+
else oDt = inferDatatypeForShorthandLexical(oLex);
|
|
3867
3877
|
}
|
|
3868
3878
|
|
|
3869
3879
|
if (oDt !== null) {
|
|
@@ -3978,6 +3988,23 @@
|
|
|
3978
3988
|
results.push(s2);
|
|
3979
3989
|
}
|
|
3980
3990
|
|
|
3991
|
+
// Also match quoted log:implies triples present as data in the current scope.
|
|
3992
|
+
if (facts && typeof facts.length === 'number') {
|
|
3993
|
+
ensureFactIndexes(facts);
|
|
3994
|
+
const pb = facts.__byPred.get(goal.p.__tid) || [];
|
|
3995
|
+
for (const idx of pb) {
|
|
3996
|
+
const tr = facts[idx];
|
|
3997
|
+
|
|
3998
|
+
let s2 = unifyTerm(goal.s, tr.s, subst);
|
|
3999
|
+
if (s2 === null) continue;
|
|
4000
|
+
|
|
4001
|
+
s2 = unifyTerm(goal.o, tr.o, s2);
|
|
4002
|
+
if (s2 === null) continue;
|
|
4003
|
+
|
|
4004
|
+
results.push(s2);
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
|
|
3981
4008
|
return results;
|
|
3982
4009
|
}
|
|
3983
4010
|
|
|
@@ -4007,6 +4034,23 @@
|
|
|
4007
4034
|
results.push(s2);
|
|
4008
4035
|
}
|
|
4009
4036
|
|
|
4037
|
+
// Also match quoted log:impliedBy triples present as data in the current scope.
|
|
4038
|
+
if (facts && typeof facts.length === 'number') {
|
|
4039
|
+
ensureFactIndexes(facts);
|
|
4040
|
+
const pb = facts.__byPred.get(goal.p.__tid) || [];
|
|
4041
|
+
for (const idx of pb) {
|
|
4042
|
+
const tr = facts[idx];
|
|
4043
|
+
|
|
4044
|
+
let s2 = unifyTerm(goal.s, tr.s, subst);
|
|
4045
|
+
if (s2 === null) continue;
|
|
4046
|
+
|
|
4047
|
+
s2 = unifyTerm(goal.o, tr.o, s2);
|
|
4048
|
+
if (s2 === null) continue;
|
|
4049
|
+
|
|
4050
|
+
results.push(s2);
|
|
4051
|
+
}
|
|
4052
|
+
}
|
|
4053
|
+
|
|
4010
4054
|
return results;
|
|
4011
4055
|
}
|
|
4012
4056
|
|
|
@@ -1,57 +1,11 @@
|
|
|
1
1
|
# ARC-style examples in Eyeling
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This content is now integrated into the handbook:
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- [Appendix F — The ARC approach: Answer • Reason Why • Check](../../HANDBOOK.md#app-f)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
That appendix now includes:
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Ruben Verborgh’s [Insight Economy](https://ruben.verborgh.org/blog/2025/08/12/inside-the-insight-economy/) argues that raw data is a bad thing to trade directly. Instead of handing over the source data, a system should refine it into a **specific, purpose-limited, time-bound insight** that is useful in one context, loses value when copied, and can be governed more safely.
|
|
14
|
-
|
|
15
|
-
That makes the examples below especially relevant: Eyeling can derive those narrow insights explicitly, explain why they hold, and check that the resulting decision respects policy, purpose, and consistency constraints.
|
|
16
|
-
|
|
17
|
-
## ARC-style examples in `examples/`
|
|
18
|
-
|
|
19
|
-
Each entry links to both the source example and the corresponding generated output in [`examples/output/`](../output/).
|
|
20
|
-
|
|
21
|
-
### Insight Economy and governed-data cases
|
|
22
|
-
|
|
23
|
-
- [`../auroracare.n3`](../auroracare.n3) · [`../output/auroracare.txt`](../output/auroracare.txt) — Purpose-based medical data exchange with explicit allow/deny reasoning and checks around role, purpose, and conditions.
|
|
24
|
-
- [`../calidor.n3`](../calidor.n3) · [`../output/calidor.txt`](../output/calidor.txt) — Heatwave-response case where private household signals become a narrow, expiring cooling-support insight.
|
|
25
|
-
- [`../delfour.n3`](../delfour.n3) · [`../output/delfour.txt`](../output/delfour.txt) — Shopping-assistance case where a private condition becomes a bounded “prefer lower-sugar products” insight.
|
|
26
|
-
- [`../flandor.n3`](../flandor.n3) · [`../output/flandor.txt`](../output/flandor.txt) — Macro-economic coordination case for Flanders that turns sensitive local signals into a regional retooling insight.
|
|
27
|
-
- [`../medior.n3`](../medior.n3) · [`../output/medior.txt`](../output/medior.txt) — Post-discharge care-coordination case that derives a minimal continuity-bundle insight without sharing the full record.
|
|
28
|
-
- [`../parcellocker.n3`](../parcellocker.n3) · [`../output/parcellocker.txt`](../output/parcellocker.txt) — One-time parcel pickup authorization with a clear permit decision, justification, and misuse checks.
|
|
29
|
-
|
|
30
|
-
### Core ARC-style walkthroughs
|
|
31
|
-
|
|
32
|
-
- [`../bmi.n3`](../bmi.n3) · [`../output/bmi.txt`](../output/bmi.txt) — Body Mass Index calculation with normalization, WHO category assignment, and boundary checks.
|
|
33
|
-
- [`../control-system.n3`](../control-system.n3) · [`../output/control-system.txt`](../output/control-system.txt) — Small control-system example that derives actuator commands and explains feedforward and feedback contributions.
|
|
34
|
-
- [`../easter.n3`](../easter.n3) · [`../output/easter.txt`](../output/easter.txt) — Gregorian Easter computus with a readable explanation and date-window checks.
|
|
35
|
-
- [`../french-cities.n3`](../french-cities.n3) · [`../output/french-cities.txt`](../output/french-cities.txt) — Graph reachability over French cities with explicit path reasoning.
|
|
36
|
-
- [`../gps.n3`](../gps.n3) · [`../output/gps.txt`](../output/gps.txt) — Tiny route-planning example for western Belgium with route comparison and metric checks.
|
|
37
|
-
- [`../resto.n3`](../resto.n3) · [`../output/resto.txt`](../output/resto.txt) — RESTdesc-style service composition from person and date to a concrete restaurant reservation.
|
|
38
|
-
- [`../sudoku.n3`](../sudoku.n3) · [`../output/sudoku.txt`](../output/sudoku.txt) — Sudoku solver and report generator with consistency checks over the solved grid.
|
|
39
|
-
- [`../wind-turbine.n3`](../wind-turbine.n3) · [`../output/wind-turbine.txt`](../output/wind-turbine.txt) — Predictive-maintenance example that turns sensor readings into an auditable inspection decision.
|
|
40
|
-
|
|
41
|
-
### Technical and scientific ARC demos
|
|
42
|
-
|
|
43
|
-
- [`../matrix-mechanics.n3`](../matrix-mechanics.n3) · [`../output/matrix-mechanics.txt`](../output/matrix-mechanics.txt) — Small 2×2 matrix example deriving trace, determinant, products, and a non-zero commutator.
|
|
44
|
-
- [`../pn-junction-tunneling.n3`](../pn-junction-tunneling.n3) · [`../output/pn-junction-tunneling.txt`](../output/pn-junction-tunneling.txt) — Semiconductor toy model that explains current-proxy behavior across bias points.
|
|
45
|
-
- [`../transistor-switch.n3`](../transistor-switch.n3) · [`../output/transistor-switch.txt`](../output/transistor-switch.txt) — NPN low-side switch model with exact arithmetic and cutoff-versus-saturation checks.
|
|
46
|
-
|
|
47
|
-
### Deep-classification stress tests
|
|
48
|
-
|
|
49
|
-
- [`../deep-taxonomy-10.n3`](../deep-taxonomy-10.n3) · [`../output/deep-taxonomy-10.txt`](../output/deep-taxonomy-10.txt) — ARC-style deep-taxonomy benchmark at depth 10.
|
|
50
|
-
- [`../deep-taxonomy-100.n3`](../deep-taxonomy-100.n3) · [`../output/deep-taxonomy-100.txt`](../output/deep-taxonomy-100.txt) — ARC-style deep-taxonomy benchmark at depth 100.
|
|
51
|
-
- [`../deep-taxonomy-1000.n3`](../deep-taxonomy-1000.n3) · [`../output/deep-taxonomy-1000.txt`](../output/deep-taxonomy-1000.txt) — ARC-style deep-taxonomy benchmark at depth 1000.
|
|
52
|
-
- [`../deep-taxonomy-10000.n3`](../deep-taxonomy-10000.n3) · [`../output/deep-taxonomy-10000.txt`](../output/deep-taxonomy-10000.txt) — ARC-style deep-taxonomy benchmark at depth 10000.
|
|
53
|
-
- [`../deep-taxonomy-100000.n3`](../deep-taxonomy-100000.n3) · [`../output/deep-taxonomy-100000.txt`](../output/deep-taxonomy-100000.txt) — ARC-style deep-taxonomy benchmark at depth 100000.
|
|
54
|
-
|
|
55
|
-
## Why these examples fit together
|
|
56
|
-
|
|
57
|
-
These files all present reasoning in a recognizably ARC-like way: they derive an answer, make the reason visible in a compact report, and include checks that are meant to catch real mistakes. Some are classical logic or numeric examples; others show how Eyeling can express policy-aware, insight-oriented decision flows without collapsing everything into opaque application code.
|
|
9
|
+
- a brief explanation of ARC,
|
|
10
|
+
- a brief explanation of the Insight Economy,
|
|
11
|
+
- and links to the ARC-style examples in `examples/` together with their outputs in `examples/output/`.
|
|
@@ -28,6 +28,7 @@ Completed grid
|
|
|
28
28
|
3 5 6 | 4 7 8 | 2 1 9
|
|
29
29
|
2 4 1 | 9 3 5 | 8 6 7
|
|
30
30
|
8 9 7 | 2 6 1 | 3 5 4
|
|
31
|
+
|
|
31
32
|
=== Reason Why ===
|
|
32
33
|
The solver starts from 23 clues and fills the remaining 58 cells by combining constraint propagation with depth-first search. At each step it chooses the empty cell with the fewest legal digits, places forced singles immediately, and only guesses when more than one candidate remains. Across the search it made 213 forced placements and tried 22 guesses, visited 23 search nodes overall, and backtracked 12 times before reaching the completed grid. The solver also confirmed that the solution is unique. Early steps: r2c3=4: guess, r5c3=3: forced, r2c1=5: guess, r2c4=1: guess, r2c6=9: forced, r2c7=6: guess, r2c8=7: forced, r1c7=4: guess, … and 50 more placements
|
|
33
34
|
|
package/examples/sudoku.n3
CHANGED
|
@@ -114,8 +114,8 @@
|
|
|
114
114
|
log:outputString ?puzzleText ;
|
|
115
115
|
log:outputString "\n" ;
|
|
116
116
|
log:outputString "Completed grid\n" ;
|
|
117
|
-
log:outputString ?solutionText
|
|
118
|
-
|
|
117
|
+
log:outputString ?solutionText .
|
|
118
|
+
:01b-answer log:outputString "\n" .
|
|
119
119
|
:02-reason log:outputString "=== Reason Why ===\n" ;
|
|
120
120
|
log:outputString ?reasonText ;
|
|
121
121
|
log:outputString "\n\n" .
|
package/eyeling.js
CHANGED
|
@@ -1338,6 +1338,15 @@ function parseXsdFloatSpecialLex(s) {
|
|
|
1338
1338
|
return null;
|
|
1339
1339
|
}
|
|
1340
1340
|
|
|
1341
|
+
function inferDatatypeForShorthandLexical(lex) {
|
|
1342
|
+
if (typeof lex !== 'string' || isQuotedLexical(lex)) return null;
|
|
1343
|
+
if (lex === 'true' || lex === 'false') return XSD_NS + 'boolean';
|
|
1344
|
+
if (/^[+-]?\d+$/.test(lex)) return XSD_NS + 'integer';
|
|
1345
|
+
if (/^[+-]?(?:\d+\.\d*|\.\d+)$/.test(lex)) return XSD_NS + 'decimal';
|
|
1346
|
+
if (/^[+-]?(?:\d+\.\d*|\.\d+|\d+)(?:[eE][+-]?\d+)$/.test(lex)) return XSD_NS + 'double';
|
|
1347
|
+
return null;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1341
1350
|
// ===========================================================================
|
|
1342
1351
|
// Math builtin helpers
|
|
1343
1352
|
// ===========================================================================
|
|
@@ -3850,6 +3859,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3850
3859
|
if (oDt === null) {
|
|
3851
3860
|
if (literalHasLangTag(g.o.value)) oDt = RDF_NS + 'langString';
|
|
3852
3861
|
else if (isPlainStringLiteralValue(g.o.value)) oDt = XSD_NS + 'string';
|
|
3862
|
+
else oDt = inferDatatypeForShorthandLexical(oLex);
|
|
3853
3863
|
}
|
|
3854
3864
|
|
|
3855
3865
|
if (oDt !== null) {
|
|
@@ -3964,6 +3974,23 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3964
3974
|
results.push(s2);
|
|
3965
3975
|
}
|
|
3966
3976
|
|
|
3977
|
+
// Also match quoted log:implies triples present as data in the current scope.
|
|
3978
|
+
if (facts && typeof facts.length === 'number') {
|
|
3979
|
+
ensureFactIndexes(facts);
|
|
3980
|
+
const pb = facts.__byPred.get(goal.p.__tid) || [];
|
|
3981
|
+
for (const idx of pb) {
|
|
3982
|
+
const tr = facts[idx];
|
|
3983
|
+
|
|
3984
|
+
let s2 = unifyTerm(goal.s, tr.s, subst);
|
|
3985
|
+
if (s2 === null) continue;
|
|
3986
|
+
|
|
3987
|
+
s2 = unifyTerm(goal.o, tr.o, s2);
|
|
3988
|
+
if (s2 === null) continue;
|
|
3989
|
+
|
|
3990
|
+
results.push(s2);
|
|
3991
|
+
}
|
|
3992
|
+
}
|
|
3993
|
+
|
|
3967
3994
|
return results;
|
|
3968
3995
|
}
|
|
3969
3996
|
|
|
@@ -3993,6 +4020,23 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3993
4020
|
results.push(s2);
|
|
3994
4021
|
}
|
|
3995
4022
|
|
|
4023
|
+
// Also match quoted log:impliedBy triples present as data in the current scope.
|
|
4024
|
+
if (facts && typeof facts.length === 'number') {
|
|
4025
|
+
ensureFactIndexes(facts);
|
|
4026
|
+
const pb = facts.__byPred.get(goal.p.__tid) || [];
|
|
4027
|
+
for (const idx of pb) {
|
|
4028
|
+
const tr = facts[idx];
|
|
4029
|
+
|
|
4030
|
+
let s2 = unifyTerm(goal.s, tr.s, subst);
|
|
4031
|
+
if (s2 === null) continue;
|
|
4032
|
+
|
|
4033
|
+
s2 = unifyTerm(goal.o, tr.o, s2);
|
|
4034
|
+
if (s2 === null) continue;
|
|
4035
|
+
|
|
4036
|
+
results.push(s2);
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
|
|
3996
4040
|
return results;
|
|
3997
4041
|
}
|
|
3998
4042
|
|
package/lib/builtins.js
CHANGED
|
@@ -859,6 +859,15 @@ function parseXsdFloatSpecialLex(s) {
|
|
|
859
859
|
return null;
|
|
860
860
|
}
|
|
861
861
|
|
|
862
|
+
function inferDatatypeForShorthandLexical(lex) {
|
|
863
|
+
if (typeof lex !== 'string' || isQuotedLexical(lex)) return null;
|
|
864
|
+
if (lex === 'true' || lex === 'false') return XSD_NS + 'boolean';
|
|
865
|
+
if (/^[+-]?\d+$/.test(lex)) return XSD_NS + 'integer';
|
|
866
|
+
if (/^[+-]?(?:\d+\.\d*|\.\d+)$/.test(lex)) return XSD_NS + 'decimal';
|
|
867
|
+
if (/^[+-]?(?:\d+\.\d*|\.\d+|\d+)(?:[eE][+-]?\d+)$/.test(lex)) return XSD_NS + 'double';
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
|
|
862
871
|
// ===========================================================================
|
|
863
872
|
// Math builtin helpers
|
|
864
873
|
// ===========================================================================
|
|
@@ -3371,6 +3380,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3371
3380
|
if (oDt === null) {
|
|
3372
3381
|
if (literalHasLangTag(g.o.value)) oDt = RDF_NS + 'langString';
|
|
3373
3382
|
else if (isPlainStringLiteralValue(g.o.value)) oDt = XSD_NS + 'string';
|
|
3383
|
+
else oDt = inferDatatypeForShorthandLexical(oLex);
|
|
3374
3384
|
}
|
|
3375
3385
|
|
|
3376
3386
|
if (oDt !== null) {
|
|
@@ -3485,6 +3495,23 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3485
3495
|
results.push(s2);
|
|
3486
3496
|
}
|
|
3487
3497
|
|
|
3498
|
+
// Also match quoted log:implies triples present as data in the current scope.
|
|
3499
|
+
if (facts && typeof facts.length === 'number') {
|
|
3500
|
+
ensureFactIndexes(facts);
|
|
3501
|
+
const pb = facts.__byPred.get(goal.p.__tid) || [];
|
|
3502
|
+
for (const idx of pb) {
|
|
3503
|
+
const tr = facts[idx];
|
|
3504
|
+
|
|
3505
|
+
let s2 = unifyTerm(goal.s, tr.s, subst);
|
|
3506
|
+
if (s2 === null) continue;
|
|
3507
|
+
|
|
3508
|
+
s2 = unifyTerm(goal.o, tr.o, s2);
|
|
3509
|
+
if (s2 === null) continue;
|
|
3510
|
+
|
|
3511
|
+
results.push(s2);
|
|
3512
|
+
}
|
|
3513
|
+
}
|
|
3514
|
+
|
|
3488
3515
|
return results;
|
|
3489
3516
|
}
|
|
3490
3517
|
|
|
@@ -3514,6 +3541,23 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3514
3541
|
results.push(s2);
|
|
3515
3542
|
}
|
|
3516
3543
|
|
|
3544
|
+
// Also match quoted log:impliedBy triples present as data in the current scope.
|
|
3545
|
+
if (facts && typeof facts.length === 'number') {
|
|
3546
|
+
ensureFactIndexes(facts);
|
|
3547
|
+
const pb = facts.__byPred.get(goal.p.__tid) || [];
|
|
3548
|
+
for (const idx of pb) {
|
|
3549
|
+
const tr = facts[idx];
|
|
3550
|
+
|
|
3551
|
+
let s2 = unifyTerm(goal.s, tr.s, subst);
|
|
3552
|
+
if (s2 === null) continue;
|
|
3553
|
+
|
|
3554
|
+
s2 = unifyTerm(goal.o, tr.o, s2);
|
|
3555
|
+
if (s2 === null) continue;
|
|
3556
|
+
|
|
3557
|
+
results.push(s2);
|
|
3558
|
+
}
|
|
3559
|
+
}
|
|
3560
|
+
|
|
3517
3561
|
return results;
|
|
3518
3562
|
}
|
|
3519
3563
|
|
package/package.json
CHANGED
package/test/api.test.js
CHANGED
|
@@ -2152,6 +2152,90 @@ _:x :hates { _:foo :making :mess }.
|
|
|
2152
2152
|
],
|
|
2153
2153
|
notExpect: [/:result\s+:sumX\s+"329"\^\^xsd:decimal\s*\./, /:result\s+:meanX\s+"47"\^\^xsd:decimal\s*\./],
|
|
2154
2154
|
},
|
|
2155
|
+
{
|
|
2156
|
+
name: '244 regression: log:dtlit recognizes shorthand numeric and boolean literals',
|
|
2157
|
+
opt: { proofComments: false },
|
|
2158
|
+
input: `@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
2159
|
+
@prefix log: <http://www.w3.org/2000/10/swap/log#> .
|
|
2160
|
+
@prefix : <http://example.org#> .
|
|
2161
|
+
|
|
2162
|
+
:let :term 4, 2.5, 3e1, true, "3"^^xsd:integer .
|
|
2163
|
+
|
|
2164
|
+
{
|
|
2165
|
+
:let :term ?term .
|
|
2166
|
+
(?text ?datatype) log:dtlit ?term .
|
|
2167
|
+
}
|
|
2168
|
+
=>
|
|
2169
|
+
{
|
|
2170
|
+
?term :is (?text ?datatype) .
|
|
2171
|
+
}.
|
|
2172
|
+
`,
|
|
2173
|
+
expect: [
|
|
2174
|
+
/^4\s+:is\s+\("4"\s+xsd:integer\)\s*\./m,
|
|
2175
|
+
/^2\.5\s+:is\s+\("2\.5"\s+xsd:decimal\)\s*\./m,
|
|
2176
|
+
/^3e1\s+:is\s+\("3e1"\s+xsd:double\)\s*\./m,
|
|
2177
|
+
/^true\s+:is\s+\("true"\s+xsd:boolean\)\s*\./m,
|
|
2178
|
+
/^"3"\^\^xsd:integer\s+:is\s+\("3"\s+xsd:integer\)\s*\./m,
|
|
2179
|
+
],
|
|
2180
|
+
},
|
|
2181
|
+
{
|
|
2182
|
+
name: '245 regression: log:includes sees quoted log:implies triples as data',
|
|
2183
|
+
opt: { proofComments: false },
|
|
2184
|
+
input: `@prefix : <http://example.org/> .
|
|
2185
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
|
|
2186
|
+
@prefix log: <http://www.w3.org/2000/10/swap/log#> .
|
|
2187
|
+
|
|
2188
|
+
<> :data {
|
|
2189
|
+
{
|
|
2190
|
+
?A a ?B .
|
|
2191
|
+
?B rdfs:subClassOf ?C.
|
|
2192
|
+
}
|
|
2193
|
+
=>
|
|
2194
|
+
{
|
|
2195
|
+
?A a ?C .
|
|
2196
|
+
}.
|
|
2197
|
+
}.
|
|
2198
|
+
|
|
2199
|
+
{
|
|
2200
|
+
?W :data ?F.
|
|
2201
|
+
?F log:includes { ?X log:implies ?Y }.
|
|
2202
|
+
}
|
|
2203
|
+
=>
|
|
2204
|
+
{
|
|
2205
|
+
:result :is ?X .
|
|
2206
|
+
}.
|
|
2207
|
+
`,
|
|
2208
|
+
expect: [/^:result\s+:is\s+\{[\s\S]*\?A\s+a\s+\?B\s*\.[\s\S]*\?B\s+rdfs:subClassOf\s+\?C\s*\.[\s\S]*\}\s*\./m],
|
|
2209
|
+
},
|
|
2210
|
+
{
|
|
2211
|
+
name: '246 regression: log:includes sees quoted log:impliedBy triples as data',
|
|
2212
|
+
opt: { proofComments: false },
|
|
2213
|
+
input: `@prefix : <http://example.org/> .
|
|
2214
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
|
|
2215
|
+
@prefix log: <http://www.w3.org/2000/10/swap/log#> .
|
|
2216
|
+
|
|
2217
|
+
<> :data {
|
|
2218
|
+
{
|
|
2219
|
+
?A a ?C .
|
|
2220
|
+
}
|
|
2221
|
+
<=
|
|
2222
|
+
{
|
|
2223
|
+
?A a ?B .
|
|
2224
|
+
?B rdfs:subClassOf ?C.
|
|
2225
|
+
}.
|
|
2226
|
+
}.
|
|
2227
|
+
|
|
2228
|
+
{
|
|
2229
|
+
?W :data ?F.
|
|
2230
|
+
?F log:includes { ?Y <= ?X }.
|
|
2231
|
+
}
|
|
2232
|
+
=>
|
|
2233
|
+
{
|
|
2234
|
+
:result :is ?X .
|
|
2235
|
+
}.
|
|
2236
|
+
`,
|
|
2237
|
+
expect: [/^:result\s+:is\s+\{[\s\S]*\?A\s+a\s+\?B\s*\.[\s\S]*\?B\s+rdfs:subClassOf\s+\?C\s*\.[\s\S]*\}\s*\./m],
|
|
2238
|
+
},
|
|
2155
2239
|
];
|
|
2156
2240
|
|
|
2157
2241
|
let passed = 0;
|