The cheapest way from A to D, and the honest fine print behind “cheapest”.
shortest-path.pl · output · proof · check · try it in the playground
A small road map: four places, five one-way roads, each with a cost (think minutes, or kilometres).
a --4--> b --3--> d
a --2--> c --1--> b
c --8--> d
What is the cheapest way to get from a to d?
Finding a route is easy. Saying a route is the cheapest means saying that no cheaper route exists — a claim about everything you didn’t pick.
edge(a, b, 4).
edge(a, c, 2).
edge(c, b, 1).
edge(b, d, 3).
edge(c, d, 8).
path(X, Y, Cost) :+ edge(X, Y, Cost).
path(X, Z, Cost) :+ path(X, Y, Before), edge(Y, Z, Weight), Cost is Before+Weight.
A road is a path; a path followed by one more road is a longer path, and the
costs add up. The :+ means “keep applying this until nothing new follows”.
cheaper(X, Y, Cost) :- path(X, Y, Other), Other < Cost.
shortest(X, Y, Cost) :+ path(X, Y, Cost), \+ cheaper(X, Y, Cost).
true :+ shortest(a, d, Cost).
\+ means “not”. A path is the shortest if there is no cheaper path
between the same two places. The last line asks the question.
Eyedia first finishes listing all paths, and only then looks for “no cheaper one”, so the search for something cheaper is over a complete list.
shortest(a, d, 6).
There are three ways from a to d, costing 7 (via b), 10 (via c) and 6 (via c, then b). The cheapest costs 6.
shortest rule.Steps 1–3 are shown in full. Step 4 is different: it is a claim that something does not exist.
absent obligation,
\+ cheaper(a, d, 6).An absence means Eyedia looked through everything it knows and found no cheaper path. A proof can show a path exists; it cannot show one doesn’t. So the checker records this as an obligation, and checks that nothing in the proof contradicts it — no cheaper path appears there.
Verdict: checked_with_obligations.
If you need a proof with nothing taken on trust, ask for it:
node bin/eyedia.js --proof examples/shortest-path.pl > /tmp/sp-proof.pl
node bin/eyedia.js --strict-proof --check-proof /tmp/sp-proof.pl examples/shortest-path.pl
The strict check refuses this proof — verdict failed(1) — because it leans
on the trusted absence. Nothing is wrong with the answer; strict mode just
does not accept “searched and found nothing” as evidence.
node bin/eyedia.js examples/shortest-path.pl # the answer
node bin/eyedia.js --proof examples/shortest-path.pl # with its proof
Or open it in the playground.
Add a direct road edge(a, d, 5). and run again: the answer becomes
shortest(a, d, 5).
“Best” always hides a “nothing better exists”. Eyedia shows the route it found, and tells you plainly which part of the answer is a search that came up empty.