@@ -67,8 +67,9 @@ object Main extends ZCaseApp[Config] {
6767 classesTasks = classesStream.map(c => ZIO .effectTotal(processSuperclasses(c, whelk, config)))
6868 queue <- Queue .unbounded[Restriction ]
6969 activeRestrictions <- Ref .make(0 )
70- _ <- traverse(properties, classes, whelk, config.mode, queue, activeRestrictions)
71- restrictionsStream = Stream .fromQueue(queue).map(r => processRestrictionAndExtendQueue(r, classes, whelk, config.mode, queue, activeRestrictions))
70+ seenRef <- Ref .make(Map .empty[AtomicConcept , Set [AtomicConcept ]])
71+ _ <- traverse(properties, classes, whelk, config.mode, queue, activeRestrictions, seenRef)
72+ restrictionsStream = Stream .fromQueue(queue).map(r => processRestrictionAndExtendQueue(r, classes, whelk, config.mode, queue, activeRestrictions, seenRef))
7273 allTasks = classesTasks ++ restrictionsStream
7374 processed = allTasks.mapMParUnordered(JRuntime .getRuntime.availableProcessors)(identity)
7475 _ <- processed.foreach {
@@ -101,22 +102,33 @@ object Main extends ZCaseApp[Config] {
101102
102103 def allClasses (ont : OWLOntology ): ZStream [Any , Nothing , OWLClass ] = Stream .fromIterable(ont.getClassesInSignature(Imports .INCLUDED ).asScala.to(Set ) - OWLThing - OWLNothing )
103104
104- def traverse (properties : Hierarchy , classes : Hierarchy , reasoner : ReasonerState , mode : Config .OutputMode , queue : Queue [Restriction ], activeRestrictions : Ref [Int ]): UIO [Unit ] =
105- ZIO .foreach_ (properties.subclasses.getOrElse(Top , Set .empty)) { subprop =>
106- traverseProperty(subprop, properties, classes, reasoner, mode, queue, activeRestrictions)
105+ def traverse (properties : Hierarchy , classes : Hierarchy , reasoner : ReasonerState , mode : Config .OutputMode , queue : Queue [Restriction ], activeRestrictions : Ref [Int ], seenRef : Ref [ Map [ AtomicConcept , Set [ AtomicConcept ]]] ): UIO [Unit ] = {
106+ ZIO .foreachPar_ (properties.subclasses.getOrElse(Top , Set .empty) - Bottom ) { subprop =>
107+ traverseProperty(subprop, properties, classes, reasoner, mode, queue, activeRestrictions, seenRef )
107108 }
109+ }
108110
109- def traverseProperty (property : AtomicConcept , properties : Hierarchy , classes : Hierarchy , whelk : ReasonerState , mode : Config .OutputMode , queue : Queue [Restriction ], activeRestrictions : Ref [Int ]): UIO [Unit ] = {
110- val restrictions = if (hasSubClasses(property, whelk)) {
111+ def traverseProperty (property : AtomicConcept , properties : Hierarchy , classes : Hierarchy , whelk : ReasonerState , mode : Config .OutputMode , queue : Queue [Restriction ], activeRestrictions : Ref [Int ], seenRef : Ref [Map [AtomicConcept , Set [AtomicConcept ]]]): UIO [Unit ] = {
112+ val propertyHasResults = hasSubClasses(property, whelk)
113+ val restrictions = if (propertyHasResults) {
111114 (classes.subclasses.getOrElse(Top , Set .empty) - Bottom ).map(filler => Restriction (Role (property.id), filler))
112- } else Set .empty
115+ } else Set .empty[ Restriction ]
113116 for {
117+ subProperties <- seenRef.modify { seen =>
118+ val subProperties = properties.subclasses.getOrElse(property, Set .empty) - Bottom
119+ val seenForThisProperty = seen.getOrElse(property, Set .empty) ++ restrictions.map(_.filler)
120+ val updatedSeen = seen.updated(property, seenForThisProperty)
121+ val unseenProperties = subProperties.filterNot(updatedSeen.keySet)
122+ (unseenProperties, updatedSeen ++ unseenProperties.map(p => p -> Set .empty[AtomicConcept ]).toMap)
123+ }
124+ _ <- ZIO .foreachPar_(subProperties) { subProp =>
125+ traverseProperty(subProp, properties, classes, whelk, mode, queue, activeRestrictions, seenRef)
126+ }
114127 _ <- activeRestrictions.update(current => current + restrictions.size)
115128 _ <- queue.offerAll(restrictions).unit
116129 active <- activeRestrictions.get
117130 _ <- queue.shutdown.when(active < 1 )
118131 } yield ()
119-
120132 }
121133
122134 def hasSubClasses (property : AtomicConcept , whelk : ReasonerState ): Boolean = {
@@ -127,12 +139,18 @@ object Main extends ZCaseApp[Config] {
127139 (updatedWhelk.closureSubsBySuperclass.getOrElse(queryConcept, Set .empty) - Bottom ).nonEmpty
128140 }
129141
130- def processRestrictionAndExtendQueue (restriction : Restriction , classes : Hierarchy , whelk : ReasonerState , mode : Config .OutputMode , queue : Queue [Restriction ], activeRestrictions : Ref [Int ]): UIO [TriplesGroup ] = {
142+ def processRestrictionAndExtendQueue (restriction : Restriction , classes : Hierarchy , whelk : ReasonerState , mode : Config .OutputMode , queue : Queue [Restriction ], activeRestrictions : Ref [Int ], seenRef : Ref [ Map [ AtomicConcept , Set [ AtomicConcept ]]] ): UIO [TriplesGroup ] = {
131143 for {
132144 triples <- ZIO .effectTotal(processRestriction(restriction, whelk, mode))
133- directFillerSubclassesRestrictions = if (triples.redundant.nonEmpty)
134- (classes.subclasses.getOrElse(restriction.filler, Set .empty) - Bottom ).map(c => Restriction (restriction.property, c))
135- else Set .empty
145+ directFillerSubclassesRestrictions <- if (triples.redundant.nonEmpty) seenRef.modify { seen =>
146+ val propertyConcept = AtomicConcept (restriction.property.id)
147+ val seenForThisProperty = seen.getOrElse(propertyConcept, Set .empty)
148+ val subClasses = classes.subclasses.getOrElse(restriction.filler, Set .empty) - Bottom
149+ val unseenSubClasses = subClasses -- seenForThisProperty
150+ val updatedSeen = seen.updated(propertyConcept, seenForThisProperty ++ subClasses)
151+ val newRestrictions = unseenSubClasses.map(c => Restriction (restriction.property, c))
152+ (newRestrictions, updatedSeen)
153+ } else ZIO .succeed(Set .empty[Restriction ])
136154 _ <- activeRestrictions.update(current => current - 1 + directFillerSubclassesRestrictions.size)
137155 _ <- queue.offerAll(directFillerSubclassesRestrictions)
138156 active <- activeRestrictions.get
@@ -179,12 +197,14 @@ object Main extends ZCaseApp[Config] {
179197
180198 def propertyHierarchy (ont : OWLOntology ): Hierarchy = {
181199 val subPropAxioms = ont.getAxioms(AxiomType .SUB_OBJECT_PROPERTY ).asScala.to(Set ).collect {
182- case ax if ax.getSubProperty.isNamed && ax.getSuperProperty.isNamed => ConceptInclusion (
200+ case ax if ax.getSubProperty.isNamed && ax.getSuperProperty.isNamed && ! ax.getSuperProperty.isOWLTopObjectProperty => ConceptInclusion (
183201 AtomicConcept (ax.getSubProperty.asOWLObjectProperty.getIRI.toString),
184202 AtomicConcept (ax.getSuperProperty.asOWLObjectProperty.getIRI.toString))
185203 }
186- val allProps = ont.getObjectPropertiesInSignature((Imports .INCLUDED )).asScala.to(Set ).map(prop =>
187- ConceptInclusion (AtomicConcept (prop.getIRI.toString), AtomicConcept (prop.getIRI.toString)))
204+ val allProps = ont.getObjectPropertiesInSignature((Imports .INCLUDED )).asScala.to(Set )
205+ .filterNot(_.isOWLTopObjectProperty)
206+ .map(prop =>
207+ ConceptInclusion (AtomicConcept (prop.getIRI.toString), AtomicConcept (prop.getIRI.toString)))
188208 val allAxioms = (subPropAxioms ++ allProps).toSet[Axiom ]
189209 val whelk = Reasoner .assert(allAxioms)
190210 classHierarchy(whelk)
0 commit comments