เนื่องจากในบทนี้ชุดคำสั่งของ caracas ยังไม่ลองรับการใช้งานสำหรับสมการเชิงอนุพันธ์โดยตรง ทำให้จำเป็นต้องใช้การคำนวณด้วยชุดคำสั่งของ SymPy โดยตรงจากภาษาไพธอน แต่ผู้เขียนจะใช้วิธีทำงานบนพื้นฐานของอาร์อยู่ เพื่อคงไว้ซึ่งชื่อของหนังสือคือ คณิตศาสตร์สำหรับนักเศรษฐศาสร์ด้วยอาร์
การที่นักเศรษฐศาสตร์ต้องศึกษาสมการเชิงอนุพันธ์ (Ordinary Differential Equations: ODEs) เป็นเรื่องที่ สำคัญมาก โดยเฉพาะในสายงานเศรษฐศาสตร์ที่เกี่ยวข้องกับ พลวัตของระบบ (dynamic systems) เช่น การเจริญเติบโตทางเศรษฐกิจ, พฤติกรรมการบริโภคในระยะเวลา, หรือแม้แต่การเงินระหว่างประเทศ
ทำไมนักเศรษฐศาสตร์ต้องศึกษาสมการเชิงอนุพันธ์?
เพื่อเข้าใจพลวัตของระบบเศรษฐกิจ เศรษฐกิจเป็นระบบที่เปลี่ยนแปลงตามเวลา เช่น GDP, เงินเฟ้อ, การลงทุน ฯลฯ สมการ ODE ช่วยอธิบายว่า “ตัวแปรหนึ่งเปลี่ยนแปลงตามเวลาอย่างไร” เช่น Solow growth model: การเปลี่ยนแปลงของทุน K \[ \frac{dK(t)}{dt} = sY(t) - \delta K(t)\]
ใช้สร้างแบบจำลองเศรษฐศาสตร์จุลภาคและมหภาค
Consumption models เช่น Ramsey–Cass–Koopmans model ใช้ ODE อธิบายการบริโภคระยะยาว
IS-LM dynamic model ใช้ ODE แสดงการปรับตัวของตลาดเงินและตลาดสินค้า
Overlapping Generation Model (OLG) อาศัย ODE เพื่อวิเคราะห์พฤติกรรมของรุ่นประชากรในอนาคต
ใช้ในเศรษฐศาสตร์การเงิน (Financial Economics)
การกำหนดราคาสินทรัพย์ (เช่น bond, stock)
Black-Scholes Equation เป็นสมการเชิงอนุพันธ์บางส่วน (PDE) ที่มีรากฐานจาก ODE
Interest Rate Models เช่น Vasicek model
เข้าใจพฤติกรรมสมดุลและเสถียรภาพ
ตัวอย่างสมการที่นักเศรษฐศาสตร์ควรรู้
Solow Model
\(\frac{dk}{dt} = sf(k) - \delta k\)
การเติบโตของทุนต่อหัว
Ramsey Model
\(\frac{dc}{dt} = \frac{1}{\theta}(f'(k) - \rho - \delta) \cdot c\)
พฤติกรรมบริโภคที่เหมาะสม
IS-LM dynamic
\(\frac{dY}{dt} = \alpha (C(Y) + I(r) + G - Y)\)
การปรับตัวของรายได้
Predator-Prey (ในเศรษฐกิจพลังงาน/สิ่งแวดล้อม)
\(\frac{dx}{dt} = ax - bxy\) ,\(\frac{dy}{dt} = -cy + dxy\)
ทรัพยากร vs การบริโภค
สมการเชิงอนุพันธ์ (Ordinary Differential Equation: ODE)
สมการเชิงอนุพันธ์ คือสมการที่เกี่ยวข้องกับฟังก์ชัน \(y(t)\) และอนุพันธ์ของมัน (เช่น \(\frac{dy}{dt}\) , \(\frac{d^2y}{dt^2}\) , ฯลฯ)
สมการที่มีลักษณะทั่วไป: \[F\left(t, y, \frac{dy}{dt}, \frac{d^2y}{dt^2}, \dots, \frac{d^n y}{dt^n}\right) = 0\] โดยที่ \(y = y(t)\) คือฟังก์ชันที่ไม่ทราบล่วงหน้า (unknown function) และ \(t\) คือตัวแปรอิสระ เช่นเวลา
ประเภทของสมการเชิงอนุพันธ์
ตามลำดับอนุพันธ์
อันดับหนึ่ง (First order): \[\frac{dy}{dt} = f(t, y)\]
อันดับสองขึ้นไป (Higher-order): \[\frac{d^2y}{dt^2} + p(t)\frac{dy}{dt} + q(t)y = g(t)\]
ตามลักษณะ
เชิงเส้น (Linear): ไม่มี \(y^2\) , \(y \cdot \frac{dy}{dt}\) , ฯลฯ
ไม่เชิงเส้น (Nonlinear): มีผลคูณหรือกำลังของ \(y\) และอนุพันธ์
การแก้สมการเชิงอนุพันธ์
เป้าหมายคือ: หา ฟังก์ชัน \(y(t)\) ที่เป็นคำตอบของสมการนั้น
ตัวอย่าง:
\[
\frac{dy}{dt} = 3y
\]
วิธีแก้:
แยกตัวแปร (Separation of Variables): \[\frac{1}{y} \, dy = 3 \, dt\]
อินทิเกรตทั้งสองข้าง: \[\ln|y| = 3t + C\]
ยกกำลัง: \[y = Ce^{3t}\]
คำตอบทั่วไป (General Solution): ฟังก์ชันที่ขึ้นกับค่าคงที่ \(C\)
คำตอบเฉพาะ (Particular Solution): เมื่อกำหนดเงื่อนไขเริ่มต้น เช่น \(y(0) = 2\) แล้วแทนหา \(C\)
การแก้สมการเชิงอนุพันธ์ด้วย caracas และ SymPy
แม้ caracas
จะไม่สามารถแก้ ODE ได้โดยตรงเหมือนใน SymPy (Python) แต่เราสามารถใช้ caracas
ร่วมกับ reticulate
เพื่อเรียก SymPy
มาใช้งานได้เต็มรูปแบบในอาร์
# 1. เรียกใช้านชุดคำสั่งที่จำเป็น
library (reticulate)
# 2. นำเข้า SymPy
sympy <- import ("sympy" )
สมมุติเราจะแก้สมการ
\[\frac{dy}{dt} = ky\] 3. นิยามตัวแปรและฟังก์ชัน
t <- sympy$ symbols ("t" )
k <- sympy$ Symbol ("k" )
y <- sympy$ Function ("y" )
สร้างสมการเชิงอนุพันธ์
ode <- sympy$ Eq (sympy$ diff (y (t), t), k * y (t))
ode
Eq(Derivative(y(t), t), k*y(t))
5. แก้สมการเชิงอนุพันธ์
sol <- sympy$ dsolve (ode)
sol
ปัญหา ผลลัพธ์ที่ออกอยู่ในรูปการคำนวณด้วยโปรแกรม แต่ก็ยังสามารถอ่านเข้าใจได้ แต่สำหรับการเขียนรายงานแล้ว จำเป็นต้องเปลี่ยนผลลัพธ์ให้อยู่ในรูปสมการที่สวยงาน จึงสร้างฟังก์ชัน latex_render()
ขึ้นมาเพื่อเปลี่ยนผลลัพธ์เป็นภาษา
latex_render <- function (sympy_expr, use_rhs = TRUE ) {
sympy <- import ("sympy" )
# ถ้าเป็น Eq ให้เลือก rhs หรือทั้งสมการ
if ("Eq" %in% class (sympy_expr) && use_rhs) {
latex_str <- sympy$ latex (sympy_expr$ rhs)
} else {
latex_str <- sympy$ latex (sympy_expr)
}
cat ("$$" , latex_str, "$$ \n " )
}
วิธีการใช้งาน จะต้อง กำหนด chuck code ในรูปแบบนี้
```{r}
#| results='asis'
latex_render (sol)
```
ผลลัพธ์ในรายจะออกมาเป็นสมการสวยงามแบบนี้
\[ y{\left(t \right)} = C_{1} e^{k t} \]
เพิ่มเติม: การกำหนดเงื่อนไขเริ่มต้น (Initial Conditions) เช่น กำหนดว่า \(y(0) = y_0\) สามารทำได้โดยใช้ฟังก์ชัน dic()
ช่วยดังนี้
# สร้าง initial condition: y(0) = y0
ics <- dict ()
ics[[y (0 L)]] <- sympy$ Symbol ("y0" )
ics
# แก้ ODE พร้อมเงื่อนไขเริ่มต้น
sol2 <- sympy$ dsolve (ode, ics = ics)
sol2
เราสามารถสร้างฟังก์ชัน สำหรับกำหนดเงื่อนไขได้ ดังนี้
make_ics <- function (ics_list, funcname = "y" , sympy = import ("sympy" )) {
ics_dict <- reticulate:: dict ()
for (name in names (ics_list)) {
# แยกชื่อ เช่น "y(0)" $\rightarrow$ 0
matches <- regmatches (name, regexec (paste0 (funcname, " \\ (([^)]+) \\ )" ), name))[[1 ]]
if (length (matches) != 2 ) {
stop ("Initial condition key format must be like: y(0), y(1), etc." )
}
t_val <- as.numeric (matches[2 ]) # เวลา เช่น 0
f_t <- sympy$ Function (funcname)
ics_dict[[f_t (t_val)]] <- sympy$ Symbol (ics_list[[name]])
}
return (ics_dict)
}
วิธีการใช้งาน
ics <- make_ics (list ("y(0)" = "y0" ))
ics
จะแก้สมการเชิงอนุพันธ์พร้อมเงื่อนไข เริ่มต้นได้
# แก้ ODE พร้อมเงื่อนไขเริ่มต้น
sol2 <- sympy$ dsolve (ode, ics = ics)
sol2
การใช้ SymPy ด้วยอาร์มีความยุ่งยากเพิ่มขึ้นเล็กน้อย ดังนั้นในเนื้อหา ODE มีหมายถึงฟังก์ชัน ที่จะถูกใช้งานบ่อยๆ เราสามารถเปลี่ยนเป็นฟังก์ชัน ที่ช่วยให้เขียนได้สั้น และกระชับลงได้มาก ดังนี้
เยี่ยมมากครับ! ถ้าคุณต้องใช้ SymPy
ผ่าน reticulate
เพื่อแก้ สมการเชิงอนุพันธ์ (ODE) ใน R บ่อย ๆ — ผมแนะนำให้คุณสร้างฟังก์ชัน R ย่อ ๆ (wrapper functions) เพื่อ ลดความยุ่งยาก และเพิ่มความสะดวก
ฟังก์ชันที่ใช้บ่อยในการแก้ ODE ด้วย sympy
:
symbols()
– กำหนดตัวแปร
Function()
– สร้างฟังก์ชัน \(y(t)\)
diff()
– หาอนุพันธ์
Eq()
– นิยามสมการ
dsolve()
– แก้สมการเชิงอนุพันธ์
การสร้างฟังก์ชันในอาร์เพื่อใช้ SymPy แก้สมการเชิงอนุพันธ์
# โหลด SymPy
library (reticulate)
sympy <- import ("sympy" )
# กำหนด helper ฟังก์ชัน
# สร้างตัวแปร
syms <- sympy$ symbols
# สร้างฟังก์ชัน
func <- sympy$ Function
# หาอนุพันธ์
diff_ <- sympy$ diff
# สร้างสมการ
Eq <- sympy$ Eq
# แก้สมการเชิงอนุพันธ์
dsolve <- sympy$ dsolve
ตัวอย่างการใช้งาน:
ไม่มีเงื่อนไขเริ่มต้น:
t <- syms ("t" )
k <- syms ("k" )
y <- func ("y" )
ode <- Eq (diff_ (y (t),t), k* y (t))
ode
Eq(Derivative(y(t), t), k*y(t))
มีเงื่อนไขเริ่มต้น \(y(0) = y_0\) :
ics <- make_ics (list ("y(0)" = "y0" ))
dsolve (ode, ics = ics)
ตัวอย่างสมการเชิงอนุพันธ์ในทางเศรษฐศาสตร์
Consumption Growth Equation (Euler Equation)
\[\frac{dC}{dt} = \frac{1}{\theta}(r - \rho)C,~\theta,\rho,r>0\] มาจากทฤษฎี Ramsey–Cass–Koopmans Model
ใช้วิเคราะห์การเติบโตของการบริโภค \(c(t)\) ตามอัตราดอกเบี้ย \(r\) , ความชอบของผู้บริโภค \(\theta\) , และ discount rate \(\rho\)
จุดเด่น
\[
C(t) = C_1 e^{ \frac{(r - \rho)}{\theta} t }
\]
ใช้ SymPy ในการหาคำตอบ
# สร้างตัวแปร
t <- syms ("t" )
theta <- syms ("theta" , positive = TRUE )
r <- syms ("r" , positive = TRUE )
rho <- syms ("rho" , positive = TRUE )
# สร้างฟังก์ชัน
C <- func ("C" ) # ห้ามตั้งชื่อด้วย c เพราะจะไปตรงกับ c( ) ของ R
ode <- Eq (sympy$ diff (C (t), t), (r - rho) * C (t)/ theta)
ode
Eq(Derivative(C(t), t), (r - rho)*C(t)/theta)
จัดเป็นสมการให้สวยงาม
\[ \frac{d}{d t} C{\left(t \right)} = \frac{\left(r - \rho\right) C{\left(t \right)}}{\theta} \]
Eq(C(t), C1*exp(t*(r - rho)/theta))
มีเงื่อนไขเริ่มต้น \(C(0) = C_0\) :
ics <- make_ics (list ("C(0)" = "C0" ), funcname = "C" )
latex_render (dsolve (ode, ics = ics))
\[ C{\left(t \right)} = C_{0} e^{\frac{t \left(r - \rho\right)}{\theta}} \]
Solow Growth Equation (Capital Accumulation)
\[
\frac{dk}{dt} = s k^\alpha - \delta k
\]
จาก Solow-Swan Model ซึ่งอธิบายการเติบโตของทุนต่อหัวในระยะยาว
\(s\) คืออัตราการออม, \(\delta\) คืออัตราการเสื่อม, \(\alpha \in (0,1)\) คือผลผลิตส่วนเพิ่มของทุน
จุดเด่น:
ใช้ SymPy ในการหาคำตอบ
# สร้างตัวแปร
s <- syms ("s" , positive = TRUE )
delta <- syms ("delta" , positive = TRUE )
alpha <- syms ("alpha" , positive = TRUE )
# สร้างฟังก์ชัน
k <- func ("k" )
rhs <- s* k (t)^ alpha- delta* k (t)
ode <- Eq (sympy$ diff (k (t), t), rhs)
ode
Eq(Derivative(k(t), t), -delta*k(t) + s*k(t)**alpha)
จัดเป็นสมการให้สวยงาม
\[ \frac{d}{d t} k{\left(t \right)} = - \delta k{\left(t \right)} + s k^{\alpha}{\left(t \right)} \]
ถ้าไม่กำหนดค่า \(\alpha\) เท่ากับค่าเป็นตัวเลขในช่วง (0,1) จะไม่สามารถแก้สมการ ดังนั้น สมมุติให้ \(\alpha = 0.5\) จะได้
# แทนค่า theta = 0.5
ode_sub <- ode$ subs (alpha, 0.5 )
ode_sub
Eq(Derivative(k(t), t), -delta*k(t) + s*k(t)**0.5)
latex_render (dsolve (ode_sub))
\[ k{\left(t \right)} = e^{\delta \left(C_{1} - t\right)} + \frac{2 s e^{\frac{\delta \left(C_{1} - t\right)}{2}}}{\delta} + \frac{s^{2}}{\delta^{2}} \]
Price Adjustment Model (Adaptive Expectations)
\[\frac{dp}{dt} = \lambda (p^e - p)\]
คือ แบบจำลองการปรับตัวของราคา (Price Adjustment Model) ภายใต้ ความคาดหวังแบบปรับตัว (Adaptive Expectations) ซึ่งใช้กันอย่างแพร่หลายในเศรษฐศาสตร์มหภาค โดยเฉพาะในการอธิบายการปรับราคาหรือค่าจ้างเมื่อผู้ผลิตหรือแรงงานยังไม่ทราบราคาที่ดุลยภาพแน่ชัด
ความหมายของแต่ละสัญลักษณ์
\(p(t)\)
ราคาจริง (actual price) ณ เวลา \(t\)
\(p^e(t)\)
ราคาที่คาดการณ์ไว้ (expected price)
\(\lambda > 0\)
ความเร็วในการปรับราคา (speed of adjustment)
\(\frac{dp}{dt}\)
อัตราการเปลี่ยนแปลงของราคา
คำอธิบายแบบจำลอง:
ถ้า \(p^e > p\) : ผู้ผลิตคาดว่าราคาจะสูงกว่าราคาจริง \(\rightarrow\) ราคาจะปรับเพิ่มขึ้น
ถ้า \(p^e < p\) : ราคาจะปรับลดลง
ยิ่ง \(\lambda\) ใหญ่ \(\rightarrow\) ราคาปรับเร็ว
เมื่อ \(p \to p^e\) \(\rightarrow\) \(\frac{dp}{dt} \to 0\) \(\rightarrow\) ราคาคงที่
ถ้า \(p^e\) เป็น ค่าคงที่ \(\rightarrow\) เป็น ODE ที่มีคำตอบทั่วไป:
\[
p(t) = p^e + (p_0 - p^e) e^{-\lambda t}
\]
โดยที่ \(p_0 = p(0)\) คือราคาตั้งต้น
ใช้ SymPy ในการหาคำตอบ และกำหนด \(p^e\) คือค่าคงที่โดยใช้ \(p_e\) แทน
# สร้างตัวแปร
t <- syms ("t" )
lambda <- syms ("lambda_" , positive = TRUE )
pe <- syms ("p_e" , positive = TRUE )
# สร้างฟังก์ชัน
p <- func ("p" )
ode <- Eq (sympy$ diff (p (t), t), lambda* (pe- p (t)))
latex_render (ode)
\[ \frac{d}{d t} p{\left(t \right)} = \lambda_{} \left(p_{e} - p{\left(t \right)}\right) \]
แก้สมการ
latex_render (dsolve (ode))
\[ p{\left(t \right)} = C_{1} e^{- \lambda_{} t} + p_{e} \]
มีเงื่อนไขเริ่มต้น \(p(0) = p_0\) :
ics <- make_ics (list ("p(0)" = "p0" ), funcname = "p" )
latex_render (dsolve (ode, ics = ics))
\[ p{\left(t \right)} = p_{e} + \left(p_{0} - p_{e}\right) e^{- \lambda_{} t} \]
Exponential Capital Depreciation
\[
\frac{dK}{dt} = -\delta K
\] คือแบบจำลองการ เสื่อมราคาของทุน (Exponential Capital Depreciation Model)
โดยสมมติว่า ทุน (Capital stock) ลดลงต่อเนื่องตามอัตราส่วนคงที่ของปริมาณทุนเอง
คำอธิบายสัญลักษณ์
\(K(t)\)
ปริมาณทุน (capital stock) ณ เวลา \(t\)
\(\delta > 0\)
อัตราการเสื่อมราคา (depreciation rate)
\(\frac{dK}{dt}\)
อัตราการเปลี่ยนแปลงของทุนตามเวลา
ความหมายของสมการ
ใช้ SymPy ในการหาคำตอบ
# สร้างตัวแปร
t <- syms ("t" )
delta <- syms ("delta" , positive = TRUE )
# สร้างฟังก์ชัน
K <- func ("K" )
ode <- Eq (sympy$ diff (K (t), t), - delta* K (t))
latex_render (ode)
\[ \frac{d}{d t} K{\left(t \right)} = - \delta K{\left(t \right)} \]
แก้สมการ
latex_render (dsolve (ode))
\[ K{\left(t \right)} = C_{1} e^{- \delta t} \]
มีเงื่อนไขเริ่มต้น \(K(0) = K_0\) :
ics <- make_ics (list ("K(0)" = "K0" ), funcname = "K" )
latex_render (dsolve (ode, ics = ics))
\[ K{\left(t \right)} = K_{0} e^{- \delta t} \]
พฤติกรรม:
เมื่อ \(t \to \infty\) , \(K(t) \to 0\)
ยิ่ง \(\delta\) มาก \(\rightarrow\) ทุนลดเร็ว
ใช้ในโมเดลการเจริญเติบโต (Growth Models) เช่น Solow, Ramsey เพื่อคำนวณทุนสุทธิ:
\[
\frac{dK}{dt} = I(t) - \delta K(t)
\] โดย \(I(t)\) คือการลงทุน
แบบจำลองนี้แสดงให้เห็นว่าหากไม่มีการลงทุนเพิ่ม ทุนจะลดลงตามเวลาอย่างต่อเนื่อง
ใช้ได้ทั้งกับทุนกายภาพ (เครื่องจักร อาคาร) และทุนมนุษย์ (ในบางบริบท)
Solow Growth Model (simplified)
\[\frac{dk}{dt} = s k^\alpha - \delta k, s,\delta>0, ~\alpha\in (0,1)\] คือรูปแบบ Solow Growth Model แบบง่ายที่สุด (simplified) ภายใต้การเปลี่ยนแปลงของทุนต่อหัว (capital per worker) โดยไม่มีการเจริญเติบโตของประชากรหรือเทคโนโลยี
คำอธิบายของแต่ละพารามิเตอร์:
\(k(t)\)
ทุนต่อแรงงาน (capital per worker) ณ เวลา \(t\)
\(\frac{dk}{dt}\)
อัตราการเปลี่ยนแปลงของทุนต่อแรงงาน
\(s\)
อัตราการออม (saving rate)
\(\delta\)
อัตราการเสื่อมราคา (depreciation rate)
\(\alpha \in (0,1)\)
ผลตอบแทนต่อขนาดของทุน (capital share) จากฟังก์ชัน Cobb-Douglas \(y = k^\alpha\)
ความหมายของสมการ:
แสดงการสะสมทุนในระบบเศรษฐกิจหนึ่ง ๆ
ทุนเพิ่มขึ้นจากการออม: \(s k^\alpha\)
ทุนลดลงจากการเสื่อม: \(\delta k\)
เป็นแบบจำลองพื้นฐานในเศรษฐศาสตร์การเจริญเติบโต
ใช้ SymPy ในการหาคำตอบ แต่ถ้ามีค่าของตัวแปรที่ไม่ทราบค่ามากเกินไปอาจจะไม่ได้คำตอบ หรือเกิดข้อผิดพลาดได้ กำหนดให้ \(\alpha =0.5\)
# ตัวแปร
s <- syms ("s" , positive = TRUE )
delta <- syms ("delta" , positive = TRUE )
t <- syms ("t" )
# ฟังก์ชัน
K <- func ("K" )
# สร้างสมการ
ode <- Eq (diff_ (K (t),t),s * K (t)^ 0.5 - delta * K (t))
latex_render (ode)
\[ \frac{d}{d t} K{\left(t \right)} = - \delta K{\left(t \right)} + s K^{0.5}{\left(t \right)} \]
แก้สมการ
latex_render (dsolve (ode))
\[ K{\left(t \right)} = e^{\delta \left(C_{1} - t\right)} + \frac{2 s e^{\frac{\delta \left(C_{1} - t\right)}{2}}}{\delta} + \frac{s^{2}}{\delta^{2}} \]
Andersen, M. M., & Højsgaard, S. (2023).
caracas: Computer Algebra .
https://github.com/r-cas/caracas
Berkelaar, M. (2024).
lpSolve: Interface to ’Lp_solve’ v. 5.5 to Solve Linear/Integer Programs .
https://doi.org/10.32614/CRAN.package.lpSolve
Meurer, A., Smith, C. P., Paprocki, M., Čertı́k, O., Kirpichev, S. B., Rocklin, M., Kumar, A., Ivanov, S., Moore, J. K., Singh, S., และคณะ. (2017). SymPy: symbolic computing in Python.
PeerJ Computer Science ,
3 , e103.
https://doi.org/10.7717/peerj-cs.103
Sievert, C. (2020).
Interactive Web-Based Data Visualization with R, plotly, and shiny . Chapman; Hall/CRC.
https://plotly-r.com
Ushey, K., Allaire, J., & Tang, Y. (2025).
reticulate: Interface to ’Python’ .
https://doi.org/10.32614/CRAN.package.reticulate
Wickham, H. (2016).
ggplot2: Elegant Graphics for Data Analysis . Springer-Verlag New York.
https://ggplot2.tidyverse.org