Introduction
Before we begin the tutorial there are few things to keep in mind.
- The reasoner supports a subset of the full RDFS and OWL constructs (see below).
- The tutorial examples below are in Lisp. The AllegroGraph Learning Center is the best place to find Java examples of using the reasoner and much, much more.
- This tutorial is written for people who know how to get around in the IDE or in Emacs. You can load this file in a buffer and start executing its forms from top to bottom.
- The Lisp program 'reasoner-tutorial.lisp' contains all of the illustrative examples below. You may want to open this in your development environment and follow along by evaluating its forms as you go. The program is in the 'tutorial-files' sub-directory of the AllegroGraph installation directory.
Reasoning Supported.
We support all the RDFS and OWL reasoning that you can do with the predicates below.
- rdf:type
- rdfs:domain
- rdfs:range
- rdfs:subClassOf
- rdfs:subPropertyOf
- owl:inverseOf
- owl:sameAs
- owl:TransitiveProperty
Before you look up the semantics of these predicates in the W3C documentation you may want to first examine the examples in the tutorial below. Note that for efficiency's sake, our RDFS++ reasoner will not make every possible inference given a triple-store's ground triples. In particular, some non-rdf:type and rdfs:subClassOf reasoning involving chains of transitive predicates will not be followed unless the predicate is supplied as part of the query. We are constantly improving our inference algorithms and will continue to extend the reasoner's reach. If there are particular inferences that are important to you and AllegroGraph is not making them, please let us know so that we can work together to reach a solution.
Functions discussed in this tutorial.
This tutorial discusses: make-tutorial-store, prepare-reasoning and get-triples-list. The first is just a convenience function to create a fresh triple-store in a temporary directory. The only thing to be careful of is that the directory is chosen by the built-in Allegro Common Lisp function sys:temporary-directory. It is possible for this to return a directory into which you do not have write access. In this case, make-tutorial-store will generate an error. The solution is to either alter the value of the ag-property :temporary-directory or to supply your own directory as the optional argument of make-tutorial-store.
Close any current triple-store and create a new empty one in a temporary directory.
The directory used can be passed in as an optional parameter. If it is not supplied, then it will get its value from (ag-property temporary-directory).
The new triple-store will be bound to *db* and is also returned by make-tutorial-store.
Prepare-reasoning is a function called internally by the AllegroGraph reasoner. It is unlikely that you will need to call it yourself. Its function is to update the internal data structures used by the reasoner.
This function has to be called before any inferences are made. It creates internal hashtables to speed up the reasoner. In normal operation, AllegroGraph will call prepare-reasoning as necessary. You can see diagnostic messages by using the parameter verbose which defaults to the value of (ag-property :verbose-prepare-reasoning). You can also force the hashtables to be regenerated using the force parameter. Finally, the show-progress keyword argument can be used to cause prepare-reasoning to print a message for each of the hashtables it builds.
The function prepare-reasoning returns no value.
Finally, the reasoner works with get-triples-list and get-triples. You can turn the reasoner on either by using the keyword argument :use-reasoner when you call one of these functions or by setting the value of the special variable *use-reasoner*. When the reasoner is turned on, then get-triples-list will return all of the inferred triples (depending on the setting of :limit.)
Query a triple store for triples matching the given subject, predicate, object, and graph, specified either as part IDs (UPIs), future-parts, strings in N-Triples format, or the wildcard nil. Returns a list of matching triples. The get-triples-list function supports a multitude of options:
db- This keyword argument specifies the triple store to query, defaulting to the value of *db*.s,p,o,g- controls the actual query pattern. Usenilas a wildcard.s-end,p-end,o-end,g-end- Allows for range queries over encoded triples (triples whose parts are encoded UPIs). Each?-endparameter may only be used in conjunction with its corresponding starting value parameter.cursor- if cursor is supplied then AllegroGraph will use it to return more triples rather than building a new cursor.if-fewer- controls the behavior ofget-triples-listwhen fewer thanlimittriples match the query. Possible values are (defaults tonil):nil- return list of actual results:error- signal error if fewer results than limit
other -- return other instead of short list
if-more- controls what happens when more results thanlimitare available. Possible values are (defaults to:cursor):nil- return list of limit results:error- signal error if more results than limit:cursor- return the list of limit results and a second value of a cursor that will yield the remaining resultsother - return other instead of truncated list
limit- This keyword argument can be used to place a cap on the maximum number of triples returned. It defaults to the value of the special variable get-triples-list-limit. If set, then get-triples-list will return no more than:limittriples. If it is nil, then get-triples-list will return all of the triples found by the query. Warning: settinglimitto nil can causeget-triples-listto return every triple in the triple-store; this can be a very bad thing over a serial connection.return-encoded-triples- If true, then get-triples-list returns triples with encoded parts; i.e., triples that use directly encoded UPIs rather than strings stored in the dictionary. The is set to true unless overridden.return-non-encoded-triples- if true, thenget-triples-listwill return triples all of whose UPIs are stored as strings. This is set to true unless overridden.use-reasoner- if true, then the RDFS++ reasoner will be used to return inferred triples. If left unspecified, this will take on the value of*use-reasoner*. Note that most of the arguments toget-triples-listdo not make sense when reasoning is turned on. AllegroGraph will signal an error if you try to combine reasoning with other parameters that it cannot use.
It's helpful to be able to quickly print out the results of a query. For this purpose, we define a new function ptl.
(defun ptl (s p o)
(let ((*use-reasoner* t))
(dolist (e (get-triples-list :s s :p p :o o))
(print-triple e :format :concise))))
This is an abbreviation for print-triples-list. It passes the s-p-o pattern to get-triples-list and then prints out all inferred triples in an easy to read form.
example: (ptl !ex:Jans !ex:has nil)
Finally, the reasoner introduces a new Prolog functor
(qs ?s ?p ?o)
that is used like q in prolog clauses. The difference is that q only works with the actual triples in the triple-store whereas qs will turn the reasoner on.
Example: using q ...
(select (?x)
(q ?x !cyc:isa !cyc:Terrorist))
This will find all the triples that literally have the predicate !cyc:isa and the object !cyc:Terrorist.
This next query does the same thing but uses the reasoner and might return more triples.
(select (?x)
(qs ?x !cyc:isa !cyc:Terrorist))
On your marks, get set ...
The examples below assume that the following code has been evaluated in your Lisp session. So please make sure you do so in your session before continuing.
(require :agraph)
(in-package :triple-store-user)
;; short for print-triples-list
(defun ptl (s p o)
(let ((*use-reasoner* t))
(dolist (e (get-triples-list :s s :p p :o o))
(print-triple e :format :concise))))
(register-namespace
"rdf" "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
(register-namespace
"owl" "http://www.w3.org/2002/07/owl#")
(register-namespace
"rdfs" "http://www.w3.org/2000/01/rdf-schema#")
(register-namespace
"ex" "http://www.franz.com/example#" :errorp nil)
Reasoner Examples
Inverse of
(make-tutorial-store)
(add-triple !ex:jans !ex:owns !ex:birra)
(add-triple !ex:owned-by !owl:inverseOf !ex:owns)
(add-triple !ex:has !owl:inverseOf !ex:owned-by)
(ptl !ex:birra !ex:owned-by nil)
(ptl nil !ex:owned-by nil)
(ptl nil !ex:owned-by !ex:jans)
(ptl !ex:jans !ex:has nil)
(ptl nil !ex:has nil)
(ptl nil !ex:has !ex:birra)
(ptl nil nil nil)
; this will return nothing
; because it works on only the triples explicity
; added to the triple-store
(select (?x)
(q !ex:birra !ex:owned-by ?x))
; this will return something
; because it works on inferred triples
(select (?x)
(qs !ex:birra !ex:owned-by ?x))
Sub-property of
(make-tutorial-store)
(add-triple !ex:jans !ex:has-pet !ex:birra)
(add-triple !ex:has-pet !rdfs:subPropertyOf !ex:owns)
(add-triple !ex:birra !ex:friend-of !ex:samira)
(ptl !ex:jans !ex:owns !ex:birra)
(ptl !ex:jans !ex:owns nil)
(ptl nil !ex:owns !ex:birra)
(ptl !ex:jans !ex:has-pet !ex:birra)
(ptl !ex:jans !ex:has-pet nil)
(ptl nil !ex:has-pet !ex:birra)
(select (?x ?y)
(qs !ex:jans !ex:owns ?x)
(qs ?x !ex:friend-of ?y))
inverse and sub properties
(make-tutorial-store)
(add-triple !ex:jans !ex:has-pet !ex:birra)
(add-triple !ex:owned-by !owl:inverseOf !ex:owns)
(add-triple !ex:has !owl:inverseOf !ex:owned-by)
(add-triple !ex:has-pet !rdfs:subPropertyOf !ex:owns)
(add-triple !ex:pet-of !owl:inverseOf !ex:has-pet)
;; direct triples
(ptl !ex:jans !ex:has-pet !ex:birra)
(ptl nil !ex:has-pet !ex:birra)
(ptl !ex:jans !ex:has-pet nil)
;; inverse of !ex:has-pet
(ptl !ex:birra !ex:pet-of !ex:jans)
(ptl nil !ex:pet-of !ex:jans)
(ptl !ex:birra !ex:pet-of nil)
;; subproperty
(ptl !ex:jans !ex:owns !ex:birra)
(ptl !ex:jans !ex:owns nil)
(ptl nil !ex:owns !ex:birra)
;; inverse of subproperty
(ptl !ex:birra !ex:owned-by !ex:jans)
(ptl nil !ex:owned-by !ex:jans)
(ptl !ex:birra !ex:owned-by nil)
;; inverse of inverse
(ptl !ex:jans !ex:has !ex:birra)
(ptl nil !ex:has !ex:birra)
(ptl !ex:jans !ex:has nil)
Same-as
(make-tutorial-store)
(add-triple !ex:jans !ex:owns !ex:birra)
(add-triple !ex:jans !owl:sameAs !ex:jannes)
(add-triple !ex:aasman !owl:sameAs !ex:jannes)
(add-triple !ex:birra !owl:sameAs !ex:son-of-samira)
(ptl !ex:aasman !ex:owns !ex:son-of-samira)
(ptl !ex:aasman !ex:owns nil)
(ptl nil !ex:owns !ex:son-of-samira)
(ptl nil !ex:owns nil)
Same-as, inverse, and sub-properties
(make-tutorial-store)
(add-triple !ex:jans !ex:has-pet !ex:birra)
(add-triple !ex:owned-by !owl:inverseOf !ex:owns)
(add-triple !ex:has !owl:inverseOf !ex:owned-by)
(add-triple !ex:has-pet !rdfs:subPropertyOf !ex:owns)
(add-triple !ex:pet-of !owl:inverseOf !ex:has-pet)
(add-triple !ex:birra !ex:age !ex:twelve)
(add-triple !ex:jans !owl:sameAs !ex:jannes)
(add-triple !ex:aasman !owl:sameAs !ex:jannes)
(add-triple !ex:birra !owl:sameAs !ex:son-of-samira)
;; direct triples
(ptl !ex:aasman !ex:has-pet !ex:son-of-samira)
(ptl nil !ex:has-pet !ex:son-of-samira)
(ptl !ex:aasman !ex:has-pet nil)
;; inverse of !ex:owns
(ptl !ex:son-of-samira !ex:pet-of !ex:aasman)
(ptl nil !ex:pet-of !ex:aasman)
(ptl !ex:son-of-samira !ex:pet-of nil)
;; inverse of inverse
(ptl !ex:aasman !ex:has !ex:son-of-samira)
(ptl nil !ex:has !ex:son-of-samira)
(ptl !ex:aasman !ex:has nil)
;; subproperty
(ptl !ex:aasman !ex:owns !ex:son-of-samira)
(ptl !ex:aasman !ex:owns nil)
(ptl nil !ex:owns !ex:son-of-samira)
;; inverse of subproperty
(ptl !ex:son-of-samira !ex:owned-by !ex:aasman)
(ptl nil !ex:owned-by !ex:aasman)
(ptl !ex:son-of-samira !ex:owned-by nil)
;; what to do with this?
(ptl nil nil nil)
;; but what if predicate is unknown?
(ptl !ex:jans nil !ex:birra) ;; this returns only one valid result
;; what should i do here, find all the
;; predicates defined for !ex:aasman (and the sames)
;; and then try them all?
(ptl !ex:aasman nil !ex:birra)
(ptl !ex:aasman nil nil)
type with sub-class
(make-tutorial-store)
(add-triple !ex:mammal !rdfs:subClassOf !ex:animal)
(add-triple !ex:human !rdfs:subClassOf !ex:mammal)
(add-triple !ex:man !rdfs:subClassOf !ex:human)
(add-triple !ex:jans !rdf:type !ex:man)
(add-triple !ex:jans !owl:sameAs !ex:jannes)
(add-triple !ex:aasman !owl:sameAs !ex:jannes)
(ptl !ex:jans !rdf:type !ex:man)
(ptl !ex:jans !rdf:type !ex:human)
(ptl !ex:jans !rdf:type nil)
(ptl !ex:aasman !rdf:type !ex:man)
(ptl !ex:aasman !rdf:type !ex:human)
(ptl !ex:aasman !rdf:type nil)
(ptl nil !rdf:type !ex:man)
(ptl nil !rdf:type !ex:human)
(ptl nil !rdf:type nil)
type with range
(make-tutorial-store)
(add-triple !ex:jans !ex:has-pet !ex:birra)
(add-triple !ex:has-pet !rdfs:range !ex:pet)
(add-triple !ex:pet !rdfs:subClassOf !ex:mammal)
(add-triple !ex:fatcat !owl:sameAs !ex:birra)
(ptl !ex:birra !rdf:type !ex:pet)
(ptl !ex:birra !rdf:type nil)
(ptl nil !rdf:type !ex:pet)
(ptl !ex:birra !rdf:type !ex:mammal)
(ptl !ex:fatcat !rdf:type !ex:mammal)
type with domain
(make-tutorial-store)
(add-triple !ex:jans !ex:has-pet !ex:birra)
(add-triple !ex:has-pet !rdfs:domain !ex:human)
(add-triple !ex:human !rdfs:subClassOf !ex:mammal)
(add-triple !ex:jans !owl:sameAs !ex:aasman)
(ptl !ex:jans !rdf:type !ex:human)
(ptl !ex:jans !rdf:type nil)
(ptl nil !rdf:type !ex:human)
;; not returning all solutions..
(ptl nil !rdf:type nil)
Transitivity with Same As
(make-tutorial-store)
(add-triple !ex:contains !rdf:type !owl:TransitiveProperty)
(add-triple !ex:usa !ex:contains !ex:california)
(add-triple !ex:golden-state !ex:contains !ex:contra-costa)
(add-triple !ex:contra-costa !ex:contains !ex:moraga)
(add-triple !ex:usa !owl:sameAs !ex:uncle-sam)
(add-triple !ex:moraga !owl:sameAs !ex:mytown)
(add-triple !ex:california !owl:sameAs !ex:golden-state)
(ptl !ex:usa !ex:contains !ex:moraga)
(ptl !ex:uncle-sam !ex:contains !ex:mytown)
(ptl !ex:uncle-sam !ex:contains !ex:mytown)
(ptl !ex:golden-state !ex:contains !ex:moraga)
(ptl !ex:california !ex:contains !ex:moraga)
(ptl !ex:california !ex:contains !ex:mytown)
(ptl !ex:usa !ex:contains nil)
(ptl !ex:uncle-sam !ex:contains nil)
(ptl nil !ex:contains !ex:moraga)
(ptl nil !ex:contains !ex:mytown)