A medida que aumenta la población, el gráfico modelo SIR debe cambiar a la izquierda. Y las barras de velocidad de recuperación no funcionan en absoluto

Estoy tratando de simular la propagación de un virus usando el modelo SIR en VB. pero mi código no funciona.

aumentar las infecciones iniciales: debe cambiar el gráfico izquierda (pero la mía no)
aumentar Población: turnos gráfico izquierda (pero la mía no)
aumento Susceptible: cambio de gráfico izquierda (pero la mía no)
aumentar la tasa de transmisión (b): aumenta el pico de la curva "infectivas" (pero mi barra de pistas no funciona en absoluto - produce un error de desbordamiento)
aumentar la tasa de recuperación (a): 'infectives' disminuye el pico, mientras que las otras dos líneas suben

Esto es lo que el gráfico debería hacer: https://faradars.org/ev/sir-simulator/?lang=en

Estas imágenes demuestran los errores de mi código que no sé cómo solucionar:

One

Two

Three

Four

Aquí está mi código:

Imports System.Windows.Forms.DataVisualization.Charting
Public Class Form1
  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load


    'initail values  
    Dim N As Double = 10000
    Dim S As Double = 8000
    Dim R = 0.0
    Dim I As Double = N - S - R


    Dim t As Double = 0
    Dim b As Double = 2 'contact rate
    Dim a As Double = 0.5 'removal rate
    Dim scale As Double = 0.1



    setupForm(N, S, I, R, t, b, a, scale)
    ProccessGraph()
End Sub

Sub setupForm(N, S, I, R, t, b, a, scale)

    'Trackbars
    Dim tbData(7) As Decimal
    tbData(1) = N           'population N
    tbData(2) = S           'Susceptibles S
    tbData(3) = I           'infectives I
    tbData(4) = R           'Recoveries R
    tbData(5) = t           'time t
    tbData(6) = b           'infection rate b
    tbData(7) = a           'removal rate a
    Dim y As Integer = 10
    For I = 1 To 7
        Dim Tbar As New TrackBar
        With Tbar
            .Location = New Point(20, y)
            .Size = New Size(140, 30)
            .BackColor = Color.White
            .Minimum = 0
            .Maximum = 10000
            .SmallChange = 1
            .Name = "Trackbar" & I
            .Value = tbData(I)
        End With
        Me.Controls.Add(Tbar)



        'labels (display value) ✓
        Dim labvalue As New Label
        With labvalue
            .Location = New Point(180, y)
            .Name = "label" & I
            .Size = New Size(50, 15)
        End With
        Me.Controls.Add(labvalue)


        'labels (tbar title) ✓
        Dim labtitle_data(7) As String
        labtitle_data(1) = "Population N"
        labtitle_data(2) = "Susceptibles S"
        labtitle_data(3) = "Infectives I"
        labtitle_data(4) = "Recoveries R"
        labtitle_data(5) = "time"
        labtitle_data(6) = "infection rate"
        labtitle_data(7) = "removal rate"
        Dim labtitle As New Label
        With labtitle
            .Location = New Point(240, y)
            .Name = "label" & I
            .Size = New Size(60, 60)
            .Text = labtitle_data(I)
        End With
        y += 60
        Me.Controls.Add(labtitle)


        'ComboBox (to list countries) ✓
        Dim cb1 As New ComboBox
        cb1.Items.Add("China")
        cb1.Location = New Point(990, 50)
        Me.Controls.Add(cb1)


        'Form properties ✓
        Me.Size = New Size(1200, 500)
        Me.BackColor = Color.White

        AddHandler Tbar.ValueChanged, AddressOf ProccessGraph 'every time the value changes, recreate the graph to match it
    Next
End Sub

Sub ProccessGraph()
    Dim tblist(7) As TrackBar 'array of trackbars
    For tbar = 1 To 7
        tblist(tbar) = Me.Controls("TrackBar" & tbar)
        Me.Controls("label" & tbar).Text = tblist(tbar).Value 'adds value to label
    Next
    'reset NSIR values to match trackbar values
    Dim N = tblist(1).Value
    Dim S = tblist(2).Value
    Dim I = tblist(3).Value
    Dim R = tblist(4).Value
    Dim t = tblist(5).Value


    Dim b = tblist(6).Value
    'Dim a = tblist(7).Value
    Dim a As Double = 0.5
    Dim scale As Double = 0.1
    'b = tblist(6).Value
    'a = tblist(7).Value



    'chart lines ✓
    Chart1.Series.Clear()
    Chart1.Titles.Clear()
    Dim serS As New Series
    Dim serI As New Series
    Dim serR As New Series
    serS.Name = "S"
    serS.ChartType = SeriesChartType.Line
    serS.BorderWidth = 2
    serI.Name = "I"
    serI.ChartType = SeriesChartType.Line
    serI.BorderWidth = 2
    serR.Name = "R"
    serR.ChartType = SeriesChartType.Line
    serR.BorderWidth = 2

    'chart calculations ✓
    For ind = 0 To 99
        serS.Points.AddXY(t, S)
        serI.Points.AddXY(t, I)
        serR.Points.AddXY(t, R)
        Dim ds = (-b * S * I) / N
        Dim Di = ((b * S * I) / N) - a * I
        Dim Dr = a * I
        Dim dt = 1
        S = S + ds * scale
        I = I + Di * scale
        R = R + Dr * scale
        t = t + dt * scale
    Next
    'chart properties ✓
    Chart1.Series.Add(serS)
    Chart1.Series.Add(serI)
    Chart1.Series.Add(serR)
    Chart1.ChartAreas("ChartArea1").AxisX.Title = "Days"
    Chart1.ChartAreas("ChartArea1").AxisY.Title = "Population"
    Chart1.ChartAreas("ChartArea1").AxisX.Interval = 10
    Chart1.ChartAreas("ChartArea1").AxisY.Interval = 500
    Chart1.Titles.Add("SIR Graph")
    Chart1.Location = New Point(280, 30)
    Chart1.Size = New Size(700, 400)

    ''trackbar colors which, remember, are only accessible via the array tbs
    'tblist(1).BackColor = Color.LightGray
    'tblist(2).BackColor = Color.Blue
    'tblist(3).BackColor = Color.Yellow
    'tblist(4).BackColor = Color.LightCoral
  End Sub
End Class`

Modelos SIR existentes: https://faradars.org/ev/sir-simulator/?lang=en

Código de modelos SIR: https://www.google.com/s/jamesmccaffrey.wordpress.com/2020/02/11/the-kermack-mckendrick-sir-disease-model-using-c/amp/https://github.com/henrifroese/infectious_disease_modelling/blob/master/part_two.ipynb

Pregunta hecha hace 3 años, 4 meses, 25 días - Por codervoyager


2 Respuestas:

  • El problema principal que veo en tu código es que no estás actualizando correctamente los valores de S, I, y R en cada iteración del loop donde se calculan los nuevos datos para el gráfico. Además, parece que estás utilizando la misma variable 't' para representar el tiempo en el eje X del gráfico.

    Aquí te dejo algunas correcciones que podrías hacer en tu código para intentar solucionar el problema:

    • En el método `ProccessGraph`, necesitas actualizar los valores de S, I, y R en cada iteración del loop. Al añadir los puntos al gráfico, debes utilizar un nuevo valor de tiempo en cada iteración.
    • También podrías considerar ajustar los intervalos en los ejes X e Y del gráfico para una mejor visualización.

    Aquí te dejo una versión corregida del método ProccessGraph con las sugerencias mencionadas:

    vb
    Sub ProccessGraph()
        Dim tblist(7) As TrackBar 'array of trackbars
        For tbar = 1 To 7
            tblist(tbar) = Me.Controls("Trackbar" & tbar)
            Me.Controls("label" & tbar).Text = tblist(tbar).Value 'adds value to label
        Next
    
        Dim N = tblist(1).Value
        Dim S = tblist(2).Value
        Dim I = tblist(3).Value
        Dim R = tblist(4).Value
        Dim t = tblist(5).Value
    
        Dim b = tblist(6).Value
        Dim a As Double = tblist(7).Value
        Dim scale As Double = 0.1
    
        'chart lines
        Chart1.Series.Clear()
        Chart1.Titles.Clear()
        Dim serS As New Series
        Dim serI As New Series
        Dim serR As New Series
        serS.Name = "S"
        serS.ChartType = SeriesChartType.Line
        serS.BorderWidth = 2
        serI.Name = "I"
        serI.ChartType = SeriesChartType.Line
        serI.BorderWidth = 2
        serR.Name = "R"
        serR.ChartType = SeriesChartType.Line
        serR.BorderWidth = 2
    
        'chart calculations
        For ind = 0 To 99
            serS.Points.AddXY(t, S)
            serI.Points.AddXY(t, I)
            serR.Points.AddXY(t, R)
    
            Dim ds = (-b  S  I) / N
            Dim Di = ((b  S  I) / N) - a  I
            Dim Dr = a  I
            Dim dt = 1
    
            S += ds  scale
            I += Di  scale
            R += Dr  scale
            t += dt  scale
        Next
    
        'chart properties
        Chart1.Series.Add(serS)
        Chart1.Series.Add(serI)
        Chart1.Series.Add(serR)
        Chart1.ChartAreas("ChartArea1").AxisX.Title = "Days"
        Chart1.ChartAreas("ChartArea1").AxisY.Title = "Population"
        Chart1.ChartAreas("ChartArea1").AxisX.Interval = 10
        Chart1.ChartAreas("ChartArea1").AxisY.Interval = 500
        Chart1.Titles.Add("SIR Graph")
        Chart1.Location = New Point(280, 30)
        Chart1.Size = New Size(700, 400)
    End Sub
    

    Espero que estas correcciones te ayuden a resolver los problemas que estás experimentando con tu gráfico del modelo SIR en VB. ¡Déjame saber si necesitas más ayuda!

    Respondida el Dec 21, 2020 a las 22:49 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • He revisado tu código y he identificado algunos problemas que pueden estar causando los errores que mencionas:

    Error de desbordamiento:

    En la línea: Dim dr = a </strong> I, estás multiplicando a por I, que son ambos valores de tipo Decimal. Esto puede dar lugar a valores muy grandes y provocar un error de desbordamiento.

    Gráfico que no se desplaza hacia la izquierda:

    Cuando ajustas N, S o I, los valores de ds, di y dr en el bucle For se calculan utilizando los valores actuales de S, I y R. Esto significa que el gráfico no se desplazará hacia la izquierda, ya que los valores iniciales no se utilizan en los cálculos posteriores.

    Gráfico que no responde a cambios en b:

    En el bucle For, estás calculando ds, di y dr utilizando valores constantes para b y a. Para que el gráfico responda a los cambios en b, debes utilizar el valor actualizado de b en los cálculos.

    Aquí tienes un código corregido:

    vb
    Imports System.Windows.Forms.DataVisualization.Charting
    
    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            ' Initial values
            Dim N As Double = 10000
            Dim S As Double = 8000
            Dim R = 0.0
            Dim I As Double = N - S - R
    
            Dim t As Double = 0
            Dim b As Double = 2 ' Infection rate
            Dim a As Double = 0.5 ' Removal rate
            Dim scale As Double = 0.1
    
            setupForm(N, S, I, R, t, b, a, scale)
            ProccessGraph()
        End Sub
    
        Sub setupForm(N, S, I, R, t, b, a, scale)
    
            ' Trackbars
            Dim tbData(7) As Decimal
            tbData(1) = N ' Population N
            tbData(2) = S ' Susceptibles S
            tbData(3) = I ' Infectives I
            tbData(4) = R ' Recoveries R
            tbData(5) = t ' Time t
            tbData(6) = b ' Infection rate b
            tbData(7) = a ' Removal rate a
            Dim y As Integer = 10
            For I = 1 To 7
                Dim Tbar As New TrackBar
                With Tbar
                    .Location = New Point(20, y)
                    .Size = New Size(140, 30)
                    .BackColor = Color.White
                    .Minimum = 0
                    .Maximum = 10000
                    .SmallChange = 1
                    .Name = "Trackbar" & I
                    .Value = tbData(I)
                End With
                Me.Controls.Add(Tbar)
    
                ' Labels (display value)
                Dim labvalue As New Label
                With labvalue
                    .Location = New Point(180, y)
                    .Name = "label" & I
                    .Size = New Size(50, 15)
                End With
                Me.Controls.Add(labvalue)
    
                ' Labels (tbar title)
                Dim labtitle_data(7) As String
                labtitle_data(1) = "Population N"
                labtitle_data(2) = "Susceptibles S"
                labtitle_data(3) = "Infectives I"
                labtitle_data(4) = "Recoveries R"
                labtitle_data(5) = "Time"
                labtitle_data(6) = "Infection rate"
                labtitle_data(7) = "Removal rate"
                Dim labtitle As New Label
                With labtitle
                    .Location = New Point(240, y)
                    .Name = "label" & I
                    .Size = New Size(60, 60)
                    .Text = labtitle_data(I)
                End With
                y += 60
                Me.Controls.Add(labtitle)
    
                ' ComboBox (to list countries)
                Dim cb1 As New ComboBox
                cb1.Items.Add("China")
                cb1.Location = New Point(990, 50)
                Me.Controls.Add(cb1)
    
                ' Form properties
                Me.Size = New Size(1200, 500)
                Me.BackColor = Color.White
    
                AddHandler Tbar.ValueChanged, AddressOf ProccessGraph ' Every time the value changes, recreate the graph to match it
            Next
        End Sub
    
        Sub ProccessGraph()
            Dim tblist(7) As TrackBar ' Array of trackbars
            For tbar = 1 To 7
                tblist(tbar) = Me.Controls("TrackBar" & tbar)
                Me.Controls("label" & tbar).Text = tblist(tbar).Value ' Adds value to label
            Next
    
            ' Reset NSIR values to match trackbar values
            Dim N = tblist(1).Value
            Dim S = tblist(2).Value
            Dim I = tblist(3).Value
            Dim R = tblist(4).Value
            Dim t = tblist(5).Value
    
            Dim b = tblist(6).Value
            Dim a = tblist(7).Value
            Dim scale As Double = 0.1
    
            ' Chart lines
            Chart1.Series.Clear()
            Chart1.Titles.Clear()
            Dim serS As New Series
            Dim serI As New Series
            Dim serR As New Series
            serS.Name = "S"
            serS.ChartType = SeriesChartType.Line
            serS.BorderWidth = 2
            serI.Name = "I"
            serI.ChartType = SeriesChartType.Line
            serI.BorderWidth = 2
            serR.Name = "R"
            serR.ChartType = SeriesChartType.Line
            serR.BorderWidth = 2
    
            ' Chart calculations
            For ind = 0 To 99
                serS.Points.AddXY(t, S)
                serI.Points.AddXY(t, I)
                serR.Points.AddXY(t, R)
                Dim ds As Double = (-b  S  I) / N
                Dim di As Double = ((b  S  I) / N) - (a  I)
                Dim dr As Double = a  I
                Dim dt As Double = 1
                S += ds  scale
                I += di  scale
                R += dr  scale
                t += dt  scale
            Next
    
            ' Chart properties
            Chart1.Series.Add(serS)
            Chart1.Series.Add(serI)
            Chart1.Series.Add(serR)
            Chart1.ChartAreas("ChartArea1").AxisX.Title = "Days"
            Chart1.ChartAreas("ChartArea1").AxisY.Title = "Population"
            Chart1.ChartAreas("ChartArea1").AxisX.Interval = 10
            Chart1.ChartAreas("ChartArea1").AxisY.Interval = 500
            Chart1.Titles.Add("SIR Graph")
            Chart1.Location = New Point(280, 30)
            Chart1.Size = New Size(700, 400)
    
            '' Trackbar colors which, remember, are only accessible via the array tbs
            'tblist(1).BackColor = Color.LightGray
            'tblist(2).BackColor = Color.Blue
            'tblist(3).BackColor = Color.Yellow
            'tblist(4).BackColor = Color.LightCoral
        End Sub
    End Class
    

    Diferencias clave:

    He cambiado Dim dr = a </strong> I a Dim dr As Double = a <strong> I para convertir el resultado a Double y evitar el desbordamiento. En el bucle For, estoy utilizando los valores actualizados de S, I y R en los cálculos de ds, di y dr.

    • Estoy utilizando el valor actualizado de `b` en los cálculos de `ds` y `di`.

    Espero que este código corregido te ayude a resolver los problemas que estabas teniendo. Déjame saber si tienes alguna otra pregunta.

    Respondida el Dec 21, 2020 a las 22:49 - por Gemini

    Votos positivos: 0 | Votos negativos: 0