Rafael Kalachev
Rafael Kalachev

Reputation: 11

Issue with Infering attribures from master if child entity does not have them in TypeDB

Hi I'm having the following issue.

In my database there are some entities (requirement) that have a set of attributes (name, req-type, description). and an entity can be "branched" from another. The idea is to infer that all the attributes that the child entity did not overwrite should be taken from the master entity.

Here is the existing schema.

> database schema test-req-branch
define

description sub attribute,
    value string;

name sub attribute,
    value string;

req-type sub attribute,
    value string;

req-branching sub relation,
    relates branch-item,
    relates branched-from;

requirement sub entity,
    owns description,
    owns name,
    owns req-type,
    plays req-branching:branch-item,
    plays req-branching:branched-from;

and the dummy data

test-req-branch::data::read> match $e isa entity, has $a;
                             get $e, $a; group $e;
                             
iid 0x826e80018000000000000001 isa requirement => {
    {
        $a "master" isa name;
        $e iid 0x826e80018000000000000001 isa requirement;
    }
    {
        $a "demo master" isa description;
        $e iid 0x826e80018000000000000001 isa requirement;
    }
    {
        $a "whatever" isa req-type;
        $e iid 0x826e80018000000000000001 isa requirement;
    }
}
iid 0x826e80018000000000000000 isa requirement => {
    {
        $a "other" isa name;
        $e iid 0x826e80018000000000000000 isa requirement;
    }
}
answers: 2, total (with concept details) duration: 12 ms


test-req-branch::data::read> match $r (branch-item:$bi, branched-from:$bf)isa req-branching;
                             $bf has name $bfn;
                             $bi has name $bin;
                             
{
    $r iid 0x847080018000000000000000 (branch-item: iid 0x826e80018000000000000000, branched-from: iid 0x826e80018000000000000001) isa req-branching;
    $bf iid 0x826e80018000000000000001 isa requirement;
    $bin "other" isa name;
    $bi iid 0x826e80018000000000000000 isa requirement;
    $bfn "master" isa name;
}
answers: 1, total (with concept details) duration: 8 ms

wince the master requirement has (name, req-type, description) and the child entity "other" has only (name) I want to infer req-type and description form the master.

I devised a query that gets the attributes that the child entity does not have.

test-req-branch::data::read> match 
                             $rr (branched-from:$rm, branch-item:$cr) isa req-branching;
                             $rm has  $ma;
                             $cr has attribute $ca;
                             $ma isa! $t;
                             not {
                                 $ca isa! $t;
                             };
                             get $ma;
                             
{ $ma "demo master" isa description; }
{ $ma "whatever" isa req-type; }
answers: 2, total (with concept details) duration: 5 ms

And I converted this into a rule:

rule when-not-defined-attributes-derive-from-parent:
    when
    {
        $rr (branched-from: $rm, branch-item: $cr) isa req-branching;
        $rm has $ma;
        $cr has attribute $ca;
        $ma isa! $t;
        not
        {
            $ca isa! $t;
        };
    }
    then
    {
        $cr has $ma;
    };

But when i queried the attributes I got the master's name attached to the child as well.

> transaction test-req-branch data read --infer true
test-req-branch::data::read> match $rr (branched-from: $rm, branch-item: $cr) isa req-branching;
                             $cr has $a;
                             get $a;
                             
{ $a "other" isa name; }
{ $a "whatever" isa req-type; }
{ $a "demo master" isa description; }
{ $a "master" isa name; }
answers: 4, total (with concept details) duration: 91 ms

What am I doing wrong?


PS: I'm using the typedb docker image:

sudo docker ps 
CONTAINER ID   IMAGE                   COMMAND                  CREATED      STATUS      PORTS                                       NAMES
b8e4d1200059   vaticle/typedb:latest   "/opt/typedb-all-lin…"   4 days ago   Up 4 days   0.0.0.0:1729->1729/tcp, :::1729->1729/tcp   typedb
./typedb console --version
2.11.0
2.11.0

Upvotes: 0

Views: 71

Answers (1)

Dmitrii Ubskii
Dmitrii Ubskii

Reputation: 26

That match query is not correct for what you're trying to achieve, which you would have noticed had the branch-item had another attribute. I've added req-type "blah" to the item, and this is what what I got:

test-req-branch::data::read> match
                             $rr (branched-from:$rm, branch-item:$cr) isa req-branching;
                             $rm has  $ma;
                             $cr has attribute $ca;
                             $ma isa! $t;
                             not {
                                 $ca isa! $t;
                             };
                             get $ma;

{ $ma "master" isa name; }
{ $ma "demo master" isa description; }
{ $ma "whatever" isa req-type; }

To understand why, let's take a look at what the result of the query looks like before negation.

test-req-branch::data::read> match
                             $rr (branched-from:$rm, branch-item:$cr) isa req-branching;
                             $rm has  $ma;
                             $cr has attribute $ca;
                             get $ma, $ca;

{   $ma "whatever" isa req-type;
    $ca "blah" isa req-type; }
{   $ma "master" isa name;
    $ca "blah" isa req-type; }
{   $ma "demo master" isa description;
    $ca "blah" isa req-type; }
{   $ma "whatever" isa req-type;
    $ca "other" isa name; }
{   $ma "master" isa name;
    $ca "other" isa name; }
{   $ma "demo master" isa description;
    $ca "other" isa name; }

The negation acts as a sort of filter on all these pairs of attributes $ca and $ma. If they have different types, i.e. $ma isa! $t; not { $ca isa! $t; };, then $ma is a valid output. But if $ca has two potential types, we're guaranteed to find one that doesn't match $t! So we'll get all the attributes of the branched-from entity.

A solution would be to tweak the query like so:

test-req-branch::data::read> match
                             $rr (branched-from:$rm, branch-item:$cr) isa req-branching;
                             $rm has  $ma;
                             $ma isa! $t;
                             not {
                                 $cr has $ca;
                                 $ca isa! $t;
                             };
                             get $ma;

{ $ma "demo master" isa description; }

Here, the negation acts as a filter on $ma alone. For each $ma, as long as there is at least one $ca with the same type, we reject it.

Unfortunately, this won't work as a rule. The negation as part of the query essentially boild the rule down to "if $cr does not have an attribute with the type of $ma, then it has $ma". But that means that it has an attribute with the type of $ma, namely, $ma! This causes a contradiction (A cycle containing negation(s) that can cause inference contradictions), and so the rule is invalid.

P.S. Thanks to Krishnan Govindraj for his help with this answer.

Upvotes: 1

Related Questions