n3 2.2.8 → 2.2.9
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/browser/n3.esm.min.js +1 -1
- package/browser/n3.min.js +1 -1
- package/lib/N3Reasoner.js +57 -41
- package/package.json +1 -1
- package/src/N3Reasoner.js +62 -33
package/lib/N3Reasoner.js
CHANGED
|
@@ -33,7 +33,7 @@ class N3Reasoner {
|
|
|
33
33
|
// Caps a rule's premise count, as `_evaluatePremise` recurses once per premise
|
|
34
34
|
this._maxPremiseDepth = options.maxPremiseDepth === undefined ? Infinity : options.maxPremiseDepth;
|
|
35
35
|
}
|
|
36
|
-
_add(subject, predicate, object, graphItem, cb) {
|
|
36
|
+
_add(subject, predicate, object, graphItem, c, cb) {
|
|
37
37
|
// Only add to the remaining indexes if there is not already a value in the index
|
|
38
38
|
if (!this._store._addToIndex(graphItem.subjects, subject, predicate, object)) return;
|
|
39
39
|
this._store._addToIndex(graphItem.predicates, predicate, object, subject);
|
|
@@ -42,43 +42,63 @@ class N3Reasoner {
|
|
|
42
42
|
// after all three indexes are updated, so a caught error leaves the store
|
|
43
43
|
// in a consistent state (the reasoning result is merely incomplete).
|
|
44
44
|
if (++this._derivations > this._maxDerivations) throw new Error(`Reasoning exceeded the maximum of ${this._maxDerivations} derivations`);
|
|
45
|
-
cb();
|
|
45
|
+
cb(c);
|
|
46
46
|
}
|
|
47
|
+
|
|
48
|
+
// Emit conclusions without allocating per-match callbacks
|
|
49
|
+
_emit(rule, content, cb) {
|
|
50
|
+
const conclusion = rule.conclusion;
|
|
51
|
+
for (let k = 0; k < conclusion.length; k++) {
|
|
52
|
+
const c = conclusion[k];
|
|
53
|
+
this._add(c.subject.value, c.predicate.value, c.object.value, content, c, cb);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Bound values use direct lookups; unbound values scan the index
|
|
47
58
|
_evaluatePremise(rule, content, cb, i = 0) {
|
|
48
|
-
let
|
|
59
|
+
let value, index1;
|
|
49
60
|
const [val0, val1, val2] = rule.premise[i].value,
|
|
50
61
|
index = content[rule.premise[i].content];
|
|
62
|
+
const last = i === rule.premise.length - 1;
|
|
51
63
|
const v0 = !(value = val0.value);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
64
|
+
if (v0) {
|
|
65
|
+
// Intermediate index entries are always non-empty
|
|
66
|
+
for (value in index) {
|
|
67
|
+
index1 = index[value];
|
|
68
|
+
val0.value = Number(value);
|
|
69
|
+
this._evaluateLevel1(rule, content, cb, i, last, val1, val2, index1);
|
|
70
|
+
}
|
|
71
|
+
val0.value = null;
|
|
72
|
+
} else if (index1 = index[value]) {
|
|
73
|
+
this._evaluateLevel1(rule, content, cb, i, last, val1, val2, index1);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
_evaluateLevel1(rule, content, cb, i, last, val1, val2, index1) {
|
|
77
|
+
let value, index2;
|
|
78
|
+
const v1 = !(value = val1.value);
|
|
79
|
+
if (v1) {
|
|
80
|
+
for (value in index1) {
|
|
81
|
+
index2 = index1[value];
|
|
82
|
+
val1.value = Number(value);
|
|
83
|
+
this._evaluateLevel2(rule, content, cb, i, last, val2, index2);
|
|
84
|
+
}
|
|
85
|
+
val1.value = null;
|
|
86
|
+
} else if (index2 = index1[value]) {
|
|
87
|
+
this._evaluateLevel2(rule, content, cb, i, last, val2, index2);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
_evaluateLevel2(rule, content, cb, i, last, val2, index2) {
|
|
91
|
+
let value;
|
|
92
|
+
const v2 = !(value = val2.value);
|
|
93
|
+
if (v2) {
|
|
94
|
+
for (value in index2) {
|
|
95
|
+
val2.value = Number(value);
|
|
96
|
+
if (last) this._emit(rule, content, cb);else this._evaluatePremise(rule, content, cb, i + 1);
|
|
79
97
|
}
|
|
98
|
+
val2.value = null;
|
|
80
99
|
}
|
|
81
|
-
|
|
100
|
+
// Bound leaves run once even when the key is absent
|
|
101
|
+
else if (last) this._emit(rule, content, cb);else this._evaluatePremise(rule, content, cb, i + 1);
|
|
82
102
|
}
|
|
83
103
|
_evaluateRules(rules, content, cb) {
|
|
84
104
|
for (let i = 0; i < rules.length; i++) {
|
|
@@ -96,14 +116,12 @@ class N3Reasoner {
|
|
|
96
116
|
});
|
|
97
117
|
}
|
|
98
118
|
|
|
99
|
-
//
|
|
119
|
+
// Reuse addRule instead of allocating a callback per conclusion
|
|
100
120
|
const addConclusions = conclusion => {
|
|
101
|
-
conclusion.
|
|
102
|
-
|
|
103
|
-
this._add(c.subject.value, c.predicate.value, c.object.value, content,
|
|
104
|
-
|
|
105
|
-
});
|
|
106
|
-
});
|
|
121
|
+
for (let k = 0; k < conclusion.length; k++) {
|
|
122
|
+
const c = conclusion[k];
|
|
123
|
+
this._add(c.subject.value, c.predicate.value, c.object.value, content, c, addRule);
|
|
124
|
+
}
|
|
107
125
|
};
|
|
108
126
|
this._evaluateRules(rules, content, addRule);
|
|
109
127
|
let r;
|
|
@@ -194,9 +212,7 @@ class N3Reasoner {
|
|
|
194
212
|
basePremise: p
|
|
195
213
|
});
|
|
196
214
|
}
|
|
197
|
-
r2.variables.
|
|
198
|
-
v.value = null;
|
|
199
|
-
});
|
|
215
|
+
for (let k = 0; k < r2.variables.length; k++) r2.variables[k].value = null;
|
|
200
216
|
}
|
|
201
217
|
}
|
|
202
218
|
}
|
package/package.json
CHANGED
package/src/N3Reasoner.js
CHANGED
|
@@ -22,7 +22,7 @@ export default class N3Reasoner {
|
|
|
22
22
|
this._maxPremiseDepth = options.maxPremiseDepth === undefined ? Infinity : options.maxPremiseDepth;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
_add(subject, predicate, object, graphItem, cb) {
|
|
25
|
+
_add(subject, predicate, object, graphItem, c, cb) {
|
|
26
26
|
// Only add to the remaining indexes if there is not already a value in the index
|
|
27
27
|
if (!this._store._addToIndex(graphItem.subjects, subject, predicate, object)) return;
|
|
28
28
|
this._store._addToIndex(graphItem.predicates, predicate, object, subject);
|
|
@@ -32,39 +32,68 @@ export default class N3Reasoner {
|
|
|
32
32
|
// in a consistent state (the reasoning result is merely incomplete).
|
|
33
33
|
if (++this._derivations > this._maxDerivations)
|
|
34
34
|
throw new Error(`Reasoning exceeded the maximum of ${this._maxDerivations} derivations`);
|
|
35
|
-
cb();
|
|
35
|
+
cb(c);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// Emit conclusions without allocating per-match callbacks
|
|
39
|
+
_emit(rule, content, cb) {
|
|
40
|
+
const conclusion = rule.conclusion;
|
|
41
|
+
for (let k = 0; k < conclusion.length; k++) {
|
|
42
|
+
const c = conclusion[k];
|
|
43
|
+
this._add(c.subject.value, c.predicate.value, c.object.value, content, c, cb);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Bound values use direct lookups; unbound values scan the index
|
|
38
48
|
_evaluatePremise(rule, content, cb, i = 0) {
|
|
39
|
-
let
|
|
49
|
+
let value, index1;
|
|
40
50
|
const [val0, val1, val2] = rule.premise[i].value, index = content[rule.premise[i].content];
|
|
51
|
+
const last = i === rule.premise.length - 1;
|
|
41
52
|
const v0 = !(value = val0.value);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (v1) val1.value = null;
|
|
53
|
+
if (v0) {
|
|
54
|
+
// Intermediate index entries are always non-empty
|
|
55
|
+
for (value in index) {
|
|
56
|
+
index1 = index[value];
|
|
57
|
+
val0.value = Number(value);
|
|
58
|
+
this._evaluateLevel1(rule, content, cb, i, last, val1, val2, index1);
|
|
59
|
+
}
|
|
60
|
+
val0.value = null;
|
|
61
|
+
}
|
|
62
|
+
else if (index1 = index[value]) {
|
|
63
|
+
this._evaluateLevel1(rule, content, cb, i, last, val1, val2, index1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
_evaluateLevel1(rule, content, cb, i, last, val1, val2, index1) {
|
|
68
|
+
let value, index2;
|
|
69
|
+
const v1 = !(value = val1.value);
|
|
70
|
+
if (v1) {
|
|
71
|
+
for (value in index1) {
|
|
72
|
+
index2 = index1[value];
|
|
73
|
+
val1.value = Number(value);
|
|
74
|
+
this._evaluateLevel2(rule, content, cb, i, last, val2, index2);
|
|
65
75
|
}
|
|
76
|
+
val1.value = null;
|
|
77
|
+
}
|
|
78
|
+
else if (index2 = index1[value]) {
|
|
79
|
+
this._evaluateLevel2(rule, content, cb, i, last, val2, index2);
|
|
66
80
|
}
|
|
67
|
-
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
_evaluateLevel2(rule, content, cb, i, last, val2, index2) {
|
|
84
|
+
let value;
|
|
85
|
+
const v2 = !(value = val2.value);
|
|
86
|
+
if (v2) {
|
|
87
|
+
for (value in index2) {
|
|
88
|
+
val2.value = Number(value);
|
|
89
|
+
if (last) this._emit(rule, content, cb);
|
|
90
|
+
else this._evaluatePremise(rule, content, cb, i + 1);
|
|
91
|
+
}
|
|
92
|
+
val2.value = null;
|
|
93
|
+
}
|
|
94
|
+
// Bound leaves run once even when the key is absent
|
|
95
|
+
else if (last) this._emit(rule, content, cb);
|
|
96
|
+
else this._evaluatePremise(rule, content, cb, i + 1);
|
|
68
97
|
}
|
|
69
98
|
|
|
70
99
|
_evaluateRules(rules, content, cb) {
|
|
@@ -85,12 +114,12 @@ export default class N3Reasoner {
|
|
|
85
114
|
});
|
|
86
115
|
}
|
|
87
116
|
|
|
88
|
-
//
|
|
117
|
+
// Reuse addRule instead of allocating a callback per conclusion
|
|
89
118
|
const addConclusions = conclusion => {
|
|
90
|
-
conclusion.
|
|
91
|
-
|
|
92
|
-
this._add(c.subject.value, c.predicate.value, c.object.value, content,
|
|
93
|
-
}
|
|
119
|
+
for (let k = 0; k < conclusion.length; k++) {
|
|
120
|
+
const c = conclusion[k];
|
|
121
|
+
this._add(c.subject.value, c.predicate.value, c.object.value, content, c, addRule);
|
|
122
|
+
}
|
|
94
123
|
};
|
|
95
124
|
|
|
96
125
|
this._evaluateRules(rules, content, addRule);
|
|
@@ -185,7 +214,7 @@ export default class N3Reasoner {
|
|
|
185
214
|
basePremise: p,
|
|
186
215
|
});
|
|
187
216
|
}
|
|
188
|
-
r2.variables.
|
|
217
|
+
for (let k = 0; k < r2.variables.length; k++) r2.variables[k].value = null;
|
|
189
218
|
}
|
|
190
219
|
}
|
|
191
220
|
}
|