After writing the Introduction to systems thinking,
I scheduled my yearly trip through the internet looking for easy to use and reasonably priced
systems modeling software, and didn’t quite find what I wanted.
Aftewards, I decided to do an experiment in defining a text format for models, loosely
inspired by Graphviz, and build some tools for running those models.
That experiment culminated in the systems library
for Python, which I’ll use here to model a hiring funnel.
We’ll start with a very simple model, and continue layering on concepts until we
have something interesting. Installation instructions are here,
but for most cases you can install via Python’s pip module:
python3 -m pip install systems
Once you have systems install, we can start writing our model,
starting with the simplest definition:
Breaking this down into a few interesting details.
Each line represents two stocks and one flow.
Prospect > PhoneScreen @ 0.5
For example, the line above shows the the Prospect stock and the
PhoneScreen stock. There is a 50% conversion flow between them,
such that each round the entire value of Prospect will be multiplied
by 50% and that value will be added to PhoneScreen. Prospect itself
will be zeroed out by the conversion, but in this case it’ll be refilled
immediately by the flow from Candidate:
[Candidate] > Prospect @ 10
Stocks surrounded by brackets, such as [Candidate], are infinite stocks,
typically used as the entry or exit of a system. These stand to be stand-ins
for some other system that you’re not modeling right now. This flow,
represented by the whole number 10, will remove 10 from the Candidate
stock and add 10 to Prospect. If the source stock has less than ten,
the flow will move up to ten instead, although in this case the source is
infinite so that’s not likely to happen.
Assuming we have written our model in hiring.txt, we can
run the model via:
cat hiring.txt | systems-run
Which will run the model for ten rounds, showing this output:
A few things to note. First, the infinite [Candidate] stock is not rendered,
because the state of infinite stocks isn’t very interesting. Second, that getting
folks hired takes a long time! Finally, note that converion flows require that
their source reach a high enough number than the output is a whole number, which
means that you see some buffering across rounds in Onsite or Offer as their
preceeding flows’ inputs get to 4 and 2 respectively.
This model isn’t quite as realistic as it could be though, for example, we
don’t really get ten new prospects each day, it depends on how many sourcers
are sourcing. Also, we’re probably hiring more recruiters as well to scale
until we run out of recruiting headcount! We can model the second bit by creating a
new stock Recruiters stock that has an initial value of 3 and a maximum
of 8, assuming that eight is your headcount available for recruiters.
[Candidate] > Recruiters(3, 7) @ 1
In round zero we’ll have three recruiters, and we’ll add one each round until
we have seven recruiters, at which point we’ll stop.
More interesting, we can use the value of the Recruiters stock to determine
the number of prospects we find each round. For example, we could say that
each recruiter will source ten prospects per round:
[Candidate] > Prospect @ Recruiters * 10
In the first round we’ll get thity prospects, forty in the second round, up to
seventy in the last round. Now when we run the model:
cat hiring.txt | systems-run
We see these results (hiding the Hires column so the results fit on screen more easily):
This is pretty neat, because we’ve been able to develop a fairly sophisticated
model which would be rather hard to represent in a spreadsheet (particularly the
backpressure of the stock maximums), and were able to do it in a couple of minutes.
If you want to do some graphing on these outputs, you can export them as CSV