aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Igne <git@federicoigne.com>2021-09-29 16:43:01 +0100
committerFederico Igne <git@federicoigne.com>2021-09-29 16:43:01 +0100
commita5a4f5eba46c51c2a14e9915bfa34e78bff59030 (patch)
tree2bb20ae0d2ada44d3cc0cec7fc25d719bfe06f26
parentb1799a0af7bd243fb24bff66682f6f848557c27d (diff)
downloadRSAComb-a5a4f5eba46c51c2a14e9915bfa34e78bff59030.tar.gz
RSAComb-a5a4f5eba46c51c2a14e9915bfa34e78bff59030.zip
Add import of multiple queries
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala56
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala4
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala50
3 files changed, 70 insertions, 40 deletions
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala
index a1fd20f..b1fd721 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala
@@ -49,7 +49,7 @@ object RSAConfig {
49 -h | -? | --help 49 -h | -? | --help
50 print this help message 50 print this help message
51 51
52 -q <file> | --query <file> 52 -q <file> | --queries <file>
53 path to a file containing a single SPARQL query. If no query 53 path to a file containing a single SPARQL query. If no query
54 is provided, only the approximation to RSA will be performed. 54 is provided, only the approximation to RSA will be performed.
55 55
@@ -97,11 +97,11 @@ object RSAConfig {
97 println(help) 97 println(help)
98 sys.exit(0) 98 sys.exit(0)
99 } 99 }
100 case flag @ ("-q" | "--query") :: _query :: tail => { 100 case flag @ ("-q" | "--queries") :: _query :: tail => {
101 val query = new File(_query) 101 val query = new File(_query)
102 if (!query.isFile) 102 if (!query.isFile)
103 exit(s"'$query' is not a valid filename.") 103 exit(s"'$query' is not a valid filename.")
104 parse(tail, config ++ Map('query -> query)) 104 parse(tail, config ++ Map('queries -> query))
105 } 105 }
106 case _ontology :: _data => { 106 case _ontology :: _data => {
107 val ontology = new File(_ontology) 107 val ontology = new File(_ontology)
@@ -132,36 +132,32 @@ object RSAComb extends App {
132 config('data).get[List[File]] 132 config('data).get[List[File]]
133 ).normalize(new Normalizer) 133 ).normalize(new Normalizer)
134 134
135 //ontology.axioms foreach println
136
135 /* Approximate the ontology to RSA */ 137 /* Approximate the ontology to RSA */
136 val toRSA = new Upperbound 138 val toRSA = new Upperbound
137 val rsa = ontology approximate toRSA 139 val rsa = ontology approximate toRSA
138 140
139 if (config contains 'query) { 141 if (config contains 'queries) {
140 val query = 142 val queries =
141 RDFoxUtil.loadQueryFromFile(config('query).get[File].getAbsoluteFile) 143 RDFoxUtil.loadQueriesFromFile(config('queries).get[File].getAbsoluteFile)
142 144
143 ConjunctiveQuery.parse(query) match { 145 val answers = rsa ask queries
144 case Some(query) => { 146
145 // Retrieve answers 147 // Logger.print(s"$answers", Logger.VERBOSE)
146 val answers = rsa ask query 148 // Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})"
147 Logger.print(s"$answers", Logger.VERBOSE) 149 // Retrieve unfiltered answers
148 Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})" 150 // val unfiltered = rsa.queryDataStore(
149 // Retrieve unfiltered answers 151 // """
150 // val unfiltered = rsa.queryDataStore( 152 // SELECT (count(?K) as ?COUNT)
151 // """ 153 // WHERE {
152 // SELECT (count(?K) as ?COUNT) 154 // ?K a rsa:QM .
153 // WHERE { 155 // }
154 // ?K a rsa:QM . 156 // """,
155 // } 157 // RSA.Prefixes
156 // """, 158 // )
157 // RSA.Prefixes 159 // unfiltered.foreach((u) =>
158 // ) 160 // Logger print s"Number of unfiltered answers: ${u.head._2}"
159 // unfiltered.foreach((u) => 161 // )
160 // Logger print s"Number of unfiltered answers: ${u.head._2}"
161 // )
162 }
163 case None =>
164 throw new RuntimeException("Submitted query is not conjunctive")
165 }
166 } 162 }
167} 163}
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 0c88f7f..8e05f3a 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala
@@ -496,6 +496,8 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File])
496 def unfold(axiom: OWLSubClassOfAxiom): Set[Term] = 496 def unfold(axiom: OWLSubClassOfAxiom): Set[Term] =
497 this.self(axiom) | this.cycle(axiom) 497 this.self(axiom) | this.cycle(axiom)
498 498
499 def ask(queries: Seq[ConjunctiveQuery]): Seq[ConjunctiveQueryAnswers] = ???
500
499 /** Returns the answers to a query 501 /** Returns the answers to a query
500 * 502 *
501 * @param query query to execute 503 * @param query query to execute
@@ -553,7 +555,7 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File])
553 val ans = filter.answerQuery 555 val ans = filter.answerQuery
554 RDFoxUtil 556 RDFoxUtil
555 .submitQuery(data, ans, RSA.Prefixes) 557 .submitQuery(data, ans, RSA.Prefixes)
556 .map(new ConjunctiveQueryAnswers(query.bcq, query.variables, _)) 558 .map(new ConjunctiveQueryAnswers(query, query.variables, _))
557 .get 559 .get
558 } 560 }
559 561
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 3d67270..620d2dd 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
@@ -41,6 +41,7 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{
41 Term 41 Term
42} 42}
43import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery 43import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery
44import uk.ac.ox.cs.rsacomb.sparql.ConjunctiveQuery
44import uk.ac.ox.cs.rsacomb.suffix.Nth 45import uk.ac.ox.cs.rsacomb.suffix.Nth
45import uk.ac.ox.cs.rsacomb.util.Logger 46import uk.ac.ox.cs.rsacomb.util.Logger
46 47
@@ -177,15 +178,6 @@ object RDFoxUtil {
177 def materialize(data: DataStoreConnection): Unit = 178 def materialize(data: DataStoreConnection): Unit =
178 Logger.timed(data.updateMaterialization(), "Materialization", Logger.DEBUG) 179 Logger.timed(data.updateMaterialization(), "Materialization", Logger.DEBUG)
179 180
180 /** Load SPARQL query from file. */
181 def loadQueryFromFile(file: File): String = {
182 val source = io.Source.fromFile(file)
183 val query = source.getLines mkString "\n"
184 Logger print s"Loaded query:\n$query"
185 source.close()
186 query
187 }
188
189 /** Export data in `text/turtle`. 181 /** Export data in `text/turtle`.
190 * 182 *
191 * @param data datastore connection from which to export data. 183 * @param data datastore connection from which to export data.
@@ -206,6 +198,46 @@ object RDFoxUtil {
206 ) 198 )
207 } 199 }
208 200
201 /** Load SPARQL queries from file.
202 *
203 * The file can list multiple queries, each preceeded with a
204 * single line containing "#^[Query<id>]" where "<id>" is a number.
205 * Empty lines are ignored.
206 *
207 * @note if a query is not recognized as a [[SelectQuery]] by RDFox
208 * it is discarded.
209 *
210 * @param file file containing a list of conjunctive queries.
211 * @param prefixes additional prefixes for the query. It defaults to
212 * an empty set.
213 *
214 * @return a list of [[tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery SelectQuery]] queries.
215 */
216 def loadQueriesFromFile(
217 file: File,
218 prefixes: Prefixes = new Prefixes()
219 ): List[ConjunctiveQuery] = {
220 val source = io.Source.fromFile(file)
221 val queries = source.getLines
222 .map(_.trim.filter(_ >= ' '))
223 .filterNot(_ == "")
224 .foldRight((List.empty[List[String]], List.empty[String])) {
225 case (line, (acc, query)) => {
226 if ("^#\\^\\[Query\\d+\\]$".r.matches(line))
227 (query :: acc, List.empty)
228 else
229 (acc, line :: query)
230 }
231 }
232 ._1
233 .map(_.mkString(" "))
234 .map(ConjunctiveQuery.parse(_, prefixes))
235 .collect { case Some(q) => q }
236 Logger print s"Loaded ${queries.length} queries from ${file.getAbsolutePath}"
237 source.close()
238 queries
239 }
240
209 /** Parse a SELECT query from a string in SPARQL format. 241 /** Parse a SELECT query from a string in SPARQL format.
210 * 242 *
211 * @param query the string containing the SPARQL query 243 * @param query the string containing the SPARQL query