Imagine this

One organization’s customer base (MooseCo = M) interacts with another organization’s customer base (WolfCo = W). W poaches customers from M. That is the interaction. In the wild world of unbridled short-term profit for profit’s sake, M effectively does a lot of the work of customer acquisition for W while M blithely and seemingly allows the poaching campaign to continue.

Analogically, and in behavioral terms, we can also imagine one team bullying another to give up its players. In a technological context we can imagine a computing platform giving up performance and reliability (due to heat degradation) to a component technology (more powerful and also hotter). In polities and their statecraft we can imagine an interaction between special interests and the common good.1

Given initial customer bases for each organization as well as acquisition and switching rates for each of the two organizations, we wonder

  • who leads/lags whom,

  • is the interaction reach an equililibrium, a balance, or simple continues unabated,

  • is the process consistent with observed movements in (this case) customer acquisition and switching behavior,

  • any other interpretations?

The model we will use throughout this note is based on the Lotka (1920) - Volterra (1928) coupled interaction models more well known as predator-prey models. ## Design

Our first task is to design a model, a way of systematic thinking through the interaction set-up, as a way to reaching some understanding of the interaction over time. Having reached some stable understanding will later attempt to apply a managerial (or policy) intervention.

The first figure displays notes for a design of an interaction model imagined in this note. There are six steps.

6-step framework to design a system dynamics model.
6-step framework to design a system dynamics model.
  1. Pose the question for research, simulation, action, or simply discussion.

  2. Detail the four causes (final cause or end sought, formal cause or design, material cause or resources, and efficient cause or agents and their interventions) to answer the question.

  3. Develop a closed loop diagram of the interaction of stocks (e.g., customer bases here), flows ( changes in stocks ), and auxiliary components (e.g., acquisition and switch rates, initial values).

  4. Develop a stock-flow-diagram to highlight the accumulate of a simulation history of flows in stocks as well as relationships among the collection of stocks and flows. Based on this diagram develop the equations for stocks, flows, and auxiliary variables.

  5. Lay out a priori graphs of expected simulated behavior of stocks and flows over time.

  6. Check that the design is a system, namely, does it possess a a) collection of relevant stocks, flows, and auxiliary variable complete enough to answer the question, b) connections to relate stocks, flows, and auxiliary variables, and c) coherent model components which support all four causes, especially the final cause, the end or good being sought.

In this figure a detailed stock-flow-diagram is developed along with equations of motion of the two stocks (e.g., customer bases) through time.

Customer base interaction stock-flow-diagram.
Customer base interaction stock-flow-diagram.

We let \(t\) denote a time index with fixed intervals normalized to a size of 1, \(M(t)\) and \(W(t)\) be the stocks of MooseCo and WolfCo customers at time \(t\) with initial (\(t=0\)) values \(M(0)\) and \(W(0)\), and with subscripts \(m\) and \(w\) for MooseCo and Wolfco we denote customer acquisition rates \(a_m\) and \(a_w\) and switching rates \(s_m\) and \(s_w\), all between 0 and 1.

\[ M(t) = M(t-1) + a_m M(t-1) - a_m M(t-1)W(t-1), \] and

\[ W(t) = W(t-1) + s_m a_w M(t-1)W(t-1) - s_w W(t-1). \] These equations determine the simultaneous interactions through the coupling moderation terms in \(M(t-1)W(t-1)\).

Simulate

We will feature Vensim and R simulations. The model we develop here is based on McElreath (2020), Chapter 16, p. 541-550.

Vensim model

Stocks and flows

Stock-flow-model
Stock-flow-model

Equations

(01)    aMooseAcquisitionRate=
        0.5
    Units: **undefined**
    
(02)    aMooseInitial=
        30
    Units: **undefined**
    
(03)    aMooseSwitchingRate=
        0.05
    Units: **undefined**
    
(04)    aWolfAcquisitionRate=
        0.5
    Units: **undefined**
    
(05)    aWolfInitial=
        4
    Units: **undefined**
    
(06)    aWolfSwitchingRate=
        0.5
    Units: **undefined**
    
(07)    FINAL TIME  = 24
    Units: Month
    The final time for the simulation.

(08)    fMooseAcquisition=
        aMooseAcquisitionRate * sMoose
    Units: **undefined**
    
(09)    fMooseSwitching=
        aMooseSwitchingRate * sMoose * sWolf
    Units: **undefined**
    
(10)    fWolfAcquisition=
        aMooseSwitchingRate * aWolfAcquisitionRate * sMoose * sWolf
    Units: **undefined**
    
(11)    fWolfSwitching=
        aWolfSwitchingRate * sWolf
    Units: **undefined**
    
(12)    INITIAL TIME  = 0
    Units: Month
    The initial time for the simulation.

(13)    SAVEPER  = 
       TIME STEP 
    Units: Month [0,?]
    The frequency with which output is stored.

(14)    sMoose= INTEG (
        fMooseAcquisition-fMooseSwitching,
            aMooseInitial)
    Units: **undefined**
    
(15)    sWolf= INTEG (
        fWolfAcquisition-fWolfSwitching,
            aWolfInitial)
    Units: **undefined**
    
(16)    TIME STEP  = 0.0625
    Units: Month [0,?]
    The time step for the simulation.

Graphs

Moose-Wolf plots. Both time series (top) and phase diagram (bottom) show repeating cyclic (oscillatory) behavior, one leading / lagging the other.

R model

Build simulation function

Using the equations we construct a simulation function in R.

#
library( tidyverse )
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.2     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.2     ✔ tibble    3.2.1
## ✔ lubridate 1.9.2     ✔ tidyr     1.3.0
## ✔ purrr     1.0.1     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
#
sim_Wolf_Moose <- function( n_steps, initial, gamma, dt = 0.002 ){
  W <- rep( NA, n_steps )
  M <- rep( NA, n_steps )
  W[1] <- initial[1]
  M[1] <- initial[2]
  for ( t in 2:n_steps ){
    M[t] <- M[t-1] + (gamma[1]*M[t-1] - gamma[2]*M[t-1]*W[t-1]) * dt
    W[t] <- W[t-1] + (gamma[3]*gamma[2] * M[t-1] * W[t-1] - gamma[4]*W[t-1]) * dt
  }
  return( tibble(
    W = W,
    M = M
  ))
}

We introduced a time step interval size \(dt\) which will simulate \(n-steps\) values of \(M(t)\) and \(W(t)\).

Simulation data

Having defined a function, we proceed to make some simulation data for the function including a vector of acquisition and switching rates, and a vector of initial customer base values.

gamma <- c( 0.50, 0.05, 0.50, 0.50 )
# c( moose acquisition rate, moose switching, wolf acquistion, wolf switching)
initial_W_M <- c( 4, 30 ) # 4 WolfCo and 30 MooseCo customers

Run simulations (until morale improves!)

We run the model with n_steps=10000, and keeping the time step at dt=0.002. This amounts to 20 observable time periods (say, months for example).

n_steps <- 10000
z <- sim_Wolf_Moose( n_steps, initial_W_M, gamma )
str( z )
## tibble [10,000 × 2] (S3: tbl_df/tbl/data.frame)
##  $ W: num [1:10000] 4 4 4 4.01 4.01 ...
##  $ M: num [1:10000] 30 30 30 30.1 30.1 ...

We should plot our handiwork next.

Plot it!

library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
p <- ggplot( ) +
  geom_line( aes( x = 1:n_steps, y = z$W)) +
  geom_line( aes( x = 1:n_steps, y = z$M))
ggplotly( p )

Interpretation

More Moose base than Wolf base. Moose peaks before Wolf base.

To do

These are items to do in no particular order yet.

  1. Define gamma friendlier. Then unpack into the function.

  2. Put labels on the graph, even a legend.

  3. Construct phase diagram. This is a plot of the \(W(t)\) on the y-axis with \(M(t)\).

  4. Use polynumbers throughout.

\[ \pi=\left\vert \overline{% \begin{array} [c]{c}% u_{0}\\ u_{1}\\ \vdots\\ u_{k}% \end{array} }\right. \]

References

Lotka, Alfred J. 1920. “Analytical Note on Certain Rhythmic Relations in Organic Systems.” Proceedings of the National Academy of Sciences 6 (7): 410–15.
McElreath, Richard. 2020. Statistical Rethinking: A Bayesian Course with Examples in R and Stan. Second edition. CRC Press. https://xcelab.net/rm/statistical-rethinking/.
Volterra, Vito. 1928. “Variations and Fluctuations of the Number of Individuals in Animal Species Living Together.” ICES Journal of Marine Science 3 (1): 3–51.

  1. A bit more blunt is this quote from James K. Galbraith: “The predator-prey model explains some things that other models cannot: in particular, cycles of prosperity and depression. Growth among the prey stimulates predation. The two populations grow together at first, but when the balance of power shifts toward the predators (through rising interest rates, utility rates, oil prices, or embezzlement), both can crash abruptly. When they do, it takes a long time for either to recover.” James K. Galbraith, (retrieved 2024-03-08 from https://www.motherjones.com/politics/2006/05/predator-state/)↩︎