diff options
| author | Federico Igne <git@federicoigne.com> | 2021-09-30 18:10:01 +0100 |
|---|---|---|
| committer | Federico Igne <git@federicoigne.com> | 2021-10-01 10:25:40 +0100 |
| commit | bc37ee9293d8a4098edce2a77db6efa3d87b6dd2 (patch) | |
| tree | cb85cc0b3b48855aca503b07f93c7b54e4b99c07 /src/main/scala | |
| parent | 1ef8a2502532dd1736c1e3d6a1ff78ed6b8b643c (diff) | |
| download | RSAComb-bc37ee9293d8a4098edce2a77db6efa3d87b6dd2.tar.gz RSAComb-bc37ee9293d8a4098edce2a77db6efa3d87b6dd2.zip | |
Make canonical model generation parametric over named graph
Diffstat (limited to 'src/main/scala')
6 files changed, 141 insertions, 83 deletions
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/CanonicalModel.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/CanonicalModel.scala index 3467d3c..a39b9c0 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/CanonicalModel.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/CanonicalModel.scala | |||
| @@ -31,7 +31,8 @@ import tech.oxfordsemantic.jrdfox.logic.datalog.{ | |||
| 31 | BodyFormula, | 31 | BodyFormula, |
| 32 | Negation, | 32 | Negation, |
| 33 | Rule, | 33 | Rule, |
| 34 | TupleTableAtom | 34 | TupleTableAtom, |
| 35 | TupleTableName | ||
| 35 | } | 36 | } |
| 36 | import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term, Variable} | 37 | import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term, Variable} |
| 37 | 38 | ||
| @@ -48,8 +49,9 @@ import uk.ac.ox.cs.rsacomb.util.{DataFactory, RSA} | |||
| 48 | * (via materialization). | 49 | * (via materialization). |
| 49 | * | 50 | * |
| 50 | * @param ontology the RSA ontology the canonical model is targeting. | 51 | * @param ontology the RSA ontology the canonical model is targeting. |
| 52 | * @param graph the graph the canonical model will be generated into. | ||
| 51 | */ | 53 | */ |
| 52 | class CanonicalModel(val ontology: RSAOntology) { | 54 | class CanonicalModel(val ontology: RSAOntology, val graph: IRI) { |
| 53 | 55 | ||
| 54 | /** Simplify conversion between OWLAPI and RDFox concepts */ | 56 | /** Simplify conversion between OWLAPI and RDFox concepts */ |
| 55 | import implicits.RDFox._ | 57 | import implicits.RDFox._ |
| @@ -65,6 +67,7 @@ class CanonicalModel(val ontology: RSAOntology) { | |||
| 65 | * versions need to be explicitly stated in terms of logic rules. | 67 | * versions need to be explicitly stated in terms of logic rules. |
| 66 | */ | 68 | */ |
| 67 | val rolesAdditionalRules: List[Rule] = { | 69 | val rolesAdditionalRules: List[Rule] = { |
| 70 | val tt = TupleTableName.create(graph.getIRI) | ||
| 68 | ontology.roles | 71 | ontology.roles |
| 69 | .collect { case prop: OWLObjectProperty => prop } | 72 | .collect { case prop: OWLObjectProperty => prop } |
| 70 | .flatMap((pred) => { | 73 | .flatMap((pred) => { |
| @@ -83,8 +86,8 @@ class CanonicalModel(val ontology: RSAOntology) { | |||
| 83 | ) | 86 | ) |
| 84 | ) | 87 | ) |
| 85 | yield Rule.create( | 88 | yield Rule.create( |
| 86 | TupleTableAtom.rdf(varX, iri :: hSuffix, varY), | 89 | TupleTableAtom.create(tt, varX, iri :: hSuffix, varY), |
| 87 | TupleTableAtom.rdf(varX, iri :: bSuffix, varY) | 90 | TupleTableAtom.create(tt, varX, iri :: bSuffix, varY) |
| 88 | ) | 91 | ) |
| 89 | }) | 92 | }) |
| 90 | } | 93 | } |
| @@ -108,6 +111,8 @@ class CanonicalModel(val ontology: RSAOntology) { | |||
| 108 | 111 | ||
| 109 | object CanonicalModelConverter extends RDFoxConverter { | 112 | object CanonicalModelConverter extends RDFoxConverter { |
| 110 | 113 | ||
| 114 | override val graph = TupleTableName.create(CanonicalModel.this.graph.getIRI) | ||
| 115 | |||
| 111 | private def rules1( | 116 | private def rules1( |
| 112 | axiom: OWLSubClassOfAxiom | 117 | axiom: OWLSubClassOfAxiom |
| 113 | ): Result = { | 118 | ): Result = { |
| @@ -115,11 +120,10 @@ class CanonicalModel(val ontology: RSAOntology) { | |||
| 115 | // Fresh Variables | 120 | // Fresh Variables |
| 116 | val v0 = RSA("v0_" ++ axiom.hashed) | 121 | val v0 = RSA("v0_" ++ axiom.hashed) |
| 117 | val varX = Variable.create("X") | 122 | val varX = Variable.create("X") |
| 118 | implicit val unfoldTerm = RSA(unfold.hashCode.toString) | ||
| 119 | // TODO: use axiom.toTriple instead | 123 | // TODO: use axiom.toTriple instead |
| 120 | val atomA: TupleTableAtom = { | 124 | val atomA: TupleTableAtom = { |
| 121 | val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI | 125 | val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI |
| 122 | TupleTableAtom.rdf(varX, IRI.RDF_TYPE, cls) | 126 | TupleTableAtom.create(graph, varX, IRI.RDF_TYPE, cls) |
| 123 | } | 127 | } |
| 124 | val roleRf: TupleTableAtom = { | 128 | val roleRf: TupleTableAtom = { |
| 125 | val prop = | 129 | val prop = |
| @@ -132,12 +136,15 @@ class CanonicalModel(val ontology: RSAOntology) { | |||
| 132 | .getFiller | 136 | .getFiller |
| 133 | .asInstanceOf[OWLClass] | 137 | .asInstanceOf[OWLClass] |
| 134 | .getIRI | 138 | .getIRI |
| 135 | TupleTableAtom.rdf(v0, IRI.RDF_TYPE, cls) | 139 | TupleTableAtom.create(graph, v0, IRI.RDF_TYPE, cls) |
| 136 | } | 140 | } |
| 137 | val facts = unfold map RSA.In | 141 | val unfoldSet = RSA(unfold.hashCode.toString) |
| 142 | val facts = unfold.map(TupleTableAtom.create(graph, _, RSA.IN, unfoldSet)) | ||
| 143 | val notInX = | ||
| 144 | Negation.create(TupleTableAtom.create(graph, varX, RSA.IN, unfoldSet)) | ||
| 138 | val rules = List( | 145 | val rules = List( |
| 139 | Rule.create(roleRf, atomA, RSA.NotIn(varX)), | 146 | Rule.create(roleRf, atomA, notInX), |
| 140 | Rule.create(atomB, atomA, RSA.NotIn(varX)) | 147 | Rule.create(atomB, atomA, notInX) |
| 141 | ) | 148 | ) |
| 142 | (facts, rules) | 149 | (facts, rules) |
| 143 | } | 150 | } |
| @@ -155,7 +162,7 @@ class CanonicalModel(val ontology: RSAOntology) { | |||
| 155 | // Predicates | 162 | // Predicates |
| 156 | def atomA(t: Term): TupleTableAtom = { | 163 | def atomA(t: Term): TupleTableAtom = { |
| 157 | val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI | 164 | val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI |
| 158 | TupleTableAtom.rdf(t, IRI.RDF_TYPE, cls) | 165 | TupleTableAtom.create(graph, t, IRI.RDF_TYPE, cls) |
| 159 | } | 166 | } |
| 160 | def roleRf(t1: Term, t2: Term): TupleTableAtom = | 167 | def roleRf(t1: Term, t2: Term): TupleTableAtom = |
| 161 | super.convert(roleR, t1, t2, Forward) | 168 | super.convert(roleR, t1, t2, Forward) |
| @@ -165,7 +172,7 @@ class CanonicalModel(val ontology: RSAOntology) { | |||
| 165 | .getFiller | 172 | .getFiller |
| 166 | .asInstanceOf[OWLClass] | 173 | .asInstanceOf[OWLClass] |
| 167 | .getIRI | 174 | .getIRI |
| 168 | TupleTableAtom.rdf(t, IRI.RDF_TYPE, cls) | 175 | TupleTableAtom.create(graph, t, IRI.RDF_TYPE, cls) |
| 169 | } | 176 | } |
| 170 | //Rules | 177 | //Rules |
| 171 | List( | 178 | List( |
| @@ -190,7 +197,7 @@ class CanonicalModel(val ontology: RSAOntology) { | |||
| 190 | // Predicates | 197 | // Predicates |
| 191 | def atomA(t: Term): TupleTableAtom = { | 198 | def atomA(t: Term): TupleTableAtom = { |
| 192 | val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI | 199 | val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI |
| 193 | TupleTableAtom.rdf(t, IRI.RDF_TYPE, cls) | 200 | TupleTableAtom.create(graph, t, IRI.RDF_TYPE, cls) |
| 194 | } | 201 | } |
| 195 | def roleRf(t: Term): TupleTableAtom = | 202 | def roleRf(t: Term): TupleTableAtom = |
| 196 | super.convert(roleR, t, v1, Forward) | 203 | super.convert(roleR, t, v1, Forward) |
| @@ -200,7 +207,7 @@ class CanonicalModel(val ontology: RSAOntology) { | |||
| 200 | .getFiller | 207 | .getFiller |
| 201 | .asInstanceOf[OWLClass] | 208 | .asInstanceOf[OWLClass] |
| 202 | .getIRI | 209 | .getIRI |
| 203 | TupleTableAtom.rdf(v1, IRI.RDF_TYPE, cls) | 210 | TupleTableAtom.create(graph, v1, IRI.RDF_TYPE, cls) |
| 204 | } | 211 | } |
| 205 | cycle.flatMap { x => | 212 | cycle.flatMap { x => |
| 206 | List( | 213 | List( |
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 6e9a119..5a89bf9 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala | |||
| @@ -48,6 +48,7 @@ import tech.oxfordsemantic.jrdfox.Prefixes | |||
| 48 | import tech.oxfordsemantic.jrdfox.logic.datalog.{ | 48 | import tech.oxfordsemantic.jrdfox.logic.datalog.{ |
| 49 | Rule, | 49 | Rule, |
| 50 | TupleTableAtom, | 50 | TupleTableAtom, |
| 51 | TupleTableName, | ||
| 51 | Negation, | 52 | Negation, |
| 52 | BodyFormula | 53 | BodyFormula |
| 53 | } | 54 | } |
| @@ -91,6 +92,20 @@ object RSAOntology { | |||
| 91 | /** Name of the RDFox data store used for CQ answering */ | 92 | /** Name of the RDFox data store used for CQ answering */ |
| 92 | private val DataStore = "answer_computation" | 93 | private val DataStore = "answer_computation" |
| 93 | 94 | ||
| 95 | /** Canonical model named graph */ | ||
| 96 | private val CanonGraph: IRI = | ||
| 97 | RDFoxUtil.getNamedGraph(DataStore, "CanonicalModel") | ||
| 98 | |||
| 99 | /** Filtering program named graph | ||
| 100 | * | ||
| 101 | * @param query query associated with the returned named graph. | ||
| 102 | * | ||
| 103 | * @return named graph for the filtering program associated with the | ||
| 104 | * input query. | ||
| 105 | */ | ||
| 106 | private def FilterGraph(query: ConjunctiveQuery): IRI = | ||
| 107 | RDFoxUtil.getNamedGraph(DataStore, s"Filter${query.id}") | ||
| 108 | |||
| 94 | /** Filtering program for a given query | 109 | /** Filtering program for a given query |
| 95 | * | 110 | * |
| 96 | * @param query the query to derive the filtering program | 111 | * @param query the query to derive the filtering program |
| @@ -343,11 +358,12 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File]) | |||
| 343 | private val topAxioms: List[Rule] = { | 358 | private val topAxioms: List[Rule] = { |
| 344 | val varX = Variable.create("X") | 359 | val varX = Variable.create("X") |
| 345 | val varY = Variable.create("Y") | 360 | val varY = Variable.create("Y") |
| 361 | val graph = TupleTableName.create(RSAOntology.CanonGraph.getIRI) | ||
| 346 | concepts | 362 | concepts |
| 347 | .map(c => { | 363 | .map(c => { |
| 348 | Rule.create( | 364 | Rule.create( |
| 349 | RSA.Thing(varX), | 365 | TupleTableAtom.create(graph, varX, IRI.RDF_TYPE, IRI.THING), |
| 350 | TupleTableAtom.rdf(varX, IRI.RDF_TYPE, c.getIRI) | 366 | TupleTableAtom.create(graph, varX, IRI.RDF_TYPE, c.getIRI) |
| 351 | ) | 367 | ) |
| 352 | }) ++ roles.map(r => { | 368 | }) ++ roles.map(r => { |
| 353 | val name = r match { | 369 | val name = r match { |
| @@ -356,8 +372,11 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File]) | |||
| 356 | x.getInverse.getNamedProperty.getIRI.getIRIString :: Inverse | 372 | x.getInverse.getNamedProperty.getIRI.getIRIString :: Inverse |
| 357 | } | 373 | } |
| 358 | Rule.create( | 374 | Rule.create( |
| 359 | List(RSA.Thing(varX), RSA.Thing(varY)), | 375 | List( |
| 360 | List(TupleTableAtom.rdf(varX, name, varY)) | 376 | TupleTableAtom.create(graph, varX, IRI.RDF_TYPE, IRI.THING), |
| 377 | TupleTableAtom.create(graph, varY, IRI.RDF_TYPE, IRI.THING) | ||
| 378 | ), | ||
| 379 | List(TupleTableAtom.create(graph, varX, name, varY)) | ||
| 361 | ) | 380 | ) |
| 362 | }) | 381 | }) |
| 363 | } | 382 | } |
| @@ -382,23 +401,31 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File]) | |||
| 382 | val varX = Variable.create("X") | 401 | val varX = Variable.create("X") |
| 383 | val varY = Variable.create("Y") | 402 | val varY = Variable.create("Y") |
| 384 | val varZ = Variable.create("Z") | 403 | val varZ = Variable.create("Z") |
| 385 | List( | 404 | val graph = TupleTableName.create(RSAOntology.CanonGraph.getIRI) |
| 405 | // Equality properties | ||
| 406 | val properties = List( | ||
| 386 | // Reflexivity | 407 | // Reflexivity |
| 387 | Rule.create(RSA.Congruent(varX, varX), RSA.Thing(varX)), | 408 | Rule.create( |
| 409 | TupleTableAtom.create(graph, varX, RSA.CONGRUENT, varX), | ||
| 410 | TupleTableAtom.create(graph, varX, IRI.RDF_TYPE, IRI.THING) | ||
| 411 | ), | ||
| 388 | // Simmetry | 412 | // Simmetry |
| 389 | Rule.create(RSA.Congruent(varY, varX), RSA.Congruent(varX, varY)), | 413 | Rule.create( |
| 414 | TupleTableAtom.create(graph, varY, RSA.CONGRUENT, varX), | ||
| 415 | TupleTableAtom.create(graph, varX, RSA.CONGRUENT, varY) | ||
| 416 | ), | ||
| 390 | // Transitivity | 417 | // Transitivity |
| 391 | Rule.create( | 418 | Rule.create( |
| 392 | RSA.Congruent(varX, varZ), | 419 | TupleTableAtom.create(graph, varX, RSA.CONGRUENT, varZ), |
| 393 | RSA.Congruent(varX, varY), | 420 | TupleTableAtom.create(graph, varX, RSA.CONGRUENT, varY), |
| 394 | RSA.Congruent(varY, varZ) | 421 | TupleTableAtom.create(graph, varY, RSA.CONGRUENT, varZ) |
| 395 | ) | 422 | ) |
| 396 | ) | 423 | ) |
| 397 | } | 424 | } |
| 398 | 425 | ||
| 399 | /** Canonical model of the ontology */ | 426 | /** Canonical model of the ontology */ |
| 400 | lazy val canonicalModel = Logger.timed( | 427 | lazy val canonicalModel = Logger.timed( |
| 401 | new CanonicalModel(this), | 428 | new CanonicalModel(this, RSAOntology.CanonGraph), |
| 402 | "Generating canonical model program", | 429 | "Generating canonical model program", |
| 403 | Logger.DEBUG | 430 | Logger.DEBUG |
| 404 | ) | 431 | ) |
| @@ -505,19 +532,18 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File]) | |||
| 505 | * @return a collection of answers for each query. | 532 | * @return a collection of answers for each query. |
| 506 | */ | 533 | */ |
| 507 | def ask(queries: Seq[ConjunctiveQuery]): Seq[ConjunctiveQueryAnswers] = { | 534 | def ask(queries: Seq[ConjunctiveQuery]): Seq[ConjunctiveQueryAnswers] = { |
| 535 | /* Open connection with RDFox server */ | ||
| 508 | val (server, data) = RDFoxUtil.openConnection(RSAOntology.DataStore) | 536 | val (server, data) = RDFoxUtil.openConnection(RSAOntology.DataStore) |
| 509 | val canonNamedGraph = "http://cs.ox.ac.uk/isg/RSAComb#CanonicalModel" | ||
| 510 | // Create a new NamedGraph for the canonical model | ||
| 511 | data.createTupleTable(canonNamedGraph, Map("type" -> "named-graph").asJava) | ||
| 512 | 537 | ||
| 513 | /* Upload data from data file */ | 538 | /* Upload data from data file */ |
| 514 | RDFoxUtil.addData(canonNamedGraph, data, datafiles: _*) | 539 | RDFoxUtil.addData(data, RSAOntology.CanonGraph, datafiles: _*) |
| 515 | /* Top / equality axiomatization */ | 540 | /* Top / equality axiomatization */ |
| 516 | RDFoxUtil.addRules(data, topAxioms ++ equalityAxioms) | 541 | RDFoxUtil.addRules(data, topAxioms ++ equalityAxioms) |
| 517 | /* Generate `named` predicates */ | 542 | /* Generate `named` predicates */ |
| 543 | // TODO: do I need both to generate all NAMED atoms? | ||
| 518 | RDFoxUtil.addFacts( | 544 | RDFoxUtil.addFacts( |
| 519 | canonNamedGraph, | ||
| 520 | data, | 545 | data, |
| 546 | RSAOntology.CanonGraph, | ||
| 521 | (individuals ++ literals) map RSA.Named | 547 | (individuals ++ literals) map RSA.Named |
| 522 | ) | 548 | ) |
| 523 | data.evaluateUpdate( | 549 | data.evaluateUpdate( |
| @@ -525,9 +551,9 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File]) | |||
| 525 | RSA.Prefixes, | 551 | RSA.Prefixes, |
| 526 | s""" | 552 | s""" |
| 527 | INSERT { | 553 | INSERT { |
| 528 | GRAPH <$canonNamedGraph> { ?X a rsa:Named } | 554 | GRAPH ${RSAOntology.CanonGraph} { ?X a ${RSA.NAMED} } |
| 529 | } WHERE { | 555 | } WHERE { |
| 530 | GRAPH <$canonNamedGraph> { ?X a owl:Thing } | 556 | GRAPH ${RSAOntology.CanonGraph} { ?X a ${IRI.THING} } |
| 531 | } | 557 | } |
| 532 | """, | 558 | """, |
| 533 | new java.util.HashMap[String, String] | 559 | new java.util.HashMap[String, String] |
| @@ -538,7 +564,7 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File]) | |||
| 538 | RDFoxUtil.addRules(data, this.canonicalModel.rules) | 564 | RDFoxUtil.addRules(data, this.canonicalModel.rules) |
| 539 | 565 | ||
| 540 | Logger print s"Canonical model facts: ${this.canonicalModel.facts.length}" | 566 | Logger print s"Canonical model facts: ${this.canonicalModel.facts.length}" |
| 541 | RDFoxUtil.addFacts(canonNamedGraph, data, this.canonicalModel.facts) | 567 | RDFoxUtil.addFacts(data, RSAOntology.CanonGraph, this.canonicalModel.facts) |
| 542 | 568 | ||
| 543 | queries map { query => | 569 | queries map { query => |
| 544 | { | 570 | { |
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/converter/RDFoxConverter.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/converter/RDFoxConverter.scala index 276ee1a..2f48798 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/converter/RDFoxConverter.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/converter/RDFoxConverter.scala | |||
| @@ -24,7 +24,8 @@ import tech.oxfordsemantic.jrdfox.logic.datalog.{ | |||
| 24 | BindAtom, | 24 | BindAtom, |
| 25 | BodyFormula, | 25 | BodyFormula, |
| 26 | Rule, | 26 | Rule, |
| 27 | TupleTableAtom | 27 | TupleTableAtom, |
| 28 | TupleTableName | ||
| 28 | } | 29 | } |
| 29 | import tech.oxfordsemantic.jrdfox.logic.expression.{Term, IRI, FunctionCall} | 30 | import tech.oxfordsemantic.jrdfox.logic.expression.{Term, IRI, FunctionCall} |
| 30 | import uk.ac.ox.cs.rsacomb.RSAOntology | 31 | import uk.ac.ox.cs.rsacomb.RSAOntology |
| @@ -59,6 +60,10 @@ trait RDFoxConverter { | |||
| 59 | private val manager = OWLManager.createOWLOntologyManager() | 60 | private val manager = OWLManager.createOWLOntologyManager() |
| 60 | private val factory = manager.getOWLDataFactory() | 61 | private val factory = manager.getOWLDataFactory() |
| 61 | 62 | ||
| 63 | /** Default named graph to be used when generating new atoms */ | ||
| 64 | val graph: TupleTableName = | ||
| 65 | TupleTableName.create("http://oxfordsemantic.tech/RDFox#DefaultTriples") | ||
| 66 | |||
| 62 | /** Represents the result of the conversion of a | 67 | /** Represents the result of the conversion of a |
| 63 | * [[org.semanticweb.owlapi.model.OWLClassExpression OWLClassExpression]]. | 68 | * [[org.semanticweb.owlapi.model.OWLClassExpression OWLClassExpression]]. |
| 64 | * | 69 | * |
| @@ -193,7 +198,8 @@ trait RDFoxConverter { | |||
| 193 | .flatMap((cls) => | 198 | .flatMap((cls) => |
| 194 | convert(cls, term, unsafe, NoSkolem, suffix)(fresh)._1 | 199 | convert(cls, term, unsafe, NoSkolem, suffix)(fresh)._1 |
| 195 | ) | 200 | ) |
| 196 | val bottom = TupleTableAtom.rdf(term, IRI.RDF_TYPE, IRI.NOTHING) | 201 | val bottom = |
| 202 | TupleTableAtom.create(graph, term, IRI.RDF_TYPE, IRI.NOTHING) | ||
| 197 | ResultR(List(Rule.create(bottom, body: _*))) | 203 | ResultR(List(Rule.create(bottom, body: _*))) |
| 198 | } | 204 | } |
| 199 | 205 | ||
| @@ -310,7 +316,7 @@ trait RDFoxConverter { | |||
| 310 | */ | 316 | */ |
| 311 | case e: OWLClass => { | 317 | case e: OWLClass => { |
| 312 | val iri: IRI = if (e.isTopEntity()) IRI.THING else e.getIRI | 318 | val iri: IRI = if (e.isTopEntity()) IRI.THING else e.getIRI |
| 313 | val atom = TupleTableAtom.rdf(term, IRI.RDF_TYPE, iri) | 319 | val atom = TupleTableAtom.create(graph, term, IRI.RDF_TYPE, iri) |
| 314 | (List(atom), List()) | 320 | (List(atom), List()) |
| 315 | } | 321 | } |
| 316 | 322 | ||
| @@ -340,7 +346,8 @@ trait RDFoxConverter { | |||
| 340 | .collect { case x: OWLNamedIndividual => x } | 346 | .collect { case x: OWLNamedIndividual => x } |
| 341 | if (named.length != 1) | 347 | if (named.length != 1) |
| 342 | throw new RuntimeException(s"Class expression '$e' has arity != 1.") | 348 | throw new RuntimeException(s"Class expression '$e' has arity != 1.") |
| 343 | val atom = RSA.Congruent(term, named.head.getIRI) | 349 | val atom = |
| 350 | TupleTableAtom.create(graph, term, RSA.CONGRUENT, named.head.getIRI) | ||
| 344 | (List(atom), List()) | 351 | (List(atom), List()) |
| 345 | } | 352 | } |
| 346 | 353 | ||
| @@ -412,7 +419,7 @@ trait RDFoxConverter { | |||
| 412 | val (res, ext) = | 419 | val (res, ext) = |
| 413 | vars.map(convert(cls, _, unsafe, skolem, suffix)(fresh)).unzip | 420 | vars.map(convert(cls, _, unsafe, skolem, suffix)(fresh)).unzip |
| 414 | val props = vars.map(convert(role, term, _, suffix)(fresh)) | 421 | val props = vars.map(convert(role, term, _, suffix)(fresh)) |
| 415 | val eq = RSA.Congruent(y, z) | 422 | val eq = TupleTableAtom.create(graph, y, RSA.CONGRUENT, z) |
| 416 | (List(eq), res.flatten ++ props) | 423 | (List(eq), res.flatten ++ props) |
| 417 | } | 424 | } |
| 418 | 425 | ||
| @@ -515,7 +522,7 @@ trait RDFoxConverter { | |||
| 515 | */ | 522 | */ |
| 516 | case e: OWLObjectProperty => { | 523 | case e: OWLObjectProperty => { |
| 517 | val role = IRI.create(e.getIRI.getIRIString :: suffix) | 524 | val role = IRI.create(e.getIRI.getIRIString :: suffix) |
| 518 | TupleTableAtom.rdf(term1, role, term2) | 525 | TupleTableAtom.create(graph, term1, role, term2) |
| 519 | } | 526 | } |
| 520 | 527 | ||
| 521 | /** Inverse of a named role/property | 528 | /** Inverse of a named role/property |
| @@ -555,7 +562,7 @@ trait RDFoxConverter { | |||
| 555 | */ | 562 | */ |
| 556 | case e: OWLDataProperty => { | 563 | case e: OWLDataProperty => { |
| 557 | val role = IRI.create(e.getIRI.getIRIString :: suffix) | 564 | val role = IRI.create(e.getIRI.getIRIString :: suffix) |
| 558 | TupleTableAtom.rdf(term1, role, term2) | 565 | TupleTableAtom.create(graph, term1, role, term2) |
| 559 | } | 566 | } |
| 560 | 567 | ||
| 561 | /** The infamous impossible case. | 568 | /** The infamous impossible case. |
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RSAAtom.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RSAAtom.scala index 795e039..ff48f1f 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RSAAtom.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RSAAtom.scala | |||
| @@ -51,19 +51,14 @@ object RSAAtom { | |||
| 51 | import RDFox._ | 51 | import RDFox._ |
| 52 | import JavaCollections._ | 52 | import JavaCollections._ |
| 53 | 53 | ||
| 54 | val name: String = atom.getTupleTableName.getName | 54 | val tt: TupleTableName = atom.getTupleTableName |
| 55 | 55 | ||
| 56 | val args: List[Term] = atom.getArguments | 56 | val args: List[Term] = atom.getArguments |
| 57 | 57 | ||
| 58 | val isRDF: Boolean = | 58 | val isRDF: Boolean = atom.getArguments.length == 3 |
| 59 | name == "http://oxfordsemantic.tech/RDFox#DefaultTriples" | ||
| 60 | 59 | ||
| 61 | val isClassAssertion: Boolean = { | 60 | val isClassAssertion: Boolean = |
| 62 | isRDF && { | 61 | isRDF && atom.getArguments.get(1) == IRI.RDF_TYPE |
| 63 | val pred = atom.getArguments.get(1) | ||
| 64 | pred == IRI.RDF_TYPE | ||
| 65 | } | ||
| 66 | } | ||
| 67 | 62 | ||
| 68 | val isRoleAssertion: Boolean = isRDF && !isClassAssertion | 63 | val isRoleAssertion: Boolean = isRDF && !isClassAssertion |
| 69 | 64 | ||
| @@ -77,18 +72,15 @@ object RSAAtom { | |||
| 77 | case iri: IRI => IRI.create(iri.getIRI :: suffix) | 72 | case iri: IRI => IRI.create(iri.getIRI :: suffix) |
| 78 | case other => other | 73 | case other => other |
| 79 | } | 74 | } |
| 80 | TupleTableAtom.rdf(subj, pred, obj1) | 75 | TupleTableAtom.create(tt, subj, pred, obj1) |
| 81 | } else { | 76 | } else { |
| 82 | val pred1 = pred match { | 77 | val pred1 = pred match { |
| 83 | case iri: IRI => IRI.create(iri.getIRI :: suffix) | 78 | case iri: IRI => IRI.create(iri.getIRI :: suffix) |
| 84 | case other => other | 79 | case other => other |
| 85 | } | 80 | } |
| 86 | TupleTableAtom.rdf(subj, pred1, obj) | 81 | TupleTableAtom.create(tt, subj, pred1, obj) |
| 87 | } | 82 | } |
| 88 | } else { | 83 | } else atom |
| 89 | val ttname = TupleTableName.create(name :: suffix) | ||
| 90 | TupleTableAtom.create(ttname, atom.getArguments()) | ||
| 91 | } | ||
| 92 | 84 | ||
| 93 | def reified(implicit | 85 | def reified(implicit |
| 94 | fresh: DataFactory | 86 | fresh: DataFactory |
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 6f5ff31..568858c 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 | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | package uk.ac.ox.cs.rsacomb.util | 17 | package uk.ac.ox.cs.rsacomb.util |
| 18 | 18 | ||
| 19 | import java.io.{OutputStream, File, StringReader} | 19 | import java.io.{OutputStream, File, StringReader} |
| 20 | import scala.collection.JavaConverters._ | ||
| 20 | import tech.oxfordsemantic.jrdfox.Prefixes | 21 | import tech.oxfordsemantic.jrdfox.Prefixes |
| 21 | import tech.oxfordsemantic.jrdfox.client.{ | 22 | import tech.oxfordsemantic.jrdfox.client.{ |
| 22 | ComponentInfo, | 23 | ComponentInfo, |
| @@ -38,7 +39,8 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{ | |||
| 38 | Literal, | 39 | Literal, |
| 39 | Resource, | 40 | Resource, |
| 40 | Variable, | 41 | Variable, |
| 41 | Term | 42 | Term, |
| 43 | IRI | ||
| 42 | } | 44 | } |
| 43 | import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery | 45 | import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery |
| 44 | import uk.ac.ox.cs.rsacomb.sparql.ConjunctiveQuery | 46 | import uk.ac.ox.cs.rsacomb.sparql.ConjunctiveQuery |
| @@ -92,6 +94,22 @@ object RDFoxUtil { | |||
| 92 | (server, data) | 94 | (server, data) |
| 93 | } | 95 | } |
| 94 | 96 | ||
| 97 | /** Get the IRI of a named graph (creating it if necessary) | ||
| 98 | * | ||
| 99 | * @param datastore name of the datastore to perform the action in. | ||
| 100 | * @param name name of the named graph. | ||
| 101 | * | ||
| 102 | * @return the full IRI for the (new) named graph. | ||
| 103 | */ | ||
| 104 | def getNamedGraph(datastore: String, name: String): IRI = { | ||
| 105 | val graph = RSA(name) | ||
| 106 | val (server, data) = openConnection(datastore) | ||
| 107 | if (!data.containsTupleTable(graph.getIRI)) | ||
| 108 | data.createTupleTable(graph.getIRI, Map("type" -> "named-graph").asJava) | ||
| 109 | RDFoxUtil.closeConnection(server, data) | ||
| 110 | return graph | ||
| 111 | } | ||
| 112 | |||
| 95 | /** Create a built-in `rdfox:SKOLEM` TupleTableAtom. */ | 113 | /** Create a built-in `rdfox:SKOLEM` TupleTableAtom. */ |
| 96 | def skolem(name: String, terms: Term*): TupleTableAtom = | 114 | def skolem(name: String, terms: Term*): TupleTableAtom = |
| 97 | TupleTableAtom.create( | 115 | TupleTableAtom.create( |
| @@ -143,14 +161,14 @@ object RDFoxUtil { | |||
| 143 | * @param facts collection of facts to be added to the data store | 161 | * @param facts collection of facts to be added to the data store |
| 144 | */ | 162 | */ |
| 145 | def addFacts( | 163 | def addFacts( |
| 146 | graph: String, | ||
| 147 | data: DataStoreConnection, | 164 | data: DataStoreConnection, |
| 165 | graph: IRI, | ||
| 148 | facts: Seq[TupleTableAtom] | 166 | facts: Seq[TupleTableAtom] |
| 149 | ): Unit = | 167 | ): Unit = |
| 150 | Logger.timed( | 168 | Logger.timed( |
| 151 | if (facts.length > 0) { | 169 | if (facts.length > 0) { |
| 152 | data.importData( | 170 | data.importData( |
| 153 | graph, | 171 | graph.getIRI, |
| 154 | UpdateType.ADDITION, | 172 | UpdateType.ADDITION, |
| 155 | RSA.Prefixes, | 173 | RSA.Prefixes, |
| 156 | facts | 174 | facts |
| @@ -165,12 +183,13 @@ object RDFoxUtil { | |||
| 165 | /** Imports a sequence of files directly into a datastore. | 183 | /** Imports a sequence of files directly into a datastore. |
| 166 | * | 184 | * |
| 167 | * @param data datastore connection. | 185 | * @param data datastore connection. |
| 186 | * @param graph named graph where the data should be uploaded | ||
| 168 | * @param files sequence of files to upload. | 187 | * @param files sequence of files to upload. |
| 169 | */ | 188 | */ |
| 170 | def addData(graph: String, data: DataStoreConnection, files: File*): Unit = | 189 | def addData(data: DataStoreConnection, graph: IRI, files: File*): Unit = |
| 171 | Logger.timed( | 190 | Logger.timed( |
| 172 | files.foreach { | 191 | files.foreach { |
| 173 | data.importData(graph, UpdateType.ADDITION, RSA.Prefixes, _) | 192 | data.importData(graph.getIRI, UpdateType.ADDITION, RSA.Prefixes, _) |
| 174 | }, | 193 | }, |
| 175 | "Loading data files", | 194 | "Loading data files", |
| 176 | Logger.DEBUG | 195 | Logger.DEBUG |
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/util/RSA.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/util/RSA.scala index 8b341ba..96d3aa8 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/util/RSA.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/util/RSA.scala | |||
| @@ -42,32 +42,29 @@ import scala.collection.JavaConverters._ | |||
| 42 | 42 | ||
| 43 | object RSA { | 43 | object RSA { |
| 44 | 44 | ||
| 45 | /** Set of default prefixes to be included in all datastore operations */ | ||
| 45 | val Prefixes: Prefixes = new Prefixes() | 46 | val Prefixes: Prefixes = new Prefixes() |
| 46 | Prefixes.declarePrefix("rsa:", "http://www.cs.ox.ac.uk/isg/rsa/") | 47 | Prefixes.declarePrefix("rsacomb:", "http://www.cs.ox.ac.uk/isg/RSAComb#") |
| 48 | Prefixes.declarePrefix("rdfox:", "http://oxfordsemantic.tech/RDFox#") | ||
| 47 | Prefixes.declarePrefix("owl:", "http://www.w3.org/2002/07/owl#") | 49 | Prefixes.declarePrefix("owl:", "http://www.w3.org/2002/07/owl#") |
| 48 | 50 | ||
| 49 | val CONGRUENT = RSA("congruent") | 51 | /** Creates a `rsacomb:<name>` IRI */ |
| 50 | val NAMED = RSA("Named") | 52 | def apply(name: Any): IRI = |
| 51 | 53 | IRI.create( | |
| 52 | private def atom(name: IRI, vars: List[Term]): TupleTableAtom = | 54 | Prefixes.getPrefixIRIsByPrefixName.get("rsacomb:").getIRI + name.toString |
| 53 | TupleTableAtom.create(TupleTableName.create(name.getIRI), vars: _*) | 55 | ) |
| 54 | |||
| 55 | def E(t1: Term, t2: Term) = | ||
| 56 | TupleTableAtom.rdf(t1, RSA("E"), t2) | ||
| 57 | |||
| 58 | def PE(t1: Term, t2: Term) = | ||
| 59 | TupleTableAtom.rdf(t1, RSA("PE"), t2) | ||
| 60 | 56 | ||
| 61 | def U(t: Term) = | 57 | val NAMED = RSA("Named") |
| 62 | TupleTableAtom.rdf(t, IRI.RDF_TYPE, RSA("U")) | 58 | val CONGRUENT = RSA("congruent") |
| 59 | val IN = RSA("In") | ||
| 63 | 60 | ||
| 64 | def In(t: Term)(implicit set: Term) = | 61 | // def In(t: Term)(implicit set: Term) = |
| 65 | TupleTableAtom.rdf(t, RSA("In"), set) | 62 | // TupleTableAtom.rdf(t, RSA("In"), set) |
| 66 | 63 | ||
| 67 | def NotIn(t: Term)(implicit set: Term) = Negation.create(In(t)(set)) | 64 | // def NotIn(t: Term)(implicit set: Term) = Negation.create(In(t)(set)) |
| 68 | 65 | ||
| 69 | def Congruent(t1: Term, t2: Term) = | 66 | // def Congruent(t1: Term, t2: Term) = |
| 70 | TupleTableAtom.rdf(t1, RSA("congruent"), t2) | 67 | // TupleTableAtom.rdf(t1, RSA("congruent"), t2) |
| 71 | 68 | ||
| 72 | def QM(implicit q: ConjunctiveQuery) = | 69 | def QM(implicit q: ConjunctiveQuery) = |
| 73 | atom(RSA("QM"), q.answer ::: q.bounded) | 70 | atom(RSA("QM"), q.answer ::: q.bounded) |
| @@ -104,8 +101,18 @@ object RSA { | |||
| 104 | atom(RSA("Ans"), q.answer) | 101 | atom(RSA("Ans"), q.answer) |
| 105 | } | 102 | } |
| 106 | 103 | ||
| 107 | def apply(name: Any): IRI = | 104 | /* TODO: review after reworking the dependency graph construction */ |
| 108 | IRI.create( | 105 | |
| 109 | Prefixes.getPrefixIRIsByPrefixName.get("rsa:").getIRI + name.toString | 106 | // private def atom(name: IRI, vars: List[Term]): TupleTableAtom = |
| 110 | ) | 107 | // TupleTableAtom.create(TupleTableName.create(name.getIRI), vars: _*) |
| 108 | |||
| 109 | def E(t1: Term, t2: Term) = | ||
| 110 | TupleTableAtom.rdf(t1, RSA("E"), t2) | ||
| 111 | |||
| 112 | def PE(t1: Term, t2: Term) = | ||
| 113 | TupleTableAtom.rdf(t1, RSA("PE"), t2) | ||
| 114 | |||
| 115 | def U(t: Term) = | ||
| 116 | TupleTableAtom.rdf(t, IRI.RDF_TYPE, RSA("U")) | ||
| 117 | |||
| 111 | } | 118 | } |
