# Chapter 7: Expression and Functions

## Expressions

FRED models include expressions that evaluate to either a single numerical value or a lists of values.

Expressions are always evaluated with respect to a single agent, called the evaluating agent. The evaluating agent may be an ordinary agent, a group agent, or the Meta agent.

Expressions may include any read-only variable described in Chapter 6. In addition, expressions can include:

### single-valued expressions

Single-valued expressions are expressions that evaluate to a numerical value. FRED includes both shared and agent variables, each capable of storing the result of a single-valued expression. Agent variables may have distinct values for eaxch agent. Shared variables are shared by all agents–each agent “sees” the same value. A shared table variable may also store single valued expressions.

An example of a single-valued expression:

my_eligibility_to_vote = gte(age, 18)


In this example, an agent is setting the my_eligibility_to_vote variable to 1 if the agent is at least 18 years old and 0 otherwise. In this expression, the variable age is evaluated with respect to the agent evaluating the expression.

The mathematical operators +, -, *, / , and % will produce single-valued expressions if both arguments are single-valued:

• <expression> + <expression> : returns the sum of the expressions.

• <expression> - <expression> : returns the difference of the expressions.

• <expression> * <expression> : returns the product of the expressions.

• <expression> / <expression> : returns the quotient of the expressions.

• <expression> % <expression> : returns modulus of expressions.

The following examples may help clarify how the mathematical operators act on single-valued expressions:

x = 1 + 2  # 3
x = 2 - 1  # 1
x = 2 * 3  # 6
x = 6 / 3  # 2
x = 6 % 5  # 1


Finally, accessing an element of a table will result in a single-valued expression:

• <table>[key] : returns a value associated with a key from a table.

### list-valued expressions

List-valued expressions are expressions that evaluate to lists of numerical values. FRED includes both shared and agent list-variables, each capable of storing the result of a list-valued expression. Agent list-variables are agent-specific lists of values, while shared list-variables are accessible by all agents.

An example of a list-expression:

my_housemates = members(Household)


In this example, an agent is setting a list-variable, my_housemates, to a list of all agents who are members of the evaluating agent’s household. The members() function returns a list of agent ID numbers.

A list-valued expression may consist of a simple list, e.g. list(1, 2, 3, 4). A list may be composed of either numerical values or other lists, for example:

old_list = list(1, 2, 3)
new_list = list(4, old_list, 5)


The list-variable, new_list, contains the list-valued expression list(4, 1, 2, 3, 5). list() is an example of a function that returns a list:

• list(<expression>, <expression>, ..., <expression>) – returns the list of values of the given expressions.

Note

Each argument may be single-valued or list-valued. The result is always flattened into single list.

The mathematical operators +, -, * and / can produce list-valued expressions if either argument is a list:

• <list_expression> + <expression> returns a list of values consisting of the sum of the single-valued expression and each of the values in the list.

• <expression> - <list_expression> - returns a list of values consisting of the difference of the first expression and each of the values in the list.

• <list_expression> - <expression> - returns a list of values consisting of the difference of each of the values in the list with the value of the second expression.

• <list_expression> - <list_expression> - returns a list of values consisting of the difference of the items in the first list with the corresponding items in the second list. The lists must have equal lengths.

• <list_expression> * <expression> - returns a list of values consisting of the product of the single-valued expression and each of the values in the list.

• <list_expression> * <list_expression> - returns a list of values consisting of the product of the items in the first list with the corresponding items in the second list.

• <expression> / <list_expression> - returns a list of values consisting of the quotient of the first expression and each of the values in the list.

• <list_expression> / <expression>) - returns a list of values consisting of the quotient of each of the values in the list with the value of the second expression.

• <list_expression> / <list_expression> - returns a list of values consisting of the quotient of the items in the first list with the corresponding items in the second list. The lists must have equal lengths.

Note

The add(), sub(), mult() and div() functional form of the mathematical operators all take list-valued arguments. If either or both arguments is a list, the result is a list of values.

Note

The addition and multiplication operators, + and *, are commutative, i.e reversing the order will result in the same expression.

The following examples may help clarify how the mathematical operators act on lists:

x_list = list(1, 2, 3)
y_list = list(10, 20, 30)

x = 10 + x_list  # list(11, 12, 13)

# subtraction
x = 10 - x_list  # list(9, 8, 7)
x = x_list - 10  # list(-9, -8, -7)
z_list = y_list - x_list  # list(9, 18, 27)

# multiplication
x = x_list * 10  # list(10, 20, 30)
x = 10 * x_list  # list(10, 20, 30)
z_list = y_list * y_list  # list(10, 40, 90)

# division
x = x_list / 2  # list(0.5, 1.0, 1.5)
x = 1.5 / x_list  # list(1.5, 0.75, 0.5)
z_list = y_lixt / x_list  # list(10, 10, 10)


The following returns a list of integers:

• range(start,stop,step) - returns a list of integers from start in increments of step up (or down if step < 0) to but not including stop. If two arguments are given, the step is assumed to be 1. If only one argument is given, then start = 0 and step = 1. So range(5) returns the list (0, 1, 2,\ 3, 4). It is an error if step = 0. The list is empty if step > 0 and stop <= start, or if step < 0 and start <= stop.

Accessing an element of a list-table will result in a list-valued expression:

• <list-table>[key] : returns a list associated with a key from a list-table.

Finally, accessing a list of elements in a table will result in a list-valued expression:

• <table>[<list_expression>] : returns a list of values associated with a list of keys.

### table-valued expressions

Table-valued expressions are expressions that evaluate to a table or list-table consisting of key-value pairs. Table variables are capable of storing the result of a table-valued expression.

Tables and list-tables are data structures consisting of key-value pairs. For tables, the values are real numbers. For list-tables, the values are lists. All tables are shared variables accessible by all agents.

## Numerical Operators

Expressions may contain the usual numerical operators +, -, *, /, and % for addition, subtraction, multiplication, division, and the modulo operator. Each of these can be expressed either in infix or prefix notation:

infix

prefix

x + y

add(x, y)

x - y

sub(x, y)

x * y

mult(x, y)

x / y

div(x, y)

x % y

mod(x, y)

Note

The numerical operators +, -, *, /, and % are expressed in infix notation, where A + B is a synonym for add(A, B), etc. FRED parses expressions into prefix notation prior to execution, so you may see the prefix form in error and warning messages.

Note

The numerical operators +, -, *, and / apply to list-valued arguments as well as mixed single-valued and list-valued arguments.

Warning

Division by zero will cause FRED to abort a simulation with an appropriate error message.

## Input Functions

FRED supports input function that read from files. The following function returns a list of values:

• read(filename, column) – returns a list of numeric values in the indicated from the named comma-separated value file. Column numbers begin with 0. Blank lines in the file are skipped, as are any lines with a non-numeric value in the first column.

## Mathematical Functions

FRED supports a number of mathematical functions:

### comparison

• equal(x, y) – returns 1 if the arguments are equal, 0 otherwise.

• eq(x, y) – synonym for equal(x, y).

• neq(x, y) - returns 1 if the arguments are not equal, 0 otherwise.

• lt(x, y) - returns 1 if x is less than y, 0 otherwise.

• lte(x, y) - returns 1 if x is less than or equal to y, 0 otherwise.

• gt(x, y) - returns 1 if x is greater than y, 0 otherwise.

• gte(x, y) - returns 1 if x is greater than or equal to y, 0 otherwise.

### rounding and remainder

• floor(x) – returns the largest integral value less than or equal to x.

• ceil(x) – returns the largest integral value greater than or equal to x.

• int(x) – returns the integer part of x. the result is equal to floor(x) if x is non-negative and ceil(x) if x is negative.

• round(x) – returns the integral value nearest to x, rounding half-way cases away from zero.

### exponential, logarithmic, and power

• log(x) - returns the base $$e$$ logarithm of x, $$\log_e(x)$$

• pow(x, y) - returns the base, x, raised to the power exponent, y, $$x^y$$

• exp(x) - returns the base $$e$$ exponential of x, which is $$e$$ raised to the power x, $$e^x$$.

• sqrt(x) - returns the square root of x.

### trigonometric

• sin(x) – returns the sine of x, where x is interpreted as radians.

• cos(x) – returns the cosine of x, where x is interpreted as radians.

• tan(x) – returns the tangent of x, where x is interpreted as radians.

• asin(x) – returns the principal value of the inverse sine of x. The result is in the range $$[-\pi/2, \pi/2]$$.

• acos(x) – returns the principle value of the inverse cosine of x. The result is in the range $$[0, \pi]$$.

• atan(x) – returns the principal value of the inverse tangent of x. The result is in the range $$[-\pi/2, \pi/2]$$.

• atan2(y, x) – returns the principal value of the inverse tangent of y/x using the signs of both arguments to determine the quadrant of the returned value.

• sinh(x) – returns the hyperbolic sine of x.

• cosh(x) – returns the hyperbolic cosine of x.

• tanh(x) – returns the hyperbolic tangent of x.

• asinh(x) – returns the inverse hyperbolic sine of x.

• acosh(x) – returns the principle value of the inverse hyperbolic cosine of x. The result is in the range $$[0, \infty]$$.

• atanh(x) – returns the inverse hyperbolic tangent of x.

### miscellaneous

• min(x, y) – returns the smallest of the two values.

• max(x, y) – returns the largest of the two values.

• abs(x) – returns the absolute value of x.

• nprob(p, n) – returns the probability, math:q, such that, when an agent makes n repeated independent choices with probability of success :mathq, the total probability of success is p. This is equivalent to the expression 1- pow(1 - p, 1 / n).

• distance(lat1, lon1, lat2, lon2) – returns the distance in km between the points, (lat1, lon1) and (lat2, lon2), on the surface of the Earth.

Warning

Illegal operations using mathematical functions will cause FRED to abort a simulation with an appropriate error message. Examples of illegal operations include taking the logarithm of a negative number or taking the inverse sine of a number outside the range [-1,1].

## Statistical Distribution Functions

FRED provides the following functions that return draws from statistical distributions:

• bernoulli(p) – returns 1 with probability p, otherwise 0.

• binomial(t, p) – returns an integer according to a binomial discrete distribution. This distribution produces random integers in the range $$[0, t]$$, where each value represents the number of successes in a sequence of t trials (each with a probability of success equal to p).

• cauchy(a, b) – returns a floating point number according to a Cauchy distribution with a median a and shape parameter, b. This is equivalent to a Student-t distribution with one degree of freedom.

• chi_squared(n) – returns a floating point number according to a chi-squared distribution. This distribution produces random numbers as if the square of n independent standard normal random variables with $$\mu=0$$ and $$\sigma=1$$, were aggregated, where n is the distribution parameter, known as degrees of freedom.

• exponential(λ) – returns a floating point number according to an exponential distribution. This distribution produces random numbers where each value represents the interval between two random events that are independent but statistically defined by a constant average rate of occurrence, λ.

• extreme_value(a, b) – returns a floating point number according to a Type I extreme value distribution. This distribution produces random numbers where each value can be interpreted as the extreme (maximum or minimum) of a number of samples of a random variable.

• fisher_f(m, n) – returns a floating point number according to a Fisher-F distribution. This distribution produces random numbers as the result of dividing two independent Chi-squared distributions of m with n degrees of freedom.

• gamma(α, β) – returns a floating point number according to a Gamma distribution. This distribution can be interpreted as the aggregation of α exponential distributions, each with β as parameter. It is often used to model waiting times.

• gompertz(shape, scale) – returns a floating point random number according to a Gompertz distribution.

• lognormal(median, dispersion) – returns a floating point random number according to a lognormal distribution with the given median and dispersion.

Note

The default parameterization is the “multiplicative”, also known as the “geometric parameterization”, i.e., median = exp(μ) and dispersion = exp(σ).

• negative_binomial(k, p) – returns a random integer according to a negative binomial discrete distribution. This distribution produces random integers where each value represents the number of successful trials before k unsuccessful trials happen in a sequence of trials, each with a probability of success equal to p.

• normal(μ, σ) – returns a floating point random number from a normal distribution with a given μ and standard deviation, σ.

• poisson(λ) – returns an integer value drawn from a Poisson distribution with a mean λ.

• student_t(n) – returns a floating point random number according to a Student-T distribution with n degrees of freedom. This distribution produces random numbers as the result of normalizing the values of a relatively small sample ($$n+1$$ values) of independent normally-distributed values. As the sample size increases, the distribution approaches a standard normal distribution.

• uniform(l, u) – returns a uniform random number in range [l, u).

• weibull(a, b) – returns a floating point random number according to a 2-parameter Weibull distribution with a probability density function of:

$p(x|a,b) = \frac{a}{b}\left( \frac{x}{b}\right)^{a-1}e^{-\left(\frac{x}{b}\right)^a}$

## Date and Time Functions

FRED operates in steps each representing one hour of simulated time. The functions in this section are often used in connection with wait rules to control the amount of time an agent spends in a given state.

The following function returns the simulation step corresponding to a given date and hour:

• sim_step(year, month, day, hour) – returns the simulation time step corresponding to the given date and hour. For example, sim_step(2020, 6, 16, 19) returns the simulation time step corresponding to June 6, 2020 at 7pm.

Note

sim_step(year, month, day) is equivalent to sim_step(year, month, day, 0).

Often this function is used in combination with wait rules. For example, the following wait rule would cause an agent to wait until the simulation time step corresponding to Aug 12 at 2 a.m. during the year represented by the variable Yr:

wait(sim_step(Yr, 8, 12, 2) - now)


The until() function returns the number of hours until the specified date and time:

• until(year, month, day_of_month, hour)

For example, the following wait rule would wait until 2020-Dec-31 at 11 p.m.

wait(until(2020, 12, 31, 23))


The until() function understands symbolic terms for months and hours, so the above could also be written as:

wait(until(2020, Dec, 31, 11pm))


If three arguments are given of the form until(month, day, hour), where the first argument is the symbolic name of the month, the function returns the number of hours until the next occurrence of the given date and time.

For example, the following makes an agent wait until 11 p.m. on the next New Year’s Eve:

wait(until(Dec, 31, 11pm))


The until() function also accepts two arguments, as long as the first argument is a symbolic name for a month or a day of the week, for example:

wait(until(Sat, 11pm))
wait(until(Dec, 31))


In the latter case, the hour is assumed to be 12am.

If a single argument is given consisting of a number following by am or pm, until() returns the number of hours until the next occurrence of the indicated time, for example:

wait(until(1pm))


Finally, if until() is given a single argument not in the format <number>am or <number>pm, the argument is interpreted as a timestamp or a datestamp:

• A timestamp is an expression that evaluates to a number of the form YYYYMMDDHH, where YYYY represents the year, MM represents the month (with values 01, ..., 12), and HH represents the hour on a 24-hour clock (with values 00, ..., 23.

You can construct a timestamp using the the formula:

my_timestamp = 1000000 * year + 10000 * month + 100 * day_of_month + hour

• A datestamp is an expression that evaluates to a number of the form YYYYMMDD.

The formula for a datestamp is:

my_datestamp = 10000 * year + 100 * month + day_of_month


For example, we might have a variable next_change whose current value is 20201104 (a valid datestamp). Then the following makes an agent wait until 2020-Nov-04 at 12 a.m.:

wait(until(next_change))


If the current value of next_change is the timestamp 2020110413, then the following makes an agent wait until 2020-Nov-04 at 1 p.m.:

wait(until(next_change))


If the expression does not evaluate to a valid timestamp or datestamp, a run-time error will occur and the simulation will be terminated.

The following function is useful for finding the time between two specified timestamps:

• steps_between(<timestamp1>, <timestamp2>) returns the number of time steps between the two timestamps.

• The result is positive if <timestamp1> occurs before <timestamp2>.

• If the timestamps are equal, steps_between() returns 0.

• If either timestamp evaluates to a datestamp value of the form YYYYMMDD, it is interpreted as YYYYMMDDHH where HH = 00.

• An error is thrown if either timestamp is not valid.

The following function extract the components of a timestamp:

• get_year_from_timestamp(<timestamp>) returns the value of the YYYY portion of the timestamp.

• get_month_from_timestamp(<timestamp>) returns the value of the MM portion of the timestamp.

• get_day_from_timestamp(<timestamp>) returns the value of the DD portion of the timestamp.

• get_hour_from_timestamp(<timestamp>) returns the value of the HH portion of the timestamp.

Timestamps are correctly computed for 100 years before the start_date to 100 years after the end_date. Outside this range, the results are unpredictable.

## Functions on Conditions

• current_count(<condition_name>.<state_name>, <group_name>) - returns the number of agents currently in the given state. The second argument is optional. If a group name is provided, the count is restricted to agents that share the given group with the agent.

• current_state(<condition_name>) - returns the current state of the agent in the given condition.

• daily_count(<condition_name>.<state_name>, <group_name>) - returns the number of agents that entered the given state on the previous day. The second argument is optional. If a group name is provided, the count is restricted to agents that share the given group with the agent.

• source(<condition_name>.<state_name>, <group_name>) - returns the agent ID of the transmission source for the given condition.

• transmissions(<condition_name>.<state_name>, <group_name>) - returns the number of other agents that have been exposed to the given condition by the current agent. The result is 0 if the agent has not transmitted the condition.

• total_count(<condition_name>.<state_name>, <group_name>) - returns the total number of agents that have ever entered the given state. The second argument is optional. If a group name is provided, the count is restricted to agents that share the given group with the agent.

• prev_state(<condition_name>) - returns the agent’s previous state before transitioning to the current state.

Note

The previous transition may have been from the current state.

• sus_list(<condition_name>) - returns the list of agents that are susceptible to a condition, i.e. agents who have a susceptibility greater than 0.0.

## Functions on Groups

• get_group_id(<group_name>) - returns the group ID of the named group, or 0 if the calling agent is not a member of such a group.

• current_place() - returns the place ID of the place that the agent is visiting at the current time, or 0 if the agent is not at any place.

### associated agents

• size(Population) - returns the number of ordinary agents in the population.

• size(<group>) - returns the number of

members in the ordinary agent’s given group. Returns 0 if the agent has no such group.

• size(<expression>) - returns the number of

members in the group whose ID is the value of the expression. Error occurs if the expression does not evaluate to agroup ID.

• get_size() - returns the number of members in a group agent’s group. Error occurs if called by a non-group agent.

• members(<group>, <group>, ..., <group>) - returns a list of all agents who share one or more of the groups with the agent.

For example,

new_list = members(Household, Classroom)

returns a list of all the agents who are in the agent’s household or
classroom, or both. Each agent appears at most once in the resulting list.
The result is sorted by agent ID numbers.

• get_group_agents(<group_name>) - returns a list of IDs for the group agents associated with the sites of the given group type. If the group type does not have group agents, the list will be empty.

• get_group_agent(<group_name>) - returns the group agent ID if the evaluating agent is a member of the named group and the group agent exists. Otherwise, returns 0.

• get_group_agent(<group_ID>) - returns the group agent ID of the group with the given ID, or 0 if the group does not exist or the group has no group agent.

### geographical

The following functions return information on the location or relative location of one or more places:

• latitude(<place_name>) – latitude of the agent’s place. If the argument is omitted, return the latitude of the agent itself.

• longitude(<place_name>) – longitude of the agent’s place. If the argument is omitted, return the longitude of the agent itself.

• elevation(<place_name>) - returns the height in meters above sea level of the agent’s place. If the argument is omitted, return the elevation of the agent itself.

• getx(<place_name>) – x-coordinate of the agent’s place (meters from western edge in simulation area). If the argument is omitted, return the x-coordinate of the agent itself.

• gety(<place_name>) – y-coordinate of the agent’s place (meters from southern edge of simulation area). If the argument is omitted, return the y-coordinate of the agent itself.

• dist(<place_name1>, <place_name2>) – returns the distance in km between the places whose IDs are represented by the arguments.

### place containers

• get_container(<container_type>, <place_name>) : returns the place ID of the container of the type in the first argument that contains the agent’s place of the type in the second argument.

### on networks

• links(Network) returns a list of agents to which the agent is directly connected by edges in the given undirected network.

• outlinks(Network) returns a list of agents to which the agent is directly connected by outward edges in the given directed network.

• inlinks(Network) returns a list of agents that have edges to the agent in the given directed network.

• get_weight(Network, source, destination) : returns the weight of the edge from source to destination in the named network. Returns 0 if no such edge exists.

• shortest_path(Network, source, destination) : returns a list of nodes in the Network from source to destination with the shortest total edge weights, using Dijkstra’s algorithm. Returns an empty list if either node is not in the network, or if there is no path from source to destination.

• weight_neighborhood(Network, source, weight_limit, weight_vec) : returns a list of nodes in the Network whose shortest paths from the source node have weights less than or equal to weight_limit. The nodes are sorted by ascending weight of the their shortest paths. The 4th argument is optional; if present it must be the name of a shared or agent list-variable, which is set to the list of weights of the returned list of nodes.

• edge_neighborhood(Network, source, edge_limit, edge_vec) : returns a list of nodes whose shortest edge-paths have no more than edge_limit edges in the named network. The nodes are sorted by ascending edge-lengths of the their shortest edge-paths. The 4th arg is optional; if present it must be the name of a shared or agent list var, which is set to the list of edge-lengths of the returned list of nodes.

## Functions on Other Agents

• get_population() – returns a list of IDs of all oridinary agents in the population.

• ask(<expression1>, <expression2>) – If the first argument evaluates to the ID of another agent, the function returns the value of the second argument, evaluated with respect to the other agent. If the first argument evaluates to a list of agent IDs, the function returns a list of values of the second expression, evaluated with respect to each of the other agents. If the first argument is the name of a group (such as School), then the other agent is the group agent for the primary agent’s group of that type. If there is no such group agent, the result of the function is 0.

The following sets the value of sibling_age to the age of the agent whose ID is stored in my_sibling:

sibling_age = ask(my_sibling, age)


The following sets my_household_ages_list to a list of the ages of the members of the agent’s household:

my_household_ages_list = ask(members(Household), age)


Suppose the evaluating agent is a member of a group called Theater. Then the following sets available_tickets to the value of the tickets agent variable for the group agent for the agent’s Theater:

available_tickets = ask(Theater, tickets)


## Functions on Lists

### selecting an element

An element in a list variable may be accessed using square brackets, <list_variable>[<expression>]. The expressions is truncated to an integer, and used as an index into the list. If the element does not exist, 0.0 is returned. Equivalently, this can be accomplished with the select() function.

Note

If X is declared as a list variable then the parser translates X[string] to select(X, string), so the following are equivalent:

• select(x_list, index_list) and x_list[index_list]

• select(x_list, _ > 0) and x_list[_ > 0] - returns all positive numbers in x_list

• select(x_list, ask(_, age) > 18) and x_list[ask(_, age) > 18] - returns the list of agents in x_list that have age > 18.

A single element can be selected from a list by the following functions:

• select(<list-expression>, <expression>) – returns the item in the value of the first argument indexed by the second argument. Note that th <list-expression> need not be a list variable, For example, select(members(Household),0) would retrun the first member of the agent’s household.

• last(<list_expression>) – returns the last item in the list. Throws an exception if the list is empty.

The select function can also be used to select a sub-list:

• select(<list-expression>, <list_expression>) - returns the sub-list of the first argument corresponding to the list of indices in the second argument.

• find_index(<value>, <list_expression>) – returns the index of the value in the list_expression, or -1 if the value does not occur in the list.

Elements in a list may also be selected based on a test:

• select(<list-expression>, <test>) - returns the sub-list of the first argument consisting of the items that pass the test. The special variable _ in the test refers to the list item being evaluated. For example select(list(20, 5, 2, 40), (10 < _)) would return the list (20, 40).

• select_index(<list-expression>, <test>) - returns the list of the indices for the list in the first argument corresponding to items that pass the test. The special variable _ in the test refers to the list item being evaluated. For example select_index(list(20, 5, 2, 40), (10 < _)) would return the list (0, 3).

#### examples

You can access the first or last element in a list X:

first_item = X[0]
last_item = X[length(X) - 1]
last_item = last(X)


or select a member of an agent’s household:

first_housemate = select(members(Household), 0)

• unique(<list-expression>) - Returns a sorted list of unique elements that occur in the list parameter.

### miscellaneous

• length(<list_expression>) – returns the number of items in the value of the list-expression.

• max(<list_expression>) – returns the maximum of values in the list. Returns 0 if list is empty.

• min(<list_expression>) – returns the minimum of values in the list. Returns 0 if list is empty.

• percentile(<value>, <list_epression>) - returns the percentile of a value within a list of sorted list of values.

• prod(<list_expression>) – returns the product of values in the list. Returns 0 if list is empty.

• sum(<list_expression>) – returns the sum of values in the list. Returns 0 if list is empty.

• partial_sums(<list_expression>) - returns the list of partial sums of the values in the list. That is, each value in the resulting list consists of the sum of all items up to an including the current item.

• unique(<list_expression>) - returns a list of unique elements from the list.

#### examples

The following example sets a variable, mean_X, equal to the average of a list X:

if (length(X) > 0) then mean_X = sum(X) / length(X)


### filtering

Filtering a list entails producing a sub-list from a list that matches some criteria. There are several functions that perform filtering. The following functions act on any list:

• filter_values(<list_expr>, <op>, <expr>) - returns a sub-list of the values that satisfy the test of the given operator against the expression, where <op> is <, <=, =, ==, >, >=, or !=.

• index_values(<list_expr>, <op>, <expr>) returns the sub-list of values that satisfy the given test.

• filter_by_index(<list_expr>, <list_of_desired_indexes>) returns the selected items from a list given the list of desired index values.

Another set of functions specifically act on a list of agent IDs:

• filter_agents(<list-expression>, <test1>, <test2>, ..., <testN>) - returns a list of all agents in the list-expression that satisfy all the tests in the remaining arguments.

• index_agents(<list-expression>, <test1>, ..., <testN>) - returns a list of indexes of agents on the list that satisfy all the tests.

Note

The <list-expression> argument in the preceding two functions must be a list of agent IDs.

#### examples

For example, a list can be filtered based on the value of it’s elements:

old_list = list(2, 10, 8, 4, 6)
new_list = filter_values(old_list, >, old_list[0] + 3)


The resulting list, new_list, is equal to list(10, 8, 6).

Similarly, the indices that produce this filtering can be recovered:

old_list = list(2, 10, 8, 4, 6)
index_list = index_values(old_list, >, old_list[0] + 3)
new_list = filter_by_index(old_list, index_list)


The resulting list, index_list, is equal to list(1, 2, 4). That list of indices can be used to generate the filtered list, new_list, again equal to list(10, 8, 6).

For example, to generate a list of all the agents who are in an agent’s school, older than the agent, and are of the opposite sex:

my_older_opposite_sex_friends = filter_agents(members(School),\


Note

The special variable _ is replaced by the current item in the list of agent being processed. For example, in the first test in the example above, the read-only variable age refers to the age of the agent evaluating the expression, and the expression ask(_,age) returns to the age of the agent being evaluated by the filter, that is the current item in the list member(Schhol).

### sampling

The following functions return a random sample from a list. Each call to the function returns a distinct randomized sample.

• sample_without_replacement(<list-expr>, <expr>) - returns a random sample of the list of size k where k is the value of second expression. Sampling is without replacement, meaning that no item is selected more than once.

• sample_without_replacement(<list-expr>, <expr>, <list-expr2>) - returns a random sample of the list of size k where k is the value of second expression. Sampling uses the weights specified in the last argument, which must evaluate to a list of positive values with the same length as the first argument. Sampling is without replacement meaning that no item is selected more than once.

• sample_with_replacement(<list-expr>, <expr>) - returns a random sample of the list of size k where k is the value of second expression. Sampling is performed with replacement, meaning that items may be selected more than once.

• sample_with_replacement(<list-expr>, <expr>, <list-expr2>) - returns a random sample of the list of size k where k is the value of second expression. Sampling uses the weights specified in the last argument, which must evaluate to a list of positive values with the same length as the first argument. Sampling is performed with replacement meaning that items may be selected more than once.

### set operations

The following functions implement set union, intersection, and difference operations:

• union(<list_expr>, <list_expr>) - returns a list of unique items that occur in either list, sorted in increasing order.

• intersection(<list_expr>, <list_expr>) - returns a list of unique items that occur in both lists, sorted in increasing order.

• set_difference(<list-expr1>, <list-expr2>) - returns the list of unique items that are in the first list but not in the second list.

### sorting

The following functions can be used to reorder a list:

• sort(<list_expr>) - returns a sorted list.

• arg_sort(<list_expr>) - returns a list of indices that sort the list.

• shuffle(<list_expr>) - returns a randomly sorted copy of the list.

### evaluating an expression on each item

• apply(<list_expr>, <expression>) - returns a list of the values of the expression in the second argument, evaluated with respect to each item in the first argument. Any occurrence of _ in the expression refers to the value of the current item in the list.

#### examples

For example, a new list can be generated by multiplying every element in a list by 2.0:

x_list = list(1, 2, 3, 4, 5)
y_list = apply(x_list, 2 * _)
# result: y_list = list(2, 4, 6, 8, 10)


## Functions on Tables

Tables and list-tables are data structures consisting of key-value pairs. For tables, the values are real numbers. For list-tables, the values are lists. A value in a table or list-table may be selected using square brackets, <table-name>[<key>]. Equivalently, this can be accomplished using the lookup() function.

A specific position in a list-table can be accessed using two values in square brackets. For example, if x is a list-table and the list associated with key key has three values in the list x[key], then x[key][2] refers to the third value in the list. In the following example, we set the third item in the list to the first item in the list plus 1:

x[key][2] = x[key][0] + 1


Functions on tables and list-tables include:

• lookup(<table_name>, <key-expression>) - returns the value in the table/list-table associated with the given key.

Note

If the key does not exist, a run-time error occurs unless the table has a defined default_value property, in which case the default value is returned. The default value is not inserted into the table as the value of the key.

• length(<table_name>) – returns the number of key-value pairs in the table/list-table.

• get_keys(<table_name>) - returns the list of keys stored in the indicated table/list-table.

• get_values(<table_name>) - returns the list of values stored in the indicated table.

## True-or-False Predicates

The predicates discussed in Chapter 8 evaluate to true or false. When used as part of an expression, they evaluate to numeric values, with true being treated as 1 and false treated as 0`.