Learning Resources for v1.0.x

Index


Fluents and Event Theory

Facts that can vary over time in LPS are called fluents and are associated with a cycle's timestamp. For example, the fact ready(alice) at time 2 can be represented as ready(alice, 2). All fluents that hold in the same timestamp are considered to be part of the same state.

To indicate that a term is a fluent, you need to use the fluent/1 or fluents/1 definition. For example:

fluent(ready(Person)).

Alternatively, you can also use a shorthand to indicate the number of arguments the fluent should have:

fluent(ready/1).

If you need to declare several fluents in one go, you can use the fluents/1 definition by passing a list of fluent declarations as such:

fluents([
  ready/1
]).

The initially/1 definition tells LPS about facts that should hold from time 1. For example, suppose alice is ready from time 1, you can write:

initially(ready(alice)).

LPS's event theory provisions for the initiation and termination of fluents whenever an action is executed or an external event is observed. Without any initiation or termination, unaffected fluents will persist from the current state to the next state.

Initiation

When an event or action occurs, a fluent can be initiated using the initiates/2 definition. For example, suppose the event putdown(Person, Item) initiates the fluent onFloor(Item), you can write in LPS:

initiates(putdown(Person, Item), onFloor(Item)).

When there are conditions to the initiation, initiates/2 can appear as the head of a logic program clause, where its conditions appear in the body of the clause. For example:

initiates(putdown(Person, Item), onFloor(Item)) <-
  canBePlacedOnFloor(Item).

Termination

Similarly, a fluent can be terminated using the terminates/2 definition when an event or action occurs. For example, suppose the event pickup(Person, Item) terminates the fluent onFloor(Item), you can write:

terminates(pickup(Person, Item), onFloor(Item)).

Like initiates/2, when there are conditions to the termination, terminates/2 can appear as the head of a logic program clause, where its conditions appear in the body of the clause. For example:

terminates(pickup(Person, Item), onFloor(Item)) <-
  canBePickedUp(Item).

Updating

If the initiation of a fluent depends on the termination of another fluent, the updates/3 definition can be used fluent can be terminated using the terminates/2 definition when an event or action occurs. For example, suppose the event pickup(Person, Item) terminates the fluent onFloor(Item), you can write a clause as such:

updates(
  transfer(FromPerson, ToPerson, Amount),   % action / event
  balance(FromPerson, OldAmount),           % termating fluent
  balance(FromPerson, NewAmount)            % initiating fluent
) <-
  NewAmount = OldAmount - Amount.