New Page 2
Моделирование систем. Урок 2. Система "Хищник,
жертва, растения".
Первая задача моделирования которую мы рассмотрим, это
простейшая модель экологической системы. Пусть у нас существует три вида
популяций: Predator (Хищник), Herbivore
(Травоядное животное), Plant (Растение). Все
они живут на определенной ограниченной площади -
Area. На каждом квадратном метре площади может
произрастать определенное количество Plant. За единицу
времени каждый из Herbivore
съедает определенное количество Plant. Если
Plant не хватает, то те животные, которым не хватило,
вымирают. Каждый Predator так же потребляет
определенное количество Herbivore за единицу времени.
Если им пищи не хватает - то те хищники, которые остались голодными, так же
умирают. Если хищникам либо травоядным животным хватает пищи, то они
размножаются с определенной скоростью. И еще одно допущение модели:
Plant растет независимо от наличия
Plant. Допустим, Herbivore
съели весь Plant, но пока они его съедали,
семена успели разлететься и из них вырос новый Plant.
Что касается Herbivore
и Predator то они растут только при
наличии онных, каждую единицу времени прирост на определенный процент. Тоесть Herbivore
и Predator растут в геометрической прогрессии,
Plant в арифметической.
И так, давайте начнем писать программу. Сначала объявим
базовый класса (мы же еще и библиотеку попутно пишем):
public
abstract class
BaseClass
{
private
BaseClass _owner;
public BaseClass
owner
{
get
{
return _owner;
}
set
{
_owner = value;
}
}
public abstract
string GetClassCaption();
} |
Теперь напишем класс для реализации растений (Plant):
public class
Plant :
BaseClass
{
public override
string GetClassCaption()
{
return
"Растение";
}
private double
_countOnAreaUnit;
///
<summary>
///
Количество растений на квадратный метр
///
</summary>
public double
countOnAreaUnit
{
get
{
return _countOnAreaUnit;
}
set
{
_countOnAreaUnit = value;
}
}
private
double _growthSpeed;
///
<summary>
///
Скорость роста, кол во в единицу времени.
///
</summary>
public
double growthSpeed
{
get
{
return
_growthSpeed;
}
set
{
_growthSpeed =
value;
}
}
private
double _count;
///
<summary>
///
Общее количество растений
///
</summary>
public
double count
{
get
{
return
_count;
}
set
{
_count =
value;
}
}
///
<summary>
///
Моделирование роста растений
///
</summary>
///
<param name="availabalArea">Доступная
площадь</param>
public void
grow(double availabalArea)
{
double totalCount = _count + _growthSpeed;
double totalArea = totalCount /
_countOnAreaUnit;
if (totalArea > availabalArea) totalArea = availabalArea;
_count = totalArea*_countOnAreaUnit;
}
} |
Аналогично Herbivore:
public class
Herbivore
{
public virtual
string GetClassCaption()
{
return
"Травоядное
животное";
}
private double
_foodNeed;
///
<summary>
///
Сколько одному животному нужно еды на единицу времени
///
</summary>
public double
foodNeed
{
get
{
return _foodNeed;
}
set
{
_foodNeed = value;
}
}
private
double _growthSpeed;
///
<summary>
///
Скорость размножения, относительный прирост за единицу времени.
///
</summary>
public double
growthSpeed
{
get
{
return _growthSpeed;
}
set
{
_growthSpeed = value;
}
}
private int
_count;
///
<summary>
///
Количество
животных
///
</summary>
public int
count
{
get
{
return _count;
}
set
{
_count = value;
}
}
///
<summary>
///
Жизненный
цикл
///
</summary>
///
<param name="plant">Доступная
пища</param>
public void
liveLoop(Plant plant)
{
double availabalFood =
plant.count;
double needFood = _count * _foodNeed;
//проверим, хватает ли еды
if (needFood
> availabalFood)
{
//если еды
не хватает,
//то
некоторые живтоные умирают
int
animalIsFull = Convert.ToInt32(availabalFood
/ _foodNeed); //
скольки
животным
хватит
еды
_count = animalIsFull;
//выживает только те, кто успел "пообедать"
//все
растения съедены
plant.count = 0;
}
else
{
//еды
хватило всем, животные размножаються
_count =
Convert.ToInt32(_count * (1 + _growthSpeed));
//животные съели растения, отразим этот
факт - уменьшим кол-во растений
plant.count = plant.count - needFood;
}
}
} |
И Predator:
public class
Predator
{
public virtual
string GetClassCaption()
{
return
"Хищник";
}
private int
_foodNeed;
///
<summary>
///
Сколько одному хищнику нужно еды на единицу времени
///
</summary>
public int
foodNeed
{
get
{
return _foodNeed;
}
set
{
_foodNeed = value;
}
}
private
double _growthSpeed;
///
<summary>
///
Скорость размножения, относительный прирост за единицу времени.
///
</summary>
public double
growthSpeed
{
get
{
return _growthSpeed;
}
set
{
_growthSpeed = value;
}
}
private int
_count;
///
<summary>
///
Количество
хищников
///
</summary>
public int
count
{
get
{
return _count;
}
set
{
_count = value;
}
}
///
<summary>
///
Жизненный
цикл
///
</summary>
///
<param name="herbivore">Доступная
пища</param>
public void
liveLoop(Herbivore herbivore)
{
int availabalFood =
herbivore.count;
int needFood = _count * _foodNeed;
//проверим, хватает ли еды
if (needFood
> availabalFood)
{
//если еды
не хватает,
//то
некоторые хищники умирают
int
animalIsFull = Convert.ToInt32(availabalFood
/ _foodNeed); //
скольки
животным
хватит
еды
_count = animalIsFull;
//выживает только те, кто успел "пообедать"
//все
жертвы съедены
herbivore.count = 0;
}
else
{
//еды
хватило всем, хищники размножаются
_count =
Convert.ToInt32(_count * (1 + _growthSpeed));
//хищники съели травоядных, отразим этот
факт - уменьшим кол-во растений
herbivore.count = herbivore.count - needFood;
}
}
} |
Что бы моделировать взаимодействие всех этих объектов, создадим класс
Area:
public class
Area :
BaseClass
{
private Plant
_plant;
public override
string GetClassCaption()
{
return
"Площадка";
}
///
<summary>
///
Растения
///
</summary>
public Plant
plant
{
get
{
return _plant;
}
set
{
_plant = value;
}
}
private
Herbivore _herbivore;
///
<summary>
///
Травоядные
///
</summary>
public Herbivore
herbivore
{
get
{
return _herbivore;
}
set
{
_herbivore = value;
}
}
private Predator
_predator;
///
<summary>
///
Хищники
///
</summary>
public Predator
predator
{
get
{
return _predator;
}
set
{
_predator = value;
}
}
private double
_availabalArea;
///
<summary>
///
Доступная
площадь
///
</summary>
public double
availabalArea
{
get
{
return _availabalArea;
}
set
{
_availabalArea=value;
}
}
///
<summary>
///
Жизненный
цикл
///
</summary>
public void
liveLoop()
{
_plant.grow(_availabalArea);
_herbivore.liveLoop(_plant);
_predator.liveLoop(_herbivore);
}
} |
Теперь накидаем на форму меток и кнопочку:
Вместе с конструктором и обработчиком нажатия на кнопочку, программа выглядит
примерно так (у вас могут быть другие начальные данные и название объектов):
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.Windows.Forms;
namespace
WindowsFormsApplication1
{
public partial
class Form1
: Form
{
private Area
_area;
public Form1()
{
InitializeComponent();
_area = new
Area();
_area.availabalArea = 10000;
_area.herbivore = new
Herbivore();
_area.herbivore.count = 200;
_area.herbivore.foodNeed = 2;
_area.herbivore.growthSpeed = 0.1;
_area.plant = new
Plant();
_area.plant.count = 2000;
_area.plant.countOnAreaUnit = 10;
_area.plant.growthSpeed = 500;
_area.predator = new
Predator();
_area.predator.count = 10;
_area.predator.foodNeed = 1;
_area.predator.growthSpeed = 0.1;
showData();
}
private void
showData()
{
lbHerbirove.Text = _area.herbivore.count.ToString();
lbPlants.Text = _area.plant.count.ToString();
lbPredators.Text = _area.predator.count.ToString();
}
private void
btnNext_Click(object sender,
EventArgs e)
{
_area.liveLoop();
showData();
}
}
} |
И так, запускаем программу и наблюдаем результат:
Вообще, скажу сразу, какие бы исходные данные вы не завели,
кончиться все одинаково: хищники съедать всех травоядных и вымрут сами.
Попробуйте поэкспериментировать. Почему так происходит? Ответ прост и очевиден:
количество хищников растет неограниченно, а количество травоядных ограничено
количество подножного корма - когда трава заполнить всю доступную площадь,
прирост травоядных прекратится. А хищники будут плодиться и размножаться, пока
не съедят всех травоядных.
Ну что-ж, подведем итоги. Мы запрограммировали простейшую
модель экосистемы, которая, как оказалось, неустойчивая и в конце концов
приходит к коллапсу. В следующих уроках мы придумаем другие, более устойчивые
системы и будем их моделировать.
Скриншоты, приведенные в данной статье,
являются цитатами и иллюстрациями программного
продукта "Microsoft Visual Studio 2010", авторское право на
который принадлежит Microsoft.
|