# Vytvorenie rovnomerne rozložených hodnôt pre os x (od -2 po 2, spolu 100 bodov)
x_grid <- seq(-2, 2, length.out = 100)
# Vytvorenie rovnomerne rozložených hodnôt pre os y (od -2 po 2, spolu 100 bodov)
y_grid <- seq(-2, 2, length.out = 100)
# Vypočítanie hodnôt funkcie z = exp(-x^2 - y^2) pre každý pár (x, y) z gridu
# Výsledkom je matica z hodnôt pre 3D zobrazenie povrchu funkcie
z_surface <- outer(x_grid, y_grid, function(x, y) exp(-x^2 - y^2))
# Vytvorenie hodnôt pre rez funkcie pozdĺž osi x (rovnaký rozsah a počet bodov)
x_cut <- seq(-2, 2, length.out = 100)
# Pevne daná hodnota y = 0 pre účely rezu
y_fixed <- 0
# Vypočítanie hodnoty funkcie z = exp(-x^2 - y^2) pozdĺž rezu pri y = 0
# Výsledkom je jednorozmerné pole hodnôt funkcie pre daný rez
z_cut <- exp(-x_cut^2 - y_fixed^2)Objem pod povrchom funkcie dvoch premenných
1 Úvod
Výpočet objemu pod funkciou je klasický problém matematickej analýzy a numerickej matematiky, ktorý má široké uplatnenie v oblasti fyziky, ekonómie či technických vied. V tomto projekte sa zameriame na výpočet objemu pod funkciou dvoch premenných pomocou dvojitého integrálu. Ako konkrétny príklad zvolíme funkciu
\[ f(x, y) = e^{-x^2 - y^2} \]
ktorá opisuje hladký 3D povrch podobný zvonu, a vypočítame objem pod touto funkciou nad danou oblasťou v rovine xy.
2 Teoretické pozadie
Objem pod funkciou \(f(x,y)\) nad oblasťou \(D \subset \mathbb{R}^2\)
je daný pomocou dvojitého integrálu:
\[ V = \iint_D f(x, y)\, dx\, dy \]
Funkcia \(f(x, y) = e^{-x^2 - y^2}\) je hladká. Zvolíme oblasť \(D = [-2, 2] \times [-2, 2]\), ktorá zahŕňa väčšinu hmotnosti tejto funkcie. Zvolená funkcia \(f(x, y) = e^{-x^2 - y^2}\) má tvar tzv. Gaussovej krivky v 2D, ktorá sa často využíva v štatistike a fyzike. Jej objem nad celou rovinou je známy analyticky:
\[ \iint_{\mathbb{R}^2} e^{-x^2 - y^2} \, dx \, dy = \pi \]
3 Numerický výpočet v R
3.1 Definovanie funkcie a oblasti
3.2 Výpočet objemu
# Načítanie knižnice `cubature`, ktorá umožňuje viacrozmernú numerickú integráciu
library(cubature)
# Definujeme funkciu f(x, y) = exp(-x^2 - y^2)
# `xy` je vektor s dvoma prvkami: xy[1] = x, xy[2] = y
f <- function(xy) {
x <- xy[1] # prvý prvok vektora: x
y <- xy[2] # druhý prvok vektora: y
exp(-x^2 - y^2) # hodnota funkcie f(x, y)
}
# Vykonáme numerickú integráciu funkcie f nad štvorcovou oblasťou [-2, 2] x [-2, 2]
result <- adaptIntegrate(
f, # funkcia na integráciu
lowerLimit = c(-2, -2), # dolná hranica premennej x a y
upperLimit = c(2, 2) # horná hranica premennej x a y
)3.3 Porovnanie presnosti výpočtu
Vypočítaný objem pod funkciou \(e^{-x^2 - y^2}\) na oblasti \([-2, 2] \times [-2, 2]\) je približne:
result$integral[1] 3.112271
3.4 Výsledok numerickej integrácie
Absolútna chyba voči skutočnej hodnote \(\pi\) je teda približne:
real_value <- pi
abs_error <- abs(real_value - result$integral)
abs_error[1] 0.0293217
, čo svedčí o vysokej presnosti použitej numerickej metódy
4 Vizualizácia povrchu
library(tidyverse) # Načítanie balíka tidyverse (obsahuje ggplot2, dplyr, atď.)
library(plotly) # Načítanie balíka plotly pre interaktívne 3D grafy
# Definujeme vlastnú farebnú škálu – štýl „morských“ odtieňov modrej
sea_colorscale <- list(
c(0.0, "#001f3f"), # veľmi tmavomodrá – najnižšia hodnota
c(0.2, "#0074D9"), # sýta modrá
c(0.4, "#00B8D9"), # tyrkysová
c(0.6, "#7FDBFF"), # svetlá azúrová
c(0.8, "#B2FFFF"), # veľmi svetlá modrá
c(1.0, "#E0FFFF") # takmer biela – najvyššia hodnota
)
# Vytvorenie 3D povrchovej vizualizácie funkcie
viz1 <- plot_ly(
x = ~x_grid, # použitie definovanú premennú x_grid
y = ~y_grid, # použitie definovanú premennú y_grid
z = ~z_surface, # použitie maticu z_surface
type = "surface", # typ grafu: 3D povrch
colorscale = sea_colorscale, # použitie definovanej farebnej škály
opacity = 0.95 # mierna priehľadnosť
) %>%
layout(
title = "3D vizualizácia povrchu funkcie, pod ktorou počítame objem", # názov grafu
scene = list(
xaxis = list(title = "x"), # popis osi x
yaxis = list(title = "y"), # popis osi y
zaxis = list(title = "z") # popis osi z
)
)source("saveplotlypng.R")
if (knitr::is_latex_output()) {
save_plotly_png(viz1, "viz1.png")
} else {
viz1
}# Vytvorenie vektora hodnôt pre x – 100 rovnomerne rozložených bodov v intervale od -2 do 2
x <- x_cut
# Zafixujeme hodnotu y na 0, aby sme mohli spraviť rez funkcie v tejto rovine
y <- y_fixed
# Vypočítame hodnoty funkcie f(x, y) = exp(-x^2 - y^2) pre y = 0
# Keďže y = 0, výraz sa zjednoduší na f(x, 0) = exp(-x^2)
z <- z_cut
# Vykreslenie 2D grafu: funkcie f(x, 0) voči x
plot(
x, z, # súradnice bodov (x a z)
type = "l", # typ grafu: spojnicový ("line")
col = "#0074D9", # farba čiary – sýta modrá
main = "Rez funkcie v rovine y = 0", # hlavný nadpis grafu
xlab = "x", # popis osi x
ylab = "f(x, 0)", # popis osi y (hodnoty funkcie)
font.main = 1 # štýl písma nadpisu: 1 = normálne písmo
)library(plotly) # Načítame knižnicu plotly pre interaktívne vizualizácie
# Definujeme mriežku hodnôt x a y na intervale [-2, 2]
x <- x_grid
y <- y_grid
# Vypočítame hodnoty funkcie z = e^(-x² - y²) pre každý bod mriežky
z <- z_surface
# Definujeme vlastnú farebnú škálu
sea_colorscale <- list(
c(0.0, "#001f3f"),
c(0.2, "#0074D9"),
c(0.4, "#00B8D9"),
c(0.6, "#7FDBFF"),
c(0.8, "#B2FFFF"),
c(1.0, "#E0FFFF")
)
# Vytvorenie 3D povrchovej grafiky s nastaveniami vizualizácie
viz2 <- plot_ly(
x = ~x, y = ~y, z = ~z, # definujeme osy a výšky (z)
type = "surface", # typ grafu: povrch
opacity = 0.88, # mierna priehľadnosť povrchu
colorscale = sea_colorscale, # použijeme našu vlastnú farebnú škálu
showscale = TRUE, # zobrazíme farebnú legendu
# Vrstevnice (kontúry) pre os z
contours = list(
z = list(
show = TRUE, # zobrazíme vrstevnice
start = 0.1, # počiatočná hodnota vrstevníc
end = 1, # koncová hodnota
size = 0.05, # krok medzi vrstevnicami
color = "#004d80", # farba vrstevníc
highlightcolor = "#00FFFF",# zvýraznenie pri prechode myšou
width = 2, # hrúbka čiar
project = list(z = TRUE) # projekcia vrstevníc na povrch
)
),
# Nastavenie osvetlenia povrchu pre lepší 3D efekt
lighting = list(
ambient = 0.6, # základné osvetlenie (globálne rozptýlené)
diffuse = 0.7, # rozptýlené svetlo (mäkké tiene)
specular = 0.5, # lesk na povrchu
roughness = 0.4, # drsnosť povrchu
fresnel = 0.2 # efekt okrajového odrazu
),
# Poloha svetelného zdroja v priestore
lightposition = list(
x = 100,
y = 200,
z = 0
)
) %>%
layout(
title = "3D vizualizácia funkcie s vrstevnicami", # názov grafu
scene = list(
xaxis = list(title = "x", gridcolor = "white"), # os x
yaxis = list(title = "y", gridcolor = "white"), # os y
zaxis = list(title = "f(x, y)", gridcolor = "lightblue"), # os z (výšky)
# Uhol pohľadu kamery pre lepšiu vizualizáciu 3D tvaru
camera = list(
eye = list(x = 1.3, y = 1.3, z = 1.2)
)
)
)source("saveplotlypng.R")
if (knitr::is_latex_output()) {
save_plotly_png(viz2, "viz2.png")
} else {
viz2
}5 Záver
Pomocou numerickej integrácie sme určili objem pod hladkou funkciou \(e^{-x^2 - y^2}\) nad štvorcovou oblasťou \([-2, 2] \times [-2, 2]\). Výsledný objem je reálne číslo s obmedzenou presnosťou, ktoré sa zhoduje s teoretickým očakávaním pre Gaussovu funkciu. Teoretická hodnota objemu pod touto funkciou nad celou rovinou \(\mathbb{R}^2\) je známa a rovná sa (Stewart 2015):
\[\iint_{\mathbb{R}^2} e^{-x^2 - y^2} \, dx \, dy = \pi\]
Keďže nami zvolená oblasť integrácie zachytáva len časť tejto funkcie, očakávame, že výsledok bude blízky hodnote \({\pi}\) = 3,14159…, ale o niečo menší. Výsledok ukazuje, že aj jednoduchá numerická integrácia môže dať veľmi dobrý odhad objemu pod funkciou, pokiaľ je oblasť správne zvolená. Rozdiel oproti analytickej hodnote \({\pi}\) je približne 0.03, čo je prijateľné pri danej presnosti. Tento prístup je veľmi dobre aplikovateľný na výpočty objemov v reálnych úlohách technického či prírodovedného charakteru, kde nie je možné analyticky vyrátať objem alebo kde je oblasť definovaná numericky, empiricky či inak zložito. V takých prípadoch sa numerická integrácia stáva neoceniteľným nástrojom, ktorý umožňuje získať dostatočne presné výsledky aj bez úplnej znalosti analytického riešenia.