[ https://issues.apache.org/jira/browse/RYA-292?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16137219#comment-16137219 ]
ASF GitHub Bot commented on RYA-292: ------------------------------------ Github user ejwhite922 commented on a diff in the pull request: https://github.com/apache/incubator-rya/pull/206#discussion_r134575148 --- Diff: sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java --- @@ -653,170 +664,406 @@ private void refreshAllValuesFromRestrictions(Map<Resource, URI> restrictions) t } } - 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 RDFHandlerBase() { + @Override + public void handleStatement(final Statement statement) throws RDFHandlerException { + final Resource type = statement.getSubject(); + // head will point to a type that is part of the intersection. + final URI head = (URI) statement.getObject(); + if (!intersectionsProp.containsKey(type)) { + intersectionsProp.put(type, new ArrayList<Set<Resource>>()); + } + + // head should point to a list of items that forms the + // intersection. + try { + final Set<Resource> intersection = new LinkedHashSet<>(getList(head)); + if (!intersection.isEmpty()) { + // 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); + } + } catch (final QueryEvaluationException e) { + throw new RDFHandlerException("Error getting intersection list.", e); + } + } + }); + + intersections.clear(); + for (final 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); + } + } + } + for (final Set<Resource> intersection : intersectionList) { + addIntersection(intersection, type); + } + } + for (final Entry<Resource, List<Set<Resource>>> entry : intersectionsProp.entrySet()) { + final Resource type = entry.getKey(); + final List<Set<Resource>> intersectionList = entry.getValue(); + + final Set<URI> superClasses = getSuperClasses((URI) type); + for (final URI superClass : superClasses) { + // Add intersections to super classes if applicable. + // IF: + // :A intersectionOf[:B, :C] + // AND + // :A subclassOf :D + // Then we can infer: + // intersectionOf[:B, :C] subclassOf :D + for (final Set<Resource> intersection : intersectionList) { + addIntersection(intersection, superClass); + } + } + // Check if other keys have any of the same intersections and infer + // the same subclass logic to them that we know from the current + // type. Propagating up through all the superclasses. + for (final Set<Resource> intersection : intersectionList) { + final Set<Resource> otherKeys = Sets.newHashSet(intersectionsProp.keySet()); + otherKeys.remove(type); + for (final Resource otherKey : otherKeys) { + if (intersectionsProp.get(otherKey).contains(intersection)) { + for (final URI superClass : superClasses) { + addSubClassOf(otherKey, superClass); + } + } + } + } + } + for (final Entry<Resource, List<Set<Resource>>> entry : intersectionsProp.entrySet()) { + final Resource type = entry.getKey(); + final List<Set<Resource>> intersectionList = entry.getValue(); + for (final Set<Resource> intersection : intersectionList) { + addIntersection(intersection, type); --- End diff -- Yep. The second loop is gone now. > 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)