rust-kgdb 0.4.1 → 0.4.2
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 +1236 -1971
- package/examples/business-assertions.test.ts +1196 -0
- package/examples/core-concepts-demo.ts +502 -0
- package/examples/datalog-example.ts +478 -0
- package/examples/embeddings-example.ts +376 -0
- package/examples/graphframes-example.ts +367 -0
- package/examples/hypermind-fraud-underwriter.ts +669 -0
- package/examples/pregel-example.ts +399 -0
- package/package.json +3 -2
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Datalog Example for rust-kgdb TypeScript SDK
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates Datalog reasoning capabilities including:
|
|
5
|
+
* - Adding facts and rules
|
|
6
|
+
* - Semi-naive evaluation
|
|
7
|
+
* - Recursive rule evaluation
|
|
8
|
+
* - Stratified negation
|
|
9
|
+
* - Query evaluation
|
|
10
|
+
* - Integration with RDF graphs
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { DatalogEngine, GraphDb } from 'rust-kgdb';
|
|
14
|
+
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Example 1: Basic Facts and Rules
|
|
17
|
+
// =============================================================================
|
|
18
|
+
|
|
19
|
+
async function basicDatalogExample() {
|
|
20
|
+
console.log('=== Basic Datalog Facts and Rules ===\n');
|
|
21
|
+
|
|
22
|
+
const engine = new DatalogEngine();
|
|
23
|
+
|
|
24
|
+
// Add facts: parent(X, Y) means X is parent of Y
|
|
25
|
+
engine.addFact('parent', ['alice', 'bob']);
|
|
26
|
+
engine.addFact('parent', ['alice', 'carol']);
|
|
27
|
+
engine.addFact('parent', ['bob', 'david']);
|
|
28
|
+
engine.addFact('parent', ['bob', 'eve']);
|
|
29
|
+
engine.addFact('parent', ['carol', 'frank']);
|
|
30
|
+
|
|
31
|
+
console.log('Facts added:');
|
|
32
|
+
console.log(' parent(alice, bob)');
|
|
33
|
+
console.log(' parent(alice, carol)');
|
|
34
|
+
console.log(' parent(bob, david)');
|
|
35
|
+
console.log(' parent(bob, eve)');
|
|
36
|
+
console.log(' parent(carol, frank)\n');
|
|
37
|
+
|
|
38
|
+
// Add rule: grandparent(X, Z) :- parent(X, Y), parent(Y, Z)
|
|
39
|
+
engine.addRule(
|
|
40
|
+
'grandparent', // head predicate
|
|
41
|
+
['X', 'Z'], // head variables
|
|
42
|
+
[
|
|
43
|
+
{ predicate: 'parent', args: ['X', 'Y'] },
|
|
44
|
+
{ predicate: 'parent', args: ['Y', 'Z'] }
|
|
45
|
+
]
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
console.log('Rule added:');
|
|
49
|
+
console.log(' grandparent(X, Z) :- parent(X, Y), parent(Y, Z)\n');
|
|
50
|
+
|
|
51
|
+
// Evaluate to derive all facts
|
|
52
|
+
engine.evaluate();
|
|
53
|
+
|
|
54
|
+
// Query grandparents
|
|
55
|
+
const grandparents = engine.query('grandparent', ['?who', '?grandchild']);
|
|
56
|
+
console.log('Query: grandparent(?who, ?grandchild)');
|
|
57
|
+
console.log('Results:');
|
|
58
|
+
for (const result of grandparents) {
|
|
59
|
+
console.log(` ${result.who} is grandparent of ${result.grandchild}`);
|
|
60
|
+
}
|
|
61
|
+
console.log();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// =============================================================================
|
|
65
|
+
// Example 2: Recursive Rules (Transitive Closure)
|
|
66
|
+
// =============================================================================
|
|
67
|
+
|
|
68
|
+
async function recursiveDatalogExample() {
|
|
69
|
+
console.log('=== Recursive Rules (Transitive Closure) ===\n');
|
|
70
|
+
|
|
71
|
+
const engine = new DatalogEngine();
|
|
72
|
+
|
|
73
|
+
// Add edge facts for a graph
|
|
74
|
+
engine.addFact('edge', ['a', 'b']);
|
|
75
|
+
engine.addFact('edge', ['b', 'c']);
|
|
76
|
+
engine.addFact('edge', ['c', 'd']);
|
|
77
|
+
engine.addFact('edge', ['d', 'e']);
|
|
78
|
+
engine.addFact('edge', ['a', 'c']); // shortcut
|
|
79
|
+
|
|
80
|
+
console.log('Graph edges: a->b, b->c, c->d, d->e, a->c\n');
|
|
81
|
+
|
|
82
|
+
// Base case: path(X, Y) :- edge(X, Y)
|
|
83
|
+
engine.addRule(
|
|
84
|
+
'path',
|
|
85
|
+
['X', 'Y'],
|
|
86
|
+
[{ predicate: 'edge', args: ['X', 'Y'] }]
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// Recursive case: path(X, Z) :- edge(X, Y), path(Y, Z)
|
|
90
|
+
engine.addRule(
|
|
91
|
+
'path',
|
|
92
|
+
['X', 'Z'],
|
|
93
|
+
[
|
|
94
|
+
{ predicate: 'edge', args: ['X', 'Y'] },
|
|
95
|
+
{ predicate: 'path', args: ['Y', 'Z'] }
|
|
96
|
+
]
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
console.log('Rules added:');
|
|
100
|
+
console.log(' path(X, Y) :- edge(X, Y) % base case');
|
|
101
|
+
console.log(' path(X, Z) :- edge(X, Y), path(Y, Z) % recursive case\n');
|
|
102
|
+
|
|
103
|
+
// Evaluate using semi-naive algorithm
|
|
104
|
+
const iterations = engine.evaluateSemiNaive();
|
|
105
|
+
console.log(`Semi-naive evaluation completed in ${iterations} iterations\n`);
|
|
106
|
+
|
|
107
|
+
// Query all paths from 'a'
|
|
108
|
+
const paths = engine.query('path', ['a', '?end']);
|
|
109
|
+
console.log('Query: path(a, ?end)');
|
|
110
|
+
console.log('Results (nodes reachable from a):');
|
|
111
|
+
for (const result of paths) {
|
|
112
|
+
console.log(` a can reach ${result.end}`);
|
|
113
|
+
}
|
|
114
|
+
console.log();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// =============================================================================
|
|
118
|
+
// Example 3: Stratified Negation
|
|
119
|
+
// =============================================================================
|
|
120
|
+
|
|
121
|
+
async function negationDatalogExample() {
|
|
122
|
+
console.log('=== Stratified Negation ===\n');
|
|
123
|
+
|
|
124
|
+
const engine = new DatalogEngine();
|
|
125
|
+
|
|
126
|
+
// Add employee facts
|
|
127
|
+
engine.addFact('employee', ['alice', 'engineering']);
|
|
128
|
+
engine.addFact('employee', ['bob', 'engineering']);
|
|
129
|
+
engine.addFact('employee', ['carol', 'sales']);
|
|
130
|
+
engine.addFact('employee', ['david', 'hr']);
|
|
131
|
+
|
|
132
|
+
// Add manager facts
|
|
133
|
+
engine.addFact('manager', ['alice']);
|
|
134
|
+
engine.addFact('manager', ['carol']);
|
|
135
|
+
|
|
136
|
+
console.log('Facts:');
|
|
137
|
+
console.log(' employee(alice, engineering), employee(bob, engineering)');
|
|
138
|
+
console.log(' employee(carol, sales), employee(david, hr)');
|
|
139
|
+
console.log(' manager(alice), manager(carol)\n');
|
|
140
|
+
|
|
141
|
+
// Rule: non_manager(X) :- employee(X, _), NOT manager(X)
|
|
142
|
+
engine.addRuleWithNegation(
|
|
143
|
+
'non_manager',
|
|
144
|
+
['X'],
|
|
145
|
+
[{ predicate: 'employee', args: ['X', '_'] }],
|
|
146
|
+
[{ predicate: 'manager', args: ['X'] }] // negated atoms
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
console.log('Rule with negation:');
|
|
150
|
+
console.log(' non_manager(X) :- employee(X, _), NOT manager(X)\n');
|
|
151
|
+
|
|
152
|
+
// Stratified evaluation (handles negation correctly)
|
|
153
|
+
engine.evaluateStratified();
|
|
154
|
+
|
|
155
|
+
// Query non-managers
|
|
156
|
+
const nonManagers = engine.query('non_manager', ['?person']);
|
|
157
|
+
console.log('Query: non_manager(?person)');
|
|
158
|
+
console.log('Results:');
|
|
159
|
+
for (const result of nonManagers) {
|
|
160
|
+
console.log(` ${result.person} is not a manager`);
|
|
161
|
+
}
|
|
162
|
+
console.log();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// =============================================================================
|
|
166
|
+
// Example 4: Aggregate Functions
|
|
167
|
+
// =============================================================================
|
|
168
|
+
|
|
169
|
+
async function aggregateDatalogExample() {
|
|
170
|
+
console.log('=== Aggregate Functions ===\n');
|
|
171
|
+
|
|
172
|
+
const engine = new DatalogEngine();
|
|
173
|
+
|
|
174
|
+
// Add sales facts: sale(product, amount, region)
|
|
175
|
+
engine.addFact('sale', ['laptop', '1200', 'west']);
|
|
176
|
+
engine.addFact('sale', ['laptop', '1100', 'east']);
|
|
177
|
+
engine.addFact('sale', ['phone', '800', 'west']);
|
|
178
|
+
engine.addFact('sale', ['phone', '850', 'east']);
|
|
179
|
+
engine.addFact('sale', ['tablet', '500', 'west']);
|
|
180
|
+
engine.addFact('sale', ['tablet', '450', 'east']);
|
|
181
|
+
|
|
182
|
+
console.log('Sales facts added\n');
|
|
183
|
+
|
|
184
|
+
// Rule with aggregation: total_by_product(P, sum(A)) :- sale(P, A, _)
|
|
185
|
+
engine.addAggregateRule(
|
|
186
|
+
'total_by_product',
|
|
187
|
+
['Product', 'Total'],
|
|
188
|
+
{ predicate: 'sale', args: ['Product', 'Amount', '_'] },
|
|
189
|
+
{ function: 'sum', variable: 'Amount', output: 'Total' },
|
|
190
|
+
['Product'] // group by
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
// Rule: avg_by_region(R, avg(A)) :- sale(_, A, R)
|
|
194
|
+
engine.addAggregateRule(
|
|
195
|
+
'avg_by_region',
|
|
196
|
+
['Region', 'Average'],
|
|
197
|
+
{ predicate: 'sale', args: ['_', 'Amount', 'Region'] },
|
|
198
|
+
{ function: 'avg', variable: 'Amount', output: 'Average' },
|
|
199
|
+
['Region']
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
console.log('Aggregate rules added:');
|
|
203
|
+
console.log(' total_by_product(P, sum(A)) :- sale(P, A, _)');
|
|
204
|
+
console.log(' avg_by_region(R, avg(A)) :- sale(_, A, R)\n');
|
|
205
|
+
|
|
206
|
+
engine.evaluate();
|
|
207
|
+
|
|
208
|
+
// Query totals by product
|
|
209
|
+
const totals = engine.query('total_by_product', ['?product', '?total']);
|
|
210
|
+
console.log('Total sales by product:');
|
|
211
|
+
for (const result of totals) {
|
|
212
|
+
console.log(` ${result.product}: $${result.total}`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Query averages by region
|
|
216
|
+
const avgs = engine.query('avg_by_region', ['?region', '?avg']);
|
|
217
|
+
console.log('\nAverage sale by region:');
|
|
218
|
+
for (const result of avgs) {
|
|
219
|
+
console.log(` ${result.region}: $${result.avg}`);
|
|
220
|
+
}
|
|
221
|
+
console.log();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// =============================================================================
|
|
225
|
+
// Example 5: RDF Graph Integration
|
|
226
|
+
// =============================================================================
|
|
227
|
+
|
|
228
|
+
async function rdfIntegrationExample() {
|
|
229
|
+
console.log('=== RDF Graph Integration ===\n');
|
|
230
|
+
|
|
231
|
+
// Create RDF graph
|
|
232
|
+
const db = new GraphDb('http://example.org/company');
|
|
233
|
+
|
|
234
|
+
// Load company data
|
|
235
|
+
const ttl = `
|
|
236
|
+
@prefix ex: <http://example.org/> .
|
|
237
|
+
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
|
|
238
|
+
@prefix org: <http://www.w3.org/ns/org#> .
|
|
239
|
+
|
|
240
|
+
ex:alice a foaf:Person ;
|
|
241
|
+
foaf:name "Alice" ;
|
|
242
|
+
org:memberOf ex:engineering .
|
|
243
|
+
|
|
244
|
+
ex:bob a foaf:Person ;
|
|
245
|
+
foaf:name "Bob" ;
|
|
246
|
+
org:memberOf ex:engineering ;
|
|
247
|
+
org:reportsTo ex:alice .
|
|
248
|
+
|
|
249
|
+
ex:carol a foaf:Person ;
|
|
250
|
+
foaf:name "Carol" ;
|
|
251
|
+
org:memberOf ex:sales .
|
|
252
|
+
|
|
253
|
+
ex:engineering a org:OrganizationalUnit ;
|
|
254
|
+
org:name "Engineering Department" .
|
|
255
|
+
|
|
256
|
+
ex:sales a org:OrganizationalUnit ;
|
|
257
|
+
org:name "Sales Department" .
|
|
258
|
+
`;
|
|
259
|
+
|
|
260
|
+
db.loadTtl(ttl, null);
|
|
261
|
+
console.log('RDF graph loaded with company data\n');
|
|
262
|
+
|
|
263
|
+
// Create Datalog engine from RDF
|
|
264
|
+
const engine = db.toDatalog();
|
|
265
|
+
|
|
266
|
+
// The RDF triples become facts:
|
|
267
|
+
// triple(subject, predicate, object)
|
|
268
|
+
console.log('RDF triples converted to Datalog facts\n');
|
|
269
|
+
|
|
270
|
+
// Add reasoning rules
|
|
271
|
+
// colleague(X, Y) :- memberOf(X, Dept), memberOf(Y, Dept), X != Y
|
|
272
|
+
engine.addRule(
|
|
273
|
+
'colleague',
|
|
274
|
+
['X', 'Y'],
|
|
275
|
+
[
|
|
276
|
+
{ predicate: 'triple', args: ['X', 'http://www.w3.org/ns/org#memberOf', 'Dept'] },
|
|
277
|
+
{ predicate: 'triple', args: ['Y', 'http://www.w3.org/ns/org#memberOf', 'Dept'] }
|
|
278
|
+
],
|
|
279
|
+
{ filter: 'X != Y' }
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
// manager(X, Y) :- reportsTo(Y, X)
|
|
283
|
+
engine.addRule(
|
|
284
|
+
'manager',
|
|
285
|
+
['Manager', 'Employee'],
|
|
286
|
+
[
|
|
287
|
+
{ predicate: 'triple', args: ['Employee', 'http://www.w3.org/ns/org#reportsTo', 'Manager'] }
|
|
288
|
+
]
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
console.log('Reasoning rules added:');
|
|
292
|
+
console.log(' colleague(X, Y) :- memberOf(X, Dept), memberOf(Y, Dept), X != Y');
|
|
293
|
+
console.log(' manager(M, E) :- reportsTo(E, M)\n');
|
|
294
|
+
|
|
295
|
+
engine.evaluate();
|
|
296
|
+
|
|
297
|
+
// Query colleagues
|
|
298
|
+
const colleagues = engine.query('colleague', ['?person1', '?person2']);
|
|
299
|
+
console.log('Colleagues (same department):');
|
|
300
|
+
for (const result of colleagues) {
|
|
301
|
+
console.log(` ${result.person1.split('/').pop()} and ${result.person2.split('/').pop()}`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Query managers
|
|
305
|
+
const managers = engine.query('manager', ['?manager', '?employee']);
|
|
306
|
+
console.log('\nManagement relationships:');
|
|
307
|
+
for (const result of managers) {
|
|
308
|
+
console.log(` ${result.manager.split('/').pop()} manages ${result.employee.split('/').pop()}`);
|
|
309
|
+
}
|
|
310
|
+
console.log();
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// =============================================================================
|
|
314
|
+
// Example 6: Access Control Rules (Practical Application)
|
|
315
|
+
// =============================================================================
|
|
316
|
+
|
|
317
|
+
async function accessControlExample() {
|
|
318
|
+
console.log('=== Access Control Rules ===\n');
|
|
319
|
+
|
|
320
|
+
const engine = new DatalogEngine();
|
|
321
|
+
|
|
322
|
+
// User roles
|
|
323
|
+
engine.addFact('role', ['alice', 'admin']);
|
|
324
|
+
engine.addFact('role', ['bob', 'developer']);
|
|
325
|
+
engine.addFact('role', ['carol', 'developer']);
|
|
326
|
+
engine.addFact('role', ['david', 'viewer']);
|
|
327
|
+
|
|
328
|
+
// Resource permissions by role
|
|
329
|
+
engine.addFact('permission', ['admin', 'read']);
|
|
330
|
+
engine.addFact('permission', ['admin', 'write']);
|
|
331
|
+
engine.addFact('permission', ['admin', 'delete']);
|
|
332
|
+
engine.addFact('permission', ['developer', 'read']);
|
|
333
|
+
engine.addFact('permission', ['developer', 'write']);
|
|
334
|
+
engine.addFact('permission', ['viewer', 'read']);
|
|
335
|
+
|
|
336
|
+
// Resource ownership
|
|
337
|
+
engine.addFact('owns', ['alice', 'resource1']);
|
|
338
|
+
engine.addFact('owns', ['bob', 'resource2']);
|
|
339
|
+
|
|
340
|
+
console.log('Access control facts loaded\n');
|
|
341
|
+
|
|
342
|
+
// Rule: can_access(User, Resource, Action) :- role(User, Role), permission(Role, Action)
|
|
343
|
+
engine.addRule(
|
|
344
|
+
'can_access',
|
|
345
|
+
['User', 'Resource', 'Action'],
|
|
346
|
+
[
|
|
347
|
+
{ predicate: 'role', args: ['User', 'Role'] },
|
|
348
|
+
{ predicate: 'permission', args: ['Role', 'Action'] }
|
|
349
|
+
]
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
// Rule: owner_override(User, Resource, delete) :- owns(User, Resource)
|
|
353
|
+
engine.addRule(
|
|
354
|
+
'can_access',
|
|
355
|
+
['User', 'Resource', 'delete'],
|
|
356
|
+
[
|
|
357
|
+
{ predicate: 'owns', args: ['User', 'Resource'] }
|
|
358
|
+
]
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
console.log('Access control rules:');
|
|
362
|
+
console.log(' can_access(U, R, A) :- role(U, Role), permission(Role, A)');
|
|
363
|
+
console.log(' can_access(U, R, delete) :- owns(U, R) % owner override\n');
|
|
364
|
+
|
|
365
|
+
engine.evaluate();
|
|
366
|
+
|
|
367
|
+
// Check specific access
|
|
368
|
+
const checkAccess = (user: string, action: string) => {
|
|
369
|
+
const results = engine.query('can_access', [user, '?resource', action]);
|
|
370
|
+
return results.length > 0;
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
const checks = [
|
|
374
|
+
['alice', 'delete'],
|
|
375
|
+
['bob', 'write'],
|
|
376
|
+
['bob', 'delete'],
|
|
377
|
+
['david', 'read'],
|
|
378
|
+
['david', 'write']
|
|
379
|
+
];
|
|
380
|
+
|
|
381
|
+
console.log('Access checks:');
|
|
382
|
+
for (const [user, action] of checks) {
|
|
383
|
+
const allowed = checkAccess(user, action);
|
|
384
|
+
const icon = allowed ? '✓' : '✗';
|
|
385
|
+
console.log(` ${icon} ${user} can ${action}: ${allowed}`);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Bob can delete resource2 because he owns it
|
|
389
|
+
const bobCanDelete = engine.query('can_access', ['bob', 'resource2', 'delete']);
|
|
390
|
+
console.log(`\n Bob can delete resource2 (owner): ${bobCanDelete.length > 0}`);
|
|
391
|
+
console.log();
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// =============================================================================
|
|
395
|
+
// Example 7: Incremental Updates
|
|
396
|
+
// =============================================================================
|
|
397
|
+
|
|
398
|
+
async function incrementalExample() {
|
|
399
|
+
console.log('=== Incremental Updates ===\n');
|
|
400
|
+
|
|
401
|
+
const engine = new DatalogEngine();
|
|
402
|
+
|
|
403
|
+
// Initial facts
|
|
404
|
+
engine.addFact('friend', ['alice', 'bob']);
|
|
405
|
+
engine.addFact('friend', ['bob', 'carol']);
|
|
406
|
+
|
|
407
|
+
// Bidirectional friendship rule
|
|
408
|
+
engine.addRule(
|
|
409
|
+
'friends_with',
|
|
410
|
+
['X', 'Y'],
|
|
411
|
+
[{ predicate: 'friend', args: ['X', 'Y'] }]
|
|
412
|
+
);
|
|
413
|
+
engine.addRule(
|
|
414
|
+
'friends_with',
|
|
415
|
+
['X', 'Y'],
|
|
416
|
+
[{ predicate: 'friend', args: ['Y', 'X'] }]
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
// Transitive friends-of-friends
|
|
420
|
+
engine.addRule(
|
|
421
|
+
'fof',
|
|
422
|
+
['X', 'Z'],
|
|
423
|
+
[
|
|
424
|
+
{ predicate: 'friends_with', args: ['X', 'Y'] },
|
|
425
|
+
{ predicate: 'friends_with', args: ['Y', 'Z'] }
|
|
426
|
+
],
|
|
427
|
+
{ filter: 'X != Z' }
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
engine.evaluate();
|
|
431
|
+
|
|
432
|
+
console.log('Initial state:');
|
|
433
|
+
let fofs = engine.query('fof', ['alice', '?friend']);
|
|
434
|
+
console.log(` Alice's friends-of-friends: ${fofs.map(r => r.friend).join(', ')}\n`);
|
|
435
|
+
|
|
436
|
+
// Incremental update: add new friendship
|
|
437
|
+
console.log('Adding new fact: friend(carol, david)');
|
|
438
|
+
engine.addFact('friend', ['carol', 'david']);
|
|
439
|
+
|
|
440
|
+
// Incremental evaluation (only processes new facts)
|
|
441
|
+
engine.evaluateIncremental();
|
|
442
|
+
|
|
443
|
+
console.log('\nAfter incremental update:');
|
|
444
|
+
fofs = engine.query('fof', ['alice', '?friend']);
|
|
445
|
+
console.log(` Alice's friends-of-friends: ${fofs.map(r => r.friend).join(', ')}`);
|
|
446
|
+
|
|
447
|
+
console.log('\nIncremental evaluation is much faster for dynamic graphs!');
|
|
448
|
+
console.log();
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// =============================================================================
|
|
452
|
+
// Run All Examples
|
|
453
|
+
// =============================================================================
|
|
454
|
+
|
|
455
|
+
async function main() {
|
|
456
|
+
console.log('========================================');
|
|
457
|
+
console.log(' Datalog Reasoning Examples');
|
|
458
|
+
console.log('========================================\n');
|
|
459
|
+
|
|
460
|
+
try {
|
|
461
|
+
await basicDatalogExample();
|
|
462
|
+
await recursiveDatalogExample();
|
|
463
|
+
await negationDatalogExample();
|
|
464
|
+
await aggregateDatalogExample();
|
|
465
|
+
await rdfIntegrationExample();
|
|
466
|
+
await accessControlExample();
|
|
467
|
+
await incrementalExample();
|
|
468
|
+
|
|
469
|
+
console.log('========================================');
|
|
470
|
+
console.log(' All examples completed successfully!');
|
|
471
|
+
console.log('========================================');
|
|
472
|
+
} catch (error) {
|
|
473
|
+
console.error('Error running examples:', error);
|
|
474
|
+
process.exit(1);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
main();
|