您當前的位置:首頁 > 體育

運籌學筆記---分支定界 (branch and bound)求解TSP問題

作者:由 IELBHJY 發表于 體育時間:2021-10-06

1、方法簡介

分支定界我理解就是一種有規律的列舉,所以它是可以求出精確的解。分支定界幾個關鍵點就是設定界限函式,隨著搜尋的過程中逐漸更新界限,直至上界和下界重合;構建節點表,在每個分支的過程中需要將資訊記錄下來,按照某一個標準在節點表裡儲存,後續取點刪點。

運籌學筆記---分支定界 (branch and bound)求解TSP問題

2、方法應用

下邊以b&b在求解tsp中的應用來說明,不同問題思路相近,大同小異。求解步驟如下:

(1)規約費用矩陣

。即使費用矩陣中每一行每一列都包含0元素,此時規約係數就是該問題的一個下界。

運籌學筆記---分支定界 (branch and bound)求解TSP問題

(2)選擇分支邊

。在(a,b)處分支可以有兩個選擇:一個是選擇從a點到b點;另外就是選擇從a點不到b點。如果選擇了a到b那就就應該從費用矩陣裡將第a行和第b列對應的費用值剔除,因為tsp問題裡每一個點只能經過一次。然後還有防止路徑成環修改其他的費用值,這個後邊專門說。如果選擇a點不到b點,表明a,b點都沒有被選,只需要將費用矩陣裡(a,b)對應的費用值改為正無窮即可,表明後續不再選擇a點到b點。

(3)將每個分支的矩陣加入優先佇列中,按照下界從小到大排序。

每次分支後,從優先佇列裡選擇下界最小的那張表進行後續分支。

(4)防止成環處理。防止成環,也就是說所有點還沒有訪問完就回到起點,即第一次分支選擇點a到點b,第二次分支選擇點b到點c,那麼後續分支中如果選擇點c到點a,那麼就會形成a,b,c的環路。導致解是不可行的,因此需要做出修改。

運籌學筆記---分支定界 (branch and bound)求解TSP問題

3、演算法實現

Point類

public

class

point

{

public

double

c

[][];

//費用矩陣

public

int

rowNumber

[];

// 費用矩陣的行號

public

int

colNumber

[];

//費用矩陣對應的列號

public

int

ad

[];

//路徑

public

int

k

// 階數

public

double

lowbound

// 下界

public

point

int

count

){

c

=

new

double

count

][

count

];

rowNumber

=

new

int

count

];

colNumber

=

new

int

count

];

ad

=

new

int

Main

city

];

k

=

count

}

}

public

class

BBTSP

{

public

static

int

n

=

Main

city

/**

* 計算某一行最小值和次小值

* @param p 點

* @param row p的第row行

* @return 返回 第row行的最小值和次小值

*/

double

[]

row_min

point

p

int

row

){

double

result

[]=

new

double

2

];

if

p

c

row

][

0

]<

p

c

row

][

1

]){

result

0

]=

p

c

row

][

0

];

result

1

]=

p

c

row

][

1

];

}

else

{

result

0

]=

p

c

row

][

1

];

result

1

]=

p

c

row

][

0

];

}

for

int

i

=

2

i

<

p

k

i

++){

if

p

c

row

][

i

]<

result

0

]){

result

1

]=

result

0

];

result

0

]=

p

c

row

][

i

];

}

else

if

p

c

row

][

i

]<

result

1

]){

result

1

]=

p

c

row

][

i

];

}

}

return

result

}

double

[]

col_min

point

p

int

col

){

double

result

[]=

new

double

2

];

if

p

c

0

][

col

]<

p

c

1

][

col

]){

result

0

]=

p

c

0

][

col

];

result

1

]=

p

c

1

][

col

];

}

else

{

result

0

]=

p

c

1

][

col

];

result

1

]=

p

c

0

][

col

];

}

for

int

i

=

2

i

<

p

k

i

++){

if

p

c

i

][

col

]<

result

0

]){

result

1

]=

result

0

];

result

0

]=

p

c

i

][

col

];

}

else

if

p

c

i

][

col

]<

result

1

]){

result

1

]=

p

c

i

][

col

];

}

}

return

result

}

/**

* 規約矩陣

* @param p 點

* @return p對應的費用矩陣的規約值

*/

double

changeMaxtrix

point

p

){

double

sum

=

0

temp

for

int

i

=

0

i

<

p

k

i

++){

temp

=

row_min

p

i

)[

0

];

for

int

j

=

0

j

<

p

k

j

++){

p

c

i

][

j

]-=

temp

}

sum

+=

temp

}

for

int

i

=

0

i

<

p

k

i

++){

temp

=

col_min

p

i

)[

0

];

for

int

j

=

0

j

<

p

k

j

++){

p

c

j

][

i

]-=

temp

}

sum

+=

temp

}

return

sum

}

/**

* 選擇分支邊

* @param p 點

* @return 返回分支邊

*/

double

[]

edge_sel

point

p

){

int

i

j

double

temp

d

=-

1

double

result

[]=

new

double

3

];

double

row_value

[]=

new

double

p

k

];

double

col_value

[]=

new

double

p

k

];

for

i

=

0

i

<

p

k

i

++){

row_value

i

]=

row_min

p

i

)[

1

];

}

for

i

=

0

i

<

p

k

i

++){

col_value

i

]=

col_min

p

i

)[

1

];

}

for

i

=

0

i

<

p

k

i

++){

for

j

=

0

j

<

p

k

j

++){

if

p

c

i

][

j

]==

0

{

temp

=

row_value

i

+

col_value

j

];

if

temp

>

d

{

d

=

temp

result

0

=

d

result

1

=

i

result

2

=

j

}

}

}

}

return

result

}

/**

* 修改費用矩陣,刪除對應行和列

* @param p 點

* @param vk 第vk行

* @param vl 第vl列

* @return 返回修改後的點

*/

point

del_rowcolnew

point

p

int

vk

int

vl

){

point

result

=

new

point

p

k

-

1

);

result

k

=

p

k

-

1

int

i

=

0

int

j

=

0

int

r

c

for

r

=

0

r

<

p

k

r

++){

j

=

0

if

r

==

vk

){

continue

;}

for

c

=

0

c

<

p

k

c

++){

if

c

==

vl

){

continue

;}

result

c

i

][

j

]=

p

c

r

][

c

];

j

++;

}

i

++;

}

i

=

0

for

r

=

0

r

<

p

k

r

++){

if

r

==

vk

){

continue

;}

result

rowNumber

i

]=

p

rowNumber

r

];

i

++;

}

i

=

0

for

r

=

0

r

<

p

k

r

++){

if

r

==

vl

){

continue

;}

result

colNumber

i

]=

p

colNumber

r

];

i

++;

}

for

r

=

0

r

<

n

r

++){

result

ad

r

]=

p

ad

r

];

}

return

result

}

/**

* 防止成環操作

* @param p

* @param vk

* @param vl

* @return

*/

point

edge_bypnew

point

p

int

vk

int

vl

){

int

vk1

=

p

rowNumber

vk

];

int

vl1

=

p

colNumber

vl

];

p

ad

vk1

]=

vl1

if

vk

>=

0

&&

vl

>=

0

){

p

c

vl

][

vk

]=

Double

MAX_VALUE

}

int

e

=

vk1

int

s

=

vl1

int

c

=

0

while

c

<

n

){

for

int

i

=

0

i

<

n

i

++){

if

p

ad

i

]==

e

){

e

=

i

break

}

}

break

}

c

=

0

while

c

<

n

){

for

int

i

=

0

i

<

n

i

++){

if

i

==

s

&&

p

ad

i

]>-

1

){

s

=

p

ad

i

];

break

}

}

break

}

int

d

for

c

=

0

c

<

p

rowNumber

length

c

++){

for

d

=

0

d

<

p

colNumber

length

d

++){

if

p

rowNumber

c

]==

s

&&

p

colNumber

d

]==

e

){

p

c

c

][

d

]=

Double

MAX_VALUE

}

}

}

return

p

}

/**

* 初始化

* @param c

* @param m

* @return

*/

point

initalnew

double

c

[][],

int

m

){

int

i

j

point

node

=

new

point

m

);

for

i

=

0

i

<

m

i

++){

for

j

=

0

j

<

m

j

++){

node

c

i

][

j

]=

c

i

][

j

];

}

}

for

i

=

0

i

<

m

i

++){

node

rowNumber

i

]=

i

node

colNumber

i

]=

i

}

for

i

=

0

i

<

m

i

++){

node

ad

i

]=-

1

}

node

k

=

m

return

node

}

}

以28個點的tsp為例,測試結果如下:

運籌學筆記---分支定界 (branch and bound)求解TSP問題

標簽: Result  ++  row  col  param