Table of Contents

Introduction

Reasoning Supported.

Changes between AllegroGraph 2.x and 3.0

Functions discussed in this tutorial.

Getting Ready

Reasoner Examples

Inverse of

Sub-property of

inverse and sub properties

Same-as

Same-as, inverse, and sub-properties

type with sub-class

type with range

type with domain

Transitivity with Same As

Introduction

Before we begin the tutorial there are few things to keep in mind.

Reasoning Supported.

We support all the RDFS and OWL reasoning that you can do with the predicates below.

We also support owl:hasValue reasoning. Its use is covered in a separate tutorial.

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. 1 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.

Changes between AllegroGraph 2.x and 3.0

In AllegroGraph 2.x, reasoning was applied at the individual query level. Every triple-store supported a single kind of reasoning (RDFS++) which could be turned on for some queries and turned off for others. AllegroGraph 3.0's new architecture provides much greater flexibility in composing multiple triple-stores and reasoning engines in whatever shape is needed for a particular application. Given this flexibility, the simple "this query has reasoning and this one does not" no longer makes sense. Instead, you should create the triple-stores that you need to perform each different kind of query (use federate-triple-stores, encapsulate-triple-store, and db-apply-reasoner to build each store) and run your queries against them. For example, suppose we create a triple-store and add two triples (if you not familiar with the !-notation, see the section of the reference-guide on future-parts):

> (setf ground-ts (create-triple-store "sample"))  
#<triple-db /home/gwking/sample, open @  
  #x13d41812>  
 
> (register-namespace "ex" "http://www.franz.com/simple#")  
  "http://www.franz.com/simple#"     
 
> (add-triple !ex:jans !ex:owns !ex:birra)  
1  
 
> (add-triple !ex:jans !owl:sameAs !ex:jannes)  
2 

We'll make sure that the triples are in there and use enable-print-decoded so that the rest of the example is easier to read:

> (print-triples *db*  :format :concise)  
<1: ex:jans ex:owns ex:birrabirra>  
<2: ex:jans owl:sameAs ex:jannesjannes>  
; No value  
 
> (enable-print-decoded t)  
t 

If we ask for all of the triples whose predicate is !ex:owns, we get back the single ground triple.

> (get-triples-list :p !ex:owns)  
(<jans owns birra>)  
nil 

If we want to use AllegroGraph's RDFS++ reasoner, we call apply-rdfs++-reasoner. If called with no additional parameters, this will encapsulate the current triple-store (i.e., *db*) with a reasoning-triple-store whose reasoner is of type rdfs++-reasoner. It will also bind *db* to this new store. The return value of the call makes it clear what has happened.

> (setf inferred-ts (apply-rdfs++-reasoner))  
#<reasoning-triple-store  
  sample, inner #<triple-db /home/gwking/sample, open @ #x13d41812>  
  @ #x140a26f2> 

Now if we make the same call to get-triples-list, we get two results back. One ground triple and one that has been inferred.

> (get-triples-list :p !ex:owns)  
(<jans owns birra> <jannes owns birra>) 

Note that we can specify which triple-store to query using the :db argument. If we ask for the triples from ground-ts, that is what we will get. We could also have accomplished the same thing by using the reasoning-triple-store's inner-triple-store:

> (get-triples-list :p !ex:owns :db ground-ts)  
(<jans owns birra>)  
 
> (get-triples-list :p !ex:owns :db (inner-triple-store *db*))  
(<jans owns birra>)  

Functions discussed in this tutorial.

This tutorial discusses: make-tutorial-store, apply-rdfs++-reasoner, inner-triple-store and get-triples-list. The first is just a convenience function to create a fresh triple-store in a temporary directory. 2

make-tutorial-store &key temporary-directory apply-reasoner-p use-reasoner
function

Close any current triple-store and create a new empty one in a temporary directory. Make-tutorial-store takes two keyword parameters:

  • :temporary-directory - the directory where the store will be created. If it is not supplied, then it will get its value from (ag-property temporary-directory).

  • :use-reasoner - If true (the default), then the new triple-store will use RDFS++ reasoning. If nil, then the triple-store will have no reasoning.

The new triple-store will be bound to *db* and is also returned by make-tutorial-store.

As discussed above, apply-rdfs++-reasoner wraps a triple-store in a reasoning-triple-store and uses the rdfs++-reasoner as the reasoning class.

apply-rdfs++-reasoner &key db name
function

Return a new reasoning-triple-store that encapsulates db and adds an rdfs++-reasoner.

  • db - the triple-store to encapsulate. The defaults to the value of *db*.
  • name - the name to give the encapsulated-triple-store. Defaults to the current db-name of the db with rdfs++- prepended.

You can query a reasoning-triple-store almost anywhere that you can use a regular triple-store. SPARQL, our family of Prolog select functors, get-triples and get-triples-list all know how to work with a reasoning-triple-store.

It's helpful to be able to quickly print out the results of a query. For this purpose, we define a new function ptl (for print-triples-list):

(defun ptl (s p o)  
  (print-triples (get-triples :s s :p p :o o) :format :concise)) 

As you can see, it simply passes the s-p-o pattern to get-triples and then uses print-triples to display them in an easy to read form.

example: (ptl !ex:Jans !ex:has nil)

Finally, the reasoner introduces a new Prolog functor

(q ?s ?p ?o) 

that is used like q- in prolog clauses. The difference is that q- will work on the inner-triple-store whereas q will work with the actual *db* (obviously, if *db* is a non-encapsulated-store, then q- and q will be the same.)

Example: Assume that *db* is a reasoning-triple-store, then 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)  
  (q ?x !cyc:isa !cyc:Terrorist)) 

Getting Ready

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)  
  (print-triples (get-triples :s s :p p :o o) :format :concise))  
 
(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 explicitly  
; 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)  
	(q !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)  
	(q !ex:jans !ex:owns ?x)  
	(q ?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: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)  

Footnotes

  1. 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.
  2. 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.