owlcs / ont-api Goto Github PK
View Code? Open in Web Editor NEWONT-API (OWL-API over Apache Jena)
ONT-API (OWL-API over Apache Jena)
a factory method to provide no-cache (direct) manger instance (would be possible after #22 )
Need to replace ru.avicomp
with something...
The suggested artifact name: com.github.owlcs
:ontapi
For the upcoming release v2.0.0, the root domain name has been already changed,
so we can safely modify any other parts of the API.
This is the last chance, after the release, such an opportunity will no longer exist, so need to do it finally.
(note: this is a continuation of the issue https://github.com/avicomp/ont-api/issues/83)
So, there are following propositions:
1) changes in Ont[Graph]Model
components naming
OntSWRL
:
OntSWRL.Atom.BuiltIn
-> OntSWRL.Atom.WithBuiltin
OntSWRL.Atom.OntClass
-> OntSWRL.Atom.WithClass
OntSWRL.Atom.DataRange
-> OntSWRL.Atom.WithDataRange
OntSWRL.Atom.ObjectProperty
-> OntSWRL.Atom.WithObjectProperty
OntSWRL.Atom.DataProperty
-> OntSWRL.Atom.WithDataProperty
OntSWRL.Atom.DifferentIndividuals
-> OntSWRL.Atom.WithDifferentIndividuals
OntSWRL.Atom.SameIndividuals
-> OntSWRL.Atom.WithSameIndividuals
OntEntity
)
OntClass
-> OntClass.Named
OntDT
-> OntDataRange.Named
OntNOP
-> OntObjectProperty.Named
OntNAP
-> OntAnnotationProperty
OntNDP
-> OntDataProperty
OntCE
-> OntClass
OntDR
-> OntDataRange
OntOPE
-> OntObjectProperty
OntProperty
-> OntNamedProperty
OntDOP
-> OntRealProperty
OntPE
-> OntProperty
OntFR
-> OntFacetRestriction
OntNPA.ObjectAssertion
-> OntNegativeAssertion.WithObjectProperty
OntNPA.DataAssertion
-> OntNegativeAssertion.WithDataProperty
2) changes in methods signatures
OntStatement#isAnnotation
->isAnnotationAssertion
OntStatement#isBulkAnnotation
-> belongsToAnnotation
OntResource#getRoot
-> getMainStatement
CreateRanges.*
-> uniformity with CreateClasses
createOneOfDataRange
-> createDataOneOf
createComplementOfDataRange
-> createDataComplementOf
createUnionOfDataRange
-> createDataUnionOf
createIntersectionOfDataRange
-> createDataIntersectionOf
createRestrictionDataRange
->CreateClasses.*
-> uniformity with CreateRanges
createOneOf
-> createObjectOneOf
createComplementOf
-> createObjectComplementOf
createUnionOf
-> createObjectUnionOf
createIntersectionOf
-> createObjectIntersectionOf
3) remove methods
OntStatement#isRoot
OntStatement#isObject
OntStatement#isData
these things are out of use, so better to remove them.
ONTObject
has a reference to the RDF graph, storing these object in some memory store may cause memory-leak.
So it is better to return clean OWLObject by default.
the source: sszuev/ont-converter#1
There is a fix in OWL-API 5.1.16 that our project needs. We are currently using ONT-API 2.0.0 and appreciate the integration with Jena. Are there plans to create a new version of ONT-API that pulls in the latest OWL-API? It looks like Jena also has a more recent release.
Thanks for supporting this library.
The testcase:
String ns = "http://x#";
OntologyManager m = OntManagers.createONT();
OntologyModel o = m.createOntology();
OntGraphModel g = o.asGraphModel();
g.createOntClass(ns + "X").addSuperClass(g.createOntClass(ns + "Y"));
g.write(System.out, "ttl");
o.axioms().forEach(System.out::println);
List<RemoveAxiom> changes = o.axioms().map(x -> new RemoveAxiom(o, x)).collect(Collectors.toList());
m.applyChanges(changes);
g.write(System.out, "ttl");
o.axioms().forEach(System.out::println);
*Impl
classes from the com.github.owlcs.ontapi.owlapi
package (just delete prefix OWL
) so as not to confuse them with the original OWLAPI-impl ones (also applicable for 2.x.x)com.github.owlcs.ontapi.jena.utils.Iter#toUnmodifiable*
with Collectors.*
methodsCollections.unmodifiable*
-> *.of
,new HashMap<>{ {put()} }
syntax with Map.of
(OntVocabulary
, AxiomParserProvider
, OWLCommonTransform
)The default impl is following:
if (containsAxiom(axiom)) {
return true;
}
return axioms(axiom.getAxiomType()).anyMatch(ax -> ax.equalsIgnoreAnnotations(axiom));
No need to iterate over all axioms if we know exactly that there is no annotations for the given type
Since the root package and the artifact names have been changed, there is an idea to change names of several major classes as well (for coming release 2.0.0).
Currently this proposition includes the following changes:
com.github.owlcs.ontapi.OntologyModel
(former ru.avicomp.ontapi.OntologyModel
) -> com.github.owlcs.ontapi.Ontology
.
Why ?
The suffix 'Model' is absent in OWL-API. Also it is a part name of graph-model (the current OntGraphModel
). To distinguish RDF-view and OWL-view, better to leave suffix 'Model' for things from the first category.
ONT-API top components:
OntologyID
-> ID
OntID
in jena subsystem, where prefix Ont
means it is OntObject
. On top level there is no such mnemonic rule.com.github.owlcs.ontapi.jena.model.OntGraphModel
(former ru.avicom.ontapi.jena.model.OntGraphModel
) -> com.github.owlcs.ontapi.jena.model.OntModel
.
Why?
Because the name OntModel
is shorter, and therefore better.
It makes no sense to emphasize it is a Graph model, since this fact is already encoded in the full class name (the package is *.jena.model.
*). Any model in Jena is a graph model.
The main argument why such a name (i.e. OntGraphModel
) was chosen was desire to distinguish our model with jena org.apache.jena.ontology.OntModel
.
Now I think, this was not quit correct - both models hardly can live in one snippet simultaneously, and it would be better for clients to use only one model, either Jena’s or ours. Well, they actually can mix whatever they want, but it is just a marker of poor design. In functional sense, there should not be anything that org.apache.jena.ontology.OntModel
could do, but our model (com.github.owlcs.ontapi.jena.model.OntModel
) could not. Well, with except of inference.
And we could not use the prefix Owl
or OWL
: the first one is just incorrect, and the second one is reserved by OWL-API. The prefix ONT
is also incorrect - it is abbreviation, not acronym.
So, the only right prefix is Ont
, which leads to the same name - OntModel
Jena Ontology API (RDF Model components) refactoring, see #8
Move/rename com.github.owlcs.ontapi.jena.utils.BuiltIIn
( -> com.github.owlcs.ontapi.jena.OntVocabulary
as analogue of org.semanticweb.owlapi.vocab.OWLRDFVocabulary
) + rename methods (add get
prefix for methods returning collections, i.e. for all)
com.github.owlcs.ontapi.transforms.Transform
refactoring: get rid of Transform abstraction, that accept model/graph as constructor parameter, instead there should be stateless interface (currently it is GraphTransforms.Maker
- but this is a bad name)
it would be nice to provide direct (non-cache) manager out-of-the-box;
in order to do this it is need a way to disable changing some config properties (or even whole config) - otherwise it would not be safe.
Not all methods of such kind have optimizations yet.
This could be critical for some systems and big ontologies.
This is the old issue, the source: https://github.com/avicomp/ont-api/issues/33
List of methods for optimization --
OWLDatatype
:1 ::: Stream<OWLDatatypeDefinitionAxiom> axioms(OWLDatatype)
2 ::: Stream<OWLDatatypeDefinitionAxiom> datatypeDefinitions(OWLDatatype)
OWLClass
:1 ::: Stream<OWLClassAxiom> axioms(OWLClass)
2 ::: Stream<OWLEquivalentClassesAxiom> equivalentClassesAxioms(OWLClass)
3 ::: Stream<OWLSubClassOfAxiom> subClassAxiomsForSuperClass(OWLClass)
4 ::: Stream<OWLSubClassOfAxiom> subClassAxiomsForSubClass(OWLClass)
5 ::: Stream<OWLDisjointClassesAxiom> disjointClassesAxioms(OWLClass)
6 ::: Stream<OWLDisjointUnionAxiom> disjointUnionAxioms(OWLClass)
7 ::: Stream<OWLClassAssertionAxiom> classAssertionAxioms(OWLClassExpression)
8 ::: Stream<OWLHasKeyAxiom> hasKeyAxioms(OWLClass)
OWLIndividual
:1 ::: Stream<OWLIndividualAxiom> axioms(OWLIndividual)
2 ::: Stream<OWLClassAssertionAxiom> classAssertionAxioms(OWLIndividual)
3 ::: Stream<OWLSameIndividualAxiom> sameIndividualAxioms(OWLIndividual)
4 ::: Stream<OWLDifferentIndividualsAxiom> differentIndividualAxioms(OWLIndividual)
5 ::: Stream<OWLObjectPropertyAssertionAxiom> objectPropertyAssertionAxioms(OWLIndividual)
6 ::: Stream<OWLNegativeObjectPropertyAssertionAxiom> negativeObjectPropertyAssertionAxioms(OWLIndividual)
7 ::: Stream<OWLDataPropertyAssertionAxiom> dataPropertyAssertionAxioms(OWLIndividual)
8 ::: Stream<OWLNegativeDataPropertyAssertionAxiom> negativeDataPropertyAssertionAxioms(OWLIndividual)
OWLObjectProperty
:1 ::: Stream<OWLObjectPropertyAxiom> axioms(OWLObjectPropertyExpression)
2 ::: Stream<OWLEquivalentObjectPropertiesAxiom> equivalentObjectPropertiesAxioms(OWLObjectPropertyExpression)
3 ::: Stream<OWLSubObjectPropertyOfAxiom> objectSubPropertyAxiomsForSuperProperty(OWLObjectPropertyExpression)
4 ::: Stream<OWLSubObjectPropertyOfAxiom> objectSubPropertyAxiomsForSubProperty(OWLObjectPropertyExpression)
5 ::: Stream<OWLInverseObjectPropertiesAxiom> inverseObjectPropertyAxioms(OWLObjectPropertyExpression)
6 ::: Stream<OWLFunctionalObjectPropertyAxiom> functionalObjectPropertyAxioms(OWLObjectPropertyExpression)
7 ::: Stream<OWLInverseFunctionalObjectPropertyAxiom> inverseFunctionalObjectPropertyAxioms(OWLObjectPropertyExpression)
8 ::: Stream<OWLSymmetricObjectPropertyAxiom> symmetricObjectPropertyAxioms(OWLObjectPropertyExpression)
9 ::: Stream<OWLAsymmetricObjectPropertyAxiom> asymmetricObjectPropertyAxioms(OWLObjectPropertyExpression)
10 ::: Stream<OWLTransitiveObjectPropertyAxiom> transitiveObjectPropertyAxioms(OWLObjectPropertyExpression)
11 ::: Stream<OWLReflexiveObjectPropertyAxiom> reflexiveObjectPropertyAxioms(OWLObjectPropertyExpression)
12 ::: Stream<OWLIrreflexiveObjectPropertyAxiom> irreflexiveObjectPropertyAxioms(OWLObjectPropertyExpression)
13 ::: Stream<OWLObjectPropertyDomainAxiom> objectPropertyDomainAxioms(OWLObjectPropertyExpression)
14 ::: Stream<OWLObjectPropertyRangeAxiom> objectPropertyRangeAxioms(OWLObjectPropertyExpression)
15 ::: Stream<OWLDisjointObjectPropertiesAxiom> disjointObjectPropertiesAxioms(OWLObjectPropertyExpression)
OWLDataProperty
:1 ::: Stream<OWLDataPropertyAxiom> axioms(OWLDataProperty)
2 ::: Stream<OWLEquivalentDataPropertiesAxiom> equivalentDataPropertiesAxioms(OWLDataProperty)
3 ::: Stream<OWLSubDataPropertyOfAxiom> dataSubPropertyAxiomsForSuperProperty(OWLDataPropertyExpression)
4 ::: Stream<OWLSubDataPropertyOfAxiom> dataSubPropertyAxiomsForSubProperty(OWLDataProperty)
5 ::: Stream<OWLFunctionalDataPropertyAxiom> functionalDataPropertyAxioms(OWLDataPropertyExpression)
6 ::: Stream<OWLDataPropertyDomainAxiom> dataPropertyDomainAxioms(OWLDataProperty)
7 ::: Stream<OWLDataPropertyRangeAxiom> dataPropertyRangeAxioms(OWLDataProperty)
8 ::: Stream<OWLDisjointDataPropertiesAxiom> disjointDataPropertiesAxioms(OWLDataProperty)
OWLAnnotationProperty
:1 ::: Stream<OWLAnnotationAxiom> axioms(OWLAnnotationProperty)
2 ::: Stream<OWLSubAnnotationPropertyOfAxiom> subAnnotationPropertyOfAxioms(OWLAnnotationProperty)
3 ::: Stream<OWLAnnotationPropertyRangeAxiom> annotationPropertyRangeAxioms(OWLAnnotationProperty)
4 ::: Stream<OWLAnnotationPropertyDomainAxiom> annotationPropertyDomainAxioms(OWLAnnotationProperty)
The existing way is cache-based, but cache is optional.
Also need to add contains
functionality.
The original issue: https://github.com/avicomp/ont-api/issues/91
Here is the result of research for OWLClass
:
PIZZA_DEF :::: 0.004917777777777773 (iter=1800)
PIZZA_OP1 :::: 0.005793888888888896 (iter=1800)
PIZZA_OP2 :::: 2.0111111111111122E-4 (iter=1800)
FAMILY_DEF :::: 0.0057155555555555605 (iter=1800)
FAMILY_OP1 :::: 0.01308277777777759 (iter=1800)
FAMILY_OP2 :::: 1.5666666666666674E-4 (iter=1800)
PEOPLE_DEF :::: 0.0015594444444444451 (iter=1800)
PEOPLE_OP1 :::: 0.0026055555555555554 (iter=1800)
PEOPLE_OP2 :::: 1.661111111111112E-4 (iter=1800)
CAMERA_DEF :::: 4.7777777777777814E-4 (iter=1800)
CAMERA_OP1 :::: 7.361111111111111E-4 (iter=1800)
CAMERA_OP2 :::: 9.27777777777778E-5 (iter=1800)
KOALA_DEF :::: 7.161111111111113E-4 (iter=1800)
KOALA_OP1 :::: 0.001042777777777777 (iter=1800)
KOALA_OP2 :::: 2.255555555555557E-4 (iter=1800)
TRAVEL_DEF :::: 9.677777777777774E-4 (iter=1800)
TRAVEL_OP1 :::: 0.0015283333333333342 (iter=1800)
TRAVEL_OP2 :::: 2.127777777777779E-4 (iter=1800)
WINE_DEF :::: 0.004534444444444434 (iter=1800)
WINE_OP1 :::: 0.006112777777777789 (iter=1800)
WINE_OP2 :::: 1.4888888888888897E-4 (iter=1800)
FOOD_DEF :::: 0.0026238888888888904 (iter=1800)
FOOD_OP1 :::: 0.0031288888888888846 (iter=1800)
FOOD_OP2 :::: 2.1722222222222236E-4 (iter=1800)
NCBITAXON_CUT_DEF :::: 0.014476111111110846 (iter=1800)
NCBITAXON_CUT_OP1 :::: 0.02335722222222164 (iter=1800)
NCBITAXON_CUT_OP2 :::: 5.700000000000004E-4 (iter=1800)
HP_CUT_DEF :::: 7.311111111111114E-4 (iter=1800)
HP_CUT_OP1 :::: 0.0011872222222222217 (iter=1800)
HP_CUT_OP2 :::: 5.1666666666666664E-5 (iter=1800)
FAMILY_PEOPLE_UNION_DEF :::: 3.833333333333336E-4 (iter=1800)
FAMILY_PEOPLE_UNION_OP1 :::: 7.41111111111111E-4 (iter=1800)
FAMILY_PEOPLE_UNION_OP2 :::: 3.5222222222222247E-4 (iter=1800)
TMP_HP_NM_DEF :::: 1.7008555555555547 (iter=360)
TMP_HP_NM_OP1 :::: 2.225877777777778 (iter=360)
TMP_HP_NM_OP2 :::: 0.015452777777777758 (iter=360)
TMP_TTO_NM_DEF :::: 1.0611944444444465 (iter=360)
TMP_TTO_NM_OP1 :::: 2.481030555555556 (iter=360)
TMP_TTO_NM_OP2 :::: 0.02709444444444447 (iter=360)
DEF - is a classic way (loading axioms + parsing axioms's cache)
OP1 - loading axioms + reading graph
OP2 - reading graph
it is hard to debug, continuous problems with running tests in IDE, need to install jena-impl, etc
+ there is spin-off of jena-ont-model https://github.com/sszuev/jena-owl2
so in the next release it will have to be done anyway
this is a continuation of #20
Several axioms, such as SubClassOf
, usually have named subject and anonymous object.
There is a searching by predicate (i.e. $any rdfs:subClassOf $any
+ filter) and refined searching for the case of named triple (exact match with $some rdfs:subClassOf $some
- issue #20) .
Need a general way to optimize the cases of $some $some $any
and $any $some $some
.
The behavior is different for ONTAPI and OWLAPI-impl.
e.g.
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<http://Y> rdf:type owl:Class .
[ <http://RP> 42 ] .
<http://RP> rdf:type rdf:Property .
<http://D> rdf:type rdfs:Datatype .
<http://DP> rdf:type owl:DatatypeProperty .
<http://X> rdf:type rdfs:Class .
ONTAPI axioms:
Declaration(Class(<http://Y>))
Declaration(Datatype(<http://D>))
Declaration(AnnotationProperty(<http://RP>))
Declaration(DataProperty(<http://DP>))
AnnotationAssertion(<http://RP> _:d218b4c5a8fa42a2481225de8088780e "42"^^xsd:integer)
OWLAPI-impl axioms:
Declaration(Class(<http://X>))
Declaration(DataProperty(<http://DP>))
Declaration(Class(<http://Y>))
Declaration(Datatype(<http://D>))
AnnotationAssertion(<http://RP> _:genid2147483648 "42"^^xsd:integer)
UDD
Now I think it's ok as the default behavior: you always can configure that behavior by adding/removing custom/builtin transformers.
So this is wontfix issue
Nested interfaces and using class-types may confuse and look a bit difficult.
The functionality OntExpression#asNamed()
seems to be a little more convenient than OntExpression#as(Named.class)
.
This would allow not to use '.Named' part everywhere, but use only OntClass
, OntDataRange
, etc, without their named parts implicitly. Therefore client-code would look better.
Although this is minor (i.e. "sugar") improvement, I don't see reasons why not.
In the OWL-community there are a lot of students and newbies, which might appreciate this functionality.
equivalent of jena's org.apache.jena.ontology.OntClass#listDeclaredProperties(direct:boolean)
,
see doc https://jena.apache.org/documentation/notes/rdf-frames.html
analogue of org.apache.jena.ontology.OntProperty#listDeclaringClasses(direct:boolean)
,
etc
maybe it's worth adding the class-properties functionality too
https://github.com/sszuev/ont-dot/blob/master/src/main/java/com/github/sszuev/ontdot/utils/ClassPropertyMapImpl.java#L57 (listRelatedProperties
?)
Not sure if this is a mistake/regression or is it due to recent changes in OWL-API.
Anyway it is a bug of ONT-API.
The testcase:
OWLDataFactory owlapi = OntManagers.createOWL().getOWLDataFactory();
DataFactory ontapi = OntManagers.getDataFactory();
String value = "1922";
OWL2Datatype dt = OWL2Datatype.XSD_POSITIVE_INTEGER;
OWLLiteral x = owlapi.getOWLLiteral(value, dt);
OWLLiteral z = ontapi.getOWLLiteral(value, dt);
System.out.println(x.hashCode() + " ? " + z.hashCode());
Assert.assertEquals(x, z);
the current implementation is time based - it use delays,
it doesn't seem to be very good solution,
also, there are other questionable solutions, e.g. each of the Iterator
produced by the graph holds Thread
reference, this may lead to memory leak.
jena:4.x.x supports java.util.stream.Stream
out-of-the-box on the org.apache.jena.graph.Graph
level,
so need to use it instead of existing custom solution
In case the serialization format (lang) is not provided we have to iterate all supported formats to find the best suitable.
This peace of code can be optimized using file rewinding or parallel running.
To compare:
Standard sequence reading
private static void loadStd(Path p, int n, long lines) throws IOException {
int step = n / 100;
for (int i = 0; i < n; i++) {
if (i % step == 0) {
System.out.print("#");
}
try (BufferedReader r = Files.newBufferedReader(p)) {
if (lines != r.lines().count()) {
throw new IllegalStateException();
}
}
}
System.out.println();
}
vs SeekableByteChannel
reading
private static void loadNio(Path p, int n, long lines) throws IOException {
int step = n / 100;
try (SeekableByteChannel chanel = Files.newByteChannel(p, StandardOpenOption.READ)) {
for (int i = 0; i < n; i++) {
if (i % step == 0) {
System.out.print("#");
}
BufferedReader r = new BufferedReader(Channels.newReader(chanel, StandardCharsets.UTF_8));
if (lines != r.lines().count()) {
throw new IllegalStateException();
}
chanel.position(0);
}
}
System.out.println();
}
vs concurrent reading
private static void loadParallel(Path p, int n, long lines) throws ExecutionException, InterruptedException {
System.out.println("Go");
ExecutorService service = Executors.newWorkStealingPool();
CompletableFuture<?>[] futures = IntStream.range(0, n).mapToObj(x -> CompletableFuture.runAsync(() -> {
try (BufferedReader r = Files.newBufferedReader(p)) {
if (lines != r.lines().count()) {
throw new IllegalStateException();
}
System.out.println(Thread.currentThread() + " is done.");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}, service)).toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).get();
System.out.println("Done");
}
Current implementation based on searching over existing axiom caches is extremely inefficient.
The graph optimized way is, as usual, much more faster.
Here is statistic:
START::: 2020-03-03T17:18:20.695Z
========================================
TEST PIZZA:::: CLASSES=100 ||| AXIOMS=945 |||| iter = 10
DEF::: 0.0431 s.
GRH::: 0.07750000000000003 s.
========================================
TEST FAMILY:::: CLASSES=58 ||| AXIOMS=2845 |||| iter = 10
DEF::: 0.020599999999999997 s.
GRH::: 0.029400000000000003 s.
========================================
TEST PS:::: CLASSES=6038 ||| AXIOMS=38872 |||| iter = 5
DEF::: 8.541 s.
GRH::: 0.183 s.
========================================
TEST GALEN:::: CLASSES=23142 ||| AXIOMS=96463 |||| iter = 1
DEF::: 1484.803 s.
GRH::: 4.399 s.
========================================
TEST HP:::: CLASSES=15984 ||| AXIOMS=143855 |||| iter = 1
DEF::: 516.407 s.
GRH::: 3.229 s.
========================================
TEST TTO:::: CLASSES=38705 ||| AXIOMS=336291 |||| iter = 1
DEF::: 655.279 s.
GRH::: 1.467 s.
========================================
TEST GO:::: CLASSES=49797 ||| AXIOMS=556475 |||| iter = 1
DEF::: 4839.628 s.
GRH::: 6.022 s.
TOTAL::: PT2H6M40.32S
The code (for the ont-api.wiki project, AxiomReferencesTmp.java) follows:
private static final Set<Class<? extends OntClass.CardinalityRestrictionCE<?, ?>>> OBJECT_CARDINALITY_TYPES =
Stream.of(OntClass.ObjectMaxCardinality.class,
OntClass.ObjectMinCardinality.class, OntClass.ObjectCardinality.class).collect(Collectors.toSet());
private static final Set<AxiomTranslator<? extends OWLAxiom>> CLASS_TRANSLATORS = OWLContentType.all()
.filter(x -> x.hasComponent(OWLComponentType.CLASS))
.map(OWLContentType::getAxiomType)
.map(AxiomParserProvider::get).collect(Collectors.toSet());
public static void main(String... args) throws Exception {
Instant s = Instant.now();
System.out.println("START::: " + s);
testReferences(TestData.PIZZA, 10);
testReferences(TestData.FAMILY, 10);
testReferences(TestData.PS, 5);
testReferences(TestData.GALEN, 1);
testReferences(TestData.HP, 1);
testReferences(TestData.TTO, 1);
testReferences(TestData.GO, 1);
System.out.println("TOTAL::: " + Duration.between(s, Instant.now()));
}
private static void testReferences(TestData data, int num) throws Exception {
System.out.println("========================================");
OntologyManager m = OntManagers.createONT();
Ontology o = m.loadOntologyFromOntologyDocument(data.getDocumentSource());
Set<OWLClass> classes = o.classesInSignature().collect(Collectors.toSet());
System.out.printf("TEST %s:::: CLASSES=%d ||| AXIOMS=%d |||| iter = %d%n",
data, classes.size(), o.getAxiomCount(), num);
long count1 = measure("DEF", num, () -> classes.stream().flatMap(o::referencingAxioms));
long count2 = measure("GRH", num, () -> classes.stream().flatMap(x -> referencingAxioms(o, x)));
if (count1 != count2) throw new IllegalStateException();
}
private static long measure(String pref, int num, Supplier<Stream<?>> get) {
long count = 0;
double d = 0;
for (int i = 0; i < num; i++) {
Instant s = Instant.now();
count += get.get().distinct().count();
d += getDurationInSeconds(Duration.between(s, Instant.now()));
}
count /= num;
d /= num;
System.out.println(pref + "::: " + d + " s.");
return count;
}
public static double getDurationInSeconds(Duration d) {
return (double) d.getSeconds() + d.getNano() / 1_000_000_000d;
}
public static Stream<OWLAxiom> referencingAxioms(Ontology o, OWLClass c) {
OntModel m = o.asGraphModel();
OntClass clazz = m.getOntClass(c.getIRI().getIRIString());
Stream<OntStatement> candidates = Stream.concat(m.statements(clazz, null, null),
m.statements(null, null, clazz).flatMap(AxiomReferencesTmp::roots));
if (OWL.Thing.equals(clazz)) {
candidates = Stream.concat(candidates, specialForThing(m).flatMap(AxiomReferencesTmp::roots));
}
return candidates.flatMap(s -> translators(s).map(x -> x.toAxiom(s).getOWLObject()));
}
private static Stream<OntStatement> specialForThing(OntModel m) {
return Stream.of(OWL.cardinality, OWL.maxCardinality, OWL.minCardinality)
.flatMap(p -> m.statements(null, p, null))
.filter(AxiomReferencesTmp::isObjectRestriction);
}
private static boolean isObjectRestriction(OntStatement s) {
return OBJECT_CARDINALITY_TYPES.stream().anyMatch(t -> s.getSubject().canAs(t));
}
private static Stream<? extends AxiomTranslator<? extends OWLAxiom>> translators(OntStatement s) {
return CLASS_TRANSLATORS.stream().filter(x -> x.testStatement(s));
}
private static Stream<OntStatement> roots(OntStatement s) {
return roots(s.getModel(), s, new HashSet<>());
}
private static Stream<OntStatement> roots(OntModel m, OntStatement st, Set<OntStatement> seen) {
Resource s = st.getSubject();
if (s.isURIResource()) {
return Stream.of(st);
}
Set<OntStatement> set = m.statements(null, null, s).filter(seen::add).collect(Collectors.toSet());
if (set.isEmpty()) return Stream.of(st);
return set.stream().flatMap(x -> roots(m, x, seen));
}
I raised the issue in the Apache Jena community: apache/jena#1961
Nobody seems to use concurrency support in ONT-API or OWL-API, is it true?
If false, what are scenarios?
Consider the following ontology:
Declaration(Class(<http://www.ex.org/tribe#foremother>))
EquivalentClasses(<http://www.ex.org/tribe#foremother> ObjectIntersectionOf(<http://www.co-ode.org/roberts/family-tree.owl#Woman> ObjectSomeValuesFrom(<http://www.co-ode.org/roberts/family-tree.owl#isForemotherOf> <http://www.co-ode.org/roberts/family-tree.owl#Person>)) )
There are two forms of graph serialization:
t:foremother a owl:Class ;
owl:equivalentClass [ a owl:Class ;
owl:intersectionOf ( f:Woman
[ a owl:Restriction ;
owl:onProperty f:isForemotherOf ;
owl:someValuesFrom f:Person
]
)
] .
and
[ a owl:Class ;
owl:equivalentClass t:foremother ;
owl:intersectionOf ( f:Woman
[ a owl:Restriction ;
owl:onProperty f:isForemotherOf ;
owl:someValuesFrom f:Person
]
)
] .
t:foremother a owl:Class .
Think, that the first form is more preferable, but ONT-API chooses the second one that corresponds the natural OWLObject
order provided by OWL-API.
So, need to change the order.
It is a minor enhancement - both forms are actually equivalent.
the source: https://github.com/avicomp/ont-api/issues/87
com.github.owlcs.ontapi.jena.model.OntModel covers OWL2 syntax but not inference and OWL profiles.
org.apache.jena.ontology.OntModel supports inference, but only follows OWL1 specification.
This error is being generated when I execute the clojure command-line clj -X:deps tree
after including this project as a dependency.
Error generating tree: Could not find artifact com.github.sszuev:concurrent-rdf-graph:jar:1.0.0 in central (https://repo1.maven.org/maven2/)
Version 3.0.4
This includes following functionalities:
OntModels#toOntStatement(Triple, OntModel)
- which can return main statement (i.e. OntObject#getMainStatement
) if needed.AixomTranslator#toAxiom(OntStatement, ONTObjectFactory, AxiomsSettings)
(there is already toAxiom
but without parameters)AxiomTranslator
by AxiomType
(i.e. move AxiomParserProvider#get
and make it deprecated)this is generic and useful functionality
right now it is an abstract class, that fact limits usefulness and flexibility
something like this:
com.github.owlcs.ontapi.jena.model.OntClass#disjointLists()
with return type com.github.owlcs.ontapi.jena.model.OntDisjoint.Classes
- I think this would be useful
see OWL-API default impl, issue owlcs/owlapi#882
The testcase:
public static void main(String ... args) {
OntologyManager m1 = OntManagers.createONT();
Ontology a = m1.createOntology(IRI.create("A"));
Ontology b = m1.createOntology(IRI.create("B"));
a.asGraphModel().addImport(b.asGraphModel());
b.asGraphModel().addImport(a.asGraphModel());
testManager(m1);
OntologyManager m2 = OntManagers.createONT();
m1.ontologies().forEach(x -> m2.copyOntology(x, OntologyCopy.SHALLOW));
testManager(m2);
}
private static void testManager(OntologyManager m) {
Assert.assertEquals(2, m.ontologies().peek(x -> {
System.out.println("TEST: " + x);
Assert.assertEquals(2, Graphs.baseGraphs(((Ontology)x).asGraphModel().getGraph()).count());
}).count());
}
Additional info:
The method copyOntology
with OntologyCopy.SHALLOW
is used in RDF Protege.
The example of ontology with cyclic imports is http://www.w3.org/TR/owl-guide/wine.rdf
If subject and object are URIs then there is no need to iterate for searching.
This is an optimization for the direct mode (i.e. when cache is disabled).
And it is, probably, the last thing for the 2.1.0 release
Update: add simplified contains/find for the case if the subject and object are anonymous individuals - since they are unique within the system and does not require complex hashCode/equlas.
For a case when triples has one anonymous expression (as subject or object), the optimization is also needed, but this can be next issue.
This is actually known behavior which is by design.
There is no guarantee that any method of unattached (i.e. deleted) object will not throw an exception.
It is already deleted, so it has no connection with the graph.
Unlike OWL-API default impl, in ONT-API there is a dynamic object's state, which depends on graph and model's settings, it is true even for isBuiltIn parameter-property.
But for OWLEntity#isBuiltIn()
it is better to make an exception:
there is an example of code in Protege where an entity is still in use even after its deletion (see org.protege.editor.owl.model.hierarchy.OWLAnnotationPropertyHierarchyProvider#handleChanges(...)
).
Moreover - it is always possible to safely determine whether an entity is builtin even it is deleted.
The testcase:
OntologyManager m = OntManagers.createONT();
DataFactory df = m.getOWLDataFactory();
Ontology o = m.createOntology();
OWLAxiom a = df.getOWLDeclarationAxiom(df.getOWLAnnotationProperty("a"));
o.add(a);
OWLEntity e1 = o.signature().filter(AsOWLAnnotationProperty::isOWLAnnotationProperty)
.findFirst().orElseThrow(AssertionError::new);
Assert.assertFalse(e1.isBuiltIn());
o.remove(a);
Assert.assertFalse(e1.isBuiltIn());
with\without class-hierarchy, it could be useful
I cloned the repo and ran a Maven build. I get these two errors, which I also get if I import the code into Eclipse as a Maven project:
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /home/camfe/andy/ws/sadl/git/ont-api/ont-api/src/test/java/com/github/owlcs/ontapi/tests/managers/SimpleLoadTest.java:[120,45] incompatible types: inference variable T has incompatible bounds
equality constraints: org.semanticweb.owlapi.model.OWLAxiom
lower bounds: java.lang.Object
[ERROR] /home/camfe/andy/ws/sadl/git/ont-api/ont-api/src/test/java/com/github/owlcs/ontapi/utils/SP.java:[206,15] reference to Module is ambiguous
both interface org.topbraid.spin.model.Module in org.topbraid.spin.model and class java.lang.Module in java.lang match
I loaded an ontology with SWRL rules:
IRI iri = IRI.create(BASE_URL);
OntologyManager manager = OntManagers.createManager();
// Load an ontology
Ontology mergedOntology = manager.loadOntologyFromOntologyDocument(iri);
Then I instantiate a Hermit reasoner:
import org.semanticweb.HermiT.ReasonerFactory;
OWLReasonerFactory reasonerFactory = new ReasonerFactory();
OWLReasoner reasoner = reasonerFactory.createReasoner(mergedOntology);
Finally, I query:
try (
QueryExecution qexec = QueryExecutionFactory.create(QueryFactory
.create("SELECT ?s ?p ?o WHERE { ?s ?p ?o }"), mergedOntology.asGraphModel())
) {
ResultSet res = qexec.execSelect();
while (res.hasNext()) {
System.out.println(res.next());
}
}
However the reasoner wasn't used. Is there a way to do what I want?
Since ONTObjectImpl
(in contradistinction to OWLObjectImpl
) has ref to prefixed model inside, it would be nice to replace default toString
implementation (which is based on SimpleRenderer
) with new one that reflects model settings
it is more convenient: e.g. there is a possibility to combine parameterized test-cases and a regular one in a single class
The org.apache.jena.ontology.OntDocumentManager
is a part of org.apache.jena.ontology.OntModel
.
Since we going to support all jena ont-model functionality, we should probably support this mechanism as well.
(related to #45)
If you are reading this issue, you are probably know what ONTAPI is: it is an alternative OWLAPI implementation, which (I believe) has comparable performance and memory consumption.
But according to my observations (on github projects), sometimes people are using ONTAPI as a simple conversion tool only, or even after a while since beginning of use ONTAPI, they decide to give up it in favor of the default implementation.
This seems strange, and it would be very valuable to know the reasons of such decisions.
So, if there is a lack of performance you faced, or something else, it would be nice to have some feedback on it (as a response on this issue or as a new issue whatever).
Then, perhaps, we can try to fix these cases.
Silence cannot be a driving force in the open source world.
Thanks in advance.
there are two kind of spin-tests - for graph-transformation and spin-inference (used also in ONT-D2RQ).
Now it seems these tests are better to be moved into examples (wiki) project since they have rather a demonstration nature and in the main project (i.e. ONT-API) they are logically superfluous.
Exceptions are not properly handled in case of linux (differences in try-with-resource, Pipe[Input/Output]Streams ? - not sure)
The environment:
Linux ... 5.0.0-36-generic #39~18.04.1-Ubuntu SMP Tue Nov 12 11:09:50 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
concurrent RDF-Graph (https://github.com/sszuev/concurrent-rdf-graph) is not enough.
OntModel
methods are still not protected properly.
There is already concurrent implementation (com.github.owlcs.ontapi.OntologyModelImpl.Concurrent.asGraphModel
), but it does not cover all cases.
TODO:
Model#write
, Model#write
)Iterator
on graph level with internal own lock
)OntObject
s as wellHi,
I'm using the latest Maven project Ont-api version 2.0.0 .
I'm trying to lead a local ontology with the instructions below :
String pathFileInTest = "Misc/Ontologies_Input/pizza.owl";
String iriFileTest = "http://www.co-ode.org/ontologies/pizza/pizza.owl";
OntologyManager m = OntManagers.createONT();
OWLDataFactory df = m.getOWLDataFactory();
OWLOntology ontology = m.loadOntologyFromOntologyDocument(new File(pathFileIn));
Here's the output :
Exception in thread "main" org.semanticweb.owlapi.io.UnparsableOntologyException: Problem parsing file:/Users/--/Misc/Ontologies_Input/pizza.owl
Could not parse ontology. Either a suitable parser could not be found, or parsing failed.
Suppressed: com.github.owlcs.ontapi.OntologyFactoryImpl$UnsupportedFormatException: Can't read FileDocumentSource file:/Users/--/Misc/Ontologies_Input/pizza.owl.
Suppressed: com.github.owlcs.ontapi.OntologyFactoryImpl$UnsupportedFormatException: org.apache.jena.riot.RiotException: [line: 22, col: 32] {E201} Multiple children of property element. Format: RDF_XML. IRI: <file:/Users/--/Misc/Ontologies_Input/pizza.owl>. Cause: '[line: 22, col: 32] {E201} Multiple children of property element'
Caused by: org.apache.jena.riot.RiotException: [line: 22, col: 32] {E201} Multiple children of property element
Suppressed: com.github.owlcs.ontapi.OntologyFactoryImpl$UnsupportedFormatException: org.apache.jena.riot.RiotException: [line: 1, col: 7 ] Bad character in IRI (space): <?xml[space]...>. Format: TURTLE. IRI: <file:/Users/--/Misc/Ontologies_Input/pizza.owl>. Cause: '[line: 1, col: 7 ] Bad character in IRI (space): <?xml[space]...>'
Caused by: org.apache.jena.riot.RiotException: [line: 1, col: 7 ] Bad character in IRI (space): <?xml[space]...>
Suppressed: com.github.owlcs.ontapi.OntologyFactoryImpl$UnsupportedFormatException: org.apache.jena.riot.thrift.RiotThriftException: org.apache.thrift.protocol.TProtocolException: don't know what type: 15. Format: RDF_THRIFT. IRI: <file:/Users/--/Misc/Ontologies_Input/pizza.owl>. Cause: 'org.apache.thrift.protocol.TProtocolException: don't know what type: 15'
Caused by: org.apache.jena.riot.thrift.RiotThriftException: org.apache.thrift.protocol.TProtocolException: don't know what type: 15
When I load this same ontology with the method loadOntology
(from internet) : it works.
It also works when I load a RDF format file like the wine.rdf ontology.
the method
loadOntologyFromOntologyDocument
seems to parse with JENA and not with OWLAPI but I can't figure it out why.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.