![](/img/trans.png)
[英]Store multiple ordinary differential equations outputs using StepHandlers with classical runge-kutta integrator
[英]Runge-Kutta (RK4) for system of differential equations in Java
這個問題主要是該線程的結果: Java中的微分方程 。
基本上,我嘗試遵循Jason S.的建議,並通過Runge-Kutta方法(RK4)實現微分方程的數值解。
大家好,我正在嘗試用Java創建一個簡單的SIR-流行病模型仿真程序。 基本上,SIR由三個微分方程組定義:
S'(t)=-lamda(t)* S(t)
I'(t)= lamda(t)* S(t)-γ(t)* I(t)
R'(t)=伽瑪(t)* I(t)
S-易感人群,I-感染者,R-康復者。 lamda(t)= [c * x * I(t)] / N(T)c-接觸人數,x-傳染性(與患病人員接觸后生病的可能性),N(t)-總人口(其中是恆定的)。
γ(t)= 1 /疾病持續時間(恆定)
在第一次嘗試不太成功之后,我嘗試使用Runge-KUtta解決此方程式,此嘗試導致以下代碼:
package test;
public class Main {
public static void main(String[] args) {
double[] S = new double[N+1];
double[] I = new double[N+1];
double[] R = new double[N+1];
S[0] = 99;
I[0] = 1;
R[0] = 0;
int steps = 100;
double h = 1.0 / steps;
double k1, k2, k3, k4;
double x, y;
double m, n;
double k, l;
for (int i = 0; i < 100; i++) {
y = 0;
for (int j = 0; j < steps; j++) {
x = j * h;
k1 = h * dSdt(x, y, S[j], I[j]);
k2 = h * dSdt(x+h/2, y +k1/2, S[j], I[j]);
k3 = h * dSdt(x+h/2, y+k2/2, S[j], I[j]);
k4 = h * dSdt(x+h, y + k3, S[j], I[j]);
y += k1/6+k2/3+k3/3+k4/6;
}
S[i+1] = S[i] + y;
n = 0;
for (int j = 0; j < steps; j++) {
m = j * h;
k1 = h * dIdt(m, n, S[j], I[j]);
k2 = h * dIdt(m+h/2, n +k1/2, S[j], I[j]);
k3 = h * dIdt(m+h/2, n+k2/2, S[j], I[j]);
k4 = h * dIdt(m+h, n + k3, S[j], I[j]);
n += k1/6+k2/3+k3/3+k4/6;
}
I[i+1] = I[0] + n;
l = 0;
for (int j = 0; j < steps; j++) {
k = j * h;
k1 = h * dRdt(k, l, I[j]);
k2 = h * dRdt(k+h/2, l +k1/2, I[j]);
k3 = h * dRdt(k+h/2, l+k2/2, I[j]);
k4 = h * dRdt(k+h, l + k3, I[j]);
l += k1/6+k2/3+k3/3+k4/6;
}
R[i+1] = R[i] + l;
}
for (int i = 0; i < 100; i ++) {
System.out.println(S[i] + " " + I[i] + " " + R[i]);
}
}
public static double dSdt(double x, double y, double s, double i) {
return (- c * x * i / N) * s;
}
public static double dIdt(double x, double y, double s, double i) {
return (c * x * i / N) * s - g * i;
}
public static double dRdt(double x, double y, double i) {
return g*i;
}
private static int N = 100;
private static int c = 5;
private static double x = 0.5;
private static double g = (double) 1 / x;
}
這似乎不起作用,因為患病人數(I)應該先增加,然后再增加到大約0,並且康復的人數應嚴格增加。 生病+健康+康復的總數應為100,但是我的代碼產生了一些奇怪的結果:
99.0 1.0 0.0
98.9997525 0.9802475 0.03960495
98.99877716805084 0.9613703819491656 0.09843730763898331
98.99661215494893 0.9433326554629141 0.1761363183872249
98.99281287394908 0.9261002702516101 0.2723573345404987
98.98695085435723 0.9096410034385773 0.3867711707625441
98.97861266355956 0.8939243545756241 0.5190634940761019
98.96739889250752 0.8789214477384787 0.6689342463444292
98.95292320009872 0.8646049401404658 0.8360970974155659
98.93481141227473 0.8509489367528628 1.0202789272217598
98.91270067200323 0.8379289104653137 1.22121933523726
98.8862386366277 0.8255216273600343 1.438670175799961
98.8550827193552 0.8137050767097959 1.672395117896858
我找不到錯誤,請指教! 提前謝謝了!
我發現這不是一個真正的編程問題,但是我還是會回答。
快速瀏覽一下,我將嘗試兩種方法:假設您的時間單位是天,此刻您似乎正在評估第一天后的情況(如果我錯了,請糾正我)。 對於您要呈現的情況,我想您想了解幾天內的演變。 因此,您必須增加循環數或時間步長(但要小心一點)
其次,您似乎在這里有一個錯誤:c * x * i / N ...不應該是(c * x * i)/ N嗎? 檢查是否有區別。 我認為您可以通過S'+ I'+ R'= 0的事實來檢查...
再一次,我沒有對此進行非常深入的檢查,只是看一看,讓我知道它是否有任何改變。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.