Chapter 8: Predicates

Rule statements can be qualified by one or more tests. Such tests are referred to as predicates. Predicates are true/false assertions that are evaluated by an agent within a state. Predicates take the form:

if (<test1> & <test2> & ... & <testN>) then <rule>

In the above example, the predicate is the collection of tests within the parentheses following the if keyword. All predicates must be preceded with if. Multiple tests are combined using the logical &. When multiple tests are present, the if statement will evaluate to true if and only if all the tests evaluate to true.

Note

Predicates may also be treated as expressions that return 1 or 0 if true or false respectively.

Any predicate may be negated by a not():

  • not(<test>) – true if <test> is false, and false if <test> is true.

For example,

if (not(<test1> & <test2> & ... & <testN>)) then <rule>

will result in an agent executing the rule if any of the tests are false.

Numeric Predicates

Predicates can use any of the comparison functions. When used in a predicate, the infix form of the comparison functions may be used instead:

infix

functional

x == y

eq(x, y)

x != y

neq(x, y)

x < y

lt(x, y)

x <= y

lte(x, y)

x > y

gt(x, y)

x >= y

gte(x, y)

Warning

Using the infix form of a comparison outside of a predicate is not allowed. For example,

x = x + gt(age, 10)  # adds 1 to x if age > 10
x = x + (age > 10)  # will result in a fred_compiler error message.

In addition to the two-way predicates above, there is a three-way numeric predicate:

  • is_in_range(<expression>, <lower_bound>, <upper_bound>) – evaluates to true if the value of the expression is between the lower and upper bounds, inclusive.

For example, the following is true if an agent’s current age is at least 15 and no greater than 20:

is_in_range(age, 15, 20)

Predicates on Lists

The following predicate can be used to check for the presence of a value in a list:

  • is_in_list(<list-expression>, <expression>) – true if the value of the list expression has an item whose value is the second argument.

For example, the following rule would apply to any agent whose ID is in the list, Agent_List:

if (is_in_list(Agent_List, id)) then ...

Predicates on Agents

The following predicates test which type of agent is evaluating the statement:

  • is_group_agent(<group>) – evaluates to true if the evaluating agent represents a group of the given type.

  • is_meta_agent() – true for the Meta agent only.

Predicates on Conditions

A predicate may depend on an agent’s state within a condition using the current_state() function. For example, the following predicate tests whether an agent is in the Exposed state in the INF condition:

if (current_state(INF) == INF.Exposed) then ...

For transmissible conditions, the following predicates depend on the exposure history of an egent:

  • was_exposed_in(<condition>, <group>) – true if the agent was exposed to the given condition in the given group.

  • was_exposed_externally(<condition>) – evaluates to true if the agent was exposed to the given condition by an importation event.

Predicates on Mixing Groups

The following predicates depend on an agents state with respect to a mixing group:

  • is_member(<group>) – evaluates to true if the agent is a member of the given group type.

  • is_skipping(<group>) – true if the agent is a member of the specified group type and is temporarily not attending the group as a result of an skip() action.

  • is_at(<group>) – true if the agent is currently attending the specified group type, e.g. is_at(School) is true during times when the agent’s school is open and agent is actually present at the school.

  • is_open(<group>) – true if the agent is a member of a group of the given group type and the group is currently open. That is, the current hour is among the usual business hours for the group type and the group has not been temporarily closed by the group agent.

  • is_group_open() – this is only permiited for group agents and is true if the agent’s group is currently open. That is, the current hour is among the usual business hours for the group type and the group has not been temporarily closed by the group agent.

  • is_temporarily_closed(<group>) – true if the agent is a member of a group of the given type and the group has been temporarily closed by the group agent.

  • was_exposed_in(<condition>, <group>) – true if the agent was exposed to the given condition in the given group.

The following predicates are specific to networks:

  • is_connected_to(<agent_id>, <network>) – true if the agent is connected to the agent with agent_id in the given network.

  • is_connected_from(<agent_id>, <network>) – true if the agent has a connection from the agent with agent_id in the given network.

Predicates on the Date

There are several ways to test the current simulated date in FRED. One way to test the date is to use the today factor in a comparison. Recall that today evaluates to a datestamp integer representing the current simulation date in the format YYYYMMDD. For example, the following predicate would be satisfied if the simulation date is 2020-Dec-15:

if (today == 20201215) then ...

The following predicate would be satisfied on any day before 2021-Mar-13:

if (today < 20210313) then ...

In the following example, either predicate would be true on any day between 2020-Dec-30 and 2021-May-28, inclusive:

variables {
    global beginDate endDate
    beginDate = 20201230
    endDate = 20210528
}
...

<COND>.<State> {
   ...
   if (beginDate <= today & today <= endDate) then ...
   if (is_in_range(today, beginDate, endDate)) then ...
   ...
}

You can also test the individual values of year, month, and day_of_month in a predicate. The following predicates are equivalent:

if (year==2020 & month == 5 & day_of_month <= 15) ...
if (year==2020 & month == May & day_of_month <= 15) ...

Note

FRED treats the three-letter abbreviation of a month as an integer between 1 (for Jan) and 12 (for Dec).

The following predicate tests whether the current simulation dates falls between two dates expressed as month and day-of-month:

  • is_date_in_range(<date1>,<date2>) – evaluates to true if the current dates is between the dates, taking into account the wrap-around nature of the calendar. Each date is a fixed string of the form MMM-DD where MMM is a three-letter abbreviation for the month.

For example, the following predicate is true if the current simulation date is between December 10 and January 1, including those dates:

if (is_date_in_range(Dec-10,Jan-01)) ...

Predicates on Files

The following predicate can be used to test is a file ahs been opened:

  • is_file_open(<filename>) – evaluates to true if the indicated filename has been opened using the open_csv(<filename>) action.