簡體   English   中英

Java中的微分方程組的Runge-Kutta(RK4)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM