library(caracas)
5 การหาค่าสูงสุด/ต่ำสุดภายใต้ข้อจำกัด (Constrained Optimization)
5.1 บทนำ
ในทางเศรษฐศาสตร์ นักเศรษฐศาสตร์มักต้องการหาค่า สูงสุด (maximize) หรือ ต่ำสุด (minimize) ของฟังก์ชัน เช่น:
ผู้บริโภค: ต้องการเพิ่มอรรถประโยชน์สูงสุด ภายใต้ข้อจำกัดงบประมาณ
ผู้ผลิต: ต้องการลดต้นทุนให้น้อยที่สุด ภายใต้ข้อจำกัดการผลิต
ปัญหานี้เรียกว่า Constrained Optimization
วิธีแก้ปัญหาหลักคือ Lagrange Multiplier Method หรือภาษาไทยเรียกว่า ตัวคูณลากรองช์
ก่อนที่จะกล่าวถึงหัวข้อตัวคูณลากรองซ์ ในบทที่ 2 ผู้อ่านได้เรียนรู้ถึงการประยุกต์อนุพันธ์ เพื่อหาค่าสูงสุด/ต่ำสุดของฟังก์ชันมาแล้ว ในบทนี้จะมีตัวแปรตั้งแต่ 2 ตัวขึ้นทำให้ ผู้อ่านต้องการเรื่องหาอนุพันธ์บางส่วนของฟังก์ชันก่อน
5.2 อนุพันธ์บางส่วน (Partial Derivative)
ตัวอย่าง
ให้
อนุพันธ์บางส่วนของ
5.3 เกรเดียนต์ (Gradient)
เกรเดียนต์ คือ เวกเตอร์ที่รวมอนุพันธ์บางส่วนทั้งหมดของฟังก์ชัน เข้าด้วยกัน
จากตัวอย่างที่ผ่านมา
คุณสมบัติสำคัญของเกรเดียนต์
คุณสมบัติ | อธิบาย |
---|---|
ทิศทาง | ชี้ไปในทิศทางที่ |
ความยาว (norm) | บอกอัตราความชัน หรือความเร็วของการเพิ่มขึ้น |
ถ้า |
จุดนั้นอาจเป็น maximum, minimum, หรือ saddle point (critical point) |
5.4 การคำนวณเชิงสัญลักษณ์ของอนุพันธ์บางส่วนด้วย caracas
- เรียกใช้ชุดคำสั่ง caracas
จากตัวอย่าง
- กำหนดตัวแปรและฟังก์ชันที่ต้องการ
<- symbol("x")
x <- symbol("y")
y <- x^2+x*y+y^2
f f
- หาอนุพันธ์บางส่วนด้วยฟังก์ชัน
der()
หา
der(f, x)
หา
der(f, y)
ส่วนคำนวณเกรเดียนต์ด้วย caracas ก็ยังใช้คำสั่ง der()
เช่นเดิม แต่เปลี่ยนกับใส่ตััวแปรให้อยู่ในของ list แทน และแสดงผลในรูปของเมตริกซ์ขนาด
der(f, list(x,y))
5.4.1 การสร้างตัวแปรเป็นจำนวนมากด้วย caracas
ในหลายๆปัญหาทางเศรษฐศาสตร์ นิยมสร้างตัวเป็นลำดับ (sequence) เช่น as_sym()
สามารถเปลี่ยนเวคเตอร์และเมตริกซ์ในอาร์ เป็นตัวแปรของ caracas ได้
# สร้างเวคเตอร์ p เก็บค่า p1 .. p5
<- paste0("p", 1:5)
p # เปลี่ยนเวคเตอร์เป็นตัวแปร caracas ด้วย as_sym()
<- as_sym(p)
p <- -sum(p*log(p))
entropy entropy
ทดลองหาค่าเกรเดียนต์
der(entropy, p)
5.5 การหาค่าสูงสุด/ต่ำสุดของฟังก์ชันและไม่มีข้อจำกัด (Unconstrained Optimization)
หัวข้อนี้ฟังก์ชันจะต้องมีตั้งแต่ 2 ตัวแปรขึ้นไปมีขั้นตอนการทำดังนี้
5.5.1 สรุปขั้นตอนการคำนวณ
ขั้นตอน | ทำอะไร | หมายเหตุ |
---|---|---|
1 | กำหนดปัญหา | maximize หรือ minimize ฟังก์ชันไหน |
2 | หา FOC | ตั้งอนุพันธ์ = 0 |
3 | แก้หา Critical Points | ได้ค่า |
4 | ตรวจสอบ SOC | ด้วย |
5 | สรุปผลลัพธ์ | ว่าเป็นจุดสูงสุด/ต่ำสุดหรือไม่ |
ทำตามขั้นตอน 1. หาอนุพันธ์หรือเกรเดียนต์
ตั้ง FOC:
แก้ระบบสมการ
ได้ตรวจ Hessian:
- สรุปผล เป็น minimum
กว่าจะได้คำตอบเหนื่อยจัง ถูกรึเปล่าก็ยังไม่รู้
5.5.2 การทำ 4 ขั้นตอนแรกด้วย caracas
- สร้างฟังก์ชัน
<- symbol("x")
x <- symbol("y")
y # สร้างฟังก์ชัน หาค่าต่ำสุดของ f
<- 3*x^2 + 2*x*y + y^2 - 4*x - 5*y
min_f min_f
- ตั้ง FOC: ด้วยการหาเกรเดียนต์ด้วย
der()
<- der(min_f, list(x,y))
Gmin_f Gmin_f
- แก้สมการหา Critical Points ด้วยคำสั่ง
solve_sys()
solve_sys(Gmin_f, list(x,y))
Solution 1:
x = -1/4
y = 11/4
- ตรวจสอบคำตอบด้วย Hessian Matrix ถ้าใช้ caracas มีฟังก์ชันชื่อ
hessian()
ช่วยหา
# หา hessian จากฟังก์ชันข้อ 1 โดยตั้งชื่อ hes.M
<-hessian(min_f, list(x, y))
hes.M hes.M
ค่า diagonal ทุกตัวมากกว่า 0
- หาค่า det เพื่อสรุปผล
det(hes.M)
ดีเทอมิแนนท์มีค่ามากกว่า 0 แสดงว่าเป็นจุดต่ำสุด
ที่จุด
subs(min_f, list(x = -1/4, y =11/4))
ลองวาดแผนภาพเส้นชั้นความสูง (contour plot) ด้วยอาร์ด้วย ggplot2
# เปลี่ยนฟังก์ชันจาก caracas เป็น ฟังก์ชันใน R ด้วย as_func()
<- as_func(min_f)
plot.f # โหลดแพ็กเกจที่จำเป็น
library(ggplot2)
# กำหนดช่วงของ x และ y
<- seq(-5, 5, length.out = 100)
x <- seq(-5, 7, length.out = 100)
y
# สร้างตารางค่าที่จะใช้วาด
<- expand.grid(x = x, y = y)
grid
# คำนวณค่าฟังก์ชัน f(x,y)
$z <- plot.f(grid$x,grid$y)
grid
# วาดกราฟ contour
ggplot(grid, aes(x = x, y = y, z = z)) +
geom_contour_filled() + # วาด contour แบบมีไล่สี
labs(title = "Contour Plot of f(x,y)",
x = "x",
y = "y",
fill = "f(x,y)") +
theme_classic(base_size = 14)+
theme(text = element_text(family = "TH Sarabun New", size = 16)) +
annotate(geom = "text",x = -1/4, y =11/4, label = "X", size =8)
ถ้าผู้อ่านสนใจการวาดกราฟด้วยอาร์สามารถศึกษาได้จาก การสร้างภาพนิทัศน์ด้วยภาษาอาร์
สำหรับผู้อ่านจาก HTML book จะเห็นกราฟแบบ interactive
# ติดตั้ง plotly ถ้ายังไม่มี
# install.packages("plotly")
library(plotly)
# สร้างข้อมูล
<- seq(-5, 7, length.out = 50)
x_seq <- seq(-5, 7, length.out = 50)
y_seq
<- outer(x_seq, y_seq, function(x, y) {
z_matrix 3*x^2 + 2*x*y + y^2 - 4*x - 5*y
})# วาด surface plot แบบ interactive
plot_ly(
x = ~x_seq, y = ~y_seq, z = ~z_matrix
|>
) add_surface() |>
layout(
title = "Surface Plot of f(x,y)",
scene = list(
xaxis = list(title = "X"),
yaxis = list(title = "Y"),
zaxis = list(title = "f(x,y)")
) )
5.5.3 ตัวอย่างการหาค่าสูงสุดต่ำสุดโดยไม่มีข้อจำกัดในทางเศรษฐศาสตร์เพิ่มเติม
โดยใช้การคำนวณเชิงสัญลักษณ์และวาดกราฟประกอบ
ทำ 4 ขั้นตอนแรกด้วย caracas
- สร้างฟังก์ชัน
<- symbol("x")
x <- symbol("y")
y # สร้างฟังก์ชัน หาค่าต่ำสุดของ f
<- 100*x +80*y-x^2-y^2 -x*y
max_Pi max_Pi
- ตั้ง FOC: ด้วยการหาเกรเดียนต์ด้วย
der()
<- der(max_Pi, list(x,y))
Gmax_Pi Gmax_Pi
- แก้สมการหา Critical Points ด้วยคำสั่ง
solve_sys()
solve_sys(Gmax_Pi, list(x,y))
Solution 1:
x = 40
y = 20
- ตรวจสอบคำตอบด้วย Hessian Matrix ถ้าใช้ caracas มีฟังก์ชันชื่อ
hessian()
ช่วยหา
# หา hessian จากฟังก์ชันข้อ 1 โดยตั้งชื่อ hes.M
<-hessian(max_Pi, list(x, y))
hes.M hes.M
ค่าใน diagonal ทุกตัวน้อยกว่า 0
- หาค่า det เพื่อสรุปผล
det(hes.M)
ดีเทอมิแนนท์มีค่าเท่ากับ 3 มากกว่า 0 แสดงว่าเป็นจุดสูงสุด ที่จุด
subs(max_Pi, list(x = 40, y =20))
สามารถกราฟ contour และ surfaceเพื่อพิจารณา ฟังก์ชันนี้มีค่าสูงสุด หรือต่ำสุดจริงๆ หรือไม่?
# เปลี่ยนฟังก์ชันจาก caracas เป็น ฟังก์ชันใน R ด้วย as_func()
<- function(x, y){
plot.Pi return(100*x + 80*y -x^2 - y^2 - x*y)
}# โหลดแพ็กเกจที่จำเป็น
library(ggplot2)
# กำหนดช่วงของ x และ y
<- seq(0, 200, length.out = 1000)
x <- seq(0, 200, length.out = 1000)
y
# สร้างตารางค่าที่จะใช้วาด
<- expand.grid(x = x, y = y)
grid
# คำนวณค่าฟังก์ชัน f(x,y)
$z <- plot.Pi(grid$x,grid$y)
grid
# วาดกราฟ contour
ggplot(grid, aes(x = x, y = y, z = z)) +
geom_contour_filled(bins = 20) + # วาด contour แบบมีไล่สี
labs(title = "Contour Plot of Pi(x,y)",
x = "x",
y = "y",
fill = "f(x,y)") +
theme_classic(base_size = 14)+
theme(legend.position = "none", # นำ legend ออก
text = element_text(family = "TH Sarabun New", size = 10))
วาด surface plot
# ติดตั้ง plotly ถ้ายังไม่มี
# install.packages("plotly")
library(plotly)
# สร้างข้อมูล
<- seq(0, 200, length.out = 200)
x_seq <- seq(0, 200, length.out = 200)
y_seq
<- outer(x_seq, y_seq, plot.Pi)
z_matrix # วาด surface plot แบบ interactive
plot_ly(
x = ~x_seq, y = ~y_seq, z = ~z_matrix
|>
) add_surface() |>
layout(
title = "Surface Plot of f(x,y)",
scene = list(
xaxis = list(title = "X"),
yaxis = list(title = "Y"),
zaxis = list(title = "f(x,y)")
) )
เหตุผลที่ไม่วากราฟก่อนคำนวณ การการกำหนดความช่วงที่พิจารณา ถ้า กำหนดความช่วงกว้างเกินไป อาจจะเห็นไม่ชัดเจน และถ้ากำหนดความยาวช่วงสั้นเกินไป ก็อาจจะไม่ไม่รวมคำตอบอยู่ในกราฟก็ได้
ทำ 4 ขั้นตอนแรกด้วย caracas
- สร้างฟังก์ชัน
<- symbol("K")
K <- symbol("L")
L # สร้างฟังก์ชัน หาค่าต่ำสุดของ f
<- K^2 +2*K*L +3*L^2 -20*K -30*L
min_C min_C
- ตั้ง FOC: ด้วยการหาเกรเดียนต์ด้วย
der()
<- der(min_C, list(K,L))
Gmin_C Gmin_C
- แก้สมการหา Critical Points ด้วยคำสั่ง
solve_sys()
solve_sys(Gmin_C, list(K,L))
Solution 1:
K = 15/2
L = 5/2
- ตรวจสอบคำตอบด้วย Hessian Matrix ถ้าใช้ caracas มีฟังก์ชันชื่อ
hessian()
ช่วยหา
# หา hessian จากฟังก์ชันข้อ 1 โดยตั้งชื่อ hes.M
<-hessian(min_C, list(K,L))
hes.M hes.M
ค่าใน diagonal ทุกตัวมากกว่า 0
- หาค่า det เพื่อสรุปผล
det(hes.M)
ดีเทอมิแนนท์มีค่าเท่ากับ 8 มากกว่า 0 แสดงว่าเป็นจุดต่ำสุด ที่จุด
subs(min_C, list(K = 15/2, L = 5/2))
สามารถกราฟ contour และ surfaceเพื่อพิจารณา ฟังก์ชันนี้มีค่าสูงสุด หรือต่ำสุดจริงๆ หรือไม่?
#| fig-format: png
#| fig-dpi: 400
# เปลี่ยนฟังก์ชันจาก caracas เป็น ฟังก์ชันใน R ด้วย as_func()
<- function(K, L){
plot.C return(K^2 +2*K*L +3*L^2 -20*K -30*L)
}# โหลดแพ็กเกจที่จำเป็น
library(ggplot2)
# กำหนดช่วงของ x และ y
<- seq(0, 15, length.out = 1000)
x <- seq(0, 5, length.out = 1000)
y
# สร้างตารางค่าที่จะใช้วาด
<- expand.grid(x = x, y = y)
grid # คำนวณค่าฟังก์ชัน f(x,y)
$z <- plot.C(grid$x,grid$y)
grid# วาดกราฟ contour
ggplot(grid, aes(x = x, y = y, z = z)) +
geom_contour_filled() + # วาด contour แบบมีไล่สี
labs(title = "Contour Plot of C(K,L)",
x = "K",
y = "L",
fill = "C(K,L)") +
theme_classic(base_size = 14)+
theme(text = element_text(family = "TH Sarabun New", size = 10))
วาด surface plot
# ติดตั้ง plotly ถ้ายังไม่มี
# install.packages("plotly")
library(plotly)
# สร้างข้อมูล
<- seq(0, 15, length.out = 200)
x_seq <- seq(0, 5, length.out = 200)
y_seq
<- outer(x_seq, y_seq, plot.C)
z_matrix # วาด surface plot แบบ interactive
plot_ly(
x = ~x_seq, y = ~y_seq, z = ~z_matrix
|>
) add_surface() |>
layout(
title = "Surface Plot of C(K,L)",
scene = list(
xaxis = list(title = "K"),
yaxis = list(title = "L"),
zaxis = list(title = "C(K,L)")
) )
ทำ 4 ขั้นตอนแรกด้วย caracas
- สร้างฟังก์ชัน
# สร้างเวคเตอร์ ตัวแปร
<- paste0("x",1:2)
x <- as_sym(x)
x # สร้างฟังก์ชัน หาค่าสูงสุด
<- 4*x[1]-x[1]^2 +3*x[2]-x[2]^2
max_U max_U
- ตั้ง FOC: ด้วยการหาเกรเดียนต์ด้วย
der()
<- der(max_U, x)
Gmax_U Gmax_U
- แก้สมการหา Critical Points ด้วยคำสั่ง
solve_sys()
solve_sys(Gmax_U, x)
Solution 1:
x1 = 2
x2 = 3/2
- ตรวจสอบคำตอบด้วย Hessian Matrix ถ้าใช้ caracas มีฟังก์ชันชื่อ
hessian()
ช่วยหา
# หา hessian จากฟังก์ชันข้อ 1 โดยตั้งชื่อ hes.M
<-hessian(max_U, x)
hes.M hes.M
ค่าใน diagonal ทุกตัวน้อยกว่า 0
- หาค่า det เพื่อสรุปผล
det(hes.M)
ดีเทอมิแนนท์มีค่าเท่ากับ 8 มากกว่า 0 แสดงว่าเป็นจุดสูงสุด ที่จุด
subs(max_U, x,c(2,3/2))
สามารถกราฟ contour และ surfaceเพื่อพิจารณา ฟังก์ชันนี้มีค่าสูงสุด หรือต่ำสุดจริงๆ หรือไม่?
# เปลี่ยนฟังก์ชันจาก caracas เป็น ฟังก์ชันใน R ด้วย as_func()
<- function(x1,x2){
plot.U return(4*x1-x1^2 +3*x2-x2^2)
}# โหลดแพ็กเกจที่จำเป็น
library(ggplot2)
# กำหนดช่วงของ x และ y
<- seq(0, 4, length.out = 100)
x <- seq(0, 5, length.out = 100)
y
# สร้างตารางค่าที่จะใช้วาด
<- expand.grid(x = x, y = y)
grid # คำนวณค่าฟังก์ชัน f(x,y)
$z <- plot.U(grid$x,grid$y)
grid# วาดกราฟ contour
ggplot(grid, aes(x = x, y = y, z = z)) +
geom_contour_filled() + # วาด contour แบบมีไล่สี
labs(title = "Contour Plot of U(x1,x2)",
x = "x1",
y = "x2",
fill = "U(x1,x2") +
theme_classic(base_size = 14)+
theme(text = element_text(family = "TH Sarabun New", size = 10))
วาด surface plot
# ติดตั้ง plotly ถ้ายังไม่มี
# install.packages("plotly")
library(plotly)
# สร้างข้อมูล
<- seq(0, 5, length.out = 200)
x_seq <- seq(0, 5, length.out = 200)
y_seq
<- outer(x_seq, y_seq, plot.U)
z_matrix # วาด surface plot แบบ interactive
plot_ly(
x = ~x_seq, y = ~y_seq, z = ~z_matrix
|>
) add_surface() |>
layout(
title = "Surface Plot of U(x1,x2)",
scene = list(
xaxis = list(title = "x1"),
yaxis = list(title = "x2"),
zaxis = list(title = "U(x1,x2)")
) )
ทำ 4 ขั้นตอนแรกด้วย caracas
- สร้างฟังก์ชัน
# สร้างเวคเตอร์ ตัวแปร
<- symbol("K", "positive" = TRUE)
K <- symbol("L", "positive" = TRUE)
L # สร้างฟังก์ชัน หาค่าสูงสุด
<- 20*sqrt(K)*sqrt(L)-2*K -3*L
max_Q max_Q
- ตั้ง FOC: ด้วยการหาเกรเดียนต์ด้วย
der()
<- der(max_Q, list(K,L))
Gmax_Q Gmax_Q
- แก้สมการหา Critical Points ด้วยคำสั่ง
solve_sys()
solve_sys(Gmax_Q, list(K,L))
No solutions
สามารถเช็คได้โดยง่ายว่า จากเกรเดียนต์ ไม่สามารถหาคำตอบได้
5.6 การหาค่าสูงสุด/ต่ำสุดของฟังก์ชันและมีข้อจำกัด (Constrained Optimization)
เพราะเศรษฐศาสตร์เกี่ยวข้องกับ “การเลือกภายใต้ข้อจำกัด” (Choice under Scarcity)
เศรษฐศาสตร์ศึกษา “การเลือก” (choice) ที่เกิดขึ้นเพราะ ทรัพยากรมีจำกัด (scarcity)
ทุกการตัดสินใจทางเศรษฐกิจ — เช่น การบริโภค การผลิต การลงทุน การกำหนดราคาสินค้า — ล้วนเกิดขึ้นภายใต้ ข้อจำกัด:
รายได้จำกัด (budget constraint)
ต้นทุนการผลิต
เวลาจำกัด
กำลังการผลิตจำกัด
ทรัพยากรธรรมชาติจำนวนจำกัด
เพราะโลกจริงมีข้อจำกัดเสมอ การทำ optimization ที่ไม่คำนึงถึง constraint จะไม่สะท้อนโลกจริง
ตัวอย่างการใช้ Constrained Optimization ในเศรษฐศาสตร์จริง
สถานการณ์ | ฟังก์ชันเป้าหมาย | ข้อจำกัด |
---|---|---|
การบริโภคของผู้บริโภค | อรรถประโยชน์ (utility maximization) | งบประมาณ (budget constraint) |
การผลิตของบริษัท | ผลผลิต (production maximization) | ทุนและแรงงานจำกัด |
บริษัทตั้งราคา | กำไร (profit maximization) | กำลังการผลิตหรือข้อกำหนดภาครัฐ |
การจัดสรรทรัพยากร | สวัสดิการสังคม (welfare maximization) | งบประมาณรัฐจำกัด |
การลงทุน | ผลตอบแทนรวม (return maximization) | ความเสี่ยงหรืองบลงทุนจำกัด |
5.6.1 ขั้นตอนการทำ Constrained Optimization
5.7 ตัวอย่างการประยุกต์
5.7.1 การเพิ่มอรรถประโยชน์ภายใต้งบประมาณ (Utility Maximization)
วิธีทำ สร้างฟังก์ชัน Lagrangian:
ตั้งสมการ FOC:
แก้ระบบสมการ จะได้ Demand Functions สำหรับ
5.4 เงื่อนไข Second-Order (SOC: Second-Order Conditions) - ใช้ตรวจสอบว่าจุดที่หาได้เป็นจุดสูงสุดหรือต่ำสุดจริงหรือไม่ - โดยตรวจสอบลักษณะของ Hessian Matrix ของฟังก์ชัน - ในเศรษฐศาสตร์ปกติเราสนใจเฉพาะกรณีที่ เป็นจุดสูงสุด (Maximization)
5.5 กรณีมีหลายข้อจำกัด (Multiple Constraints)
ถ้ามีมากกว่าหนึ่งข้อจำกัด เช่น
5.7.2 การคำนวณเชิงสัญลักษณ์ด้วย caracas
จะเหมือนกับหัวข้อที่ผ่านทุกประการ เพียงแค่ต้องคำนวณว่าผ่านฟังก์ชันลากรองซ์เท่านั้นเอง
5.8 แบบฝึกหัด Constrained Optimization
หาค่าสูงสุดของฟังก์ชัน
ภายใต้ข้อจำกัดหาค่าต่ำสุดของ
โดยที่หาค่าสูงสุดของฟังก์ชันอรรถประโยชน์
ภายใต้ข้อจำกัดให้ฟังก์ชัน
, จงหาค่าต่ำสุดเมื่อผู้ผลิตต้องการผลิตที่
ให้น้อยที่สุด ภายใต้ข้อจำกัดหาค่ามากที่สุดของ
ภายใต้ข้อจำกัดให้ฟังก์ชัน
, จงหาค่าสูงสุดภายใต้หาค่าต่ำสุดของ
โดยที่ผู้บริโภคมีอรรถประโยชน์
, ต้องการใช้จ่ายไม่เกิน 60 บาท โดยที่ . จงหาปริมาณการบริโภค ที่ให้ U สูงสุดหาค่าต่ำสุดของ
โดยมีข้อจำกัดให้
, หา ภายใต้หาค่าสูงสุดของ
โดยที่ให้ฟังก์ชัน
, หา ภายใต้ผู้บริโภคมีงบ 100 บาท ต้องการบริโภค
โดย และอรรถประโยชน์ . จงหา ที่ทำให้ U สูงสุดหาค่าต่ำสุดของ
ภายใต้หา
ภายใต้ให้
, จงหา เมื่อหาค่าสูงสุดของฟังก์ชัน
เมื่อหาค่าต่ำสุดของ
โดยที่ผู้ผลิตต้องการลดต้นทุน
ให้ต่ำสุด โดยต้องผลิต . จงหาค่าที่เหมาะสมของ