Predator-Prey Model at Node.js

Recently, a surge of references to the game Life has passed through the network , mainly due to the fact that its creator died.

Now is the time, everyone has become interested in biology, everywhere these survival schedules, well, I suddenly got out of the bins of memory an interesting model, according to which I once wrote a term paper.

The model is similar to Life in that it is the same cyclical process that can be viewed as a fire, meditate endlessly and reflect on the eternal.

This is a Predator-victim , a very serious model from applied mathematics (Predator-prey in the English-speaking world).

The essence of the process is that in a certain forest there lives a herd of deer (in the alternative version - rabbits, but not the essence), which eat into the wild and breed wildly, and sooner or later fill the whole territory.

However, in the same forest there are also predators that feed on these deer (wolves, but for hares, usually foxes).

A pair of predators that find themselves in this abundant forest multiplies exponentially vigorously in accordance with the law of Malthus , but at some point, deer resources begin to dry up, wolves begin to starve and die out, the exhibitor quickly flies down and only the most persistent survive there.

The deer, driven into a corner, raise their heads, turn on their exhibitor and begin to dominate the forest, but the surviving wolves with fresh meat find strength in themselves for a new wave of fertility ... and so on in circles and to infinity.

Here is a graph (dragged from Wikipedia): The



mathematical model of this process was described at the beginning of the 20th century by Lotka and Volterra and named after them.

Why has this model been around for a hundred years and still relevant?

There are two main reasons: it is very simple and describes the process quite realistically.

The model has only four parameters:

  • alpha) deer breeding rate
  • beta) deer eating speed by wolves
  • gamma) the rate of extinction of hungry wolves
  • delta) breeding rate of well-fed wolves

The model contains minimal nonlinearity and is considered analytically. With well-chosen parameters, it is stable (neither deer nor wolves die out to the end) and realistically describes the dynamics of fluctuations in populations.

For a hundred years, there have been many attempts to make something more realistic - but any increase in complexity leads to a nonlinear system of a higher level and then everything rests on impenetrable integral equations that can only be solved by numerical methods.

There is another method - just program this process as a game.

In fact, this approach is called multi-agent modeling and is quite suitable to pass the course.

Choosing a Technology


I would like the program to have visualization, not only on the author’s machine, but on the largest possible audience, and that it should be all by itself, with minimal effort and all that.
It is logical that the solution will be to run the program in a browser and, therefore, you will have to write it in javascript.

Well, in order not to produce a technology zoo, we will also write a server on it.

The standard steps for installing node.js and everything you need are described on the github .

Deer growth model


We pass to the most interesting - reproduction. Without predators, we have a Malthusian model in conditions of limited resources (in the world of mathematics it is described by a logistic function or the Verhulst equation ), now it must somehow be applied to agents.

It is possible to select probabilistic coefficients for each deer and everything should work out.
But agent agent modeling is good - you can specify the behavior without limiting yourself to a few factors.

In general, the deer model of life looks like this:

  • deer need to move. A deer that could not budge per unit of time dies (and he could not budge just because all the neighboring cages are occupied by his friends).
  • , , .

  breed(u) {
    var spots = MapUtil.get_adj(u.point, this.W, this.H)
    if (!spots || spots.length < 1)
      return false
    var free = spots.filter(p => !this.GM.get(p))
    if (free.length < spots.length)
      return false
    var spot = _.sample(spots)
    if (!spot)
      return false
    var born = new Wild(u.kind)
    born.move(spot)
    this.add_wild(born)
    this.born.push(born)
  }

Next, we will make an easy test app that creates a 20x20 forest world, runs into the very center of the deer, and runs 100 cycles, each time printing the status in csv.

We will drive the resulting csv-file into Google Spreadsheet and generate a graph:



It’s quite an exponent. We see that the number is stabilizing for 200+ deer, this can easily be explained by the fact that the need for movement requires at least two cages for the deer, and the area of ​​the whole forest is 400. The

maximum growth happens quite early - on move 14-15, and the last 20 moves stands still with slight fluctuations.

In general, I want to emphasize that the simplest agent model behaves very realistically, quite similar to a logistic curve diluted with a slight noise.

But we came here not so much for numbers, but for pictures that you can look at and relax.

So, it's time to make a page with a map and graphs, and transfer the model run to the server.

We put express and socket.io, and we will draw directly on html5 canvas (I am not familiar with js engines, and the task is not very difficult).

We look and get nervous about how deer literally flood the forest in a few iterations, and then asymptotically fluctuate around the maximum.



On the one hand, this is just a model, but in some places this is a real problem - just google deers overpopulation and be surprised at the abundance of material on this topic.

This model does not take into account forest degradation, but in fact deer are rather greedy consumers - they eat shoots, trample the earth and generally destroy their forests.

What should the forest owner do in this case?

He buys wolves, hangs a GPS sensor on each and prays that they will not disappear.

Wolves


It's time to introduce the wolf into our model.

Two things need to be decided - how the wolf eats and multiplies.

It's easy to hunt when there is someone - if there is a deer in any neighboring cage - just eat it.

If there is no deer, then you can survive for a period of time.

To begin with, let’s say that there can be a wolf every move, but if in two moves it was not possible - to the side of evolution.

With the multiplication of more options.

To begin with - we remove the delicacy, let the wolves multiply always when there is free space.

And add a restriction - hungry wolves do not breed.

First pancake


Let the deer multiply a little and throw the wolf into the crowd: the



Model turned out, to put it mildly, unstable - the wolves instantly mowed out all the deer and quickly died out.

One frustration, no zen.

Second attempt


Something needs to be changed.

It hurts the eye at how explosive the wolves are breeding.

Let's complicate their life a little - we set the condition that it is possible to breed only if there are more deer than wolves on neighboring deer cells.

    var preys = spots.map(p => this.GM.get(p)).filter(u => u && u.kind == Wilds.DEER)
    var preds = spots.map(p => this.GM.get(p)).filter(u => u && u.kind == Wilds.WOLF)
    if (preys.length <= preds.length)
      return false

And abandon the wolves when the deer population reaches its maximum.

This attempt succeeded much better.

The balance of predators and victims is constantly on the move, the deer population has greatly decreased and now it’s not even getting close to its maximum.



However, anything can happen, and almost every time it happens that the wolves manage to die out, and the deer triumphantly fill the thicket again.

In this run, the wolves lasted a long time:



Third circle


We'll have to tighten the breeding nuts even harder.

We now state the condition: there must be deer nearby, but there should be no wolves.
Such gentle wolves do not tolerate competition.

The system is more stable.

Compared to the previous graph, the peaks are smoothed by both deer and wolves.



In general, it’s clear where to move to get the same smooth schedule as on Wikipedia.
As a result, we come to a banal conclusion - we must reproduce consciously, and not to the maximum.
It sounds like an advertisement for hedonism, but you can further reduce the fertility of wolves in the expectation of "improving the quality and duration of their life" ...



Deployment


As an epilogue, deployment instructions.

It is very short:

1. We write a simple docker file:

FROM node:14
ADD https://github.com/tprlab/predator-prey/archive/master.zip /
RUN unzip /master.zip
WORKDIR /predator-prey-master
RUN npm install
EXPOSE 8081
CMD ["node", "server.js"]

2. docker build. -t predator-prey

3. docker run -p 8081: 8081 predator-prey

For the laziest, I collected and uploaded the image to the Docker Hub.

If you don’t want to mess with the docker, there is an installation instruction from scratch on the repo page (link below).

References



All Articles