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. --- 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 ++++++++++++++++++++-- 4 files changed, 91 insertions(+), 16 deletions(-) (limited to 'src/main/scala') 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