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.
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.
in_basket indicates that a particular fruit is in our basket. Note that
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
can_bake_pie indicates we have enough fruit to bake a pie. Note that
is a defined fluent. The return value of a defined fluents is always
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
: Ok, denotationally speaking they are the same thing, but practically, they're quite different.