YODA - quasylab/sibilla GitHub Wiki

Sibilla provides a module that simplifies the specification of YODA models.

A YODA model is an agent description language where the focus is on the intercommunication between agents and the environment. The former is defined in terms of 1) state, 2) observations, 3) set of actions, and 4) behaviour. In YODA, observations are provided by the system, which acts as a first-class citizen and allows the agents to communicate with each other.

YODA can be used to model scenarios where agents are required to interact with a supervisor and are able to decide themselves which action should be performed in order to reach the goal.

Each YODA model consists of a sequence of elements declaring:

Parameters

Parameters are values that can be changed even after the model has been loaded. In the Robotic model, we have:

param no = 5;
param na = 3;

where no is the number of obstacles that will be placed in the environment, and na is the number of agents that will operate in the environment.

Constants

Constants are used to associate specific values to names, and can not be changed when the model is loaded. In the Robotic model, we have:

const height = 10;
const width = 10;

where height and width are respectively the height and the width of the grid (both set to 10).

Agents

The agent declaration is the main component of a YODA model and is declared in the following manner:

agent <agentName> =
    <stateDeclaration>
    <featuresDeclaration>
    <observationsDeclaration>
    <actionsDeclaration>
    <behaviourDeclaration>
end

Now we see in detail each declaration of the agent.

Agent State

The state represents the inner knowledge of the agent. The state is fully under the control of the agent and can be modified by it. This construct is declared as follows:

state: 
    (<nameDeclaration;>)*

The component is preceded by the keyword state and the nameDeclaration is used to declare a variable, its type, and the default value.

In the Robotic Scenario, the agent state can be declared as follows:

state:
    int dirx = 0; int diry = 0;

In this example, we can highlight the direction of the agent on both axes.

Agent Features

The features are used to declare the external information of an agent, meaning that are not under its control, differently from the state. The syntax is the same as the state declaration, but the keyword features is used.

A robot may consider as its features the position it has inside the environment, as follows:

features:
    int x = 0; int y = 0;

Agent Observations

Observations refer to the capacity of the agents to sense their surroundings. The syntax is the same as the state declaration, but the keyword observations is used.

In the Robotic Scenario, the robot can observe its closer cells and can recognise if it has reached the goal area. The declaration can be the following:

observations:
    bool north = false; bool south = false; 
    bool east = false; bool west = false; 
    bool goal = false;

Agent Actions

Actions are used to allow agents to step into the next state. In this construct, we need to declare how the state fields are modified when a certain action is performed. Each action should be declared in the following manner:

<actionName> [(<stateFieldName> <- <expr>;)*]

The <actionName> is the identifier of the action that will be called later in the behaviour. The <stateFieldName> corresponds to one of the available fields in the state, which should be assigned with an <expr> of the proper type.

Robots may act as declared below:

actions :
    moveNorth [ dirx <- 0; diry <- 1;]
    moveSouth [ dirx <- 0; diry <- -1;]
    moveEast [ dirx <- 1; diry <- 0;]
    moveWest [ dirx <- -1; diry <- 0;]
    stop [ dirx <- 0; diry <- 0; ]

Considering the grid spaces as integer values, the agent is allowed only to move between cells through the axes. The directions are set according to the chosen movement, while they are set to 0 if the agent stops.

Agent Behaviour

The behaviour is the core of the agent and is composed of a set of conditions returning a certain action. In this construct, we can consider both observation and state fields because these are intrinsically known by the agent. The syntax can be declared in the following manner:

when <boolExpr> -> [ <actionName> : <weightExpr> ]
(orwhen <boolExpr> -> [ <actionName> : <weightExpr> ])*
otherwise [ <actionName> : <weightExpr> ]

The rules must have one of the three keywords at the beginning (when if it is the first rule, orwhen from the second rule, and otherwise the default one). Then, apart from the default rule, a boolean condition boolExpr has to be declared. Finally, between the square brackets, an existing action, along with a weight, must be pointed.

In the Robotic scenario, the behaviour of a robot can be written in the following way:

behaviour :
    when goal -> [ stop: 1 ]
    orwhen !north -> [ moveNorth: 1 ]
    orwhen !east -> [ moveEast: 1 ]
    orwhen !west -> [ moveWest: 1 ]
    otherwise [ stop: 1 ]

In case the agent has reached the goal area, it will stop moving. The agent tries to move north until it finds an obstacle: in that case, it will try to turn left, and finally turn right. If any of these movements are not possible, the default condition is applied, stopping the robot.

Elements

Elements in YODA represent those entities that are static and don't perform any operation. They can be declared as follows:

element <elementName> = 
    (<nameDeclaration>;)*
end

where <elementName> is the name of the element, while <nameDeclaration> is used to declare a field variable.

In the Robotic Scenario case, we can declare an Obstacle as an element that has both positions x and y. The initial value is set to 0.

element Obstacle =
    int posx = 0; int posy = 0;
end

Environment

In a YODA environment, we can identify two main components: the sensing function and the dynamic evolution.

environment : 
    sensing :
        (<agentName>[<sensingFunction>])*
    dynamic : 
        (<agentName>[<sensingFunction>])*
end

Sensing Function

In the sensing function, we update each observation of each agent previously declared using the following syntax:

<observationName> <- <expr>;

The <observationName> contains a variable that has been already declared in the agent observations set, while the <expr> is a value belonging to the same type of the corresponding observation.

Given the previous robot specification, we can write the respective sensing function in the following way:

sensing :
    Robot [
        north <- any Obstacle : (posy==it.y+1)&&(posx==it.x);
        south <- any Obstacle : (posy==it.y-1)&&(posx==it.x);
        east <- any Obstacle : (posx==it.x+1)&&(posy==it.y);
        west <- any Obstacle : (posx==it.x-1)&&(posy==it.y);
        goal <- it.y==height+1;
    ]

The cardinal observations are set to true if there is an obstacle in the position. The goal is set to true if the robot is over the height of the grid.

Dynamics Evolution

Dynamics evolution refers to a function that updates the features of each agent. The syntax for each update is the same as the one seen in the sensing function.

In the case of the Robotic Scenario, a Robot can update its position:

dynamic :
    Robot [
        x <- x + dirx;
        y <- y + diry;
    ]

As we can see, the x and y are modified considering the directions on both axes (which belong to the state).

Configuration

The configuration syntax construct is used by the simulation to initialise the system. A configuration should be expressed with the following form:

configuration <confName> : 
    (<collectiveExpression>)*
end

To accept a configuration we need a <confName>, which will be later called by the simulator. A <collectiveExpression> is an expression used to initialise the entities inside the system. It may refer to both elements and agents. In this syntax construct, we can define three types of expressions: the single instantiation, the for-loop, and the if-then-else.

In the robotic scenario, we can express a simple configuration like the one below:

configuration Main :
   for ox sampled distinct no time from U[0, width] do
      Obstacle[ posx = ox; posy = 7; ]
   endfor
   Robot[ x = 9 ; y = 0 ; ]
end

To initialise the obstacles, we can use a for-loop to create 5 (parameter no) elements. The value ox will be repeated five times, with a distinct random value between 0 and the width of the grid.

For this example, we initialise a single agent by assigning the initial position to the Robot.

It should be noted that the other attributes of agents are not initialised, thus the values will be the default ones.


Examples

In this section, we can find different examples that show how YODA models work.

The available case studies are:

  • Robotic Scenario: a model where robots have to reach a goal area while avoiding obstacles.
  • Flock: a model representing the behaviour of a flock.

Robotic Scenario

In our Robotic Scenario, a robot (the agent) has to reach a goal area located on the opposite side of its starting row.

The robot moves inside a grid environment while avoiding obstacles randomly distributed in the area.

In this case, the robot has a non-deterministic behaviour and when an obstacle is met, it may equally decide to go to its right or left. Otherwise, the robot will keep moving forward.

The example is available at the following link.

Flock

The model represents the behaviour of a Flock, or a group of birds moving around without getting dispersed.

This behaviour has been originally described by Reynolds in "Flocks, herds and schools: A distributed behavioral model".

Our version slightly differs from the original one, even if the main three policies (alignment, cohesion, and separation) are preserved. In fact, our model is based on a mean point extracted from the position of all the birds.

The example is available at the following link

⚠️ **GitHub.com Fallback** ⚠️