This page formally defines what a query produces, what a test compares, and under what conditions a test passes or fails. It is the reference counterpart to ../getting-started/reading-a-test.md, which introduces the same material gently.
A query is written as an expression followed by ?:
E ?
Running a query on expression E produces a query result: a pair
( FactsSet , FactsIsClosed , FalsehoodsSet , FalsehoodsIsClosed )
where:
FactsSetis the set of bindings ofE's free variables for whichEhas been proven to be a factFalsehoodsSetis the set of bindings for whichEhas been proven to be a falsehoodFactsIsClosedistrueiff the reasoner certifies thatFactsSetcontains every binding that makesEa factFalsehoodsIsClosedis defined analogously for falsehoods
These two "closed" flags are what the incompleteness marker .. reports in textual form. A side is closed iff its printed form omits ..; a side is open iff its printed form includes ...
A binding that is in neither set, on a side that is closed, has been affirmatively excluded from that side. A binding that is in neither set, on a side that is open, has no claim made about it.
Query results are printed as:
[ facts-list ][ falsehoods-list ]
where each list is a comma-separated sequence of bindings, optionally ending in .. to indicate that side is open.
A binding is written as (v1=value1, v2=value2, ...) or as () for the empty binding (a solution with no free variables). An empty list [] is the closed claim "no bindings on this side."
| Printed form | FactsSet | Facts closed? | FalsehoodsSet | Falsehoods closed? |
|---|---|---|---|---|
[()][] |
{()} |
yes | {} |
yes |
[][()] |
{} |
yes | {()} |
yes |
[..][..] |
{} |
no | {} |
no |
[(f=5)][..] |
{(f=5)} |
yes | {} |
no |
[(a=T1),(a=T2)][..] |
{(a=T1),(a=T2)} |
yes | {} |
no |
[][..] |
{} |
yes | {} |
no |
[(a=0),..][..] |
{(a=0)} |
no | {} |
no |
A test is written as:
E ? [ expected-facts ][ expected-falsehoods ]
The engine runs the query E ? to get an actual result, and compares the actual result to the expected result expressed by the two bracket literals.
The test passes iff both of the following hold:
expected-factsmatchesactualFactsSetand its closure flagexpected-falsehoodsmatchesactualFalsehoodsSetand its closure flag
"Matches" is defined per-side as follows.
Let expected be one bracket literal and actual be the corresponding actual side of the query result.
- If
expectedis closed (does not contain..), it matches iffexpectedis the same set of bindings asactual, andactualis also closed. - If
expectedis open (contains..), it matches iff:- every binding listed explicitly in
expectedis present inactual, and - any remaining bindings in
actualare allowed (no enumeration constraint beyond the listed ones).
- every binding listed explicitly in
In short: a closed bracket asserts an exact set; an open bracket asserts a lower bound (the listed bindings must be present; more are permitted).
A test that only asserts the facts side (by using [..] on the falsehoods side) is not checking falsehoods at all. Conversely, [][(a=T1)] asserts a specific falsehood and an empty, closed facts side. Both sides are first-class; a test expresses whatever facts-and-falsehoods claims the author intends.
Actual result: FactsSet = {(f=5)}, facts closed, FalsehoodsSet = {}, falsehoods open.
Checking:
- Expected facts
[(f=5)]is closed. Equals{(f=5)}, and actual facts is closed. ✓ - Expected falsehoods
[..]is open with no listed bindings. Every listed binding (none) is in actual. ✓
Passes.
Actual result: FactsSet = {()}, facts closed, FalsehoodsSet = {}, falsehoods closed.
Checking:
- Expected facts
[()]is closed. Equals{()}, and actual is closed. ✓ - Expected falsehoods
[]is closed. Equals{}, and actual is closed. ✓
Passes.
Actual result: FactsSet = {}, facts open, FalsehoodsSet = {}, falsehoods open.
Checking:
- Expected facts
[..]is open with no bindings. Actual has no bindings. ✓ - Expected falsehoods
[..]is open with no bindings. Actual has no bindings. ✓
Passes.
From integersTest.nl. Actual result: FactsSet = {} but open (there are infinitely many positive integers, so the reasoner cannot close the side); FalsehoodsSet = {(a=0)} open (there are other falsifying bindings too: (a=-1), (a=-2), ...).
Checking:
- Expected facts
[..]open with no listed bindings. ✓ - Expected falsehoods
[(a=0),..]open with(a=0)listed.(a=0)is in actual. ✓
Passes.
If we changed the last test to a>0 ? [..][(a=1),..], it would fail: (a=1) is a fact side binding of a>0, not a falsehood. The expected falsehoods list asserts (a=1) is a falsehood, but the actual falsehoods side does not contain it.
Given a binding b of the free variables, the query result classifies b as follows:
bin actual facts ⇒bis a factbin actual falsehoods ⇒bis a falsehoodbin neither, both sides closed ⇒ impossible (would mean the reasoner assertsbis neither, but has certified completeness, yetbis a syntactically valid binding — treated as a programming error)bin neither, at least one side open ⇒b's status is unknown (the open side makes no claim)
See three-valued-logic.md for the semantic model behind this.
A query without expected brackets (E ?) does not pass or fail; it just prints its result. Bare queries are useful during development. A file of bare queries (like queryOnly.nl) runs and produces a transcript, which you can read, compare to your expectations, and then turn into tests by adding brackets.
../getting-started/reading-a-test.md— gentle introduction to the same materialthree-valued-logic.md— what facts, falsehoods, and unknown meanwriting-rules.md— how rules produce the facts and falsehoods that tests observe