Seven readings about the knowledge, where the rest of the instrumentation reads the engine: which rules never fire, how skewed the predicate extents are, how deep the rule graph's chains reach, how much of the taxonomy is connected to anything, which argument declarations name a position their predicate does not have, which rules another rule already covers, and which rule pairs would contradict each other if both fired.
settle-stats and chain-stats answer how the engine ran. These answer whether the
knowledge is any good, which is the question the author of a large KB has and the one
nothing else here asks. None of it is a gate: a threshold on somebody's ontology is not
a build failure, and lein perf gates the engine while this reports on the content.
Every reading comes off state that already exists, and nothing new is indexed. A
rule -> firings index would be a second copy of the JTMS adjacency to keep in step,
which is the failure class the taxonomy's single :support map exists to avoid. So the
cost is
`O(terms + rules + firings + ancestor pairs + declarations × super-predicates
and neverO(sentexes)— the **vocabulary and the rule set**, which on a KB of a million facts about a hundred individuals is a hundred-odd names and a few hundred rules. **Ancestor pairs and not edges**, which is the term worth spelling out:taxonomy-coveragereads each type's wholegenl` up-closure to find
the root, so a chain of V types costs Θ(V²) where it has V−1 edges. Vocabulary-sized on
any ontology anybody writes, which is the claim that matters, and not an edge count::consequences adjacency, the candidate
set jtms/restrength-informant* uses, and never scans the justification map. At
11.5M justifications that difference is the report existing or not.(genl ?a ?b) & (genl ?b ?c) => (genl ?a ?c) alone
makes it so — so memoizing a path re-explores the reachable subgraph along every one
of them. Memoize the component.× super-predicates above and the
one term of the formula that is not flat. It is also the second reader of the record
store, for the declarations themselves — vocabulary, and therefore few.+ rules + candidate pairs is what they add. A pair
is a candidate only where the consequent index says one rule could conclude what the
other does, and the two properties they read are gated on the KB declaring any
(marked-groups), so a KB whose rules conclude different things pays the grouping and
stops.Every count is of what is stored. A believed extent is O(n) per predicate
(vaelii.core/count-with-functor says why), which would turn an O(predicates) report
into an O(sentexes) one — and stored-vs-believed is exactly the distinction an author
wants to see rather than have chosen for them. Two readings consult belief anyway: the
firing census, because "fired and every conclusion defeated" is a category and not a
rounding error, and the declaration census, because a disbelieved declaration constrains
nothing for a reason that has nothing to do with the position it names. The two
rule-hygiene readings are as-stored about the rules and belief-following about the
declarations they read, which rules read against each other below argues.
Seven readings about the **knowledge**, where the rest of the instrumentation reads the engine: which rules never fire, how skewed the predicate extents are, how deep the rule graph's chains reach, how much of the taxonomy is connected to anything, which argument declarations name a position their predicate does not have, which rules another rule already covers, and which rule pairs would contradict each other if both fired. `settle-stats` and `chain-stats` answer *how the engine ran*. These answer *whether the knowledge is any good*, which is the question the author of a large KB has and the one nothing else here asks. None of it is a gate: a threshold on somebody's ontology is not a build failure, and `lein perf` gates the engine while this reports on the content. **Every reading comes off state that already exists, and nothing new is indexed.** A `rule -> firings` index would be a second copy of the JTMS adjacency to keep in step, which is the failure class the taxonomy's single `:support` map exists to avoid. So the cost is `O(terms + rules + firings + ancestor pairs + declarations × super-predicates + candidate rule pairs)` and never `O(sentexes)` — the **vocabulary and the rule set**, which on a KB of a million facts about a hundred individuals is a hundred-odd names and a few hundred rules. **Ancestor pairs and not edges**, which is the term worth spelling out: `taxonomy-coverage` reads each type's whole `genl` up-closure to find the root, so a chain of V types costs Θ(V²) where it has V−1 edges. Vocabulary-sized on any ontology anybody writes, which is the claim that matters, and not an edge count: - **One walk over the term roster**, and one is the number: the functor names come off it by filter, and the type-shaped names come off *those* rather than off the roster a second time. Measured at 8x the terms for 8x the cost, so the walk is the term the formula above leads with. - **Three O(1) index reads per functor name** — the stored extent off the count-aware trie, and the rule postings *both* ways. That is everything the extent and chain readings need, and it is where the rule handles come from, so nothing on this pass reaches the record store at all — the record reads are the listed rules' and the two rule-hygiene readings' below. - **The firing census reads each rule's own `:consequences` adjacency**, the candidate set `jtms/restrength-informant*` uses, and never scans the justification map. At 11.5M justifications that difference is the report existing or not. - **The chain depth condenses strongly-connected components first.** A KB's rule graph is cyclic in the ordinary case — `(genl ?a ?b) & (genl ?b ?c) => (genl ?a ?c)` alone makes it so — so memoizing a *path* re-explores the reachable subgraph along every one of them. Memoize the component. - **The declaration census enumerates the declarations** and asks each what binds its own predicate's length, rather than asking every predicate what declares it. That is a map read where the predicate carries a length of its own and one arity read per super-predicate where it inherits one, which is the `× super-predicates` above and the one term of the formula that is not flat. It is also the second reader of the record store, for the declarations themselves — vocabulary, and therefore few. - **The two rule-hygiene readings are the third**, and the one that reads a record per *rule*: a rule's antecedents, its consequent and its four availability slots live on the record and nowhere else, so `+ rules + candidate pairs` is what they add. A pair is a candidate only where the consequent index says one rule could conclude what the other does, and the two properties they read are gated on the KB declaring any (`marked-groups`), so a KB whose rules conclude different things pays the grouping and stops. Every count is of what is **stored**. A believed extent is O(n) per predicate (`vaelii.core/count-with-functor` says why), which would turn an O(predicates) report into an O(sentexes) one — and stored-vs-believed is exactly the distinction an author wants to see rather than have chosen for them. Two readings consult belief anyway: the firing census, because "fired and every conclusion defeated" is a category and not a rounding error, and the declaration census, because a disbelieved declaration constrains nothing for a reason that has nothing to do with the position it names. The two rule-hygiene readings are as-stored about the *rules* and belief-following about the *declarations* they read, which `rules read against each other` below argues.
(census kb {:keys [limit on-progress]})The seven readings as one map — {:rules … :extents … :chains … :taxonomy … :declarations … :subsumption … :clashes …}. vaelii.core/kb-quality is the door and
documents the options.
The seven readings as one map — `{:rules … :extents … :chains … :taxonomy …
:declarations … :subsumption … :clashes …}`. `vaelii.core/kb-quality` is the door and
documents the options.How many rules and how many heavy predicates the report lists before it says it
truncated. A cap rather than the whole set because the counts are the headline and a
30,000-entry list is not one; :limit raises it.
How many rules and how many heavy predicates the report lists before it says it truncated. A cap rather than the whole set because the *counts* are the headline and a 30,000-entry list is not one; `:limit` raises it.
(report {:keys [rules extents chains taxonomy declarations subsumption clashes]
:as quality})The census map as Markdown — the seven readings in the order an author reads them,
the counts first and the lists after. A map that is not a census answer is refused
(:not-a-report) rather than rendered as a page of zeros, which is what a caller passing
the wrong map would otherwise be handed and believe.
:declarations, :subsumption and :clashes are not in the shape test, and that is
deliberate: a census answer from before one of those readings existed is still a census
answer, and refusing to render one would turn a stored report into an unreadable one.
Each section is written when its key is there and omitted when it is not, and a listed
declaration's reason line is the :message the census carries rather than a second
derivation of it — which would be the same sentence written twice, free to drift on
either side.
The `census` map as Markdown — the seven readings in the order an author reads them, the counts first and the lists after. A map that is not a `census` answer is refused (`:not-a-report`) rather than rendered as a page of zeros, which is what a caller passing the wrong map would otherwise be handed and believe. `:declarations`, `:subsumption` and `:clashes` are **not** in the shape test, and that is deliberate: a census answer from before one of those readings existed is still a census answer, and refusing to render one would turn a stored report into an unreadable one. Each section is written when its key is there and omitted when it is not, and a listed declaration's reason line is the `:message` the census carries rather than a second derivation of it — which would be the same sentence written twice, free to drift on either side.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |