aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFederico Igne <git@federicoigne.com>2021-09-30 12:32:25 +0100
committerFederico Igne <git@federicoigne.com>2021-09-30 12:32:25 +0100
commit1ef8a2502532dd1736c1e3d6a1ff78ed6b8b643c (patch)
treeeb3471b39e10f667650dbb415eb5d366465fa0c8 /src
parent95a2e9e85e1783e1bf2b50ae37bd9eab003a6ca8 (diff)
downloadRSAComb-1ef8a2502532dd1736c1e3d6a1ff78ed6b8b643c.tar.gz
RSAComb-1ef8a2502532dd1736c1e3d6a1ff78ed6b8b643c.zip
Refactor query answering to use named graphs
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala176
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/filtering/FilteringProgram.scala3
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/filtering/NaiveFilteringProgram.scala9
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/filtering/RevisedFilteringProgram.scala4
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala38
5 files changed, 148 insertions, 82 deletions
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala
index 8e05f3a..6e9a119 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala
@@ -96,7 +96,10 @@ object RSAOntology {
96 * @param query the query to derive the filtering program 96 * @param query the query to derive the filtering program
97 * @return the filtering program for the given query 97 * @return the filtering program for the given query
98 */ 98 */
99 def filteringProgram(query: ConjunctiveQuery): FilteringProgram = 99 def filteringProgram(
100 graph: String,
101 query: ConjunctiveQuery
102 ): FilteringProgram =
100 Logger.timed( 103 Logger.timed(
101 FilteringProgram(FilterType.REVISED)(query), 104 FilteringProgram(FilterType.REVISED)(query),
102 "Generating filtering program", 105 "Generating filtering program",
@@ -496,76 +499,131 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File])
496 def unfold(axiom: OWLSubClassOfAxiom): Set[Term] = 499 def unfold(axiom: OWLSubClassOfAxiom): Set[Term] =
497 this.self(axiom) | this.cycle(axiom) 500 this.self(axiom) | this.cycle(axiom)
498 501
499 def ask(queries: Seq[ConjunctiveQuery]): Seq[ConjunctiveQueryAnswers] = ??? 502 /** Returns the answers to a collection of queries
500
501 /** Returns the answers to a query
502 * 503 *
503 * @param query query to execute 504 * @param queries a sequence of conjunctive queries to answer.
504 * @return a collection of answers 505 * @return a collection of answers for each query.
505 */ 506 */
506 def ask(query: ConjunctiveQuery): ConjunctiveQueryAnswers = Logger.timed( 507 def ask(queries: Seq[ConjunctiveQuery]): Seq[ConjunctiveQueryAnswers] = {
507 { 508 val (server, data) = RDFoxUtil.openConnection(RSAOntology.DataStore)
508 val (server, data) = RDFoxUtil.openConnection(RSAOntology.DataStore) 509 val canonNamedGraph = "http://cs.ox.ac.uk/isg/RSAComb#CanonicalModel"
509 val canon = this.canonicalModel 510 // Create a new NamedGraph for the canonical model
510 val filter = RSAOntology.filteringProgram(query) 511 data.createTupleTable(canonNamedGraph, Map("type" -> "named-graph").asJava)
511 512
512 /* Upload data from data file */ 513 /* Upload data from data file */
513 RDFoxUtil.addData(data, datafiles: _*) 514 RDFoxUtil.addData(canonNamedGraph, data, datafiles: _*)
514 515 /* Top / equality axiomatization */
515 RDFoxUtil printStatisticsFor data 516 RDFoxUtil.addRules(data, topAxioms ++ equalityAxioms)
516 517 /* Generate `named` predicates */
517 /* Top / equality axiomatization */ 518 RDFoxUtil.addFacts(
518 RDFoxUtil.addRules(data, topAxioms ++ equalityAxioms) 519 canonNamedGraph,
519 520 data,
520 /* Generate `named` predicates */ 521 (individuals ++ literals) map RSA.Named
521 RDFoxUtil.addFacts(data, (individuals ++ literals) map RSA.Named) 522 )
522 data.evaluateUpdate( 523 data.evaluateUpdate(
523 null, // the base IRI for the query (if null, a default is used) 524 null, // the base IRI for the query (if null, a default is used)
524 RSA.Prefixes, 525 RSA.Prefixes,
525 "INSERT { ?X a rsa:Named } WHERE { ?X a owl:Thing }", 526 s"""
526 new java.util.HashMap[String, String] 527 INSERT {
527 ) 528 GRAPH <$canonNamedGraph> { ?X a rsa:Named }
528 529 } WHERE {
529 /* Add canonical model */ 530 GRAPH <$canonNamedGraph> { ?X a owl:Thing }
530 Logger print s"Canonical model rules: ${canon.rules.length}" 531 }
531 RDFoxUtil.addRules(data, canon.rules) 532 """,
532 533 new java.util.HashMap[String, String]
533 Logger print s"Canonical model facts: ${canon.facts.length}" 534 )
534 RDFoxUtil.addFacts(data, canon.facts)
535 535
536 RDFoxUtil printStatisticsFor data 536 /* Add canonical model */
537 Logger print s"Canonical model rules: ${this.canonicalModel.rules.length}"
538 RDFoxUtil.addRules(data, this.canonicalModel.rules)
537 539
538 //{ 540 Logger print s"Canonical model facts: ${this.canonicalModel.facts.length}"
539 // import java.io.{PrintStream, FileOutputStream, File} 541 RDFoxUtil.addFacts(canonNamedGraph, data, this.canonicalModel.facts)
540 // val rules1 = new FileOutputStream(new File("rules1-lubm200.dlog"))
541 // val facts1 = new FileOutputStream(new File("facts1-lubm200.ttl"))
542 // RDFoxUtil.export(data, rules1, facts1)
543 // val rules2 = new PrintStream(new File("rules2-q34.dlog"))
544 // rules2.print(filter.rules.mkString("\n"))
545 //}
546 542
547 /* Add filtering program */ 543 queries map { query =>
548 Logger print s"Filtering program rules: ${filter.rules.length}" 544 {
549 RDFoxUtil.addRules(data, filter.rules) 545 val filterNamedGraph =
546 s"http://cs.ox.ac.uk/isg/RSAComb#Filter${query.id}"
547 val filter = RSAOntology.filteringProgram(filterNamedGraph, query)
548 /* Add filtering program */
549 Logger print s"Filtering program rules: ${filter.rules.length}"
550 RDFoxUtil.addRules(data, filter.rules)
550 551
551 RDFoxUtil printStatisticsFor data 552 // We remove the rules, should we drop the tuple table as well?
553 data.clearRulesAxiomsExplicateFacts()
552 554
553 /* Gather answers to the query */ 555 /* Gather answers to the query */
554 val answers = {
555 val ans = filter.answerQuery
556 RDFoxUtil 556 RDFoxUtil
557 .submitQuery(data, ans, RSA.Prefixes) 557 .submitQuery(data, filter.answerQuery, RSA.Prefixes)
558 .map(new ConjunctiveQueryAnswers(query, query.variables, _)) 558 .map(new ConjunctiveQueryAnswers(query, query.variables, _))
559 .get 559 .get
560 } 560 }
561 }
562 }
561 563
562 RDFoxUtil.closeConnection(server, data) 564 //def ask(query: ConjunctiveQuery): ConjunctiveQueryAnswers = Logger.timed(
563 565 // {
564 answers 566 // val (server, data) = RDFoxUtil.openConnection(RSAOntology.DataStore)
565 }, 567 // val canon = this.canonicalModel
566 "Answers computation", 568 // val filter = RSAOntology.filteringProgram(query)
567 Logger.DEBUG 569
568 ) 570 // /* Upload data from data file */
571 // RDFoxUtil.addData(data, datafiles: _*)
572
573 // RDFoxUtil printStatisticsFor data
574
575 // /* Top / equality axiomatization */
576 // RDFoxUtil.addRules(data, topAxioms ++ equalityAxioms)
577
578 // /* Generate `named` predicates */
579 // RDFoxUtil.addFacts(data, (individuals ++ literals) map RSA.Named)
580 // data.evaluateUpdate(
581 // null, // the base IRI for the query (if null, a default is used)
582 // RSA.Prefixes,
583 // "INSERT { ?X a rsa:Named } WHERE { ?X a owl:Thing }",
584 // new java.util.HashMap[String, String]
585 // )
586
587 // /* Add canonical model */
588 // Logger print s"Canonical model rules: ${canon.rules.length}"
589 // RDFoxUtil.addRules(data, canon.rules)
590
591 // Logger print s"Canonical model facts: ${canon.facts.length}"
592 // RDFoxUtil.addFacts(data, canon.facts)
593
594 // RDFoxUtil printStatisticsFor data
595
596 // //{
597 // // import java.io.{PrintStream, FileOutputStream, File}
598 // // val rules1 = new FileOutputStream(new File("rules1-lubm200.dlog"))
599 // // val facts1 = new FileOutputStream(new File("facts1-lubm200.ttl"))
600 // // RDFoxUtil.export(data, rules1, facts1)
601 // // val rules2 = new PrintStream(new File("rules2-q34.dlog"))
602 // // rules2.print(filter.rules.mkString("\n"))
603 // //}
604
605 // /* Add filtering program */
606 // Logger print s"Filtering program rules: ${filter.rules.length}"
607 // RDFoxUtil.addRules(data, filter.rules)
608
609 // RDFoxUtil printStatisticsFor data
610
611 // /* Gather answers to the query */
612 // val answers = {
613 // val ans = filter.answerQuery
614 // RDFoxUtil
615 // .submitQuery(data, ans, RSA.Prefixes)
616 // .map(new ConjunctiveQueryAnswers(query, query.variables, _))
617 // .get
618 // }
619
620 // RDFoxUtil.closeConnection(server, data)
621
622 // answers
623 // },
624 // "Answers computation",
625 // Logger.DEBUG
626 //)
569 627
570 /** Query the RDFox data store used for query answering. 628 /** Query the RDFox data store used for query answering.
571 * 629 *
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/FilteringProgram.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/FilteringProgram.scala
index 2774cb1..d6ad8c5 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/FilteringProgram.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/FilteringProgram.scala
@@ -46,6 +46,9 @@ object FilteringProgram extends Versioned[FilterType] {
46 */ 46 */
47trait FilteringProgram { 47trait FilteringProgram {
48 48
49 /** Named graph used for filtering process */
50 val graph: String
51
49 /** Query from which the filtering program is generated */ 52 /** Query from which the filtering program is generated */
50 val query: ConjunctiveQuery 53 val query: ConjunctiveQuery
51 54
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/NaiveFilteringProgram.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/NaiveFilteringProgram.scala
index 45dd867..3d9717c 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/NaiveFilteringProgram.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/NaiveFilteringProgram.scala
@@ -36,8 +36,8 @@ object NaiveFilteringProgram {
36 * 36 *
37 * @param query CQ to be converted into logic rules. 37 * @param query CQ to be converted into logic rules.
38 */ 38 */
39 def apply(query: ConjunctiveQuery): FilteringProgram = 39 def apply(graph: String, query: ConjunctiveQuery): FilteringProgram =
40 new NaiveFilteringProgram(query) 40 new NaiveFilteringProgram(graph, query)
41} 41}
42 42
43/** Filtering Program generator 43/** Filtering Program generator
@@ -47,7 +47,7 @@ object NaiveFilteringProgram {
47 * 47 *
48 * Instances can be created using the companion object. 48 * Instances can be created using the companion object.
49 */ 49 */
50class NaiveFilteringProgram(val query: ConjunctiveQuery) 50class NaiveFilteringProgram(val graph: String, val query: ConjunctiveQuery)
51 extends FilteringProgram { 51 extends FilteringProgram {
52 52
53 /** Extends capabilities of 53 /** Extends capabilities of
@@ -321,5 +321,6 @@ class NaiveFilteringProgram(val query: ConjunctiveQuery)
321 r9 :: List()) map RDFoxUtil.reify 321 r9 :: List()) map RDFoxUtil.reify
322 } 322 }
323 323
324 val answerQuery = RDFoxUtil.buildDescriptionQuery("Ans", query.answer.size) 324 val answerQuery =
325 RDFoxUtil.buildDescriptionQuery(graph, "Ans", query.answer.size)
325} 326}
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/RevisedFilteringProgram.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/RevisedFilteringProgram.scala
index 4a4e65c..5d11369 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/RevisedFilteringProgram.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/RevisedFilteringProgram.scala
@@ -422,12 +422,12 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
422 s""" 422 s"""
423 SELECT $answer 423 SELECT $answer
424 WHERE { 424 WHERE {
425 ?K a rsa:Ans . 425 GRAPH <$graph> { ?K a rsa:Ans } .
426 TT <http://oxfordsemantic.tech/RDFox#SKOLEM> { $answer $bounded ?K } . 426 TT <http://oxfordsemantic.tech/RDFox#SKOLEM> { $answer $bounded ?K } .
427 } 427 }
428 """ 428 """
429 } else { 429 } else {
430 "ASK { ?X a rsa:Ans }" 430 s"ASK { GRAPH <$graph> { ?X a rsa:Ans } }"
431 } 431 }
432 } 432 }
433 433
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala
index 620d2dd..6f5ff31 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala
@@ -124,13 +124,14 @@ object RDFoxUtil {
124 def addRules(data: DataStoreConnection, rules: Seq[Rule]): Unit = 124 def addRules(data: DataStoreConnection, rules: Seq[Rule]): Unit =
125 Logger.timed( 125 Logger.timed(
126 if (rules.length > 0) { 126 if (rules.length > 0) {
127 data.importData( 127 data addRules rules
128 UpdateType.ADDITION, 128 // data.importData(
129 RSA.Prefixes, 129 // UpdateType.ADDITION,
130 rules 130 // RSA.Prefixes,
131 .map(_.toString(Prefixes.s_emptyPrefixes)) 131 // rules
132 .mkString("\n") 132 // .map(_.toString(Prefixes.s_emptyPrefixes))
133 ) 133 // .mkString("\n")
134 // )
134 }, 135 },
135 s"Loading ${rules.length} rules", 136 s"Loading ${rules.length} rules",
136 Logger.DEBUG 137 Logger.DEBUG
@@ -141,10 +142,15 @@ object RDFoxUtil {
141 * @param data datastore connection 142 * @param data datastore connection
142 * @param facts collection of facts to be added to the data store 143 * @param facts collection of facts to be added to the data store
143 */ 144 */
144 def addFacts(data: DataStoreConnection, facts: Seq[TupleTableAtom]): Unit = 145 def addFacts(
146 graph: String,
147 data: DataStoreConnection,
148 facts: Seq[TupleTableAtom]
149 ): Unit =
145 Logger.timed( 150 Logger.timed(
146 if (facts.length > 0) { 151 if (facts.length > 0) {
147 data.importData( 152 data.importData(
153 graph,
148 UpdateType.ADDITION, 154 UpdateType.ADDITION,
149 RSA.Prefixes, 155 RSA.Prefixes,
150 facts 156 facts
@@ -161,14 +167,10 @@ object RDFoxUtil {
161 * @param data datastore connection. 167 * @param data datastore connection.
162 * @param files sequence of files to upload. 168 * @param files sequence of files to upload.
163 */ 169 */
164 def addData(data: DataStoreConnection, files: File*): Unit = 170 def addData(graph: String, data: DataStoreConnection, files: File*): Unit =
165 Logger.timed( 171 Logger.timed(
166 files.foreach { 172 files.foreach {
167 data.importData( 173 data.importData(graph, UpdateType.ADDITION, RSA.Prefixes, _)
168 UpdateType.ADDITION,
169 RSA.Prefixes,
170 _
171 )
172 }, 174 },
173 "Loading data files", 175 "Loading data files",
174 Logger.DEBUG 176 Logger.DEBUG
@@ -315,11 +317,13 @@ object RDFoxUtil {
315 * compatible with RDFox engine. This helper allows to build a query 317 * compatible with RDFox engine. This helper allows to build a query
316 * to gather all instances of an internal predicate 318 * to gather all instances of an internal predicate
317 * 319 *
320 * @param graph named graph to query for the provided predicate
318 * @param pred name of the predicate to describe. 321 * @param pred name of the predicate to describe.
319 * @param arity arity of the predicate. 322 * @param arity arity of the predicate.
320 * @return a string containing a SPARQL query. 323 * @return a string containing a SPARQL query.
321 */ 324 */
322 def buildDescriptionQuery( 325 def buildDescriptionQuery(
326 graph: String,
323 pred: String, 327 pred: String,
324 arity: Int 328 arity: Int
325 ): String = { 329 ): String = {
@@ -328,12 +332,12 @@ object RDFoxUtil {
328 s""" 332 s"""
329 SELECT $variables 333 SELECT $variables
330 WHERE { 334 WHERE {
331 ?K a rsa:$pred. 335 GRAPH <$graph> { ?K a rsa:$pred }.
332 TT <http://oxfordsemantic.tech/RDFox#SKOLEM> { $variables ?K } . 336 TT <http://oxfordsemantic.tech/RDFox#SKOLEM> { $variables ?K } .
333 } 337 }
334 """ 338 """
335 } else { 339 } else {
336 "ASK { ?X a rsa:Ans }" 340 s"ASK { GRAPH <$graph> { ?X a rsa:Ans } }"
337 } 341 }
338 } 342 }
339 343