Công việc này được đảm nhiểm bởi hàm int solve(). Hàm này sẽ trả về giá trị 1 nếu như có thể tiếp tục biến đổi được bảng đơn hình và trả về giá trị 0 nếu không thể tiếp tục biến đổi bảng đơn hình. Hàm này thực hiện các công việc sau:
- Tìm cột xoay c bằng cách tìm ra giá trị Δi lớn hơn 0 và lớn nhất nếu như hàm mục tiêu tiến tới min hoặc nhỏ hơn 0 và nhỏ nhất nếu hàm mục tiêu tiến tới max.
Code:
for (int i=1; i<=num_unknown; i++)
if (target==-1&&(Fx[2][i]>0||(Fx[2][i]==0&&Fx[1][i]>0)))
{
c=i;
for (int j=c+1; j<=num_unknown; j++)
if ((Fx[2][j]>Fx[2][c])||(Fx[2][j]==Fx[2][c]&&Fx[1][j]>Fx [1][c])) c=j; break; } else if (target==1&&(Fx[2][i]<0||(Fx[2][i]==0&&(Fx[1][i]<0)))) { c=i;
for (int j=c+1; j<=num_unknown; j++)
if ((Fx[2][j]<Fx[2][c])||(Fx[2][j]==Fx[2][c]&&(Fx[1][j]<Fx
[1][c])))
c=j;
break;
}
- Tìm dòng xoay r bằng cách tìm phần tử a[i][c] lớn hơn 0 và có giá trị Xj / a[i][c] là lớn nhất.
Code:
for (int i=1;i<=num_equation;i++) if (a[i][c]>0)
---
SVTH: Bùi Hữu Giáp 25 GVHD: Trịnh Thị Phú
r=i;
for (int j=r;j<=num_equation;j++)
if (a[j][c]>0&&(float)Xj[j]/a[j][c]<(float)Xj[r]/a[r][c])
r=j;
break;
}
- Nếu không tìm được phần tử trục thì trả về giá trị 0.
- Lưu lại giá trị phần tử trục vào biến ars và lưu lại giá trị các phận tử thuộc trục xoay của bảng trước vào một nơi an toàn (cột thứ num_unknown+3 của mảng a).
Code:
float arc=a[r][c];
for (int i=1; i<=num_equation; i++)
a[i][num_unknown+3]=a[i][Aj[r]];
- Chia dòng xoay cho giá trị ars. Code:
Xj[r]=(float)Xj[r]/arc;
for (int i=1; i<=num_unknown; i++)
if (i!=c)
a[r][i]=(float)a[r][i]/arc;
- Cập nhật lại giá trị của các phần tử Xj và aij khác trong bảng. Code:
for (int i=1;i<=num_equation;i++)
for (int j=1;j<=num_unknown;j++)
if (i!=r&&j!=c)
a[i][j]=a[i][j]-a[i][c]*a[r][j];
for (int i=1;i<=num_equation;i++)
if (i!=r)
Xj[i]=Xj[i]-a[i][c]*Xj[r];
- Cập nhất lại giá trị của cột xoay Aj, Cj và giá trị của hàm F(x). Code:
for (int i=1; i<=num_equation; i++)
---
SVTH: Bùi Hữu Giáp 26 GVHD: Trịnh Thị Phú
Aj[r]=c;
Cj[1][r]=fx[1][c]; Cj[2][r]=fx[2][c];
Fx[1][0]=Fx[1][0]-Fx[1][c]*Xj[r];
- Tính lại các giá trị của ∆. Code:
for (int i=1;i<=num_unknown;i++)
if (i!=c) { Fx[1][i]=Fx[1][i]-Fx[1][c]*a[r][i]; Fx[2][i]=Fx[2][i]-Fx[2][c]*a[r][i]; } Fx[1][c]=0; Fx[2][c]=0; 3.8.Các hàm khác trong chương trình
Ngoài các hàm chính tham gia trực tiếp vào công việc giải bài toán được đề cập ở trên, còn một số hàm phục khác cũng gián tiếp tham gia vào công công việc chung này:
- Hàm float m_abs(float x) dùng để tính giá trị tuyệt đối của một số thực x nào đó, kết quả được trả về trực tiếp thông qua lời gọi hàm.
- Hàm void p_problem(int k) dùng để in ra màn hình một bài toán quy hoạch tuyến tính theo đúng với trong toán học. Đối số k dùng để đưa vào thông tin bài toán có được chuẩn hóa từ chưa phải dạng chính tắc sang dạng chính tắc không.
- Hàm void p_table() dùng để in bảng đơn hình ra màn hình với hai dạng đó là bài toán có ẩn phụ và bài toán không có ẩn phụ.
3.9.Thực hiện công việc giải bài toán.
Công việc này được thực hiện sau khi nhập và chuẩn hóa bài toán và ngay trong hàm main() bằng một vòng while với tư tưởng:
- Nếu phương án hiện tại đã là tối ưu thì đưa ra kết quả của bài toán và kết thúc.
---
SVTH: Bùi Hữu Giáp 27 GVHD: Trịnh Thị Phú
- Nếu bài toán không có phương án tối ưu thì đưa ra thông báo bài toán không có phương án tối ưu và kết thúc
- Nếu không rơi vào hai trường hợp trên thì kiểm tra xem có tiếp tục biến đổi bảng đơn hình được không, nếu được thì tiếp tục biến đổi bảng đơn hình, nếu không thì thông báo là không thể tiếp tục biến đổi và kết thúc. Code: while (1) { int kq=result(); if (kq==1) {
// Đưa ra kết quả của bài toán và kết thúc
}
else if (kq==0)
{
// Kết luận không có phương án tối ưu và kết thúc
}
else if (kq==-1)
{
// Nếu tìm được biến đưa vào thì tiếp tục biến đổi bảng đơn hình.
// Ngược lại thì thông báo không tim được biến đưa vào và kết thúc.
}
---
SVTH: Bùi Hữu Giáp 28 GVHD: Trịnh Thị Phú
PHẦN IV: KẾT LUẬN
4.1.Tóm tắt kết quả nghiên cứu
Trong môn Tối ưu hóa, thuật toán đơn hình là một trong những thuật toán quan trọng nhất. Nếu chưa học thuật toán đơn hình, có thể coi như chúng ta chưa được họn môn Tối ưu hóa. Vì tầm quan trọng như vậy, dưới sự hướng dẫn của cô Trịnh Thị Phú, tôi đã thực hiện đề tài “Cài đặt thuật toán đơn hình bằng ngôn
ngữ C” nhằm cho ra đời 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.
Đề tài của tôi chỉ là tiêu biểu của một trong số rất nhiều những cách thức tiếp cận vấn đề “Cài đặt thuật toán đơn hình bằng ngôn ngữ C” thực sự có hiệu quả, 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 thuận tiện khi giải các bài toán quy hoạch tuyến tính bằng phương pháp đơn hình. Tuy có sự hạn hẹp cả về mặt thời gian vả trình độ nhưng với đề tài này, tôi đã cố gắng hết sức để có thể hoàn thành các yêu cầu đặt ra, bao gồm:
- Khai báo các biến để lưu trữ bài toán. - Tổ chức đọc giữ liệu từ tệp.
- Chuẩn hóa bài toán.
- 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.
4.2.Đề xuất và hướng phát triển
Đề tài này có thể sử dụng làm tài liệu tham khảo phục vụ cho sinh viên ngành công nghệ thông tin học tập các môn học như: lập trình cấu trúc với C, cấu trúc dữ liệu và giải thuật, tối ưu hóa, … Ngoài ra, chương trình có thể được sử dụng
---
SVTH: Bùi Hữu Giáp 29 GVHD: Trịnh Thị Phú
để kiểm tra tính đúng đắn của những bài làm thủ công một cách chính xác và thuận tiện.
Đề tài này có thể được phát triển theo các hướng như sau:
- Xây dựng chương trình để giải các bài toán thực tế như bài toán vận tải, bài toán cái túi,…
---
SVTH: Bùi Hữu Giáp 30 GVHD: Trịnh Thị Phú
TÀI LIỆU THAM KHẢO
- Lê Minh Hoàng, Giải thuật & lập trình – NXB Đại học sư phạm Hà Nội.
- Nguyễn Đức Nghĩa, Quy hoạch tuyến tính – NXB Giáo dục năm 1997.