1. Trang chủ
  2. » Công Nghệ Thông Tin

phương pháp nhánh cận và các bài toán tối ưu

11 8,9K 25
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 11
Dung lượng 372,96 KB

Nội dung

phương pháp nhánh cận,bài toán cái tui,bài toán người đóng thùng,bài toán người du lịch

1 CHƯƠNG 5 BÀI TOÁN TỐI ƯU 1. Giới thiệu bài toán Chọn cấu hình tối ưu trong số các cấu hình thoả mãn các điều kiện cho trước gọi là bài toán tối ưu. Dạng tổng quát của bài toán như sau: Hàm f(x) gọi là hàm mục tiêu, mỗi phần tử x  D gọi là một phương án (phương án chính là cấu hình thoả mãn các điều kiện cho trước), tập D gọi là tập các phương án. Phương án x *  D sao cho f(x * ) nhỏ nhất (hay lớn nhất) gọi là phương án tối ưu, khi đó giá trị f * =f(x * ) gọi là giá trị tối ưu. 2. Một số bài toán tối ưu 2.1 Bài toán người du lịch Có n thành phố, một người du lịch xuất phát từ một thành phố, muốn đi qua n-1 thành phố còn lại, mỗi tp một lần, rồi quay về tp xuất phát. Biết chi phí từ tp i đến tp j là C i,j , hãy tìm hành trình có tổng chi phí là nhỏ nhất. HD: Gọi x 1 là tp xp, mỗi hành trình có dạng: x 1 -> x 2 ->… ->x n . Đặt f(x)=C x1,x2 + C x2,x3 +…+ C xn,x1 gọi D={(x 2 , .,x n )| (x 2 , .,x n ) là hoán vị của tập {1,2,…,n}\{x 1 }} . Bài toán người du lịch có thể phát biểu ở dạng bài toán tối ưu như sau: Tìm min { f(x) | x=(x 2 , .,x n ) D}. NX: ta có (n-1)! hành trình cần phải xét để tìm ra hành trình tối ưu! 2.2 Bài toán cái túi Có n vật, vật thứ i có trọng lượng là a i giá trị sử dụng là c i . Một nhà thám hiểm có cái túi với khả năng chứa trọng lượng tối đa là b. Hỏi nhà thám hiểm cần đem theo các vật nào để tổng giá trị sử dụng là lớn nhất? HD: Một phương án có dạng x=(x 1 , x 2 ,…, x n ) với x i =1 là đồ vật thứ i được đem theo x i =0 là đồ vật thứ i không được đem theo. Với phương án x giá trị đồ vật mang theo là f(x)= 1 n i i i c x   tổng trọng lượng đồ vật mang theo là g(x)= 1 n i i i a x   . Gọi D={(x 1 , x 2 ,…, x n )| x i =0 hoặc x i =1}, bài toán cái túi có thể phát biểu ở dạng bài toán tối ưu như sau: Tìm max { f(x) |g(x)  b, x  D}. NX: ta có 2 n phương án cần xét để tìm ra phương án tối ưu. 2.3 Bài toán phân công Có n công việc n thợ, mỗi thợ thực hiện 1 công việc 1 công việc chỉ do 1 thợ thực hiện. Gọi C ij là chi phí cần trả để thợ i hoàn thành cv j. Hãy tìm cách thuê sao cho tổng chi phí thuê là nhỏ nhất. Tìm giá trị nhỏ nhất (hay lớn nhất) của hàm f(x); với x D (D là tập hữu hạn) 2 HD: Gọi P={1,2,…,m} là tập các chỉ số của thợ. Tập các phương án là: D={x=(x 1 ,…,x n ) | x là một hoán vị của P}. Chi phí với phương án x D là: F(x)=C x1,1 +…+C xn,n . Bài toán phân công có thể phát biểu ở dạng bài toán tối ưu như sau: Tìm min { F(x) | x D}. 2.4 Bài toán cho thuê máy Một ông chủ có một cái máy để cho thuê. Đầu tháng ông ta nhận được yêu cầu thuê máy của m khách hàng. Mỗi khách hàng i sẽ cho biết tập N i các ngày trong tháng cần sử dụng máy. Ông chủ có quyền từ chối hoặc nếu nhận thì phải bố trí máy phục vụ khách hàng i đúng những ngày mà khách hàng này yêu cầu. Hỏi rằng ông chủ phải tiếp nhận các yêu cầu của khách như thế nào để cho tổng số ngày sử dụng máy là lớn nhất? Biết rằng mỗi ngày máy chỉ có thể cho 1 người thuê. HD: Gọi P={1,2,…,m} là tập chỉ số khách hàng yêu cầu thuê máy. Khi đó tập các phương án cho thuê máy là: D={K P : N i N j =  , i,,j K, i  j } tổng số ngày sử dụng theo phương án KD là F(K)= k k K N   . Bài toán cho thuê máy có thể phát biểu ở dạng bài toán tối ưu như sau: Tìm max {F(K)| KD}. 2.5 Bài toán đóng thùng Tìm cách xếp n vật có trọng lượng là w 1 ,…,w n (w i  b) vào các cái thùng sao cho số thùng sử dụng là ít nhất. Biết rằng mỗi thùng có khả năng chứa một trọng lượng là b. HD: Gọi P={1,2,…,n} là chỉ số các vật N i P là tập các chỉ số của vật được cất vào hộp i. D={x=(N 1 ,…,N m ) | N i P; bw i Nj j    ; nN m i i   1 || ; N i  N j =  , i  j , } là tập các phương án Bài toán đóng thùng có thể phát biểu ở dạng bài toán tối ưu như sau: Tìm min {f(x)=m| xD } 3. Các thuật toán duyệt 3.1 Thuật toán duyệt toàn bộ Dùng các thuật toán liệt kê, duyệt tất cả các phương án có thể xảy ra, tính giá trị hàm mục tiêu của mỗi phương án. So sánh các giá trị hàm mục tiêu để tìm ra phương án tối ưu. Nếu số phương án qúa nhiều thì thuật toán sẽ thực thi rất chậm đến nỗi không thể chấp nhận được. Ta cần tận dụng những thông tin đã tìm được để loại bỏ bớt những phương án không tối ưu dẫn đến thuật toán nhánh cận. 3.2 Thuật toán nhánh cận 3.2.1 Ý tưởng: Sử dụng thuật toán quay lui dùng hàm “cận dưới” g để loại bớt các phương án không thể là phương án tối ưu. 3 - Xét phương án hoàn chỉnh x =(x 1 ,…,x k ,…x n ); a=(a 1 ,…,a k ) với a i =x i , gọi là phương án bộ phận cấp k (k n). - G/s đã xây dựng được hàm g (hàm tính cận dưới) như sau: với mọi phương án bộ phận (a 1 ,…,a k ) với mọi k=1,…,n g(a 1 , …,a k )  min {f(x): x  D, x 1 = a 1 , …,x k = a k } Gọi x là phương án hoàn chỉnh tốt nhất hiện có f = f( x ) gọi là kỷ lục hiện tại. Nếu một phương án bộ phận a=(a 1 ,…,a k ) nào đó mà có g(a 1 , …,a k ) > f  f < g(a 1 , …,a k )  min {f(x): x  D, x 1 = a 1 , …,x k = a k }  các phương án hoàn chỉnh x=(x 1 ,…,x n ) phát triển từ phương án bộ phận a=(a 1 , …,a k ) đều có hàm mục tiêu f(x) > kỷ lục hiện tại f , nên ta loại tất cả các phương án hoàn chỉnh x phát triển từ phương án bộ phận a. * Ghi chú: Nếu bài toán tối ưu là tìm max {f(x): x  D} thì cần xây dựng được hàm g (hàm tính cận trên) sao cho: g(a 1 , …,a k )  max {f(x): x  D, x 1 = a 1 , …,x k = a k } nếu một phương án bộ phận a=(a 1 ,…,a k ) nào đó mà có g(a 1 , …,a k ) < f  f > g(a 1 , …,a k ) max {f(x): x  D, x 1 = a 1 , …,x k = a k }  các phương án hoàn chỉnh x=(x 1 ,…,x n ) phát triển từ phương án bộ phận a=(a 1 , …,a k ) đều có hàm mục tiêu f(x) < kỷ lục f , nên ta loại tất cả các phương án hoàn chỉnh x phát triển từ phương án bộ phận a. 3.2.2 Cài đặt: (tìm min) void Try(int i) //xac dinh x i { for (xét tất cả các kn j của x i ) { if (chấp nhận kn j ) //nếu chấp nhận khả năng j { ghi nhận việc đã chọn kn j // (*) :lệnh này có thể không có x i = kn j ; //lưu kn j vào x i if (i==n) //nếu đã xác định đủ n thành phần cập nhật kỷ lục nếu kỷ lục mới nhỏ hơn kỷ lục hiện tại; else if (g(a 1 , …,a k )  f ) //tim max thi g(a 1 , …,a k )  f Try(i+1); // xác định x i+1 ghi nhận việc bỏ chọn knj // lệnh này không có nếu (*) không có } } } void nhanhcan() { 4 f = + ; //nếu biết một phương án x nào đó thì có thể đặt f = f( x ).Nếu tìm max thì f = -  Try(1); //tim x 1 } * Nhận xét: - Nếu không kiểm tra điều kiện g(a 1 , …,a k )  f thì thuật toán trở thành thuật toán duyệt toàn bộ các phương án. - Hàm g(x) cần xây dựng đơn giản để việc tính g được nhanh chóng 3.2.3 Giải một số bài toán bằng thuật toán nhánh cận: a) Bài toán cái túi: Có n loại đồ vật, loại đồ vật thứ i có trọng lượng a i giá trị sử dụng c i . Cần chất các đồ vật này vào một cái túi có trọng lượng là b, sao cho tổng giá trị sử dụng của các đồ vật chất trong túi là lớn nhất. HD: Gọi x i là số vật loại i được cất vào túi. D={x =(x 1 ,…,x n ): 1 n i i i a x   b, x i Z + , i=1,…,n} là tập các phương án. Hàm mục tiêu f(x) = 1 n i i i c x   . Bài toán cái túi có dạng: Tìm max {f(x) :x  D} (1) Không giảm tính tổng quát, ta giả thiết các loại đồ vật được đánh số sao cho thoả mãn: c 1 /a 1  c 2 /a 2  … c n /a n Mệnh đề: Phương án tối ưu của (1) với biến liên tục (x i R + ) là x =(x 1 ,x 2 ,…,x n )=(b/a 1 ,0,…,0) giá trị tối ưu là (c 1 /a 1 )b. Chứng minh: c i /a i  c 1 /a 1 , i=1,…,n  c i x i  (c 1 /a 1 )a i x i  f(x) = 1 n i i i c x    1 1 1 ( / ) n i i i c a a x   =(c 1 /a 1 ) 1 n i i i a x    (c 1 /a 1 )b Bây giờ giả sử đã có phương án bộ phận cấp k: (u 1 , …,u k ). Khi đó gía trị sử dụng trong túi là: k  =c 1 u 1 +…+c k u k trọng lượng còn lại của cái túi là b k = b – a 1 u 1 – a 2 u 2 – … – a k u k . Ta có: max {f(x)= 1 n i i i c x   : x  D, x i = u i , i = 1,…,k} = max { k  + 1 n i i i k c x    : 1 n i i i k a x    b k , x i Z + }  k  + max { 1 n i i i k c x    : 1 n i i i k a x    b k , x i 0} 5 = k  + (c k+1 /a k+1 )b k  chọn hàm tính cận trên là g(x)= k  + (c k+1 /a k+1 )b k * Nhận xét: a k+1 x k+1 +….+ a n x n  b k  x k+1 +(a k+2 x k+2 ….+ a n x n )/a k+1  b k / a k+1  x k+1 b k / a k+1 các khả năng có thể chọn cho x k+1 là 0,…, b k / a k+1 các khả năng có thể chọn cho x k là 0,…, b k-1 / a k Do mệnh đề đã cm, ta chọn các khả năng theo thứ tự giảm dần. Ví dụ: Giải bài toán cái túi sau: Tìm max của : f(x)=10x 1 +5x 2 +3x 3 +6x 4 Thoả điều kiện: 5x 1 +3x 2 +2x 3 +4x 4  8 x i  Z + HD: gọi  giá trị của các đồ vật trong túi, w là trọng lượng còn lại, g=  + (c k+1 /a k+1 )w 10/5 5/3 3/2 6/4 f = -  *k=1: x 1  b 0 / a 1 = 8/5 x 1 =0,1 x 1 =1 :  =10, w=8-5=3, g=10+5/3 x 3=15 x 1 =0 :  =0, w=8, g=0+5/3 x 8=40/3 < f =15 (*) nên loại *k=2: x 2  b 1 / a 2 = 3/3=1 x 2 =0,1 x 2 =1 :  =15, w=3-3=0, g=15+3/2 x 0=15 x 2 =0 :  =10, w=3, g=10+3/2 x 3=29/2=14.5< f =15 (*) nên loại *k=3: x 3  b 2 / a 3 = 0/2=0  x 3 =0 x 3 =0 :  =15, w=0, g=15+6/4 x 0=15 *k=4: x 4  b 3 / a 4 = 0/4=0  x 4 =0 x 4 =0 :  =15, w=0  pán x=(1,1,0,0)  f =15 (*) * Cài đặt /* Bai toan cai tui */ #include <stdio.h> #include <conio.h> //c[i]: gia tri su dung cua vat loai i, a[i]: trong luong vat loai i float c[100],a[100]; //x: chua phuong an trung gian, xopt: phuong an toi uu int x[100],xopt[100]; 6 //d: so thu tu cua loai i la d[i] int d[100],n;//n la so loai vat /*w la trong luong toi da tui co the chua, weight: trong luong hien tai cua tui fopt: gia tri hien tai lon nhat cua tui cost: gia tri hien tai */ float w,weight,fopt,cost; /* file caitui.dat co dang sau: 4 8 //n=4, b=8 5 3 2 4 //a: trong luong moi loai vat 10 5 3 6 //c: gia tri moi loai vat */ void ReadFile() { FILE *fin; int i; if ((fin = fopen("caitui.dat", "rt"))== NULL) { printf("Khong tim thay file caitui.dat.\n"); return ; } fscanf(fin,"%d%f",&n,&w); for (i=0;i<n;i++) fscanf(fin,"%f",&a[i]); for (i=0;i<n;i++) fscanf(fin,"%f",&c[i]); fclose(fin); printf("\nSo loai vat:%d",n); printf("\nTrong luong cai tui:%0.0f",w); printf("\nTrong luong cac loai vat:"); for (i=0;i<n;i++) printf("%0.0f ",a[i]); printf("\nGia tri cac loai vat:"); for (i=0;i<n;i++) printf("%0.0f ",c[i]); } void Init() { int i,j,k,t; fopt=0;// gia tri lon nhat =0 weight=0;//trong luong ban dau cua tui=0; for (i=0; i<n; i++) d[i]=i+1; for (i=0; i<n-1; i++) { k=i; for (j=i+1; j<n; j++) if (c[j]/a[j]>c[k]/a[k]) k=j; 7 if (k!=i) { t=a[i];a[i]=a[k];a[k]=t; t=c[i];c[i]=c[k];c[k]=t; t=d[i];d[i]=d[k];d[k]=t; } } } void KyLuc() { if (cost>fopt) { for (int i=0; i<n; i++) { xopt[i]=x[i]; fopt=cost; } } } void Try(int i) { int j,t; t=(w-weight)/a[i];//w: suc chua cua tui for (j=t; j>=0; j--) { x[i]=j; weight=weight+a[i]*x[i];//weight:trong luong tui cost=cost+c[i]*x[i];//cost: gia tri tui if (i==n-1) KyLuc(); else if (cost+c[i+1]*(w-weight)/a[i+1]>fopt) Try(i+1); weight=weight-a[i]*x[i]; cost=cost-c[i]*x[i]; } } void InKq() { printf("\nTong gia tri do vat:%0.0f",fopt); for (int i=0; i<n; i++) printf("\nso luong do vat loai %d la %d",d[i],xopt[i]); } void main() { clrscr(); ReadFile(); 8 Init(); Try(0); InKq(); getch(); } b) Bài toán người du lịch: Cố định thành phố xuất phát là T 1 . Bài toán người du lịch trở thành bài toán : Tìm min { f(x 2 ,…,x n )=c[1,x 2 ]+c[x 2 ,x 3 ]+…+c[x n-1 ,x n ]+c[x n ,1] | (x 2 ,…,x n ) là hoán vị của {2,…,n} } G/s đã đi qua k thành phố: T 1 --> T(a 1 ) -->… -->T(a k ) ứng với phương án bộ phận (a 1 , a 2 ,…, a k ) chi phí cho hành trình bộ phận này là  =c[1,a 2 ]+c[a 2 ,a 3 ]+…+c[a k-1 ,a k ]. Để phát triển thành hành trình đầy đủ, còn phải đi qua n-k+1 đoạn đường nữa. Ta có:  +(n-k+1)c min  min {f(x): x 1 = a 1 , …,x k = a k } nên có thể chọn g(a 1 ,…,a k )=  +(n-k+1)c min Ví dụ: giải bài toán người du lịch với ma trận chi phí sau: C= HD: c min =3. Gọi  chi phí hành trình bộ phận, cận dưới g=  + 3(n-k+1) f = +  *k=2: x 2 =2,3,4,5 x 2 =2 :  =3, g=3+(5-2+1) x 3=15 x 2 =3 :  =14, g=14+(5-2+1) x 3=26 x 2 =4 :  =18, g=18+(5-2+1) x 3=30 x 2 =5 :  =15, g=15+(5-2+1) x 3=27 vv… * Cài đặt /* bai toan nguoi du lich */ #include <stdio.h> #include <conio.h> #include <values.h> 0 3 14 18 15 3 0 4 22 20 17 9 0 16 4 6 2 7 0 12 9 15 11 5 0 9 int n;//so thanh pho int c[100][100];//ma tran chi phi int cmin;//chi phi nho nhat trong ma tran chi phi int tp[100];//tp[i]=0:tp i da di qua, =1 chua di qua int cost;//chi phi bo phan int fopt; //gia tri ky luc, gia tri cuoi cung la gia tri toi uu int x[100];//la mot phuong an int xopt[100];//la phuong an toi uu void ReadFile() { FILE *fin; int i,j; if ((fin = fopen("dulich.dat", "rt"))== NULL) { printf("Khong tim thay file dulich.dat.\n"); return ; } //doc so thanh pho fscanf(fin,"%d",&n); //doc ma tran chi phi for (i=0;i<n;i++) for (j=0;j<n;j++) fscanf(fin,"%d",&c[i][j]); fclose(fin); //xuat thong tin de kiem tra printf("\nSo thanh pho:%d",n); printf("\nMa tran chi phi:"); for (i=0;i<n;i++) { printf("\n"); for (j=0;j<n;j++) printf("%3d",c[i][j]); } } void Init() { int i,j; cmin=MAXINT;//so kieu int lon nhat for (i=0;i<n;i++) { tp[i]=1;//tat ca tp i deu chua di qua for (j=0;j<n;j++)//tim cmin if ( (i!=j)&&(c[i][j]<cmin)) cmin=c[i][j]; } 10 fopt=MAXINT;//ky luc ban dau cost=0;//chi phi bo phan x[0]=0;//tp bat dau di la tp 0 } void CNKL() //cap nhat ky luc { int i,s; s=cost+c[x[n-1]][x[0]];//cong them chi phi tro ve tp dau if (s<fopt)//neu chi phi cua hanh trinh nay < ky luc { fopt=s;//ghi nhan ky luc moi for (i=0;i<n;i++) xopt[i]=x[i]; //ghi nhan hanh trinh moi } } void Try(int i) { int j; for (j=1;j<n;j++) if (tp[j]) { x[i]=j; tp[j]=0;//tp j da duoc chon cost=cost+c[x[i-1]][x[i]];//chi phi bo phan if (i==n-1) CNKL(); else if (cost+(n-i+1)*cmin<=fopt) Try(i+1); tp[j]=1; cost=cost-c[x[i-1]][x[i]]; } } void Result() { int i; printf("\n\nChi phi nho nhat:%d",fopt); printf("\nHanh trinh co chi phi nho nhat:\n"); for (i=0;i<n;i++) printf ("%d -> ",xopt[i]+1); printf ("%d",xopt[0]+1); } void main() { clrscr(); ReadFile(); Init(); Try(1); . x 2 =2,3,4 ,5 x 2 =2 :  =3, g=3+ ( 5- 2+1) x 3= 15 x 2 =3 :  =14, g=14+ ( 5- 2+1) x 3=26 x 2 =4 :  =18, g=18+ ( 5- 2+1) x 3=30 x 2 =5 :  = 15, g= 15+ ( 5- 2+1) x 3=27. 3/2 6/4 f = -  *k=1: x 1  b 0 / a 1 = 8 /5 x 1 =0,1 x 1 =1 :  =10, w=8 -5 = 3, g=10 +5/ 3 x 3= 15 x 1 =0 :  =0, w=8, g=0 +5/ 3 x 8=40/3 < f = 15 (*) nên loại

Ngày đăng: 26/08/2013, 21:04

TỪ KHÓA LIÊN QUAN

w