Để đi tìm lời giải chính xác cho bài tốn TSP khơng cịn cách nào khác ngồi việc chúng ta phải duyệt tất cả các lời giải cĩ thể, tuy nhiên số lượng này là quá lớn (= n!), trong đĩ rất lãng phí các lời giải khơng cần thiết. Cách tiếp cận hiệu quả nhất từ trước tới nay trong chiến lược này đĩ chính là thuật tốn nhánh cận(cĩ thể cắt các nhánh ở các lời giải khơng cần thiết) * Tính cận và phân nhánh - Tính cận: Cốđịnh thành phố 1 • Tìm cực tiểu của hàm : f(x2, x3, . . , xn) = c[1,x2] + c[x2,x3] + ... + c[xn,1] => min x2, x3, . . , xn là hốn vị của các số 2, 3, …, n
• Giả sử cĩ phương án bộ phận (u1,u2, …, uk)
– Chi phí phải trả là : σ = c[1,u2] + c[u2,u3] + ... + c[uk-1, uk]
– Cận dưới là : g (u1,u2, …, uk) = σ + (n-k+1)*cmin
- Thuật tốn phân nhánh dựa vào thuật tốn liệt kê các hốn vị của n phần tử{1, 2, ....,
n}. Nghĩa là nếu bài tốn con của ta cĩ lời giải bộ phận là c1, c2, ...., ci. Thì các bài tốn con sinh ra cĩ lời giải bộ phận (c1, c2, ...., ci-1+1), ..., (c1, c2, ...., n – k + i).
* Các lớp xây dựng cho bài tốn TSP
Như chúng ta đã biết, bài tốn yêu cầu tìm giải pháp tốt nhất cho người du lịch sao cho chi đi qua mỗi thành phố một lần và tổng chi phí quãng đường là nhỏ nhất. Dưới đây là khai báo lớp Problem cho bài tốn TSP:
• Lớp Problem lưu giữ số lượng thành phố và ma trận giá trị giữa các thành phố
class Problem { private:
Number N; // Số lượng thành phố trong bài tốn Matrix c; // Ma trận giá trị giữa các đỉnh public:
Problem (); ...
};
• Lớp bài tốn con diễn tả một bài tốn bộ phận. Một bài tốn con được xác định bởi các dữ liệu sau : đỉnh đầu iV, đỉnh cuối eV của lời giải bộ phận, và cận dưới costứng với lời giải bộ phận sol .
private:
unsigned iV, /// đỉnh đầu tiên eV, /// đỉnh kết thúc trong hành trình cost; /// gía trị thật
Tset visitedSet; /// các thành phốđến thăm Solution sol; /// giá trị tốt nhất hiện thơi
public:
SubProblem ();
... };
Lớp bài tốn con phải cung cấp các hàm chính sau :
- InitSubProblem(pbm) : sinh ra bài tốn con ban đầu với iV = 0;
eV = 0; cost = 0;
- Các hàm tính cận dưới (LowerBound), tính cận trên (UpperBound), phân nhánh(Branch). • Lớp Solution lưu giữ lời giải hiện tại Class Solution() { ……. }
* Trên mơi trường tuần tự
Khi thực thi trên mơi trường tuần tự người dùng chỉ cần gọi phương thức run() của lớp Solver_Seq: void Solver_Seq::run() { if (dir == Minimize) { minimizing(); } else { maximizing(); } }
* Trên mơi trường song song
Tương tự, khi đĩ phương thức run() của lớp Solver_Lan sẽ được gọi:
void Solver_Lan::run() {
minimizing(); }