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.
Pose the question for research, simulation, action, or simply discussion.
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.
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).
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.
Lay out a priori graphs of expected simulated behavior of stocks and flows over time.
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.
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)\).
We will feature Vensim and R simulations. The model we develop here is based on McElreath (2020), Chapter 16, p. 541-550.
(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.
Both time series (top) and phase diagram (bottom) show repeating cyclic (oscillatory) behavior, one leading / lagging the other.
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)\).
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
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.
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 )
More Moose base than Wolf base. Moose peaks before Wolf base.
These are items to do in no particular order yet.
Define gamma friendlier. Then unpack into the function.
Put labels on the graph, even a legend.
Construct phase diagram. This is a plot of the \(W(t)\) on the y-axis with \(M(t)\).
Use polynumbers throughout.
\[ \pi=\left\vert \overline{% \begin{array} [c]{c}% u_{0}\\ u_{1}\\ \vdots\\ u_{k}% \end{array} }\right. \]
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/)↩︎