3
MC L C
DANH MC B NG ................................................................................................... 5
DANH MC HÌNH NH .......................................................................................... 5
CHƯƠNG 1: CƠ S THUYT ........................................................................... 6
1.1. Thu t toán nhánh c n ........................................................................................ 6
1.2. Nguyên lý .......................................................................................................... 6
1.3. Ưu đi ợc đim và như m ca thut toán nhánh cn .......................................... 6
1.3.2. Nhược đim ................................................................................................ 7
1.4. c bưc chính ca thut toán .......................................................................... 7
1.5. Mô t thu t toán ................................................................................................ 7
1.6. Áp d ng gi i bài toán ........................................................................................ 9
CHƯƠNG 2: PHÂN TÍCH I ƯU HÓA L- XÂY DNG THUT TOÁN T A
CH N Đ V T TRONG BÀI TOÁN BALO (KNAPSACK) ............................... 14
2.1. Mô t bài toán ................................................................................................. 14
2.1.1. Xây d ng bài toán th c thế ...................................................................... 14
2.1.2. Phát bi i d ng t ng quátu bài toán dư .................................................. 14
2.2. Xây d ng thu t toán ........................................................................................ 15
2.2.2. Xây d ng gi mã ...................................................................................... 16
2.3. Ví d minh h tìm ki m nhánh c n trên và thu t toán backtrack ............ 18 a v ế
CHƯƠNG 3: CÀI ĐT THUT TOÁN BNG NGÔN NG LP TRÌNH
PYTHON ................................................................................................................... 19
3.1. i đt thut toán ............................................................................................ 19
3.1.1. Cài đt class Item ..................................................................................... 19
3.1.4. Cài đt thut toán backtrack .................................................................... 20
3.2. Ki m th ......................................................................................................... 24
3.2.1. D li u vào u đ ........................................................................................ 24
4
3.2.2. D li u ra u đ .......................................................................................... 25
3.2.3. Ki các ch a thu t toánm th c năng c ................................................... 25
3.3. Đánh giá và so sánh ........................................................................................ 27
3.3.2. So sánh th i gian th n thu t toán c hi .................................................... 28
TNG KT ............................................................................................................... 30
ĐÁNH GIÁ NI B ................................................................................................ 31
TÀI LI U THAM KH O ......................................................................................... 32
5
DANH M C B NG
Bng 1. B ng d li u vào. .................................................................................. 25 u đ
Bng 2. B i bng đánh giá n i. ................................................................................. 31
DANH M C HÌNH NH
nh 1. Xây dng cây tìm kiếm cho bài toán cái túi. ................................................. 11
nh 2. Xây dng cây tìm ki i du lếm cho bài toán ngư ch. ..................................... 12
nh 3. Ví d minh h a tìm kiếm nhánh trên và thut toán backtrack. ..................... 18
6
CHƯƠNG 1: CƠ S LÝ THUYT
1.1. Thu t toán nhánh c n
Thut toán nhánh c n là m y u gi i bài toán t i t trong các phương pháp ch ế
ưu t ợp. Tư tưởng cơ b h n ca nó là trong quá trình tìm kiếm ta phân hoch các
phương án c p con như các nút, loa bài toán ra thành hai hay nhiu t i b nhng
nhánh mà ta bi t ch c ch n là không ch ế a phương án ti ưu.
K thu t nhánh c n phát tri n t ý tưng c a thu t toán quay lui. Thay vì duy t
tt c ng h các trư p, n n m t vếu ta đế trí mà giá tr c a hàm m c tiêu t i đó và các
đim v sau chc chn không tt nht thì quay li luôn.
1.2. Nguyên lý
Nhánh (Branch): Thu t toán chia nh bài toán l n thành các bài toán con nh
hơn, t i nhánh đc là to ra các nhánh trong quá trình gii. M i din cho mt trng
thái ho c m t t p con c a không gian tìm ki m. Quá trình này ti p t n khi ế ế c cho đế
đ t đư c mt gii pháp h p l hoc không th tìm thêm nhánh con nào na.
Cn (Bound): Cn là bưc quan tr ng trong thu t toán nhánh c n, giúp lo i b
các nhánh không c n thi t trong quá trình tìm ki m. M i nhánh s có m t giá tr "c n" ế ế
tính toán đưc, và thu t toán ch ti p t c tìm ki m trong các nhánh mà giá tr c n c a ế ế
chúng h a h n mang l i gi i pháp t t hơn so v i pháp đã tìm được trưc đó. Nếi gi u
giá tr c n c a m t nhánh không th t t hơn gii pháp hi n t i, nhánh đó s b loi b .
1.3. Ưu đim và nhưc đim ca thut toán nhánh cn
1.3.1. Ưu đim
- m ki m gi i pháp tế i ưu: Thut toán nhánh cn luôn đ o tìm đưm b c gii
pháp t u không gian tìm ki c duy t trong nhi ưu nế ếm đư t đy đ. Đây là m ng ưu
đi m quan trng nht khi so v i các thut toán tham lam (Greedy) ho c x p x .
- Gi m thi u không gian tìm ki m: Thu t toán s d c l c nhánh lo i ế ng bư đ
b các nhánh không kh thi ho c không có ti m năng mang li gi i pháp t t hơn, giúp
gim đáng k s lưng trng thái cn kim tra.
- Linh ho t v i nhi u bài toán: Thu t toán có th áp d ng cho nhi u bài toán
ti ưu hóa r c như bài toán cái balo, bài toán đi đưi r ng ngn nht (Traveling
Salesman Problem), bài toán phân ho ch, bài toán l p l ch và nhi u bài toán khác.
- Kh n d ng chi c c n: S d ng các k thu t tính toán c n hi u năng t ến lư
qu (upper bound - c n trên ho c lower bound - c n dưi) giúp nâng cao hi u qu c a
thut toán và gi m th i gian tính toán.
- Kh năng dng sớm: Khi tìm đưc m t gi i pháp mà giá tr c n c a các nhánh
còn l i không th t i pháp hi n t i, thu t toán có th d ng s m mà không t hơn gi
cn duy t toàn b không gian.
7
1.3.2. Nhược đim
- T n kém v b nh : Do c t t c các nhánh và thông tin liên quan n lưu tr
(như tr ớ, đ t đng thái, giá tr cn), thut toán có th yêu cu rt nhiu b nh c bi i
vi các bài toán có không gian tìm ki m lế n.
- Đ ph c t p tính toán cao: M c dù thu t toán lo i b đưc nhi u nhánh không
cn thi t, vi c tính toán c n và qu n lý các nhánh v n tiêu t n th i gian và tài nguyên, ế
đc bit vi các bài toán có kích thưc ln.
- Ph thu c vào chi c c n: Hi u qu c a thu t toán ph thu c r t nhi u ến lư
vào cách tính toán c n trên ho c c n dưi. Nếu cn không chính xác ho c không ch t
ch, thu t toán có th ph i duy t qua nhi u nhánh không c n thi t, làm gi m hi u qu . ế
- Không phù h p v i không gian tìm ki m quá l n: Khi không gian tìm ki m ế ế
quá r ng ho c không th d dàng tính toán c n, thu t toán có th tr nên ch m và
kém hi u qu so v p x . ới các phương pháp x
- Khó khăn trong trin khai: Vi c tri n khai thu t toán nhánh c n yêu c u hi u
rõ bài toán và các k thu t tính toán c n, điu này có th ph c t p hơn so vi các thu t
toán tham lam ho c quy ho ng. ch đ
1.4. Các bưc chính ca thut toán
- Kh i t o: B u v i m t gi u (có th là gi i pháp x p x ho c t đ i pháp ban đ
gii pháp hp l nh t), tính toán c i (ho c c n trên) c c n dư a bài toán. Đây là bư
khi t o không gian tìm ki m. ế
- Chia nhánh (Branching): T o ra các nhánh con b ng cách chia bài toán l n
thành các bài toán con nh n không gian tìm ki m. M i nhánh có hơn, t đó phát tri ế
th đi di n cho m t t p con c a các l n ho ng thái. a ch c các tr
- nh c n (Bounding): V i m i nhánh, tính toán giá tr c ng là c n n (thư
dưới đ n trên đ i đa). Cậi vi bài toán ti thiu hoc c i vi bài toán t n này là mt
ư c lư ng c a giá tr t i ưu trong nhánh đó.
- L i b c n c c nhánh (Pruning): Lo các nhánh mà giá tr a chúng không th
tt hơn gi năng tìm ra m t hơn. Đii pháp hin ti hoc không có kh t gii pháp t u
này giúp gi m thi u không gian tìm ki m và ti t ki m th i gian. ế ế
- Ti n hành tìm ki m: Ti p t c m r ng các nhánh còn l n khi tìm ế ế ế i cho đế
đưc gii pháp t kii ưu hoc không còn nhánh nào đ m tra.
1.5. Mô t thu t toán
Ta s mô t thu t toán trên mô hình bài toán t ng quát sau: i ưu t
min { f(x) : x D },
Trong đó D là tp h u h n ph n t .
Gi
thi t r ng t c mô t ế p D đư như sau:
8
D={x = (x , x , ... , x )
1 2 n
A × A × ... × A : x tho mãn nh ch t P},
1 2 n
Vi A , A , ... , A là các t p h u h n, còn P là tính ch -các
1 2 n
t cho trên tích Đ
A
1
× A
2
... . × × A
n
Vi gi thi t v t p D nêu trên, chúng ta có th s d ng thu ế t toán quay lui đ
lit kê các phương án ca bài toán. Trong quá trình li t kê theo thu t toán quay lui, ta
s xây d ng d n các thành ph n c t b g m k thành ph n (a , a , a , a phương án. M
1 2 3
i là phương án b, a ) xu
k
t hin trong trong quá trình thut toán s g phn cp k.
Thut toán nhánh c n có th áp d gi ng đ i bài toán đ ếu như có tht ra n tìm
đưc m nh trên trên tt hàm g xác đ p tt c phương án b phn ca bài toán tha
mãn b ng tht đ c sau:
g(a
1
, a , ... , a
2 k
) min {f(x): x D, x = a , i = 1, 2, ..., k}
i i
(*)
Bt đ c (*) có nghĩa là giá tr i phương án bng th ca hàm g t phn (a , a ,
1 2
, a
k
) là không vưt quá giá tr nh nh t c a hàm m c tiêu c a bài toán trên t p con
các phương án.
D(a
1
, a , a )={ x
2
,
k
D : x =a , i = 1, 2, ... , k}
1 i
Hay nói m t cách khác, g(a , a , a ) là c i c a giá tr hàm m c tiêu
1 2
,
k
n dư
trên t p D(a , a ). Vì l
1 2
, , a
k
đó, hàm g đưc gi là hàm c i và giá tr g(a , a , n dư
1 2
đ , a c g
k
) đư i là c i cn dư a tp D(a , a ). Do có th
1 2
, , a
k
ng nht tp D(a ,
1
a
2
, , a
k
) v ph n (a , a i giá tr g(a , a , aới phương án b
1 2
, , a
k
), nên ta cũng g
1 2 3,
, a ) là c i c ph
k
n dư a phương án b n (a , a ).
1 2
, , a
k
Gi s xét cách s d gi m b đã có hàm g. Ta ng hàm này đ t kh ng i lư
duyt trong quá trình duy t t t c t toán quay lui. Trong quá các phương án theo thu
trình li t s a bài toán. G i t kê các phương án có th đã thu đưc m phương án c x
là phương án v các phương án đã tìm đưi giá tr hàm mc tiêu nh nht trong s c,
kí hi u = f( f
x
). Ta s g i x
là phương án t đã t nh t hi n có, còn là k l c. Gi s f
có f
, khi đó nếu:
g(a
1
, a ) > ,
2
, , a
k
f󰋀
Thì t b ng th c (*) suy ra t đ
f󰋀 < g(a , a
1 2
, , a
k
) min {f(x): x D : x = a , i= 1, 2, ... , k}
1 i
Vì th tế p con các phương án y c a bài toán D (a
1
, a
2
, , a
k
) chc ch n không
cha phương án ti ưu. Trong trưng hp này ta không cn tiếp tc phát trin các
phương án b các phương án phn ( nói cách khác là ta có th(a
1
, a ),
2
, , a
k
loi b
trong t p D i quá trình tìm ki m. (a
1
, a )
2
, , a
k
kh ế
9
1.6. Áp d ng gi i bài toán
1.6.1. Bài toán cái túi
Đưa ra gi thi t r ng có n lo v t và s v t m i lo i là không h n ế i đ lượng đ
ch biế. Khi đó ta có mô hình bài toán cái túi ến nguyên sau đây: n loi đ t, đ v
vt th j có tr ng a và giá tr s d ng là c (j = 1, 2, ... , n). C n ch v t ng lư
j
j
t các đ
này vào m t cái túi có tr ng là b sao cho t ng giá tr s d ng c v t ng lư a các đ
cht trong túi là l n nh t.
Mô hình c a bài toán s có d ng như sau:
Tìm:
𝑓 = 𝑚𝑎𝑥
{𝑓
(
𝑥
)
= 𝑐
𝑗
𝑥
𝑗
𝑛
𝑗=1
; 𝑎
𝑗
𝑥
𝑗
𝑛
𝑗=1
𝑏, 𝑥
𝑗
𝑍
+
, 𝑗 = 1, 2, . .. , 𝑛}(1)
Trong đó Z
+
là t p các s nguyên không âm.
𝐷 = {𝑥 = (𝑥
1
, 𝑥
2
, . .. ,𝑥
𝑛
; 𝑎
𝑗
𝑥
𝑗
𝑛
𝑗=1
𝑏, 𝑥
𝑗
𝑍
+
,𝑗 = 1, 2, . .. , 𝑛}
Không gian t ng quát ta gi thi t r v sao cho b t ế ng các đ t được đánh s
đng thc sau đưc tho mãn:
𝑐
1
𝑎
1
𝑐
2
𝑎
2
. . .
𝑐
𝑛
𝑎
𝑛
(2)
Đ ti p t c xây d ng hàm tính c i, cùng v i bài toán cái túi (1) ta xét bài ế n dư
toán cái túi bi n liên tế c sau:
m:
𝑔 = 𝑚𝑎𝑥 𝑓
{
(
𝑥
)
=
𝑐
𝑗
𝑥
𝑗
𝑛
𝑗=1
:
𝑎
𝑗
𝑥
𝑗
𝑛
𝑗=1
𝑏, 𝑥
𝑗
0, 𝑗 = 1, 2, . .. , 𝑛} (3)
Mnh đ: Phương án ti ưu ca bài toán (3) là vectơ x
= (x
1
, x
2
, ... , x
n
) v i
các thành ph nh b i công th c: n được xác đ
𝑥
1
=
𝑏
𝑎
1
, 𝑥 𝑥 𝑥
2
=
3
= . . . =
𝑛
= 0.
Và giá tr ti ưu là 𝑔 =
𝑐
1
𝑏
1
𝑎
1
Chng minh: Thc v y, xét x = (x , x , ... , x ) là m ý c a
1 2 n
t phương án tu
bài toán (3). Khi đó t bt đng thc (3) và do x
1
0, ta suy ra:
𝑐
𝑗
𝑥
𝑗
(𝑐
1
/𝑎
1
) 𝑎
𝑗
𝑥
𝑗
, 𝑗 = 1, 2, . .. ,𝑛
Suy ra:
10
𝑐
𝑗
𝑥
𝑗
𝑛
𝑗=1
(𝑐
1 1
/𝑎 )𝑎
𝑗
𝑥
𝑗
𝑛
𝑗=1
= (𝑐
1 1
𝑎 ) 𝑎
𝑗
𝑥
𝑗
𝑛
𝑗=1
(𝑐
1
/𝑎
1
)𝑏 = 𝑔
.
M nh c ch ng minh. đ đư
Bây gi , gi s ph n c p k: (u , u , ... , u ta có phương án b
1 2 k
). Khi đó giá tr
s d ng c v a các đ t đang có trong túi là:
𝜎
𝑘
= 𝑐
1
𝑢
1
+ 𝑐
2 2
𝑢 + . . .+𝑐
𝑘
𝑢
𝑘
Và tr ng còn l i cng lư a túi là:
𝑏
𝑘
= 𝑏 𝑎
1 2 2
𝑢
1
+ 𝑎 𝑢 + . .. +𝑎
𝑘
𝑢
𝑘
.
Ta có:
𝑚𝑎𝑥{ 𝑓(𝑥): 𝑥 𝐷, 𝑥
𝑗
= 𝑢
𝑗
, 𝑗 = 1, 2, . .. , 𝑘}
= 𝑚𝑎𝑥{ 𝜎
𝑘
+ 𝑐
𝑗
𝑥
𝑗
𝑛
𝑗=𝑘+1
: 𝑎
𝑗
𝑥
𝐽
𝑛
𝑗=𝑘+1
𝑏
𝑘
, 𝑥
𝑗
𝑍
+
, 𝑗 = 𝑘 + 1, 𝑘 + 2, . .. , 𝑛}
𝜎
𝑘
+ 𝑚𝑎𝑥{ 𝑐
𝑗
𝑥
𝑗
𝑛
𝑗=𝑘+1
: 𝑎
𝑗
𝑥
𝐽
𝑛
𝑗=𝑘+1
𝑏
𝑘
, 𝑥
𝑗
0, 𝑗 = 𝑘 + 1, 𝑘 + 2, .. . , 𝑛}
(Theo m : Giá tr s h ng th hai là ) nh đ 𝑐 𝑏 /𝑎
𝑘+𝑗 𝑘 𝑘+𝑗
V y ta có th tính c ph n (u , u ) b i công n trên cho phương án b
1 2
, , u
k
thc:
𝑔(𝑢 ,𝑢
1 2
, . . ., 𝑢
𝑘
) = 𝜎
𝑘
+ 𝑐
𝑘+1
𝑏
𝑘
/𝑎
𝑘+1
Chú ý: Khi ti p t c xây d ng thành ph n th k + 1 c i gi i, các giá tr ế a l đ
c cho x ]. Do có k t qu c , khi ch n giá tr cho
k+1
s là 0, 1, , [b
k
a
k+1
ế a mnh đ
x
k+1
ta s duy t các giá tr đ c theo th t gi m d n.
Ví d ng d ng: Gii bài toán cái túi theo thu t toán nhánh c n v a trình bày.
𝑓
(
𝑥
)
= 10𝑥
1
+ 5𝑥
2
+ 3𝑥
3
+ 6𝑥
4
𝑚𝑎𝑥,
5𝑥
1
+ 3𝑥
2
+ 2𝑥
3
+ 4𝑥
4
8,
𝑥
𝑗
𝑍
+
,𝑗 = 1, 2, 3,4.
Gi i:
11
nh 1. Xây dng cây tìm kiếm cho bài toán cái túi.
Quá trình gi c mô t trong cây tìm ki m trong hình trên. Thông i bài toán đư ế
tin v m t phương án b phn trên cây được ghi trong các ô trên hình tương ng theo
th t u tiên là các thành ph n c c v t : đ a phương án, tiếp đến σ là giá tr a các đ
đang ch ng lưt trong túi, w tr ng còn li c a túi và g cn trên.
K t thúc thu t i ế t toán, ta thu được phương án ti ưu là x=(1,1,0,0), và giá tr
ưu là f=15.
1.6.2. Bài toán ngưi du lch
C đnh thành ph xu t phát là 𝑇
1
, bài toán ngưi du l n v bài toán: ch d
Tìm cc ti a hàm: u c
𝑓
(
𝑥 ,𝑥 , ,𝑥
2 3 𝑛
)
= 𝑐 1, 𝑥
[
2
]
+ 𝑐 𝑥 ,𝑥
[
2 3
]
+ + 𝑐 𝑥 , 𝑥
[
𝑛−1 𝑛
]
+ 𝑐
[
𝑥
𝑛
, 1 min,
]
V
i điu ki n:
(
𝑥 ,𝑥 , , 𝑥
2 3 𝑛
)
là hoán v c . a các s 2,3, , 𝑛
Ký hi u:
𝑐
𝑚𝑖𝑛
= min{𝑐 𝑖, 𝑗
[ ]
, 𝑖, 𝑗 = 1,2, , 𝑛, 𝑖 𝑘á𝑐 𝑗} là chi phí đi li nh nh t
gia các thành ph.
Đ có đưc thu t toán nhánh c n gi i bài toán ngưi du l c h t cch, trư ế n đưa
ra cách đánh giá cn dưới cho phương án b ph n. Gi s đang có phương án b ph n
(
𝑢
1
,𝑢
2
, , 𝑢
𝑘
)
. Phương án này tương ng v i hành trình b ph n qua k thành ph :
𝑇
1
𝑇
(
𝑢
2
)
𝑇
(
𝑢
𝑘−1
)
𝑇(𝑢
𝑘
)
Vì vy chi phí ph i tr theo hành trình b ph n này s là:
𝜎 = 𝑐 1, 𝑢
[
2
]
+ 𝑐 , 𝑢
[
𝑢
2 3
]
+ + 𝑐[𝑢 , 𝑢
𝑘−1 𝑘
]
12
Đ phát tri n hành trình b ph , ta còn ph n này thành hành trình đy đ i đi
qua thành ph còn l i r i quay tr l i thành ph𝑛 𝑘 𝑇
1
, t c là còn ph i đi qua 𝑛
𝑘 + 1 đon đưng na. Do chi phí ph i tr cho vi c đi qua mi mt trong s 𝑛 𝑘 +
1 đon đư ếu không ít hơn ng còn li n 𝑐
𝑚𝑖𝑛
, nên c ph n n dưới cho phương án b
(
𝑢
1
,𝑢
2
, , 𝑢
𝑘
)
có th tính theo công th c
𝑔
(
𝑢 ,𝑢 , , 𝑢
1 2 𝑘
)
= 𝜎 + 𝑛 𝑘 + 1 𝑐
( )
𝑚𝑖𝑛
S d ng cách c n dưi va nêu ta có th áp d ng thu t toán nhánh c gi i n đ
bài toán ngưi du lch.
Ví d: Gii bài toán ngư i du l ch v i ma trn chi phí sau:
0
3
14
18
15
3
0
4
22
20
C
=
17
9
0
16
4
6
2
7
0
12
9
15
11
5
0
Ta có . Quá trình th c hi n thu c mô t b i cây tìm ki m 𝑐 = 3
𝑚𝑖𝑛
t toán đư ế
dưi đây:
nh 2. Xây dng cây tìm ki i du lếm cho bài toán ngư ch.
Thông tin v m t b ph ng n trên cây đuc ghi trong các ô trên hình tương
theo th t : đu tiên là các thành phn c a phương án, tiếp đến là chi phí tương theo
hành trình b ph n và g - c i. n dư
13
Kết thúc thu ng t toán, ta thu được phương án ti ưu (1, 2 , 3, 5, 4, 1) tương
vi hành trình:
𝑇
1
𝑇
2
𝑇
3
𝑇
5
𝑇
4
𝑇
1
,
Và chi phí nh nh t là 25.
Hiu qu c t toán nhánh c n ph thu c vào vi ng hàm tính c n a thu c xây d
dưi. Vi c xây d ng hàm tính c i l i ph thu c vào cách xây d ng th t c duy t n dư
các phương án ca bài toán (đư c phân nhánh). Trên đây chúng ta đã c gi là th t
trình bày cách xây d ng c n cho bài toán n i ti ng c a t n dưới khá đơn gi ế i ưu t
hợp. c chương trình được cài đ t toán đó, tuy r t hơn t theo các thu ng làm vic t
nhiu so vi duy t toàn b có th áp d gi i các bài toán v , nhưng cũng ch ng đ i
kích thư i được các bài toán đ i kích thước lơn hơn cc nh. Mun gi t ra v n có
cách đánh giá cn t t hơn.
14
CHƯƠNG 2: PHÂN CH - XÂY DNG THU T TOÁN T I ƯU HÓA
LA CH VN Đ T TRONG BÀI TOÁN BALO (KNAPSACK)
2.1. Mô t bài toán
2.1.1. Xây d ng bài toán th c thế
B n là m t nhà thám hi n b cho m t chuy n có m và đang chu ến đi dài. B
mt balo vi tr ng t n có m t sng lư i đa cho phép là X Kilogram (KG). B đ v t
cn mang theo, mi đ vt có m t tr ng và m t giá tr khác nhau. M c tiêu c a ng lư
bn là t v t ng giá tr mang theo mà không i ưu hóa vic l a ch n đ t đ i đa hóa t
vư t quá tr ng tng lư i đa c a balo.
Yêu c u vào c a bài toán bao g m: u đ
- Tr ng t t s ng lư i đa ca balo: M nguyên dương.
- v t: M t danh sách ch a thông tin v t v Danh sách đ ng đ t như ID đ
vt, tr ng (KG), giá trng lư ti n t ). (đơn v
Yêu c u ra c a bài toán bao g m: u đ
- v c ch n: M t danh sách các ID c a t v c Danh sách đ t đư ng đ t đã đư
chn mang đi.
- T ng giá tr : M t s nguyên th hi n t ng giá tr c a các đ vt đã đưc ch n.
- T ng tr ng: M t s nguyên th hi n t ng tr ng c v t ng lư ng lư a các đ
đã đưc chn.
Nhi m v c th :
- Phát tri n thu t toán: S d ng phương pháp nhánh cn đ tìm ki m gi i pháp ế
ti ưu cho bài toán balo.
- Th c hi n ki m tra ràng bu m b o r ng t ng tr ng c c: Đ ng lư a các đ
vt không vưt quá tr ng t a balo. ng lư i đa c
- In ra k t qu : Hi n th v c ch n, t ng giá tr và t ng ế danh sách các đ t đư
trng lưng.
- Phân tích và so sánh: So sánh k t qu v ế ới các phương pháp khác (nếu có) đ
đánh giá hiu qu ca thut toán nhánh cn.
2.1.2. Phát bi i d ng t ng quát u bài toán dư
T c xây d ng t i , ta có th phát bi i d ng t ng bài toán đư Mc 2.1.1. u dư
quát như sau:
Cho n đ vt khác nhau, trong đó, đ v t th i có mã , tr ng ID
i
ng lư w
i
và giá
tr . B n mang theo m t chi c balo có t i tr ng t , nhi m v v
i
ế i đa là W đt ra là ch n
các đ v cho vào balo sao cho t ng giá tr t đ các đ v t l y đưc là l n nh t có th ?
Yêu c u vào c a bài toán là m t tu đ p tin đnh dng .xlsx, trong đó bao gm:
15
- Tr ng t t s ng lư i đa ca balo: M nguyên dương.
- v t: M t danh sách ch a thông tin v t v Danh sách đ ng đ t như ID đ
vt, tr ng (KG), giá trng lư ti n t ). (đơn v
Yêu c u ra c a bài toán: u đ
- u tiên: M t danh sách ID c v n. Dòng đ a đ t đã đưc ch
- Dòng th hai: M t s nguyên th hi n t ng giá tr c v c a các đ t đã đư
chn.
- Dòng th ba: M t s nguyên th hi n t ng tr ng c v ng lư a các đ t đã
đưc chn.
2.2. Xây d ng thu t toán
2.2.1. ng Ý tư
Bài toán balo yêu c u tìm ki m giá tr t t t p h v t trong ế i ưu ca m ợp các đ
mt balo có tr ng t . M v t chng lư i đa W i đ có th đưc ch c không chn ho n
mt l n duy nh u vào g m tr ng t c a balo và m t danh sách các t. Đ ng lư i đa W
đ vt, m v có các thui đ t đ c tính là ID tr, ng lưng (w - weight) giá tr và (v -
value).
Bước đu tiên, thc hin tính t l
giá tr
tr
ng ng lư
=
v
w
ca m vi đ t. Sau đó, ta
s
p x v theo th t gi m d n c a t lếp danh sách các đ t đã cho
v
w
, vì vi c l a
ch
n các đ vt có t l
v
w
cao s mang l i giá tr t i ưu hơn.
Ti p theo, ta áp d ng thu t toán nhánh và cế n (branch and bound) đ tính toán
giá tr t i ưu. Công thc tính cn trên (upper bound) như sau:
𝑢𝑏
= 𝑣 + 𝑊 𝑤
( )
vi + 1
wi + 1
Trong đó:
-
v
: T ng giá tr c v n. a các đ t đã ch
-
W
: Tr ng tng lư i đa ca balo.
-
w
: Tr ng hi n t i cng lư a balo.
-
v
i+1
: Giá tr c ti p x p. a món đ ếp theo trong danh sách đã s ế
-
w
i+1
: Tr ng c ti p x p. ng lư a món đ ếp theo trong danh sách đã s ế
Thu t toán b u v i tr ng và giá tr t đ ng lư w = 0 v = 0. Sau đó, ta tính giá
tr c n trên ubMax và ti n hành duy t qua t v t. T i m i l n duy t, n u tr ng ế ng đ ế
lưng c hia món đ n ti i (1 n) t quá i không vư W (w
i
W), ta ch vn đ t đó
và c p nh t l i giá tr vMax += v
i
(giá tr t t nh t hi n t i) và wMax += w
i
(trng lưng
16
ti đa hi n món đ vì vư ng lưn ti). Nếu không ch đó t quá tr ng ti đa (w
i
> W),
ta b qua nó.
Quá trình này ti p t n khi không th ch nào vào balo ế c cho đế n thêm món đ
mà không vư ng lư i đa ( các món đ đã t quá tr ng t wMax W), hoc khi tt c
đưc xét qua.
Cu i cùng, thu t toán quay lui c s d tìm ki m các gi i backtrack đư ng đ ế
pháp t t toán b u b ng vi c tính toán ch s i di n i ưu hơn. Thu backtrack t đ r, đ
cho ch s c c thêm vào túi do tr t quá a món hàng đu tiên không đư ng lượng vư
kh năng cha ca túi w
r
> - W w
r
. Sau đó, tính toán giá tr gii hn trên theo công
thc:
𝑢𝑏 =
v + vr
𝑟−1
𝑗
(n y) ếu balo chưa đ
Nếu giá tr t quá hi n t i, thu t toán s quay l i m t ub này không vư ubMax
bư c trư c đó trong quá trình tìm kiế ếm đ tìm ki m các gii pháp t t hơn.
Quay l i m t tình t bước trước đó có nghĩa là khi thut toán đang trong m
hung mà nó đã chn hoc b qua mt món đ, thut toán s quay li và th mt la
chn khác. Ví d , thay vì b t toán s th ch xem có tìm ra giá món đ đó, thu n đ
tr t t hơn không.
2.2.2. Xây d ng gi mã
function knapsack_backtrack(W, items):
# W: Trng lưng ti đa ca balo
# items: Danh sách các đ vt, mi đ vt có ID, trng lưng, giá tr
# Sp xếp đ vt theo giá tr/trng lưng (v/w) theo th t gim dn
sort items by v/w descending
# Khi to các biến cn thiết
vMax = 0 # Giá tr ti ưu hin ti
wMax = 0 # Trng lưng ti đa mang đưc
current_weight = 0 # Trng lưng hin ti trong balo
current_value = 0 # Giá tr hin ti trong balo
solution = [] # Danh sách các đ vt đưc chn
# Hàm tính cn trên
function upper_bound(index, current_weight, current_value):
remaining_weight = W current_value -
bound = current_value
while index (items) items[index]< len and .weight <=
remaining_weight:
remaining_weight -= items[index] weight .
bound += items[index] weight .
index += 1
if index (items) < len
bound += items[index] value (remaining_weight . * /
items[index].weight)
return bound
17
# Hàm backtracking
function backtrack(index, current_weight, current_value, solution):
nonlocal vMax, wMax
# Cp nht giá tr ti ưu nếu có
if current_value vMax: >
vMax = current_value
wMax = current_weight
best_solution = solution[:]
# Nếu không th chn thêm đ vt (quá trng lưng hoc hết đ
vt)
if index (items) current_weight >= len or >= W:
ret urn
# Tính cn trên
bound = upper_bound(index, current_weight, current_value)
# Nếu cn trên không th vưt qua giá tr ti ưu, quay lui
if bound vMax: <=
ret urn
# Chn đ vt ti index
solution.append(items[index].ID)
backtrack(index + 1 , current_weight + items[index].weight,
current_value + items[index] value, solution) .
# Quay li, không chn đ vt ti index
solution.pop()
backtrack(index + 1 , current_weight, current_value, solution)
# Bt đu thut toán backtracking t index 0
backtrack(0, 0 0, , [])
return vMax, wMax, best_solution
18
2.3. Ví d minh h a v tìm ki m nhánh c n trên và thu t toán backtrack ế
nh 3. d minh ha tìm kiếm nhánh trên và thu t toán backtrack.
19
CHƯƠNG 3: CÀI ĐT THUT TOÁN B NG
NGÔN NG L P TRÌNH PYTHON
3.1. Cài đt thut toán
3.1.1. Cài đt class Item
Class Item bao g m m t c kh i t c g i khi m t phương th o (__init__), đư
đi tư ớp Item đư o ra. Phương thng mi ca l c t c này nhn vào ba tham s bao
gm: ID, tr ng (ng lư w) và giá tr ( ). Các tham sv này l c gán cho các n lượt đư
thuc tính tương ng c a đi tư ng bao g m và . Ngoài self.ID, self.weight self.value
ra, t l
giá tr
tr
ng ng lư
=
v
w
c tính toán và gán cho thu c tính cũng đư self.ratio. T l này
dùng đ ếp danh sách các món đ i ưu hóa. sp x , ph c v cho bài toán t
class Item:
def (__init__ self, ID, weight, value):
self.ID ID =
self.weight weight =
self.value value =
self.ratio value weight = /
3.1.2. Cài đ p tin đt đc d liu đu vào t t nh dng .xlsx
Mt hàm knapsack_from_excel được đnh nghĩa đ đc d li u t m t t p tin
Excel có đnh d ng và t .xlsx o ra các đi tưng Item t d li u đó. Đu tiên, hàm m
file Excel t ng d n thông qua vi c s d n i đư file_path ng thư vi openpyxl, sau đó
ly sheet đang hot đng (active sheet) trong workbook. Sau đó, nó ly giá tr ti ô
A1, trích xu t s nguyên t giá tr c a ô này và gán nó cho bi n (tr ng t i ế W ng lư
đa c 6 đếa balo). Hàm lp qua các dòng t dòng th n dòng th n cha thông tin các
đ vt thông qua mt vòng lp for. Trong m i ln lp, hàm ly ra giá tr các ct A, B
và C tương a đ ng lưng vi ba thông tin c vt bao gm ID, tr ng và giá tr. Các
giá tr t ng m i v i các thu c tính , này được dùng đ o ra các đi tư Item ID weight
và . N u các giá tr này t n t ng s trong value ế i, đi tư Item được thêm vào lưu tr
danh sách c khai báo s ch a t t c ng c items. Danh sách items đư đi tư Item đư
to ra t d li u c a t p tin Excel.
# Hàm đc d liu t file Excel
def knapsack_from_excel(file_path):
# Đc d liu t file Excel
wb = openpyxl load_workbook(file_path) .
sheet = wb active .
# Ly trng lưng ti đa t ô A1
cell_value = sheet[ value 'A1'].
W = int(re.search(r'\d+', cell_value) group()) .
# Đc các đ vt t các ô
items = [] # Mng lưu tr thông tin đ vt
for row , sheet max_row ): in range(6 . + 1
ID = sheet[f value 'A{row}'].
weight = sheet[f value 'B{row}'].
value sheet[f value = 'C{row}'].
if ID weight value: and and
20
items append(Item(ID, weight, value)) .
3.1.3. Cài đt tìm kiếm cn trên
Ý tư đng xây dng hàm upper_bound là tính toán giá tr cn trên ca bài
toán. Đu tiên hàm nhn vào các tham s:
- : Tr ng hi n t i c v n. w ng lư a các đ t đã ch
- : Giá tr hi n t i c v n. v a các đ t đã ch
- index : Ch s b v t ti p theo. t đu đ xem xét các đ ế
- items : Danh sách các đ v t, m v t là m ng Item. i đ t đi tư
- : Tr ng tW ng lư i đa ca balo.
Sau đó hàm ng lư i đã vưkim tra ràng buc, nếu tr ng hin t t quá trng
lưng ti đa (w W) thì tr v 0, vì không th l vy thêm đ t nào na. Nếu chưa
vư t quá (w < W), hàm kh i to biến:
- : Kh i t o giá tr t ng giá tr hi n t i . bound = v i đa b v
- : Kh i t o t ng tr ng b ng tr ng hi n t i . total_weight = w ng lư ng lư w
Ti p theo hàm s d ng m t vòng l p duy t qua t t c v t có ch ế for đ các đ
s t index đến h t danh sách ế items. Trong m i l n l p, hàm th c hi n so sánh gi a
trng lư ng lượng đ đang xétng hin ti cng tr vt ti v trí trong danh sách vi
trng lư i đa c hơn trng lư i đa cng t a balo. Nếu tng trên vn nh ng t a balo,
trng lư t đó đưng ca v c cp nht thêm vào tr ng hi n t i và giá tr c a v t ng lư
đó cũng đư ớn hơn trng lưc cp nht thêm vào giá tr hin ti. Nếu tng trên l ng
ti đa ca balo, hàm s d ng vì không th v t nào n a. thêm đ
# Hàm tính cn trên
def upper_bound(w, v, index, items, W):
if w W: >
return 0
bound v =
total_weight = w
# Tính giá tr ti đa có th đt đưc t index hin ti
for i (index, (items)): in range len
if total_weight items[i] weight W: + . <=
total_weight += items[i] weight .
bound = items[i] value .
else:
bre ak
return bound
3.1.4. Cài đt thut toán backtrack
Hàm nh n vào các tham s bao g m: knapsack_backtrack
- : Ch s hi n t i. index
- : Tr ng hi n t i. current_weight ng lư
21
- : Giá tr hi n t i. current_value
- v t. items : Danh sách các đ
- : Tr ng tW ng lư i đa ca balo.
- v t hi c ch n. current_solution : Danh sách các đ n đã đư
Hai bi n toàn c c giá tr t c) và ế vMax (lưu tr i đa tìm đư best_solution (lưu
tr gi i pháp t t nh c). t tìm đư
Đu tiên, thu t toán ki m tra n u tr ng hi n t i t quá tr ng ế ng lư không vư
lư ng t a balo và ti đa c ng giá tr ca gii pháp hin ti l tớn hơn giá tr i đa đã
biết ( ). NvMax ếu điu đó đúng, thut toán c p nh t giá tr t i đa mi cho vMax và sao
chép gii pháp hi n t i vào . best_solution
Ti p theo, n t t t c v t trong danh sách, t c là ch s ế ếu đã xét hế các đ index
lúc này vượt quá đ dài c a danh sách items, thu t toán s d ng l i. c khi th xét Trư
nhánh hi n t i, thu t toán tính c n trên b ng cách g i hàm upper_bound. N u c n trên ế
ca nhánh hi n t i không l , thu t toán s c t b nhánh này vì không th ớn hơn vMax
mang l i giá tr t t hơn.
Sau đó, thut toán s th hai la chn:
- L a ch n 1: Không ch v t hi n t i và g ti p t n đ i đ quy đ ế c xét các đ
vt ti i tr ng và giá trếp theo mà không thay đ ng lư .
- L n 2: Ch v t hi n t i n t quá tr ng t a a ch n đ ếu không vư ng lư i đa c
balo. Trong trư ng lư , sau đó tiếng hp này, thut toán s cp nht tr ng và giá tr p
tc gi đ tìm xem li u còn gi i pháp t quy đ t hơn không.
# Hàm backtracking
def knapsack_backtrack(index, current_weight, current_value, items, W,
current_solution):
global vMax, best_solution
# Cp nht giá tr ti ưu nếu tìm đưc gii pháp tt hơn
if current_weight W current_value vMax: <= and >
vMax = current_value
best_solution = current_solution[:]
# Nếu đã xét hết các đ vt, dng li
if index (items): >= len
return
# Tính cn trên đ kim tra xem có nên tiếp tc không
vMax:
return # Ct nhánh vì không th đt giá tr tt hơn vMax
# B qua đ vt hin ti
knapsack_backtrack(index + 1 , current_weight, current_value, items,
W, current_solution)
22
# Thêm đ vt hin ti nếu không vưt quá trng lưng ti đa
if current_weight items[index] weight W: + . <=
current_solution.append(items[index])
knapsack_backtrack(index + 1, current_weight +
items[index].weight, current_value items[index]+ .value, items, W,
current_solution)
current_solution.pop()
3.1.5. Cài đt chương trình hoàn chnh
import re
import time
import openpyxl
start = time time() .
# Khi to lp Item đi din cho mi đ vt
class Item:
def (__init__ self, ID, weight, value):
self.ID ID =
self.weight weight =
self.value value =
self.ratio value weight = /
# Hàm tính cn trên
def upper_bound(w, v, index, items, W):
if w W: >=
return 0
bound = v
total_weight = w
# Tính giá tr ti đa có th đt đưc t index hin ti
for i (index, (items)): in range len
if total_weight items[i] weight W: + . <=
total_weight += items[i] weight .
bound += items[i] value .
else:
bre ak
return bound
# Hàm backtracking
def knapsack_backtrack(index, current_weight, current_value, items, W,
current_solution):
global vMax, best_solution
# Cp nht giá tr ti ưu nếu tìm đưc gii pháp tt hơn
if current_weight W current_value vMax: <= and >
vMax = current_value
best_solution = current_solution[:]
# Nếu đã xét hết các đ vt, dng li
if index (items): >= len
return
# Tính cn trên đ kim tra xem có nên tiếp tc không
vMax:

Preview text:

MC LC
DANH MỤC BẢNG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
DANH MỤC HÌNH ẢNH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
CHƯƠNG 1: CƠ SỞ LÝ THUYẾT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1. Thuật toán nhánh cận . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2. Nguyên lý . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3. Ưu điểm và nhược điểm của thuật toán nhánh cận . . . . . . . . . . . . . . . . . . . . . 6
1.3.1. Ưu điểm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.2. Nhược điểm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.4. Các bước chính của thuật toán . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.5. Mô tả thuật toán . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.6. Áp dụng giải bài toán . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.6.1. Bài toán cái túi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.6.2. Bài toán người du lch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
CHƯƠNG 2: PHÂN TÍCH - XÂY DỰNG THUẬT TOÁN TỐI ƯU HÓA LỰA
CHỌN ĐỒ VẬT TRONG BÀI TOÁN BALO (KNAPSACK) . . . . . . . . . . . . . . . . 14
2.1. Mô tả bài toán . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.1.1. Xây dng bài toán thc thế . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.1.2. Phát biểu bài toán dưới dng tng quát . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.2. Xây dựng thuật toán . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.2.1. Ý tưởng . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.2.2. Xây dựng giả mã . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.3. Ví dụ minh họa về tìm kiếm nhánh cận trên và thuật toán backtrack . . . . . . 18
CHƯƠNG 3: CÀI ĐẶT THUẬT TOÁN BẰNG NGÔN NGỮ LẬP TRÌNH
PYTHON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.1. Cài đặt thuật toán . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.1.1. Cài đặt class Item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.1.2. Cài đặt đọc d liệu đầu vào t tệp tin định dng .xlsx . . . . . . . . . . . . . . 19
3.1.3. Cài đặt tìm kiếm cn trên . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.1.4. Cài đặt thut toán backtrack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.1.5. Cài đặt chương trình hoàn chỉnh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.2. Kiểm thử . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.2.1. D liệu đầu vào . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 3
3.2.2. D liệu đầu ra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.2.3. Kim th các chức năng của thut toán . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.3. Đánh giá và so sánh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.3.1. Độ phc tp ca thut toán . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.3.2. So sánh thi gian thc hin thut toán . . . . . . . . . . . . . . . . . . . . . . . . . . 28
TỔNG KẾT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
ĐÁNH GIÁ NỘI BỘ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
TÀI LIỆU THAM KHẢO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 4
DANH MC BNG
Bảng 1. Bảng dữ liệu đầu vào. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Bảng 2. Bảng đánh giá nội bội. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
DANH MC HÌNH NH
Ảnh 1. Xây dựng cây tìm kiếm cho bài toán cái túi. . . . . . . . . . . . . . . . . . . . . . . . . . 11
Ảnh 2. Xây dựng cây tìm kiếm cho bài toán người du lịch. . . . . . . . . . . . . . . . . . . . 12
Ảnh 3. Ví dụ minh họa tìm kiếm nhánh trên và thuật toán backtrack. . . . . . . . . . . . 18 5
CHƯƠNG 1: CƠ SỞ LÝ THUYT
1.1. Thut toán nhánh cn
Thuật toán nhánh cận là một trong các phương pháp chủ yếu giải bài toán tối
ưu tổ hợp. Tư tưởng cơ bản của nó là trong quá trình tìm kiếm ta phân hoạch các
phương án của bài toán ra thành hai hay nhiều tập con như các nút, loại bỏ những
nhánh mà ta biết chắc chắn là không chứa phương án tối ưu.
Kỹ thuật nhánh cận phát triển từ ý tưởng của thuật toán quay lui. Thay vì duyệt
tất cả các trường hợp, nếu ta đến một vị trí mà giá trị của hàm mục tiêu tại đó và các
điểm về sau chắc chắn không tốt nhất thì quay lại luôn. 1.2. Nguyên lý
Nhánh (Branch): Thuật toán chia nhỏ bài toán lớn thành các bài toán con nhỏ
hơn, tức là tạo ra các nhánh trong quá trình giải. Mỗi nhánh đại diện cho một trạng
thái hoặc một tập con của không gian tìm kiếm. Quá trình này tiếp tục cho đến khi đạt đ ợ
ư c một giải pháp hợp lệ hoặc không thể tìm thêm nhánh con nào nữa.
Cận (Bound): Cận là bước quan trọng trong thuật toán nhánh cận, giúp loại bỏ
các nhánh không cần thiết trong quá trình tìm kiếm. Mỗi nhánh sẽ có một giá trị "cận"
tính toán được, và thuật toán chỉ tiếp tục tìm kiếm trong các nhánh mà giá trị cận của
chúng hứa hẹn mang lại giải pháp tốt hơn so với giải pháp đã tìm được trước đó. Nếu
giá trị cận của một nhánh không thể tốt hơn giải pháp hiện tại, nhánh đó sẽ bị loại bỏ.
1.3. Ưu điểm và nhược điểm ca thut toán nhánh cn
1.3.1. Ưu điểm
- Tìm kiếm giải pháp tối ưu: Thuật toán nhánh cận luôn đảm bảo tìm được giải
pháp tối ưu nếu không gian tìm kiếm được duyệt đầy đủ. Đây là một trong những ưu
điểm quan trọng nhất khi so với các thuật toán “tham lam” (Greedy) hoặc xấp xỉ.
- Giảm thiểu không gian tìm kiếm: Thuật toán sử dụng bước lọc nhánh để loại
bỏ các nhánh không khả thi hoặc không có tiềm năng mang lại giải pháp tốt hơn, giúp
giảm đáng kể số lượng trạng thái cần kiểm tra.
- Linh hoạt với nhiều bài toán: Thuật toán có thể áp dụng cho nhiều bài toán
tối ưu hóa rời rạc như bài toán cái balo, bài toán đi đường ngắn nhất (Traveling
Salesman Problem), bài toán phân hoạch, bài toán lập lịch và nhiều bài toán khác.
- Khả năng tận dụng chiến lược cận: Sử dụng các kỹ thuật tính toán cận hiệu
quả (upper bound - cận trên hoặc lower bound - cận dưới) giúp nâng cao hiệu quả của
thuật toán và giảm thời gian tính toán.
- Khả năng dừng sớm: Khi tìm được một giải pháp mà giá trị cận của các nhánh
còn lại không thể tốt hơn giải pháp hiện tại, thuật toán có thể dừng sớm mà không
cần duyệt toàn bộ không gian. 6
1.3.2. Nhược điểm
- Tốn kém về bộ nhớ: Do cần lưu trữ tất cả các nhánh và thông tin liên quan
(như trạng thái, giá trị cận), thuật toán có thể yêu cầu rất nhiều bộ nhớ, đặc biệt đối
với các bài toán có không gian tìm kiếm lớn.
- Độ phức tạp tính toán cao: Mặc dù thuật toán loại bỏ được nhiều nhánh không
cần thiết, việc tính toán cận và quản lý các nhánh vẫn tiêu tốn thời gian và tài nguyên,
đặc biệt với các bài toán có kích thước lớn.
- Phụ thuộc vào chiến lược cận: Hiệu quả của thuật toán phụ thuộc rất nhiều
vào cách tính toán cận trên hoặc cận dưới. Nếu cận không chính xác hoặc không chặt
chẽ, thuật toán có thể phải duyệt qua nhiều nhánh không cần thiết, làm giảm hiệu quả.
- Không phù hợp với không gian tìm kiếm quá lớn: Khi không gian tìm kiếm
quá rộng hoặc không thể dễ dàng tính toán cận, thuật toán có thể trở nên chậm và
kém hiệu quả so với các phương pháp xấp xỉ.
- Khó khăn trong triển khai: Việc triển khai thuật toán nhánh cận yêu cầu hiểu
rõ bài toán và các kỹ thuật tính toán cận, điều này có thể phức tạp hơn so với các thuật
toán tham lam hoặc quy hoạch động.
1.4. Các bước chính ca thut toán
- Khởi tạo: Bắt đầu với một giải pháp ban đầu (có thể là giải pháp xấp xỉ hoặc
giải pháp hợp lệ nhất), tính toán cận dưới (hoặc cận trên) của bài toán. Đây là bước
khởi tạo không gian tìm kiếm.
- Chia nhánh (Branching): Tạo ra các nhánh con bằng cách chia bài toán lớn
thành các bài toán con nhỏ hơn, từ đó phát triển không gian tìm kiếm. Mỗi nhánh có
thể đại diện cho một tập con của các lựa chọn hoặc các trạng thái.
- Tính cận (Bounding): Với mỗi nhánh, tính toán giá trị cận (thường là cận
dưới đối với bài toán tối thiểu hoặc cận trên đối với bài toán tối đa). Cận này là một
ước lượng của giá trị tối ưu trong nhánh đó.
- Lọc nhánh (Pruning): Loại bỏ các nhánh mà giá trị cận của chúng không thể
tốt hơn giải pháp hiện tại hoặc không có khả năng tìm ra một giải pháp tốt hơn. Điều
này giúp giảm thiểu không gian tìm kiếm và tiết kiệm thời gian.
- Tiến hành tìm kiếm: Tiếp tục mở rộng các nhánh còn lại cho đến khi tìm
được giải pháp tối ưu hoặc không còn nhánh nào để kiểm tra.
1.5. Mô t thut toán
Ta sẽ mô tả thuật toán trên mô hình bài toán tối ưu tổng quát sau: min { f(x) : x ∈ D },
Trong đó D là tập hữu hạn phần tử.
Giả thiết rằng tập D được mô tả như sau: 7
D={x = (x1, x2, ... , xn) ∈ A1 × A2 × ... × An: x thoả mãn tính chất P},
Với A1, A2, . . , An là các tập hữu hạn, còn P là tính chất cho trên tích Đề-các A1 × A2 × . . × An.
Với giả thiết về tập D nêu trên, chúng ta có thể sử dụng thuật toán quay lui để
liệt kê các phương án của bài toán. Trong quá trình liệt kê theo thuật toán quay lui, ta
sẽ xây dựng dần các thành phần của phương án. Một bộ gồm k thành phần (a1, a2, a3,
… , ak) xuất hiện trong trong quá trình thuật toán sẽ gọi là phương án bộ phận cấp k.
Thuật toán nhánh cận có thể áp dụng để giải bài toán đặt ra nếu như có thể tìm
được một hàm g xác định trên trên tập tất cả phương án bộ phận của bài toán thỏa
mãn bất đẳng thức sau:
g(a1, a2, ... , ak) ≤ min {f(x): x ∈ D, xi = ai, i = 1, 2, ..., k} (*)
Bất đẳng thức (*) có nghĩa là giá trị của hàm g tại phương án bộ phận (a1, a2,
… , ak) là không vượt quá giá trị nhỏ nhất của hàm mục tiêu của bài toán trên tập con các phương án.
D(a1, a2, … , ak)={ x ∈ D : x1 =ai, i = 1, 2, ... , k}
Hay nói một cách khác, g(a1, a2, … , ak) là cận dưới của giá trị hàm mục tiêu
trên tập D(a1, a2, … , ak). Vì lẽ đó, hàm g được gọi là hàm cận dưới và giá trị g(a1, a2,
… , ak) được gọi là cận dưới của tập D(a1, a2, … , ak). Do có thể đồng nhất tập D(a1,
a2, … , ak) với phương án bộ phận (a1, a2, … , ak), nên ta cũng gọi giá trị g(a1, a2, a3,
… , ak) là cận dưới của phương án bộ phận (a1, a2, … , ak).
Giả sử đã có hàm g. Ta xét cách sử dụng hàm này để giảm bớt khối lượng
duyệt trong quá trình duyệt tất cả các phương án theo thuật toán quay lui. Trong quá
trình liệt kê các phương án có thể đã thu được một số phương án của bài toán. Gọi x
là phương án với giá trị hàm mục tiêu nhỏ nhất trong số các phương án đã tìm được,
kí hiệu f = f(x). Ta sẽ gọi x là phương án tốt nhất hiện có, còn f là kỷ lục. Giả sử đã có f, khi đó nếu:
g(a1, a2, … , ak) > f󰋀,
Thì từ bất đẳng thức (*) suy ra
f󰋀 < g(a1, a2, … , ak) ≤ min {f(x): x ∈ D : x1 = ai, i= 1, 2, ... , k}
Vì thế tập con các phương án ấy của bài toán D(a1, a2, … , ak) chắc chắn không
chứa phương án tối ưu. Trong trường hợp này ta không cần tiếp tục phát triển các
phương án bộ phận ((a1, a2, … , ak), nói cách khác là ta có thể loại bỏ các phương án
trong tập D(a1, a2, … , ak) khỏi quá trình tìm kiếm. 8
1.6. Áp dng gii bài toán
1.6.1. Bài toán cái túi

Đưa ra giả thiết rằng có n loại đồ vật và số lượng đồ vật mỗi loại là không hạn
chế. Khi đó ta có mô hình bài toán cái túi biến nguyên sau đây: Có n loại đồ vật, đồ
vật thứ j có trọng lượng aj và giá trị sử dụng là cj (j = 1, 2, . . , n). 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.
Mô hình của bài toán sẽ có dạng như sau: Tìm: 𝑛 𝑛
𝑓 = 𝑚𝑎𝑥 {𝑓(𝑥) = ∑ 𝑐𝑗𝑥𝑗 ; ∑ 𝑎𝑗𝑥𝑗 ≤ 𝑏, 𝑥𝑗 ∈ 𝑍+, 𝑗 = 1, 2, . .. , 𝑛} (1) 𝑗=1 𝑗=1
Trong đó Z+ là tập các số nguyên không âm. 𝑛
𝐷 = {𝑥 = (𝑥1, 𝑥2, . .. ,𝑥𝑛; ∑ 𝑎𝑗𝑥𝑗 ≤ 𝑏, 𝑥𝑗 ∈ 𝑍+,𝑗 = 1, 2,. .. , 𝑛} 𝑗=1
Không gian tổng quát ta giả thiết rằng các đồ vật được đánh số sao cho bất
đẳng thức sau được thoả mãn: 𝑐1 𝑐2 𝑐𝑛 𝑎 ≥ ≥ . . . ≥ (2) 1 𝑎2 𝑎𝑛
Để tiếp tục xây dựng hàm tính cận dưới, cùng với bài toán cái túi (1) ta xét bài
toán cái túi biến liên tục sau: Tìm:
𝑔 = 𝑚𝑎𝑥 { 𝑓(𝑥) = ∑ 𝑛 𝑛
𝑗=1𝑐𝑗𝑥𝑗 : ∑𝑗=1 𝑎𝑗𝑥𝑗 ≤ 𝑏, 𝑥𝑗 ≥ 0, 𝑗 = 1, 2, . . . , 𝑛} (3)
Mệnh đề: Phương án tối ưu của bài toán (3) là vectơ x = (x1, x2, ... , xn) với
các thành phần được xác định bởi công thức: 𝑏
𝑥 1 =𝑎 ,𝑥 2 = 𝑥 3 = ...= 𝑥 𝑛 = 0. 1
Và giá trị tối ưu là 𝑔 = 𝑐1𝑏1 𝑎1
Chng minh: Thực vậy, xét x = (x1, x2, . . , xn) là một phương án tuỳ ý của
bài toán (3). Khi đó từ bất đẳng thức (3) và do x1 ≥ 0, ta suy ra:
𝑐𝑗𝑥𝑗 ≥ (𝑐1/𝑎1) 𝑎𝑗𝑥𝑗, 𝑗 = 1, 2,. .. ,𝑛 Suy ra: 9 𝑛 𝑛 𝑛
∑ 𝑐𝑗𝑥𝑗 ≤ ∑(𝑐1/𝑎1)𝑎𝑗𝑥𝑗 = (𝑐1𝑎1) ∑ 𝑎𝑗𝑥𝑗 ≤ (𝑐1/𝑎1)𝑏 = 𝑔∗. 𝑗=1 𝑗=1 𝑗=1
Mệnh đề được chứng minh.
Bây giờ, giả sử ta có phương án bộ phận cấp k: (u1, u2, . . , uk). Khi đó giá trị
sử dụng của các đồ vật đang có trong túi là:
𝜎𝑘 = 𝑐1𝑢1 + 𝑐2𝑢2+ .. .+𝑐𝑘𝑢𝑘
Và trọng lượng còn lại của túi là:
𝑏𝑘 = 𝑏 − 𝑎1𝑢1 + 𝑎2𝑢2+ . .. +𝑎𝑘𝑢𝑘. Ta có:
𝑚𝑎𝑥{ 𝑓(𝑥): 𝑥 ∈ 𝐷, 𝑥𝑗 = 𝑢𝑗, 𝑗 = 1, 2,. .. , 𝑘} 𝑛 𝑛
= 𝑚𝑎𝑥{ 𝜎𝑘 + ∑ 𝑐𝑗𝑥𝑗 : ∑ 𝑎𝑗𝑥𝐽 ≤ 𝑏𝑘, 𝑥𝑗 ∈ 𝑍+, 𝑗 = 𝑘 + 1, 𝑘 + 2, . .., 𝑛} 𝑗=𝑘+1 𝑗=𝑘+1 𝑛 𝑛
≤ 𝜎𝑘 + 𝑚𝑎𝑥{ ∑ 𝑐𝑗𝑥𝑗 : ∑ 𝑎𝑗𝑥𝐽 ≤ 𝑏𝑘, 𝑥𝑗 ≥ 0, 𝑗 = 𝑘 + 1, 𝑘 + 2, .. . ,𝑛} 𝑗=𝑘+1 𝑗=𝑘+1
(Theo mệnh đề: Giá trị số hạng thứ hai là 𝑐𝑘+𝑗𝑏𝑘/𝑎 ) 𝑘+𝑗
Vậy ta có thể tính cận trên cho phương án bộ phận (u1, u2, … , uk) bởi công thức:
𝑔(𝑢1,𝑢2, . . . , 𝑢𝑘) = 𝜎𝑘 + 𝑐𝑘+1𝑏𝑘/𝑎𝑘+1
Chú ý: Khi tiếp tục xây dựng thành phần thứ k + 1 của lời giải, các giá trị đề
cử cho xk+1 sẽ là 0, 1, … , [bkak+1]. Do có kết quả của mệnh đề, khi chọn giá trị cho
xk+1 ta sẽ duyệt các giá trị đề cử theo thứ tự giảm dần.
Ví d ng dng: Giải bài toán cái túi theo thuật toán nhánh cận vừa trình bày.
𝑓(𝑥) = 10𝑥1 + 5𝑥2 + 3𝑥3 + 6𝑥4 → 𝑚𝑎𝑥,
5𝑥1 + 3𝑥2 + 2𝑥3 + 4𝑥4 ≤ 8,
𝑥𝑗 ∈ 𝑍+,𝑗 = 1,2, 3,4. Gii: 10
nh 1. Xây dng cây tìm kiếm cho bài toán cái túi.
Quá trình giải bài toán được mô tả trong cây tìm kiếm trong hình trên. Thông
tin về một phương án bộ phận trên cây được ghi trong các ô trên hình tương ứng theo
thứ tự: đầu tiên là các thành phần của phương án, tiếp đến σ là giá trị của các đồ vật
đang chất trong túi, w – trọng lượng còn lại của túi và g – cận trên.
Kết thúc thuật toán, ta thu được phương án tối ưu là x=(1,1,0,0), và giá trị tối ưu là f=15.
1.6.2. Bài toán người du lch
Cố định thành phố xuất phát là 𝑇1, bài toán người du lịch dẫn về bài toán: Tìm cực tiểu của hàm:
𝑓(𝑥2,𝑥3,… ,𝑥𝑛) = 𝑐[1, 𝑥2] + 𝑐[𝑥2,𝑥3] + ⋯ + 𝑐[𝑥𝑛−1, 𝑥𝑛] + 𝑐[𝑥𝑛, 1] → min,
Với điều kiện: (𝑥2,𝑥3,… , 𝑥𝑛) là hoán vị của các số 2,3, …, 𝑛.
Ký hiệu: 𝑐𝑚𝑖𝑛 = min{𝑐[𝑖, 𝑗], 𝑖,𝑗 = 1,2, …, 𝑛, 𝑖 𝑘ℎá𝑐 𝑗} là chi phí đi lại nhỏ nhất giữa các thành phố.
Để có được thuật toán nhánh cận giải bài toán người du lịch, trước hết cần đưa
ra cách đánh giá cận dưới cho phương án bộ phận. Giả sử đang có phương án bộ phận
(𝑢1,𝑢2,… , 𝑢𝑘). Phương án này tương ứng với hành trình bộ phận qua k thành phố:
𝑇1 → 𝑇(𝑢2) → ⋯ → 𝑇(𝑢𝑘−1) → 𝑇(𝑢𝑘)
Vì vậy chi phí phải trả theo hành trình bộ phận này sẽ là:
𝜎 = 𝑐[1, 𝑢2] + 𝑐[𝑢2, 𝑢3] + ⋯ + 𝑐[𝑢𝑘−1,𝑢𝑘] 11
Để phát triển hành trình bộ phận này thành hành trình đầy đủ, ta còn phải đi
qua 𝑛 − 𝑘 thành phố còn lại rồi quay trở lại thành phố 𝑇1, tức là còn phải đi qua 𝑛 −
𝑘 + 1 đoạn đường nữa. Do chi phí phải trả cho việc đi qua mỗi một trong số 𝑛 − 𝑘 +
1 đoạn đường còn lại nếu không ít hơn 𝑐𝑚𝑖𝑛, nên cận dưới cho phương án bộ phận
(𝑢1,𝑢2,… , 𝑢𝑘) có thể tính theo công thức
𝑔(𝑢1,𝑢2,… , 𝑢𝑘) = 𝜎 + (𝑛 − 𝑘 + 1)𝑐𝑚𝑖𝑛
Sử dụng cách cận dưới vừa nêu ta có thể áp dụng thuật toán nhánh cận để giải
bài toán người du lịch.
Ví dụ: Giải bài toán người du lịch với ma trận chi phí sau: 0 3 14 18 15 3 0 4 22 20 C = 17 9 0 16 4 6 2 7 0 12 9 15 11 5 0
Ta có 𝑐𝑚𝑖𝑛 = 3. Quá trình thực hiện thuật toán được mô tả bởi cây tìm kiếm dưới đây:
nh 2. Xây dng cây tìm kiếm cho bài toán người du lch.
Thông tin về một bộ phận trên cây đuọc ghi trong các ô trên hình tương ứng
theo thứ tự: đầu tiên là các thành phần của phương án, tiếp đến là chi phí tương theo
hành trình bộ phận và g - cận dưới. 12
Kết thúc thuật toán, ta thu được phương án tối ưu (1, 2 , 3, 5, 4, 1) tương ứng với hành trình:
𝑇1 → 𝑇2 → 𝑇3 → 𝑇5 → 𝑇4 → 𝑇1,
Và chi phí nhỏ nhất là 25.
Hiệu quả của thuật toán nhánh cận phụ thuộc vào việc xây dựng hàm tính cận
dưới. Việc xây dựng hàm tính cận dưới lại phụ thuộc vào cách xây dựng thủ tục duyệt
các phương án của bài toán (được gọi là thủ tục phân nhánh). Trên đây chúng ta đã
trình bày cách xây dựng cận dưới khá đơn giản cho bài toán nổi tiếng của tối ưu tổ
hợp. Các chương trình được cài đặt theo các thuật toán đó, tuy rằng làm việc tốt hơn
nhiều so với duyệt toàn bộ, nhưng cũng chỉ có thể áp dụng để giải các bài toán với
kích thước nhỏ. Muốn giải được các bài toán đặt ra với kích thước lơn hơn cần có
cách đánh giá cận tốt hơn. 13
CHƯƠNG 2: PHÂN TÍCH - XÂY DNG THUT TOÁN TỐI ƯU HÓA
LA CHỌN ĐỒ VT TRONG BÀI TOÁN BALO (KNAPSACK)
2.1. Mô t bài toán
2.1.1. Xây d
ng bài toán thc thế
Bạn là một nhà thám hiểm và đang chuẩn bị cho một chuyến đi dài. Bạn có
một balo với trọng lượng tối đa cho phép là X Kilogram (KG). Bạn có một số đồ vật
cần mang theo, mỗi đồ vật có một trọng lượng và một giá trị khác nhau. Mục tiêu của
bạn là tối ưu hóa việc lựa chọn đồ vật để tối đa hóa tổng giá trị mang theo mà không
vượt quá trọng lượng tối đa ủ c a balo.
Yêu cầu đầu vào của bài toán bao gồm:
- Trọng lượng tối đa của balo: Một số nguyên dương.
- Danh sách đồ vật: Một danh sách chứa thông tin về từng đồ vật như ID đồ
vật, trọng lượng (KG), giá trị (đơn vị tiền tệ).
Yêu cầu đầu ra của bài toán bao gồm:
- Danh sách đồ vật được chọn: Một danh sách các ID của từng đồ vật đã được chọn mang đi.
- Tổng giá trị: Một số nguyên thể hiện tổng giá trị của các đồ vật đã được chọn.
- Tổng trọng lượng: Một số nguyên thể hiện tổng trọng lượng của các đồ vật đã được chọn. Nhiệm vụ cụ thể:
- Phát triển thuật toán: Sử dụng phương pháp nhánh cận để tìm kiếm giải pháp
tối ưu cho bài toán balo.
- Thực hiện kiểm tra ràng buộc: Đảm bảo rằng tổng trọng lượng của các đồ
vật không vượt quá trọng lượng tối đa của balo.
- In ra kết quả: Hiển thị danh sách các đồ vật được chọn, tổng giá trị và tổng trọng lượng.
- Phân tích và so sánh: So sánh kết quả với các phương pháp khác (nếu có) để
đánh giá hiệu quả của thuật toán nhánh cận.
2.1.2. Phát biểu bài toán dưới dng tng quát
Từ bài toán được xây dựng tại Mc 2.1.1., ta có thể phát biểu dưới dạng tổng quát như sau:
Cho n đồ vật khác nhau, trong đó, đồ vật thứ i có mã IDi, trọng lượng wi và giá
trị vi. Bạn mang theo một chiếc balo có tải trọng tối đa là W, nhiệm vụ đặt ra là chọn
các đồ vật để cho vào balo sao cho tổng giá trị các đồ vật lấy được là lớn nhất có thể?
Yêu cầu đầu vào của bài toán là một tập tin định dạng .xlsx, trong đó bao gồm: 14
- Trọng lượng tối đa của balo: Một số nguyên dương.
- Danh sách đồ vật: Một danh sách chứa thông tin về từng đồ vật như ID đồ
vật, trọng lượng (KG), giá trị (đơn vị tiền tệ).
Yêu cầu đầu ra của bài toán:
- Dòng đầu tiên: Một danh sách ID của đồ vật đã được chọn.
- Dòng thứ hai: Một số nguyên thể hiện tổng giá trị của các đồ vật đã được chọn.
- Dòng thứ ba: Một số nguyên thể hiện tổng trọng lượng của các đồ vật đã được chọn.
2.2. Xây dng thut toán
2.2.1.
Ý tưởng
Bài toán balo yêu cầu tìm kiếm giá trị tối ưu của một tập hợp các đồ vật trong
một balo có trọng lượng tối đa W. Mỗi đồ vật chỉ có thể được chọn hoặc không chọn
một lần duy nhất. Đầu vào gồm trọng lượng tối đa W của balo và một danh sách các
đồ vật, mỗi đồ vật đề có các thuộc tính là ID, trọng lượng (w - weight)giá tr (v - value).
Bước đầu tiên, thực hiện tính tỷ lệ giá t ịr = v của mỗi đồ vật. Sau đó, ta trọng lượng w
sắp xếp danh sách các đồ vật đã cho theo thứ tự giảm dần của tỷ lệ v , vì việc lựa w
chọn các đồ vật có tỷ lệ v cao sẽ mang lại giá trị tối ưu hơn. w
Tiếp theo, ta áp dụng thuật toán nhánh và cận (branch and bound) để tính toán
giá trị tối ưu. Công thức tính cận trên (upper bound) như sau: vi + 1
𝑢𝑏 = 𝑣 + (𝑊 − 𝑤) ∗ wi + 1 Trong đó: - v
: Tổng giá trị của các đồ vật đã chọn.
- W : Trọng lượng tối đa của balo.
- w : Trọng lượng hiện tại của balo.
- vi+1 : Giá trị của món đồ tiếp theo trong danh sách đã sắp xếp.
- wi+1 : Trọng lượng của món đồ tiếp theo trong danh sách đã sắp xếp.
Thuật toán bắt đầu với trọng lượng w = 0 và giá trị v = 0. Sau đó, ta tính giá
trị cận trên ubMax và tiến hành duyệt qua từng đồ vật. Tại mỗi lần duyệt, nếu trọng
lượng của món đồ hiện tại i (1 ≤ i ≤ n) không vượt quá W (wi W), ta chọn đồ vật đó
và cập nhật lại giá trị vMax += vi (giá trị tốt nhất hiện tại) và wMax += wi (trọng lượng 15
tối đa hiện tại). Nếu không chọn món đồ đó vì vượt quá trọng lượng tối đa (wi > W), ta bỏ qua nó.
Quá trình này tiếp tục cho đến khi không thể chọn thêm món đồ nào vào balo
mà không vượt quá trọng lượng tối đa (wMaxW), hoặc khi tất cả các món đồ đã được xét qua.
Cuối cùng, thuật toán quay lui backtrack được sử dụng để tìm kiếm các giải
pháp tối ưu hơn. Thuật toán backtrack bắt đầu bằng việc tính toán chỉ số r, đại diện
cho chỉ số của món hàng đầu tiên không được thêm vào túi do trọng lượng vượt quá
khả năng chứa của túi wr > W - wr. Sau đó, tính toán giá trị giới hạn trên theo công thức: 𝑢𝑏 = ∑𝑟−1 𝑗
v + vr (nếu balo chưa đầy)
Nếu giá trị ub này không vượt quá ubMax hiện tại, thuật toán sẽ quay lại một
bước trước đó trong quá trình tìm kiếm ể
đ tìm kiếm các giải pháp tốt hơn.
“Quay lại một bước trước đó” có nghĩa là khi thuật toán đang trong một tình
huống mà nó đã chọn hoặc bỏ qua một món đồ, thuật toán sẽ quay lại và thử một lựa
chọn khác. Ví dụ, thay vì bỏ món đồ đó, thuật toán sẽ thử chọn để xem có tìm ra giá trị tốt hơn không.
2.2.2. Xây dng gi
function knapsack_backtrack(W, items):
# W: Trọng lượng tối đa của balo
# items: Danh sách các đồ vật, mỗi đồ vật có ID, trọng lượng, giá trị
# Sắp xếp đồ vật theo giá trị/trọng lượng (v/w) theo thứ tự giảm dần sort items by v/w descending
# Khởi tạo các biến cần thiết vMax = 0
# Giá trị tối ưu hiện tại wMax = 0
# Trọng lượng tối đa mang được
current_weight = 0 # Trọng lượng hiện tại trong balo
current_value = 0 # Giá trị hiện tại trong balo solution = []
# Danh sách các đồ vật được chọn # Hàm tính cận trên
function upper_bound(index, current_weight, current_value):
remaining_weight = W - current_value bound = current_value
while index < len(items) and items[index].weight <= remaining_weight:
remaining_weight -= items[index].weight bound += items[index].weight index += 1
if index < len(items)
bound += items[index].value * (remaining_weight / items[index].weight) return bound 16
# Hàm backtracking
function backtrack(index, current_weight, current_value, solution): nonlocal vMax, wMax
# Cập nhật giá trị tối ưu nếu có
if current_value > vMax: vMax = current_value wMax = current_weight best_solution = solution[:]
# Nếu không thể chọn thêm đồ vật (quá trọng lượng hoặc hết đồ vật)
if index >= len(items) or current_weight >= W: return # Tính cận trên
bound = upper_bound(index, current_weight, current_value)
# Nếu cận trên không thể vượt qua giá trị tối ưu, quay lui if bound <= vMax: return
# Chọn đồ vật tại index
solution.append(items[index].ID)
backtrack(index + 1, current_weight + items[index].weight,
current_value + items[index].value, solution)
# Quay lại, không chọn đồ vật tại index solution.pop()
backtrack(index + 1, current_weight, current_value, solution)
# Bắt đầu thuật toán backtracking từ index 0 backtrack(0, 0, 0, [])
return vMax, wMax, best_solution 17
2.3. Ví d minh ha v tìm kiếm nhánh cn trên và thut toán backtrack
nh 3. Ví d minh ha tìm kiếm nhánh trên và thut toán backtrack. 18
CHƯƠNG 3: CÀI ĐẶT THUT TOÁN BNG
NGÔN NG LP TRÌNH PYTHON
3.1. Cài đặt thut toán
3.1.1. Cài đặt class Item
Class Item bao gồm một phương thức khởi tạo (__init__), được gọi khi một
đối tượng mới của lớp Item được tạo ra. Phương thức này nhận vào ba tham số bao
gồm: ID, trọng lượng (w) và giá trị (v). Các tham số này lần lượt được gán cho các
thuộc tính tương ứng của đối tượng bao gồm self.ID, self.weight self.value. Ngoài
ra, tỷ lệ giá t ịr = v cũng được tính toán và gán cho thuộc tính self.ratio. Tỷ lệ này trọng lượng w
dùng để sắp xếp danh sách các món đồ, phục vụ cho bài toán tối ưu hóa. class Item:
def __init__(self, ID, weight, value): self.ID = ID self.weight = weight self.value = value self.ratio = value / weight
3.1.2. Cài đặt đọc d liệu đầu vào t tệp tin định dng .xlsx
Một hàm knapsack_from_excel được định nghĩa để đọc dữ liệu từ một tệp tin
Excel có định dạng .xlsx và tạo ra các đối tượng Item từ dữ liệu đó. Đầu tiên, hàm mở
file Excel tại đường dẫn file_path thông qua việc sử dụng thư viện openpyxl, sau đó
lấy sheet đang hoạt động (active sheet) trong workbook. Sau đó, nó lấy giá trị tại ô
A1, trích xuất số nguyên từ giá trị của ô này và gán nó cho biến W (trọng lượng tối
đa của balo). Hàm lặp qua các dòng từ dòng thứ 6 đến dòng thứ n chứa thông tin các
đồ vật thông qua một vòng lặp for. Trong mỗi lần lặp, hàm lấy ra giá trị các cột A, B
và C tương ứng với ba thông tin của đồ vật bao gồm ID, trọng lượng và giá trị. Các
giá trị này được dùng để tạo ra các đối tượng Item mới với các thuộc tính ID, weight
value. Nếu các giá trị này tồn tại, đối tượng Item sẽ được thêm vào lưu trữ trong
danh sách items. Danh sách items được khai báo sẽ chứa tất cả đối tượng Item được
tạo ra từ dữ liệu của tệp tin Excel.
# Hàm đọc dữ liệu từ file Excel
def knapsack_from_excel(file_path):
# Đọc dữ liệu từ file Excel
wb = openpyxl.load_workbook(file_path) sheet = wb.active
# Lấy trọng lượng tối đa từ ô A1
cell_value = sheet['A1'].value
W = int(re.search(r'\d+', cell_value).group())
# Đọc các đồ vật từ các ô
items = [] # Mảng lưu trữ thông tin đồ vật
for row in range(6, sheet.max_row + 1): ID = sheet[f'A{row}'].value
weight = sheet[f'B{row}'].value
value = sheet[f'C{row}'].value
if ID and weight and value: 19
items.append(Item(ID, weight, value))
3.1.3. Cài đặt tìm kiếm cn trên
Ý tưởng xây dựng hàm upper_bound là để tính toán giá trị cận trên của bài
toán. Đầu tiên hàm nhận vào các tham số: - w
: Trọng lượng hiện tại của các đồ vật đã chọn. - v
: Giá trị hiện tại của các đồ vật đã chọn. - index
: Chỉ số bắt đầu để xem xét các đồ vật tiếp theo. - items
: Danh sách các đồ vật, mỗi ồ
đ vật là một đối tượng Item. - W
: Trọng lượng tối đa của balo.
Sau đó hàm kiểm tra ràng buộc, nếu trọng lượng hiện tại đã vượt quá trọng
lượng tối đa (wW) thì trả về 0, vì không thể lấy thêm đồ vật nào nữa. Nếu chưa
vượt quá (w < W), hàm khởi tạo biến: - bound = v
: Khởi tạo giá trị tối đa bằng giá trị hiện tại v.
- total_weight = w : Khởi tạo tổng trọng lượng bằng trọng lượng hiện tại w.
Tiếp theo hàm sử dụng một vòng lặp for để duyệt qua tất cả các đồ vật có chỉ
số từ index đến hết danh sách items. Trong mỗi lần lặp, hàm thực hiện so sánh giữa
trọng lượng hiện tại cộng trọng lượng đồ vật tại vị trí đang xét trong danh sách với
trọng lượng tối đa của balo. Nếu tổng trên vẫn nhỏ hơn trọng lượng tối đa của balo,
trọng lượng của vật đó được cập nhật thêm vào trọng lượng hiện tại và giá trị của vật
đó cũng được cập nhật thêm vào giá trị hiện tại. Nếu tổng trên lớn hơn trọng lượng
tối đa của balo, hàm sẽ dừng vì không thể thêm đồ vật nào nữa. # Hàm tính cận trên
def upper_bound(w, v, index, items, W): if w > W: return 0 bound = v total_weight = w
# Tính giá trị tối đa có thể đạt được từ index hiện tại
for i in range(index, len(items)):
if total_weight + items[i].weight <= W:
total_weight += items[i].weight bound = items[i].value else: break return bound
3.1.4. Cài đặt thut toán backtrack
Hàm knapsack_backtrack nhận vào các tham số bao gồm: - index : Chỉ số hiện tại. - current_weight
: Trọng lượng hiện tại. 20 - current_value : Giá trị hiện tại. - items
: Danh sách các đồ vật. - W
: Trọng lượng tối đa của balo.
- current_solution : Danh sách các đồ vật hiện đã được chọn.
Hai biến toàn cục vMax (lưu trữ giá trị tối đa tìm được) và best_solution (lưu
trữ giải pháp tốt nhất tìm được).
Đầu tiên, thuật toán kiểm tra nếu trọng lượng hiện tại không vượt quá trọng
lượng tối đa của balo và tổng giá trị của giải pháp hiện tại lớn hơn giá trị tối đa đã
biết (vMax). Nếu điều đó đúng, thuật toán cập nhật giá trị tối đa mới cho vMax và sao
chép giải pháp hiện tại vào best_solution.
Tiếp theo, nếu đã xét hết tất cả các đồ vật trong danh sách, tức là chỉ số index
lúc này vượt quá độ dài của danh sách items, thuật toán sẽ dừng lại. Trước khi thử xét
nhánh hiện tại, thuật toán tính cận trên bằng cách gọi hàm upper_bound. Nếu cận trên
của nhánh hiện tại không lớn hơn vMax, thuật toán sẽ cắt bỏ nhánh này vì không thể
mang lại giá trị tốt hơn.
Sau đó, thuật toán sẽ thử hai lựa chọn:
- Lựa chọn 1: Không chọn đồ vật hiện tại và gọi đệ quy để tiếp tục xét các đồ
vật tiếp theo mà không thay đổi trọng lượng và giá trị.
- Lựa chọn 2: Chọn đồ vật hiện tại nếu không vượt quá trọng lượng tối đa ủ c a
balo. Trong trường hợp này, thuật toán sẽ cập nhật trọng lượng và giá trị, sau đó tiếp
tục gọi đệ quy để tìm xem liệu còn giải pháp tốt hơn không.
# Hàm backtracking
def knapsack_backtrack(index, current_weight, current_value, items, W, current_solution):
global vMax, best_solution
# Cập nhật giá trị tối ưu nếu tìm được giải pháp tốt hơn
if current_weight <= W and current_value > vMax: vMax = current_value
best_solution = current_solution[:]
# Nếu đã xét hết các đồ vật, dừng lại
if index >= len(items): return
# Tính cận trên để kiểm tra xem có nên tiếp tục không
if upper_bound(current_weight, current_value, index, items, W) <= vMax:
return # Cắt nhánh vì không thể đạt giá trị tốt hơn vMax
# Bỏ qua đồ vật hiện tại
knapsack_backtrack(index + 1, current_weight, current_value, items, W, current_solution) 21
# Thêm đồ vật hiện tại nếu không vượt quá trọng lượng tối đa
if current_weight + items[index].weight <= W:
current_solution.append(items[index])
knapsack_backtrack(index + 1, current_weight +
items[index].weight, current_value + items[index].value, items, W, current_solution) current_solution.pop()
3.1.5. Cài đặt chương trình hoàn chỉnh
import re import time import openpyxl start = time.time()
# Khởi tạo lớp Item đại diện cho mỗi đồ vật class Item:
def __init__(self, ID, weight, value): self.ID = ID self.weight = weight self.value = value self.ratio = value / weight # Hàm tính cận trên
def upper_bound(w, v, index, items, W): if w >= W: return 0 bound = v total_weight = w
# Tính giá trị tối đa có thể đạt được từ index hiện tại
for i in range(index, len(items)):
if total_weight + items[i].weight <= W:
total_weight += items[i].weight bound += items[i].value else: break return bound
# Hàm backtracking
def knapsack_backtrack(index, current_weight, current_value, items, W, current_solution):
global vMax, best_solution
# Cập nhật giá trị tối ưu nếu tìm được giải pháp tốt hơn
if current_weight <= W and current_value > vMax: vMax = current_value
best_solution = current_solution[:]
# Nếu đã xét hết các đồ vật, dừng lại
if index >= len(items): return
# Tính cận trên để kiểm tra xem có nên tiếp tục không
if upper_bound(current_weight, current_value, index, items, W) <= vMax: 22