Cardinality restrictions

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

Cardinality restrictions

Rusne
Hello!

I am having a problem using cardinality restrictions in owlready. The following code illustrates the problem:

with onto:

    class Entity(Thing):
        pass

    class relates(ObjectProperty):
        pass

    class TestRelation1(Thing):
        equivalent_to = [onto.relates.exactly(2, onto.Entity)]

    class TestRelation2(Thing):
        equivalent_to = [onto.relates.some(onto.Entity)]


    relation = onto.Entity("Relation",
                                      relates=[onto.Entity("Actor1"), onto.Entity("Actor2")]
                                   )

    sync_reasoner()

    for inst in onto.TestRelation1.instances():
        print("Exactly:", inst)

    for inst in onto.TestRelation2.instances():
        print("Some:", inst)

Executing this code prints only "Some: onto.Flow1"

I would expect that as my "Relation" relates exactly two Entities, it would get classified as both TestRelation1 and TestRelation2, however, it only gets classified as TestRelation2. The same happens if I am using .min(2, Entity) or .max(2, Entity).

Could you explain why this is happening? How should I write this code to get "Relation" classified as "TestRelation1"?

I am using owlready2 v0.8

Thank you!
Reply | Threaded
Open this post in threaded view
|

Re: Cardinality restrictions

Jiba
Administrator
Hello,

This is a common "trap" in formal reasoning. Here, you asserted that the individual Relation is related to Actor1 and Actor2.

However, the reasoning works under the "open-world assumption" : every fact non asserted is not considered as false but as possible.
Here, there might be an (unasserted) Actor3 that is related to Relation, thus Relation is not classified in TestRelation1.
In addition, the reasoner also considers that Actor1 and Actor2 might be the same individual. Consequently, you cannot be sure that there is at least 2 * different * actors (this explain why you did not obtain the expected results with min(2,..)).

To solve this problem, you need :

First, to assert that the two Actors are different:

    AllDisjoint([onto.Actor1, onto.Actor2])


Second, to assert that Relation is not related to any other actors:

    relation.is_a.append(relates.only(OneOf([onto.Actor1, onto.Actor2])))

This second step can also be automated using Owlready close_world function:

    close_world(relation)


Best regards,
Jiba