Academic Meta Tool

How to check an AMT file

Three checks, from "is it well formed" to "does it say what I meant". Run them while you build the file, not after. Every message names the IRI it is about and says what to add.

1. What is checked

CheckQuestionMessage looks like
Validation (SHACL)Is the file well formed? Labels, weights, axioms complete?FAIL Validation failed … [1] ex:Thing …
DiagnosticsDoes it mean what you think? Are all edge ends nodes?ERR [AMT-E101] …
ConsistencyAfter reasoning, do the integrity axioms hold (disjoint roles, no reflexive roles)?FAIL 2 consistency violation(s)

The first two need no axioms and are what you want while building. The third only matters once you use axioms.

2. Run the check

With the wrapper (needs Python and git; it fetches the engine itself):

git clone https://github.com/alpaca-fair-framework/amt-runner
cd amt-runner
python run_amt.py my.ttl --check-only

If you get "does not know --check-only" or a Python traceback, the engine copy cached in .amt-cache/ is old:

python run_amt.py my.ttl --check-only --update

With the engine installed (pip install -e . in amt-engine):

amt-runner my.ttl --check-only
amt-runner my.ttl --check-only --strict
amt my.ttl --validate-only

In Python:

from amt import load_amt, diagnose
amt = load_amt("my.ttl")
for finding in diagnose(amt):
    print(finding.format())

3. Read the output

A file whose emperors are not nodes (the case that prompted this page):

VAL  Validating my.ttl ...
OK   Validation passed.
LOAD Loading my.ttl ...
OK   1 Concepts | 0 Roles | 4 Nodes | 7 Edges | 0 Axioms        <- 4 nodes, but 7 edges that end somewhere else

DIAG 1 error(s), 0 warning(s), 1 note(s):
ERR  [AMT-E101] 7 IRI(s) are the subject or object of a weighted statement but are not AMT nodes: <http://nomisma.org/id/aurelian>, ...
  -> Every end of an edge needs an amt:instanceOf … Add, for each, e.g.:
     <http://nomisma.org/id/aurelian> amt:instanceOf <…> ; rdfs:label "..." .

Compare the counts in the OK line with what you expect: if there are far fewer Nodes than the things your edges connect, some are not declared. A missing node is never silent any more, but a count that is too low is still the quickest hint.

Earlier versions of the engine stopped later with AssertionError: non existent node ... when drawing the graph. That was this same problem; it is now reported up front, and the graph shows such IRIs as grey placeholder nodes.

4. The messages, one by one

Diagnostics

AMT-E101 error

N IRI(s) are the subject or object of a weighted statement but are not AMT nodes

Cause. An edge points at (or starts from) an IRI that has no amt:instanceOf. The reasoner cannot place it, so the edge cannot be followed or drawn. Giving the IRI an rdfs:label is not enough.

Fix. Add amt:instanceOf and a concept to every IRI named in the message. If these IRIs are a different kind of thing than the others (coins and emperors, say), declare a second concept for them.

Example

ex:Coins a amt:Concept ; rdfs:label "Coins" .
ex:coin1 amt:instanceOf ex:Coins ; rdfs:label "coin 1" .

[] rdf:subject ex:coin1 ; rdf:predicate ex:hasAuthority ; rdf:object ex:vespasian ; amt:weight 0.5 .
ex:vespasian rdfs:label "vespasian" .          # a label does not make it a node

AMT-E102 error

<...> is declared as amt:instanceOf amt:Concept / is the target of amt:instanceOf but is not declared as an amt:Concept

Cause. amt:instanceOf must point at a concept of your own, and that concept must be declared with a amt:Concept. Pointing at amt:Concept itself, or at an IRI that is never declared, means those nodes are not loaded.

Fix. Declare the concept once with a label and point to it.

Example

ex:coin1 amt:instanceOf ex:Coins .             # ex:Coins is never declared as a concept

AMT-E103 error

A statement with amt:weight lacks rdf:subject / rdf:predicate / rdf:object

Cause. A weighted edge needs its four required properties together (subject, predicate, object, weight). A statement with a missing part is ignored.

Fix. Add the missing property.

Example

ex:C a amt:Concept ; rdfs:label "C" .
ex:a amt:instanceOf ex:C .
[] rdf:subject ex:a ; rdf:predicate ex:r ; amt:weight 0.5 .      # no rdf:object

AMT-E104 error

The statement ... has amt:weight X and fw:hasDegreeOfConnection Y

Cause. The FW ontology calls the weight fw:hasDegreeOfConnection; AMT calls it amt:weight. The engine reads both and writes amt:weight. If a statement carries both with different values, amt:weight is used and this message tells you which statement it was.

Fix. Keep one of the two properties, or give both the same value.

AMT-W201 warning

Weight X is outside [0, 1]

Cause. Weights are degrees of truth between 0 and 1. SHACL rejects the file first, but with --no-validate the engine would clamp values above 1.

Fix. Use a value between 0 and 1.

Example

ex:C a amt:Concept ; rdfs:label "C" .
ex:a amt:instanceOf ex:C . ex:b amt:instanceOf ex:C .
[] rdf:subject ex:a ; rdf:predicate ex:r ; rdf:object ex:b ; amt:weight 1.5 .

AMT-W205 warning

... is used as fw:hasType but is not one of the known types

Cause. A statement can say what kind of fuzziness its weight expresses: fw:Vagueness, fw:Uncertainty, fw:FuzzinessWobbliness, or fw:Certainty for a statement that is not fuzzy at all. Any other value is kept and counted as a type of its own, which is probably a typo or a term from another vocabulary.

Fix. Use one of the four, or leave fw:hasType out: a statement without a type is a vagueness statement.

AMT-W206 warning

N statement(s) have fw:hasType fw:Certainty but a weight below 1

Cause. A certain statement holds fully, so its weight is 1.0. A weight below 1 on a certain statement contradicts itself; the engine keeps the weight as it is and still counts the statement as certain, so an edge derived from it can be certain with a weight below 1.

Fix. Give the statement weight 1.0, or change its type to fw:Vagueness, fw:Uncertainty or fw:FuzzinessWobbliness.

AMT-W204 warning

The file contains no weighted statement

Cause. There is nothing to reason about. Typical reasons: the edges are written without amt:weight, or they are only linked from the nodes (for example with lado:hasAMT) and the reified statement itself is missing.

Fix. Write each edge as a statement with rdf:subject, rdf:predicate, rdf:object and amt:weight.

AMT-N303 note

N statement(s) have fw:hasType but no fw:hasMethod

Cause. The type says what kind of fuzziness the weight is, the method says how it was obtained. The type is used without a method, so nothing breaks; the method is what makes the statement reproducible.

Fix. Add fw:hasMethod, for example fw:EqualShareRule for a weight that comes from sharing equally.

AMT-N301 note

Role ... is used in edges but not declared as an amt:Role

Cause. Fine for simple files. Only axioms need declared roles.

Fix. Declare the role (label, domain, range) if you want to use it in an axiom.

AMT-N302 note

N node(s) have no rdfs:label

Cause. The end of the IRI is shown instead, which is hard to read in the graph.

Fix. Add an rdfs:label to the nodes.

Validation (SHACL)

These come from ontology/amt-shapes.ttl. The line above each message is the IRI it is about, followed by a hint on what to add.

Each Concept must have at least one rdfs:label.

A concept has no label. The message names the IRI. Beware: every object of amt:instanceOf counts as a concept, so this message also appears when you write amt:instanceOf amt:Concept or point at an undeclared class.

ex:Coins a amt:Concept .                       # no rdfs:label
ex:coin1 amt:instanceOf ex:Coins .

Each Role must have at least one rdfs:label. / exactly one rdfs:domain / exactly one rdfs:range.

A role declared with a amt:Role needs a label, one domain and one range.

amt:weight must be a single xsd:decimal in the closed interval [0, 1].

A weight is missing, doubled, not a number, or outside 0 to 1.

ex:C a amt:Concept ; rdfs:label "C" .
ex:a amt:instanceOf ex:C . ex:b amt:instanceOf ex:C .
[] rdf:subject ex:a ; rdf:predicate ex:r ; rdf:object ex:b ; amt:weight 1.5 .

RoleChainAxiom must have exactly one amt:consequent / amt:logic ...

An axiom lacks a part, or uses the legacy and the list form of antecedents at once. The messages for the other axiom types (inverse, subsumption, disjoint) work the same way.

RoleChainAxiom using amt:HamacherProduct must specify amt:logicParameter.

The Hamacher operator needs its parameter: amt:logicParameter 0.5.

This is how a validation failure reads (two mistakes in one file):

FAIL Validation failed with 2 violation(s):
  [1] amt:Concept
      Each Concept must have at least one rdfs:label.  (property: rdfs:label)
      -> Add  amt:Concept rdfs:label "..." .  If this IRI is not meant to be a concept, check where it is used as the object of amt:instanceOf: …
  [2] ex:Thing
      Each Concept must have at least one rdfs:label.  (property: rdfs:label)
      -> Add  ex:Thing rdfs:label "..." . …

5. Exit codes

CodeMeaning
0Done. Diagnostics may still have printed errors unless you used --strict; consistency violations of your axioms also leave this at 0.
1The file did not pass validation, or --strict found a diagnostic error.
2The input file was not found.
3Something unexpected failed. Run with --debug and report it with the file, please.

6. Questions that come up

Is lado:hasAMT (or any other link from a node to its edge statement) right?
It does no harm. The engine finds edges by their amt:weight and reads the subject, predicate and object from the statement itself. You can keep such a link for your own queries; AMT ignores it.
The checker says "OK" but the graph is empty or too small.
Look at the counts in the OK line and at the diagnostics. Zero edges usually means the statements have no amt:weight (AMT-W204); too few nodes means AMT-E101 or AMT-E102.
"Each Concept must have at least one rdfs:label", but I declared my concepts.
Every object of amt:instanceOf counts as a concept. The message names the IRI: it is either a concept of yours that lacks a label, or something you pointed at by mistake (often amt:Concept itself).
Do I need roles?
Not until you write axioms. Undeclared roles show up as a harmless note (AMT-N301).
Does validation check my data against my own ontology?
No. It checks that the file is valid AMT. Whether your concepts and roles make sense for your domain is yours to decide.
It ends with a Python traceback.
Update the engine (--update with the wrapper, git pull otherwise) and run again. If it persists, run with --debug and open an issue at amt-engine with the file attached.