'Creating an instance in OWLready2 creates a completely new class instead of asigning it to the existing class

I'm trying to create a simple ontology, following the tutorial on the official website. The code runs smoothly and everything seems fine when running this code:

import owlready2
owlready2.JAVA_EXE = r"my-path-to-java-exe"          

# new.owl is a non-existing file and therefore onto has no pre-defined classes
# if you know of any nicer way to define an ontology, I'd appreciate it

onto = get_ontology("new.owl")

with onto:
    class Drug(Thing): pass
    class number_of_tablets(Drug >> int, FunctionalProperty): pass          # Creating some properties
    class price(Drug >> float, FunctionalProperty): pass
    class price_per_tablet(Drug >> float, FunctionalProperty): pass

    rule = Imp()

    # Rule: "Drug instance ?d     AND     price of ?d is ?p     AND     drug ?d has number_of_tablets = ?n
    #        AND     ?r = ?p/?n     ->      Drug ?d has price_per_tablet = ?r"
    
    rule.set_as_rule("""Drug(?d), price(?d,?p), number_of_tablets(?d,?n), divide(?r, ?p, ?n) -> price_per_tablet(?d, ?r)""")

    # Create an instance "drug" with properties defined in brackets
    drug = Drug(number_of_tablets = 10, price = 25.0)
    #print(drug.iri)

    # Syncing the reasoner infers new info
    sync_reasoner_pellet(infer_property_values = True, infer_data_property_values = True)

    # New property price_per_tablet is now added to drug and we can use it normally:
    print(drug.price_per_tablet)

# Save this ontology with rules in the same folder, filename: test
onto.save(file = "test", format = "rdfxml")

Problem: When I open the resulting file "test" in Protégé, my instance "drug1" is not a part of the previously defined class Drug but of a new class of the same name Drug (I'll always denote this one in italic so it doesn't get confusing). Interestingly, this new class Drug is not even a subclass of owl:Thing class.

I'm not sure what's the problem. According to Protégé, the defined class Drug has IRI: file:/C:/.../new#Drug, and the other class Drug has IRI: new#Drug.

When I checked IRIs of all the described objects in Python, they were all synchronized.

I'm very confused about what happened here.

I checked the "test" file and the part concerning this instance is:

<Drug rdf:about="#drug1">
  <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
  <number_of_tablets rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">10</number_of_tablets>
  <price rdf:datatype="http://www.w3.org/2001/XMLSchema#decimal">25.0</price>
  <price_per_tablet rdf:datatype="http://www.w3.org/2001/XMLSchema#decimal">2.5</price_per_tablet>
</Drug>

This is confusing because when I opened the file PizzaTutorial.owl from the famous Pizza tutorial, an instance was defined like this:

<owl:NamedIndividual rdf:about="http://www.semanticweb.org/pizzatutorial/ontologies/2020/PizzaTutorial#AmericanaHotPizza2">
        <rdf:type rdf:resource="http://www.semanticweb.org/pizzatutorial/ontologies/2020/PizzaTutorial#AmericanaHotPizza"/>
        <hasCaloricContent rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">675</hasCaloricContent>
    </owl:NamedIndividual>

What happened?!

Another question: When I inspected the individual in Protégé, I noticed that the properties number_of_tablets and price were added as Annotations, and not as Data Properties. I assume that this is the reason why my SWRL rule (which was correctly exported) doesn't conclude the price_per_tablet property for this individual when I remove the sync_reasoner line.

Please comment on anything you notice is wrong, I'm a beginner in ontology programming and in both tools and I would very much appreciate your help!



Solution 1:[1]

I found an answer!

The problem was in the base IRI, "new.owl" is not acceptable.

IRI must be formatted as a link - even if it's a fake one. For example, if IRI is "http://test.org/new.owl", my code works perfectly.

Solution 2:[2]

Regarding your extra question, there seems to be an error in how rdfxml is saved. Switching to ntriples format solves the problem with data and object properties being written out properly (exported using Owlready2 v0.37 and imported in Protégé v5.5.0)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mathbbandstuff
Solution 2 Nathan Daelman