diff options
author | Federico Igne <federico.igne@cs.ox.ac.uk> | 2021-01-26 14:31:43 +0000 |
---|---|---|
committer | Federico Igne <federico.igne@cs.ox.ac.uk> | 2021-01-26 14:34:37 +0000 |
commit | 87b180f1de0e1c30a4624e546825b77c2edf9bbe (patch) | |
tree | 8cf5cbb5651548c156f3d5b6d600101f0255de97 | |
parent | a3b33898b4a595c212fffb66b89cf573adbfe69d (diff) | |
download | RSAComb-87b180f1de0e1c30a4624e546825b77c2edf9bbe.tar.gz RSAComb-87b180f1de0e1c30a4624e546825b77c2edf9bbe.zip |
Simplify top axiomatization as shown in #7
-rw-r--r-- | src/main/scala/uk/ac/ox/cs/rsacomb/CanonicalModel.scala | 127 |
1 files changed, 84 insertions, 43 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 5001c8a..96a953f 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/CanonicalModel.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/CanonicalModel.scala | |||
@@ -24,68 +24,109 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{ | |||
24 | IRI | 24 | IRI |
25 | } | 25 | } |
26 | 26 | ||
27 | import implicits.JavaCollections._ | ||
28 | |||
27 | import uk.ac.ox.cs.rsacomb.converter._ | 29 | import uk.ac.ox.cs.rsacomb.converter._ |
28 | import uk.ac.ox.cs.rsacomb.suffix._ | 30 | import uk.ac.ox.cs.rsacomb.suffix._ |
29 | import uk.ac.ox.cs.rsacomb.util.RSA | 31 | import uk.ac.ox.cs.rsacomb.util.RSA |
30 | 32 | ||
33 | /** Canonical model generator | ||
34 | * | ||
35 | * Converts the input axioms in a given ontology into logic rules that | ||
36 | * can then be passed to RDFox to compute the actual canonical model | ||
37 | * (via materialization). | ||
38 | * | ||
39 | * @param ontology the RSA ontology the canonical model is targeting. | ||
40 | */ | ||
31 | class CanonicalModel(val ontology: RSAOntology) { | 41 | class CanonicalModel(val ontology: RSAOntology) { |
32 | 42 | ||
43 | /** Simplify conversion between OWLAPI and RDFox concepts */ | ||
33 | import implicits.RDFox._ | 44 | import implicits.RDFox._ |
34 | import implicits.JavaCollections._ | 45 | |
46 | /** Extends capabilities of | ||
47 | * [[tech.oxfordsemantic.jrdfox.logic.datalog.TupleTableAtom TupleTableAtom]] | ||
48 | */ | ||
35 | import uk.ac.ox.cs.rsacomb.implicits.RSAAxiom._ | 49 | import uk.ac.ox.cs.rsacomb.implicits.RSAAxiom._ |
36 | 50 | ||
51 | /** Introduce additional rules for each role. | ||
52 | * | ||
53 | * Some relations between roles and their inverse or their "suffixed" | ||
54 | * versions need to be explicitly stated in terms of logic rules. | ||
55 | */ | ||
37 | val rolesAdditionalRules: List[Rule] = { | 56 | val rolesAdditionalRules: List[Rule] = { |
38 | // Given a role (predicate) compute additional logic rules | ||
39 | def additional(pred: String): Seq[Rule] = { | ||
40 | val varX = Variable.create("X") | ||
41 | val varY = Variable.create("Y") | ||
42 | for ( | ||
43 | (hSuffix, bSuffix) <- List( | ||
44 | (Empty, Forward), | ||
45 | (Empty, Backward), | ||
46 | (Inverse, Forward + Inverse), | ||
47 | (Inverse, Backward + Inverse), | ||
48 | (Backward + Inverse, Forward), | ||
49 | (Forward + Inverse, Backward), | ||
50 | (Backward, Forward + Inverse), | ||
51 | (Forward, Backward + Inverse) | ||
52 | ) | ||
53 | ) | ||
54 | yield Rule.create( | ||
55 | TupleTableAtom.rdf(varX, pred :: hSuffix, varY), | ||
56 | TupleTableAtom.rdf(varX, pred :: bSuffix, varY) | ||
57 | ) | ||
58 | } | ||
59 | // Compute additional rules per role | ||
60 | ontology.roles | 57 | ontology.roles |
61 | .collect { case prop: OWLObjectProperty => prop } | 58 | .collect { case prop: OWLObjectProperty => prop } |
62 | .map(_.getIRI.getIRIString) | 59 | .flatMap((pred) => { |
63 | .flatMap(additional) | 60 | val iri = pred.getIRI.getIRIString |
61 | val (varX, varY) = (Variable.create("X"), Variable.create("Y")) | ||
62 | for ( | ||
63 | (hSuffix, bSuffix) <- Seq( | ||
64 | (Empty, Forward), | ||
65 | (Empty, Backward), | ||
66 | (Inverse, Forward + Inverse), | ||
67 | (Inverse, Backward + Inverse), | ||
68 | (Backward + Inverse, Forward), | ||
69 | (Forward + Inverse, Backward), | ||
70 | (Backward, Forward + Inverse), | ||
71 | (Forward, Backward + Inverse) | ||
72 | ) | ||
73 | ) | ||
74 | yield Rule.create( | ||
75 | TupleTableAtom.rdf(varX, iri :: hSuffix, varY), | ||
76 | TupleTableAtom.rdf(varX, iri :: bSuffix, varY) | ||
77 | ) | ||
78 | }) | ||
64 | } | 79 | } |
65 | 80 | ||
66 | private lazy val topAxioms: List[Rule] = { | 81 | /** Top axiomatization |
67 | val varX = Variable.create("X") | 82 | * |
68 | val varY = Variable.create("Y") | 83 | * Corresponding to the following rules: |
69 | val concepts = ontology.concepts.map(c => { | 84 | * |
85 | * ``` | ||
86 | * [?a, rdf:type, owl:Thing] :- [?a, rdf:type, ?b] . | ||
87 | * [?a, rdf:type, owl:Thing], [?b, rdf:type, owl:Thing] :- [?a, ?r, ?b], FILTER(?r != rdf:type). | ||
88 | * ``` | ||
89 | * | ||
90 | * @note this is a naïve implementation of top axiomatization and | ||
91 | * might change in the future. The ideal solution would be for RDFox | ||
92 | * to take care of this, but at the time of writing this is not | ||
93 | * compatible with the way we are using the tool. | ||
94 | */ | ||
95 | private val topAxioms: List[Rule] = { | ||
96 | val varA = Variable.create("A") | ||
97 | val varR = Variable.create("R") | ||
98 | val varB = Variable.create("B") | ||
99 | List( | ||
70 | Rule.create( | 100 | Rule.create( |
71 | RSA.Thing(varX), | 101 | RSA.Thing(varA), |
72 | TupleTableAtom.rdf(varX, IRI.RDF_TYPE, c.getIRI) | 102 | TupleTableAtom.rdf(varA, IRI.RDF_TYPE, varB) |
73 | ) | 103 | ), |
74 | }) | ||
75 | val roles = ontology.roles.map(r => { | ||
76 | val name = r match { | ||
77 | case x: OWLObjectProperty => x.getIRI.getIRIString | ||
78 | case x: OWLObjectInverseOf => | ||
79 | x.getInverse.getNamedProperty.getIRI.getIRIString :: Inverse | ||
80 | } | ||
81 | Rule.create( | 104 | Rule.create( |
82 | List(RSA.Thing(varX), RSA.Thing(varY)), | 105 | List(RSA.Thing(varA), RSA.Thing(varB)), |
83 | List(TupleTableAtom.rdf(varX, name, varY)) | 106 | List( |
107 | TupleTableAtom.rdf(varA, varR, varB), | ||
108 | FilterAtom.create(FunctionCall.notEqual(varR, IRI.RDF_TYPE)) | ||
109 | ) | ||
84 | ) | 110 | ) |
85 | }) | 111 | ) |
86 | concepts ::: roles | ||
87 | } | 112 | } |
88 | 113 | ||
114 | /** Equality axiomatization | ||
115 | * | ||
116 | * Introduce reflexivity, simmetry and transitivity rules for a naïve | ||
117 | * equality axiomatization. | ||
118 | * | ||
119 | * @note that we are using a custom `congruent` predicate to indicate | ||
120 | * equality. This is to avoid interfering with the standard | ||
121 | * `owl:sameAs`. | ||
122 | * | ||
123 | * @note RDFox is able to handle equality in a "smart" way, but this | ||
124 | * behaviour is incompatible with other needed features like | ||
125 | * negation-as-failure and aggregates. | ||
126 | * | ||
127 | * @todo to complete the equality axiomatization we need to introduce | ||
128 | * substitution rules to explicate a complete "equality" semantics. | ||
129 | */ | ||
89 | private val equalityAxioms: List[Rule] = { | 130 | private val equalityAxioms: List[Rule] = { |
90 | val varX = Variable.create("X") | 131 | val varX = Variable.create("X") |
91 | val varY = Variable.create("Y") | 132 | val varY = Variable.create("Y") |