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.
npm installNode.js 18 or newer. The package depends on eyemind and nothing else.
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.n3A 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.
n3-to-eyemind examples/invoice.n3 -o invoice.js
eyemind invoice.js > conclusions.js
eyemind-to-n3 --prefixes examples/invoice.n3 conclusions.jsn3-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/ 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 |
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/testsThe 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:memoizeis 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:semanticsOrErrorandlog:contentread 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:conclusionknows the closure of each formula the document states or fetches, worked out while compiling, andlog:parsedAsN3each 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:equalToandlog:notEqualTocompare them as sets, matching blank nodes and variables by unification. log:impliesandlog:impliedByin 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:collectAllInandlog:forAllInneed 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:floatis one too, so0.1 + 0.2is not0.3and"42"^^xsd:floatequals42.0.INFand-INFcompare as infinities;NaNis 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.
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 N3reasonN3(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.
npm testUnit tests, every example against its saved output, and the three commands
chained against eyemind-n3.
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.