
Eyedia — reasoning you can see.
Every example also has a card deck that explains it for a wide audience.
Run a source, generate its proof, or check its saved proof:
node bin/eyedia.js examples/socrates.pl
node bin/eyedia.js --proof examples/socrates.pl
node bin/eyedia.js --check-proof examples/proof/socrates.pl examples/socrates.pl
Each program has a matching conclusion file in output/, a certificate in
proof/, and a Prolog C1-C7 verification report in check/. The names match the
source: lists.pl has output/lists.pl, proof/lists.pl and check/lists.pl.
| Program | Demonstrates |
|---|---|
| socrates.pl | Class membership derived through a subclass rule |
| deep-taxonomy-10.pl | A ten-level subclass chain with branches that lead nowhere |
| deep-taxonomy-100.pl | The same taxonomy benchmark at a hundred levels |
| deep-taxonomy-1000.pl | The same taxonomy benchmark at a thousand levels |
| deep-taxonomy-10000.pl | The same taxonomy benchmark at ten thousand levels |
| backward.pl | Backward definitions inside forward bodies |
| fibonacci.pl | Fast doubling for exact Fibonacci numbers, and the golden ratio |
| graphs.pl | Base data, negation and collection |
| terms.pl | Quoted graphs, triple terms and residual witnesses |
| reachability.pl | Finite closure in a graph containing a cycle |
| shortest-path.pl | Weighted paths and stratified minimum selection |
| path-discovery.pl | Full airport network with configurable endpoints and maximum stopovers |
| lists.pl | Concatenation, mapping and summation |
| strings.pl | Text construction and Unicode inspection |
| inventory.pl | An invoice from collected line totals |
| dog-license.pl | A licensing threshold based on collected dog counts |
| permissions.pl | Role permissions with exclusions |
| witnesses.pl | Structured witnesses and shared multi-head conclusions |
| state-transitions.pl | Account balances from an ordered event log |
| integrity.pl | A provable integrity violation |
| alternatives.pl | Alternative routes, disjunction and once |
| unification.pl | Open lists and repeated-variable constraints |
| schema-inference.pl | Subclasses, subproperties, domains and ranges |
| family-cousins.pl | Generations, family branches and cousin relationships |
| hanoi.pl | Recursive construction of a disk-move sequence |
| collatz.pl | Parity-based recursive trajectories over a range of starts |
| flat-map.pl | Predicate-based mapping with multiple or missing values |
| paraconsistent-animals.pl | Local summaries of conflicting observations |
| scoped-audit.pl | Presence and absence within separate quoted graphs |
| control-system.pl | Feedforward and nonlinear feedback commands for two actuators |
| lldm.pl | Leg length discrepancy measured from radiograph landmarks, with an alarm and its reason |
| variable-predicates.pl | Relations selected and renamed through data bindings |
| good-cobbler.pl | Trade-specific classification from structured descriptions |
| peano.pl | Symbolic arithmetic, relational addition and a chained derivation |
| expression-eval.pl | Recursive expression graphs used in forward inference |
| complex.pl | Complex arithmetic, exact over Gaussian integers and polar beyond them |
| polynomial.pl | Complex roots of polynomials up to degree 4 by Cardan and Lagrange |
| interval-relations.pl | All thirteen interval relations and endpoint completion |
| bayes-diagnosis.pl | Normalized probabilities for illustrative printer faults |
| policy-risk.pl | Ranked findings with explanations and suggested mitigations |
| research-portal.pl | A hospital research portal combines ODRL/DPV policy decisions with Digital Omnibus device consent and breach plans |
| package-holiday.pl | Package holiday cancellations under the tour operator’s ODRL terms and the 2015 and revised EU Package Travel Directive |
| queens.pl | Configurable N-queens search with diagonal constraints |
| age.pl | Calendar-year and elapsed-day age checks at an explicit reference date |
| ackermann.pl | The Ackermann function through the hyperoperation sequence, exactly |
| peasant.pl | Peasant multiplication and exponentiation by halving and doubling |
| sieve.pl | The sieve of Eratosthenes over an explicit list of integers |
| goldbach.pl | Goldbach splits of every power of two up to 2^25 |
| kaprekar.pl | Every four-digit Kaprekar routine reaches 6174 within seven steps |
| easter.pl | Easter Sunday by the anonymous Gregorian algorithm, 2021 to 2050 |
| turing.pl | A Turing machine interpreter running a binary incrementer |
| zebra.pl | The zebra puzzle solved by narrowing five partially known houses |
| aunt-agatha.pl | Who killed Aunt Agatha? A conclusion entailed by holding in every model of the premises |
| four-color.pl | Four-colouring the map of the European Union |
| wolf-goat-cabbage.pl | The river crossing, with seven crossings shown to be minimal |
| monkey-bananas.pl | Every plan of up to five moves that gets the monkey the bananas |
| gps.pl | Goal-driven parallel sequences: routes to a goal state within duration, cost, belief and comfort limits |
| superdense-coding.pl | Superdense coding in discrete quantum theory, with interference as odd path counts |
| teleportation.pl | Quantum teleportation in discrete quantum theory, checked for every state and outcome |
integrity.pl intentionally exits with code 65 because it concludes false.
Its proof-check report is valid: the certificate explains why the constraint was
violated. Negation and collection examples list their absent and collected
obligations in the check report; --strict-proof rejects those obligations.
Every check file includes condition/4 facts for C1-C7, verification counts and
a verdict/1 fact. Reports with failures include failure/3; reports with
trusted boundaries include obligation/3. Add --json to the check command
for JSON output instead of Prolog facts.
fibonacci.pl answers F(0), F(1), F(10), F(100), F(1000) and F(10000), the
last a 2090-digit integer, then divides successive values to watch the ratio
converge on the golden ratio. It uses fast doubling, which halves the index at
each recursive step and fits within the default reasoning limits. Its saved
proof records the arithmetic and recursive clause instances without trusted
obligations.
The deep-taxonomy examples are the deep-taxonomy benchmark: one individual, a
chain of subclass rules, and two sibling branches at every level that lead
nowhere. The goal has to follow the single productive branch the whole way
down, so the chain length is also the backward recursion depth. The four sizes
run from ten to ten thousand levels, and each costs exactly one resolution
step per level, which --stats reports and the saved check report confirms:
deep-taxonomy-10000 verifies 10001 steps. Backward search is an explicit
machine, so the depth costs heap rather than host stack.
node bin/eyedia.js --stats examples/deep-taxonomy-10000.pl
Time, proof size and checking all grow linearly with the depth, so a longer chain only costs proportionally more; the ten-thousand-level source is about 1 MB and its certificate about 1.3 MB, since a certificate records every step it claims.
path-discovery.pl contains 7,698 airport records and 37,505 directed
connections. Its default goal finds three routes from Ostend to Prague with
at most two stopovers. Use any airport-name atoms and a nonnegative integer
limit with path_discovery(From, To, MaxStopovers, Path):
node bin/eyedia.js --goal "path_discovery('Liège Airport', 'Václav Havel Airport Prague', 1, Path)" examples/path-discovery.pl
goal="path_discovery('Ostend-Bruges International Airport', 'Liège Airport', 0, Path)"
node bin/eyedia.js --proof --goal "$goal" examples/path-discovery.pl > /tmp/route-proof.pl
node bin/eyedia.js --strict-proof --check-proof /tmp/route-proof.pl --goal "$goal" examples/path-discovery.pl
--goal replaces the default goal, so checking that proof names the same goal. Zero stopovers allows only direct flights;
N stopovers allows at most N+1 flights. Routes follow the recorded direction
and never repeat an airport. Equal endpoints and unknown names return no
routes. Negative or noninteger limits also return no routes. You can leave
From or To as a variable to discover endpoints; keep MaxStopovers bound.
List the available names with --goal "airport(Id, Name)". These are historical
network records, rather than current flight schedules. The search uses explicit
disequalities to prevent cycles, so its proofs have no trusted obligations.
Large bounds on a dense network may still reach the configured reasoning limits.
peano.pl represents natural numbers as zero, s(zero), and so on. Its
addition goal enumerates every split of a known sum, and a second goal chains
all three relations: (1*2)+3 is 5, whose factorial is 120 nested successors.
expression-eval.pl evaluates a graph for (2*3)+(10-4) and emits
result(example, 12).
complex.pl adds a numeric domain the engine knows nothing about. A complex
number is the ordinary term complex(Real, Imaginary), and addition,
multiplication, conjugation, division, norm, modulus and integer powers are all
ordinary clauses over integer arithmetic. Components stay exact wherever the
arithmetic allows it: dividing complex(-5, 10) by complex(1, 2) recovers
complex(3, 4) as integers because the norm divides both parts, while the same
division applied to complex(3, 4) yields the float pair complex(2.2, -0.4).
The example also derives i*i = -1 from the multiplication clause rather than
assuming it, confirms that the Gaussian norm is multiplicative, and raises
complex(1, 1) to the eighth power by repeated squaring.
Polar form then leaves the integers altogether, so a complex number can be
raised to a complex power. The square root of -1 is i, e to the power i*pi
is -1, i to the power i is the real number 0.20787957635076193, and the
inverse sine and cosine of 2 are complex. Logarithm, sine, cosine, tangent and
arctangent follow, each applied to the answer of its own inverse so the
round trip is visible: the sine of the arcsine of 2 comes back as 2. The example
passes strict proof checking, so every component of every conclusion is
recomputed by the checker:
node bin/eyedia.js --goal "complex_power(complex(1, 1), 16, Result)" examples/complex.pl
node bin/eyedia.js --goal "complex_div(complex(1, 0), complex(0, 1), Inverse)" examples/complex.pl
polynomial.pl is Alain Colmerauer’s solver for polynomial equations up to
degree 4, with complex coefficients and roots as [Re, Im] pairs. Degree 3
follows Cardan’s formula and degree 4 Lagrange’s method, which solves a cubic
on the way. Its default goals find the roots of (x-1)(x-2)(x-3)(x-4) and of a
quartic with complex coefficients whose roots are 3+2i, 5+i, i and 1+i, each
up to rounding. The original evaluates expressions by building calls with
=..; here each operation has its own clause, and the zero tests compare
numbers instead of cutting. Lagrange’s step collects the roots of a cubic with
a predicate of its own, so that collection depends only on a lower degree.
A list of all roots is a completed collection, so the default certificate is
small: four steps, with the arithmetic inside two collected obligations. Ask
for one root at a time and every arithmetic step is in the certificate
instead. For a cubic it passes strict checking:
node bin/eyedia.js --proof --goal "racine([[1, 0], [-6, 0], [11, 0], [-6, 0]], Z)" examples/polynomial.pl
queens.pl returns the first solution for an 8x8 board by default; another
goal enumerates other board sizes:
node bin/eyedia.js --goal "queens(4, Columns)" examples/queens.pl
node bin/eyedia.js --goal "add(A, B, s(s(s(zero))))" examples/peano.pl
interval-relations.pl uses half-open intervals with integer-minute endpoints.
It completes endpoints from durations and classifies each valid interval pair
into exactly one of thirteen relations. Empty and reversed intervals are
excluded from classification.
control-system.pl computes two actuator commands. The first is a
proportional part on a conditioned measurement minus a feedforward
compensation, the base-10 logarithm of a measured disturbance. The second is
a proportional, nonlinear differential feedback controller on the error
between a target and an output. The results are ordinary floats, and the proof
recomputes every arithmetic step.
lldm.pl measures a leg length discrepancy from four landmarks on a
radiograph. Two landmarks fix a reference line, and each leg runs from one of
the other two to its perpendicular projection on that line. With a 1.25 cm
threshold the measured legs, 21.55 cm and 23.46 cm, raise an alarm, printed
with the lengths, the discrepancy, the threshold and the reason. The reason
names the side of the threshold that fired; the version this was adapted from
gave the same reason for both. Every intermediate value is a separate val/3
clause, so the strict certificate recomputes each one.
bayes-diagnosis.pl models printer faults using illustrative priors and two
conditionally independent observations. It keeps exact integer likelihood
weights and their collected total alongside a floating-point probability.
policy-risk.pl reports a rank, clause, clamped score, severity, reason and
mitigation. Rank 1 has the highest score; equal scores share a rank. Output
follows inference order, with ranks recorded explicitly. Adding the missing
safeguards removes the affected findings. Both examples expose their collection
obligations, and policy findings also expose absence obligations.
research-portal.pl evaluates a hospital research portal under two rulebooks.
An ODRL/DPV policy decides research access first, then the baseline or
original Digital Omnibus rulebook decides the device-consent step. Eleven
sessions produce permits with planned deletion duties, pending device consent,
or explicit policy and device refusals. Three incidents have notification
plans under both regimes, always retaining internal documentation. Changes
compare final plans; a device exemption never overrides withdrawn research
consent or a prohibition.
package-holiday.pl is the same pattern in the domain of leisure. A tour
operator’s cancellation terms, written as an ODRL offer, decide first who may
cancel and at what fee; then the EU Package Travel Directive, in its 2015
version and as revised in 2026, decides when a cancellation is free and how
the money comes back. Eight cancellations and two complaints are decided
under both versions, with fees and refunds computed in euro. The revision
makes a cancellation free when floods close the departure airport, gives
accepted vouchers statutory guarantees, and sets complaint deadlines. Every
condition of the terms is checked one by one, so the proof passes
--strict-proof with no trusted steps.
age.pl checks whether a person’s age strictly exceeds years(N) or days(N).
It uses as_of(date(2026, 10, 1)) for reproducible output and proofs. Edit that
fact to change the default date, or pass a reference date directly:
node bin/eyedia.js examples/age.pl
node bin/eyedia.js --goal "age_above(pat_h, years(80), date(2024, 8, 22))" examples/age.pl
node bin/eyedia.js --goal "age_days(pat_h, date(2026, 10, 1), Days)" examples/age.pl
Exactly on the threshold anniversary, age_above/3 fails; it succeeds on the
following day. A February 29 anniversary falls on February 28 in a non-leap
year. Elapsed days follow the Gregorian calendar, including century leap-year
rules. Invalid dates, future births, unknown people, and negative or noninteger
thresholds return no answers. Reference dates are explicit source data rather
than clock readings, and the example passes strict proof checking.
The classics from ackermann.pl to teleportation.pl are written without a
library. Relations such as between/3, member/2 or length/2 are defined in
each program as ordinary clauses, and a search commits with once/1, or with
guards that make its alternatives exclusive, where Prolog would use cut.
ackermann.pl computes A(4, 2), a number with 19,729 digits, through the
hyperoperation sequence: addition, multiplication and exponentiation have closed
forms, and every higher level is the one below it iterated. peasant.pl
multiplies and raises to powers using only halving, doubling and addition.
sieve.pl lists the primes below 100 by striking out multiples from an
explicit list; it stops there because its certificate records every
intermediate list, which grows far faster than the answer.
goldbach.pl splits every power of two from 4 to 2^25 into two primes, taking
the split with the smallest prime. easter.pl dates Easter Sunday for 2021 to
2050 with the anonymous Gregorian algorithm, every step integer arithmetic on
the year. turing.pl is a Turing machine interpreter running a machine that
adds one to a binary number.
zebra.pl solves Einstein’s riddle by narrowing a list of five partially known
houses with unification alone. aunt-agatha.pl is Pelletier’s problem 55
(TPTP PUZ001), a classic test for theorem provers: nine premises about the
three residents of Dreadbury Mansion, and the claim that Agatha killed
herself. A puzzle like the zebra asks for one solution; this one asks what
follows, which is what holds in every situation the premises allow. The
premises leave open who hates whom and who is richer than whom, so the program
enumerates every model of them: Agatha is the killer in four, the butler and
Charles in none. A full model is printed as a witness, with a proof that each
premise holds in it. four-color.pl colours the 27 countries of the
European Union so that no neighbours share a colour. wolf-goat-cabbage.pl
shows that a safe crossing takes seven trips and that no shorter one exists,
then prints both seven-trip plans. monkey-bananas.pl lists every plan of up
to five moves that gets the monkey the bananas, shortest first.
gps.pl is goal-driven parallel sequences: it finds sequences of actions from
the current state to a goal state, here driving from Gent to Oostende on a
partial map of Belgium. Duration and cost add up along a path and belief and
comfort multiply, and each must stay within its limit, as must the number of
stages, runs of steps in the same map. Two routes qualify, directly through
Brugge and the longer one through Kortrijk. The original keeps the current
state in the database, reading transitions with clause/2 and asserting and
retracting fluents as it moves; here the state is a list of fluents passed
along the search, so every step is an ordinary clause instance and the
certificate passes strict checking. Stages are counted as changes of map plus
one, where the original stops counting at two.
superdense-coding.pl sends two classical bits through one qubit in discrete
quantum theory, where amplitudes come from a finite field and the merge of
alternative branches is exclusive: an answer survives when it is reached an odd
number of times. The original toggles asserted facts to get that parity; here
each of Alice’s messages N and Bob’s readings M collects its ways through the
shared entangled pair and keeps the pair when their number is odd. Every
message arrives as itself by exactly one way, and every wrong reading by two
ways that cancel or by none, so Bob reads 0 to 3 exactly as Alice sent them.
The parity depends on all the ways, so the certificate carries the four
collections behind its answers as obligations.
teleportation.pl runs the companion protocol in the same theory, with the
same relations. Alice measures the qubit to send together with her half of the
entangled pair, in the four-state basis Bob decodes with in superdense coding,
and sends him the outcome. Bob applies the inverse of that basis relation, which
turns out to be one of Alice’s four operations from superdense coding, to his
half. For each of the three nonzero states over the two-element field and each
of the four outcomes, Bob ends up holding exactly the state Alice sent, and a
false :+ rule would stop the run with exit code 65 if he did not. The
protocol was written for this collection, not taken from a sibling project.
Certificates that lean on a completed search say so. In kaprekar.pl the whole
verification sits inside one negation, so its certificate is two steps plus an
absent obligation: the exhaustive check over 705 digit multisets is exactly
what the obligation names. four-color.pl collects the countries with
findall/3 and rules out conflicts with negation, so it carries both kinds.
Run npm test for the full suite or npm run test:examples for this corpus.
Every example runs through the API and all three CLI modes. The test log prints
[current/total] and the name of each test before executing it. Tests compare
results with saved artifacts and do not overwrite them.
After an intentional behavior change, run npm run examples:update and review
the source and artifact changes together. When adding an example, register its
name, description, expected halt code (if any) and proof obligations in
manifest.json, then generate its artifacts.