Hi!
Thank you so much for this awesome API bringing ontology work to the modern world in Python :) I have an ontology (RDF/XML) built in Protege to the effect of: ---- Classes: Thing Ingredient Kale <--- subClassOf: hasTaste some Bitter . EquivalentTo: {kale} Taste Bitter <--- EquivalentTo: {bitter} Individuals: kale bitter Object Properties: hasTaste ---------- Notice that I've closed/reified the Kale and Bitter classes to include exactly 1 individual each. When I run the following code: from owlready2 import * world = World() onto = world.get_ontology('.../my/ontology/file.owl') print(onto.Kale.instances()) # [] sync_reasoner(world) print(onto.Kale.instances()) # [onto.kale] GOOD! print(onto.hasTaste[onto.kale]) # [] BAD; Expected: [onto.bitter] Any ideas how to make this work? I've tried wrapping it in with onto: ... But that hasn't worked either. Thanks in advance! |
Administrator
|
Hi,
Owlready was not taking into account the relation asserted at the class level. In the devlopment version, I've modified the .indirect() method so as it takes into account class-level assertions, so you can now do: list(onto.kale.hasTaste.indirect()) (it returns a generator you you need to convert it to a list for printing it) Best regards, Jiba |
Unfortunately this still returns []
print(list(onto.kale.hasTaste.indirect())) It doesn't look like it would grab SuperClass "hasSomeValuesFrom" restrictions and infer it for individuals. https://owlready2.readthedocs.io/en/latest/properties.html?highlight=.indirect()#obtaining-indirect-relations-considering-subproperty-transitivity-etc |
Administrator
|
I tested your example (its now test case prop_29 in test/regtest.py), as follows:
def test_prop_29(self): world = self.new_world() n = world.get_ontology("http://www.semanticweb.org/test.owl") with n: class Ingredient(Thing): pass class Kale(Ingredient): pass class Taste(Thing): pass class Bitter(Taste): pass class has_taste(Ingredient >> Taste): pass bitter = Bitter() Kale.is_a.append(has_taste.some(Bitter)) kale = Kale() print(kale.has_taste) print(set(kale.has_taste.indirect())) assert kale.has_taste == [] assert set(kale.has_taste.indirect()) == { Bitter } kale.has_taste.indirect() contains Bitter. It is not the instance but the class, because resolving singleton is not so simple (if you want to resolve all of them, you must take into account "same as" relations between individuals). If you really need individuals, you can remove the class Bitter, create individual bitter as an instance of Taste, and assert that: Kale.is_a.append(has_taste.value(bitter)) Jiba |
Thank you for taking this time to address this problem. I can see how resolving relationships between individuals is hard. Would it help to assume these assertions?
kale = Kale("kale") bitter = Bitter("bitter") Bitter.equivalent_to.append(OneOf([bitter])) Kale.equivalent_to.append(OneOf([kale])) AllDifferent([bitter, kale]) Kale.is_a.append(has_taste.some(Bitter)) close_world(Ingredient) Unfortunately, even with this, I'm still getting an assertion error on: assert set(kale.has_taste.indirect()) == { Bitter } We don't even want classes in triples, do we? That seems wrong. What is .indirect() really supposed to capture and what does it do that inference does not? |
Administrator
|
Hi,
The equivalent_to relation is not sufficient to "replace" Bitter (class) by bitter (individual), because it does not prevent Bitter to be equivalent to another individual, e.g. bitter2, bitter3,... If the property is asserted at the class level, I prefer to stay at that level -- changing level would require a true reasoning, but .indirect() does not do that, it just resolves transitive property and (now) gets the value asserted at the class level. In my opinion, kale.has_taste should not be though as "triple" but rather as a Python attribute. In that sense, having classes in it is not a problem. I tested the following program, and I obtain the expected results (= [t.Bitter]). Are you obtaining something else? Best regards, Jiba ----8<-------- from owlready2 import * onto_path.append('/tmp') onto = get_ontology('http://test.org/t.owl') with onto: class Ingredient(Thing): pass class Kale(Ingredient): pass class Bitter(Ingredient): pass class has_taste(Thing >> Thing): pass kale = Kale("kale") bitter = Bitter("bitter") Bitter.equivalent_to.append(OneOf([bitter])) Kale.equivalent_to.append(OneOf([kale])) AllDifferent([bitter, kale]) Kale.is_a.append(has_taste.some(Bitter)) close_world(Ingredient) print(list(kale.has_taste.indirect())) |
Free forum by Nabble | Edit this page |