Step 2: Relationships ❤️
If we've defined our sorts, we're well on our way to a working model of our system. But sorts aren't enough: as they say, life is all about relationships. In ALM, we capture relationships with functions. These are functions in the mathematical sense: they aren't a unit of computation like in imperative or functional programming - rather, they are just labels that map elements of zero or more sorts into another sort[1].
There are two kinds of functions in ALM: statics, whose mappings never change, and fluents, whose mappings change over time as a consequence of actions. Fluents come in two flavors, basic and defined - we'll address the difference shortly.
Let's extend our fruit example with some statics and fluents:
Our first function, the static good_for_baking
will be used to denote whether a variety
of apple can be used in making a pie.
The fluent in_basket
indicates that a particular fruit is in our basket. Note that in_basket
is a basic fluent. Basic fluents have inertia: if you put a fruit in the basket, it will stay
there until you remove it.
The basic fluent basket_is_full
describes when we can't fit any more fruit in the basket.
As a function, it takes zero parameters; hence it doesn't have the ->
.
The fluent can_bake_pie
indicates we have enough fruit to bake a pie. Note that can_bake_pie
is a defined fluent. The return value of a defined fluents is always booleans
.
Additionally, defined fluents do not have inertia - they are only true when something makes
them true, and immediately become false if there conditions are not satisfied (we'll define the
conditions for can_bake_pie
shortly).
[1]: Ok, denotationally speaking they are the same thing, but practically, they're quite different.