Cùng với sự phát triển mạnh mẽ của khoa học – kĩ thuật, các bài toán tối ưu trong các lĩnh vực thực tiễn xuất hiện ngày càng nhiều với quy mô ngày càng lớn và tính phức tạp ngày càng cao. Phạm vi và khả năng ứng dụng của chúng cũng ngày càng đa dạng và phong phú nhằm mục đích đưa chi phí sử dụng xuống mức tối thiểu và mang lại hiệu quả tối đa. Những bài toán thực tế này khi được tối ưu tốt có thể ảnh hưởng sống còn đối với sự phát triển của một doanh nghiệp, một công ti, một quốc gia, … mang lại một hiệu quả kinh tế không hề nhỏ. Thuật toán đơn hình (simplex algorithm) được George Bernard Dantzig đưa ra năm 1947 cùng lúc với việc ông khai sinh ra quy hoạch tuyến tính. Đây là một phương pháp thực sự có hiệu quả để giải những bài toán quy hoạch tuyến tính cỡ lớn trong thực tế. Nó là một trong những thuật toán làm thay đổi thế giới, được tạp chí Ecommerce Times xếp vào top 10 thuật toán của mọi thời đại. Nhằm mang lại cho các bạn những kiến thức cơ bản về thuật toán đơn hình, đồng thời đưa ra một giải pháp cụ thể để cài đặt chương trình, tôi đã quyết định lựa chọn đề tài “Cài đặt thuật toán đơn hình bằng ngôn ngữ C”. Để có thể nắm rõ được những thuật toán, các bước cài đặt cũng như cách thức tổ chức hoạt động của chương trình, mời các bạn tìm hiểu phần nội dung đề tài.
Trang 1TRƯỜNG ĐH HỒNG ĐỨC KHOA CNTT&TT - -
BÀI TIỂU LUẬN HỌC PHẦN TỐI ƯU HÓA
Đề tài:
“Cài đặt thuật toán đơn hình trên ngôn ngữ C”
Thanh Hóa, 5/2014
Trang 2KHOA CNTT&TT - -
BÀI TIỂU LUẬN HỌC PHẦN TỐI ƯU HÓA
Đề tài:
“Cài đặt thuật toán đơn hình trên ngôn ngữ C”
Thanh Hóa, 5/2014
Trang 3LỜI CẢM ƠN
Trong quá trình học tập tại trường, em đã được học hỏi và tiếp thu rất nhiều kiến thức đại cương cũng như chuyên ngành nhằm nâng cao vốn hiểu biết và là hành trang quý báu giúp em vững bước vào đời Em xin gửi lời cảm ơn chân thành đến khoa Công Nghệ Thông Tin và truyền thông, quý thầy cô đã giảng dạy chúng em trong suốt thời gian qua, cũng như tất cả quý thầy cô trong trường Đại học Hồng Đức Đặc biệt em xin chân thành cảm ơn cô Trịnh Thị Phú – Giảng viên trực tiếp giảng dạy học phần Tối ưu hóa và đồng thời là người tận tình hướng dẫn em trong suốt thời gian thực hiện đề tài này
Tuy nhiên, dù rất cố gắng nhưng do thời gian có hạn nên chắc rằng bài tiểu luận của em khó tránh khỏi những thiếu sót Em rất mong nhận được sự thông cảm và đóng góp ý kiến của quý thầy cô và các bạn để bài tiểu luận của em được hoàn chỉnh hơn
Em xin chân thành cảm ơn!
Thanh Hóa, 5/2014
Sinh viên thực hiện
Trang 4MỤC LỤC
CHƯƠNG I: MỞ ĐẦU 1
1.1 Lí do chọn đề tài 1
1.2 Mục tiêu và nhiệm vụ của đề tài 1
1.1.1 Mục tiêu đề tài 1
1.1.2 Nhiệm vụ đề tài 1
1.3 Khách thể, đối tượng và phạm vi nghiên cứu 2
1.1.1 Khách thể nghiên cứu 2
1.1.2 Đối tượng và phạm vi nghiên cứu 2
1.4 Các phương pháp nghiên cứu 2
CHƯƠNG II: CƠ SỞ LÍ LUẬN 3
2.1 Dạng chính tắc và dạng chuẩn tắc 3
2.1.1 Định nghĩa 3
2.1.2 Các phép biến đổi 3
2.1.3 Phương án cơ bản 4
2.1.4 Các tính chất 5
2.2 Phương pháp đơn hình 5
2.2.1 Nội dung 5
2.2.2 Bảng đơn hình 6
2.2.3 Cơ sở lí luận 7
2.2.4 Các bước giải bài toán đơn hình 7
2.2.5 Bài toán ẩn phụ 9
2.2.6 Bài toán ẩn giả 10
PHẦN III: NỘI DUNG 14
3.1 Tổ chức lưu trữ bài toán 14
3.2 Đọc dữ liệu từ tệp 15
3.3 Chuẩn hóa bài toán 17
3.4 Tìm các phần tử thuộc ma trận đơn vị 20
3.5 Khởi tạo giá trị 21
3.6 Kiểm tra tính dừng của thuật toán 22
3.7 Biến đổi bảng đơn hình 24
3.8 Các hàm khác trong chương trình 26
3.9 Thực hiện công việc giải bài toán 26
PHẦN IV: KẾT LUẬN 28
4.1 Tóm tắt kết quả nghiên cứu 28
4.2 Đề xuất và hướng phát triển 28
TÀI LIỆU THAM KHẢO 30
Trang 5Thuật toán đơn hình (simplex algorithm) được George Bernard Dantzig đưa
ra năm 1947 cùng lúc với việc ông khai sinh ra quy hoạch tuyến tính Đây là một phương pháp thực sự có hiệu quả để giải những bài toán quy hoạch tuyến tính cỡ lớn trong thực tế Nó là một trong những thuật toán làm thay đổi thế giới, được tạp chí Ecommerce Times xếp vào top 10 thuật toán của mọi thời đại
Nhằm mang lại cho các bạn những kiến thức cơ bản về thuật toán đơn hình, đồng thời đưa ra một giải pháp cụ thể để cài đặt chương trình, tôi đã quyết định
lựa chọn đề tài “Cài đặt thuật toán đơn hình bằng ngôn ngữ C” Để có thể nắm rõ
được những thuật toán, các bước cài đặt cũng như cách thức tổ chức hoạt động của chương trình, mời các bạn tìm hiểu phần nội dung đề tài
1.2 Mục tiêu và nhiệm vụ của đề tài
Trang 6- Tìm các phần tử thuộc ma trận đơn vị
- Khởi tạo giá trị cho các biến tại bảng đơn hình đầu tiên
- Kiểm tra tính dừng của thuật toán
- Biến đổi bảng đơn hình
- Thực hiện công việc lặp để giải bài toán đồng thời hiển thị từng bước ra màn hình
1.3 Khách thể, đối tượng và phạm vi nghiên cứu
1.1.1 Khách thể nghiên cứu
Cài đặt một chương trình thực hiện công việc giải bài toán quy hoạch tuyến tính bằng phương pháp đơn hình trên ngôn ngữ C
1.1.2 Đối tượng và phạm vi nghiên cứu
Chương trình giải bài toán quy hoạch tuyến tính bằng phương pháp đơn hình 1.4 Các phương pháp nghiên cứu
- Phương pháp thu thập tài liệu: thu thập tài liệu từ những bài báo khoa học, các trang web tin học và một số ebook về đề tài nghiên cứu, giáo trình và các tài liệu học tập khác
- Phương pháp phân tích và tổng hợp tài liệu: từ những tài liệu đã thu thập, tiến hành tìm hiểu, phân tích và tồng hợp nội dung liên quan đến đề tài
- Phương pháp chuyên gia: trong quá trình nghiên cứu có sự góp ý, điều chinh từ giáo viên hướng dẫn
- Phương pháp phân tích và tổng hợp kinh nghiệm: sau quá trình tìm hiểu và đúc kết kinh nghiệm, tiến hành tổng hợp và hoàn thiện đề tài
- Phương pháp thực nghiệm: sau khi cài đặt xong chương trình cần xây dựng một số bộ test tiêu biểu và thực hiện kiểm tra tính đúng đắn dựa trên kết quả thu được từ chương trình
Trang 7PHẦN II: CƠ SỞ LÍ LUẬN
2.1 Dạng chính tắc và dạng chuẩn tắc
2.1.1 Định nghĩa
Trong thực tế, đa số các bài toán có điều kiện không âm của các ẩn Từ đó
có định nghĩa dạng chính tắc là bài toán (Ɗ, ƒ) như sau:
( ) = → (1)
= ( = 1 ) (2) ≥ 0 ( = 1 ) (3)Trong đó, (2) gọi là ràng buộc cưỡng bức, (3) gọi là ràng buộc tự nhiên Với bài toán (Ɗ, ƒ) chính tắc, có thể giả sử m ≤ n
Một trường hợp đặc biệt của dạng chính tắc là ma trận số liệu A = (aij)m x n
có chứa đủ m vector cột là m vector đơn vị của không gian Rm và bi ≥ 0 (i = 1 m) gọi là dạng chuẩn tắc Không mất tính tổng quát, có thể định nghĩa bài toán (Ɗ, ƒ) chuẩn tắc như sau:
≥ 0 ( = 1 ) Trong đó: bi ≥ 0 (i = 1 m)
2.1.2 Các phép biến đổi
Các phép biến đổi sau để đưa bài toán (Ɗ, ƒ) bất kì về dạng chính tắc tương đương để giải, và từ đó suy ra nghiệm của bài toán ban đầu
- ƒ(x) → max ⟺ g(x) = - ƒ(x) → min
Trang 8- ∑ ≤ ⟺ ∑ + = với xn+i ≥ 0
xi+n gọi là ẩn phụ Có kết luận sau:
Nếu = (x1, x2, …, xn, xn+1, …, xn+m) là nghiệm của bài toán chính tắc biến đổi thì x = (x1, x2, …, xn) là nghiệm của bài toán gốc
- Nếu ẩn xj không ràng buộc về dấu thì được thay bằng hiệu hai ẩn không âm Nghĩa là đặt xj = + với ≥ 0 và ≥ 0
- Trường hợp bj < 0 thì nhân hai vế phương trình với -1 có được bj > 0
Vậy: Mọi bài toán quy hoạch tuyến tính đều có thể đưa về bài toán dạng tương đương Hơn nữa, có thể các hệ số tự do bj trong hệ ràng buộc là không âm
2.1.3 Phương án cơ bản
Xét bài toán (Ɗ, ƒ) dạng chính tắc:
= ( = 1 ) ≥ 0 ( = 1 ) Đặt Aj = (a1j, a2j, …, amj) là vector cột thứ j trong ma trận Amxn
- Phương án cơ bản có tối đa m thành phần dương Phương án cơ bản
có đúng m thành phần dương gọi là không suy biến Ngược lại được gọi là suy biến Bài toán có phương án cơ bản suy biến gọi là bài toán suy biến
- Số phương án cơ bản của một bài toán (Ɗ, ƒ) là hữu hạn
Trang 9- Với bài toán dạng chuẩn tắc thì có phương án cơ bản là X0 = (b1, b2,
Xuất phát từ phương án cơ bản nào đó, tìm cách đánh giá nó Nếu chưa tối
ưu thì chuyển sang phương án cơ bản mới tốt hơn Nếu bài toán có nghiệm thì sau hữu hạn bước sẽ tìm được phương án cơ bản tối ưu Hơn nữa dấu hiệu vô nghiệm cũng đươc thể hiện trên thuật toán
Ví dụ 2.1: Xét bài toán (Ɗ, ƒ) dạng chuẩn tắc:
ƒ(x) = x1 – 2x2 + 3x3 – 2x4 → min
2 − 3 + = 4 + + = 5
= x1 – 2x2 + 3(4 – 2x1 + 3x2) – 2(5 – x1 – x2)
= 2 – 3x1 + 9x2
Trang 10∀j = 1 n đặt ∆j = − và gọi là ước lượng của ẩn xj đối với phương án cơ bản X0 = (b1, b2, …, bm, 0, …, 0) với ƒ(X0) = ∑
Trang 11∀j = 1 , đặt ∆j = −
Có phương án cơ bản X0 = (b1, b2, …, bm, 0, , 0) với ƒ(X0) = ∑ Định lí 1 (Dấu hiệu tối ưu): Nếu ∆j ≤ 0 ∀j = 1 n thì X0 là phương án tối ưu Định lí 2 (Dấu hiệu vô nghiệm): Nếu ∃∆k > 0 và ajk ≤ 0 ∀i =1 m thì bài toán
vô nghiệm
Định lí 3 (Điều chỉnh phương án): Nếu ∃∆k > 0 và ∃ajk > 0 thì có thể tìm được phương án cơ bản mới tốt hơn X0, trong trường hợp bài toán không suy biến
2.2.4 Các bước giải bài toán đơn hình
Bước 1: Kiểm tra tính tối ưu của phương án X0 = (b1, b2, …, bm, 0, , 0)
- Nếu ∆j ≤ 0 ∀j =1 n thì X0 là phương án tối ưu và ƒmin= ƒ(X0)
= ∑
- Nếu ∃∆k > 0 thì chuyển tới bước 2
Trang 12Bước 2: Kiểm tra điều kiện vô nghiệm
- Nếu ∃∆k > 0 và ajk ≤ 0 ∀i = 1 m thì bài toán vô nghiệm
- Nếu ∃∆k > 0 và ∃ajk > 0 thì chuyển tới bước 3
Bước 3: Tìm ẩn thay thế và loại ra
- Nếu ∆s = max {∆j} với ∆j > 0 (i = 1 n) thì đưa xs vào tập ẩn cơ bản
- Nếu = min { } với ais > 0 thì loại xr ra khỏi tập ẩn cơ bản
- Chuyển sang bước 4
Bước 4: Biến đổi bảng đơn hình
- Biến đổi bảng đơn hình theo công thức sau:
=
= Ѳ
- Tính lại các ∆j, quay lại bước 1
Quá trình này có thể được mô tả như việc biến đổi sơ cấp về hàng trên ma trận bổ sung của của hệ ràng buộc sao cho vector As, trở thành đơn vị thứ r, và các vector đơn vị khác vẫn giữ nguyên
Nhận xét: Các công thức biến đổi cho aij cũng đúng cho cả bj và ∆j nếu xem
Trang 13xn+i được gọi là ẩn phụ Có kết luận sau:
Nếu = (x1, x2, …, xn, xn+1, , xn+m) là nghiệm của bài toán chính tắc biến đổi thì X = (x1, x2, …, xn) là nghiệm của bài toán gốc
Ví dụ 2.4:
Bài toán chính tắc tương đương:
Trang 14Trong đó x5, x6 là ẩn phụ
Đây là bài toán (Ɗ, ƒ) chuẩn tắc nên được đưa vào bảng đơn hình để giải
∆j ≤ 0 ∀ j = 1 6, xopt = (4, 5, 0, 0, 0, 11) và ƒmin = -11 Vậy nghiệm của bài toán gốc là xopt = (4, 5, 0, 0) và ƒmin = -11
Nếu các giá trị min/max đạt được tại nhiều vị trí thì chọn tùy ý một vị trí bất
kì trong số đó Thông thường chọn chỉ số nhỏ nhất
2.2.6 Bài toán ẩn giả
Cho bài toán (Ɗ, ƒ) dạng chính tắc:
= ( = 1 )
≥ 0 ( = 1 ) Trong đó: bi ≥ 0 (i = 1 m)
Trang 15Xét bài toán:
≥ 0 ( = 1 + ) Với M là số dương khá lớn (M ⟶ ∞)
Bài toán này gọi là bài toán mở rộng của bài toán trên, hay bài toán M Với bài toán M có ngay phương án cơ bản ban đầu với xn+i (i = 1, ) là các ẩn cơ bản
Dùng thuật toán đơn hình để giải
xn+i gọi là các ẩn giả
Sau khi giải bài toán M có được quan hệ giữa bài toán M và bài toán (Ɗ, ƒ)
như sau:
- Nếu bài toán M vô nghiệm thì bài toán (Ɗ, ƒ) vô nghiệm
- Nếu bài toán M có nghiệm = (x1, x2, …, xn, 0, , 0) thì X = (x1, x2,
…, xn) là nghiệm của bài toán (Ɗ, ƒ)
- Nếu bài toán M có nghiệm = (x1, x2, …, xn+m) và ∃ xm+n > 0 thì bài toán (Ɗ, ƒ) vô nghiệm
Tiến trình giải bài toán M là loại dần các ẩn giả ra khỏi tập ẩn cơ bản cho
đến khi loại tất cả là bắt đầu giải bài toán gốc Nên từ đó có thể không cần tính cho các cột ẩn giả Nếu cuối cùng không loại được các ẩn giả mà nhận giá trị 0 thì bài toán gốc cũng có nghiệm
Ở đây giả sử bài toán (Ɗ, ƒ) trong ma trận số liệu A không có vector đơn vị nào Tuy nhiên, chỉ cẩn thêm một số (<m) ẩn giả cho đủ m vector đơn vị
Ví dụ 2.5:
Trang 16Dạng chính tắc tương đương:
Trong đó x4, x5 là hai ẩn phụ
Bài toán chính tắc trên cần thêm hai ẩn giả để đưa về bài toán chuẩn tắc là
x6, x7
Bài toán M tương ứng :
Đây là bài toán dạng chuẩn tắc nên ta đưa vào bảng đơn hình để giải
Trang 17Nghiệm của bài toán là = ( , , , 0, 0, 0, 0), ẩn giả đã bị loại từ bảng 3 Nghiệm của bài toán gốc chính tắc là X = ( , , , 0, 0), với x4, x5 là ẩn phụ, nên
có nghiệm của bài toán gốc là Xopt = ( , , , 0, 0) và ƒmax =
Trang 18PHẦN III: NỘI DUNG
3.1 Tổ chức lưu trữ bài toán
Để lưu trữ được bài toán này, những biến sau đã được sử dụng:
Code:
int num_unknown, num_equation, target;
float fx[3][max+1], a[max+1][max+4], Fx[3][max+1], condition[max+1], Cj[3] [max+1], Xj[max+1];
int Aj[max+1];
Trong đó:
- Hàm mục tiêu được lưu trữ bằng ba biến là target, num_unknown và fx[3][max+1], num_unknown là số ẩn của bài toán; target là mục tiêu, nó nhận giá trị -1 nếu hàm mục tiêu tiến tới min và nhận giá trị 1 nếu hàm mục tiêu tiến tới max; fx[3][max+1] là biến dùng để lưu trữ
hệ số của hàm mục tiêu với dòng thứ nhất của ma trận để lưu lại những
hệ số tương ứng trong hàm mục tiêu, dòng thứ hai dùng để đánh dấu những ẩn có hệ số là M sau khi chuẩn hóa
- Những điều kiện ràng buộc của bài toán được lưu trữ bằng các biến num_equation và a[max+1][max+4], num_equation là số ràng buộc của bài toán; a[max+1][max+4] là biến dùng để lưu trữ các ràng buộc của bài toán, a[i][j] (i = 1, num_equation, j =
1, num_unknown) ứng với a[i][j] của bài toán, a[i][num_unknown +1] dùng để lưu dấu của ràng buộc và a[i][num_unknown+2] ứng với giá trị bj của bài toán
- Những ràng buộc về dấu của biến được lưu trữ bằng biến condition[max+1] với giá trị của condition[i] ứng với ràng buộc về dấu của biến xi tương ứng
Trang 19- Fx[3][max+1], Cj[3] [max+1], Xj[max+1], Aj[max+1] lần lượt ứng với ∆, Cj, Xj, Aj khi tiến hành các bước giải bài toán
3.2 Đọc dữ liệu từ tệp
Dữ liệu được nhập từ file Sinplex.inp với cấu trúc:
- Dòng đầu tiên là số nguyên dương num_unknown ứng với số ẩn của bài toán
- Dòng thứ hai gồm num_unknown + 1 con số với num_unknown con
số đầu tiên kiểu thực ứng với hệ số của các ẩn tương ứng trong hàm mục tiêu, số nguyên dương thứ num_unknown + 1 ứng với dấu của hàm mục tiêu, bằng 1 nếu hàm mục tiêu tiến tới max và bằng -1 nếu hàm mục tiêu tiến tới min
- Dòng thứ ba chứa số nguyên dương num_equation ứng với số điều kiện ràng buộc của bài toán
- num_equation dòng tiếp theo, mối dòng gồm num_unknown + 2 con số ứng với các hàm mục tiêu Trong đó, num_unknown số thực đầu tiên ứng với hệ số các phần tử thuộc vế trái của hàm mục tiêu; con
số nguyên thứ num_unknown + 1 ứng với dấu của ràng buộc, nó nhận giá trị:
+ -2 nếu dấu là <
+ -1 nếu dấu là <=
+ 1 nếu dấu là >=
+ 2 nếu dấu là >
Con số thực thứ num_unknown + 2 ứng với giá trị của bj tương ứng
- num_unknown dòng tiếp theo, mỗi dòng chứa một con số nguyên ứng với ràng buộc về dấu của biến tương ứng:
Trang 20Nếu file Simplex.inp không tồn tại hoặc giá trị num_unknown quá lớn so với số lượng quy định của chương trình thì thông báo cho người dùng và kết thúc chương trình
Ví dụ: Để nhập dữ liệu cho bải toán
ƒ(x) = x1 – 2x2 + 3x3 – 2x4 → min
2 − 3 + = 4 + + = 5
Trang 21fx[2][i]=0;
}
fscanf(f,"%d",&target);
fscanf(f,"%d",&num_equation);
for (int i=1; i<=num_equation; i++)
for (int j=1; j<=num_unknown+2; j++)
3.3 Chuẩn hóa bài toán
Công việc này sẽ được hàm int standardize() thực hiện với các công việc sau:
Duyệt lần lượt điều kiện xác định của các ẩn, nếu xj không ràng buộc về dấu hoặc có ràng buộc nhưng là dấu âm thì ta thay bằng hiệu hai ẩn không âm Nghĩa
Trang 22condition[i]=1;
condition[i+1]=1;
}
- Duyệt lần lượt các ràng buộc của bài toán, nếu ràng buộc nào mà bj
có dấu âm thì ta nhân cả hai vế với -1 để có bj > 0
Trang 24for (int i=1; i<=num_equation; i++)
Hàm này thực hiện các công việc: duyệt từ 1 tới num_unknown, nếu phần
tử a[n][i] có hệ số bằng 1 thì kiểm tra tất cả các phần tử a[j][i] (j ≠ n) xem hệ số
có bằng 0 không, nếu đúng thì trả về giá trị của cột i tương ứng, nếu sai thì tiếp tục duyệt Khi đã duyệt hết tất cả các phần tử ở dòng n mà không tìm thấy phần
tử thứ n của ma trận đơn vị thì trả về giá trị 0
Trang 253.5 Khởi tạo giá trị
Sau khi dữ liệu được nhập vào, hàm void initial() sẽ được gọi tới để tính giá trị các biến ở bảng đơn hình thứ nhất để tạo dữ liệu cho các bước lặp sau
Các công việc được thực hiện báo gồm:
- Chuẩn hóa bài toán bằng cách gọi hàm standardize()
- Tìm ma trận đơn vị, phương án cơ sở và hệ số của ẩn ứng với cơ sở trong hàm mục tiêu