Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define a transitive relation in graql

my model consists of organizations that have projects and the projects have buckets. The buckets can be shared to other projects in the same organization. I defined a rule for project sharing which means that two projects are in this relation when first is sharing a bucket with the other.

    define

    organization sub entity,
        plays organizationRole,
        key identifier;

    project sub entity,
        plays projectRole,
        plays projectSourceRole, 
        plays projectTargetRole,
        plays transitiveProjectSourceRole,
        plays transitiveProjectTargetRole,
        key identifier;

    bucket sub entity,
        plays bucketRole,
        plays sharedBucketSourceRole,
        plays sharedBucketTargetRole,
        key identifier;


    organizationToProject sub relation,
        relates organizationRole,
        relates projectRole;

    projectToBucket sub relation,
        relates projectRole,
        relates bucketRole;

    sharedBucket sub relation,
        relates sharedBucketSourceRole,
        relates sharedBucketTargetRole;

    projectSharing sub relation,
        relates projectSourceRole,
        relates projectTargetRole;

    project-sharing sub rule, 
      when { 
        (projectRole: $ps, bucketRole: $bs) isa projectToBucket; 
        (projectRole: $pt, bucketRole: $bt) isa projectToBucket;
        (sharedBucketSourceRole: $bs, sharedBucketTargetRole: $bt) isa sharedBucket;
        $ps != $pt;
      }, then { 
        (projectSourceRole: $ps, projectTargetRole: $pt) isa projectSharing; 
      };

It works fine. (see enter image description here)

But I want to define a rule for transitive relation (according to some ancestry example I found in the docs) so I added to the schema:

    transitiveProjectSharing sub relation,
        relates transitiveProjectSourceRole,
        relates transitiveProjectTargetRole;

    transitive-project-sharing sub rule,
      when {
        (projectSourceRole: $a, projectTargetRole: $b) isa projectSharing;
        (projectSourceRole: $b, projectTargetRole: $c) isa projectSharing; 
      }, then {
        (transitiveProjectSourceRole: $a, transitiveProjectTargetRole: $c) isa transitiveProjectSharing;
      };

It finds nothing (but there are several transitive ones, see enter image description here)

Would anyone have a suggestion where is the mistake?

like image 894
JakubM Avatar asked Nov 11 '19 13:11

JakubM


People also ask

How do you identify a transitive relationship?

In mathematics, a relation R on a set X is transitive if, for all elements a, b, c in X, whenever R relates a to b and b to c, then R also relates a to c.

What makes a relation transitive?

Transitive relations are binary relations defined on a set such that if the first element is related to the second element, and the second element is related to the third element of the set, then the first element must be related to the third element.

Can a set with 2 elements be transitive?

Say we have the relation R on the set {a,b}. Then provided aRa, bRb, aRb AND bRa, so that R{(a,a),(b,b),(a,b),(b,a)}, then R is reflexive, and symmetric, and must therefore be transitive, given there are only two elements. This is what really clarified it for me!

How many transitive relations are there in a set?

Ans. 3 Transitive relations are binary relations in set theory that are defined on a set X such that component 'p' must be associated to element 'r', if 'p' is related to 'q' and 'q' is related to 'r', for p, q, r in X. Q.


2 Answers

I've got a hint from Grakn.ai Slack. The transitivity should be defined on the projectSharing role itself, additional transitiveProjectSharing is not necessary. So the definition should be:

transitive-project-sharing sub rule,
  when {
    (projectSourceRole: $a, projectTargetRole: $b) isa projectSharing;
    (projectSourceRole: $b, projectTargetRole: $c) isa projectSharing; 
  }, then {
    (projectSourceRole: $a, projectTargetRole: $c) isa projectSharing; 
  };

and the query works well: enter image description here

like image 86
JakubM Avatar answered Sep 28 '22 21:09

JakubM


As a slight improvement over your awesomely elegant answer (thanks!!), you can also use subtyping to differentiate explicit relationships from inferred relationships:

indirectProjectSharing sub projectSharing;

transitive-project-sharing sub rule,
  when {
    (projectSourceRole: $a, projectTargetRole: $b) isa projectSharing;
    (projectSourceRole: $b, projectTargetRole: $c) isa projectSharing; 
  }, then {
    (projectSourceRole: $a, projectTargetRole: $c) isa indirectProjectSharing; 
  };

Since indirectProjectSharing is a subtype of projectSharing, the rule's condition will match both relations, and you'll be able to refer to either type in your own queries depending on the use case.

like image 33
David Ammouial Avatar answered Sep 28 '22 21:09

David Ammouial