What is a better way to express Rxy for all x in A and y in B (closed)

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

What is a better way to express Rxy for all x in A and y in B (closed)

William
This post was updated on .
Hi~

What is a better way to express Rxy for all x in A and y in B? for example every man loves every woman.
It could be
    A.is_a.append(Not(R).only(not(B)))
but it is invalid.
Reply | Threaded
Open this post in threaded view
|

Re: What is a better way to express Rxy for all x in A and y in B

Jiba
Administrator
Hi,

The common way to solve this problem is to reify the property. For example let's consider a StaphylococcusAureus class and a Methycyline class (a bacteria class and an antibiotic class). You want to assert that all StaphylococcusAureus are resistant to all form of Methycyline.

First, reify the property: instead of the "resistant_to" property, create a Resistance class and two properties (with their inverses): has_bacteria/is_bacteria_of and has_antibiotic/is_antbiotic_of.

Second, create an instance of Resistance, let's call it r.

Third, assert that StaphylococcusAureus is_bacteria_of r (value restriction in Protégé), and that Methycyline is_antibiotic_of r (value restriction also).

Fourth, assert that r has_bacteria some StaphylococcusAureus, and has_antibiotic some Methycyline (some restriction in Protégé).

And that's it!

Jiba
Reply | Threaded
Open this post in threaded view
|

Re: What is a better way to express Rxy for all x in A and y in B

William
This post was updated on .
Hi~
So could we define a method to do that automatically. For example
 all(resistant, StaphylococcusAureus, Methycyline), after all, the class Resistance is totally technical. Anyway, It is a cute idea.


Following makes it simple.

with society:

    class Cat(Thing):
        pass

    class Dog(Thing):
        pass

    class Love(Thing):
        pass

    class is_loved(Thing>> Dog, TransitiveProperty):
        pass

    class love(Cat>> Thing, TransitiveProperty):
        inverse_property = is_loved

    l = Love('l')
    c = Cat('c')
    d = Dog('d')
 
    Cat.is_a.append(love.value(l))
    Dog.is_a.append(is_loved.value(l))


close_world(society)
#sync_reasoner(debug=1)  # raise OwlReadyInconsistentOntologyError, why? (related to CWA maybe)
print(Cat.is_a)
print(Cat.love)
print(c.love)

# OUTPUT
[owl.Thing, society.love.value(society.l), OneOf([society.c]), society.is_loved.only(owl.Nothing), society.love.only(OneOf([society.l, society.l]))]
[society.l]
[]

So, why c.love is empty and C.love ==[society.l]?

PS: why is there two 'society.l's in
OneOf([society.l, society.l]).
Reply | Threaded
Open this post in threaded view
|

Re: What is a better way to express Rxy for all x in A and y in B

Jiba
Administrator
Hi,

There is several problems in your example:

1) the domain/range are not good. Since love and is_loved are inverse properties, they should have reverse domain/ range (= the range of one property is the domain of the other, et vice versa). Otherwise, the reasoner will "deduce" that, causing inconsistencies.

2) You also need to add:

    l.is_a.append(is_loved.some(society.Cat))
    l.is_a.append(love.some(Dog))

You may also use the following Owlready shortcut, that defines the relation in both directions:

    Cat.love.append(l)
    Dog.is_loved.append(l)

It's equivalent to:

    Cat.is_a.append(love.value(l))
    Dog.is_a.append(is_loved.value(l))     l.is_a.append(is_loved.some(society.Cat))
    l.is_a.append(love.some(Dog))

Jiba
Reply | Threaded
Open this post in threaded view
|

Re: What is a better way to express Rxy for all x in A and y in B

William
Thank you for your reply. But the output is not what we want.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from owlready2 import *
test = get_ontology("http://test.org/test.owl")


with test:

    class Cat(Thing):
        pass

    class Dog(Thing):
        pass

    class Love(Thing):
        pass

    class is_loved(Thing >> Thing, TransitiveProperty):
        pass

    class love(Thing >> Thing, TransitiveProperty):
        inverse_property = is_loved

    l = Love('l')
    c = Cat('c')
    d = Dog('d')

    Cat.love.append(l)
    Dog.is_loved.append(l)
    # or the equivalent form

close_world(test)
# sync_reasoner(debug=1)  # raise OwlReadyInconsistentOntologyError
print(Cat.is_a)
print(Cat.love)
print(c.love)

# OUTPUT
[owl.Thing, test.love.value(test.l), OneOf([test.c]), test.is_loved.only(owl.Nothing), test.love.only(OneOf([test.l, test.l]))]
[test.l]
[]


PS:
Can we take a uniqueness-check for OneOf([test.l, test.l]), Are the two test.ls identified with each other?
Otherwise, we should suspect something wrong about TransitiveProperty.
PSS:
If I define
    class is_loved(TransitiveProperty):
        pass

    class love(TransitiveProperty):
        inverse_property = is_loved
it will raise AttributeError: 'inverse_property' annotation property is not defined.
Reply | Threaded
Open this post in threaded view
|

Re: What is a better way to express Rxy for all x in A and y in B

Jiba
Administrator
Hi,

The problem is caused by the transitivity of the love relation. As Cat loves i and i loves Dog, the reasoner deduce via transitivity that Cat loves Dog. But, because you closed the world, Cat loves only the entities asserted (here, i). This leads to inconsistancy.

If you want to deduce new "love" relation, you must not close them, or not entirely.

Regarding PPS, TransitiveProperty is not defined as a child of ObjectProperty in Owlready, so you need to define properties as follows : class love(ObjectProperty, TransitiveProperty): ...

Jiba