1. Các toán tử cơ bản: Matlab là một phần mềm cao cấp dùng để giải các bài
toán. Để khởi động MATLAB ta bấm đúp vào icon của nó. Các file MATLAB
có dạng *.m và chỉ chạy trong môi trường MATLAB. MATLAB xử lí số liệu
như là ma trận. Khi ta đánh lệnh vào cửa sổ lệnh, nó sẽ được thi hành ngay và
kết quả hiện lên màn hình. Nếu ta không muốn cho kết quả hiện lên màn
hình thì sau lệnh ta đặt thêm dấu “;”. Nếu lệnh quá dài, không vừa một dòng
dòng có thể đánh lệnh trên nhiều dòng và cuối mỗi dòng đặt thêm dấu . rồi
xuống dòng. Khi soạn thảo lệnh ta có thể dùng các phím tắt :
              
                                            
                                
            
 
            
                 541 trang
541 trang | 
Chia sẻ: phuongt97 | Lượt xem: 874 | Lượt tải: 0 
              
            Bạn đang xem trước 20 trang nội dung tài liệu Các lệnh trong Matlab, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
  
KC1 = 112/121;  
KC2 = 9/121; 
h312 = 3*h*[‐1 2 1]; 
for k = 4:n 
    p1 = y(k ‐ 3, :) + h34*(2*(F(1, :) + F(3, :)) ‐ F(2, :)); %Pt.(8a) 
    m1 = p1 + KC1*(c ‐ p); %Pt.(8b) 
    if nargin(f) > 1 
        c1 = (‐y(k ‐ 2, :) + 9*y(k, :) + h312*[F(2:3, :);  
       feval(f, t(k + 1), m1)ʹ])/8; %Pt.(8c) 
    else 
        c1 = (‐y(k ‐ 2, :) + 9*y(k, :) + h312*[F(2:3, :); 
        feval(f, t(k + 1))ʹ])/8; Pt.(8c) 
    end 
    y(k+1,:) = c1 ‐ KC2*(c1 ‐ p1); %Pt.(8d) 
    p = p1; c = c1; %cap nhat cac gia tri du bao/hieu chinh 
    if nargin(f) > 1 
        F = [F(2:3, :); feval(f, t(k + 1),y(k + 1,:))ʹ]; 
    else 
 383
        F = [F(2:3, :); feval(f, t(k + 1))ʹ]; 
    end 
end 
Để giải phương trình ta dùng chương trình cthamming.m: 
clear all, clc 
a = 0; 
b = 1; 
y = @f1; 
ya = [0 1 1]ʹ; 
n = 10; 
tic 
[t, y] = hamming(y, a, b, ya, n); 
toc 
plot(t, y) 
§9. PHƯƠNG PHÁP MILNE 
  Quá trình tính toán nghiệm được thực hiện qua ba bước: 
  ‐ Tính gần đúng ym+1 theo công thức (dự đoán): 
  ( )+ − − −′ ′ ′= + − +(1)m 1 m 3 m 2 m 1 m4hy y 2y y 2y3           (1) 
  ‐ Dùng  +
(1)
m 1y  để tính: 
  + + +′ = (1)m 1 m 1 m 1y f(x ,y )                 (2) 
  ‐ Dùng  +′m 1y  vừa tính được để tính gầm đúng thứ 2 của ym+1(hiệu chỉnh)  
  ( )+ − − +′ ′ ′= + + +(2)m 1 m 1 m 1 m m 1hy y y 4y y3             (3) 
Ta xây dựng hàm milne() để thực hiện thuật toán trên: 
function [t, y] = milne(f, to, tf, y0, n) 
h = (tf ‐ to)/n; 
y(1, :) = y0ʹ; 
ts = to + 3*h; 
[t, y] = rungekutta(f, to, ts, y0, 3); 
t = [t(1:3)ʹ  t(4):h:tf]ʹ; 
for i = 2:4 
 384
    if nargin(f) > 1 
        F(i ‐ 1, :) = feval(f, t(i), y(i, :));  
    else 
        F(i ‐ 1, :) = feval(f, t(i));  
    end 
end 
for i = 4:n 
    p = y(i ‐ 3, :) + (4*h/3)*(2*F(1, :) ‐ F(2, :) + 2*F(3, :)); %Pt.(1) 
    if nargin(f) > 1 
        F(4, :) = f(t(i+1), p);%Pt.(2)           
    else 
        F(4, :) = f(t(i+1)); 
    end 
    y(i+1, :) = y(i‐1, :) + (h/3)*(F(2, :) + 4*F(3, :) + F(4, :));%Pt.(3) 
    F(1, :) = F(2, :); 
    F(2, :) = F(3, :); 
    if nargin(f) > 1 
        F(3, :) = f(t(i+1), y(i+1, :)); 
    else 
        F(3, :) = f(t(i+1)); 
    end 
end 
Để giải phương trình ta dùng chương trình ctmilne.m: 
clear all, clc 
a = 0; 
b = 1; 
y  = @f2; 
ya = 1; 
n = 10; 
[t, y] = milne(y, a, b, ya, n); 
plot(t, y) 
§10. BÀI TOÁN GIÁ TRỊ BIÊN 
1. Khái niệm chung: Ta xét bài toán tìm nghiệm của phương trình: 
 385
  ′′ ′= = α = βy f(x,y,y ) y(a) ,y(b)  
Đây  là bài  toán  tìm nghiệm của phương  trình vi 
phân  khi  biết  điều  kiện  biên  và  được  gọi  là  bài 
toán giá  trị biên hai  điểm. Trong bài  toán giá  trị 
đầu  ta có  thể bắt đầu  tìm nghiệm  ở điểm có các 
giá  trị  đầu  đã  cho và  tiếp  tục  cho  các  thời  điểm 
sau. Kỹ  thuật này  không  áp dụng  được  cho  bài 
toán giá  trị biên vì không có đủ điều kiện đầu ở 
các biên để có nghiệm duy nhất. Một cách để khác 
phục  khó  khăn  này  là  cho  các  giá  trị  còn  thiếu. 
Nghiệm  tìm  được  dĩ  nhiên  sẽ  không  thoả mãn 
điều kiện  ở các biên. Tuy nhiên  ta có  thể căn cứ 
vào  đó  để  thay  đổi  điều kiện  đầu  trước khi  tích 
phân  lại. Phương pháp này cũng giống như bắn 
bia. Trước hết  ta bắn  rồi xem  có  trúng  đích hay 
không,  hiệu  chỉnh  và  bắn  lại.  Do  vậy  phương 
pháp này gọi là phương pháp bắn. 
  Một phương pháp khác để giải bài toán giá trị biên là phương pháp sai 
phân hữu hạn  trong các đạo hàm được  thay bằng các xấp xỉ bằng sai phân 
hữu hạn tại các nút lưới cách đều. Như vậy ta sẽ nhận được hệ phương trình 
đại số đối với các sai phân.    
  Cả  hai  phương  pháp  này  có một  vấn  đề  chung:  chúng  làm  tăng  số 
phương trình phi tuyến nếu phương trình vi phân là phi tuyến. Các phương 
trình này được giải bằng phương pháp lặp nên rất tốn thời gian tính toán. Vì 
vạy việc giải bài toán biên phi tuyến rất khó. Ngoài ra, đối với phương pháp 
lặp,  việc  chọn  giá  trị  đầu  rất  quan  trọng. Nó  quyết  định  tính  hội  tụ  của 
phương pháp lặp.   
2. Phương pháp shooting: Ta xét bài toán biên là phương trình vi phân cấp 2 
với điều kiện đầu tại x = a và x = b. Ta xét phương trình: 
′′ ′= = α = βy f(x,y,y ) y(a) ,y(b)             (1) 
Ta tìm cách đưa bài toán về dạng bài toán giá trị đầu: 
  ′′ ′ ′= = α =y f(x,y,y ) y(a) ,y (a) u             (2) 
Chìa khoá  thành công  là  tìm  ra giá  trị đúng u.  ta có  thể  thực hiện việc này 
bằng phương pháp “thử và sai”: cho một giá trị u và giải bài toán giá trị đầu 
bằng cách đi từ a đến b. Nếu nghiệm giống với điều kiện biên mô tả y(b) = β 
 386
thì ta đã có nghiệm của bài toán. Nếu không ta phải hiệu chỉnh u và làm lại. 
Tuy nhiên  làm như vậy  chưa hay. Do nghiệm  của bài  toán giá  trị  đầu phụ 
thuộc u nên giá trị biên tính được y(b) là hàm của u, nghĩa là: 
  y(b) = θ(u)                     
Do đó u là nghiệm của phương trình: 
  r(u) = θ(u) ‐ β = 0                  (3) 
Trong đó θ(u) gọi  là số dự biên(hiệu số giữa giá 
trị  tính  được  và  giá  trị  biên  cho  trước). Phương 
trình  (3)  có  thể  gải  bằng  các  phương  pháp  tìm 
nghiệm  trong  chương  trước.  Tuy  nhiên  phương 
pháp  chia  đôi  cung  đòi  hỏi  tính  toán  lâu  còn 
phương pháp Newton ‐ Raphson đòi hỏi tìm đạo 
hàm dθ/dt. Do vậy cúng ta sẽ dùng phương pháp 
Brent. Tóm lại thuật oán giải bài toán giá trị biên 
gồm các bước: 
  ‐ Mô tả giá trị u1 và u2 vây nghiệm u của (3) 
  ‐ Dùng phương pháp Brent tìm nghiệm u của (3). Chú ý là mỗi bước lặp 
đòi hỏi  tính θ(u) bằng cách giải phương  trình vi phân như  là bài  toán điều 
kiện đầu. 
  ‐ Khi đã có u, giải phương trình vi phân lần nữa để tìm nghiệm  
Ta xây dựng hàm bvp2shoot() để giải phương trình bậc 2: 
function [t, x] = bvp2shoot(f, t0, tf, x0, xf, n, tol, kmax) 
%Giai phuong trinh: [x1, x2]ʹ = f(t, x1, x2) voi x1(t0) = x0, x1(tf) = xf 
if nargin < 8 
    kmax = 10;  
end 
if nargin < 7 
    tol = 1e‐8;  
end 
if nargin < 6 
    n = 100;  
end 
dx0(1) = (xf ‐ x0)/(tf ‐ t0); % cho gia tri dau cua xʹ(t0) 
y0 = [x0 dx0(1)]ʹ; 
[t, x] = rungekutta(f, t0, tf , y0, n); % khoi gan bg RK4 
 387
e(1) = x(end,1) ‐ xf;  
dx0(2) = dx0(1) ‐ 0.1*sign(e(1)); 
for k = 2: kmax‐1 
    y1 = [x0 dx0(k)]ʹ; 
    [t, x] = rungekutta(f, t0, tf, y1, n); 
    %sai so giua gia tri cuoi va dich 
    e(k) = x(end, 1) ‐ xf; % x(tf)‐ xf 
    ddx = dx0(k) ‐ dx0(k ‐ 1);  
    if abs(e(k))< tol | abs(ddx)< tol 
        break;  
    end 
    deddx = (e(k) ‐ e(k ‐ 1))/ddx;  
    dx0(k + 1) = dx0(k) ‐ e(k)/deddx;  
end 
Để giải phương trình: 
  ′′ ′= +2y 2y 4xyy  với điều kiện biên: y(0) = 0.25, y(1) = 1/3  
Đặt:  ′ = 1y y ,  ′′ = 2y y  ta đưa phương trình về hệ phương trình vi phân cấp 1: 
=⎧⎨ = +⎩
1 2
2 1 2 1
y y
y 2y 4xy y
và biểu diễn nó bằng hàm f7(): 
function dx = f7(t, x) %Eq.(6.6.5) 
dx(1) = x(2);  
dx(2) = (2*x(1) + 4*t*x(2))*x(1); 
Để giải phương trình ta dùng chương trình ctbvp2shoot.m: 
clear all, clc 
t0 = 0;  
tf = 1;  
x0 = 1/4;  
xf = 1/3; % thoi gian dau/cuoi va cac vi tri 
n = 100;  
tol = 1e‐8;  
 388
kmax = 10; 
y = @f7; 
[t, x] = bvp2shoot(y, t0, tf, x0, xf, n, tol, kmax); 
xo = 1./(4 ‐ t.*t);  
err = norm(x(:,1) ‐ xo)/(n + 1) 
plot(t,x(:, 1))  
3. Phương pháp sai phân hữu hạn: Ta xét phương trình: 
′′ ′= = α = βy f(x,y,y ) y(a) ,y(b)  
Ý tưởng của phương pháp này là chia đoạn [a, b] thành n đoạn nhỏ có bước h 
và xấp xỉ các đạo hàm bằng các sai phân: 
  + −′ = i 1 iy yy
2h
  − +− +′′ = i 1 i i 12y 2y yy h  
Như vậy: 
  − + +− + −⎛ ⎞′′ = = ⎜ ⎟⎝ ⎠
i 1 i i 1 i 1 i
i i2
y 2y y y yy f x ,y ,
h 2h
  i = 1, 2, 3,... 
Phương  trình bnày sec đưa đến hệ phương  trình đối với xi, yi. Ta xây dựng 
hàm bvp2fdf(): 
function [t, x] = bvp2fdf(a1, a0, u, t0, tf, x0, xf, n) 
% Giai pt : xʺ + a1*x’ + a0*x = u with x(t0) = x0, x(tf) = xf 
% bang pp sai phan huu han 
h = (tf ‐ t0)/n;  
h2 = 2*h*h; 
t = t0 + [0:n]ʹ*h; 
if ~isnumeric(a1) 
    a1 = a1(t(2: n));  
else 
    length(a1) == 1 
    a1 = a1*ones(n ‐ 1, 1); 
end 
if ~isnumeric(a0) 
    a0 = a0(t(2:n));  
else length(a0) == 1 
 389
    a0 = a0*ones(n ‐ 1, 1); 
end 
if ~isnumeric(u) 
    u = u(t(2:n));  
elseif length(u) == 1 
    u = u*ones(n‐1,1); 
else  
    u = u(:); 
end 
A = zeros(n ‐ 1, n ‐ 1);  
b = h2*u; 
ha = h*a1(1);  
A(1, 1:2) = [‐4 + h2*a0(1) 2 + ha]; 
b(1) = b(1) + (ha ‐ 2)*x0; 
for m = 2:n ‐ 2  
    ha = h*a1(m);  
    A(m, m ‐ 1:m + 1) = [2‐ha   ‐4+h2*a0(m)   2+ha]; 
end 
ha = h*a1(n ‐ 1);  
A(n ‐ 1, n ‐ 2:n ‐ 1) = [2‐ha   ‐4+h2*a0(n ‐ 1)]; 
b(n ‐ 1) = b(n‐1) ‐ (ha+2)*xf; 
x = [x0 trid(A,b)ʹ xf]ʹ; 
  function x = trid(A, b) 
% giai he pt trdiagonal 
n = size(A, 2); 
for m = 2:n  
    tmp = A(m, m ‐ 1)/A(m ‐ 1, m ‐ 1); 
    A(m, m) = A(m, m) ‐A(m ‐ 1, m)*tmp; 
    A(m, m ‐ 1) = 0; 
    b(m, :) = b(m, :) ‐b(m ‐ 1, :)*tmp; 
end 
x(n, :) = b(n, :)/A(n, n); 
for m = n ‐ 1: ‐1: 1  
    x(m, :) = (b(m, :) ‐A(m, m + 1)*x(m + 1))/A(m, m); 
end 
 390
Để giải phương trình: 
  ′′ ′+ − =22 2y y 0x x  
với y(1) = 5 và y(2) = 3 ta dùng chương trình ctbvp2fdf.m:  
clear, clc 
x0 = 1;%toa do bien dau  
y0 = 5; %gia tri bien dau 
xf = 2; %toa do bien cuoi 
yf = 3; %gia tri bien cuoi 
n = 100;%so buoc tinh 
a1 = inline(ʹ2./xʹ, ʹxʹ);  
a0 = inline(ʹ‐2./x./xʹ,ʹxʹ);  
u = 0;%ve phai cua phupng trinh  
[x, y] = bvp2fdf(a1, a0, u, x0, xf, y0, yf, n); 
plot(x, y)  
§11. PHƯƠNG PHÁP LẶP PICARD 
  Việc giải bài toán Cauchy: 
  ′ =y f(t,y) ,  =o oy(t ) y                 (1) 
hoàn toàn tương đương với việc tìm nghiệm y(t) của phương trình tích phân: 
  [ ]= + ∫1
o
t
o
t
y(t) y f z,y(z) dz               (2) 
Nội dung  của phương  trình Picard  là  thay  cho  việc  tìm  nghiệm  đúng  của 
phương trình (2) ta tìm nghiệm gần đúng theo công thức: 
  [ ]+ = + ∫1
o
t
n 1 o
t
y y f z,y(z) dz               (3) 
Trong đó để đơn giản ta chọn nghiệm gần đúng đầu tiên là: 
  yo(x) = yo 
Ta xây dựng hàm picard() để thực hiện thuật toán trên: 
function g = picard(f, y0, maxiter) 
syms x y 
g = subs(f, y0); 
 391
g = int(g, x); 
for i = 1:maxiter 
    g = subs(f, g); 
    g = int(g, x); 
end 
g = sort(g);  
Để  giải  phương  trình  ta  dùng  chương  trình 
ctpicard.m: 
clear all, clc 
syms x y 
%f = 1 + y^2;%Phuong trinh yʹ = 1+y^2 
%y0 = 0;%dieu kien dau 
f = y ‐ x; 
y0 = 2; 
g = picard(f, y0, 4) 
§12. PHƯƠNG PHÁP GILL 
  Phương pháp Gill cũng tương tự như phương pháp Runge ‐ Kutta, giá 
trị nghiệm tại yn+1 được tính bằng: 
  +
⎡ ⎤= + + − + + +⎢ ⎥⎦⎣n 1 n 1 2 4 4
1y y k (2 2)k (2 2)k k
6
Với: 
  =1 n nk hf(x ,y )  
       ⎡ ⎤= + +⎢ ⎥⎣ ⎦2 n n 1
1 1k hf x h,y k
2 2
  ( )⎡ ⎤⎛ ⎞= + + − + + −⎢ ⎥⎜ ⎟⎝ ⎠⎣ ⎦3 n n 1 21 1 2k hf x h,y 1 2 k 1 k2 2 2  
⎡ ⎤⎛ ⎞= + − + +⎢ ⎥⎜ ⎟⎝ ⎠⎣ ⎦4 n n 2 3
2 2k hf x h,y k 1 k
2 2
Ta xây dựng hàm gill() để thực hiên thuật toán trên: 
function [x, y] = gill(f, a, b, y0, n) 
%Phuong phap Gill de giai phuong trinh yʹ(x) = f(x,y(x)) 
if nargin < 4 | n <= 0 
 392
    n = 100;  
end 
if nargin < 3 
    y0 = 0;  
end 
y(1,:) = y0(:)ʹ;  
h = (b ‐ a)/n;  
x = a + [0:n]ʹ*h; 
if nargin(f) >1 
    for k = 1:n 
        k1 = h*feval(f, x(k), y(k, :));  
        k1 = k1(:)ʹ;  
        k2 = h*feval(f, x(k)+h/2, y(k, :)+k1/2);  
        k2 = k2(:)ʹ;        
        k3 = h*feval(f, x(k)+h/2, y(k, :)+(sqrt(2)‐1)*k1/2+(1‐sqrt(2)/2)*k2);  
        k3 = k3(:)ʹ; 
        k4 = h*feval(f, x(k)+h, y(k, :) ‐sqrt(2)/2*k2+(1+sqrt(2)/2)*k3);  
        k4 = k4(:)ʹ;  
        y(k+1, :) = y(k, :) + (k1 + (2 ‐ sqrt(2))*k2 + (2+sqrt(2))*k3 + k4)/6;  
    end 
else 
    for k = 1:n 
        f1 = h*feval(f, x(k));  
        f1 = f1(:)ʹ;  
        f2 = h*feval(f, x(k) + h/2);  
        f2 = f2(:)ʹ;        
        f3 = h*feval(f, x(k) + h/2);  
        f3 = f3(:)ʹ; 
        f4 = h*feval(f, x(k) + h);  
        f4 = f4(:)ʹ;  
        y(k+1, :) = y(k, :) + (f1 + (2 ‐ sqrt(2))*f2 + (2+sqrt(2))*f3 + f4)/6;  
    end 
end 
Để giải phương trình ta dùng chương trình ctgill.m: 
 393
clear all, clc 
a = 0; 
b = 1; 
y = inline(ʹx + yʹ); 
ya = 0.5; 
n = 10;%so lan tinh chi n = 10 
[t, u] = gill(y, a, b, ya, n); 
plot(t, u); 
[l, v] = rungekutta(y, a, b, ya, n); 
hold on 
plot(l, v, ʹ.rʹ) 
§13. PHƯƠNG PHÁP RUNGE – KUTTA – FEHLBERG 
  Một   phương pháp để bảo đảm độ chính xác của nghiệm của phương 
trình vi phân là giả bài toán hai lần với bươc tính là h và 0.5h rồi so sánh kết 
quả tại các nút  ứng với h. Tuy nhiên điều này đòi hỏi tăng số lần tính và phải 
tính  lại khi giá trị tại các nút khác nhau nhiều. Dùng phương pháp Runge – 
Kutta – Fehlberg có thể tránh được khó khăn này. Nó có thủ tục để xác định 
liệu kích thước bước tính h đã thích hợp chưa. Tại mỗi bươc tính, hai xấp xỉ 
khác nhau của nghiệm được  tính và so sánh với nhau. Nếu chúng sai khác 
trong phạm vi sai số cho trước thì nghiệm được chấp nhận. Nếu sai khác còn 
lơn hơn sai số cho phép thì bước h được giảm và ta lại tìm nghiệm với h mới. 
Mỗi bước tính theo phương pháp Runge – Kutta – Fehlberg đòi hỏi 6 giá trị: 
  1 i ik hf(t ,y )=   
  2 i i 1
1 1k hf t h,y k
4 4
⎛ ⎞= + +⎜ ⎟⎝ ⎠  
  3 i i 1 2
3 3 9k hf t h,y k k
8 32 32
⎛ ⎞= + + +⎜ ⎟⎝ ⎠  
  4 i i 1 2 3
12 1932 7200 7296k hf t h,y k k k
13 2197 2197 2197
⎛ ⎞= + + − +⎜ ⎟⎝ ⎠  
  5 i i 1 2 3 4
439 3680 845k hf t h,y k 8k k k
216 513 4104
⎛ ⎞= + + − + −⎜ ⎟⎝ ⎠  
  5 i i 1 2 3 4 5
1 8 3544 1859 11k hf t h,y k 2k k k k
2 27 2565 4104 40
⎛ ⎞= + − + − + −⎜ ⎟⎝ ⎠  
Xấp xỉ nghiệm theo phương pháp Runge – Kutta bậc 4: 
 394
i 1 i 1 3 4 5
25 1408 2197 1y y k k k k
216 2565 4104 5+
= + + + −  
Và nghiệm tốt hơn dùng phương pháp Runge – Kutta bậc 5: 
  i 1 i 1 3 4 5 6
16 6656 28561 9 2z y k k k k k
135 12825 56430 50 55+
= + + + − +  
Bước tính tối ưu được xác định bằng sh với s là: 
1 1
4 4
i 1 i 1 i 1 i 1
h hs 0.840896
2 z y z y+ + + +
⎛ ⎞ ⎛ ⎞ε ε= =⎜ ⎟ ⎜ ⎟⎜ ⎟ ⎜ ⎟− −⎝ ⎠ ⎝ ⎠
Ta xây dựng hàm rkf() để thực hiện thuật toán trên: 
function [t, y] = rkf ( f, t0, tf, x0, parms ) 
% tim nghiem cua phuong trinh  yʹ(t) = f( t, y ), y(t0) = x0 
% dung phuong phap Runge‐Kutta‐Fehlberg bac 4, bac 5 
neqn = length(x0); 
hmin = parms(1); 
hmax = parms(2); 
tol  = parms(3); 
t(1) = t0; 
y(1:neqn, 1) = x0ʹ; 
count = 0; 
h = hmax; 
i = 2; 
while( t0 < tf ) 
    if nargin(f) > 1 
        k1 = h*feval(f, t0, x0); 
        k2 = h*feval(f, t0 + h/4, x0 + k1/4); 
        k3 = h*feval(f, t0 + 3*h/8, x0 + 3*k1/32 + 9*k2/32); 
        k4 = h*feval(f, t0 + 12*h/13, x0 + 1932*k1/2197 ‐... 
               7200*k2/2197 + 7296*k3/2197); 
        k5 = h*feval(f, t0 + h, x0 + 439*k1/216 ‐ 8*k2 +... 
               3680*k3/513 ‐ 845*k4/4104); 
        k6 = h*feval(f, t0 + h/2, x0 ‐ 8*k1/27 + 2*k2 ‐... 
               3544*k3/2565 + 1859*k4/4104 ‐ 11*k5/40); 
    else 
        k1 = h * feval(f, t0); 
        k2 = h * feval(f, t0 + h/4); 
 395
        k3 = h * feval(f, t0 + 3*h/8); 
        k4 = h * feval(f, t0 + 12*h/13); 
        k5 = h * feval(f, t0 + h); 
        k6 = h * feval(f, t0 + h/2); 
      end 
      r = max(abs(k1/360 ‐ 128*k3/4275 ‐ 2197*k4/75240 +... 
           k5/50 + 2*k6/55)/h); 
      q = 0.84*(tol/r)^(1/4); 
      if ( r < tol ) 
         x0 = x0 + 16*k1/135 + 6656*k3/12825 + 28561*k4/56430 ‐... 
                 9*k5/50 + 2*k6/55; 
          t0 = t0 + h; 
          t(i) = t0; 
          y(1:neqn, i) = x0ʹ; 
          i = i + 1;   
     end; 
      h = min(max(q, 0.1), 4.0)*h; 
     if (h > hmax) 
         h = hmax;  
      end; 
      if (t0 + h > tf) 
                    h = tf ‐ t0; 
     elseif (h < hmin) 
                   disp(ʹCan giam kich thuoc buoc tinhʹ); 
         return; 
     end; 
end; 
Để giải phương trình ta dùng chương trình ctrkf.m: 
clear all, clc 
a = 0; 
b = 1; 
y  = @f2; 
ya = 0.5; 
p = [1e‐5 1e‐3 1e‐8];%[hmin  hmax tol] 
 396
[t, y] = rkf(y, a, b, ya, p) 
plot(t, y); 
 370
CHƯƠNG 8: TỐI ƯU HOÁ 
§1. KHÁI NIỆM CHUNG VỀ TỐI ƯU HOÁ 
  Tối ưu hoá là thuật ngữ thường được dùng để cực tiểu hoá hay cực đại 
hoá một hàm. Thông thường ta chỉ cần tìm cực tiểu một hàm là đủ. Việc tìm 
cực đại của f(x) thực hiện một cách đơn giản bằng cách tìm cực tiểu của hàm 
−f(x) . Hàm f là hàm giá trị hay hàm đối tượng, cần được giữ cực tiểu. Biến x 
là biến có thể hiệu chỉnh tự do. 
  Các thuật toán cực tiểu hoá là các thủ thuật lặp đòi hỏi một giá trị ban 
đầu của biến x. Nếu f(x) có nhiều cực tiểu địa phương, việc chọn giá trị đầu sẽ 
xác định cực tiểu nào được tính. Ta không có cách nào bảo đảm là tìm được 
cực tiểu toàn cục. 
  Các biến  có  thể bị  ràng buộc bằng  các  đẳng  thức hay bất  đẳng  thức. 
Phần lớn các phương pháp là tìm cực tiểu không ràng buộc, nghĩa là không có 
hạn chế nào đối với biến x. Các bài toán này bao gồm tìm cực tiểu của hàm, 
tìm điểm tĩnh ‐ điểm có gradient triệt tiêu. Các bài toán tìm cực tiểu có ràng 
buộc khó hơn và thuật toán khá phức tạp.  
  Trong chương này chúng ta sẽ  lần  lượt xét các thuật toán tìm cực tiểu 
không ràng buộc và có ràng buộc. 
§2. PHƯƠNG PHÁP TIẾT DIỆN VÀNG 
  Ta xét bài toán tìm cực tiểu của hàm một biến f(x). Điểm cực tiểu được 
xác định  theo điều kiện df/dx = 0. Do có  thể có nhiều điểm cực  tiểu nên  ta 
phải vây điểm cực tiểu(xác định lân cận chứa điểm cực tiểu) trước. Thủ thuật 
vây điểm cực tiểu khá đơn giản: cho điểm đầu x0 và tính giá trị của hàm đang 
đi  xuống  tại  các  điểm  tiếp  theo  x1,  x2,  x3,...  cho  đến  tại  xn hàm  tăng  lại  thì 
dừng. Điểm cực tiểu bị vây trong khoảng (xn‐2, xn). Khoảng (xi+1, xi) không nên 
chọn là hằng số vì như vậy cần nhiều bước tính. Hợp lí nhất là nên tăng kích 
thước bước tính để đạt được cực tiểu nhanh hơn, ngay cả khi cực tiểu bị vây 
trong  một  đoạn  khá  rộng.  Ta  chọn  kích  thước  tăng  theo  dạng  hằng  số: 
+ =i 1 ih ch với  >c 1.  ta xây dựng hàm goldbracket() để vây điểm cực  tiểu của 
hàm: 
function [a, b] = goldbracket(func, x1, h) 
% vay diem cuc tieu cua f(x). 
c = 1.618033989; 
 371
f1 = feval(func, x1); 
x2 = x1 + h;  
f2 = feval(func,x2); 
if f2 > f1 
    h = ‐h; 
    x2 = x1 + h;  
    f2 = feval(func, x2); 
    if f2 > f1 
        a = x2;  
        b = x1 ‐ h;  
        return 
    end 
end 
for i = 1:100 
    h = c*h; 
    x3 = x2 + h;  
    f3 = feval(func, x3); 
    if f3 > f2 
        a = x1;  
        b = x3;  
        return 
    end 
    x1 = x2;  
    f1 = f2;  
    x2 = x3; 
    f2 = f3; 
end 
error(ʹGoldbracket khong tim thay diem cuc tieuʹ) 
  Tiết diện vàng là một biến thể của phương pháp chia đôi dùng khi tìm 
nghiệm của phương trình f(x) = 0. Giả sử điểm cực tiểu bị vây trong khoảng 
(a,  b)  có  độ  dài  h.  Để  thu  nhỏ  khoảng  (a,  b)  ta  tính  giá  trị  của  hàm  tại 
= −1x b rh  và  = +2x a rh  như hình vẽ. Nếu f1 = f(x1) lớn hơn f2 = f(x2) như hình 
a  thì  cực  tiểu nằm  trong  khoảng  (x1,  b) nếu ngược  lại  cực  tiểu nằm  trong 
khoảng (a, x2). 
 372
  Giả sử f1 > f2 , ta đặt a = x1 và và x1 = 
x2 và có khoảng (a, b) mới như hình b. Để 
thực  hiện  bước  thu  gọn  tiếp  theo  ta  lại 
tính giá trị của hàm tại x2 = a + rh’ và lặp 
lại quá  trình. Quá  trình  làm việc chỉ nếu 
hình a và hình b tương tự, nghĩa  là hằng 
số r không đổi khi xác định x1 và x2 ở cả 
hai hình. Từ hình a ta thấy: 
  − = −2 1x x 2rh h  
Cùng một khoảng cách đó từ hình b ta có: 
  x1 ‐ a = h’ ‐ rh’ 
Cân bằng các khoảng này ta được: 
  2rh ‐ h = h’ ‐ rh’ 
Thay h’ = rh và khử h: 
  2r ‐ 1 = r(1 ‐ r) 
Giải phương trình này ta nhận được tỉ lệ vàng: 
  −= =5 1r 0.618033989...
2
Chú ý là mỗi lần thu gọn khoảng chứa điểm cực tiểu thì khoảng (a, b) giảm tỉ 
lệ với r. Điều này làm số lần tính lớn hơn phương pháp chia đôi. Tuy nhiên 
phương pháp tỉ lệ vàng chỉ đòi hỏi tính giá trị hàm một lần trong khi phương 
pháp chia đôi cần tính giá trị hàm 2 lần. Số lần tính xác định bằng: 
  − = εnb a r  
hay: 
ε
− ε= = − −
ln
b an 2.078087n
ln b a
    h = b ‐ a = 0.382 
Ta xây dựng hàm golden() để thực hiện thuật toán này: 
function [xmin, ymin] = golden(f, a, b, delta, epsilon) 
% a va b la doan tim cuc tieu 
% delta sai so cua x 
% epsilon sai so cua y 
r1 = (sqrt(5) ‐ 1)/2; 
r2 = r1^2; 
h = b ‐ a; 
a bx1  x2 
h 
rh 
2rh‐h 
rh 
a 
a bx1  x2 
h’ 
rh’ 
rh’ 
b 
 373
fa = f(a); 
fb = f(b); 
x1 = a + r2*h; 
x2 = a + r1*h; 
f1 = f(x1); 
f2 = f(x2); 
k = 1; 
while (abs(fb‐fa) > epsilon)|(h > delta) 
   k = k + 1; 
   if (f1 < f2) 
      b = x2; 
      fb = f2; 
      x2 = x1; 
      f2 = f1; 
      h = b ‐ a; 
      x1 = a + r2*h; 
      f1 = f(x1); 
   else 
      a = x1; 
      fa = f1; 
      x1 = x2; 
      f1 = f2; 
      h = b ‐ a; 
      x2 = a + r1*h; 
      f2 = f(x2); 
   end 
end 
dp = abs(b ‐ a); 
dy = abs(fb ‐ fa); 
p = a; 
yp = fa; 
if (fb < fa) 
   p = b; 
   yp = fb; 
end 
xmin = p; 
 374
ymin = yp; 
Để tìm cực tiểu của hàm ta dùng chương trình ctgolden.m: 
clear all, clc 
f = inline(ʹ1.6*x^3 + 3*x^2 ‐2*xʹ); 
x = 0;  
delta = 1e‐8; 
epsilon = 1e‐10; 
[a, b] = goldbracket(f, x, 0.2); 
[xmin, ymin] = golden(f, a, b, delta, epsilon) 
§3. PHƯƠNG PHÁP XẤP XỈ BẬC HAI 
  Ý tưởng của phương pháp này là: 
  ‐ xấp xỉ hàm đối  tượng  f(x) bằng một hàm bậc 2 p2(x) qua 3 điểm cho 
trước 
  ‐ cập nhật 3 điểm này bằng cách  thay một  trong 3 điểm bằng cực  tiểu 
của hàm p2(x) 
  Qua 3 điểm:  
[ ] [ ] [ ]{ }0 0 1 1 2 2(x ,f(x ) , (x ,f(x ) , (x ,f(x )   x0 < x1 < x2 
ta tìm được đa thức nội suy p2(x) và điểm có đạo hàm bằng zero: 
  − + − + −= = ⎡ ⎤− + − + −⎣ ⎦
2 2 2 2 2 2
0 1 2 1 2 0 2 0 1
3
0 1 2 1 2 0 2 0 1
f (x x ) f (x x ) f (x x )x x
2 f (x x ) f (x x ) f (x x )
        (1) 
Đặc biệt, nếu các  điểm tìm được trước đây phân bố đều với khoảng cách h( 
nghĩa là x2 ‐ x1 = x1 ‐ x0 = h) thì (1) trở thành: 
  − + − + − − += = + − + −⎡ ⎤− + − + −⎣ ⎦
2 2 2 2 2 2
0 1 2 1 2 0 2 0 1 0 1 2
3 0
0 1 20 1 2 1 2 0 2 0 1
f (x x ) f (x x ) f (x x ) 3f 4f fx x h
2( f 2f f )2 f (x x ) f (x x ) f (x x )
  (2) 
Ta  cập  nhật  3  điểm  theo  cách  này  cho  đến  khi  − ≈2 0x x 0   hay 
− ≈2 0f(x ) f(x ) 0  và cực tiểu là x3. Quy tắc cập nhật 3 điểm là: 
  ‐ Trong trường hợp  < <0 3 1x x x  ta dùng  0 3 1(x , x , x )  hay  3 1 2(x , x , x )  làm 3 
điểm mới tuỳ theo f(x3) < f(x1) hay không 
  ‐ Trong trường hợp  < <1 3 2x x x  ta dùng  1 3 2(x , x , x )  hay  0 1 3(x , x , x )  làm 3 
điểm mới tuỳ theo f(x3) ≤ f(x1) hay không. 
Quá trình tìm cực tiểu được mô tả trên hình sau: 
 375
Ta xây dựng hàm optquad() để thực hiện thuật toán này. 
function [xo, fo] = optquad(f, x0, tolx, tolfun, maxiter) 
%Tim cuc tieu cua f(x) bang phuong phap xap xi bac 2 
if length(x0) > 2 
    x012 = x0(1:3); 
else 
    if length(x0) == 2 
        a = x0(1);  
        b = x0(2); 
    else  
        a = x0 ‐ 10;  
        b = x0 + 10; 
    end 
    x012 = [a (a + b)/2  b]; 
end 
f012 = f(x012); 
[xo, fo] = optquad0(f, x012, f012, tolx, tolfun, maxiter); 
function [xo, fo] = optquad0(f, x012, f012, tolx, tolfun, k) 
x0 = x012(1);  
x1 = x012(2);  
x2 = x012(3); 
 376
f0 = f012(1);  
f1 = f012(2);  
f2 = f012(3); 
nd = [f0 ‐ f2 f1 ‐ f0 f2 ‐ f1]*[x1*x1 x2*x2 x0*x0; x1 x2 x0]ʹ; 
x3 = nd(1)/2/nd(2);  
f3 = feval(f, x3); %Pt.(1) 
if k <= 0 | abs(x3 ‐ x1) < tolx | abs(f3 ‐ f1) < tolfun 
    xo = x3;  
    fo = f3; 
    if k == 0 
        fprintf(ʹDay co the xem la diem cuc tieuʹ) 
    end 
else 
    if x3 < x1 
        if f3 < f1  
            x012 = [x0 x3 x1];  
            f012 = [f0 f3 f1]; 
        else  
            x012 = [x3 x1 x2];  
            f012 = [f3 f1 f2]; 
        end 
    else 
        if f3 <= f1 
            x012 = [x1 x3 x2];  
            f012 = [f1 f3 f2]; 
        else  
            x012 = [x0 x1 x3];  
            f012 = [f0 f1 f3]; 
        end 
    end 
    [xo, fo] = optquad0(f, x012, f012, tolx, tolfun, k ‐ 1); 
end 
Để tìm điểm cực tiểu ta dùng chương trình ctoptquad.m: 
clear all, clc 
 377
%f = inline(ʹ(x.^2 ‐ 4).^2/8 ‐ 1ʹ); 
a = 0;  
b = 3; 
delta = 1e‐8; 
epsilon = 1e‐10; 
maxiter = 100; 
[xmin, ymin] = optquad(f, [a  b], delta, epsilon, maxiter) 
§4. PHƯƠNG PHÁP NELDER ‐ MEAD 
  Phương pháp Nelder ‐ Mead có thể dùng để tìm cực tiểu của hàm nhiều 
biến mà phương pháp  tiết diện vàng hay phương pháp xấp xỉ bậc 2 không 
dùng được. Thuật toán Nelder ‐ Mead gồm các bước như sau: 
Bước 1: Cho 3 điểm đầu tiên a, b, c với f(a) < f(b) < f(c) 
Bước 2: Nếu 3 điểm và các giá trị tương ứng của hàm đủ gần nhau thì ta 
coi a là điểm cực tiểu và kết thúc quá trình tính 
Bước  3:  Nếu  không  ta  coi 
điểm  cực  tiểu  nằm  đối  diện  với 
điểm  c  trên  đường  ab(xem  hình 
vẽ) và lấy: 
  e = m + 2(m ‐ c)  
với  
m = (a + b)/2 
và nếu f(e) < f(b) thì lấy: 
  r = (m + e)/2 = 2m ‐ c 
và nếu f(r) <  
            Các file đính kèm theo tài liệu này:
 cac_lenh_trong_matlab.pdf cac_lenh_trong_matlab.pdf