Listing of Inverse Properties

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Listing of Inverse Properties

franzlst
Via Python, I have defined an inverse property ("is_idealized_by") for an existing property defined in an OWL file ("idealizes").

When accessing an individual that has this property set (artifact.is_idealized_by), I retrieve the proper value. Now I expected the inverse property "is_idealized_by" to also be listed when calling "get_properties()" on this individual, however, this is not the case.

Is this a bug? Is there another way to retrieve a list of these inverse properties?
Reply | Threaded
Open this post in threaded view
|

Re: Listing of Inverse Properties

Jiba
Administrator
Hi,

Individual.get_properties() should normally also return inverse properties. Here is an example:

from owlready2 import *

onto = get_ontology("http://test.org/t.owl")

with onto:
  class C(Thing): pass
  class p(Thing >> Thing): pass
  class i(Thing >> Thing): inverse = p

  c1 = C()
  c2 = C()

  c1.p = [c2]

print(c1.get_properties()) # prints "{t.p}"
print(c2.get_properties()) # prints "{t.i}"


In what kind of situations are you encountering this problem? Could you send me a small example to reproduce it?

Jiba
Reply | Threaded
Open this post in threaded view
|

Re: Listing of Inverse Properties

franzlst
Thank you for testing this. I could now find out, what line of code causes the example to fail:

from owlready2 import *

corax = get_ontology("http://purl.org/ieee1872-owl/corax#")
sumo_cora = get_ontology("http://purl.org/ieee1872-owl/sumo-cora#")

with corax:
    class idealizes(ObjectProperty):
        pass

with sumo_cora:
    class is_idealized_by(ObjectProperty):
        inverse_property = idealizes

corax.load(reload=True)
sumo_cora.load(reload=True)

my_design = corax.Design()
my_artifact = sumo_cora.Artifact()
my_design.idealizes.append(my_artifact)

print("artifact", my_artifact, my_artifact.is_idealized_by, my_artifact.get_properties())
print("design", my_design, my_design.idealizes, my_design.get_properties())

This code correctly prints
artifact sumo-cora.artifact1 [corax.design1] {sumo-cora.is_idealized_by}
design corax.design1 [sumo-cora.artifact1] {corax.idealizes}

However, when I comment the line "with sumo_cora:", this defining "is_idealized_by" in the corax namespace, that property is no longer listed:

artifact sumo-cora.artifact1 [corax.design1] set()
design corax.design1 [sumo-cora.artifact1] {corax.idealizes}

Is that intended?
Reply | Threaded
Open this post in threaded view
|

Re: Listing of Inverse Properties

Jiba
Administrator
Hi,

I think the problem is the use of reload(). It reloads the ontology, but previously remove its current content -- thus removing the inverse property assertion.

If you want to modify an existing ontology, you should load it, and then modify it, as follows:

from owlready2 import *

corax = get_ontology("http://purl.org/ieee1872-owl/corax#").load()
sumo_cora = get_ontology("http://purl.org/ieee1872-owl/sumo-cora#").load()

with corax:
    class idealizes(ObjectProperty):
        pass

#with sumo_cora:
    class is_idealized_by(ObjectProperty):
        inverse_property = idealizes

my_design = corax.Design()
my_artifact = sumo_cora.Artifact()
my_design.idealizes.append(my_artifact)

print("artifact", my_artifact, my_artifact.is_idealized_by, my_artifact.get_properties())
print("design", my_design, my_design.idealizes, my_design.get_properties())


This code works as expected, with is_idealized_by defined in either ontology.

Jiba
Reply | Threaded
Open this post in threaded view
|

Re: Listing of Inverse Properties

franzlst
Thank you for investigating this. Knowing that an ontology first needs to be loaded before being extended is very valuable!

I would suggest to make this clear in the documentation, too, as one can get the impression and this is not required and even not suggested:

* Forward declarations tells you, that definitions are extended (but I guess this is quite limited?)
* Associating a Python module to an OWL ontology tells you that the ontology should _not_ be loaded before extending it (but I guess that only holds true then for empty ontologies?)
Reply | Threaded
Open this post in threaded view
|

Re: Listing of Inverse Properties

franzlst
I forgot to mention that I did some more variations to see where the issue comes from. In a previous post, I showed that the code works when specifying the inverse property in another ontology using `with`. However, this does not work when setting the namespace using the class property:

with corax:
    class idealizes(ObjectProperty):
        pass

class is_idealized_by(ObjectProperty):
    namespace = sumo_cora
    inverse_property = idealizes

Reply | Threaded
Open this post in threaded view
|

Re: Listing of Inverse Properties

Jiba
Administrator
Hi,

I obtain the same results using the namespace attribute, as in the following example:


from owlready2 import *

corax = get_ontology("http://purl.org/ieee1872-owl/corax#").load()
sumo_cora = get_ontology("http://purl.org/ieee1872-owl/sumo-cora#").load()

with corax:
    class idealizes(ObjectProperty):
        pass

class is_idealized_by(ObjectProperty):
    namespace = sumo_cora
    inverse_property = idealizes

my_design = corax.Design()
my_artifact = sumo_cora.Artifact()
my_design.idealizes.append(my_artifact)

print("artifact", my_artifact, my_artifact.is_idealized_by, my_artifact.get_properties())
print("design", my_design, my_design.idealizes, my_design.get_properties())


Is it the same for you?

Jiba
Reply | Threaded
Open this post in threaded view
|

Re: Listing of Inverse Properties

franzlst
That works, yes. The issue on my side was that I did not load the ontologies before defining the properties.