Marko A. Rodriguez created TINKERPOP3-881:
---------------------------------------------

             Summary: [Proposal] A Process-Based Graph Reasoner
                 Key: TINKERPOP3-881
                 URL: https://issues.apache.org/jira/browse/TINKERPOP3-881
             Project: TinkerPop 3
          Issue Type: New Feature
          Components: process
            Reporter: Marko A. Rodriguez
            Assignee: Marko A. Rodriguez


This would be a big initiative, so its more than "just a ticket," but it would 
be a neat idea.

A reasoner allows someone to express implicit edges/properties in the graph. 
For instance, it is possible to say that {{ancestor}} is transitive. If there 
was an explicit graph structure like:

{code}
marko--ancestor-->jose--ancestor-->fernando--ancestor-->someSpanishDude
{code}

Then when you did the following query:

{code}
gremlin> g.V.has('name','marko').out('ancestor').name
==>jose
==>fernando
==>someSpanishDude
{code}

That is, because it is declared the {{ancestor}} is transitive, the implicit 
{{marko--ancestor-->someSpanishDude}} is generated. Now, there are two types of 
reasoners: structure and process.

A *structure reasoner* will infer all the entailments of the schema when the 
graph is modified (added to or deleted from). Thus, what is implicit is made 
explicit and put into the graph. With this model, your data set has more data 
than what was explicitly put into it.

A *process reasoner* will infer all the entailments of the schema as it 
pertains to the current query being executed. Thus, what is implicit is made 
explicit at query runtime. With this model, you data set contains only what was 
explicitly inserted.

These two models either make a sacrifice of space or time.

If we wanted just a *process reasoner*, then this could be a 
{{ReasoningStrategy extends DecorationStrategy}}. Where the above {{ancestor}} 
query would be rewritten as:

{code}
g.V.has('name','marko').repeat(out('ancestor')).name
{code}

In essence, "transitive" means {{repeat(...).until(false)}} (loop until you can 
loop no more).

I prefer the *process reasoner* model as its less cumbersome and potentially 
damaging to the integrity of the underlying data set. Moreover, it can be 
"easily" implemented as a {{TraversalStrategy}}. 

The next question is, how is the reasoning schema (ontology) specified? Perhaps 
via a builder?

{code}
ReasoningStrategy.build().
  .transitive("ancestor")
  .subEdge("hasPet","likes") // if I have a pet dog, I like dogs.
  .symmetric("friend") // a.friend.b implies b.friend.c
  .functional("marriedTo") // a.marriedTo.b, c.marriedTo.b ==> a=b
  ...other stuff
  .create();
{code}

Here are some links to study:

* https://jena.apache.org/documentation/inference/#the-owl-reasoner
* http://owl.man.ac.uk/2003/why/latest/

In my experience, you can do a lot with support for the basics: transitive, 
symmetric, etc.




--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to