5. Diferenciální rovnice 2#
5.1. Exponenciální růst#
Namodelujeme exponenciální růst
Nejprve růst pro tři různé hodnoty koeficientu \(k\). Vidíme, že čím vyšší je \(k\), tím rychleji velikost populace roste v čase.
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.integrate import solve_ivp
### Příprava funkcí a parametrů
pocatecni_podminka = np.array([0.1])  # počáteční podmínka
meze = np.array([0,10]) # interval, na kterém hledáme řešení
parametry = [1,1.5,2] # seznam parametrů
n = 100
def rovnice(t, x, k=1):
    return k*x
### Řešení modelu
t=np.linspace(*meze, n)  # definiční obor, v těchto bodech budeme hledat řešení
df = pd.DataFrame()      # tabulka pro výstup
df.index = t              # sloupec s časem
for parametr in parametry:
    reseni = solve_ivp(
                       lambda t,x:rovnice(t,x,k=parametr),
                       meze,
                       pocatecni_podminka,
                       t_eval=t
                       )
    df[parametr] = reseni.y.T # další sloupec tabulky
    # lambda funkce viz https://www.w3schools.com/python/python_lambda.asp
    # (dočasná nepojmenovaná funkce)
df
| 1.0 | 1.5 | 2.0 | |
|---|---|---|---|
| 0.00000 | 0.100000 | 0.100000 | 1.000000e-01 | 
| 0.10101 | 0.110629 | 0.116360 | 1.223884e-01 | 
| 0.20202 | 0.122390 | 0.135402 | 1.497941e-01 | 
| 0.30303 | 0.135402 | 0.157551 | 1.833156e-01 | 
| 0.40404 | 0.149792 | 0.183314 | 2.243435e-01 | 
| ... | ... | ... | ... | 
| 9.59596 | 1469.825225 | 178046.326900 | 2.159632e+07 | 
| 9.69697 | 1626.028660 | 207190.044520 | 2.643182e+07 | 
| 9.79798 | 1798.852275 | 241143.463018 | 3.234832e+07 | 
| 9.89899 | 1990.068781 | 280661.211823 | 3.958971e+07 | 
| 10.00000 | 2201.608767 | 326591.822323 | 4.845406e+07 | 
100 rows × 3 columns
### Vizualizace řešení
ax = df.plot()
ax.set(
    ylim = (0,1000),
    title = "Model exponenciálního růstu",
    xlabel="čas",
    ylabel="velikost populace",
)
plt.legend(title="Hodnoty parametru")
<matplotlib.legend.Legend at 0x7fd083316210>
5.1.1. Volitelná část#
Po transformaci do bezrozměrného času by měly křivky splynout. Abychom to viděli graficky, budeme postupně snižovat jejich tloušťku a nastavíme částečnou průhlednost. To zajistíme volbami lw (zkratka za linewidth) a alpha.
for k,lw in zip(parametry,[8,5,2]):
    plt.plot(t*k,df[k],lw=lw,label=k,alpha=0.5)  # Na vodorovne ose neni cas ale bezrozmerny cas
ax = plt.gca()
ax.set(
    ylim=(0,100),
    xlim=(0,10),
    xlabel="bezrozměrný čas",
    ylabel="velikost populace",
    title="Růst rychlostí úměrnou velikosti v bezrozměrném čase"
)
plt.legend(title=r"Hodnota $k$");
Poznámka: Provnávání grafů je poměrně primitivní metoda. Lepší a jednoznačnější by bylo vypočítat hodnoty v časech, které si odpovídají a poté ukázat, že rozdíl je blízký nule.
5.2. Exponenciální růst k vodorovné asymptotě#
5.2.1. Úkol#
Nakreslete řešení rovnice růstu k vodorovné asymptotě (von Bertalanffyho růst)
Po splnění modifikujte kód některým z následujících způsobů. Můžete využít umělou inteligenci. Například zápisníky na Anaconda cloud
Legendu upravte tak, aby obsahovala Vámi zadaný nadpis a popisky křivek nebyla čísla, ale řetězce „k=x“, kde x je příslušná hodnota parametru.
Upravte rozsah tak, aby svislá osa začínala na nule.
Upravte graf tak, aby kreslil křivky pro různé hodnoty \(M\).
# Sem vložte řešení.
5.3. Logistický růst - pro případné samostatně pracující studenty#
5.3.1. Úkol#
Vykreslete řešení logistické rovnice
# Sem vložte řešení. Můžete jej rozdělit do více buněk, které si sem vložíte.
5.3.2. Logistická rovnice v bezrozměrném tvaru#
Nyní si ukážeme, že v určitém smyslu stačí bez újmy na obecnosti studovat případ \(K=1\) a \(r=1\). Na rovnici
pocatecni_podminka = np.array([0.1])
meze = np.array([0,10])
def rovnice(t, x, r=1, K=1):
    return r*x*(1-x/K)
# r a K budou náhodná čísla z intervalu (0,0.2) a (0,10).
K,r = np.array([10,0.2])*np.random.random(2)
print(f"r={r}, K={K}")
t = np.linspace(*meze,12)
reseni_plne_rovnice = solve_ivp(
                   lambda t,x:rovnice(t,x,r=r,K=K),
                   meze,
                   pocatecni_podminka,
                   t_eval=t
                   )
reseni_bezrozmerne_rovnice = solve_ivp(
                   rovnice,
                   r*meze,  # převod mezí na bezrozměrný čas
                   pocatecni_podminka/K,  # převod na bezrozměrnou velikost populace
                   t_eval=r*t # vyhodnoceni v bezrozmernem case
                   )
df = pd.DataFrame()
df.index = t
df["plnohodnotna"] = reseni_plne_rovnice.y[0]
df["bezrozmerna"] = K*reseni_bezrozmerne_rovnice.y[0] 
df["rozdil"] = np.abs(df["bezrozmerna"]-df["plnohodnotna"])
df["relativni rozdil"] = df["rozdil"]/df["plnohodnotna"]
df
r=0.10612541193672467, K=5.618979185026616
| plnohodnotna | bezrozmerna | rozdil | relativni rozdil | |
|---|---|---|---|---|
| 0.000000 | 0.100000 | 0.100000 | 1.387779e-17 | 1.387779e-16 | 
| 0.909091 | 0.109930 | 0.109930 | 2.362970e-09 | 2.149516e-08 | 
| 1.818182 | 0.120825 | 0.120825 | 3.746308e-07 | 3.100601e-06 | 
| 2.727273 | 0.132774 | 0.132772 | 1.470421e-06 | 1.107465e-05 | 
| 3.636364 | 0.145871 | 0.145869 | 2.649101e-06 | 1.816052e-05 | 
| 4.545455 | 0.160224 | 0.160220 | 3.430802e-06 | 2.141259e-05 | 
| 5.454545 | 0.175943 | 0.175940 | 3.528070e-06 | 2.005233e-05 | 
| 6.363636 | 0.193152 | 0.193149 | 2.845859e-06 | 1.473381e-05 | 
| 7.272727 | 0.211979 | 0.211977 | 1.481540e-06 | 6.989091e-06 | 
| 8.181818 | 0.232564 | 0.232564 | 2.751049e-07 | 1.182922e-06 | 
| 9.090909 | 0.255053 | 0.255055 | 1.941882e-06 | 7.613635e-06 | 
| 10.000000 | 0.279602 | 0.279605 | 2.844183e-06 | 1.017224e-05 | 
df.rozdil.max()
np.float64(3.5280696396855493e-06)
df["relativni rozdil"].max()
np.float64(2.14125932644692e-05)
np.isclose(df["bezrozmerna"],df["plnohodnotna"], rtol=0.0001).all()
np.True_