rdf-reasoner-konclude 0.2.1 → 0.3.0

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 CHANGED
@@ -114,26 +114,107 @@ The browser build requires COOP/COEP HTTP headers for `SharedArrayBuffer` (used
114
114
  const reasoner = new RdfReasoner();
115
115
  await reasoner.ready; // resolves when WASM module is loaded
116
116
 
117
- await reasoner.reason(store); // classify + write inferred triples into store
118
- await reasoner.classify(store); // alias for reason(store)
119
- const ok = await reasoner.checkConsistency(store); // returns boolean
117
+ // TBox: class hierarchy (rdfs:subClassOf, owl:equivalentClass)
118
+ await reasoner.classify(store);
119
+
120
+ // ABox: individual type entailments (rdf:type)
121
+ await reasoner.materialize(store);
122
+ await reasoner.materialize(store, { includeClassHierarchy: true }); // TBox + ABox
123
+
124
+ // Property hierarchy (rdfs:subPropertyOf)
125
+ await reasoner.classifyProperties(store);
126
+
127
+ // Consistency
128
+ const ok = await reasoner.checkConsistency(store); // true = consistent
129
+
130
+ // Entailment queries (post-reasoning)
131
+ const entailed = await reasoner.isEntailed(store, quad);
132
+ const results = await reasoner.isEntailed(store, [quad1, quad2]);
133
+
134
+ // Hypothetical reasoning
135
+ const { added, removed } = await reasoner.whatIf(store, [newAxiom]);
136
+
137
+ // Explanation / justification
138
+ const justs = await reasoner.explain(store, quad, { maxJustifications: 3 });
139
+ const inconsJusts = await reasoner.explainInconsistency(store);
140
+
141
+ // Satisfiability
142
+ const classes = await reasoner.getUnsatisfiableClasses(store);
143
+ const ok2 = await reasoner.isSatisfiable(store, "http://example.org/MyClass");
144
+
145
+ // Combined diagnostic
146
+ const report = await reasoner.validate(store);
147
+ // report.consistent, report.errors (Quad[][]), report.warnings (ClassWarning[])
120
148
 
121
149
  reasoner.terminate(); // shut down the Worker
122
150
  ```
123
151
 
124
- `reason(store)` and `classify(store)` write inferred triples into the
125
- `INFERRED_GRAPH_IRI` named graph inside the store. The graph is cleared before
126
- each call — do not store ontology triples there.
152
+ `classify(store)`, `materialize(store)`, and `classifyProperties(store)` write
153
+ inferred triples into the `INFERRED_GRAPH_IRI` named graph inside the store.
154
+ The graph is cleared before each call — do not store ontology triples there.
127
155
 
128
156
  Named graphs in the input are dropped at the WASM boundary (NTriples wire
129
157
  format is triple-only). Reasoning runs over the union of all graphs.
130
158
 
131
- Options for `reason(store, opts)` and `classify(store, opts)`:
159
+ Options for `classify(store, opts)`, `materialize(store, opts)`, and `classifyProperties(store, opts)`:
132
160
 
133
161
  ```typescript
162
+ // classify, classifyProperties
134
163
  interface StoreReasoningOptions {
135
- inferredGraph?: string; // IRI of the named graph for inferred triples
136
- // default: INFERRED_GRAPH_IRI
164
+ inferredGraph?: string; // default: INFERRED_GRAPH_IRI
165
+ }
166
+
167
+ // materialize
168
+ interface MaterializeStoreOptions {
169
+ inferredGraph?: string; // default: INFERRED_GRAPH_IRI
170
+ includeClassHierarchy?: boolean; // also emit subClassOf/equivalentClass; default false
171
+ }
172
+ ```
173
+
174
+ Options for the Phase 2 axiom-work methods:
175
+
176
+ ```typescript
177
+ // isEntailed: no options
178
+
179
+ // whatIf
180
+ interface WhatIfOptions {
181
+ removals?: Quad[]; // quads to remove from the base ontology
182
+ outputGraph?: string; // named graph for hypothetical inferences
183
+ }
184
+
185
+ // explain / explainInconsistency
186
+ interface ExplainOptions {
187
+ maxJustifications?: number; // default: 1
188
+ axiomFilter?: (q: Quad) => boolean; // restrict candidate axiom set
189
+ }
190
+
191
+ // validate
192
+ interface ValidateOptions {
193
+ maxJustificationsPerError?: number; // default: 1
194
+ maxJustificationsPerWarning?: number; // default: 1 (pass 0 for IRI-only scan)
195
+ axiomFilter?: (q: Quad) => boolean;
196
+ }
197
+ ```
198
+
199
+ Return types for the Phase 2 axiom-work methods:
200
+
201
+ ```typescript
202
+ // Return types
203
+ isEntailed(store, axiom: Quad): Promise<boolean | null>
204
+ isEntailed(store, axioms: Quad[]): Promise<(boolean | null)[]>
205
+ whatIf(store, additions): Promise<{ added: Quad[], removed: Quad[] }>
206
+ explain(store, axiom): Promise<Quad[][]> // [] if not entailed; throws for unsupported predicate
207
+ explainInconsistency(store): Promise<Quad[][]> // [] if consistent
208
+ validate(store): Promise<ValidationResult>
209
+ // where:
210
+ interface ValidationResult {
211
+ consistent: boolean;
212
+ errors: Quad[][]; // MIPS; non-empty only when consistent === false
213
+ warnings: ClassWarning[]; // one per unsatisfiable class
214
+ }
215
+ interface ClassWarning {
216
+ classIRI: string;
217
+ justifications: Quad[][];
137
218
  }
138
219
  ```
139
220
 
@@ -144,11 +225,315 @@ import { INFERRED_GRAPH_IRI } from "rdf-reasoner-konclude";
144
225
  // "urn:konclude:inferred"
145
226
  ```
146
227
 
147
- The default named graph where inferred triples are written by `reason(store)`.
228
+ The default named graph where inferred triples are written.
148
229
 
149
230
  ### Deprecated overloads
150
231
 
151
- `reason(quads: Iterable<Quad>)` and `classify(quads)` / `checkConsistency(quads)` accept a raw `Iterable<Quad>` and return `Promise<Quad[]>` / `Promise<boolean>`. These overloads are deprecated — use the `Store`-based API instead.
232
+ `reason(quads)`, `classify(quads)`, `checkConsistency(quads)`, and `materialize(quads)` accept a raw `Iterable<Quad>` and return `Promise<Quad[]>` / `Promise<boolean>`. These overloads are deprecated — use the `Store`-based API instead.
233
+
234
+ ## Common workflows
235
+
236
+ All examples assume a single `RdfReasoner` instance:
237
+
238
+ ```typescript
239
+ import { RdfReasoner, INFERRED_GRAPH_IRI } from "rdf-reasoner-konclude";
240
+ import { Store, Parser, DataFactory } from "n3";
241
+
242
+ const reasoner = new RdfReasoner();
243
+ await reasoner.ready;
244
+ ```
245
+
246
+ ### TBox only: classify a class hierarchy
247
+
248
+ Use `classify(store)` when the ontology has no named individuals. Returns
249
+ `rdfs:subClassOf` and `owl:equivalentClass` entailments.
250
+
251
+ ```typescript
252
+ await reasoner.classify(store);
253
+ const subClasses = store.getQuads(
254
+ null,
255
+ "http://www.w3.org/2000/01/rdf-schema#subClassOf",
256
+ null,
257
+ INFERRED_GRAPH_IRI,
258
+ );
259
+ ```
260
+
261
+ ### ABox: derive individual types
262
+
263
+ Use `materialize(store)` when the ontology includes named individuals. Returns
264
+ `rdf:type` entailments for every individual that can be classified under the
265
+ TBox. Classification runs internally as part of realization — no separate call
266
+ needed.
267
+
268
+ ```typescript
269
+ await reasoner.materialize(store);
270
+ const types = store.getQuads(
271
+ null,
272
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
273
+ null,
274
+ INFERRED_GRAPH_IRI,
275
+ );
276
+ ```
277
+
278
+ To also receive the class hierarchy in the same call:
279
+
280
+ ```typescript
281
+ await reasoner.materialize(store, { includeClassHierarchy: true });
282
+ ```
283
+
284
+ ### Property hierarchy
285
+
286
+ Use `classifyProperties(store)` to infer `rdfs:subPropertyOf` entailments.
287
+ Requires `owl:ObjectProperty` / `owl:DatatypeProperty` declarations in the
288
+ ontology.
289
+
290
+ ```typescript
291
+ await reasoner.classifyProperties(store);
292
+ const subProps = store.getQuads(
293
+ null,
294
+ "http://www.w3.org/2000/01/rdf-schema#subPropertyOf",
295
+ null,
296
+ INFERRED_GRAPH_IRI,
297
+ );
298
+ ```
299
+
300
+ ### Combine class hierarchy + property hierarchy
301
+
302
+ `INFERRED_GRAPH_IRI` is cleared by each call, so write results to separate
303
+ named graphs if you need both at once:
304
+
305
+ ```typescript
306
+ await reasoner.classify(store, { inferredGraph: "urn:myapp:class-inferred" });
307
+ await reasoner.classifyProperties(store, {
308
+ inferredGraph: "urn:myapp:prop-inferred",
309
+ });
310
+ ```
311
+
312
+ Or if storing them together is fine, call in sequence and read after both:
313
+
314
+ ```typescript
315
+ await reasoner.classify(store);
316
+ const classTriples = store.getQuads(null, null, null, INFERRED_GRAPH_IRI);
317
+
318
+ await reasoner.classifyProperties(store); // clears + repopulates INFERRED_GRAPH_IRI
319
+ const propTriples = store.getQuads(null, null, null, INFERRED_GRAPH_IRI);
320
+ ```
321
+
322
+ ### Consistency checking
323
+
324
+ ```typescript
325
+ const consistent = await reasoner.checkConsistency(store);
326
+ if (!consistent) {
327
+ console.error("Ontology is inconsistent");
328
+ }
329
+ ```
330
+
331
+ ### Incremental ontology evolution
332
+
333
+ The reasoner resets and re-loads the full store on every call. To reason over
334
+ an evolving ontology, mutate the store and call again:
335
+
336
+ ```typescript
337
+ await reasoner.classify(store);
338
+ // → first inference written to INFERRED_GRAPH_IRI
339
+
340
+ // Add new axioms
341
+ store.addQuad(
342
+ DataFactory.quad(
343
+ DataFactory.namedNode("http://example.org/Cat"),
344
+ DataFactory.namedNode("http://www.w3.org/2000/01/rdf-schema#subClassOf"),
345
+ DataFactory.namedNode("http://example.org/Animal"),
346
+ ),
347
+ );
348
+
349
+ // Re-reason: INFERRED_GRAPH_IRI is cleared and fully repopulated
350
+ await reasoner.classify(store);
351
+ ```
352
+
353
+ Concurrent calls on the same `RdfReasoner` instance are serialized
354
+ automatically — queued calls run in order, never interleaved.
355
+
356
+ ### Checking if a specific entailment holds (`isEntailed`)
357
+
358
+ `isEntailed` supports `rdfs:subClassOf`, `owl:equivalentClass`, `rdf:type`, and
359
+ `rdfs:subPropertyOf`. Returns `null` for unsupported predicates.
360
+
361
+ ```typescript
362
+ await reasoner.materialize(store);
363
+ const isAnimal = await reasoner.isEntailed(
364
+ store,
365
+ DataFactory.quad(
366
+ DataFactory.namedNode("http://example.org/Fido"),
367
+ DataFactory.namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
368
+ DataFactory.namedNode("http://example.org/Animal"),
369
+ ),
370
+ );
371
+ // true if Fido rdf:type Animal is entailed
372
+ ```
373
+
374
+ ### Hypothetical reasoning (`whatIf`)
375
+
376
+ `whatIf` reasons over a temporary store mutation without modifying the input store.
377
+
378
+ ```typescript
379
+ const { added, removed } = await reasoner.whatIf(store, [newAxiom]);
380
+ // added/removed are deltas relative to the current INFERRED_GRAPH_IRI
381
+ ```
382
+
383
+ ### Explaining an entailment (`explain`)
384
+
385
+ `explain` returns minimal justifications — each is the smallest set of axioms
386
+ that alone entails the target. Returns `[]` if the axiom is not entailed.
387
+ Each BlackBox call issues multiple Worker round-trips; use `maxJustifications: 1`
388
+ for cheap first-justification lookups.
389
+
390
+ ```typescript
391
+ const justs = await reasoner.explain(store, quad, { maxJustifications: 3 });
392
+ // justs: Quad[][] — each inner array is one minimal justification
393
+ ```
394
+
395
+ ### Diagnosing an inconsistency (`explainInconsistency`)
396
+
397
+ Returns minimal inconsistent sub-ontologies (MIPS). Returns `[]` on consistent ontologies.
398
+
399
+ ```typescript
400
+ const mips = await reasoner.explainInconsistency(store);
401
+ if (mips.length > 0) {
402
+ console.log("Minimal inconsistent core:", mips[0]);
403
+ }
404
+ ```
405
+
406
+ ### Finding unsatisfiable classes (`getUnsatisfiableClasses`, `isSatisfiable`)
407
+
408
+ `owl:Nothing` is excluded from the output. Classes absent from the taxonomy
409
+ return `true` from `isSatisfiable` (open-world assumption).
410
+
411
+ ```typescript
412
+ const unsatClasses = await reasoner.getUnsatisfiableClasses(store);
413
+ // ["http://example.org/EmptyClass", ...]
414
+
415
+ const ok = await reasoner.isSatisfiable(store, "http://example.org/MyClass");
416
+ // false if MyClass is equivalent to owl:Nothing in the ontology
417
+ ```
418
+
419
+ ### Full ontology validation (`validate`)
420
+
421
+ `validate` combines consistency checking, unsatisfiable-class detection, and
422
+ optional justification computation in a single call.
423
+
424
+ ```typescript
425
+ const report = await reasoner.validate(store);
426
+ // report.consistent — true/false
427
+ // report.errors — Quad[][], minimal inconsistent sub-ontologies (non-empty when inconsistent)
428
+ // report.warnings — ClassWarning[], one per unsatisfiable class
429
+
430
+ // Cheap IRI-only scan (skip BlackBox justifications for warnings):
431
+ const quickReport = await reasoner.validate(store, {
432
+ maxJustificationsPerWarning: 0,
433
+ });
434
+ ```
435
+
436
+ `errors` are non-empty only when `consistent` is `false`. When `consistent` is
437
+ `true`, only `warnings` may be present. Callers should check `consistent` before
438
+ acting on `warnings`.
439
+
440
+ ### Separate inferred graph per operation
441
+
442
+ The `INFERRED_GRAPH_IRI` graph is cleared before each call. If you need to
443
+ preserve results from a previous call while re-reasoning with a different
444
+ operation, use separate named graphs:
445
+
446
+ ```typescript
447
+ await reasoner.classify(store, { inferredGraph: "urn:myapp:class-hierarchy" });
448
+ await reasoner.materialize(store, { inferredGraph: "urn:myapp:abox-types" });
449
+
450
+ // Both named graphs now coexist in the store
451
+ const classTriples = store.getQuads(
452
+ null,
453
+ null,
454
+ null,
455
+ "urn:myapp:class-hierarchy",
456
+ );
457
+ const typeTriples = store.getQuads(null, null, null, "urn:myapp:abox-types");
458
+ ```
459
+
460
+ ### Node.js and browser: same API
461
+
462
+ `RdfReasoner` is identical in both environments. Under Node.js the `"node"`
463
+ export condition in `package.json` loads `index.node.mjs`, which installs a
464
+ `NodeWorkerShim` over `node:worker_threads` that matches the browser `Worker`
465
+ interface. The worker dispatch code (`dist/worker.js`) and all protocol messages
466
+ are shared. No code changes are needed when porting between environments.
467
+
468
+ ## OWL 2 DL coverage
469
+
470
+ Konclude implements the full OWL 2 DL tableau (expressivity SROIQ(D)). The sections below
471
+ document what has been verified to work, what is known not to work, and what the WASM port
472
+ does not yet surface as output.
473
+
474
+ ### Consistency checking (`checkConsistency`)
475
+
476
+ Violation detection verified against native Konclude v0.7.0 ground truth:
477
+
478
+ | # | Violation pattern | Native | WASM | Status |
479
+ | --- | --------------------------------------------------------- | ------------------ | -------------- | ---------------------------------- |
480
+ | 1 | `owl:disjointWith` (direct) | inconsistent ✓ | inconsistent ✓ | **PARITY** |
481
+ | 2 | `owl:disjointWith` (via domain/range inference) | inconsistent ✓ | inconsistent ✓ | **PARITY** |
482
+ | 3 | `owl:AsymmetricProperty` bidirectional assertion | consistent ✗ (bug) | inconsistent ✓ | **PARITY (WASM surpasses native)** |
483
+ | 4 | `owl:IrreflexiveProperty` self-reference | consistent ✗ (bug) | inconsistent ✓ | **PARITY (WASM surpasses native)** |
484
+ | 5 | `owl:maxQualifiedCardinality` + `owl:differentFrom` | inconsistent ✓ | inconsistent ✓ | **PARITY** |
485
+ | 6 | `owl:allValuesFrom` + `owl:disjointWith` | inconsistent ✓ | inconsistent ✓ | **PARITY** |
486
+ | 7 | `owl:ReflexiveProperty` + `ObjectComplementOf(HasSelf)` | inconsistent ✓ | inconsistent ✓ | **PARITY** |
487
+ | 8 | `owl:InverseFunctionalProperty` + `DifferentIndividuals` | inconsistent ✓ | inconsistent ✓ | **PARITY** |
488
+ | 9 | `owl:AllDisjointClasses` (3-way) + double membership | inconsistent ✓ | inconsistent ✓ | **PARITY** |
489
+ | 10 | `DisjointObjectProperties` + `EquivalentObjectProperties` | consistent ✗ (bug) | inconsistent ✓ | **PARITY (WASM surpasses native)** |
490
+ | 11 | `owl:disjointUnionOf` + double membership | inconsistent ✓ | inconsistent ✓ | **PARITY** |
491
+ | 12 | `owl:NegativeObjectPropertyAssertion` contradiction | inconsistent ✓ | inconsistent ✓ | **PARITY** |
492
+ | 13 | `DataAllValuesFrom xsd:minInclusive` (consistent case) | consistent ✓ | consistent ✓ | **PARITY** |
493
+ | 14 | `DataAllValuesFrom xsd:minInclusive` (inconsistent case) | inconsistent ✓ | inconsistent ✓ | **PARITY** |
494
+
495
+ **PARITY (WASM surpasses native v0.7.0)** means native Konclude v0.7.0 has a kernel bug for this
496
+ construct; this package fixes it via patches 011–012 (role axiom correctness, NPA builder fix).
497
+
498
+ `owl:AllDisjointClasses`, `owl:disjointUnionOf`, and `owl:NegativePropertyAssertion` all work in
499
+ `materialize()` — the JS layer expands list axioms to pairwise form before handing off to WASM.
500
+ The only known remaining gap is `owl:FunctionalProperty` + `owl:InverseFunctionalProperty` on the
501
+ same role with a single filler (ALIF+ precompute hang). This case is tracked in
502
+ `tests/integration/known-limitations.test.ts`.
503
+
504
+ ### Classification (`classify`)
505
+
506
+ Verified working:
507
+
508
+ - `rdfs:subClassOf` — transitive closure, with `owl:equivalentClass` folding
509
+ - `owl:intersectionOf`, `owl:unionOf`, `owl:complementOf`
510
+ - `owl:someValuesFrom`, `owl:allValuesFrom`
511
+ - `owl:minCardinality`, `owl:maxCardinality`, `owl:exactCardinality`
512
+ - `owl:minQualifiedCardinality`, `owl:maxQualifiedCardinality`, `owl:qualifiedCardinality`
513
+ - `owl:ObjectProperty` with `rdfs:domain`, `rdfs:range`, `owl:inverseOf`
514
+ - `owl:TransitiveProperty`, `owl:FunctionalProperty`, `owl:InverseFunctionalProperty`
515
+ - `owl:ReflexiveProperty`, `owl:SymmetricProperty`
516
+ - `owl:propertyChainAxiom`
517
+
518
+ ### ABox realization (`materialize`)
519
+
520
+ `materialize(store)` infers `rdf:type` entailments for named individuals under the
521
+ class hierarchy. Verified working on ontologies up to ~25 000 individuals (LUBM + data).
522
+
523
+ Input ABox axioms accepted:
524
+
525
+ - `rdf:type` assertions
526
+ - Object property assertions (`owl:ObjectProperty`)
527
+ - `owl:differentFrom` / `owl:AllDifferent`
528
+
529
+ ### Known output gaps
530
+
531
+ | Feature | Status |
532
+ | ----------------------------------------- | ----------------------------------------- |
533
+ | `rdfs:subPropertyOf` (property hierarchy) | Available via `classifyProperties(store)` |
534
+ | `owl:sameAs` entailments | Emitted by `materialize()` ✓ |
535
+ | `owl:differentFrom` entailments | Not emitted (accepted as input ✓) |
536
+ | Data property assertions | Emitted by `materialize()` ✓ |
152
537
 
153
538
  ## Browser deployment
154
539
 
@@ -214,10 +599,11 @@ LUBM + data) — matching WASM's operation selection. LUBM schema ratio is domin
214
599
  fixed WASM startup cost (pthreads pool init) on a tiny 307-triple ontology.
215
600
 
216
601
  ² WASM timing covers binary buffer encode (Quads → buffer) + `loadTripleBuffer` + realization
217
- + decode. Input RDF is pre-parsed into quads before the timing window — NTriples/Turtle parsing
218
- is excluded, matching what your application pays after data is already loaded into a Store.
219
- Node.js 20 and Chromium 135 are within ~12% of each other on most ontologies; Roberts family
220
- (SROIQ with ABox realization) is effectively equal.
602
+
603
+ - decode. Input RDF is pre-parsed into quads before the timing window — NTriples/Turtle parsing
604
+ is excluded, matching what your application pays after data is already loaded into a Store.
605
+ Node.js 20 and Chromium 135 are within ~12% of each other on most ontologies; Roberts family
606
+ (SROIQ with ABox realization) is effectively equal.
221
607
 
222
608
  Run `npm run bench` to reproduce (requires a built WASM binary — see [Build from source](#build-from-source)).
223
609
 
package/dist/index.d.ts CHANGED
@@ -14,9 +14,9 @@
14
14
  */
15
15
  import type { Quad } from "@rdfjs/types";
16
16
  import { Store } from "n3";
17
- export type { ReasoningOptions, ReasoningResult, StoreReasoningOptions, MaterializeOptions, MaterializeStoreOptions, ClassifyPropertiesStoreOptions } from "./types.js";
18
- export { INFERRED_GRAPH_IRI } from "./types.js";
19
- import type { ReasoningOptions, StoreReasoningOptions, MaterializeOptions, MaterializeStoreOptions, ClassifyPropertiesStoreOptions } from "./types.js";
17
+ export type { ReasoningOptions, ReasoningResult, StoreReasoningOptions, MaterializeOptions, MaterializeStoreOptions, ClassifyPropertiesStoreOptions, InferenceDelta, WhatIfOptions, ExplainOptions, ClassWarning, ValidationResult, ValidateOptions } from "./types.js";
18
+ export { INFERRED_GRAPH_IRI, HYPOTHETICAL_IRI } from "./types.js";
19
+ import type { ReasoningOptions, StoreReasoningOptions, MaterializeOptions, MaterializeStoreOptions, ClassifyPropertiesStoreOptions, InferenceDelta, WhatIfOptions, ExplainOptions, ValidationResult, ValidateOptions } from "./types.js";
20
20
  export declare class RdfReasoner {
21
21
  /** Resolves when the Worker WASM module is ready; rejects on init failure. */
22
22
  readonly ready: Promise<void>;
@@ -29,6 +29,10 @@ export declare class RdfReasoner {
29
29
  * loadTripleBuffer → realization → getInferredTripleBuffer sequences.
30
30
  */
31
31
  private _queue;
32
+ private _classifyCache;
33
+ private _materializeCache;
34
+ private _classifyPropertiesCache;
35
+ private _consistencyCache;
32
36
  constructor();
33
37
  /**
34
38
  * Send a method call to the Worker and return a Promise for the result.
@@ -53,14 +57,21 @@ export declare class RdfReasoner {
53
57
  reason(quads: Iterable<Quad>, opts?: ReasoningOptions): Promise<Quad[]>;
54
58
  private _reasonOnStore;
55
59
  private _reasonOnQuads;
56
- /** Classify a Store (alias for `reason(store)`). */
60
+ /** Classify a Store. Inferred rdfs:subClassOf and owl:equivalentClass triples
61
+ * are written into `opts.inferredGraph` (default `INFERRED_GRAPH_IRI`). The
62
+ * graph is cleared before each call. Concurrent calls are serialized.
63
+ *
64
+ * Internally sends a single `classification` command to the WASM worker, which
65
+ * runs TBox-only reasoning (class hierarchy + property hierarchy). No ABox
66
+ * realization is performed. For individual rdf:type entailments use
67
+ * `materialize(store)` instead. */
57
68
  classify(store: Store, opts?: StoreReasoningOptions): Promise<void>;
58
69
  /**
59
70
  * @deprecated Use `classify(store)` instead. For ABox/rdf:type results, use `materialize(store)`.
60
71
  *
61
- * Classify the given quads (alias for `reason(quads, { mode: 'classify' })`).
62
- *
63
- * Returns the inferred rdfs:subClassOf quads in the default graph.
72
+ * Classify the given quads. Returns the inferred rdfs:subClassOf quads in the
73
+ * default graph. Internally sends a single `classification` command to the
74
+ * WASM worker (TBox-only; no ABox realization).
64
75
  */
65
76
  classify(quads: Iterable<Quad>): Promise<Quad[]>;
66
77
  /** Check consistency of a Store. Does not write inferred triples. */
@@ -71,21 +82,43 @@ export declare class RdfReasoner {
71
82
  * Check whether the given quads form a consistent ontology.
72
83
  *
73
84
  * Internally: loadTripleBuffer → classification → consistency.
74
- *
75
85
  * Concurrent calls are serialized: each call waits for the previous one to
76
86
  * complete before sending its first Worker message.
77
87
  */
78
88
  checkConsistency(quads: Iterable<Quad>): Promise<boolean>;
79
- /** Materialize ABox entailments (rdf:type) into a Store. Inferred triples are
80
- * written into `opts.inferredGraph` (default `INFERRED_GRAPH_IRI`). The
81
- * graph is cleared before each call. When `opts.includeClassHierarchy` is
82
- * `true`, rdfs:subClassOf and owl:equivalentClass triples are also included.
83
- * Concurrent calls are serialized. */
89
+ /** Materialize ABox entailments (rdf:type, owl:sameAs, role assertions) into
90
+ * a Store. Inferred triples are written into `opts.inferredGraph` (default
91
+ * `INFERRED_GRAPH_IRI`). The graph is cleared before each call. When
92
+ * `opts.includeClassHierarchy` is `true`, rdfs:subClassOf and
93
+ * owl:equivalentClass triples are also included. Concurrent calls are
94
+ * serialized.
95
+ *
96
+ * Individuals are recognized from any `rdf:type <domain-class>` assertion —
97
+ * explicit `rdf:type owl:NamedIndividual` declarations are not required.
98
+ * If the ontology contains no individuals, only TBox inferences are produced
99
+ * (same result as `classify(store)` with `includeClassHierarchy: true`).
100
+ *
101
+ * Internally sends a single `realization` command to the WASM worker.
102
+ * Classification (TBox: class hierarchy + property hierarchy) is always a
103
+ * prerequisite inside the realization pipeline — it is NOT a separate call.
104
+ * Both TBox and ABox steps are submitted together in one `prepareOntology()`
105
+ * invocation at the C++ level.
106
+ *
107
+ * Pass `{ returnDelta: true }` to receive `{ delta: InferenceDelta }` with the
108
+ * quads added and removed compared to the previous inferred state. */
109
+ materialize(store: Store, opts: MaterializeStoreOptions & {
110
+ returnDelta: true;
111
+ }): Promise<{
112
+ delta: InferenceDelta;
113
+ }>;
84
114
  materialize(store: Store, opts?: MaterializeStoreOptions): Promise<void>;
85
115
  /**
86
116
  * Materialize ABox entailments (rdf:type assertions) for the given quads.
87
117
  *
88
- * Runs the full TBox+ABox realization pipeline. By default only rdf:type
118
+ * Internally sends a single `realization` command to the WASM worker.
119
+ * Classification (TBox: class hierarchy + property hierarchy) is always a
120
+ * prerequisite inside the realization pipeline — it runs as part of the same
121
+ * `prepareOntology()` call, not as a separate step. By default only rdf:type
89
122
  * entailments are returned. Pass `{ includeClassHierarchy: true }` to also
90
123
  * receive rdfs:subClassOf and owl:equivalentClass triples.
91
124
  *
@@ -116,6 +149,103 @@ export declare class RdfReasoner {
116
149
  classifyProperties(quads: Iterable<Quad>): Promise<Quad[]>;
117
150
  private _classifyPropertiesOnStore;
118
151
  private _classifyPropertiesOnQuads;
152
+ private _opForPredicate;
153
+ private _classifyInline;
154
+ private _materializeInline;
155
+ private _classifyPropertiesInline;
156
+ /**
157
+ * Private helper — like _classifyInline but also calls getUnsatisfiableClassBuffer
158
+ * and returns the list of unsatisfiable class IRIs. Updates _classifyCache and
159
+ * writes inferred triples into the store on cache miss (same invariant as
160
+ * _classifyInline). Must be called from inside a _queue slot only.
161
+ */
162
+ private _getUnsatisfiableClassesInternal;
163
+ /** Return the IRIs of all classes that are unsatisfiable (equivalent to
164
+ * owl:Nothing) in the ontology. owl:Nothing itself is excluded.
165
+ * Classes absent from the taxonomy are NOT included (open-world). */
166
+ getUnsatisfiableClasses(store: Store): Promise<string[]>;
167
+ /** Return `false` if `classIRI` is equivalent to owl:Nothing in the ontology.
168
+ * Returns `true` for any class absent from the taxonomy (open-world assumption).
169
+ * owl:Nothing is always unsatisfiable; returns `false` without a Worker call. */
170
+ isSatisfiable(store: Store, classIRI: string): Promise<boolean>;
171
+ /** Check whether a single axiom is entailed by the store's ontology. Returns
172
+ * null for unsupported predicates (a warning is logged). Triggers reasoning
173
+ * internally if the store has changed since the last call. */
174
+ isEntailed(store: Store, axiom: Quad): Promise<boolean | null>;
175
+ /** Check whether each axiom in a batch is entailed. Returns null for
176
+ * individual unsupported predicates. Reasoning is triggered at most once
177
+ * per required operation type. */
178
+ isEntailed(store: Store, axioms: Quad[]): Promise<(boolean | null)[]>;
179
+ /** Reason over a hypothetical extension of the store without mutating it.
180
+ *
181
+ * Computes full-materialize inferences over `store ∪ additions \ removals`
182
+ * without changing the store's base triples or INFERRED_GRAPH_IRI.
183
+ *
184
+ * Returns `{ added, removed }` relative to the current INFERRED_GRAPH_IRI
185
+ * content (both quads carry `graph = INFERRED_GRAPH_IRI` named node).
186
+ *
187
+ * If `opts.outputGraph` is provided the hypothetical inferences are also
188
+ * written to that named graph in the store (must not equal INFERRED_GRAPH_IRI).
189
+ */
190
+ whatIf(store: Store, additions: Quad[], opts?: WhatIfOptions): Promise<{
191
+ added: Quad[];
192
+ removed: Quad[];
193
+ }>;
194
+ /**
195
+ * Identical to _call. Named separately to mark it safe for use inside a
196
+ * _queue.then() body (no queue gating — callers must already hold the slot).
197
+ * Calling the public methods (classify, materialize, etc.) from inside a
198
+ * _queue body would deadlock.
199
+ */
200
+ private _callDirect;
201
+ private _isBuiltInDeclaration;
202
+ private _opForAxiom;
203
+ private _checkEntailmentDirect;
204
+ /**
205
+ * Returns true if the candidate subset is inconsistent.
206
+ * Uses the consistency Worker pipeline (not triple lookup).
207
+ * Safe to call from inside a _queue body.
208
+ */
209
+ private _checkInconsistencyDirect;
210
+ /**
211
+ * Returns true if `classIRI` is unsatisfiable in the candidate set.
212
+ * Uses buildUnsatisfiableClassBuffer as the oracle (not _checkEntailmentDirect,
213
+ * because buildInferredTripleBuffer suppresses `X rdfs:subClassOf owl:Nothing`).
214
+ * Safe to call from inside a _queue body.
215
+ */
216
+ private _checkUnsatisfiabilityDirect;
217
+ /** Compute minimal justifications for an axiom using the BlackBox algorithm.
218
+ *
219
+ * Returns a list of minimal subsets of the store's base quads, each of which
220
+ * alone entails the axiom. Returns [] if the axiom is not entailed.
221
+ * Each inner Quad[] is a minimal justification.
222
+ *
223
+ * Throws for unsupported predicates (unlike isEntailed which returns null).
224
+ *
225
+ * All BlackBox sub-calls run inside this method's single _queue slot using
226
+ * _callDirect. Do NOT call the public methods classify/materialize from inside.
227
+ */
228
+ explain(store: Store, axiom: Quad, opts?: ExplainOptions): Promise<Quad[][]>;
229
+ /** Compute minimal inconsistent sub-ontologies (MIPS) for an inconsistent
230
+ * ontology. Returns [] if the ontology is consistent.
231
+ *
232
+ * Uses the consistency oracle directly (loadTripleBuffer → classification →
233
+ * consistency) for all BlackBox iterations. Does not depend on
234
+ * owl:Thing rdfs:subClassOf owl:Nothing being emitted as an inferred triple.
235
+ */
236
+ explainInconsistency(store: Store, opts?: ExplainOptions): Promise<Quad[][]>;
237
+ /** Run a combined diagnostic: check consistency, find unsatisfiable classes,
238
+ * and (optionally) compute minimal justifications for each.
239
+ *
240
+ * Returns `{ consistent, errors, warnings }` where:
241
+ * - `consistent` — `true` when the ontology has at least one model
242
+ * - `errors` — MIPS (minimal inconsistent sub-ontologies); non-empty only when inconsistent
243
+ * - `warnings` — one `ClassWarning` per unsatisfiable class (owl:Nothing excluded)
244
+ *
245
+ * All BlackBox iterations run inside this method's single _queue slot.
246
+ * Do NOT call public methods from inside — use private helpers only.
247
+ */
248
+ validate(store: Store, opts?: ValidateOptions): Promise<ValidationResult>;
119
249
  /** Terminate the underlying Worker and reject all pending calls. */
120
250
  terminate(): void;
121
251
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,KAAK,EAAe,MAAM,IAAI,CAAC;AAGxC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,MAAM,YAAY,CAAC;AACxK,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,MAAM,YAAY,CAAC;AAqCvJ,qBAAa,WAAW;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAGpB;IAEJ;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAoC;;IAoElD;;;OAGG;IACH,OAAO,CAAC,KAAK;IAiBb;;6DAEyD;IACzD,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IACjE;;;;;;;;;;OAUG;IACH,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAWvE,OAAO,CAAC,cAAc;IA6BtB,OAAO,CAAC,cAAc;IAkCtB,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IACnE;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAehD,qEAAqE;IACrE,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;IAChD;;;;;;;;;OASG;IACH,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAsBzD;;;;2CAIuC;IACvC,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IACxE;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAW9E,OAAO,CAAC,mBAAmB;IAoC3B,OAAO,CAAC,mBAAmB;IA8B3B;;8EAE0E;IAC1E,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,8BAA8B,GAAG,OAAO,CAAC,IAAI,CAAC;IACtF;;;;;;;;;;OAUG;IACH,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAW1D,OAAO,CAAC,0BAA0B;IA4BlC,OAAO,CAAC,0BAA0B;IAiBlC,oEAAoE;IACpE,SAAS,IAAI,IAAI;CAQlB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"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"}