s2Eva2022PAOII_T2 EDO - población de protestantes en una sociedad

Ejercicio: 2Eva2022PAOII_T2 EDO - población de protestantes en una sociedad

El sistema de ecuaciones para el ejercicio se expresa como:

\frac{\delta}{\delta t}x(t) = b x(t) - d (x(t))^2 \frac{\delta}{\delta t}y(t) = b y(t) - d (y(t))^2 +r b (x(t)-y(t))

literal a

Simplificando la nomenclatura, la población total del país se describe con:

x' = b x - d x^2

La población de protestantes se describe con;

y' = b y - d y^2 +r b (x-y)

Sustituyendo constantes, y considerando x(0)=1 ; y(0)=0.01 ; h=0.5 valores del enunciado:

x' = 0.02 x - 0.015 x^2 y' = 0.02 y - 0.015 y^2 +0.1(0.02) (x-y)

El planteamiento de Runge-Kutta se hace junto a la primera iteración, además de encontrarse en las instrucciones con Python.

literal b

Se describen 3 iteraciones usando los resultados de la tabla con el algoritmo, para mostrar la comprensión del algoritmo.

itixiyi
0010.01

t = 0 para iniciar las iteraciones, h=0.5

K1x = 0.5 \left(0.02 (1) - 0.015 (1)^2 \right) = 0.0025 K1y = 0.5\left(0.02 (0.01) - 0.015 (0.01)^2 +0.1(0.02) (1-0.01)\right) = 0.001089

.

K2x = 0.5 \left(0.02 (1+0.0025) - 0.015 (1+0.0025)^2 \right) = 0.00248 K2y = 0.5\Big(0.02 (0.01+0.00108) - 0.015 (0.01+0.00108)^2 + 0.1(0.02) ((1+0.0025)-(0.01+0.00108))\Big) = 0.001101

La población del país en la iteración se actualiza a:

x_1 = 1 + \frac{0.0025+0.00248}{2} = 1.0025

La población de protestantes en la iteración se actualiza a:

y_1 = 0.01 + \frac{0.001089+0.001101}{2} = 0.01109

t1 = 0 + 0.5 =0.5

Se actualiza la tabla con los valores obtenidos:

itixiyi
0010.01
10.51.00250.01109

t=0.5

K1x = 0.5 \left( 0.02 (1.0025) - 0.015 (1.0025)^2 \right)= 0.002487 K1y = 0.5\left( 0.02 (0.01109) - 0.015 (0.01109)^2 +0.1(0.02) (1.0025-0.01109)\right)= 0.001101

.

K2x = 0.5 \left(0.02 (1.0025+ 0.002487) - 0.015 (1.0025+ 0.002487)^2 \right) = 0.002474 K2y = 0.5 \Big( 0.02 (0.01109+0.001101) - 0.015(0.01109+0.001101)^2 + 0.1(0.02)((1.0025+ 0.002487)-(0.01109+0.001101))\Big) = 0.001113

.

x_2 = 1.0025 + \frac{0.002487+0.002474}{2} = 1.0050 y_2 = 0.01109 + \frac{0.001101+0.001113}{2} = 0.01220

t2 = 0.5 + 0.5 = 1

itixiyi
0010.01
10.51.00250.01109
211.00500.01220

t=1

K1x = 0.5 \left( 0.02 (1.0050) - 0.015 (1.0050)^2 \right)= 0.002474 K1y = 0.5 \left(0.02 (0.01220) - 0.015 (0.01220)^2 +0.1(0.02) (1.0050-0.01220) \right)= 0.001113

.

K2x = 0.5 \left(0.02 (1.0050+ 0.002474) - 0.015 (1.0050+ 0.002474)^2 \right) = 0.002462 K2y = 0.5 \Big(0.02 (0.01220+0.001113) - 0.015 (0.01220+0.001113)^2 + 0.1(0.02) ((1.0050+ 0.002474)-(0.01220+0.001113))\Big) = 0.001126

.

x_3 = 1.0050 + \frac{0.002474+0.002462}{2} = 1.0074 y_3 = 0.01220 + \frac{0.001113+0.001126}{2} = 0.01332

t3 = 1 + 0.5 = 1.5

itixiyi
0010.01
10.51.00250.01109
211.00500.01220
31.51.00740.01332

Resultado con el algoritmo

Para obtener los datos de las iteraciones, primero se ejecuta el algoritmo para pocas iteraciones.
Para la pregunta sobre 200 años, se incrementa las iteraciones a 2 por año y las condiciones iniciales, es decir 401 muestras.

 EDO f,g con Runge-Kutta 2 Orden
i  [ xi,  yi,  zi ]
   [ K1y,  K1z,  K2y,  K2z ]
0 [0.   1.   0.01]
  [0. 0. 0. 0.]
1 [0.5      1.002494 0.011095]
  [0.0025   0.001089 0.002487 0.001101]
2 [1.       1.004975 0.012203]
  [0.002487 0.001101 0.002475 0.001114]
3 [1.5      1.007444 0.013323]
  [0.002475 0.001114 0.002462 0.001126]
4 [2.       1.0099   0.014455]
  [0.002462 0.001126 0.00245  0.001138]
5 [2.5      1.012343 0.0156  ]
  [0.00245  0.001138 0.002437 0.001151]
6 [3.       1.014774 0.016757]
  [0.002437 0.001151 0.002424 0.001163]
7 [3.5      1.017192 0.017926]
  [0.002424 0.001163 0.002412 0.001176]
8 [4.       1.019597 0.019109]
  [0.002412 0.001176 0.002399 0.001189]
9 [4.5      1.02199  0.020304]
  [0.002399 0.001189 0.002386 0.001202]
10 [5.       1.02437  0.021512]
   [0.002386 0.001202 0.002374 0.001214]
...

Observación: La población identificada como protestante, continua creciendo, mientras que la proporción de "conformistas" se reduce según los parámetros indicados en el ejercicio. Los valores de natalidad y defunción cambian con el tiempo mucho más en años por otras variables, por lo que se deben realizar ajustes si se pretende extender el modelo.

2Eva2022PAOII_T2 población protestantes vs tiempo
2Eva2022PAOII_T2 población protestantes YZ

Algoritmo en Python

# Modelo predador-presa de Lotka-Volterra
# 2Eva2022PAOII_T2 EDO - población de protestantes en una sociedad
# Sistemas EDO con Runge Kutta de 2do Orden
import numpy as np
 
# INGRESO
# Parámetros de las ecuaciones
b = 0.02
d = 0.015
r = 0.1

# Ecuaciones
f = lambda t,x,y : (b-d*x)*x
g = lambda t,x,y : (b-d*y)*y + r*b*(x-y)

# Condiciones iniciales
t0 = 0
x0 = 1
y0 = 0.01

# parámetros del algoritmo
h = 0.5
muestras = 401
 
# Algoritmo como función
def rungekutta2_fg(f,g,x0,y0,z0,h,muestras,
                   vertabla=False, precision=6):
    ''' solucion a EDO d2y/dx2 con Runge-Kutta 2do Orden,
    f(x,y,z) = z #= y'
    g(x,y,z) = expresion d2y/dx2 con z=y'
    tambien es solucion a sistemas edo f() y g()
    x0,y0,z0 son valores iniciales, h es tamano de paso,
    muestras es la cantidad de puntos a calcular.
    '''
    tamano = muestras + 1
    tabla = np.zeros(shape=(tamano,3+4),dtype=float)
    # incluye el punto [x0,y0,z0,K1y,K1z,K2y,K2z]
    tabla[0] = [x0,y0,z0,0,0,0,0]
      
    xi = x0 # valores iniciales
    yi = y0
    zi = z0
    for i in range(1,tamano,1):
        K1y = h * f(xi,yi,zi)
        K1z = h * g(xi,yi,zi)
          
        K2y = h * f(xi+h, yi + K1y, zi + K1z)
        K2z = h * g(xi+h, yi + K1y, zi + K1z)
  
        yi = yi + (K1y+K2y)/2
        zi = zi + (K1z+K2z)/2
        xi = xi + h
          
        tabla[i] = [xi,yi,zi,K1y,K1z,K2y,K2z]
          
    if vertabla==True:
        np.set_printoptions(precision)
        print('EDO f,g con Runge-Kutta 2 Orden')
        print('i ','[ xi,  yi,  zi',']')
        print('   [ K1y,  K1z,  K2y,  K2z ]')
        for i in range(0,tamano,1):  
            txt = ' '
            if i>=10:
                txt = '  '
            print(str(i),tabla[i,0:3])
            print(txt,tabla[i,3:])
      
    return(tabla)
 
# PROCEDIMIENTO
tabla = rungekutta2_fg(f,g,t0,x0,y0,h,
                       muestras,vertabla=True)
# SALIDA
print('Sistemas EDO RK2')
##print('i ','[ xi,  yi,  zi',']')
##print('   [ K1y,  K1z,  K2y,  K2z ]')
##for i in range(0,tamano,1):  
##    txt = ' '
##    if i>=10:
##        txt = '  '
##    print(str(i),tabla[i,0:3])
##    print(txt,tabla[i,3:])

Instrucciones para la parte gráfica

# GRAFICA ---------------------
import matplotlib.pyplot as plt
  
titulo = 'Sistemas EDO Runge-Kutta 2ord - Protestantes'
etiq_x = 'x = tiempo'
etiq_y = 'y = población país'
etiq_z = 'z = protestantes'
i = muestras # iteración en gráfica
  
titulo = titulo+', i='+str(i)
xi = tabla[:,0]
yi = tabla[:,1]
zi = tabla[:,2]
K1y = tabla[:,3]
K1z = tabla[:,4]
K2y = tabla[:,5]
K2z = tabla[:,6]
  
plt.subplot(211)
plt.plot(xi[0],yi[0],'o',
         color='red', label ='[t0,y0]')
if i<20: # evita muchos puntos
    plt.plot(xi[1:i+2],yi[1:i+2],'o',
             color='green', label ='[t[i],y[i]]')
plt.plot(xi[0:i+2],yi[0:i+2],
         color='blue',label='y(t)')
if i<muestras: # gráfica para una iteración
    plt.plot(xi[i+1],yi[i+1],'o',color='orange',
             label ='[x[i+1],y[i+1]]')
    plt.plot(xi[i:i+3],yi[i:i+3],'.',color='gray')
    plt.plot(xi[i:i+2],[yi[i],yi[i]], color='orange',
             label='h',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]-0.02*h],
             [yi[i],yi[i]+K1y[i+1]],
             color='green',label='K1y',linestyle='dashed')
    plt.plot([xi[i+1]+0.02*h,xi[i+1]+0.02*h],
             [yi[i],yi[i]+K2y[i+1]],
             color='magenta',label='K2y',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]+0.02*h],
             [yi[i]+K1y[i+1],yi[i]+K2y[i+1]],
             color='magenta')
if np.min(yi[0:i+1])<0: # linea 0
    plt.axhline(0, color='red')
plt.ylabel(etiq_y)
plt.title(titulo)
plt.legend()
plt.grid()
plt.tight_layout()
  
plt.subplot(212)
plt.plot(xi[0],zi[0],'o',
         color='red', label ='[t0,z0]')
if i<20: # evita muchos puntos
    plt.plot(xi[1:i+2],zi[1:i+2],'o',
             color='green', label ='[t[i],v[i]]')
plt.plot(xi[0:i+2],zi[0:i+2],
         color='green',label='z(t)')
if i<muestras: # gráfica para una iteración
    plt.plot(xi[i+1],zi[i+1],'o',color='orange',
             label ='[t[i+1],z[i+1]]')
    plt.plot(xi[i:i+3],zi[i:i+3],'.',color='gray')
    plt.plot(xi[i:i+2],[zi[i],zi[i]], color='orange',
             label='h',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]-0.02*h],
             [zi[i],zi[i]+K1z[i+1]],
             color='green',label='K1z',linestyle='dashed')
    plt.plot([xi[i+1]+0.02*h,xi[i+1]+0.02*h],
             [zi[i],zi[i]+K2z[i+1]],
             color='magenta',label='K2z',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]+0.02*h],
             [zi[i]+K1z[i+1],zi[i]+K2z[i+1]],
             color='magenta')
  
plt.xlabel(etiq_x)
plt.ylabel(etiq_z)
plt.legend()
plt.grid()
plt.tight_layout()
  
#plt.show() #comentar para la siguiente gráfica
 
# gráfica yi vs zi
fig_yz, graf3 = plt.subplots()
graf3.plot(yi,zi)
  
graf3.set_title(titulo)
graf3.set_xlabel(etiq_y)
graf3.set_ylabel(etiq_z)
graf3.grid()
plt.show() #comentar para la siguiente gráfica

Ejemplos por año