This is an automated email from the ASF dual-hosted git repository.
andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
The following commit(s) were added to refs/heads/main by this push:
new 23c3e1e1fa GH-2487: add OntModels#getLCA
23c3e1e1fa is described below
commit 23c3e1e1fadb31551f79753fbdadcc1381aa061c
Author: sszuev <[email protected]>
AuthorDate: Sat Jul 20 17:04:49 2024 +0300
GH-2487: add OntModels#getLCA
---
.../org/apache/jena/ontapi/utils/OntModels.java | 238 +++++++++++++++++-
.../java/org/apache/jena/ontapi/OntModelsTest.java | 269 +++++++++++++++++++++
.../org/apache/jena/ontapi/TestModelFactory.java | 15 +-
3 files changed, 520 insertions(+), 2 deletions(-)
diff --git
a/jena-ontapi/src/main/java/org/apache/jena/ontapi/utils/OntModels.java
b/jena-ontapi/src/main/java/org/apache/jena/ontapi/utils/OntModels.java
index fb8e7eedc2..a4b541280f 100644
--- a/jena-ontapi/src/main/java/org/apache/jena/ontapi/utils/OntModels.java
+++ b/jena-ontapi/src/main/java/org/apache/jena/ontapi/utils/OntModels.java
@@ -45,13 +45,16 @@ import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.impl.ModelCom;
import org.apache.jena.reasoner.Reasoner;
+import org.apache.jena.shared.JenaException;
import org.apache.jena.util.iterator.ExtendedIterator;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
+import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
@@ -376,7 +379,7 @@ public class OntModels {
}
/**
- * Answer a stream of the named hierarchy roots of a given OntModel.
+ * Answers a stream of the named hierarchy roots of a given OntModel.
* This will be similar to the results of {@code OntModel.hierarchyRoot()},
* with the added constraint that every member of the returned stream will
be a named class,
* not an anonymous class expression.
@@ -415,4 +418,237 @@ public class OntModels {
}
});
}
+
+ /**
+ * Answers the lowest common ancestor of two classes.
+ * This is the class that is farthest from the root concept
+ * (defaulting to {@code owl:Thing} which is a superclass of both {@code
u} and {@code v}).
+ * The algorithm is based on
+ * <a
href="http://en.wikipedia.org/wiki/Tarjan's_off-line_least_common_ancestors_algorithm">Tarjan's
off-line LCA</a>.
+ * The current implementation expects that the given model:
+ * </p>
+ * <ul>
+ * <li>is transitively closed over the {@code subClassOf} relation</li>
+ * <li>can cheaply determine <em>direct sub-class</em> relations</li>
+ * </ul>
+ * <p>Both of these conditions are true of the built-in Jena OWL reasoners,
+ * such as {@link
org.apache.jena.ontapi.OntSpecification#OWL2_FULL_MEM_MICRO_RULES_INF},
+ * and external DL reasoners such as Pellet.</p>
+ *
+ * @param u {@link OntClass}
+ * @param v {@link OntClass}
+ * @return the LCA of {@code u} and {@code v}
+ * @throws JenaException if the language profile of the given model does
not define a top concept {@code owl:Thing}
+ */
+ public static OntClass getLCA(OntClass u, OntClass v) {
+ OntClass root = OntJenaException.notNull(u.getModel().getOWLThing());
+ return getLCA(root, u, v);
+ }
+
+ /**
+ * Answers the lowest common ancestor of two classes, assuming that the
given
+ * class is the root concept to start searching from.
+ * See {@link #getLCA(OntClass, OntClass)} for details.
+ *
+ * @param root {@link OntClass}, the root concept, which will be the
starting point for the algorithm
+ * @param u {@link OntClass}, an ontology class
+ * @param v {@link OntClass}, an ontology class
+ * @return the LCA of {@code u} and {@code v}
+ */
+ public static OntClass getLCA(OntClass root, OntClass u, OntClass v) {
+ // check some common cases first
+ if (u.equals(root) || v.equals(root)) {
+ return root;
+ }
+
+ if (u.hasSubClass(v, false)) {
+ return u;
+ }
+
+ if (v.hasSubClass(u, false)) {
+ return v;
+ }
+
+ // not a common case, so apply Tarjan's LCA algorithm
+ LCAIndex index = new LCAIndex();
+ lca(root, u, v, index);
+ return (OntClass) index.getLCA(u, v);
+ }
+
+ /**
+ * Computes the LCA disjoint set at {@code cls},
+ * noting that we are searching for the LCA of {@code uCls} and {@code
vCls}.
+ *
+ * @param cls The class we are testing (this is 'u' in the Wiki article)
+ * @param uCls One of the two classes we are searching for the LCA of.
+ * We have simplified the set P of pairs to the unity set
{uCls, vCls}
+ * @param vCls One of the two classes we are searching for the LCA of.
+ * We have simplified the set P of pairs to the unity set
{uCls, vCls}
+ * @param index A data structure mapping resources to disjoint sets
+ * (since we can't side effect Jena resources),
+ * and which is used to record the LCA pairs
+ */
+ private static DisjointSet lca(OntClass cls, OntClass uCls, OntClass vCls,
LCAIndex index) {
+ DisjointSet clsSet = index.getSet(cls);
+ if (clsSet.black) {
+ // already visited
+ return clsSet;
+ }
+
+ // not visited yet
+ clsSet.ancestor = clsSet;
+
+ // for each child of cls
+ try (Stream<OntClass> subclasses = cls.subClasses(true)) {
+ subclasses.forEach(child -> {
+ if (child.equals(cls) ||
child.equals(cls.getModel().getOWLNothing())) {
+ // we ignore the reflexive case and bottom
+ return;
+ }
+
+ // compute the LCA of the subtree
+ DisjointSet v = lca(child, uCls, vCls, index);
+
+ // union the two disjoint sets together
+ clsSet.union(v);
+
+ // propagate the distinguished member
+ clsSet.find().ancestor = clsSet;
+ });
+ }
+
+ // this node is done
+ clsSet.black = true;
+
+ // are we inspecting one of the elements we're interested in?
+ if (cls.equals(uCls)) {
+ checkSolution(uCls, vCls, index);
+ } else if (cls.equals(vCls)) {
+ checkSolution(vCls, uCls, index);
+ }
+
+ return clsSet;
+ }
+
+ /**
+ * Checks to see if we have found a solution to the problem.
+ * Here, since we've assumed that P is the unity set.
+ */
+ private static void checkSolution(OntClass uCls, OntClass vCls, LCAIndex
index) {
+ DisjointSet vSet = index.getSet(vCls);
+ DisjointSet uSet = index.getSet(uCls);
+
+ if (vSet != null && vSet.black && !vSet.used && uSet != null &&
uSet.black && !uSet.used) {
+ vSet.used = true;
+ uSet.used = true;
+ OntClass lca = (OntClass) vSet.find().ancestor.node;
+ index.setLCA(uCls, vCls, lca);
+ }
+ }
+
+ /**
+ * A simple representation of disjoint sets.
+ */
+ private static class DisjointSet {
+ /**
+ * The resource this set represents
+ */
+ private final Resource node;
+
+ /**
+ * The parent set in a union
+ */
+ private DisjointSet parent;
+
+ /**
+ * Heuristic used to build balanced unions
+ */
+ private int rank;
+
+ /**
+ * The link to the distinguished member set
+ */
+ private DisjointSet ancestor;
+
+ /**
+ * Set to true when the node has been processed
+ */
+ private boolean black = false;
+
+ /**
+ * Set to true when we've inspected a black set, since the result is
only
+ * correct just after both of the sets for u and v have been marked
black
+ */
+ private boolean used = false;
+
+ DisjointSet(Resource node) {
+ this.node = node;
+ rank = 0;
+ parent = this;
+ }
+
+ /**
+ * The find operation collapses the pointer to the root parent, which
is
+ * one of Tarjan's standard optimisations.
+ *
+ * @return The representative of the union containing this set
+ */
+ DisjointSet find() {
+ DisjointSet root;
+ if (parent == this) {
+ // the representative of the set
+ root = this;
+ } else {
+ // otherwise, seek the representative of my parent and save it
+ root = parent.find();
+ this.parent = root;
+ }
+ return root;
+ }
+
+ /**
+ * The union of two sets
+ */
+ void union(DisjointSet y) {
+ DisjointSet xRoot = find();
+ DisjointSet yRoot = y.find();
+
+ if (xRoot.rank > yRoot.rank) {
+ yRoot.parent = xRoot;
+ } else if (yRoot.rank > xRoot.rank) {
+ xRoot.parent = yRoot;
+ } else if (xRoot != yRoot) {
+ yRoot.parent = xRoot;
+ xRoot.rank++;
+ }
+ }
+ }
+
+ /**
+ * Simple data structure mapping RDF nodes to disjoint sets, and
+ * pairs of resources to their LCA.
+ */
+ private static class LCAIndex {
+ private final Map<Resource, DisjointSet> setIndex = new HashMap<>();
+ private final Map<Resource, Map<Resource, Resource>> lcaIndex = new
HashMap<>();
+
+ Resource getLCA(Resource u, Resource v) {
+ Map<Resource, Resource> map = lcaIndex.get(u);
+ Resource lca = map == null ? null : map.get(v);
+ if (lca == null) {
+ map = lcaIndex.get(v);
+ lca = (map == null) ? null : map.get(u);
+ }
+ return lca;
+ }
+
+ void setLCA(Resource u, Resource v, Resource lca) {
+ Map<Resource, Resource> uMap = lcaIndex.computeIfAbsent(u, k ->
new HashMap<>());
+ uMap.put(v, lca);
+ }
+
+ DisjointSet getSet(Resource r) {
+ return setIndex.computeIfAbsent(r, DisjointSet::new);
+ }
+ }
}
diff --git
a/jena-ontapi/src/test/java/org/apache/jena/ontapi/OntModelsTest.java
b/jena-ontapi/src/test/java/org/apache/jena/ontapi/OntModelsTest.java
index 2ec8fddc83..fe7691bc41 100644
--- a/jena-ontapi/src/test/java/org/apache/jena/ontapi/OntModelsTest.java
+++ b/jena-ontapi/src/test/java/org/apache/jena/ontapi/OntModelsTest.java
@@ -25,6 +25,7 @@ import org.apache.jena.ontapi.utils.OntModels;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.riot.Lang;
import org.apache.jena.vocabulary.OWL;
+import org.apache.jena.vocabulary.OWL2;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
@@ -475,4 +476,272 @@ public class OntModelsTest {
Assertions.assertEquals(2, actual.size());
Assertions.assertEquals(expected, new HashSet<>(actual));
}
+
+ @Test
+ public void testIndexLCA0() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ A.addSubClass(B);
+ A.addSubClass(C);
+
+ Assertions.assertEquals(A, OntModels.getLCA(B, C));
+ }
+
+ @Test
+ public void testIndexLCA1() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ A.addSubClass(B);
+ A.addSubClass(C);
+
+ Assertions.assertEquals(A, OntModels.getLCA(C, B));
+ }
+
+ @Test
+ public void testIndexLCA2() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ A.addSubClass(B);
+ A.addSubClass(C);
+
+ Assertions.assertEquals(A, OntModels.getLCA(A, C));
+ }
+
+ @Test
+ public void testIndexLCA3() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ A.addSubClass(B);
+ A.addSubClass(C);
+
+ Assertions.assertEquals(A, OntModels.getLCA(B, A));
+ }
+
+ @Test
+ public void testIndexLCA4() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.getOntClass(TestModelFactory.NS + "D");
+ A.addSubClass(B);
+ A.addSubClass(C);
+ B.addSubClass(D);
+
+ Assertions.assertEquals(A, OntModels.getLCA(D, C));
+ }
+
+ @Test
+ public void testIndexLCA5() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.getOntClass(TestModelFactory.NS + "D");
+ A.addSubClass(B);
+ A.addSubClass(C);
+ B.addSubClass(D);
+
+ Assertions.assertEquals(A, OntModels.getLCA(C, D));
+ }
+
+ @Test
+ public void testIndexLCA6() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.getOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.getOntClass(TestModelFactory.NS + "E");
+
+ A.addSubClass(B);
+ A.addSubClass(C);
+ B.addSubClass(D);
+ C.addSubClass(E);
+
+ Assertions.assertEquals(A, OntModels.getLCA(D, E));
+ }
+
+ @Test
+ public void testIndexLCA7() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.getOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.getOntClass(TestModelFactory.NS + "E");
+
+ A.addSubClass(B);
+ A.addSubClass(C);
+ B.addSubClass(D);
+ C.addSubClass(E);
+
+ Assertions.assertEquals(A, OntModels.getLCA(E, D));
+ }
+
+ @Test
+ public void testIndexLCA8() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.getOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.getOntClass(TestModelFactory.NS + "E");
+
+ A.addSubClass(B);
+ A.addSubClass(C);
+ B.addSubClass(D);
+ D.addSubClass(E);
+
+ Assertions.assertEquals(A, OntModels.getLCA(C, E));
+ }
+
+ @Test
+ public void testIndexLCA9() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.getOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.getOntClass(TestModelFactory.NS + "E");
+
+ A.addSubClass(B);
+ A.addSubClass(C);
+ B.addSubClass(D);
+ D.addSubClass(E);
+
+ Assertions.assertEquals(A, OntModels.getLCA(B, C));
+ }
+
+ @Test
+ public void testIndexLCA10() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.getOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.getOntClass(TestModelFactory.NS + "E");
+ OntClass F = m.getOntClass(TestModelFactory.NS + "F");
+
+ A.addSubClass(B);
+ A.addSubClass(C);
+ A.addSubClass(D);
+ C.addSubClass(E);
+ D.addSubClass(F);
+
+ Assertions.assertEquals(A, OntModels.getLCA(B, E));
+ }
+
+ @Test
+ public void testIndexLCA11() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.getOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.getOntClass(TestModelFactory.NS + "E");
+ OntClass F = m.getOntClass(TestModelFactory.NS + "F");
+
+ A.addSubClass(B);
+ A.addSubClass(C);
+ A.addSubClass(D);
+ C.addSubClass(E);
+ D.addSubClass(F);
+
+ Assertions.assertEquals(A, OntModels.getLCA(B, F));
+ }
+
+ @Test
+ public void testIndexLCA12() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.getOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.getOntClass(TestModelFactory.NS + "E");
+ OntClass F = m.getOntClass(TestModelFactory.NS + "F");
+
+ A.addSubClass(B);
+ A.addSubClass(C);
+ A.addSubClass(D);
+ D.addSubClass(E);
+ D.addSubClass(F);
+
+ Assertions.assertEquals(D, OntModels.getLCA(F, E));
+ }
+
+ @Test
+ public void testIndexLCA13() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.getOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.getOntClass(TestModelFactory.NS + "E");
+ OntClass F = m.getOntClass(TestModelFactory.NS + "F");
+
+ A.addSubClass(B);
+ A.addSubClass(C);
+ A.addSubClass(D);
+ C.addSubClass(E);
+ D.addSubClass(E);
+ D.addSubClass(F);
+
+ Assertions.assertEquals(D, OntModels.getLCA(F, E));
+ }
+
+ @Test
+ public void testIndexLCA14() {
+ OntModel m = TestModelFactory.createClassesABCDEFGThing(
+
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF)
+ );
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.getOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.getOntClass(TestModelFactory.NS + "C");
+ OntClass E = m.getOntClass(TestModelFactory.NS + "E");
+
+ A.addSubClass(B);
+ A.addSubClass(C);
+
+ Assertions.assertEquals(OWL2.Thing, OntModels.getLCA(B, E));
+ Assertions.assertEquals(OWL2.Thing, OntModels.getLCA(C, E));
+ Assertions.assertEquals(OWL2.Thing, OntModels.getLCA(A, E));
+ }
+
}
diff --git
a/jena-ontapi/src/test/java/org/apache/jena/ontapi/TestModelFactory.java
b/jena-ontapi/src/test/java/org/apache/jena/ontapi/TestModelFactory.java
index 21448d521a..4e8beccc2e 100644
--- a/jena-ontapi/src/test/java/org/apache/jena/ontapi/TestModelFactory.java
+++ b/jena-ontapi/src/test/java/org/apache/jena/ontapi/TestModelFactory.java
@@ -18,14 +18,15 @@
package org.apache.jena.ontapi;
+import org.apache.jena.graph.Graph;
import org.apache.jena.ontapi.impl.UnionGraphImpl;
import org.apache.jena.ontapi.model.OntClass;
import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.ontapi.testutils.RDFIOTestUtils;
-import org.apache.jena.graph.Graph;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.reasoner.InfGraph;
import org.apache.jena.riot.Lang;
+import org.apache.jena.vocabulary.OWL;
class TestModelFactory {
static final String NS = "http://example.com/test#";
@@ -366,4 +367,16 @@ class TestModelFactory {
return m;
}
+
+ static OntModel createClassesABCDEFGThing(OntModel m) {
+ m.createResource(NS + "A", OWL.Class);
+ m.createResource(NS + "B", OWL.Class);
+ m.createResource(NS + "C", OWL.Class);
+ m.createResource(NS + "D", OWL.Class);
+ m.createResource(NS + "E", OWL.Class);
+ m.createResource(NS + "F", OWL.Class);
+ m.createResource(NS + "G", OWL.Class);
+ m.createResource(OWL.Thing.getURI(), OWL.Class);
+ return m;
+ }
}