How to build an AMT file
An AMT file is an ordinary Turtle file with three kinds of statements: concepts, nodes and weighted edges. The most common mistake is to forget that both ends of an edge have to be nodes.
- 1. The parts
- 2. A complete file to start from
- 3. Seven rules
- 4. Roles and axioms (optional)
- 5. Type and method (optional)
- 6. From existing RDF with SPARQL CONSTRUCT
- 7. Then check it
1. The parts
| Part | What it is | How you write it |
|---|---|---|
| Concept | a kind of thing (Person, Coin, Authority) | ex:Coin a amt:Concept ; rdfs:label "Coin" . |
| Node | one thing of that kind | ex:c1 amt:instanceOf ex:Coin ; rdfs:label "coin 1" . |
| Edge | a relation between two nodes that holds to a degree | a statement with rdf:subject, rdf:predicate, rdf:object, amt:weight |
| Type | what kind of fuzziness the weight expresses (optional; default vagueness) | fw:hasType fw:Uncertainty |
| Method | how the weight was obtained (optional) | fw:hasMethod fw:EqualShareRule |
| Role | names an edge type and says what it may connect (optional until an axiom needs it) | ex:knows a amt:Role ; rdfs:domain ex:Person ; rdfs:range ex:Person . |
| Axiom | a rule that derives new edges (optional) | see the data model |
2. A complete file to start from
Copy this, replace the names, keep the structure. It passes every check.
Start with the prefixes. ex: stands for your own data; use your own namespace.
@prefix amt: <http://academic-meta-tool.xyz/vocab#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix fw: <http://w3id.org/fw_ontology/> .
@prefix ex: <http://example.org/> .
# 1. Concepts: the kinds of things your file talks about
ex:Person a amt:Concept ;
rdfs:label "Person" .
# 2. Nodes: every end of an edge, each one an instance of a concept
ex:ada amt:instanceOf ex:Person ; rdfs:label "Ada Lovelace" .
ex:charles amt:instanceOf ex:Person ; rdfs:label "Charles Babbage" .
ex:mary amt:instanceOf ex:Person ; rdfs:label "Mary Somerville" .
# 3. Edges: subject, role, object and a weight between 0 and 1
[] rdf:subject ex:ada ;
rdf:predicate ex:knows ;
rdf:object ex:charles ;
amt:weight "0.8"^^xsd:decimal .
[] rdf:subject ex:charles ;
rdf:predicate ex:knows ;
rdf:object ex:mary ;
amt:weight "0.6"^^xsd:decimal .
3. Seven rules
- Every concept is declared with
a amt:Conceptand has anrdfs:label. - Every end of every edge is a node: it has
amt:instanceOf. This includes the thing an edge points to (the emperor, the place, the other person). A label alone does not make it a node. - Never write
amt:instanceOf amt:Concept. amt:Concept is the class of concepts. Point at a concept of your own. - An edge is a statement with four required properties, all together: subject, predicate, object and weight. The subject and object must be IRIs, not literals. Type and method are optional (section 5).
- Weights are decimals from 0 to 1 (
0.8or"0.8"^^xsd:decimal). 1 means certain, 0 means not at all. - Give nodes labels. Without one, the end of the IRI is shown, which is unreadable for IRIs like
.../coin?afeid=15661. - Extra triples are fine. AMT reads the parts above and ignores the rest. A link such as
lado:hasAMTfrom a coin to its edge statement is harmless and can stay; the engine finds edges by theiramt:weight, not by that link.
Rule 2 is the one behind the error AMT-E101. This is what it looks like when it is broken, and the repair:
Broken
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 nodeFixed
ex:Coins a amt:Concept ; rdfs:label "Coins" .
ex:Authority a amt:Concept ; rdfs:label "Authority" . # a second concept for the other end
ex:coin1 amt:instanceOf ex:Coins ; rdfs:label "coin 1" .
ex:vespasian amt:instanceOf ex:Authority ; rdfs:label "vespasian" . # now it is a node
[] rdf:subject ex:coin1 ; rdf:predicate ex:hasAuthority ; rdf:object ex:vespasian ; amt:weight 0.5 .4. Roles and axioms (optional)
Edges work without declared roles. As soon as you write an axiom, the roles it names have to be declared with a label, a domain and a range:
ex:Person a amt:Concept ; rdfs:label "Person" .
ex:ada amt:instanceOf ex:Person ; rdfs:label "Ada" .
ex:charles amt:instanceOf ex:Person ; rdfs:label "Charles" .
# A role is optional until an axiom needs it. Then it names its domain and range.
ex:knows a amt:Role ;
rdfs:label "knows" ;
rdfs:domain ex:Person ;
rdfs:range ex:Person .
[] rdf:subject ex:ada ; rdf:predicate ex:knows ; rdf:object ex:charles ; amt:weight 0.8 .
# An axiom: whoever knows someone who knows someone, knows that person a little (product logic)
ex:RCA a amt:RoleChainAxiom ;
amt:antecedents ( ex:knows ex:knows ) ;
amt:consequent ex:knows ;
amt:logic amt:ProductLogic .
All axiom types, with a figure and an example each, are on the data model page.
5. Type and method (optional)
An edge with subject, predicate, object and weight is a quadruple and is complete. Two more parts from the
FW ontology make it a hextuple: fw:hasType (fw:Vagueness,
fw:Uncertainty, fw:FuzzinessWobbliness, or fw:Certainty for a statement that is not fuzzy at all)
and fw:hasMethod (how the weight was obtained).
Add the prefix fw: and write them on the edge:
ex:Person a amt:Concept ; rdfs:label "Person" .
ex:ada amt:instanceOf ex:Person ; rdfs:label "Ada Lovelace" .
ex:charles amt:instanceOf ex:Person ; rdfs:label "Charles Babbage" .
# The weight 0.5 is an uncertainty (one of two readings is right), obtained by an equal share.
[] rdf:subject ex:ada ;
rdf:predicate ex:knows ;
rdf:object ex:charles ;
amt:weight "0.5"^^xsd:decimal ;
fw:hasType fw:Uncertainty ;
fw:hasMethod fw:EqualShareRule .
Without fw:hasType an edge is a vagueness edge, also at weight 1. To say that a statement is certain, write
fw:hasType fw:Certainty together with weight 1.0; a certain statement with a lower weight is reported as
AMT-W206. A type without a method is allowed, but the engine
points it out (AMT-N303); a type it does not know is reported as
AMT-W205. The reasoner gives inferred edges a method and a type as well; the
data model page says how.
6. From existing RDF with SPARQL CONSTRUCT
If your data is already RDF, you do not write the file by hand: a CONSTRUCT query produces it. The query has to
produce three things, in this order of importance:
- the concepts, declared with labels (once, as constant triples),
- both ends of every edge as nodes with
amt:instanceOfand a label, - one weighted statement per edge.
The example turns the vague and certain emperor attributions of the AFE coins into AMT. Sample input:
@prefix afe: <http://afe.dainst.org/coin?afeid=> .
@prefix nfdi_fw: <http://w3id.org/fw_ontology/> .
@prefix nm: <http://nomisma.org/id/> .
@prefix nmo: <http://nomisma.org/ontology#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
# a coin that is either of two emperors (vague)
afe:15661 a nmo:NumismaticObject ;
nmo:hasAuthority [ a nfdi_fw:VagueResourceValue, skos:Collection ;
skos:member [ nfdi_fw:hasConfidence 0.5 ; rdf:value nm:vespasian ],
[ nfdi_fw:hasConfidence 0.5 ; rdf:value nm:titus ] ] .
# a coin with one certain emperor
afe:15668 a nmo:NumismaticObject ;
nmo:hasAuthority nm:aurelian .
# a coin with one emperor, but only 60 % sure
afe:16048 a nmo:NumismaticObject ;
nmo:hasAuthority [ a nfdi_fw:UncertainValue ;
nfdi_fw:hasConfidence 0.6 ; rdf:value nm:philip_the_arab ] .
# a coin whose emperor is unknown: no edge, so it does not become a node
afe:11471 a nmo:NumismaticObject ;
nmo:hasAuthority nm:uncertain_value .
and the query:
PREFIX amt: <http://academic-meta-tool.xyz/vocab#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX nmo: <http://nomisma.org/ontology#>
PREFIX nm: <http://nomisma.org/id/>
PREFIX afe: <http://afe.dainst.org/coin?afeid=>
PREFIX nfdi_fw: <http://w3id.org/fw_ontology/>
CONSTRUCT {
# 1. Declare the concepts once, with labels
afe:Coins a amt:Concept ; rdfs:label "AFE coins" .
nm:Authority a amt:Concept ; rdfs:label "Authority" .
# 2. Make BOTH ends of every edge a node (this is the line people forget)
?coin amt:instanceOf afe:Coins ; rdfs:label ?coinLabel .
?authority amt:instanceOf nm:Authority ; rdfs:label ?authorityLabel .
# 3. One weighted statement per edge
?edge rdf:subject ?coin ;
rdf:predicate nmo:hasAuthority ;
rdf:object ?authority ;
amt:weight ?weight .
}
WHERE {
{
# vague or combined values: one edge per candidate, with its confidence
?coin a nmo:NumismaticObject ; nmo:hasAuthority ?container .
?container skos:member ?candidate .
?candidate rdf:value ?authority ; nfdi_fw:hasConfidence ?weight .
}
UNION
{
# one value with a confidence
?coin a nmo:NumismaticObject ; nmo:hasAuthority ?container .
?container a nfdi_fw:UncertainValue ; rdf:value ?authority ; nfdi_fw:hasConfidence ?weight .
}
UNION
{
# a certain authority: weight 1. Only real IRIs; the containers above are blank nodes
?coin a nmo:NumismaticObject ; nmo:hasAuthority ?authority .
FILTER(isIRI(?authority) && ?authority != nm:uncertain_value)
BIND("1.0"^^xsd:decimal AS ?weight)
}
BIND(BNODE() AS ?edge)
BIND(STRAFTER(STR(?coin), "?") AS ?coinLabel)
BIND(STRAFTER(STR(?authority), "http://nomisma.org/id/") AS ?authorityLabel)
}
Things to adapt: the two concept IRIs, the properties in WHERE, and how labels are made (here
STRAFTER takes the part of the IRI after a marker). BNODE() makes a fresh node for each edge statement.
A CONSTRUCT that leaves out the second part (the authority nodes) is the typical cause of
AMT-E101: the coins are nodes, the emperors are not. Run the check on a small
sample first, then on the whole file.
6. Then check it
Save the result as my.ttl and continue with how to check an AMT file,
then run it and look at the result.