Skip to content

About

Notation3 interchange for eyemind: compile N3 rules and data to eyemind programs and write their conclusions back as N3.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

n3-interchange

npm

Note

Notation3 now lives in eyemind itself: eyemind file.n3 compiles and runs an N3 document, and eyemind --program file.n3 prints the compiled program. This package is kept as it was at its last release and is no longer developed.

Notation3 (N3) for eyemind. It compiles N3 facts and rules into an eyemind program and writes eyemind's conclusions back as N3. Run together, eyemind becomes an N3 reasoner: it reads the same .n3 files and writes the same derived triples as EYE, eye-js, eyeling and eyeron. Coverage is not complete; Coverage lists the measured results and the built-ins it leaves out.

N3 document
   | n3-to-eyemind
   v
eyemind program        facts, rules and the N3 built-ins it uses, in eyemind
   | eyemind
   v
eyemind conclusions    the derived rdf/3 triples
   | eyemind-to-n3
   v
N3 derived triples

eyemind-n3 does all three in one step. Every step is readable on its own: the program is ordinary eyemind, so eyemind --proof proves its conclusions and eyemind --check-proof checks them, built-in steps included. The mapping guide gives the translation in detail.

Install

npm install

Node.js 18 or newer. The package depends on eyemind and nothing else.

Run

eyemind-n3 examples/socrates.n3
@prefix : <http://example.org/socrates#> .

:Socrates a :Mortal .

Like the other N3 reasoners, eyemind-n3 writes the triples the rules derive. With log:query rules it writes only their conclusions, and when the result holds log:outputString triples it writes their strings, ordered by subject. An inference fuse, { ... } => false, stops the run with exit status 2.

eyemind-n3 [OPTION ...] input.n3 ...
N3 options:
      --all               Write every triple, not only derived ones
      --strings           Write log:outputString values as text
      --triples           Write triples even when there are log:outputString values
      --program           Write the compiled eyemind program instead
      --base IRI          Base IRI for relative references
  -o FILE                 Write the output to FILE
eyemind options:
  -p, --proof             Print eyemind's proof of the conclusions
  -c, --prove-and-check   Generate a proof and check it against the compiled program
      --check-proof FILE  Check a proof of the compiled program (- for stdin)
      --json              Print the check report as JSON instead
      --goal GOAL         Ask an eyemind goal after forward reasoning
      --strict-proof      Reject proofs with unresolved obligations
      --unused            List the compiled clauses that make no difference
      --stats             Print reasoning statistics to stderr
      --max-depth N       Bound backward recursion (default 1000000)
      --max-iterations N  Bound forward rounds per stratum (default 100000)
      --max-inferences N  Bound reasoning work (default 1000000000)
  -v, --version           Print the versions of n3-interchange and eyemind
  -h, --help              Print this help

Several inputs are read as one document; blank-node labels stay local to each.

The eyemind options mean what they mean for eyemind, applied to the compiled program. Compiling is deterministic, so a proof saved with --proof checks later against the same N3 input:

eyemind-n3 --proof examples/invoice.n3 > invoice-proof.js
eyemind-n3 --check-proof invoice-proof.js examples/invoice.n3
eyemind-n3 --goal "rdf(S, iri('http://example.org/family#ancestor'), O)" examples/family.n3

A goal's answers are written as N3 when they are triples, and as eyemind terms otherwise. With --proof or --prove-and-check the exit codes are eyemind's: 2 for an invalid proof and 65 for a fuse that fired.

The three steps

n3-to-eyemind examples/invoice.n3 -o invoice.js
eyemind invoice.js > conclusions.js
eyemind-to-n3 --prefixes examples/invoice.n3 conclusions.js

n3-to-eyemind takes --base IRI and -o FILE. eyemind-to-n3 reads the conclusions as data, without running them, and takes --prefixes FILE (the N3 document whose prefixes to use), --strings, --triples and -o FILE.

Examples

examples/ holds small programs, each with its expected output in examples/output/:

Example Shows
socrates a forward rule
family recursive backward rules (<=) and log:query
closed-world scoped negation with log:notIncludes
invoice log:collectAllIn, math:sum and math:greaterThan
existential blank nodes in a conclusion, one per firing
report string:format and log:outputString
derived-rule a rule that concludes a rule
fuse an inference fuse, => false

Coverage

Measured on 2026-11-10 against the eyeling examples (commit 830e0b0) and the notation3tests suite as eyeling mirrors it:

Corpus Result
eyeling examples with an expected output 169 of 205 match; 11 reach the 5-second limit; 22 more need TriG inputs or JavaScript built-ins and were not run
notation3tests 1147 of 1163
node tools/corpus.mjs --timeout 5 ../eyeling/examples
node tools/notation3tests.mjs --timeout 20 ../eyeling/test/notation3tests/tests

The parser reads all 227 eyeling examples. Some built-ins need what eyemind leaves out by design, and n3-to-eyemind stops with an error naming the built-in and the reason:

Built-ins eyemind has no
log:trace printing while reasoning
time:localTime, gmTime, currentTime clock

The example run uses a short time limit to bound work on recursive programs; its timeout count is separate from differences in answers. The Notation3 suite allows longer for tests that fetch documents.

Four eyeling examples that check a crypto:sha256 digest (calidor, delfour, flandor, medior) differ because eyeling hashes the escaped text of a string, backslashes included; n3-interchange hashes the string itself.

Other limits:

  • eyemind stratifies negation and collection. A rule that negates or collects a pattern that some rule may conclude, the same one or another, is rejected as unstratified, where EYE would still answer.
  • eyemind has no tabling, so log:memoize is an ordinary fact and a backward rule recomputes every call; doubly recursive definitions such as a naive Fibonacci exhaust memory.
  • A rule whose conclusion is a variable, { ... } => ?F, is read as a triple, not as a rule.
  • eyemind reads no files and no network while it reasons, so the documents log:semantics, log:semanticsOrError and log:content read are fetched before compiling: each IRI written as their subject, and each IRI the document's facts state where a rule's pattern finds that subject. Another IRI has no document, and the goal fails.
  • log:conclusion knows the closure of each formula the document states or fetches, worked out while compiling, and log:parsedAsN3 each string the document states or a rule writes, parsed while compiling; a formula or string only built while reasoning has none, and the goal fails.
  • Quoted formulas match as ordered lists of triples, not as sets; log:equalTo and log:notEqualTo compare them as sets, matching blank nodes and variables by unification.
  • log:implies and log:impliedBy in a premise match source and derived rules as triples, including the matching rule itself. This reads their quoted formulas without solving their premises; formula patterns keep the ordered-list matching described above.
  • log:collectAllIn and log:forAllIn need their formulas written in the rule; one only known when the rule runs makes the goal fail.
  • Decimals and doubles are both binary64 floats, and xsd:float is one too, so 0.1 + 0.2 is not 0.3 and "42"^^xsd:float equals 42.0. INF and -INF compare as infinities; NaN is no number.
  • A regular expression only known while reasoning is used as it is, so it must be an ECMAScript pattern valid in Unicode mode.

JavaScript API

import { compileN3, eyemindToN3, reasonN3 } from 'n3-interchange';

const { program } = compileN3(n3Text);              // eyemind program text
const { n3, contradiction } = reasonN3(n3Text);     // derived triples as N3
const text = eyemindToN3(conclusions, { prefixes }); // conclusions as N3

reasonN3(sources, options) takes the text, or [text, name] pairs, and the options mode ('new' or 'all'), strings ('auto', true, false), base, limits (maxInferences, maxDepth, maxIterations), proof, goals and documents. It returns n3, the triples, contradiction, the compiled program and eyemind's result, whose proof checkProof from eyemind checks. await fetchSourceDocuments(sources) fetches the documents the sources read with log:semantics and log:content, for documents; without them those built-ins find nothing.

Tests

npm test

Unit tests, every example against its saved output, and the three commands chained against eyemind-n3.

Releases

package.json holds the version. A release runs the tests, bumps the version, commits, tags and pushes; the tag makes GitHub create the release and publish the package to npm through npm trusted publishing, with provenance and no stored token:

./release patch "Release v0.1.1: describe what changed"
./release minor "Release v0.2.0: describe what changed"

The message is used as given for the commit, the tag and the release, and must say what changed. The publish workflow can also be run by hand for an existing tag, optionally as a dry run, and leaves a version npm already has as it is.

About

Notation3 interchange for eyemind: compile N3 rules and data to eyemind programs and write their conclusions back as N3.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages