Skip to content

Disjunctions and preferences

Riccardo De Benedictis edited this page Sep 13, 2022 · 1 revision

Disjunctions constitute a tool offered by the language to express the fact that the solver has to take a choice. As already mentioned above, the language does not allow the possibility to define predicates having the same name, so, how can we define disjunctions? The language offers the possibility to define disjunctions through the or operator. Specifically, the syntax used for expressing disjunctions is the following:

{
  .
  .
} or {
  .
  .
} or ...

Whenever the solver encounters a disjunction construct, it non-deterministically creates a branch in the search three and executes, within each child, the code contained within each block of code (a.k.a. disjunct). It is worth noting that disjunctions can appear both in problems and within rules.

Suppose we want a rule stating that, for an agent to be at a given location, it is required either to drive to that location or to fly to the same location. We might express this disjunction within a predicate using, for example, the following code:

predicate At(Location l) {
  {
    goal d = new DriveTo(l:l);
  } or {
    goal f = new FlyTo(l:l);
  }
}

In case it is needed, it is possible to nest multiple disjunctions one inside the other. In other words, nothing prevents to define a disjunction within another disjunction.

Additionally, in order to express preferences, it is possible to assign a cost to disjuncts. Specifically, since the solver receives a penalty for each executed disjunct, it is possible to control the search so as to achieve plans having desired, yet not necessarily possible, characteristics. Costs can be expressed by adding a numeric expression, in square brackets, at the end of the corresponding disjunct. Notice that, in case the cost is not explicitly expressed, a default unitary cost is assigned. Suppose, like in the previous example, we want to state the fact that, for an agent to be at a given location, it is required either to drive to that location or to fly to the same location. However, since driving is cheaper than flying, the former is preferable to the latter. This can be expressed by means of the following code:

predicate At(Location l) {
  {
    goal d = new DriveTo(l:l);
  } [5] or {
    goal f = new FlyTo(l:l);
  } [200]
}

which give to the solver a penalty of 5, for choosing driving, and a penalty of 200 for choosing flying.