The TikZ and PGF Packages
Manual for version 3.1.10
Libraries
68 Resource Description Framework Library¶
With certain output formats (in particular, with svg), TikZ can add semantic annotations to an output file. Consider as an example the drawing of a finite automaton. In your TeX code, you might have a nice description of the automaton like the following:
This description of the automaton carries a lot of “semantic information” like the information that the node a is not just some node, but actually the initial state of the automaton, while c is a final state. Unfortunately, in the output produced by TikZ, this information is normally “lost”: In the output, a is only a short text, possibly with a circle drawn around it; but there is no information that this text and this circle together form the state of an automaton.
As a human (more precisely, as a computer scientist), you might “see” that the text and the circle form a state, but most software will have a very hard time retrieving this semantic information from the output. In particular, it is more or less impossible to design a search engine that you can query to find, say, “all automata with three states” in a document.
This is the point were semantic annotations come in. These are small labels or “hints” in the output that tell you (and, more importantly, a program) that the text and the circle together form a state of an automaton. There is a standard for specifying such annotations (“resource description framework annotations”, abbreviated rdfa) and TikZ provides a way of adding such annotations to an output file using the rdf engine key, explained in a moment. Note, however, that the output format must support such annotations; currently TikZ only supports svg.
68.1 Starting the RDF Engine¶
-
TikZ Library rdf ¶
-
/tikz/rdf engine on(no value) ¶
\usetikzlibrary{rdf} %
LaTeX
and plain
TeX
\usetikzlibrary[rdf] % ConTeXt
You need to load this library for the keys described in the following. However, even when this library is loaded,
rdf information is only written to the output inside scopes where the following key is set:
Switches “on” the generation of rdf information for the current TeX scope. The idea is that libraries can internally use the rdf engine key (explained below) a lot in order to provide good semantic information in the output when desired, but need not worry that this will bloat output files since users have to use this key explicitly to include semantic information in the output.
-
/tikz/rdf engine=⟨rdf keys⟩(no default) ¶
This key only has an effect when rdf engine on is called, otherwise the argument is silently ignored. The ⟨rdf keys⟩ get executed with the path prefix /tikz/rdf engine at the beginning of the current scope (for a node, at the beginning of the node’s scope). Depending on which keys are used, semantic information gets to be added to the output.
Note that you cannot simply use the keys with path prefix /tikz/rdf engine directly since they need to be executed at very specific times during TikZ’s processing of scopes. Always call those keys via this key.
The following key is useful for generally setting the prefix for a larger number of annotations:
-
/tikz/rdf engine/prefix=⟨prefix: iri⟩(no default) ¶
-
\tikzrdfhashmark ¶
Inside the current scope, you can use ⟨prefix⟩: inside curies (compact universal resource identifier expressions, see the rdfa specification) as an abbreviation for the ⟨iri⟩. (It has the same effect as the prefix attribute in rdfa.) You can use this key several times for a given scope.
The above could also be written more verbosely as
The use of the command \tikzrdfhashmark is necessary since TeX assigns a special meaning to hash marks. The command simple expands to a “normal” hash mark for use in texts.
Expands to # with catcode 11.
68.2 Creating Statements¶
TikZ’s method of adding semantic information to an output is based on the principles underlying the resource description framework (rdf). In this framework, all semantic information is encoded using a large graph consisting of nodes and connecting directed edges, but the nodes are called resources and the edges are called statements. A resource is identified by an iri, an internationalized resource identifier, which basically looks like the well-known urls, but allows additional Unicode characters. Note that these iris do not need to point to “real” webpages, they are just a way of conceptually identifying resources uniquely and permanently. Similarly, each edge (statement) of the rdf graph has such an iri attached to it, which identifies the “flavour” of the arc.
In a “mathematical” graph, each edge has a “tail” and a “head” vertex and a label, but in the context of the resource description framework these notions are called differently: As mentioned before, an edge is called a statement, the tail of this edge is called the subject, the head is called the object (in the linguistic sense), and the label is called the predicate. Thus, a statement is – quite fittingly – a triple “subject predicate object”.
Note that in the rdf framework all semantic information must be encoded using statements of this fixed kind. Many semantic notions are easy to store in this way such as “Albert Einstein was a physicist” (“Albert Einstein” is the subject, “was” is the predicate, “a physicist” is the object), but other notions do not fit well like “The automaton has states \(q_1\), \(q_2\), \(q_a\), and \(q_b\)” since there are several objects in the statement. Nevertheless, all information must be encoded as simple statements with a single subject, a single predicate, and a single object.
You add an rdf statement to the output file using the following key:
-
/tikz/rdf engine/statement={⟨options⟩}(no default) ¶
-
/tikz/rdf engine/statements/subject=⟨subject⟩(no default) ¶
-
1. A curie (a compact universal resource identifier expression, see the rdfa specification for details). Examples are standard urls like http://www.example.org, but also text like #my_automaton. Note that in order to include a hashmark in a curie you should use the command \tikzrdfhashmark, which expands to a hash mark (TeX treats hash marks in a special way, which is why this command is used here).
-
2. When the ⟨subject⟩ starts with an opening parenthesis, that is, with “(”, the ⟨subject⟩ must have the form (⟨node or scope name⟩). In this case, the ⟨node or scope name⟩ must be the name of an already existing node (the current node or scope is considered as “existing” here). Then, the curie #⟨id⟩ is used as subject, where the ⟨id⟩ is a unique internal identifier for the node.
As an example, suppose you wish to specify that a node has some other node as child, you could write the following:
-
/tikz/rdf engine/statements/predicate=⟨predicate⟩(no default) ¶
-
/tikz/rdf engine/statements/object=⟨object⟩(no default) ¶
-
1. As for subject and predicate you can use a curie here. This is the default unless one of the following special cases is used:
-
2. As for subject and predicate, you can use the syntax (⟨name of node or scope⟩) to create and use a curie for the node or scope.
-
3. If the ⟨object⟩ starts with " and is of the form "⟨literals⟩", the object of the statement is not a curie (not a normal “resource”) but the string of ⟨literals⟩ given.
-
4. If the ⟨object⟩ is the text “scope content”, the object of the statement is actually the whole contents of the scope to which this statement is attached.
-
5. Finally if the ⟨object⟩ is of the form "⟨literals⟩" and scope content, the contents of the scope is “normally” the object, but this gets “overruled” by the ⟨literals⟩. Formally, this means that the object is the ⟨literals⟩, but the intended semantics is that the object is the scope content, only for further processing it should be considered to be ⟨literals⟩. A typical example is the case where the scope content is, say, the text “January 1st, 2000” but the ⟨literals⟩ are set to 2000-01-01, which is easier for software to process:
-
/tikz/rdf engine/statements/has type=⟨type⟩(no default) ¶
Each use of this key will add one rdf statement to the output file. The ⟨options⟩ will be executed with the path prefix /tikz/rdf engine/statements and must use the three keys subject, predicate, and object to specify the three components of the statement (these keys can, however, be called by styles internally, so not all statements will explicitly set these three keys). Note that all three must always be set, it is not possible to setup, say, just a subject for a scope and then omit the subject for statements inside the scope. (However, using styles you can setup things in such a way that a certain subject is used for several statements.)
The statements are normally added at the beginning of the scope where the rdf engine command is used (except when the object is scope content, which is explained later). This means that when you use prefix inside an rdf engine command, it will apply to all statements, regardless of the order.
Sets the subject of the to-be-created statement. The ⟨subject⟩ can be in one of two possible formats:
You can use a macro as ⟨subject⟩, it will be expanded before the above syntax check is done.
If you use the subject key several times inside a single statement command, (only) the last subject is used.
Sets the predicate for the statement. The syntax is exactly the same as for the subject. Unlike for subjects, you can use the predicate key several times inside a single statement and the uses will “accumulate” and several statements are created, namely one statement for each use of predicate for the subject and object specified inside the use of statement. This behavior is not very systematic (it violates the rule “one statement per statement”) and you should normally use the statement once for each use of the predicate key. However, in conjunction with the object scope content it is necessary to allow this behavior.
Sets the object for the statement. The syntax allowed for the ⟨object⟩ is as follows:
For the last two cases, only one statement may be given per scope that has the scope content as its object; if more than one is given, the last one wins. This is the reason why several uses of predicate are allowed in a statement.
This style is a shorthand for predicate=rdf:type and object=⟨type⟩.
68.3 Creating Resources¶
In rdf statements, when you can use the name of a TikZ scope or node surrounded by parenthesis, a curie is inserted into the output that references this scope or node. While this makes it easy to describe relationships between existing nodes, in library code (rdf generation code added to library styles and gets executed as a “byproduct”) there are two situations where this method is insufficient:
-
1. You may sometimes wish to create additional resources in the rdf graph that are not represented by any concrete node or scope in the TikZ picture. For instance, a finite automaton has a set of states and a set of transitions, but neither of these “containers” has any concrete representation in the output. One could, of course, create “dummy scopes” for this purpose, but this is rather hard to do inside styles of a library.
-
2. You may not know the name of the current scope in library code. For instance, a style like state, which can be added to a node to indicate that the node is supposed to be a state in a finite automaton, might contain something like the following code:
The problem is, of course, what should be passed to the subject. We cannot even write something like (\tikz@fig@name) since no name may have been set for the state.
Each of the above problems is solved by a special keys:
-
/tikz/rdf engine/get new resource curie=⟨macro⟩(no default) ¶
The ⟨macro⟩ will be set to a new unique curie that can be used anywhere where a curie is allowed. Here is an example how we can add a state and a transition container to an automaton, both of which have no corresponding scope in TikZ.
The ⟨macro⟩ will be valid for the whole scope.
-
/tikz/rdf engine/get scope curie=⟨macro⟩(no default) ¶
The ⟨macro⟩ will be set to a unique curie that represents the scope or node. If the scope is named (using the name key or the special parenthesis syntax for nodes) and this name is later referenced in another statement, the same curie will be generated. Note how in the following code no name is given for the automaton, which means that the whole rdf code could be moved inside a style like finite automaton or something similar.
The ⟨macro⟩ will be valid for the whole scope.
The following key builds on the above keys:
-
/tikz/rdf engine/scope is new context(no value) ¶
This key executes get scope curie=\tikzrdfcontext, thereby setting the macro \tikzrdfcontext to the current scope. The idea is the key is used with “major resources” and that keys can use this macro as the subject of statements if no subject is given explicitly. For instance, a title key might be defined as follows:
68.4 Creating Containers¶
A container is a resource that represents a set or a sequence of elements. In rdf this is modeled by having a statement say that the type of the resource is something special like rdf:Seq and then for each member resource of the container add a statement saying that the container has as its \(i\)th member the member resource. Here is an example of a container with two elements:
However, the above code is error-prone and does not integrate well with styles and libraries. For this reason, TikZ offers some styles that may help in creating containers:
-
/tikz/rdf engine/statements/is a container(no value) ¶
Add this key to a statement in order to tell TikZ that it should setup a special counter for the subject of the statement that keeps track of the container’s children.
-
/tikz/rdf engine/statements/has as member(no value) ¶
This key may only be added to statements whose subject was previously used as a subject in a statement containing the is a container key. In this case, the internal counter will be increased and the predicate will be set to rdf:_⟨count⟩. This means that we can write the above code as:
-
/tikz/rdf engine/statements/is a sequence(no value) ¶
This is a shorthand for predicate = rdf:Seq, is a container. In the above example we could say:
-
/tikz/rdf engine/statements/is a bag(no value) ¶
This is a shorthand for predicate = rdf:Bag, is a container.
-
/tikz/rdf engine/statements/is an alternative(no value) ¶
This is a shorthand for predicate = rdf:Alt, is a container.
68.5 Creating Semantic Information Inside Styles and Libraries¶
The rdf library was designed in such a way that normal document authors do not need to use the keys of the library explicitly, except possibly for saying rdf engine on somewhere at the beginning. Instead, library authors should include the necessary commands to generate rdf information that is then automatically included in the output. Furthermore, if the author does not “switch on” the generation of rdf information, all uses of rdf engine will simply be ignored silently and neither the speed of compilation nor the size of the generated files is impacted.
68.5.1 An Example Library for Drawing Finite Automata¶
In the following, we have a look at how a library might be augmented by rdf generation keys. The library we augment is a (fictitious) library for drawing finite automata. The library offers the following styles:
-
1. dfa and nfa can be added to a scope to indicate that the scope contains a deterministic or a nondeterministic finite automaton.
-
2. state can be added to a node to indicate that the node is a state in the automaton.
-
3. initial and final are used to indicate that a state is an initial or final state, which should be rendered in a special way.
-
4. transition can be added to an edge to indicate that there is a transition in the automaton from the first state to the second state. The style takes a parameter which is the symbol read by the automaton.
Here are some possible definitions of these keys that do not (yet) generate rdf information:
The library could be used as follows:
68.5.2 Adding Semantic Information About the Automata as a Whole¶
Let us change the different keys so that they add rdf information to the output. For this, we first need an ontology that defines notions like “state” or “deterministic finite automaton”. For the purposes of this example, we just assume that such an ontology exists at http://www.tcs.uni-luebeck.de/ontologies/automata/. The new definition of the dfa key might start as follows (we will extend these later on):
The definition of the style nfa would be exactly the same as for dfa, except, of course, that the last statement would have "no" as object. Note that the original styles dfa and nfa has identical definitions since, indeed, there is no “visual” difference between the two. In contrast, the rdf information stores this information in the output.
68.5.3 Adding Semantic Information About the States¶
We next augment the styles for creating states and marking them as final or initial. We could do the following (note that we do not setup the prefix since this has been done by the surrounding dfa or nfa key):
The first statement tells us that the circle with its contents is a state (and not just “any” fancy circle). The second statement tells us that the “value” of this state is the content. One might argue that, instead, only the number itself (like “\(q_0\)” or perhaps only “\(0\)”) should be the “value” or, perhaps, a different property should actually be used (like automata:stateNumber or something like that). However, these are questions of ontological modeling, not of the use of the rdf engine.
What is definitely missing from the above definition is a link between the automaton resource and the state resource. Note that the state’s rendering code will be inside the scope of the automaton, so, in a sense, the state is “inside” the automaton in the output. However, the nesting of scopes is not part of the rdf graph; we must make these relationships explicit using statements. One way to achieve this would be to add the following to the state style:
Note that we can access the macro \mylibAutomatonCurie here since this will have been setup by the surrounding dfa or nfa key. While the above is possible and legitimate, we will see a better solution using containers in a moment (“better” in the sense that the ontological model is easier to process by software).
The two styles final and initial are easy to augment:
Note that when we write node [state, final] ... the state now has two types: It has type automata:types/state and also automata:properties/final. This is perfectly legitimate. Also note that I added get scope curie to the above definition, which may seem superfluous since the state style already executes this key to get a curie for the state resource. However, users should be free to write node [final, state] ... and, now, the final key will be executed first.
The style for initial is the same as for final only with a different type.
68.5.4 Adding Semantic Information About the Transitions¶
A transition is, essentially, a labeled edge from a state to another state. It may seem tempting to model them as a statement with the first state as its subject and the second state as the object and the transition’s symbol as the label (turned into a curie in some appropriate way). However, closer inspection shows that this is not a good way of modeling transitions: In essence, it is just coincidence that the rdf graph happens to be a directed graph and, at the same time, the thing we describe by it (the automaton) can also be viewed as a directed graph. If, for instance, we consider alternating automata where a transition can involve more than two states, the simple model breaks down.
The “right” way of modeling a transition is to treat the transition as a resource of its own and then make statements like “the transition has this state as its old state”. This turns out to be relatively easy to achieve:
68.5.5 Using Containers¶
As a last step we wish to organize the states and transitions using containers. As explained earlier, we can easily add statements linking our automaton to the states and to the transitions, but the rdf standard has standard way of specifying that a set of resources form a logical sequence: containers.
In case automata contained only states, we could setup the automaton itself to be the container and the states to be its elements. However, the automaton has states and transitions and in this example I would like to keep these in separate containers. Thus, we must create two containers and then make statements that the automaton contains these two containers. Since these containers do not have any accompanying visual representation, we use the get new resource curie key to create new resources that are purely for descriptive purposes inside the rdf graph:
We can now modify the state style as follows:
The modification for the transition style is similar:
68.5.6 The Resulting RDF Graph¶
Putting it all together, we now get the following library code:
Using this code is still “as easy as before”, indeed, the code for creating the automaton is perfectly unchanged:
Let us now have a look at the result. If the above is processed using TeX and transformed to svg code, the following results (reformatted and slightly simplified):
<g id="pgf3" prefix=" automata: http://www.tcs.uni-luebeck.de/ontologies/automata/ "> <!-- The automaton --> <g about="#pgf3" property="rdf:type" resource="automata:types/automaton" /> <g about="#pgf3" property="automata:properties/deterministic" content="yes" /> <g about="#pgf4" property="rdf:type" resource="rdf:Seq" /> <g about="#pgf3" property="automata:relations/hasAsStateContainer" resource="#pgf4" /> <g about="#pgf5" property="rdf:type" resource="rdf:Seq" /> <g about="#pgf3" property="automata:relations/hasAsTransitionContainer" resource="#pgf5" /> <g id="pgf6" about="#pgf6" property="rdf:value"> <!-- State $q_0$ --> <g about="#pgf6" property="rdf:type" resource="automata:types/state" /> <g about="#pgf4" property="rdf:_1" resource="#pgf6" /> <g about="#pgf6" property="rdf:type" resource="automata:properties/initial" /> <g stroke="#f00"> <!-- Red Line --> <path id="pgf6bp" d="M 14.22636 0.0 C 14.22636 7.8571 7.8571 14.22636 0.0 14.22636 ..." /> ... </g> </g> <g id="pgf7" about="#pgf7" property="rdf:value"> <!-- State $q_1$ --> <g about="#pgf7" property="rdf:type" resource="automata:types/state" /> <g about="#pgf4" property="rdf:_2" resource="#pgf7" /> <path id="pgf7bp" d="M 56.90549 0.0 C 56.90549 7.8571 50.53622 14.22636 42.67912 14.22636 ..." /> ... </g> <g id="pgf8" > <!-- Transition from $q_0$ to $q_1$ --> <g about="#pgf8" property="rdf:type" resource="automata:types/transition" /> <g about="#pgf8" property="automata:properties/symbolReadFromTape" content="a" /> <g about="#pgf8" property="automata:relations/oldState" resource="#pgf6" /> <g about="#pgf8" property="automata:relations/newState" resource="#pgf7" /> <g about="#pgf5" property="rdf:_1" resource="#pgf8" /> <path id="pgf8p" d="M 14.52637 0.0 L 26.49275 0.0"/> ... </g> <g id="pgf11" > <!-- Transition loop at $q_1$ --> <g about="#pgf11" property="rdf:type" resource="automata:types/transition" /> <g about="#pgf11" property="automata:properties/symbolReadFromTape" content="b" /> <g about="#pgf11" property="automata:relations/oldState" resource="#pgf7" /> <g about="#pgf11" property="automata:relations/newState" resource="#pgf7" /> <g about="#pgf5" property="rdf:_2" resource="#pgf11" /> <path id="pgf11p" d="M 38.91211 14.05888 C 33.07051 35.8591 51.00113 36.72765 47.05392 16.66444"/> ... </g> <g id="pgf12" about="#pgf12" property="rdf:value"> <!-- State $q_2$ --> <g about="#pgf12" property="rdf:type" resource="automata:types/state" /> <g about="#pgf4" property="rdf:_3" resource="#pgf12" /> <g about="#pgf12" property="rdf:type" resource="automata:properties/final" /> <g stroke-width="1.80002"> <!-- Double Line --> <path id="pgf12bp" d="M 99.58461 0.0 C 99.58461 7.8571 93.21535 14.22636 85.35825 14.22636 ..." /> ... </g> </g> <g id="pgf13" > <!-- Transition from $q_1$ to $q_2$ --> <g about="#pgf13" property="rdf:type" resource="automata:types/transition" /> <g about="#pgf13" property="automata:properties/symbolReadFromTape" content="a" /> <g about="#pgf13" property="automata:relations/oldState" resource="#pgf7" /> <g about="#pgf13" property="automata:relations/newState" resource="#pgf12" /> <g about="#pgf5" property="rdf:_3" resource="#pgf13" /> <path id="pgf13p" d="M 57.20549 0.0 L 69.17188 0.0"/> ... </g> </g>
When this code is processed by some rdfa tool, the following graph will result where the blue nodes represent resources: