Дифференциальные уравнения в Java
Я пытаюсь создать простую программу моделирования модели SIR-epidemics на java.
в принципе, сэр определяется системой трех дифференциальных уравнений:
S'(t) = - l(t) * S (t)
I'(t) = l(t) * S(t) - g(t) * I (t)
R'(t) = g(t) * I (t)
s-восприимчивые люди, I - инфицированные люди, R-выздоровевшие люди.
l(t) = [c * x * I(t)] / N (T)
c-количество контактов, x-зараженность (вероятность заболеть после контакта с больным человеком), N (t) - общая численность населения (которая является постоянной).
Как я могу решать такие дифференциальные уравнения в Java? Я не думаю, что знаю какой-либо полезный способ сделать это, поэтому моя реализация производит мусор.
public class Main {
public static void main(String[] args) {
int tppl = 100;
double sppl = 1;
double hppl = 99;
double rppl = 0;
int numContacts = 50;
double infectiveness = 0.5;
double lamda = 0;
double duration = 0.5;
double gamma = 1 / duration;
for (int i = 0; i < 40; i++) {
lamda = (numContacts * infectiveness * sppl) / tppl;
hppl = hppl - lamda * hppl;
sppl = sppl + lamda * hppl - gamma * sppl;
rppl = rppl + gamma * sppl;
System.out.println (i + " " + tppl + " " + hppl + " " + sppl + " " + rppl);
}
}
}
Я был бы очень признателен за любую помощь, большое спасибо заранее!
1 ответов
дифференциальные уравнения временных рядов можно смоделировать численно, взяв DT = небольшое число и используя одно из нескольких методы численного интегрирования например метод Эйлера или Рунге-Кутта. Метод Эйлера может быть примитивным, но он хорошо работает для некоторых уравнений, и он достаточно прост, чтобы вы могли попробовать. например:
S'(t) = - l(t) * S (t)
I'(t) = l(t) * S(t) - g(t) * I (t)
R'(t) = g(t) * I (t)
int N = 100;
double[] S = new double[N+1];
double[] I = new double[N+1];
double[] R = new double[N+1];
S[0] = /* initial value */
I[0] = /* initial value */
R[0] = /* initial value */
double dt = total_time / N;
for (int i = 0; i < 100; ++i)
{
double t = i*dt;
double l = /* compute l here */
double g = /* compute g here */
/* calculate derivatives */
double dSdt = - I[i] * S[i];
double dIdt = I[i] * S[i] - g * I[i];
double dRdt = g * I[i];
/* now integrate using Euler */
S[i+1] = S[i] + dSdt * dt;
I[i+1] = I[i] + dIdt * dt;
R[i+1] = R[i] + dRdt * dt;
}
трудная часть выясняет, сколько шагов использовать. Вы должны прочитать одну из статей, на которую я ссылался. Более сложные решатели дифференциальных уравнений используют переменные размеры шага, которые адаптируются к точности / стабильности для каждого шага.
Я бы рекомендовал использовать численное программное обеспечение, такое как R или Mathematica или MATLAB или Octave, поскольку они включают в себя решатели ODE, и вам не нужно будет идти на все проблемы самостоятельно. Но если вам нужно сделать это как часть большего приложения Java, по крайней мере, попробовать его сначала с математическим программным обеспечением, а затем понять, какие размеры шагов и какие решатели работают.
удачи!