# Chapter 8: Predicates

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 (an individual agent, a group agent or the meta agent). Predicates take the form:

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

In the above example, the predicates are the tests within the parentheses following the `if` keyword. Multiple tests are combined using the logical `&` (meaning `and`). When multiple tests are present, the overall test will evaluate to true if and only if all the individual tests evaluate to true. For efficiency, any false test will prevent the evaluation of any later tests in the same statement.

Any single-valued expression or function described in Chapter 7 may be used as a predicate. If the expresssion evaluates to `0`, then the predicate is `false`; otherwise the predicate is `true`. For example, the following test will pass for any agent over the age of `0`:

```if (age) then ...
```

Conversely, the predicate defined in this chapter 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 <action>
```

will result in an agent executing the action 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 has been opened:

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