SimpleFlocking Model#

The SimpleFlocking model implements one of the earliest models of collective dynamics that shows a phase transition. It was proposed by Viczek et al. in 1995 (see References) and is inspired by the swarm behavior of schools of fish or flocks of bird (hence the name).

Model Fundamentals#

Each agent in the SimpleFlocking model is characterized by its position in space, its orientation, and a (constant) speed.

The model mechanisms are very simple: In each time step, …

  1. … all agent’s orientations are adjusted to the mean value of those agents within an interaction radius (including the agent itself), plus some angular noise.

  2. … all agent’s positions are updated using the displacement vector that results from the change in orientation.

These updates occur synchronously for all agents.

Implementation Details#

Observables#

  • agent: group that contains agent-specific data, labelled by time and agent id

    • x and y: agent position

    • orientation: agent orientation in radians \([-\pi, +\pi)\)

  • norm_group_velocity: the normalized average group velocity time series. This is what Vicsek et al., 1995, refer to as the order parameter \(v_a\) of the system.

  • orientation_circmean: circular mean orientation time series

  • orientation_circstd: circular standard deviation of orientation time series

Note the need for circular statistics in order to allow calculating these observables.

Default Model Configuration#

Below are the default model configuration parameters for the SimpleFlocking model:

# --- Space
# The physical space this model is embedded in
space:
  periodic: true
  extent: 25

# --- Initialization parameters
agent_manager:
  initial_position: random
  initial_num_agents: 300
  agent_params: {}


# --- Dynamics

# Global movement speed in absolute spatial distance / time step
speed: 0.03

# The interaction radius (in absolute distance)
interaction_radius: 1.

# The (double) amplitude of the directional noise
noise_level: 0.1


# --- Output
# Whether to store agent-specific data
# Not storing agent-specific data improves simulation speed and reduces the
# size of the output data.
store_agent_data: true

Configuration Sets#

The following configuration sets aim to reproduce some of the results of the Vicsek et al., 1995, paper. The parameters are those used in the referenced figures in that paper.

  • flocking: A scenario where the agents show flocking behavior (Figure 1b).

  • ordered: A scenario leading to a globally ordered movement (Figure 1d).

  • noise_sweep: A sweep that aims to reproduce Figure 2a: the order parameter over the system’s noise amplitude for different system sizes.

  • density_sweep: A sweep that aims to reproduce Figure 2b: the order parameter over the agent density.

The config sets with sweeps also include the corresponding plot configurations to generate the relevant figure.

Plots#

The following general plots are available for the SimpleFlocking model:

  • agents_in_domain: shows the agents with color-coded orientation moving in the domain

  • time_series:

    • norm_group_velocity: The normalized group velocity time series, which is used as the order parameter \(v_a\) by Vicsek et al..

    • orientation_circstd: The circular standard deviation of the agents’ orientation over time, which can also be interpreted as an order parameter.

    • orientation: A combined plot of the circular mean and circular standard deviation of the agent orientation over time.

For details on how to further configure these, see the plot configurations.

Default Plot Configuration#

See the default plot config
# .. Time series plots ........................................................

time_series/norm_group_velocity:
  based_on: time_series/norm_group_velocity

time_series/orientation_circstd:
  based_on: time_series/orientation_circstd

time_series/orientation:
  based_on: time_series/orientation


# .. Spatial plots ............................................................

agents_in_domain:
  based_on: agents_in_domain

Base Plot Configuration#

See the base plot config
_:
  model_data_path:      &model_data_path      data/SimpleFlocking

  aesthetics:
    hvline: &style_hvline
      linestyle: solid
      color: grey
      alpha: .4
      linewidth: 2.
      zorder: -42

# -----------------------------------------------------------------------------
# Plot configuration defaults -------------------------------------------------
# -----------------------------------------------------------------------------
# ... For all plots
.defaults.style_and_helpers:
  based_on: .default_style_and_helpers

  style:
    # https://matplotlib.org/gallery/style_sheets/style_sheets_reference.html
    # https://matplotlib.org/stable/tutorials/introductory/customizing.html

    # -- Style Sheet
    base_style: seaborn-notebook

    # -- Figure layouting etc.
    # figure.constrained_layout.use: true
    figure.dpi: 254       # important also for PDF to avoid rasterization bugs

  helpers: {}

.defaults.animation:
  file_ext: .mp4

  animation:
    enabled: true

    writer: frames  # assuming ffmpeg is not installed

    # Configuration for each writer
    writer_kwargs:
      frames:
        saving:
          dpi: 92

      ffmpeg:
        init:
          fps: 30
        saving:
          dpi: 254

.defaults.animation.ffmpeg:
  based_on: .defaults.animation
  animation:
    writer: ffmpeg

.defaults.dag:
  dag_options:
    define:
      # Can be invoked as fallback to skip a plot in a controlled fashion
      _skip_plot:
        - operation: raise_SkipPlot
          args: [true]


# Aggregated defaults
.defaults:
  based_on:
    - .defaults.style_and_helpers
    - .defaults.dag


# Creators ....................................................................
# ... for DAG-based plots

.creator.universe:
  creator: universe
  universes: all

  select:
    _model_base: "."

  dag_options:
    select_path_prefix: *model_data_path

.creator.multiverse:
  creator: multiverse

  select_and_combine:
    base_path: *model_data_path


# Helper shortcuts ............................................................

.hlpr.limits.x_min_max:
  helpers:
    set_limits:
      x: [min, max]

.hlpr.limits.y_positive:
  helpers:
    set_limits:
      y: [0, ~]


# Plot types ..................................................................

.plot.facet_grid:
  based_on:
    - .dag.generic.facet_grid
    - .defaults

  # Explicitly set individual facet size and aspect ratio
  size: 4
  aspect: 1.5

  # May want to use a custom suptitle format string
  suptitle_kwargs:
    # title: "{dim:} = {value:.3g}"   # ... for numeric values
    title: "{dim:} = {value:}"      # ... allowing non-numeric values


.plot.facet_grid.with_auto_encoding:
  based_on: .plot.facet_grid

  auto_encoding: true
  col_wrap: auto


.plot.facet_grid.type.time_series:
  based_on:
    - .plot.facet_grid.with_auto_encoding
    - .hlpr.limits.x_min_max

  x: time


# -----------------------------------------------------------------------------
# Actual plot configurations --------------------------------------------------
# -----------------------------------------------------------------------------

# .. Spatial plots ............................................................
# A spatial plot of agent positions and orientations
agents_in_domain:
  based_on:
    - .defaults
    - .defaults.animation.ffmpeg
    - .creator.universe

  module: model_plots.SimpleFlocking
  plot_func: agents_in_domain

  select:
    x:
      path: agent/x
      transform: [.data]
      allow_failure: silent
      fallback: !dag_tag _skip_plot
    y:
      path: agent/y
      transform: [.data]
    orientation:
      path: agent/orientation
      transform: [.data]

    space_extent:
      path: agent/x  # meta data is written to every other dataset as well
      transform:
        - getattr: [!dag_prev , attrs]
        - getitem: [!dag_prev , space_extent]

  transform:
    # Combine data into one dataset
    - xr.Dataset:
      - x: !dag_tag x
        y: !dag_tag y
        orientation: !dag_tag orientation
      tag: data

  # Use a square figure
  helpers:
    setup_figure:
      figsize: [6, 6]

  # Pass on space extent (used for setting limits)
  space_extent: !dag_result space_extent

  # passed on to plt.scatter
  s: 12
  cmap: hsv  # TODO Is there a better cyclic one?


# .. Time series ..............................................................

# A time series plot of the normalized absolute group velocity
time_series/norm_group_velocity:
  based_on:
    - .creator.multiverse
    - .plot.facet_grid.type.time_series
    - .hlpr.limits.y_positive

  select_and_combine:
    fields:
      data: norm_group_velocity

  helpers:
    set_title:
      title: normalized absolute group velocity

time_series/final_group_velocity:
  based_on:
    - .creator.multiverse
    - .plot.facet_grid.with_auto_encoding
    - .hlpr.limits.x_min_max
    - .hlpr.limits.y_positive

  expected_multiverse_ndim: [1, 2, 3, 4, 5]

  select_and_combine:
    fields:
      _data:
        path: norm_group_velocity
        transform:
          - .isel.item: [!dag_prev , {time: -1}]  # TODO Consider averaging

  transform:
    - define: !dag_tag _data
      tag: data

  helpers:
    set_title:
      title: final absolute group velocity
    set_limits:
      x: [0, ~]

# A time series plot of the orientation's circular std. dev.
time_series/orientation_circstd:
  based_on:
    - .creator.multiverse
    - .plot.facet_grid.type.time_series
    - .hlpr.limits.y_positive

  select_and_combine:
    fields:
      data: orientation_circstd

  helpers:
    set_title:
      title: circular std. of agent orientation


# A time series plot of the circular mean and std of the agent orientation
time_series/orientation:
  based_on:
    - .creator.multiverse
    - .plot.facet_grid.type.time_series

  # -- Data selection
  # This is a bit more complicated, because we need to address the
  # discontinuity in the orientation value to avoid perpendicular lines in the
  # plots. To that end, the time series for each universe are processed and
  # NaN values are set at each jump, such that the plot line is broken.
  dag_options:
    meta_operations:
      get_mean_and_std_orientation:
        - define: !arg 0
          tag: model_data

        - getitem: [!dag_tag model_data, orientation_circmean]
        - .data: !dag_prev
          tag: mean_data
        - getitem: [!dag_tag model_data, orientation_circstd]
        - .data: !dag_prev
          tag: std_data

        - xr.Dataset:
          - mean: !dag_tag mean_data
            std: !dag_tag std_data

  select_and_combine:
    fields:
      mean_and_std_orientation:
        path: ./
        transform:
          - get_mean_and_std_orientation

          # Remove discontinuities; see operations.py for implementation
          # NOTE An alternative operation that preserves data points is
          #      `insert_nan_at_discontinuities`. However, this will introduce
          #      new dummy time coordinates into *all* data dimensions, thus
          #      carrying through the discontinuity into the rest of the data.
          - set_nan_at_discontinuities: !dag_prev
            kwargs:
              variable: mean
              threshold: 3.14159

  transform:
    - define: !dag_tag mean_and_std_orientation
      tag: data

  # -- Plot config
  kind: errorbars
  use_bands: true
  fill_between_kwargs:
    interpolate: true

  x: time
  y: mean
  yerr: std

  helpers:
    set_limits:
      y: [-3.14159, +3.14159]

    set_hv_lines:
      hlines:
        - pos: 0.
          <<: *style_hvline

    set_labels:
      y: orientation (circ. mean and std.)

For the utopya base plots, see Multiverse Base Configuration.

Possible Future Extensions#

This model is really only a starting point in the interesting field of collective dynamics. There are a number of interesting extensions, specifically when giving the individual agents more perceptive capabilities and possible actions.

In the work by Couzin et al., 2002, the agents adjust their movement as a result to “social forces”: repulsion and attraction to other agents. In addition, the agents’ field of view is modelled and plays a role in the computation of these forces. Many models include these sets of social forces and expand on that, see e.g. Twomey et al., 2020.

In the model by Klamser & Romanczuk, 2021, a continuous version of these forces is used and a predator is introduced; this setup is then used to assess the system’s ability to be in a self-organized critical state, maximizing sensitivity to the predator. Furthermore, the agent neighborhood is determined via Voronoi tesselation and some agent parameters are subject to evolutionary dynamics.

References#

  • Vicsek, T., Czirók, A., Ben-Jacob, E., Cohen, I., & Shochet, O. (1995). Novel Type of Phase Transition in a System of Self-Driven Particles. In Physical Review Letters (Vol. 75, Issue 6, pp. 1226–1229). American Physical Society (APS). 10.1103/physrevlett.75.1226

  • Couzin, I. D., Krause, J., James, R., Ruxton, G. D., & Franks, N. R. (2002). Collective Memory and Spatial Sorting in Animal Groups. In Journal of Theoretical Biology (Vol. 218, Issue 1, pp. 1–11). Elsevier BV. 10.1006/jtbi.2002.3065

  • Twomey, C. R., Hartnett, A. T., Sosna, M. M. G., & Romanczuk, P. (2020). Searching for structure in collective systems. In Theory in Biosciences (Vol. 140, Issue 4, pp. 361–377). Springer Science and Business Media LLC. 10.1007/s12064-020-00311-9 (PDF).

  • Klamser, P. P., Romanczuk, P. (2021). Collective predator evasion: Putting the criticality hypothesis to the test. PLOS Computational Biology 17(3): e1008832. 10.1371/journal.pcbi.1008832