# Advanced Knowledge: Plan and Rule Annotations

Analogously to Java, AgentSpeak(L++) also supports the concept of annotations.

In AgentSpeak(L++) → plans and logic rules can be modified in their execution behaviour by adding annotation(s) to them.

Contents [Hide]

## Annotations to Plans and Rules

Plans: Our plan grammar specifies that (optional) annotations, prefixed with an @ symbol, can be placed in front of plan trigger, i.e.

@annotation
+!plan <-
…
.


Rules: Analogously LightJason(L++) allows adding annotations to rules.

@annotation
rule
:- conditions
:- conditions
…
.


Note: Multiple annotations can be combined, e.g. for plans

@annotation1
@annotation2
+!plan <-
…
.


## Built-in Annotations

We currently support two built-in annotations, i.e. @parallel and @atomic, which are explained in the following in further detail.

### @atomic

The @atomic annotation defines a plan to always succeed by default. This behaviour is useful in cases where failure of → actions can be expected but do not constitute erroneous behaviour or results.

Usage:

@atomic
+!plan <-
…
.


The plan will succeed regardless of failing actions or sub-plans.

For a plan

@atomic
+!plan <-
action1();
!!immediate_subplan;
!postponed_subplan;
action2();
.

the execution flow is as depicted below

### @parallel

The @parallel annotation defines a plan to execute every action and → goal in its body in parallel, via fork-join mechanism. This behaviour is useful to speed up execution of independent actions and sub-plans.

Notes:

• If any of the parallel executed body elements fails, the whole plan fails.
• The annotation only applies to plans triggered by !! and executed in the current cycle. Plans triggered via ! will be independently executed in the following cycle. For more information on triggering see → Plan Triggering Techniques.

Usage:

@parallel
+!plan <-
…
.


For a plan

@parallel
+!plan <-
action1();
!!immediate_subplan;
!postponed_subplan;
action2();
.

the execution flow is as depicted below

## Examples

The agent script

!main.

+!main <-
!!plan << generic/print(“plan failed!”)
.

+!plan <-
generic/print(“foo”);
!!subplan1;
!!subplan2;
generic/print(“bar”)
.

+!subplan1 <-
generic/print(“sub-plan1”);
fail
.

+!subplan2 <-
generic/print(“sub-plan2”)
.


will only yield

foo
sub-plan1
plan failed!


as +!subplan1 fails and the execution stops. The << represents a → repair action.

Adding @parallel to +!plan will execute every goal trigger and action in parallel, yielding

bar
sub-plan1
foo
sub-plan2
plan failed!


(ordering of output might vary). It can be observed that, despite executing every element in the body of +!plan, the whole plan still fails, as +!subplan1 fails.

Further adding @atomic to +!plan will result in successful execution of +!plan, returning

foo
bar
sub-plan1
sub-plan2


(ordering might vary). The same effect could also be achieved by preventing !subplan1 to fail via @atomic, which is left as an exercise to the reader.

The complete example with @atomic and @parallel would be

!main.

+!main <-
!!plan << generic/print(“plan failed!”)
.

@atomic
@parallel
+!plan <-
generic/print(“foo”);
!!subplan1;
!!subplan2;
generic/print(“bar”)
.

+!subplan1 <-
generic/print(“sub-plan1”);
fail
.

+!subplan2 <-
generic/print(“sub-plan2”)
.