Khái niệm về thuật toán và độ phức tạp thuật toán

Một phần của tài liệu (LUẬN văn THẠC sĩ) cơ sở của thuật toán di truyền và ứng dụng đối với một số bài toán lớp NP (Trang 32)

2.1.1 Khái niệm về thuật toán

Trong tin học, người ta quan niệm bài toán là một công việc nào đó muốn máy tính thực hiện. Khi dùng máy tính để giải bài toán, ta cần quan tâm tới 2 vấn đề: Dữ liệu cần được đưa vào máy tính (Input) là gì và cần lấy ra (Output) thông tin gì? Nói một cách khác, cho một bài toán trong tin học là việc mô tả rõ Input và Output của bài toán.

Khác với toán học, việc giải một bài toán Tin học là việc đi tìm một lời giải cụ thể, tường minh để đưa ra Output của bài toán dựa trên Input đã cho. Việc chỉ ra một cách tìm Output của bài toán gọi là một thuật toán.

Định nghĩa: Thuật toán là một dãy hữu hạn các thao tác được sắp xếp theo một trình tự nhất định để sau khi thực hiện dãy các thao tác đó, từ input ta có output cần tìm.

Trong lĩnh vực máy tính, cụm từ “thuật toán” đôi khi người ta dùng bằng một từ khác: “giải thuật”.

2.1.2. Các yêu cầu của thuật toán

Thuật toán phải đảm bảo được các yêu cầu sau đây:

- Tính xác định: Các bước của thuật toán phải được trình bày rõ ràng, mạch lạc, đảm bảo cho người đọc chỉ hiểu theo một nghĩa duy nhất.

dụng máy tính kết hợp giữa các ngôn ngữ lập trình để thể hiện thuật toán trong một khoảng thời gian chấp nhận được.

- Tính dừng: Nếu dữ liệu vào thỏa mãn điều kiện đầu vào thì thuật toán phải kết thúc và cho ra kết quả sau một số hữu hạn bước.

- Tính đúng đắn: Thuật toán phải cho kết quả chính xác và thể hiện đúng đắn trên cơ sở toán học.

- Tính tổng quan: Thuật toán phải đúng với mọi bộ dữ liệu đầu vào. - Tính tối ưu: Thuật toán phải có chi phí về không gian bộ nhớ ít nhất và chạy trong thời gian nhanh nhất.

2.2. Độ phức tạp của thuật toán

2.2.1. Chi phí phải trả cho một quá trình tính toán

Chi phí phải trả cho một quá trình tính toán bao gồm chi phí về không gian (bộ nhớ - số ô nhớ cần sử dụng trong quá trình tính toán) và chi phí về thời gian (thời gian cần sử dụng cho một quá trình tính toán).

Nếu cho một thuật toán A. Thuật toán này thực hiện trên bộ dữ liệu e. Khi đó kí hiệu

+ LA(e) là giá phải trả về không gian + TA(e) là giá phải trả về thời gian.

Khi đó ta có các khái niệm về chi phí phải trả trong các trường hợp như sau:

 Chi phí phải trả trong trường hợp xấu nhất: là chi phí trong trường hợp ứng Input là xấu nhất đối với bài toán

 Chi phí phải trả trung bình: là tổng số các chi phí khác nhau ứng với các bộ số liệu chia cho tổng số số bộ số liệu.

 Chi phí phải trả tiệm cận: là biểu thức biểu diễn tốc độ tăng của chi phí thực tế phải trả. Nó có giá trị tiệm cận với chi phí thực tế.

Nhận xét: Ngày nay do sự phát triển không ngừng của khoa học công nghệ kỹ thuật điện tử nên chi phí về bộ nhớ không còn là vấn đề cần thiết phải bàn tới mà ta chỉ quan tâm tới chi phí phải trả về thời gian thực hiện giải

thuật. Từ đây ta chỉ xét đến thời gian thực hiện giải thuật T(n), hay đó chính là độ phức tạp của thuật toán.

2.2.2. Độ phức tạp của thuật toán

Định nghĩa 1: Một hàm f(n) được xác định là O(g(n)), kí hiệu f(n) = O(g(n)) và được gọi là có cấp g(n) nếu tồn tại các hằng số c và n0 sao cho f(n) ≤ c.g(n) khi n ≥ n0.

Định nghĩa 2: Cho thuật toán T với bộ dữ liệu đầu vào có kích thước n. Nếu số phép toán cơ bản để thực hiện việc biến đổi Input(T) thành Output(T) là f(n). Khi đó ta gọi O(T)=f(n) là độ phức tạp của thuật toán T.

Chú ý: Khái niệm về độ phức tạp của thuật toán trên được hiểu theo nghĩa khái niệm về vô cùng lớn khi n tiến ra vô cùng.

Thông thường các hàm thể hiện độ phức tạp tính toán của giải thuật có dạng: O(log2n), O(n), O(nlog2n), O(n2), O(n3), O(2n), O(n!), O(nn).

Dưới đây là một số hàm số hay dùng để ký hiệu độ phức tạp tính toán và bảng giá trị của chúng để tiện theo dõi sự tăng của hàm theo đối số n.

log2n N nlog2n n2 n3 2n 0 1 0 1 1 2 1 2 2 4 8 4 2 4 8 16 64 16 3 8 24 64 512 256 4 16 64 256 4096 65536 5 32 160 1024 32768 2.147.483.648

Bảng 2.1: Bảng giá trị độ phức tạp tính toán của các hàm số

Các hàm như 2n, nn được gọi là hàm loại mũ, ngoài ra còn có hàm n! Và một số hàm khác có độ phức tạp lớn hơn các hàm mũ. Một giải thuật mà thời gian thực hiện của nó có cấp là các hàm loại mũ thì tốc độ rất chậm. Các như n3, n2, nlog2n, log2n được gọi là các hàm loại đa thức. Giải thuật với thời

gian thực hiện có cấp hàm đa thức thì thường hiệu quả và chấp nhận được.

2.2.3. Các qui tắc xác định độ phức tạp thuật toán

Quy tắc cộng: Giả sử thuật toán T gồm 2 đoạn chương trình T1 và T2 thực hiện nối tiếp nhau Khi đó O(T)=O(T1)+O(T2).

Quy tắc nhân: Giả sử thuật toán T gồm 2 đoạn chương trình T1 và T2 trong đó T2 được lồng trong T1. Khi đó O(T)=O(T1).O(T2).

Quy tắc tổng quát:

- Thời gian thực hiện mỗi câu lệnh Gán, Read, Write là O(1).

- Thời gian thực hiện mỗi chuỗi tuần tự các câu lệnh được tính theo quy tắc cộng

- Thời gian thực hiện vòng lặp được tính là tổng trên tất cả số lần lặp thời gian thực hiện thân vòng lặp. Nếu thời gian thực hiện thân vòng lặp là hằng số thì thời gian thực hiện vòng lặp là tích của số lần lặp với thời gian thực hiện thân vòng lặp.

2.3. Vấn đề phân lớp các bài toán dựa trên độ phức tạp thuật toán.

Khi cho một bài toán, có hai khả năng xảy ra là: bài toán không giải được hoặc bài toán giải được. Trong thực tế có rất nhiều các bài toán không thể giải trong thời gian chấp nhận được. Ví dụ bài toán treo (Halting Problem) nổi tiếng của Turing không thể giải bất kỳ máy tính nào, bất kể cung cấp bao nhiêu thời gian. Cũng có các bài toán có thể giải được, nhưng không phải trong thời gian đa thức O(nk) với một hằng k. Nói chung, ta xem các bài toán có thể giải được bằng các thuật toán thời gian đa thức là “dễ trị”, và các bài toán yêu cầu thời gian siêu đa thức là “khó trị”.

Vì độ phức tạp giải thuật đối với mỗi bài toán là khác nhau thông qua thời gian, trên cơ sở đó các bài toán cũng được phân chia thành các lớp thông qua độ phức tạp thuật toán.

2.3.1. Lớp bài toán P

Lớp bài toán P (Polynomial time – thời gian đa thức) là lớp các bài toán dễ, có thể giải được bằng thuật toán đơn định đa thức.

2.3.2. Lớp NP

Lớp NP (Nondeterministic Polynomial – thời gian đa thức không tất định) là lớp các bài toán có thể giải được bằng các thuật toán không đơn định đa thức.

Nhận xét: Nhiều giả thiết đặt ra rằng liệu lớp P và lớp NP có đồng nhất với nhau hay không? Điều đó đang còn là vấn đề mở chưa được làm sáng tỏ. Bởi trong NP vẫn tồn tại lớp các bài toán không giải được bằng các thuật toán đa thức, đó chính là sự có mặt của lớp NPC. Như vậy, chúng ta đang chấp nhận P NP.

2.3.3. Lớp NPC

Định nghĩa 1: (Khái niệm dẫn về được): Bài toán B được gọi là dẫn về được bài toán A một cách đa thức nếu có một thuật toán đơn định đa thức để giải bài toán A thì cũng có một thuật toán đơn định đa thức để giải bài toán B. ký hiệu B A. Khi đó bài toán A khó hơn bài toán B hay còn gọi B dễ hơn A hay B là trường hợp riêng của A.

Quan hệ  có tính bắc cầu: B C, C  A  B  A.

Định nghĩa 2: (NP hard): Bài toán A được gọi là NP – khó nếu L A với L  NP.

Định nghĩa 3: (Bài toán NP đầy đủ): Bài toán A được gọi là NP đầy đủ nếu A là NP khó và đồng thời A thuộc NP

Định nghĩa 4: Lớp NPC là lớp các bài toán NP đầy đủ, có độ phức tạp hàm mũ. Qua đó cho thấy: PNPC = Ø.

Hình 5: minh họa các lớp P, NP, NPC dưới dạng tập hợp.

Hình 2.1: Các lớp P, NP và NPC

NP P

2.4 Một số mô hình bài toán lớp NP 2.4.1 Mô hình bài toán xếp ba lô 2.4.1 Mô hình bài toán xếp ba lô

Mô hình bài toán xếp ba lô là một trong những mô hình quan trọng trong lý thuyết thuật toán. Chúng ta xét 2 mô hình cơ bản của bài toán:

2.4.1.1 Bài toánxếp ba lô 0-1

Input: + Cho n đồ vật, đồ vật thứ i có thể tích là a(i) + Cho 1 ba lô có thể tích b

Output: Hãy xác định nhóm đồ vật để đặt vừa khít ba lô

Nhận xét:

+ Bài toán trên có thể xác định lời giải chính xác bằng thuật toàn duyệt toàn bộ theo tư tưởng như sau: Hãy duyệt mọi tổ hợp của các đồ vật, ứng với mỗi tổ hợp (i1,i2,..,ik) thử điều kiện a(i1)+a(i2)+…+a(ik)=b để xác định nghiệm đúng. Khi đó số phương án được duyệt chính bằng

1 2 1

... n n 2n

n n n n

C +C + C - +C ; tức là chúng ta có độ phức tạp của thuật toán là hàm mũ.

+ Chúng ta có thể giải bài toán bằng thuật toán không đơn định đa thức như sau: sử dụng hàm: CHOICE(0,1):là hàm chọn các đồ vật. Khi đó bài toán được đưa về bài toán sau đây

Liệu có tồn tại tập chỉ số T{1,2,.. ,n}thỏa mãn ai B

T i    . Khi đó bài toán được giải bằng thuật toán sau đây:

For i:=1 to n do xi:= CHOICE({0,1}); if   n i i ia x 1

=B then TRUE else FALSE

Thuật toán trở thành thuật toán không đơn định đa thức với độ phức tạp O(n).

Hãy xác định nhóm đồ vật đặt trong balo sao cho phần thừa còn lại là ít nhất”. Khi đó việc giải bài toán cũng được thực hiện tương tự, tuy nhiên chúng ta phải đưa thêm hàm mục tiêu f=b-(a(i1)+a(i2)+…+a(ik)). Khi đó phương án cần xác định là phương án thỏa mãn f đạt giá trị nhỏ nhất (f>=0).

2.4.1.2 Bài toán xếp ba lô mở rộng

Input: + Cho n đồ vật, đồ vật thứ i có thể tích là ai, có giá trị là pi + Cho 1 ba lô có thể tích b

Output: Hãy xác định nhóm đồ vật thỏa mãn: tổng thể tích không vượt quá ba lô đồng thời tổng giá trị là lớn nhất

Nhận xét:

+ Bài toán trên có thể xác định lời giải chính xác bằng thuật toàn duyệt toàn bộ theo tư tưởng như sau: Kí hiệu (x1,x2,…,xn) là một phương án lựa chọn các đồ vật với xi {0,1}. Khi đó hãy duyệt mọi phương án (x1,x2,…,xn), ứng với mỗi phương án xác định điều kiện

1 1 2 2 ... n n

a x + a x + + a x £ b. Nếu thỏa mãn thì xác định tiếp giá trị hàm mục tiêu f X( ) = p x1 1 + p x2 2 + ...+ p xn n từ đó xác định phương án tốt nhất.

Hiển nhiên bài toán đưa về bài toán duyệt mọi dãy nhị phân có độ dài n với độ phức tạp hàm mũ.

Thuật toán giải được mô tả như sau: using namespace std;

int X[N],A[N],b,P[N],n,fmax,Xluu[N]; void input()

{

cout<<"Nhap so do vat: ";cin>>n; cout<<"Nhap the tich ba lo: ";cin>>b;

cout<<"Nhap the tich cac do vat: ";printf("\n");

cout<<"Nhap gia tri cac do vat : ";printf("\n");

for (int i=1;i<=n;i++) {cout<<"Do vat: "<<i<<" ";cin>>P[i];} fmax=0;

}

void output() { int f,T;

f=0;T=0;

for (int i=1;i<=n;i++) {T=T+X[i]*A[i];f=f+X[i]*P[i];} if ((T<=b)&(f>fmax))

{ fmax=f;

for (int i=1;i<=n;i++) Xluu[i]=X[i];} }

void Try(int k) {

int j;

for (j=0;j<=1;j++)

{ X[k]=j;if (k==n) output();else Try(k+1);} }

int main() { input();

Try(1);

cout<<"Phuong an toi uu: ";

for (int i=1;i<=n;i++) cout<<Xluu[i]<<" "; cout<<"Gia tri toi uu fmax= "<<fmax; }

+ Tương tự, chúng ta có thể giải bài toán bằng thuật toán không đơn định đa thức như sau: sử dụng hàm: CHOICE(0,1): là hàm chọn các đồ vật. Khi đó bài toán được đưa về bài toán sau đây

Liệu có tồn tại tập chỉ số T{1,2,.. ,n} thỏa mãn    n i i ix B a 1 và   n i i ix p 1

đạt max. Khi đó bài toán được giải bằng thuật toán sau đây:

For i:=1 to n do xi:= CHOICE({0,1}); if   n i i ia x 1

<=B then <xác đinh f> else FALSE

Thuật toán trở thành thuật toán không đơn định đa thức với độ phức tạp O(n).

+ Bài toán Knaspack có thể giải bằng thuật toán GA với cấu trúc gen là dãy nhị phân và toán tử lai ghép đa điểm hoặc lại ghép mặt nạ (Xem phụ lục)

2.4.2 Bài toán quân cờ Domino 2.4.2.1 Mô tả bài toán 2.4.2.1 Mô tả bài toán

Định nghĩa 1: Một quân bài Domino là một bộ (a,b) trong đó a là số hàng trên, b là số hàng dưới

a B

Định nghĩa 2: Phép lật quân được hiểu là một phép biến đổi bộ (a,b) thành bộ (b,a)

Bài toán:

Input: Cho n quân bài Domino (a1,b1),(a2,b2),...(an,bn) xếp thành một hàng ngang. Output: Hãy xác định các phép lật quân để sao cho độ chênh lệnh giữa tổng các số hàng trên so với tổng các số hàng dưới đạt giá trị nhỏ nhất.

a1 a2 .... an-1 An

b1 b2 bn-1 Bn

Phân tích

+ Kí hiệu một phương án lật quân là một bộ X=(x1,x2,…,xn) trong đó x(i)=1 tức là lật quân thứ i, x(i)=0 tức là không lật quân thứ i. Khi đó để tìm phương án lật quân tối ưu, chúng ta có thể sử dụng thuật toàn duyệt toàn bộ tất cả các phương án từ đó xác định phương án có độ chênh lệch nhỏ nhất. Kí hiệu hàm mục tiêu 1 ( ) x (b ) n i i i i f x a = = å -

Khi đó sử dụng thuật toán duyệt tất cả các dãy nhị phân độ dài n bằng thuật toán quay lui, ta mô tả thuật toán tìm lời giải chính xác của bài toán trên như sau:

using namespace std;

int X[N],A[N],B[N],n,fmin,Xluu[N]; void swap(int &a,int &b)

{ int tg;tg=a;a=b;b=tg;} void input()

{ int tren,duoi;

tren=0;duoi=0;

cout<<"Nhap so quan bai: ";cin>>n;

cout<<"Nhap gia tri hang duoi: ";printf("\n");

for (int i=1;i<=n;i++) {cin>>A[i];duoi=duoi+A[i];} cout<<"Nhap gia tri hang tren : ";printf("\n");

for (int i=1;i<=n;i++) { cin>>B[i];tren=tren+B[i];}

fmin=abs(tren-duoi); cout<<"Do chenh ban dau "<<fmin<<" "; }

void output()

tren=0;duoi=0;

for (int i=1;i<=n;i++) if (X[i]==1) swap(A[i],B[i]); for (int i=1;i<=n;i++) {tren=tren+B[i];duoi=duoi+A[i];} f=abs(tren-duoi);

if (f<fmin){fmin=f;for (int i=1;i<=n;i++) Xluu[i]=X[i];} }

void Try(int k) {int j;

for (j=0;j<=1;j++)

{ X[k]=j;if (k==n) output();else Try(k+1);} }

int main() { input();

Try(1);

cout<<"Phuong an lat quan toi uu: ";

for (int i=1;i<=n;i++) cout<<Xluu[i]<<" "; cout<<"do chenh be nhat= "<<fmin;

}

Hiển nhiên thuật toán trên có độ phức tạp O(2n).

+ Ta có thể sử dụng thuật toán quy hoạch động để giải bài toán trên như sau: Xây dựng mảng Wi là độ chênh lệch giữa phần trên và phần dưới của quân bài thứ i. Gọi C(i,j) là số các phép lật nhỏ nhất với các quân cờ từ 1 đến i, để hàng trên có tổng là j. Khi đó ta có công thức quy hoạch động:

C(i,j) = min {C(i-1, j-Tren(i)), C(i-1, Duoi(i))+1}.

Từ các C(i,j) ta dễ dàng tìm ra chênh lệch tối thiểu bằng thuật toán quy hoạch động xác định mảng C. Tuy nhiên thuật toán trên cần đòi hỏi số ô nhớ là rất lớn nếu số n là lớn

Có thể thấy rằng mô hình bài toán trên cũng là bài toán thuộc lớp NP.

+ Bài toán Domino có thể giải bằng thuật toán GA với cấu trúc gen là dãy nhị phân và toán tử lai ghép đa điểm hoặc lại ghép mặt nạ (Xem phụ lục)

2.4.3 Mô hình bài toán TSP

Bài toán: Người giao hàng cần đi giao hàng tại n địa điểm. Người giao hàng xuất phát từ một địa điểm xuất phát, đi qua các địa điểm khác để giao hàng và trở về địa điểm ban đầu trong đó yêu cầu mỗi địa điểm chỉ đến một lần. Hãy tìm một chu trình sao cho tổng quãng đường đi là nhỏ nhất.

Định lý 1: Bài toán TSP là NP đầy đủ. (Xem [1]) Nhận xét:

+ Bài toán trên có thể tìm được nghiệm chính xác bằng cách sử dụng chiến lược duyệt toàn bộ các chu trình trong đồ thị bằng thuật toán quay lui từ đó suy ra nghiệm tối ưu. Tuy nhiên độ phức tạp của thuật toán là O(n!) nên

Một phần của tài liệu (LUẬN văn THẠC sĩ) cơ sở của thuật toán di truyền và ứng dụng đối với một số bài toán lớp NP (Trang 32)

Tải bản đầy đủ (PDF)

(70 trang)