Learn R Programming

blvim: Boltzmann–Lotka–Volterra Interaction Model

blvim implements A. Wilson’s Boltzmann–Lotka–Volterra (BLV) interaction model. The model is described in Wilson, A. (2008), “Boltzmann, Lotka and Volterra and spatial structural evolution: an integrated methodology for some dynamical systems”, J. R. Soc. Interface, 5:865–871.

The package’s primary goal is to provide a fast implementation of the BLV model, complete with a collection of tools designed to explore the results through statistical summaries and graphical representations. The secondary goal is to facilitate the systematic assessment of how model parameters impact the results, again using summaries and graphical representations (see vignette("grid") for details on this aspect).

Installation

You can install blvim from CRAN with:

install.packages('blvim')

You can install the development version from R-universe with:

install.packages('blvim', repos = c('https://fabrice-rossi.r-universe.dev'))

Spatial interaction models

Spatial interaction models aim to estimate flows between locations, such as workers commuting from residential zones to employment zones. The blvim package focuses on the maximum entropy models developed by Alan Wilson. See vignette("theory") for the theoretical background.

In practice, if we have $n$ origin locations and $p$ destination locations, the goal is to compute a flow matrix $(Y_{ij})_{1\leq i\leq n, 1\leq j\leq p}$, where $Y_{ij}$ is the flow from origin $i$ to destination $j$. This computation relies on characteristics of the origin and destination locations, along with a matrix of exchange difficulties, known as a cost matrix, $(c_{ij})_{1\leq i\leq n, 1\leq j\leq p}$. For example, $c_{ij}$ can represent the distance between origin $i$ and destination $j$.

Usage

The package is loaded in a standard way.

library(blvim)

Input data

To compute a spatial interaction model with blvim, you need at least a cost matrix. The package comes with distance data for a selection of large French cities. We use the 30 largest ones as origin locations and the 20 smallest ones as destination locations. The cost matrix is the distance between the cities (in meters).

## 30 largest cities
origins <- french_cities[1:30, c("th_longitude", "th_latitude")]
## 20 smallest cities
destinations <- french_cities[
  (nrow(french_cities) - 19):nrow(french_cities),
  c("th_longitude", "th_latitude")
]
## cost matrix
cost_matrix <-
  french_cities_distances[
    1:30,
    (nrow(french_cities) - 19):nrow(french_cities)
  ]
rownames(cost_matrix) <- french_cities[1:30, "name"]
colnames(cost_matrix) <-
  french_cities[(nrow(french_cities) - 19):nrow(french_cities), "name"]

Additionally, since we focus on production-constrained models, we must specify the production for each origin location (a vector of positive values $(X_i)_{1\leq i\leq n}$). Here, we assume a common unitary production.

X <- rep(1, nrow(origins))

Finally, the simple static model requires an attractiveness value for each destination location, a vector of positive values $(Z_j)_{1\leq j\leq p}$. We again assume a common unitary attractiveness.

Z <- rep(1, nrow(destinations))

We could use the population of the cities as production constraints for instance.

Static models

In Wilson’s production-constrained maximum entropy model, the flows are given by


Y_{ij} = \frac{X_iZ_j^{\alpha}\exp(-\beta c_{ij})}{\sum_{k=1}^pZ_k^{\alpha}\exp(-\beta c_{ik})},

where $\alpha$ is a return-to-scale parameter and $\beta$ is the inverse of a cost scale parameter. Note that the flow matrix is production-constrained, meaning that the total outgoing flow from any origin location is equals the production of that location:


\forall i,\quad X_i=\sum_{j=1}^{p}Y_{ij}.

The model is obtained using the static_blvim() function:

a_model <- static_blvim(cost_matrix, X, alpha = 1.1, beta = 1 / 500000, Z)
a_model
#> Spatial interaction model with 30 origin locations and 20 destination locations
#> • Model: Wilson's production constrained
#> • Parameters: return to scale (alpha) = 1.1 and inverse cost scale (beta) =
#> 2e-06

Several functions are provided to extract parts of the result. In particular flows() returns the flow matrix $Y$.

a_model_flows <- flows(a_model)

which can be displayed using, for instance, the image() function.

par(mar = rep(0.1, 4))
image(t(a_model_flows)[, 30:1],
  col = gray.colors(20, start = 1, end = 0),
  axes = FALSE,
  frame = TRUE
)

In this representation, each row shows the flows from one origin location to all destination locations. The package also provides a ggplot2::autoplot() function, which can be used as follows:

library(ggplot2)
autoplot(a_model, "full") +
  scale_fill_gradient(low = "white", high = "black") +
  coord_fixed()
b_model <- static_blvim(cost_matrix, X, alpha = 1.1, beta = 1 / 100000, Z)
b_model
#> Spatial interaction model with 30 origin locations and 20 destination locations
#> • Model: Wilson's production constrained
#> • Parameters: return to scale (alpha) = 1.1 and inverse cost scale (beta) =
#> 1e-05
autoplot(b_model) +
  scale_fill_gradient(low = "white", high = "black") +
  coord_fixed()

As the two figures above exemplify, different values of the parameters $\alpha$ and $\beta$ result in more or less concentrated flows.

Dynamic models

A. Wilson’s Boltzmann–Lotka–Volterra (BLV) interaction model builds upon the production-constrained maximum entropy model. The core idea is to update the attractiveness of the destination locations based on their incoming flows.

Ideally, we aim for the following condition to hold in the limit:


Z_j =\sum_{i=1}^{n}Y_{ij}, 

where the flows are given by the equations above. The model is estimated using the blvim() function as follows.

a_blv_model <- blvim(cost_matrix, X, alpha = 1.1, beta = 1 / 500000, Z)
a_blv_model
#> Spatial interaction model with 30 origin locations and 20 destination locations
#> • Model: Wilson's production constrained
#> • Parameters: return to scale (alpha) = 1.1 and inverse cost scale (beta) =
#> 2e-06
#> ℹ The BLV model converged after 4800 iterations.

Notice that we start with some initial values of the attractiveness, but the final values are different. These final values can be obtained using the attractiveness() function (and visualised here using a bar plot).

par(mar = c(0.1, 4, 1, 0))
a_final_Z <- attractiveness(a_blv_model)
barplot(a_final_Z)
autoplot(a_blv_model) +
  scale_fill_gradient(low = "white", high = "black")

The autoplot() function can also be used to show the destination flows or the attractivenesses values:

autoplot(a_blv_model, "attractiveness", with_names = TRUE) +
  coord_flip()

Naturally, the results are strongly influenced by the parameters, as shown in this second example.

b_blv_model <- blvim(cost_matrix, X, alpha = 1.1, beta = 1 / 50000, Z)
b_blv_model
#> Spatial interaction model with 30 origin locations and 20 destination locations
#> • Model: Wilson's production constrained
#> • Parameters: return to scale (alpha) = 1.1 and inverse cost scale (beta) =
#> 2e-05
#> ℹ The BLV model converged after 5700 iterations.
autoplot(b_blv_model, "attractiveness", with_names = TRUE) +
  coord_flip()
autoplot(b_blv_model, with_names = TRUE) +
  scale_fill_gradient(low = "white", high = "black") +
  theme(axis.text.x = element_text(angle = 90))

bvlim offers a collection of graphical representations that can leverage the data associated to the origin and destination locations. For instance, we can display the full flows using geographical coordinates of the cities.

origin_positions(b_blv_model) <- as.matrix(origins)
destination_positions(b_blv_model) <- as.matrix(destinations)
autoplot(b_blv_model,
  with_positions = TRUE,
  show_destination = TRUE,
  show_production = TRUE,
  cut_off = 0
) +
  scale_linewidth(range = c(0, 1.5)) +
  coord_sf(crs = "epsg:4326") +
  scale_color_discrete(type = c("darkorange", "blueviolet"))

Copy Link

Version

Install

install.packages('blvim')

Version

0.1.1

License

GPL (>= 3)

Maintainer

Fabrice Rossi

Last Published

January 14th, 2026

Functions in blvim (0.1.1)

french_cities

French cities
french_departments

French departments
diversity

Compute the diversity of the destination locations in a spatial interaction model
destination_positions

positions of destination locations in a spatial interaction model
destination_names

Names of destination locations in a spatial interaction model
grid_destination_flow

Extract all the destination flows from a collection of spatial interaction models
grid_sim_converged

Reports the convergence statuses of a collection of spatial interaction models
grid_is_terminal

Extract all terminal status from a collection of spatial interaction models
fortify.sim

Turn a spatial interaction model into a data frame
flows_df

Extract the flow matrix from a spatial interaction model object in data frame format
grid_autoplot

Create a complete ggplot for spatial interaction models in a data frame
grid_blvim

Compute a collection of Boltzmann-Lotka-Volterra model solutions
french_regions

French regions
nd_graph

Compute the Nystuen and Dacey graph for a spatial interaction model
grid_attractiveness

Extract all the attractivenesses from a collection of spatial interaction models
origin_names

Names of origin locations in a spatial interaction model
inverse_cost

Extract the inverse cost scale parameter used to compute this model
location_positions

Positions of origin and destination locations in a spatial interaction model
location_names

Names of origin and destination locations in a spatial interaction model
grid_sim_iterations

Returns the number of iterations used to produce of a collection of spatial interaction models
grid_var_autoplot

Create a complete variability plot for spatial interaction models in a data frame
grid_diversity

Compute diversities for a collection of spatial interaction models
median.sim_list

Compute the "median" of a collection of spatial interaction models
names<-.sim_df

Set the column names of a SIM data frame
sim_distance

Compute all pairwise distances between the spatial interaction models in a collection
sim_is_bipartite

Reports whether the spatial interaction model is bipartite
sim_iterations

Returns the number of iterations used to produce this spatial interaction model
sim_list

Create a sim_list object from a list of spatial interaction objects
is_terminal

Report whether locations are terminal sites or not
quantile.sim_list

Compute quantiles of the flows in a collection of spatial interaction models
return_to_scale

Extract the return to scale parameter used to compute this model
terminals

Compute terminals for a spatial interaction model
production

Extract the production constraints from a spatial interaction model object
sim_df

Create a spatial interaction models data frame from a collection of interaction models
origin_positions

Positions of origin locations in a spatial interaction model
sim_df_extract

Extract or replace parts of a SIM data frame
sim_converged

Reports whether the spatial interaction model construction converged
sim_column

Get the collection of spatial interaction models from a SIM data frame
summary.sim_list

Summary of a collection of spatial interaction models
static_blvim

Compute flows between origin and destination locations
autoplot.sim_df

Create a complete ggplot for a spatial interaction models data frame
autoplot.sim

Create a complete ggplot for a spatial interaction model
c.sim_list

Combine multiple sim_list objects into a single one
as.data.frame.sim_list

Coerce to a Data Frame
costs.sim_list

Extract the common cost matrix from a collection of spatial interaction models
destination_flow

Compute the flows incoming at each destination location
attractiveness

Extract the attractivenesses from a spatial interaction model object
costs

Extract the cost matrix used to compute this model
blvim

Compute an equilibrium solution of the Boltzmann-Lotka-Volterra model
autoplot.sim_list

Create a complete variability for a collection of spatial interaction models
french_cities_distances

French cities distances
flows

Extract the flow matrix from a spatial interaction model object
fortify.sim_list

Turn a collection of spatial interaction models into a data frame