From e3534ea4b8d76e9a22991ec806ab3acd6bae0fea Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Wed, 20 Oct 2021 18:06:36 +0100 Subject: Rework RDFox simulation to be more modular This will help with faster testing and debugging. --- README.md | 5 +- simulate.rdfox | 21 ------ src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala | 21 +++--- src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala | 2 + .../scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala | 5 +- .../scala/uk/ac/ox/cs/rsacomb/util/Logger.scala | 79 ++++++++++++++++++++-- 6 files changed, 93 insertions(+), 40 deletions(-) delete mode 100644 simulate.rdfox diff --git a/README.md b/README.md index 87b721f..9cd3029 100644 --- a/README.md +++ b/README.md @@ -187,12 +187,11 @@ java -cp lib/JRDFox.jar:target/scala-2.13/RSAComb-assembly-0.2.0.jar uk.ac.ox.cs This will answers all the queries in `tests/lubm/queries.sparql` and generate debug information in a new folder in the current working directory (let's say, `rsacomb-20211005120845/`). You can run the provided RDFox script as follows ```{.sh} -./lib/RDFox-linux-x86_64-5.2.1/RDFox sandbox . "simulate " +path/to/RDFox sandbox "simulate " ``` where - `debug-folder` is the newly generated folder (`rsacomb-20211005120845` in this example) -- `` is the path to the data file used with RSAComb (`tests/lubm/data/lubm1.ttl` in this example) -- `query-id` is the identifier of the query we want to simulate (if we want to simulate query 16 we will pass `16` as an argument) +- `query-id` is the identifier of the query we want to simulate (if we want to simulate query 16 we will pass `16` as an argument). We can pass `all` to simulate all queries. This will launch a sandboxed RDFox console, where you will be able to explore a simulation of the datastore used by RSAComb. You can also access the same datastore from the web interface at [http://localhost:12110/console/](http://localhost:12110/console/). diff --git a/simulate.rdfox b/simulate.rdfox deleted file mode 100644 index 80dbf7c..0000000 --- a/simulate.rdfox +++ /dev/null @@ -1,21 +0,0 @@ - -echo "\n[Start endpoint]" -endpoint start - -echo "\n[Create new datastore]" -dstore create rsacomb -active rsacomb -prefix rsacomb: -tupletable create rsacomb:CanonicalModel type "named-graph" -tupletable create rsacomb:Filter$(3) type "named-graph" - -echo "\n[Import data]" -import > rsacomb:CanonicalModel "$(2)" -import "$(1)/axiomatisation.dlog" -insert { graph rsacomb:CanonicalModel { ?x a rsacomb:Named } } where { graph rsacomb:CanonicalModel { ?x a owl:Thing } } - -echo "\n[Load canonical model program]" -import "$(1)/canonical_model.dlog" - -echo "\n[Load filtering program for query $(3)]" -import "$(1)/filter_query$(3).dlog" 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 302db75..fe7a6db 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala @@ -42,10 +42,9 @@ object RSAComb extends App { Logger.level = config('logger).get[Logger.Level] /* Load original ontology and normalize it */ - val ontology = Ontology( - config('ontology).get[os.Path], - config('data).get[List[os.Path]] - ).normalize(new Normalizer) + val ontopath = config('ontology).get[os.Path] + val data = config('data).get[List[os.Path]] + val ontology = Ontology(ontopath, data).normalize(new Normalizer) //ontology.axioms foreach println @@ -62,12 +61,14 @@ object RSAComb extends App { val answers = rsa ask queries /* Write answers to output file */ - if (config.contains('answers)) - os.write( - config('answers).get[os.Path], - ujson.write(ujson.Arr(answers.map(_.toJSON)), indent = 2), - createFolders = true - ) + os.write( + config('answers).get[os.Path], + ujson.write(ujson.Arr(answers.map(_.toJSON)), indent = 2), + createFolders = true + ) + + /* Generate simulation script */ + Logger.generateSimulationScripts(data, queries) // Logger.print(s"$answers", Logger.VERBOSE) // Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})" diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala index 4d96850..f3039b3 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala @@ -149,6 +149,8 @@ object RSAConfig { exit("The following flag is mandatory: '-o' or '--ontology'.") if (!config.contains('data)) config += ('data -> List.empty[os.Path]) + if (!config.contains('answers)) + config += ('answers -> Logger.dir / "answers.json") config } } 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 4b8e015..5e864bb 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala @@ -623,7 +623,10 @@ class RSAOntology( /* Add filtering program */ Logger print s"Filtering program rules: ${filter.rules.length}" - Logger.write(filter.rules.mkString("\n"), s"filter_query${query.id}.dlog") + Logger.write( + filter.rules.mkString("\n"), + s"filter_query_${query.id}.dlog" + ) RDFoxUtil.addRules(data, filter.rules) // TODO: We remove the rules, should we drop the tuple table as well? diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/util/Logger.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/util/Logger.scala index b86230e..0fcde53 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/util/Logger.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/util/Logger.scala @@ -19,14 +19,12 @@ package uk.ac.ox.cs.rsacomb.util import java.util.Calendar import java.text.SimpleDateFormat import java.io.PrintStream +import uk.ac.ox.cs.rsacomb.sparql.ConjunctiveQuery -/** Rough implementation of a logger. - * - * This is a WIP class for debugging and benchmarking. - */ +/** Simple logger */ object Logger { - private lazy val dir = { + lazy val dir = { val timestamp = (new SimpleDateFormat("yyyyMMddHHmmss")).format( Calendar.getInstance().getTime ) @@ -52,10 +50,21 @@ object Logger { /** Currend logger level */ var level: Level = DEBUG + /** Print a line padded with logger level and timestamp. + * + * @param str object to be printed. + * @param lvl minimum logger level required to print. + */ def print(str: Any, lvl: Level = NORMAL): Unit = if (lvl <= level) output println s"[$lvl][${Calendar.getInstance().getTime}] $str" + /** Write provided content to file. + * + * @param content content to append to the file. + * @param file name of the file to append the content to. + * @param lvl minimum logger level required to write. + */ def write(content: => os.Source, file: String, lvl: Level = VERBOSE): Unit = if (lvl <= level) os.write.append(dir / file, content) @@ -69,4 +78,64 @@ object Logger { result } + /** Generate simulation scripts for current run + * + * @param data data files to be imported. + * @param queries collection of executed queries. + * @param lvl minimum logger level required. + */ + def generateSimulationScripts( + data: Seq[os.Path], + queries: Seq[ConjunctiveQuery], + lvl: Level = VERBOSE + ): Unit = + if (lvl <= level) { + /* Create script folder */ + val sim = os.rel / 'sim + os.makeDir(dir / sim) + /* Generate main script */ + os.write.append( + dir / "simulate.rdfox", + """ +echo "\n[Start endpoint]" +endpoint start + +echo "\n[Create new datastore]" +dstore create rsacomb +active rsacomb +prefix rsacomb: +tupletable create rsacomb:CanonicalModel type "named-graph" + +echo "\n[Import data]" +""" ++ + data + .map(d => s"""import > rsacomb:CanonicalModel \"$d\"""") + .mkString("\n") + ++ s""" +import "axiomatisation.dlog" +insert { graph rsacomb:CanonicalModel { ?x a rsacomb:Named } } where { graph rsacomb:CanonicalModel { ?x a owl:Thing } } + +echo "\\n[Load canonical model program]" +import "canonical_model.dlog" + +exec "$sim/filter_query_$$(1).rdfox" +""" + ) + /* Generate query scripts */ + queries.map(q => { + val id = q.id + os.write.append( + dir / sim / "filter_query_all.rdfox", + s"exec $sim/filter_query_$id.rdfox\n" + ) + os.write.append( + dir / sim / s"filter_query_$id.rdfox", + s""" +echo "\\n[Load filtering program for query $id]" +tupletable create rsacomb:Filter$id type "named-graph" +import "filter_query_$id.dlog" +""" + ) + }) + } } -- cgit v1.2.3