Saturday, July 25, 2009

Customizing the SPARQL DESCRIBE command

The default behavior of the SPARQL DESCRIBE command is to return all statements where the specified URI is the subject value (ex: describe <some uri>). Many applications require a much richer description of a resource that may include information about referenced URIs also. When using Intellidimension Semantics the behavior of the DESCRIBE command can be modified by providing some special inference rules.  The DESCRIBE command gets its behavior from a special inference rules call <description>. This rule (“relation”) takes four arguments as shown below.

The first three arguments are the statements describing the URI in the fourth argument.

select ?s ?p ?o ?r where {?s ?p ?o. filter(?s=?r)} as <description>

So consider the first three arguments outputs and the fourth as an input. This relation provides the default implementation of the DESCRIBE command by returning all statements about a specified URI.

To customize the DESCRIBE command, you must provide one or more rules that implement the <description> relation. For example, if you wanted to create a custom description for a factory entity that included information about chemicals it uses you could implement the following rules and include them in your DESCRIBE query.

rulebase (
select ?s ?p ?o ?r where {
?r x:usesChemical ?s.
?s ?p ?o.} as <description>
)
describe <somefactoryuri> from <data>

By adding this rule you will now get all statements about the factory plus all statements about any chemicals it uses. So you can now create different sets of rules for different entity types each with its own custom description.

Another way to accomplish this goal is to add some additional information to your ontology so that a single set of rules can be used for all entity types. For example if we added the statement {x:FactoryClass x:includedReference x:usesChemical} to the ontology a generic set of description rules could be written as follows.

rulebase (
select ?s ?p ?o ?r where
{?s ?p ?o. filter(?s=?r)} as <description>

# special rule to look for all marked predicates for the
# class of the entity (?r) and recursively describe all
# included references.
select ?s ?p ?o ?r where {
?r rdf:type ?class.
?class x:includedReference ?ref.
?r ?ref ?included.
<description>(?s, ?p, ?o, ?included).
}as <description>
)
describe <somefactoryuri>

Taking this approach we only need a single set of rules for our descriptions.


Thursday, July 16, 2009

An Introduction to Inference Rules

Intellidimension’s SPARQL extensions for inference rules are a powerful tool when developing a semantics based application. In this article I will show you a few simple examples to get you started. Intellidiemsion has added a SPARQL extension called a rulebase for defining inference rules to be used in any SPARQL query. When an SPARQL query is executed all the rules in all the rulebases are evaluated. A rulebase can be loaded into a model and referenced by uri or declared right inline with your SPARQL query. In this article let’s take a looks at an inline rulebase.

prefix rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix rdfs:<http://www.w3.org/2000/01/rdf-schema#>
prefix x:<http://example.org/>

rulebase(
# create some facts
construct {x:D rdfs:subClassOf x:B}
construct {x:C rdfs:subClassOf x:B}
construct {x:B rdfs:subClassOf x:A}

#transitive subclass rule
construct {?class rdfs:subClassOf ?super} where {
?class rdfs:subClassOf ?x.
?x rdfs:subClassOf ?super }

# root class relation
select ?class ?root where {
?class rdfs:subClassOf ?root.
not(?root) {?root rdfs:subClassOf ?super}
} as :rootClass

# aggregation relation
select ?class :count(?sub) as ?count where {
?sub rdfs:subClassOf ?class.
} group by ?class as :numberOfSubClasses

)

select ?super where {x:C rdfs:subClassOf ?super}
#select ?root where {:rootClass(x:C, ?root)}
#select ?count where {:numberOfSubClasses(x:B, ?count)}



The example about creates a rulebase with some facts about subclass relationships and some inference rules to derive some additional information about those class relationships. The rule:

construct {?class rdfs:subClassOf ?super} where {
?class rdfs:subClassOf ?x.
?x rdfs:subClassOf ?super }

Recursively generates all the subclass relationships so when the following query is run:


select ?super where {x:C rdfs:subClassOf ?super}

it results in:

<http://example.org/A> 
<http://example.org/B>

The rulebase also contains a relation rule for finding the root class (the top base class) of any class. Note that this rule actually makes use of our previous rule for recursively traversing the class hierarchy.


select ?class ?root where {
?class rdfs:subClassOf ?root.
not(?root) {?root rdfs:subClassOf ?super}
} as :rootClass

When we execute this rule in a query by replacing the SELECT query in the example with the following:


select ?root where {:rootClass(x:C, ?root)}

We get:


<http://example.org/A>

The last rule in the rulebase provides both an example of the use of a SPARQL function as well as an aggregation. This rule calculates how many subclasses a class has.

select ?class :count(?sub) as ?count where { 
?sub rdfs:subClassOf ?class.
} group by ?class as :numberOfSubClasses

When we execute this rule in a query (replace the SELECT in the example):


select ?count where {:numberOfSubClasses(x:B, ?count)}

We get:


"2"^^<http://www.w3.org/2001/XMLSchema#int>

Hopefully this is enough to get you started with inference rules. I will post some more complicated use of rules in the future.

Monday, July 6, 2009

Client Model Pooling

One simple way to improve performance of your data access services is to create a client model pool. Creating a new instance of a ClientModel for each service request can get expensive especially if the ClientModel makes use of a SemanticServerGraph. By creating a pool of client models that can be reused you benefit from cached statistics and compiled queries.

Client model pooling is implemented is by creating a single instance of a ClientModelPool. The example below creates a pool that holds a maximum of 10 client models that expire after 5 minutes.

ClientModel pool = new ClientModelPool(10, new TimeSpan(0, 5, 0));

// assign it to some global
app.ModelPool = pool;

You will want to keep this pool around in as a static member or in some other global container such as the ASP.NET Application object. Next you must create a method for creating a new instance of a client model that is configured for your application. This can be done in one of two ways:

  1. Derive an application specific class from ClientModelPool and override its Create method.
  2. Implement your own method for creating a client model on some centralized configuration class that already exists in your application.

Option 2 seems to be the most popular choice. So a simple method for getting a client model in your application class might look like.

public ClientModel GetClientModel()
{
//get a pooled model
ClientModel model = ModelPool.Get();

if (model == null)
{
// create a new one and make it pooled
model = new ClientModel();
model.SetPool(ModelPool);

// TODO: configure for your application
}

return model;
}

You should call this method in your application in the context of a using statement. When the client model is disposed then it is returned to the pool.

using (ClientModel cm = app.GetClientModel())
{
//do something
}

You should quickly discover this can have a big effect on performance.