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:
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 multiplicandoa
porI
, que son ambos valores de tipoDecimal
. 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
oI
, los valores deds
,di
ydr
en el bucleFor
se calculan utilizando los valores actuales deS
,I
yR
. 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 calculandods
,di
ydr
utilizando valores constantes parab
ya
. Para que el gráfico responda a los cambios enb
, debes utilizar el valor actualizado deb
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
aDim dr As Double = a <strong> I
para convertir el resultado aDouble
y evitar el desbordamiento. En el bucleFor
, estoy utilizando los valores actualizados deS
,I
yR
en los cálculos deds
,di
ydr
.- 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