On 6/26/06, Marco De Vitis <[EMAIL PROTECTED]> wrote:
> Hi, sorry if my question is slightly off-topic here, but I'm starting
> now a journey into OWL/RDF using RDFLib (as my final purpose is the use
> of OWL in Plone/Zope, hence my choice of Python), and I feel I still
> have to understand some basic stuff.
>
> Let's say I have a RDF file defining class A, and class B as a subclass
> of A. It then introduces an individual X as belonging to class B.
>
> After loading the graph object into memory using rdflib, somehow I can
> infer that X belongs to class A (because it belongs to class B which is
> a subclass of A).
> I could do this "by hand", by expressly searching through the triples
> stored in my rdflib graph to check if class B is defined as a subclass
> of some other class (I do not know this beforehand, if I'm not the one
> who wrote the RDF file). But is it the right way to do it?

Definately not

> Or is it what
> reasoners are made for?

This is exactly what reasoners are made for..

> And, in this case, is there a reasoner I could
> easily use from Python? Or... does the rdflib API already contain what I
> need, by chance?

Long answer to your short question:

Currently, your options may not be very appealing (depending on
whether or not you find heavy software dependencies annoying - I
certainly do):

[1] Use RDFLib with Pychinko (directly)
[2] Use RDFLib with FuXi / Pychinko
[3] Use RDFLib with RDFSClosure


[1] You can try using Pychinko with RDFLib directly to apply the
following rule on your original graph, and add the results to your
graph:

{?A rdfs:subClassOf ?B. ?S a ?A} => {?S a ?B}.

Below is a code snippet (from FuXi on how this can be done):

from pychinko.interpreter import Interpreter
from pychinko.terms import Fact, URI,Pattern,Rule, Exivar
from pychinko import terms

def _convert(node):
    if isinstance(node, Variable):
        return terms.Variable(node)
        #return node
    elif isinstance(node, BNode):
        return terms.Exivar(node)
    elif isinstance(node, URIRef):
        #return terms.URI(node)
        return node
    elif isinstance(node, Literal):
        return node
    else:
        raise Exception("Unexpected Type: %s" % type(node))


rules=[]
#Where ruleGraphs is a list of Graphs with the N3 rules
for ruleGraph in ruleGraphs:
    for s, p, o in ruleGraph.triples((None, LOG.implies, None)):
        if isinstance(s,QuotedGraph):
            lhs = [Pattern(_convert(rs), _convert(rp), _convert(ro))
for rs,rp,ro in s]
        else:
            lhs=[]
        if isinstance(o,QuotedGraph):
            rhs = [Pattern(_convert(rs), _convert(rp), _convert(ro))
for rs,rp,ro in o]
        else:
            rhs=[]
        rules.append(Rule(lhs, rhs, (s, p, o)))

.. snip ..

interp = Interpreter(rules)
facts=[]
#factGraphs is a list of Graphs with the initial facts
for factGraph in factGraphs:
    try:
        for rt in factGraph:
            if isinstance(factGraph,ConjunctiveGraph):
                s,p,o = rt[0]
                facts.append(Fact(s, p,o))

            else:
                #print factGraph, type(factGraph), rt
                s,p,o = rt
                facts.append(Fact(s, p,o))
    except:
        import traceback;traceback.print_stack()
        print "Unable to extract all facts from ", factGraph

interp.addFacts(Set(facts),initialSet=True)
interp.run()
result = [tuple(fact.spo) for fact in interp.inferredFacts]

result is the list of the inferred triples, which you can do whatever
you want with: either persist them in the original graph(s) or keep
them in a seperate graph and use ReadOnlyGraphAggregate (newly added)
to treat the original graphs plus a graph of the inferred statements
as a single graph to iterate over or query:

from rdflib.Graph import ReadOnlyGraphAggregate
inferredGraph = Graph()
for triple in result:
    inferredGraph.add(triple)
finalGraph = ReadOnlyGraphAggregate(factGraphs + [inferredGraph])
#final graph is a 'virtual' graph which with the original facts plus
the inferred statements.

Unfortunately PyChinko (perhaps this has changed, I don't think it
has) relies on CWM and the W3C SWAP code base which introduce *major*
installation / maintainence annoyances.  In addition the PyChinko code
base seems (currently) unmanaged - there are a few issues I've
directed to the developers which haven't made it back into it's code
base.

[2] FuXi (in it's current state) will handle all this for you and
allows you to pass it an original fact graph with a statement
associating it with the name of a rule graph to use to infer
additional statements (using the propery fuxi:ruleBase).  Then you can
dispatch Versa queries on the original graph transparently (it
automatically handles all of the mechanics above).  FuXi suffers the
same software dependency issues that PyChinko does (since it relies on
PyChinko) and introduces it's own

[3] RDFLIbClosure is a stand-alone solution and is probably your best
bet, the only thing is that it only does RDFS reasoning (which is fine
for your immediate needs but may not be for additional inference you
may wish to do).

Alternatively you can stay tuned.. :)  I'm currently working on a
stand-alone RETE implementation (from scratch) for FuXi as a
replacement for PyChinko with some additional expert-system
services/features .  I'm mostly there..

The links to the RDFLib reasoners mentioned above are:

[1] http://www.mindswap.org/~katz/pychinko/
[2] http://metacognition.info/FuXi/
[3] http://dev.w3.org/cvsweb/~checkout~/2004/PythonLib-IH/RDFSClosure.py

> Does SPARQL have anything to do with that? (I guess
> not, judging on what I read...)

Nope, SPARQL is a pure querying language which (currently) doesn't
include inference in it's scope
_______________________________________________
Dev mailing list
[email protected]
http://rdflib.net/mailman/listinfo/dev

Reply via email to