HOME - - - - - Lazarus Tutorials TOC - - - - - - Other material for programmers
Delicious.Com Bookmark this on Delicious     StumbleUpon.Com Recommend to StumbleUpon

Simulating Predator/ Prey Population Dynamics

And similar systems... Part 2

This is the second of two web pages. Ostensibly, they show you how to make a good start on a simulation modeling the ecology of a small woodland, inhabited by grass, rabbits and foxes. A Predator/ Prey Population Dynamics simulation.

The simulation won't win any prizes... yet... for being true- to- nature. But, having said that, the way the work already done has been done should mean that extending the simulation to make it more life-like is entirely feasible. It would be an interesting challenge.

Where we are going.

The primary value of the material here will be, I think, as an example of how you could build a simulation of things like predator/ prey interaction. Things that proceed in "generations". Cellular automata, such as Conway's "Life". Traffic flows. River flooding. One thing you could tackle this way which particularly tempts me is a simulation of how age pyramids proceed... i.e. graphs showing the numbers of males and females in age-range bands, over a series of years. Many, many possibilities!

Download the sim07- Predator/ Prey Population Dynamics simulation source-code. If you just want the source-code, to adapt to your own purposes (or to follow along, as you read this essay), it is available for download, in an archive called, not very imaginatively, "sim07.zip". The .exe that arises from compilation is included in that .zip, and can be run without any further ado. It doesn't read from or write to your hard drive. You can run it directly from the .zip, without doing an extract- and- save first. Compiled for Windows, on a Win7 machine. Download tested under Firefox.)

A few odds and ends of generally useful programming tricks and techniques also arise, as, I hope, ever.

Not "as ever" will be the level of hand-holding I generally offer, particularly in tutorials of a more elementary nature. I invite you to try some of the lower "level" tutorials at my site until you are more Lazarus (or Delphi) "fluent", if you find this one goes too quickly.

Many general techniques are illustrated along the way. A compiled .exe is available so that you can play with the application without having to compile it. The Lazarus sourcecode is in the same zip file you can download. Both are there for you to play with... but I reserve all rights to any applications derived from the sourcecode. It is there to show you programming techniques, not to be the basis of a commercial product. Well... anyone else's commercial product, anyway.

This is a continuation from sim06, a simulation of population dynamics in a woodland.

While sim06 had some very good stuff in it, and in its design and development, there was one major flaw... a pretty dumb one, at that!

You really should read that tutorial before this one, as there are many things I am not going to inflict twice on people who HAVE read the first "chapter".

The "plan" was to model the biomass of the grass, rabbits and foxes in a small woodland, by simply going 'round and 'round the following loop....

REPEAT....
   Make a note of how things stood, end of previous period.

   Based on the grass you have, add more. (It grew)
   Based on number of rabbits, decrease grass by a certain amount.

   Based on number of rabbits, increase number of rabbits. (They bred)
   Based in number of foxes, decrease number of rabbits. (They got eaten)

   Based on number of rabbits, increase or decrease number of foxes. (Their increase from breeding either did, or did not, exceed the deaths due to starvation.)

UNTIL YOU ARE BORED (or a population crashes!)

===

Remember, please... the point of this is NOT to produce the latest, greatest population dynamics simulator. Rather, it is to demonstrate some programming principles. Not least of which is "Build a framework that is robust. One which can gradually be developed, enhanced, made to incorporate more details."

===

In the pseudo-code outline, you may have noticed "Make a note of how things stood, end of previous period."

This is a common necessity in programs of this sort. It arises thus....

Early on, we are going to revise the biomass of grass present. And after that, we are going to do a calculation on the feeding success of the rabbits including as a factor, the grass available to them. But we don't want to be using the NEW grass biomass. We want access to what the grass biomass was at the end of last year.

Hence, we created the following....

lwBM_grassPrev, lwBM_rabbitPrev, lwBM_foxPrev:longword;

We will fill them, at the beginning of the loop, from lwBM_grass, lwBM_rabbit and lwBM_fox.

So far, so good. When, for instance, assessing how much rabbit biomass might have been lost in the past year due to the foxes eating rabbits, it isn't fair to use the number of foxes at the end of the year. (Of course, it isn't perfect to use the number of foxes at the beginning of the year, either. But we are going, at least for now, to "let that go", and use the number of foxes at the beginning of the year in our calculations.)

These calculations take place in the RabbitsReduce subroutine.

The problem with the first version, sim006, arose in several places. Here's one, to illustrate it.

The two lines of pseudo-code concerning the amount of rabbit biomass were as follows...

   Based on number of rabbits, increase number of rabbits. (They bred)
   Based in number of foxes, decrease number of rabbits. (They got eaten)

They turned into....

  lwBM_rabbit:=(lwBM_rabbitPrev*wRabbitAD) div 1000;
  lwBM_rabbit:=lwBM_rabbitPrev-((lwBM_fox*wRabbitRD) div 100);

A moment's thought will tell you that the first line is going to be a complete waste of time, have no effect on the rabbit biomass at the end of the current "year". The "new" (after the "Add") rabbit biomass is over-written with the result of the "reduce rabbit biomass" calculation (the second line.)

At this point, while the simulation is simple, there is a very simple fix to this problem....

  lwBM_rabbit:=(lwBM_rabbitPrev*wRabbitAD) div 1000;
  lwBM_rabbit:=lwBM_rabbit{Prev}-((lwBM_fox*wRabbitRD) div 100);

(The one set of curly brackets {} in the second line, "take out" the "Prev" between them, making the line, effectively,....

lwBM_rabbit:=lwBM_rabbit-((lwBM_fox*wRabbitRD) div 100);

... which "Would Work".

However! "It would work" "solutions" are sometimes false promises of an easy fix.

Any time you find you can fix something serious with an easy fix, examine it with care and suspicion.

If this simulation is going to be a good foundation upon which a sophisticated simulation can, in time, with work, be built, it needs to be a solid foundation, without little "tricky" bits to trip us up when we are concentrating on something else later.

At the moment, the RabbitsAdd and RabbitsReduce subroutines, from which the two lines above come, each consist of just the one line you see. If the simulation is to be made more realistic, those subroutines will grow. Remembering that in one we can work from lwBM_rabbitPrev to calculate then new lwBM_rabbit, but in the other we must work from the new, the intermediate, the "sub-total" "lwBM_rabbit"... even while in parts we will need to know the lwBM_rabbitPrev figure is just asking for trouble.

Previously, if we wanted to add 10% to the rabbit biomass, we (in effect) did....

lw_BM_rabbit:=lw_BM_rabbit*1.10

Although it will mean more variables, and more calculations, I am persuaded that for the lack of subtle things to trip us up, it may be wiser to adopt the following approach. It will mean that the way the changes are calculated in both the "Add" and "Reduce" subroutines will follow a common pattern....

Approximation of new way to add 10% to lw_BM_rabbit....

lwToAdd:=lw_BM_rabbit*0.1;
lw_BM_rabbit:=lw_BM_rabbit+lwToAdd;

.. and in the "Reduce" subroutine, we would have something like....

lwToSubtract:=lw_BM_rabbit*0.05;
lw_BM_rabbit:=lw_BM_rabbit-lwToSubtract;

Yes, I know I've "cheated" and pretended we can multiply an integer by 0.1... you'll see the way we get around that in the actual code. However, note that I have NOT cheated in the matter of trying to store a negative number in an unsigned integer type variable.

Of course, because I chose to use unsigned integers, I will need....

lwToSubtract:=lw_BM_rabbit*0.05;
if (lw_BM_rabbit>lwToSubtract) then lw_BM_rabbit:=lw_BM_rabbit-lwToSubtract
   else lw_BM_rabbit:=0;

Also all of the "rates" will have to be converted. (1020 to become 20, etc.)

Sigh. I noticed the flaw in sim06 about an hour ago. And now I have the "joy" of implementing the things discussed above. I'd much rather be extending the program, not fixing flaws! Just shows what happens to programmers who type before they have thoroughly planned (and reviewed plans.) Oh well.

===========

(After about an hour.... Onward! (Hurrah!))

I wanted to leave having a graph of the biomasses for another time... it introduces a bunch of new headaches... but I couldn't resist.

The scaling is somewhat arbitrary, with the swings of the rabbit and fox biomass exaggerated, relative to the grass biomass. If they were all to the same scale, the variation in the rabbit and fox biomass would be hard to see.

Controls related to the graphing... Image1, with a bitmap associated. (See sheepdogguides.com/lut/PixelProblem.htm, and the section marked "Set up a non-resize-able "surface" for doing graph on." in the FormCreate handler of the code. Note also the constants associated with this, wImageW, wImageH, and the extra variable, "Bitmap", of type TBitmap.

New data will be added at the right hand edge of the chart, and each "year" it will scroll one pixel to the left. Hence the new subroutines "ClearDrawingSurface", "PlotPoints" "DrawLine" and "ScrollGraph". (And "DrawDiag", if it is still present!

These, and Image1, and Bitmap, are all just for doing the graph showing the biomasses over time. Do not waste time on them if they perplex you.

Also just for the graphing: clGrass, clRabbit, clFox (determine color lines drawn in.)

Further for graphing: The offset and scaling constants, for grass, rabbit and fox: wScGrass, wOffGrass, etc.

====

At this point....

That about exhausts the time I have for this at the moment.

As I hope I have said often enough, it is NOT presented as a "finished", "complete" predator/ prey model. I hope you agree that it IS a good basic framework which could be taken much further? I hope you see elements in it which would be useful ingredients for many wants? I hope you can see that not only is the basic framework suitable for predator/ prey models, but also for other programming, for instance "artificial life" simulations, in the style of Conway's "Life". Or, as I happen to be listening to some "relaxing" music", a dynamic graphics display simulating an unfolding "biome", to be used, say, for a screensaver. The framework could be used to model movements of planets around a sun. Etc, etc.

====

To Do's....

Sigh. I REALLY have to turn to other things. But I couldn't just write about adding a "make it go by itself" button, so publication (and breakfast, and the day job, etc, etc) got delayed to do that.

The complexity of the biology can be studied in ever greater detail until you have your Ph.D in ecology, and beyond. I seriously believe that the framework in this modest start at modeling an ecosystem could "take the strain" of very significant extension. Even if just as a hobbyist (programmer, or biologist, or both!), I hope you will add more factors in- for the fun of it. A huge advance would be to add grasshoppers and mice and a kestrel... and make all feeding proportionate to a predator's "likes" and prey abundance. Harder to add, maybe, but equally important... a mechanism which introduced a lag between biomass increase and the consequent rate (in absolute terms) of "increase increase". This, done properly, would soon make the sim portray things like the famous link between lynxes and hares in Canada. 1845-1925. (The two populations went through symmetrical, but out of phase, "boom/ bust" cycles.) (More foxes (or better conditions, and hence survivorship) in June 2016 doesn't mean "more more" foxes in July of the same year. The cubs have to grow up before they reproduce!)

Many of the things you would tweak by hand, then recompile, should be accessible interactively. An ini file should hold the values you had chosen. It should be possible to save and load scenarios. If you restart the sim (with the button set up for doing that without shutting/ reopening the app), the "clock" should stop, i.e. "Auto-advance" should be turned off.

The game element (you get to "play God", selectively add biomass, to "put thumb on scale", as sim progresses) needs to be added in.

Enjoy! I hope you will publish derivatives, and let me know where, so I can go and look at what you've built! (I will assume you want a link to it from here, unless I hear otherwise)

Done!

That's it for this two part tutorial. I hope you liked it, will recommend via social media (see top of page), etc. Feedback welcome other than "needs more graphics". (I know that!)





Search across all my sites with the Google search...

Custom Search
            powered by FreeFind
  Site search Web search
Site Map    What's New    Search This search merely looks for the words you enter. It won't answer "Where can I download InpOut32?"
Ad from page's editor: Yes.. I do enjoy compiling these things for you. I hope they are helpful. However... this doesn't pay my bills!!! Sheepdog Software (tm) is supposed to help do that, so if you found this stuff useful, (and you run a Windows or MS-DOS PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!
Click here to visit editor's freeware, shareware page.

Link to Lazarus Tutorials main page
How to contact the editor of this page, Tom Boyd


Please consider contributing to the author of this site... and if you don't want to do that, at least check out his introduction to the new micro-donations system Flattr.htm....



Valid HTML 4.01 Transitional Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org. Mostly passes. There were two "unknown attributes" in Google+ button code. Sigh.


If this page causes a script to run, why? Because of things like Google panels, and the code for the search button. Why do I mention scripts? Be sure you know all you need to about spyware.

....... P a g e . . . E n d s .....