I am currently developing an ontology using protege and would like to determine if a node is a last one of a list. So basically a list points to a node and every node has some content and can have another node:
List startsWith some Node
Node hasContent some Content
Node hasNext some Node
Now I'd like to define a subclass named EndNode
that doesn't point to another Node
. This is what I've tried so far, but the after classifying, EndNode
always equals Nothing
:
Node and not(hasNext some Node)
Node and (hasNext exactly 0 Node)
First, there is a built-in List construct in RDF which you can use in the following way:
ex:mylist rdf:type rdf:List .
ex:myList rdf:first ex:firstElement .
ex:myList rdf:rest _:sublist1 .
_:sublist1 rdf:first ex:SecondElement .
_:sublist1 rdf:rest rdf:nil .
Here, in order to know you reach the end of the list, you need a special list called rdf:nil
. This plays the same role as a null
pointer at the end of a linked list in programming languages.
However, even though rdf:List
is well used in existing data on the Web, it doesn't constrain in any way the use of the predicates rdf:first
and rdf:rest
, so you can have many first elements for a given list without triggering an inconsistency.
So, if you really want to model linked list in a strict way, you need pretty expressive features of OWL. I did it a while ago and it can be found at http://purl.org/az/List.
It's normal that you have an empty class as you specified that a Node
must have a nextNode
. You should not impose that Nodes have content or next element. You should rather say that the cardinality is maximum 1, that the domain and range of hasNext
is Node, and that EndNode
is a node with no next node. But it's still not enough, as it does not impose that there is an EndNode
at all. You may have an infinite sequence or a loop.
If you want to avoid loops or infinite sequence, you have to define the transitive property hasFollower
and say that there is at least a follower in the class EndNode
.
All in all, implementing strict lists in OWL completely sucks in term of performance and is most of the time totally useless as rdf:List
is sufficient for the wide majority of the situations.