Discussion Forum

Problem in Rule Defining

Hello, everyone.

Thanks for all the help!

I’m trying define a rule as below

define
rule manager_transitive_rule:
when {
($x, $y) isa DEPENDENCY;
($y, $z) isa MANAGER, has playRole $pr;
} then {
(from:$x, to:$z) isa MANAGER_TRANSITIVE, has playRole $pr;
};

It reports error like

[GQL29] Graql Error: Rule 'manager_transitive_rule' 'then' '$r(from:$x, to:$z) isa MANAGER_TRANSITIVE, has playRole $pr': must be exactly one attribute ownership, or exactly one relation.

I just want to assign the attribute playRole from MANAGER to MANAGER_TRANSITIVE when the condition established in rule.

And I notice the description in documentation Rules | GRAKN.AI :

Each hashed line corresponds to a single TypeQL statement. In TypeQL, the “when” part of the rule is required to be a conjunctive pattern, whereas the “then” should describe a single has or relation. If your use case requires a rule with a disjunction (“or”) in the when part, notice that several rules with the same conclusion can be easily created to achieve the same behaviour.

Now I have one relation and one has in my conclusion, which seems not meet the requirement above. And I don’t quite understand description above. Would you please teach me how to solve it?

You cannot conclude 2 facts in the then of a rule. Your rule concludes both a new relation (isa MANAGER_TRANSITIVE, and the ownership of an attribute has $pr.

You can solve this in two ways:

option 1: put a pointer to the original manager relation into the manager-transitive, and then add another rule to “copy” the attribute ownership to the new manager-transitive separately.

define
rule manager-transitive-rule:
when {
($x, $y) isa dependency;
$r ($y, $z) isa manager, has play-role $pr;
} then {
(from:$x, to:$z, source: $r) isa manager-transitive;
};

define
rule copy-manager-play-role:
when {
  $rel (source: $r) isa manager-transitive;
  $r has play-role $pr;
} then {
  $rel has $pr;
};

option 2: encode the attribute as a new role player in the manager-transitive relation itself. Then you’ll have to query for the attribute differently in the future, plus modify your schema to accommodate this:

define
rule manager-transitive-rule:
when {
($x, $y) isa dependency;
$r ($y, $z) isa manager, has play-role $pr;
} then {
(from:$x, to:$z, source-play-role: $pr) isa manager-transitive;
};

eg. now you’ll have to search for the attribute with a query like this:

match (from :$x, to: $z, source-play-role: $pr) isa manager-transitive;

instead of

match (from: $x, to: $z) isa manager-transitive, has play-role $pr;

which you could do in option 1

1 Like

Thanks for your help! :grinning_face_with_smiling_eyes:
I’ve tested these two ways and both work.
By the way, is there any different between these two ways on resource(cpu/memory…) and time using?
If I’m going to use it in a one-million data project, which way should be better?

Hmm I’d generally say fewer rules is more efficient. However, I’d say try to model your problem in the way the closest to your domain and most intuitive, and then try to optimise the schema/rules later if they aren’t meeting your performance needs.

Our rule of thumb is: best model first, and only compromise that (which has massive value) if you really have to

Thanks for your suggestion and the rule of thumb!