Discussion Forum

Inference to rules does not kick in at first

Hello Grakn Community!

I noticed a strange issue with rules, where inference to the rules in a query wouldn’t work until the rules themselves are “matched” first.

Here is the schema and rules, along with an example on how to use them:

# schema
    from sub role;
    to sub role;

    close-enough sub relation,
        relates from,
        relates to;

    walkable-distance sub attribute, datatype string,
        plays from,
        plays to;

    point-a-close-enough-to-point-b sub rule,
    when { $x has walkable-distance "point-a"; $y has walkable-distance "point-b"; },
    then { (from: $x, to: $y) isa close-enough; };

# usage example
    point-a sub entity, has walkable-distance;
    point-b sub entity, has walkable-distance;

# instance
insert $a isa point-a, has walkable-distance "point-a";
insert $b isa point-b, has walkable-distance "point-b";

Now load them into a keyspace called “bug”:

grakn console --keyspace bug --file schema/bug.gql      
Loading: schema/bug.gql
{$a id V20728 isa point-a;}
{$b id V12440 isa point-b;}
Successful commit: bug.gql

Now get to the console and execute queries:

grakn console --keyspace bug 

Welcome to Grakn Console. You are now in Grakn Wonderland!
Copyright (C) 2019 Grakn Labs Limited

bug> match $x (from: $y, to: $z) isa close-enough; $z has walkable-distance $to; $to == "point-b"; $y has walkable-distance $from; get;
bug> match $x (from: $y, to: $z) isa close-enough; get;
{$x id V4136 (from: id V20728, to: id V12440) isa close-enough; $y id V20728 isa point-a; $z id V12440 isa point-b;}
bug> match $x (from: $y, to: $z) isa close-enough; $z has walkable-distance $to; $to == "point-b"; $y has walkable-distance $from; get;
{$x id V4136 (from: id V20728, to: id V12440) isa close-enough; $y id V20728 isa point-a; $z id V12440 isa point-b; $from "point-a" isa walkable-distance; $to "point-b" isa walkable-distance;}

Please note that the first query returns nothing. But after the second one, the same query returns the correct result. Why wouldn’t it work the first time?

Thanks for highlighting the issue. We will look into it.

Are you using the latest version (1.6.2)?

Yes, it is,

grakn server version
grakn console version

It’s a bug in our rule validation which lets you define relation with roleplayers being types that cannot play the defined roles. It will be patched in the next release.

In this case you are missing the fact that the point types can play the from and to roles:

    point-a sub entity, has walkable-distance, plays from, plays to;
    point-b sub entity, has walkable-distance, plays from, plays to;

But is that implied? It is now so much clearer that the role playing is originated from the attributes, not the type itself. If the type (eg, point-a) must be expressed the way you highlighted, that will force me to think that the relation is on the type level, not the attribute. This is not the intention. And it would be confusing and in the meantime redundant.

Also, if the type has multiple attributes that happen to play the same roles, every time I remove an attribute from the type, I have to carefully re-determine which play statement I need to remove. This puts burdens to the developer.

So I would think keeping the expression as is and fixing the engine bug would be a much better approach.

In general, you are correct. However any relations defined via rules must still conform to the schema. The correct behaviour in your case is to throw an exception when committing your rule - the rule simply defines a scenario that is impossible to satisfy given your schema.

It could have been so much better though. As a developer I would always prefer a simpler syntax in a language.

Thanks for getting back to me.

All feedback is welcome. How would you envisage the syntax and the behaviour then?

Is it to silently allow the rule even though it doesn’t make sense schema-wise in the hope that future schema additions may trigger it?

I think the syntax of the schema is fine. The problem is in the implementation, i.e., in the rule engine itself. So I would imagine it would a relatively straight-forward fix. But then since I don’t know much of the implementation, I could be very wrong on this.

However, I do like the current syntax. The mechanism of allowing attribute playing the role of a relation and freeing the type from having to play that role is very similar to the idea of of object composition in the object oriented world. I am with oo background so this idea of using attribute to play the role comes naturally. It would a be shame to remove it.