[ 
https://issues.apache.org/jira/browse/RYA-292?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16128088#comment-16128088
 ] 

ASF GitHub Bot commented on RYA-292:
------------------------------------

Github user jessehatfield commented on a diff in the pull request:

    https://github.com/apache/incubator-rya/pull/206#discussion_r133319932
  
    --- Diff: 
sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java 
---
    @@ -416,22 +425,131 @@ private void 
refreshHasValueRestrictions(Map<Resource, URI> restrictions) throws
             }
         }
     
    -    private static Vertex getVertex(Graph graph, Object id) {
    -        Iterator<Vertex> it = graph.vertices(id.toString());
    +    private void refreshIntersectionOf() throws QueryEvaluationException {
    +        final Map<Resource, List<Set<Resource>>> intersectionsProp = new 
HashMap<>();
    +
    +        // First query for all the owl:intersectionOf's.
    +        // If we have the following intersectionOf:
    +        // :A owl:intersectionOf[:B, :C]
    +        // It will be represented by triples following a pattern similar 
to:
    +        // <:A> owl:intersectionOf _:bnode1 .
    +        //  _:bnode1 rdf:first <:B> .
    +        //  _:bnode1 rdf:rest _:bnode2 .
    +        // _:bnode2 rdf:first <:C> .
    +        // _:bnode2 rdf:rest rdf:nil .
    +        ryaDaoQueryWrapper.queryAll(null, OWL.INTERSECTIONOF, null, new 
RyaDaoStatementIterHandler() {
    +            @Override
    +            public void handleStatementIter(final Statement st1) throws 
Exception {
    +                final Resource type = st1.getSubject();
    +                // head will point to a type that is part of the 
intersection.
    +                URI head = (URI) st1.getObject();
    +                if (!intersectionsProp.containsKey(type)) {
    +                    intersectionsProp.put(type, new 
ArrayList<Set<Resource>>());
    +                }
    +                final Set<Resource> intersection = new HashSet<>();
    +                // Go through and find all bnodes that are part of the 
defined
    +                // intersection.
    +                while (!RDF.NIL.equals(head)) {
    +                    // rdf.first will point to a type item that is in the
    +                    // intersection.
    +                    ryaDaoQueryWrapper.queryFirst(head, RDF.FIRST, null, 
new RyaDaoStatementIterHandler() {
    +                        @Override
    +                        public void handleStatementIter(final Statement 
st2) throws Exception{
    +                            // The object found in the query represents a 
type
    +                            // that should be included in the intersection.
    +                            final URI obj2 = (URI) st2.getObject();
    +                            intersection.add(obj2);
    +                        }
    +                    });
    +                    final List<URI> headHolder = new ArrayList<>(1);
    +                    // rdf.rest will point to the next bnode that's part 
of the
    +                    // intersection.
    +                    ryaDaoQueryWrapper.queryFirst(head, RDF.REST, null, 
new RyaDaoStatementIterHandler() {
    +                        @Override
    +                        public void handleStatementIter(final Statement 
st3) throws Exception {
    +                            // This object is the next bnode head to look 
for.
    +                            final URI obj3 = (URI) st3.getObject();
    +                            headHolder.add(obj3);
    +                        }
    +                    });
    +                    // As long as we get a new head there are more bnodes 
that
    +                    // are part of the intersection. Keep going until we 
reach
    +                    // rdf.nil.
    +                    if (!headHolder.isEmpty()) {
    +                        head = headHolder.get(0);
    +                    } else {
    +                        head = RDF.NIL;
    +                    }
    +                }
    +                // Add this intersection for this type. There may be more
    +                // intersections for this type so each type has a list of
    +                // intersection sets.
    +                intersectionsProp.get(type).add(intersection);
    +            }
    +        });
    +
    +        for (final Map.Entry<Resource, List<Set<Resource>>> entry : 
intersectionsProp.entrySet()) {
    +            final Resource type = entry.getKey();
    +            final List<Set<Resource>> intersectionList = entry.getValue();
    +            final Set<Resource> otherTypes = new HashSet<>();
    +            // Combine all of a type's intersections together.
    +            for (final Set<Resource> intersection : intersectionList) {
    +                otherTypes.addAll(intersection);
    +            }
    +            for (final Resource other : otherTypes) {
    +                // :A intersectionOf[:B, :C] implies that
    +                // :A subclassOf :B
    +                // :A subclassOf :C
    +                // So add each type that's part of the intersection to the
    +                // subClassOf graph.
    +                addSubClassOf(type, other);
    +                for (final Set<Resource> intersection : intersectionList) {
    +                    if (!intersection.contains(other)) {
    +                        addIntersection(intersection, other);
    --- End diff --
    
    Upon thinking about this, I wonder if it might be better to handle multiple 
intersections via the subclass relations we're adding, rather than by 
explicitly connecting each type/intersection pair like this. That is:
    
    1. If A equals (the intersection of B and C) and A equals (the intersection 
of D and E), then we want to make sure (B and C) doesn't just imply A but also 
implies D and E. (And, equivalently, that (D and E) implies both B and C.) This 
inner for loop applies this rule.
    
    2. It's also true that if A is a subclass of A2, and A equals (the 
intersection of B and C), then anything belonging to (B and C) is implied to 
belong to A2. (Because it belongs to A, and anything belonging to a subclass 
also belongs to its superclasses.)
    
    Since we're explicitly adding the facts (A subClassOf D), (A subClassOf E), 
etc., then rule 2 is just a more general version of rule 1. So an alternative 
approach would be to replace the innermost addIntersection loop with an 
implementation of this second rule, which would have the benefit of being more 
powerful in cases where the intersection type is a subclass of some other type. 
(e.g. `[ intersectionOf (X Y) ] subClassOf Z` or more likely `Z equivalentClass 
[ intersectionOf (X Y) ]` ).
    
    This could be done either at query time (in getIntersectionsImplying(type), 
get the subclasses of the type and include any of their intersections as well); 
or here at refresh time (after looping over the intersections and adding 
subclass edges, loop through again: for each (type, intersection list) pair, 
and for each superclass of that type, add the subclass's intersections to the 
superclass).


> Implement owl:intersectionOf inference
> --------------------------------------
>
>                 Key: RYA-292
>                 URL: https://issues.apache.org/jira/browse/RYA-292
>             Project: Rya
>          Issue Type: Sub-task
>          Components: sail
>            Reporter: Jesse Hatfield
>            Assignee: Eric White
>
> An *{{owl:intersectionOf}}* expression defines the set of resources who 
> belong to all of a particular set of classes.
> A basic implementation, if the ontology states that {{:Mother}} is the 
> intersection of {{:Parent}} and {{:Woman}}, should cause the inference engine 
> to:
> 1. Rewrite query patterns {{?x rdf:type :Mother}} (the intersection type) to 
> check for resources that have both types {{:Parent}} and {{:Woman}} (as well 
> as check for resources that are explicitly stated to be {{:Mother}} s)
> 2. Rewrite query patterns {{?y rdf:type :Parent}} (one of the intersecting 
> sets) to check for resources that are stated to be either {{:Mother}} or 
> {{:Parent}} , since belonging to the intersection type implies membership in 
> the component types. (Equivalent logic applies to {{Woman}} )



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to