|
1 | 1 | package net.sansa_stack.inference.utils |
2 | 2 |
|
3 | | -import scala.collection.JavaConverters._ |
4 | | -import scalax.collection.edge.Implicits._ |
5 | | -import scalax.collection.edge.LDiEdge |
6 | | -import scalax.collection.mutable.Graph |
7 | | - |
| 3 | +import net.sansa_stack.inference.rules.RuleEntailmentType |
| 4 | +import net.sansa_stack.inference.rules.RuleEntailmentType._ |
| 5 | +import net.sansa_stack.inference.utils.graph.LabeledEdge |
8 | 6 | import org.apache.jena.graph.Node |
9 | 7 | import org.apache.jena.reasoner.TriplePattern |
10 | 8 | import org.apache.jena.reasoner.rulesys.Rule |
11 | 9 | import org.jgrapht.alg.cycle.TarjanSimpleCycles |
12 | 10 |
|
13 | | -import net.sansa_stack.inference.rules.RuleEntailmentType |
14 | | -import net.sansa_stack.inference.rules.RuleEntailmentType._ |
15 | | -import net.sansa_stack.inference.utils.graph.LabeledEdge |
| 11 | +import scala.collection.JavaConverters._ |
| 12 | +import scalax.collection.edge.Implicits._ |
| 13 | +import scalax.collection.edge.LDiEdge |
| 14 | +import scalax.collection.mutable.Graph |
16 | 15 |
|
17 | 16 | /** |
18 | 17 | * Utility class for rules. |
@@ -275,6 +274,17 @@ object RuleUtils { |
275 | 274 | * @return whether it's cyclic or not |
276 | 275 | */ |
277 | 276 | def isCyclic(rule: Rule) : Boolean = { |
| 277 | + val body = rule.bodyTriplePatterns() |
| 278 | + val head = rule.headTriplePatterns() |
| 279 | + |
| 280 | + // sanity check that there is only a single head TP |
| 281 | + if(head.size > 1) { |
| 282 | + throw new IllegalArgumentException("Rules with more than one triple pattern in the head are not supported yet!") |
| 283 | + } |
| 284 | + |
| 285 | + // if there is only a single body TP, we can terminate here and return FALSE |
| 286 | + if(body.size == 1) return false |
| 287 | + |
278 | 288 | // get the type of the rule |
279 | 289 | val ruleType = entailmentType(rule) |
280 | 290 |
|
@@ -321,14 +331,21 @@ object RuleUtils { |
321 | 331 |
|
322 | 332 | } |
323 | 333 |
|
| 334 | + // we generate a graph for the rule (we use a JGraphT graph which provides better cycle detection) |
324 | 335 | val g = GraphUtils.asJGraphtRuleGraph(asGraph(rule)) |
325 | 336 |
|
326 | 337 | // get cycles of length > 2 |
327 | 338 | val cycleDetector = new TarjanSimpleCycles[Node, LabeledEdge[Node, String]](g) |
328 | | - val cycles = cycleDetector.findSimpleCycles().asScala.filter(c => c.size() == 2) |
| 339 | + val cycles = cycleDetector.findSimpleCycles().asScala.filter(c => c.size() > 2) |
| 340 | + |
| 341 | + // we can terminate if there are no cycles with length > 2 |
| 342 | + if(cycles.isEmpty) return false |
| 343 | + |
| 344 | + // we have to check for cycles that share the same predicate with the head |
329 | 345 |
|
330 | 346 | cycles.foreach(c => { |
331 | | - println(c) |
| 347 | + val nodes = c.asScala.toList |
| 348 | + val pairs = nodes zip nodes.tail |
332 | 349 | }) |
333 | 350 |
|
334 | 351 | true |
|
0 commit comments