Variable Patterns in Graql Rules


#1

Hi

I need to define a Graql Rule by using Patterns that are combined into a disjunction (‘or’).
Something like:
A sub rule
when
{
$m isa entity;
$m has type $t;
{$t contains “a”;} or {$t contains “b”;};
}
then
{
<do_something>
};

Above syntax is throwing error when being used.

Please share any example showing correct syntax.


#2

Hello!

Currently we do not support having disjunctions in either the when or then parts of rules. Having said that, your rule is equivalent to the following two rules:

when
{
$m isa entity;
$m has type $t;
$t contains “a”;
}
then
{
<do_something>
};

when
{
$m isa entity;
$m has type $t;
$t contains “b”;
}
then
{
<do_something>
};

We are planning to automate this decomposition in the future. Hope that helps.

Kasper


#3

Thanks @kasper for the response.


#4

Hi @kasper,

I have an additional query.

Is there any functionality in Grakn using which we can create a Placeholder in Grakn Rule and pass a value to it Dynamically(during Run-time). Any specific API call that accepts input parameters and create Grakn Rules dynamically?


#5

Yes, you can use the Graql API, example in Java:

    public static Rule transitiveRule(RelationshipType type, Role startRole, Role endRole, GraknTx tx){
        Var startVar = Graql.var();
        Var boundVar = Graql.var();
        Var endVar = Graql.var();

        Pattern when = Graql.and(
                Graql.var()
                        .rel(startRole.label().getValue(), startVar)
                        .rel(endRole.label().getValue(), boundVar)
                        .isa(type.label().getValue()),
                Graql.var()
                        .rel(startRole.label().getValue(), boundVar)
                        .rel(endRole.label().getValue(), endVar)
                        .isa(type.label().getValue())
        );
        Pattern then = Graql.var()
                .rel(startRole.label().getValue(), startVar)
                .rel(endRole.label().getValue(), endVar);
        return tx.putRule("transitiveRule", when, then);
    }

@james can share his experiences in generating rules in Python.


#6

Thanks @kasper. Awaiting @james inputs. :slight_smile:


#7

In Python the story is a little different as we don’t have a query builder at present, as we do in Java. I had a good experience using jinja to create Graql templates and dynamically fill them with values.

You can create a file called graql_templates /my_rule.gql:

define
when
{
## if kind == "person":
$m isa person;
## elif kind == "dog":
$m isa dog;
## endif
$m has name $t;
$t contains “{{ a_val }}”;
}
then
{
$m has age {{ age_val }};
};

And then load that template from your application, supplying the variables to fill with:

# Make a Jinja environment to point to a templates directory beneath the current file, for example
DIR_PATH = os.path.dirname(os.path.realpath(__file__))
JINJA_ENV = Environment(loader=FileSystemLoader(DIR_PATH + '/graql_templates'),
                        line_statement_prefix="##")

my_rule = JINJA_ENV.get_template("my_rule.gql").render(
                a_val=a,
                age_val=age,
                kind="person"
            )
# Now we have a string of our rule definition, with our values inserted. We can now give this to Grakn to add the rule.

# Using some existing grakn transaction grakn_tx
# Add the rule to Grakn
response = grakn_tx.query(my_rule)
# Persist the rule beyond the current transaction
grakn_tx.commit()

One of the real benefits here is readability. You can view the .gql template file using an application that supports Graql syntax highlighting. This should mostly work even with the Python control flow statements such as ## if kind == "person":. That works because we set line_statement_prefix="##", so syntax highlighting treats these statements as comments, which allows us to focus on the Graql and not the controlling Python.