eyeling 1.24.1 → 1.24.3
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 +134 -0
- package/dist/browser/eyeling.browser.js +454 -22
- package/eyeling.js +454 -22
- package/index.js +2 -0
- package/lib/cli.js +27 -10
- package/lib/engine.js +17 -7
- package/lib/lexer.js +295 -2
- package/lib/multisource.js +9 -2
- package/lib/printing.js +106 -1
- package/package.json +1 -1
- package/see/README.md +4 -0
- package/see/examples/_see.js +33 -2
- package/see/examples/age.js +27 -1
- package/see/examples/annotation.js +27 -1
- package/see/examples/backward.js +27 -1
- package/see/examples/backward_recursion.js +27 -1
- package/see/examples/bayes_diagnosis.js +27 -1
- package/see/examples/bayes_therapy.js +27 -1
- package/see/examples/bmi.js +27 -1
- package/see/examples/builtin_coverage.js +27 -1
- package/see/examples/collection.js +27 -1
- package/see/examples/complex.js +27 -1
- package/see/examples/complex_matrix_stability.js +27 -1
- package/see/examples/composition_of_injective_functions_is_injective.js +27 -1
- package/see/examples/control_system.js +27 -1
- package/see/examples/crypto_builtins_tests.js +27 -1
- package/see/examples/delfour.js +27 -1
- package/see/examples/digital_product_passport.js +27 -1
- package/see/examples/dijkstra.js +27 -1
- package/see/examples/dijkstra_risk_path.js +27 -1
- package/see/examples/doc/rdf_dataset.md +26 -0
- package/see/examples/doc/triple_terms.md +26 -0
- package/see/examples/dog.js +27 -1
- package/see/examples/eco_route_insight.js +27 -1
- package/see/examples/equals.js +27 -1
- package/see/examples/equivalence_classes_overlap_implies_same_class.js +27 -1
- package/see/examples/euler_identity.js +27 -1
- package/see/examples/ev_roundtrip_planner.js +27 -1
- package/see/examples/existential_rule.js +27 -1
- package/see/examples/expression_eval.js +27 -1
- package/see/examples/family_cousins.js +27 -1
- package/see/examples/fastpow.js +27 -1
- package/see/examples/fibonacci.js +27 -1
- package/see/examples/french_cities.js +27 -1
- package/see/examples/fundamental_theorem_arithmetic.js +27 -1
- package/see/examples/genetic_knapsack_selection.js +27 -1
- package/see/examples/goldbach_1000.js +27 -1
- package/see/examples/good_cobbler.js +27 -1
- package/see/examples/gps.js +27 -1
- package/see/examples/gray_code_counter.js +27 -1
- package/see/examples/greatest_lower_bound_uniqueness.js +27 -1
- package/see/examples/group_inverse_uniqueness.js +27 -1
- package/see/examples/hadamard_approx.js +27 -1
- package/see/examples/hanoi.js +27 -1
- package/see/examples/input/rdf_dataset.trig +34 -0
- package/see/examples/input/triple_terms.trig +28 -0
- package/see/examples/n3/rdf_dataset.n3 +34 -0
- package/see/examples/n3/triple_terms.n3 +23 -0
- package/see/examples/odrl_dpv_risk_ranked.js +27 -1
- package/see/examples/output/rdf_dataset.md +54 -0
- package/see/examples/output/triple_terms.md +53 -0
- package/see/examples/path_discovery.js +27 -1
- package/see/examples/rc_discharge_envelope.js +27 -1
- package/see/examples/rdf_dataset.js +1512 -0
- package/see/examples/rdf_message_flow.js +27 -1
- package/see/examples/rdf_messages.js +27 -1
- package/see/examples/school_placement_audit.js +27 -1
- package/see/examples/smoke_arithmetic.js +27 -1
- package/see/examples/socrates.js +27 -1
- package/see/examples/triple_terms.js +1442 -0
- package/see/examples/wind_turbine.js +27 -1
- package/see/examples/witch.js +27 -1
- package/see/see.js +101 -4
- package/test/api.test.js +86 -0
- package/test/see.test.js +0 -0
- package/tools/bundle.js +0 -0
- package/tools/n3gen.js +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Triple terms
|
|
2
|
+
|
|
3
|
+
## Entailment
|
|
4
|
+
The compiled query selected 1 fact(s) after the rule closure was computed.
|
|
5
|
+
Main entailment: **:observation :entails <<( :sensor :needs :inspection )>>.**
|
|
6
|
+
|
|
7
|
+
Selected entailments:
|
|
8
|
+
- :observation :entails <<( :sensor :needs :inspection )>> .
|
|
9
|
+
|
|
10
|
+
## Explanation
|
|
11
|
+
Starts with 2 source fact(s), applies 1 rule(s), and reaches a fixpoint.
|
|
12
|
+
The log:query projection then keeps only the matching fact(s) shown above.
|
|
13
|
+
|
|
14
|
+
Derivation steps:
|
|
15
|
+
- Rule 1: ?observation rdf:reifies <<( ?device :reports ?condition )>>; ?condition :requires ?action => ?observation :entails <<( ?device :needs ?action )>> derives :observation :entails <<( :sensor :needs :inspection )>> .
|
|
16
|
+
- Uses: :observation rdf:reifies <<( :sensor :reports :overheating )>> . _(source)_; :overheating :requires :inspection . _(source)_
|
|
17
|
+
|
|
18
|
+
Selected explanation support:
|
|
19
|
+
- :observation :entails <<( :sensor :needs :inspection )>> . _(derived by Rule 1)_
|
|
20
|
+
- :observation rdf:reifies <<( :sensor :reports :overheating )>> . _(source)_
|
|
21
|
+
- :overheating :requires :inspection . _(source)_
|
|
22
|
+
|
|
23
|
+
The query-selected facts are serialized in the Formal TriG Output section.
|
|
24
|
+
|
|
25
|
+
## Formal TriG Output
|
|
26
|
+
|
|
27
|
+
```trig
|
|
28
|
+
VERSION "1.2"
|
|
29
|
+
|
|
30
|
+
@prefix : <https://eyereasoner.github.io/eyeling/see/examples/triple_terms#> .
|
|
31
|
+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
|
32
|
+
@prefix log: <http://www.w3.org/2000/10/swap/log#> .
|
|
33
|
+
@prefix see: <https://example.org/see#> .
|
|
34
|
+
@prefix in: <https://example.org/see/input#> .
|
|
35
|
+
|
|
36
|
+
:observation :entails <<( :sensor :needs :inspection )>> .
|
|
37
|
+
|
|
38
|
+
in:metadata {
|
|
39
|
+
in:run a see:InputDataset .
|
|
40
|
+
in:run see:name "triple_terms" .
|
|
41
|
+
in:run see:title "Triple terms" .
|
|
42
|
+
in:run see:sourceFile "examples/n3/triple_terms.n3" .
|
|
43
|
+
in:run see:sourceSHA256 "f94fae1b4087f790c085c4dd1570875694238a882213951b457480ee26c06944" .
|
|
44
|
+
in:run see:description "Demonstrates RDF 1.2 TriG triple terms as input evidence and as a derived entailment." .
|
|
45
|
+
in:run see:compiler "see.js N3-to-JS compiler" .
|
|
46
|
+
in:run see:inputFacts 2 .
|
|
47
|
+
in:run see:compiledRules 1 .
|
|
48
|
+
in:run see:compiledBackwardRules 0 .
|
|
49
|
+
in:run see:compiledFuses 0 .
|
|
50
|
+
in:run see:compiledQueries 1 .
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
@@ -8,6 +8,7 @@ const crypto = require('crypto');
|
|
|
8
8
|
|
|
9
9
|
function canonical(term) {
|
|
10
10
|
if (term.kind === 'list') return ['list', term.items.map(canonical)];
|
|
11
|
+
if (term.kind === 'triple') return ['triple', canonical(term.s), canonical(term.p), canonical(term.o)];
|
|
11
12
|
if (term.kind === 'formula') return ['formula', term.atoms.map((a) => [canonical(a.s), canonical(a.p), canonical(a.o)])];
|
|
12
13
|
return [term.kind, term.value];
|
|
13
14
|
}
|
|
@@ -17,6 +18,7 @@ function compoundIndexKey() { return Array.from(arguments).map(termIndexKey).joi
|
|
|
17
18
|
function termIsConcrete(t) {
|
|
18
19
|
if (!t || t.kind === 'var') return false;
|
|
19
20
|
if (t.kind === 'list') return t.items.every(termIsConcrete);
|
|
21
|
+
if (t.kind === 'triple') return termIsConcrete(t.s) && termIsConcrete(t.p) && termIsConcrete(t.o);
|
|
20
22
|
if (t.kind === 'formula') return t.atoms.every((a) => termIsConcrete(a.s) && termIsConcrete(a.p) && termIsConcrete(a.o));
|
|
21
23
|
return true;
|
|
22
24
|
}
|
|
@@ -32,6 +34,7 @@ function primitive(t) {
|
|
|
32
34
|
if (t.kind === 'iri') return t.value.replace(/^:/, '');
|
|
33
35
|
if (t.kind === 'blank') return t.value;
|
|
34
36
|
if (t.kind === 'list') return t.items.map(primitive);
|
|
37
|
+
if (t.kind === 'triple') return termToN3(t);
|
|
35
38
|
if (t.kind === 'formula') return termToN3(t);
|
|
36
39
|
return undefined;
|
|
37
40
|
}
|
|
@@ -52,6 +55,7 @@ function termToN3(t) {
|
|
|
52
55
|
if (t.kind === 'var') return '?' + t.value;
|
|
53
56
|
if (t.kind === 'blank') return t.value.startsWith('_:') ? t.value : '_:' + t.value.replace(/^_+/, '');
|
|
54
57
|
if (t.kind === 'list') return '(' + t.items.map(termToN3).join(' ') + ')';
|
|
58
|
+
if (t.kind === 'triple') return '<<( ' + termToN3(t.s) + ' ' + termToN3(t.p) + ' ' + termToN3(t.o) + ' )>>';
|
|
55
59
|
if (t.kind === 'formula') return '{ ' + t.atoms.map(atomToN3).join(' . ') + ' }';
|
|
56
60
|
return String(t.value ?? t);
|
|
57
61
|
}
|
|
@@ -74,6 +78,7 @@ function resolve(term, env, seen = new Set()) {
|
|
|
74
78
|
return resolve(env[term.value], env, seen);
|
|
75
79
|
}
|
|
76
80
|
if (term.kind === 'list') return list(term.items.map((item) => resolve(item, env, seen)));
|
|
81
|
+
if (term.kind === 'triple') return { kind: 'triple', s: resolve(term.s, env), p: resolve(term.p, env), o: resolve(term.o, env) };
|
|
77
82
|
if (term.kind === 'formula') return { kind: 'formula', atoms: term.atoms.map((a) => ({ s: resolve(a.s, env), p: resolve(a.p, env), o: resolve(a.o, env) })) };
|
|
78
83
|
return term;
|
|
79
84
|
}
|
|
@@ -91,6 +96,14 @@ function unify(a, b, env) {
|
|
|
91
96
|
}
|
|
92
97
|
return out;
|
|
93
98
|
}
|
|
99
|
+
if (a.kind === 'triple' || b.kind === 'triple') {
|
|
100
|
+
if (a.kind !== 'triple' || b.kind !== 'triple') return null;
|
|
101
|
+
let out = unify(a.s, b.s, env);
|
|
102
|
+
if (!out) return null;
|
|
103
|
+
out = unify(a.p, b.p, out);
|
|
104
|
+
if (!out) return null;
|
|
105
|
+
return unify(a.o, b.o, out);
|
|
106
|
+
}
|
|
94
107
|
return deepEqual(a, b) ? env : null;
|
|
95
108
|
}
|
|
96
109
|
function bind(pattern, value, env) { return unify(pattern, value, env); }
|
|
@@ -106,6 +119,7 @@ function termIsGround(t, env) {
|
|
|
106
119
|
const r = resolve(t, env);
|
|
107
120
|
if (r.kind === 'var') return false;
|
|
108
121
|
if (r.kind === 'list') return r.items.every((item) => termIsGround(item, env));
|
|
122
|
+
if (r.kind === 'triple') return termIsGround(r.s, env) && termIsGround(r.p, env) && termIsGround(r.o, env);
|
|
109
123
|
if (r.kind === 'formula') return r.atoms.every((atom) => atomIsGround(atom, env));
|
|
110
124
|
return true;
|
|
111
125
|
}
|
|
@@ -665,6 +679,7 @@ function instantiate(term, env, ruleId) {
|
|
|
665
679
|
}
|
|
666
680
|
if (term.kind === 'blank') return blank('_:r' + ruleId + '_' + envSignature(env) + '_' + term.value.replace(/^_/, ''));
|
|
667
681
|
if (term.kind === 'list') return list(term.items.map((item) => instantiate(item, env, ruleId)));
|
|
682
|
+
if (term.kind === 'triple') return { kind: 'triple', s: instantiate(term.s, env, ruleId), p: instantiate(term.p, env, ruleId), o: instantiate(term.o, env, ruleId) };
|
|
668
683
|
if (term.kind === 'formula') return { kind: 'formula', atoms: term.atoms.map((a) => ({ s: instantiate(a.s, env, ruleId), p: instantiate(a.p, env, ruleId), o: instantiate(a.o, env, ruleId) })) };
|
|
669
684
|
return cloneTerm(term);
|
|
670
685
|
}
|
|
@@ -1683,6 +1698,16 @@ function formalOutputFacts(graph, queries, rules, initialFacts) {
|
|
|
1683
1698
|
}
|
|
1684
1699
|
return out;
|
|
1685
1700
|
}
|
|
1701
|
+
function termHasTripleTerm(term) {
|
|
1702
|
+
if (!term) return false;
|
|
1703
|
+
if (term.kind === 'triple') return true;
|
|
1704
|
+
if (term.kind === 'list') return term.items.some(termHasTripleTerm);
|
|
1705
|
+
if (term.kind === 'formula') return term.atoms.some(atomHasTripleTerm);
|
|
1706
|
+
return false;
|
|
1707
|
+
}
|
|
1708
|
+
function atomHasTripleTerm(atom) { return termHasTripleTerm(atom.s) || termHasTripleTerm(atom.p) || termHasTripleTerm(atom.o); }
|
|
1709
|
+
function factsHaveTripleTerms(facts) { return (facts || []).some(atomHasTripleTerm); }
|
|
1710
|
+
function trigHasVersion12(trig) { return /^s*(?:@version|VERSION)s+["']1.2["']/mi.test(String(trig || '')); }
|
|
1686
1711
|
function trigGraphBlock(label, atoms) {
|
|
1687
1712
|
const lines = [label + ' {'];
|
|
1688
1713
|
for (const atom of atoms || []) lines.push(' ' + atomToN3(atom) + ' .');
|
|
@@ -1730,7 +1755,8 @@ function formalOutputToTrig(facts, trig) {
|
|
|
1730
1755
|
const prefixes = prefixLinesFromTrig(trig);
|
|
1731
1756
|
if (state.needOutPrefix && !prefixes.some((line) => line.toLowerCase().startsWith('@prefix out:'))) prefixes.push('@prefix out: <https://example.org/see/output#> .');
|
|
1732
1757
|
const nl = String.fromCharCode(10);
|
|
1733
|
-
|
|
1758
|
+
const version = factsHaveTripleTerms(facts) ? 'VERSION "1.2"' + nl + nl : '';
|
|
1759
|
+
return version + prefixes.join(nl) + nl + nl + body.join(nl);
|
|
1734
1760
|
}
|
|
1735
1761
|
function appendFormalTrigOutput(markdown, graph, queries, rules, initialFacts, data) {
|
|
1736
1762
|
const trig = formalOutputToTrig(formalOutputFacts(graph, queries, rules, initialFacts), data && data.trig);
|
|
@@ -8,6 +8,7 @@ const crypto = require('crypto');
|
|
|
8
8
|
|
|
9
9
|
function canonical(term) {
|
|
10
10
|
if (term.kind === 'list') return ['list', term.items.map(canonical)];
|
|
11
|
+
if (term.kind === 'triple') return ['triple', canonical(term.s), canonical(term.p), canonical(term.o)];
|
|
11
12
|
if (term.kind === 'formula') return ['formula', term.atoms.map((a) => [canonical(a.s), canonical(a.p), canonical(a.o)])];
|
|
12
13
|
return [term.kind, term.value];
|
|
13
14
|
}
|
|
@@ -17,6 +18,7 @@ function compoundIndexKey() { return Array.from(arguments).map(termIndexKey).joi
|
|
|
17
18
|
function termIsConcrete(t) {
|
|
18
19
|
if (!t || t.kind === 'var') return false;
|
|
19
20
|
if (t.kind === 'list') return t.items.every(termIsConcrete);
|
|
21
|
+
if (t.kind === 'triple') return termIsConcrete(t.s) && termIsConcrete(t.p) && termIsConcrete(t.o);
|
|
20
22
|
if (t.kind === 'formula') return t.atoms.every((a) => termIsConcrete(a.s) && termIsConcrete(a.p) && termIsConcrete(a.o));
|
|
21
23
|
return true;
|
|
22
24
|
}
|
|
@@ -32,6 +34,7 @@ function primitive(t) {
|
|
|
32
34
|
if (t.kind === 'iri') return t.value.replace(/^:/, '');
|
|
33
35
|
if (t.kind === 'blank') return t.value;
|
|
34
36
|
if (t.kind === 'list') return t.items.map(primitive);
|
|
37
|
+
if (t.kind === 'triple') return termToN3(t);
|
|
35
38
|
if (t.kind === 'formula') return termToN3(t);
|
|
36
39
|
return undefined;
|
|
37
40
|
}
|
|
@@ -52,6 +55,7 @@ function termToN3(t) {
|
|
|
52
55
|
if (t.kind === 'var') return '?' + t.value;
|
|
53
56
|
if (t.kind === 'blank') return t.value.startsWith('_:') ? t.value : '_:' + t.value.replace(/^_+/, '');
|
|
54
57
|
if (t.kind === 'list') return '(' + t.items.map(termToN3).join(' ') + ')';
|
|
58
|
+
if (t.kind === 'triple') return '<<( ' + termToN3(t.s) + ' ' + termToN3(t.p) + ' ' + termToN3(t.o) + ' )>>';
|
|
55
59
|
if (t.kind === 'formula') return '{ ' + t.atoms.map(atomToN3).join(' . ') + ' }';
|
|
56
60
|
return String(t.value ?? t);
|
|
57
61
|
}
|
|
@@ -74,6 +78,7 @@ function resolve(term, env, seen = new Set()) {
|
|
|
74
78
|
return resolve(env[term.value], env, seen);
|
|
75
79
|
}
|
|
76
80
|
if (term.kind === 'list') return list(term.items.map((item) => resolve(item, env, seen)));
|
|
81
|
+
if (term.kind === 'triple') return { kind: 'triple', s: resolve(term.s, env), p: resolve(term.p, env), o: resolve(term.o, env) };
|
|
77
82
|
if (term.kind === 'formula') return { kind: 'formula', atoms: term.atoms.map((a) => ({ s: resolve(a.s, env), p: resolve(a.p, env), o: resolve(a.o, env) })) };
|
|
78
83
|
return term;
|
|
79
84
|
}
|
|
@@ -91,6 +96,14 @@ function unify(a, b, env) {
|
|
|
91
96
|
}
|
|
92
97
|
return out;
|
|
93
98
|
}
|
|
99
|
+
if (a.kind === 'triple' || b.kind === 'triple') {
|
|
100
|
+
if (a.kind !== 'triple' || b.kind !== 'triple') return null;
|
|
101
|
+
let out = unify(a.s, b.s, env);
|
|
102
|
+
if (!out) return null;
|
|
103
|
+
out = unify(a.p, b.p, out);
|
|
104
|
+
if (!out) return null;
|
|
105
|
+
return unify(a.o, b.o, out);
|
|
106
|
+
}
|
|
94
107
|
return deepEqual(a, b) ? env : null;
|
|
95
108
|
}
|
|
96
109
|
function bind(pattern, value, env) { return unify(pattern, value, env); }
|
|
@@ -106,6 +119,7 @@ function termIsGround(t, env) {
|
|
|
106
119
|
const r = resolve(t, env);
|
|
107
120
|
if (r.kind === 'var') return false;
|
|
108
121
|
if (r.kind === 'list') return r.items.every((item) => termIsGround(item, env));
|
|
122
|
+
if (r.kind === 'triple') return termIsGround(r.s, env) && termIsGround(r.p, env) && termIsGround(r.o, env);
|
|
109
123
|
if (r.kind === 'formula') return r.atoms.every((atom) => atomIsGround(atom, env));
|
|
110
124
|
return true;
|
|
111
125
|
}
|
|
@@ -665,6 +679,7 @@ function instantiate(term, env, ruleId) {
|
|
|
665
679
|
}
|
|
666
680
|
if (term.kind === 'blank') return blank('_:r' + ruleId + '_' + envSignature(env) + '_' + term.value.replace(/^_/, ''));
|
|
667
681
|
if (term.kind === 'list') return list(term.items.map((item) => instantiate(item, env, ruleId)));
|
|
682
|
+
if (term.kind === 'triple') return { kind: 'triple', s: instantiate(term.s, env, ruleId), p: instantiate(term.p, env, ruleId), o: instantiate(term.o, env, ruleId) };
|
|
668
683
|
if (term.kind === 'formula') return { kind: 'formula', atoms: term.atoms.map((a) => ({ s: instantiate(a.s, env, ruleId), p: instantiate(a.p, env, ruleId), o: instantiate(a.o, env, ruleId) })) };
|
|
669
684
|
return cloneTerm(term);
|
|
670
685
|
}
|
|
@@ -1902,6 +1917,16 @@ function formalOutputFacts(graph, queries, rules, initialFacts) {
|
|
|
1902
1917
|
}
|
|
1903
1918
|
return out;
|
|
1904
1919
|
}
|
|
1920
|
+
function termHasTripleTerm(term) {
|
|
1921
|
+
if (!term) return false;
|
|
1922
|
+
if (term.kind === 'triple') return true;
|
|
1923
|
+
if (term.kind === 'list') return term.items.some(termHasTripleTerm);
|
|
1924
|
+
if (term.kind === 'formula') return term.atoms.some(atomHasTripleTerm);
|
|
1925
|
+
return false;
|
|
1926
|
+
}
|
|
1927
|
+
function atomHasTripleTerm(atom) { return termHasTripleTerm(atom.s) || termHasTripleTerm(atom.p) || termHasTripleTerm(atom.o); }
|
|
1928
|
+
function factsHaveTripleTerms(facts) { return (facts || []).some(atomHasTripleTerm); }
|
|
1929
|
+
function trigHasVersion12(trig) { return /^s*(?:@version|VERSION)s+["']1.2["']/mi.test(String(trig || '')); }
|
|
1905
1930
|
function trigGraphBlock(label, atoms) {
|
|
1906
1931
|
const lines = [label + ' {'];
|
|
1907
1932
|
for (const atom of atoms || []) lines.push(' ' + atomToN3(atom) + ' .');
|
|
@@ -1949,7 +1974,8 @@ function formalOutputToTrig(facts, trig) {
|
|
|
1949
1974
|
const prefixes = prefixLinesFromTrig(trig);
|
|
1950
1975
|
if (state.needOutPrefix && !prefixes.some((line) => line.toLowerCase().startsWith('@prefix out:'))) prefixes.push('@prefix out: <https://example.org/see/output#> .');
|
|
1951
1976
|
const nl = String.fromCharCode(10);
|
|
1952
|
-
|
|
1977
|
+
const version = factsHaveTripleTerms(facts) ? 'VERSION "1.2"' + nl + nl : '';
|
|
1978
|
+
return version + prefixes.join(nl) + nl + nl + body.join(nl);
|
|
1953
1979
|
}
|
|
1954
1980
|
function appendFormalTrigOutput(markdown, graph, queries, rules, initialFacts, data) {
|
|
1955
1981
|
const trig = formalOutputToTrig(formalOutputFacts(graph, queries, rules, initialFacts), data && data.trig);
|