Список работ

C#: пример употребления IMSL Math; Хищник-жертва

Содержание

Введение

Создается C#-приложение, в котором средствами IMSL Math решается система обыкновенных дифференциальных уравнений (ОДУ). Рассматривается следующая модель Хищник-жертва (модель Лотки-Вольтерра):

dx/dt = a1 * x – b1 * x * y
dy/dt = –a2 * y + b2 * y * x,

в которой x и y – соответственно плотность популяций хищника и жертвы;
a1 – скорость размножения жертвы в отсутствии хищника;
a2 – естественная смертность хищника;
b1 и b2 – коэффициенты, отвечающие потребности в пище соответственно хищника и жертвы.
Система имеет следующее явное решение:

xa2eb2x = c * ya1e-b1y, c = const.

Для получения результата используется метод Рунге-Кутты.
Решение ОДУ отображается в виде фазового портрета (рис. 1).

Фазовый портрет модели Хищник-жертва

Рис. 1. Фазовая диаграмма модели Хищник-жертва

Изменение численности обоих видов происходит по периодическому закону с амплитудой колебаний, определяемой начальными значениями x и y.
В диаграмму вводится маркер в виде залитого красного круга, находящийся в начальной точке расчета (интегрирования).
Начальная точка задает некоторые значения плотностей популяций хищника и жертвы.
В дальнейшем координаты начальной точки определяются положением мыши в момент нажатия ее левой кнопки (событие MouseDown, процедура UpdateInitialPoint).
Всего рассчитываются nPoints точек, по которым выводится фазовый портрет модели.
Данные накапливаются в массивах rabbits и foxes.
Так же начальную точку можно менять, перемещая мышь с нажатой левой клавишей (событие MouseMove). Если перемещение на очень быстрое, то можно наблюдать получаемые с разных начальных точек фазовые портреты.
Число полученных фазовых портретов хранит переменная numberSolved, значение которой отображается методом dataSolved.SetTitle().
Тип проекта - Windows Form Application. Форма, создаваемая при начале нового проекта, и весь связанный с ней код удаляются. Взамен используется приводимая в следующем разделе программа.
Форма, наблюдаемая на рис. 1, генерируется этой программой. Детали построения формы см. в приводимом коде и сопутствующем комментарии.
Подключение недостающих ссылок осуществляется обычным способом: Solution Explorer – References – правая кнопка мыши – Add Reference.
Приводимый код основан на примере, имеющемся в проекте IMSLDemo, поставляемом с библиотекой C#-IMSL.

Реализация

using System;
using System.Drawing;
using System.Windows.Forms;
using Imsl.Chart2D;
using Imsl.Math;

namespace WindowsFormsApplicationIMSL
{
    static class Program
    {
        // Точка входа приложения
        [STAThread]
        static void Main()
        {
            Application.Run(new Predator());
        }
    }
    public class Predator : System.Windows.Forms.Form, Imsl.Math.OdeRungeKutta.IFunction
    {
  private Imsl.Chart2D.PanelChart panelChart1;
  private System.ComponentModel.Container components = null;
  private Imsl.Chart2D.AxisXY axis;
        // Число точек в фазовом портрете
  private const int nPoints = 100;
  private double[] rabbits, foxes;
        // Стартовая точка
  private double[] point = new double[] {2, 3};
        // Положение маркера; совпадает с начальной точкой
  private double[] initialRabbit = new double[] {2};
  private double[] initialFox = new double[] {3};
  private Data dataSolved;
  private Data dataError;
  private int numberSolved;
  private bool isMouseDown = false;

  public Predator()
  {
   InitializeComponent();
   // Обработчики событий MouseDown, MouseUp и MouseMove
   panelChart1.MouseDown += new MouseEventHandler(panelChart1_MouseDown);
   panelChart1.MouseUp += new MouseEventHandler(panelChart1_MouseUp);
   panelChart1.MouseMove += new MouseEventHandler(panelChart1_MouseMove);
   rabbits = new double[nPoints]; // Плотность популяции кроликов
   foxes = new double[nPoints]; // Плотность популяции лисиц
   SetChart();
   try
   {
    Solve();
   }
   catch (Exception exception)
   {
    Console.Out.WriteLine(exception.Message);
    return;
   }
  }
  private void InitializeComponent() {
   this.panelChart1 = new Imsl.Chart2D.PanelChart();
   this.SuspendLayout();
   //
   // panelChart1
   this.panelChart1.Location = new System.Drawing.Point(0, 0);
   this.panelChart1.Name = "panelChart1";
   this.panelChart1.Size = new System.Drawing.Size(592, 568);
   this.panelChart1.TabIndex = 0;
   //
   // Хищник
   this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
   this.ClientSize = new System.Drawing.Size(592, 566);
   this.Controls.Add(this.panelChart1);
   this.Location = new System.Drawing.Point(64, 64);
   this.Name = "Predator";
   this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
   this.Text = "Хищник-жертва";
   this.ResumeLayout(false);

  }
  private void SetChart()
  {
   Imsl.Chart2D.Chart chart = panelChart1.Chart;
   chart.ChartTitle.FontSize = 12;
   chart.ChartTitle.SetTitle("Хищник-жертва");
   axis = new AxisXY(chart);
   axis.AutoscaleInput = AxisXY.AUTOSCALE_OFF;
   axis.AxisX.SetWindow(0.0, 5.0);
   axis.AxisY.SetWindow(0.0, 5.0);
   axis.AxisX.FontSize = 11;
   axis.AxisY.FontSize = 11;
   axis.AxisX.AxisTitle.SetTitle("Плотность популяции, Кролики");
   axis.AxisY.AxisTitle.SetTitle("Плотность популяции, Лисы");
   Data data = new Data(axis, rabbits, foxes);
   data.DataType = Data.DATA_TYPE_LINE | Data.DATA_TYPE_MARKER;
   // Маркер в позиции мыши; маркер - это залитый круг красного цвета
   data.MarkerType = Data.MARKER_TYPE_FILLED_SQUARE;
   data.MarkerSize = 0.75;
   data.MarkerColor = Color.Blue;
   data.LineColor = Color.Blue;
   // Показываем маркер в позиции (initialRabbit, initialFox)
   data = new Data(axis, initialRabbit, initialFox);
   data.DataType = Data.DATA_TYPE_MARKER;
   data.MarkerType = Data.MARKER_TYPE_FILLED_CIRCLE;
   data.MarkerSize = 1.5;
   data.MarkerColor = Color.Red;
   // Позиция заголовка, отображающего значение переменной numberSolved
   double[] px = {2.5};
   double[] py = {4.7};
   dataSolved = new Data(axis, px, py);
   dataSolved.LabelType = Data.LABEL_TYPE_TITLE;
   dataSolved.SetTitle("Решено ОДУ: 1");
   dataSolved.TextColor = Color.DarkGreen;
   dataSolved.FontSize = 12;
   // Позиция сообщения об ошибке
   double[] ex = {2.5};
   double[] ey = {4.0};
   dataError = new Data(axis, ex, ey);
   dataError.LabelType = Data.LABEL_TYPE_TITLE;
   dataError.SetTitle("");
   dataError.TextColor = Color.Red;
   dataSolved.FontSize = 12;
  }
  private void Solve()
  {
   OdeRungeKutta q = new OdeRungeKutta(this);
   double dt = 10.0 / (nPoints - 1);
   for (int k = 0; k < nPoints; k++)
   {
    // Интегрируем ОДУ от k * dt до (k + 1) * dt
    q.Solve(k * dt, (k + 1) * dt, point);
    // Точка на фазовом портрете в момент времени (k + 1) * dt
    rabbits[k] = point[0]; // Плотность популяции кроликов
    foxes[k] = point[1]; // Плотность популяции лисиц
   }
   numberSolved++;
  }
  private void UpdateInitialPoint(MouseEventArgs e)
  {
   axis.MapDeviceToUser(e.X, e.Y, point);
   initialRabbit[0] = point[0];
   initialFox[0] = point[1];
   Solve();
   dataSolved.SetTitle("Решено ОДУ: " + numberSolved);
   dataError.SetTitle("");
   Refresh();
  }
  // Система ОДУ Хищник-жертва
  public void F(double t, double[] y, double[] yprime)
  {
   yprime[0] = 2.0 * y[0] - 2.0 * y[0] * y[1];
   yprime[1] = -1.0 * y[1] + 1.0 * y[1] * y[0];
  }
  private void panelChart1_MouseDown(object sender, MouseEventArgs e)
  {
   isMouseDown = true;
  }
  private void panelChart1_MouseUp(object sender, MouseEventArgs e)
  {
   isMouseDown = false;
   UpdateInitialPoint(e);
  }
  private void panelChart1_MouseMove(object sender, MouseEventArgs e)
  {
   if (isMouseDown) UpdateInitialPoint(e);
  }
 }
}

Список работ

Рейтинг@Mail.ru