Skip to content

Commit d91469c

Browse files
author
Viet Tien Pham
committed
up stuff
1 parent 4fd83ed commit d91469c

File tree

20 files changed

+971
-690
lines changed

20 files changed

+971
-690
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ lightning_logs
3131
data/cache
3232
data/instances
3333
logs
34-
nohup.out
34+
*.out

common/cal_reward.py

Lines changed: 36 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,40 @@
1-
import sys, os
2-
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
3-
4-
import numba as nb
51
import numpy as np
6-
from common.ops import run_parallel, convert_vars_np
7-
from common.nb_utils import gen_tours_batch, calc_length
8-
9-
10-
def get_reward(vars, actions=None, tours_batch=None):
11-
if tours_batch is None:
12-
tours_batch = gen_tours_batch(actions)
13-
if not isinstance(vars, dict):
14-
vars = convert_vars_np(vars)
15-
16-
reward1 = run_parallel(reward_ins, tours_batch, vars['adj'], vars['service_time'], vars['clss'], k = 1)
17-
# reward2 = run_parallel(reward_ins, tours_batch, vars['adj'], vars['service_time'], vars['clss'], k = 2)
18-
# reward3 = run_parallel(reward_ins, tours_batch, vars['adj'], vars['service_time'], vars['clss'], k = 3)
19-
# return np.float32([reward1, reward2, reward3]).T @ np.float32([1e2, 1e0, 1e-2])
20-
return reward1
21-
22-
def get_Ts(vars, actions=None, tours_batch=None):
23-
if tours_batch is None:
24-
tours_batch = gen_tours_batch(actions)
25-
reward1 = run_parallel(reward_ins, tours_batch, adj=vars['adj'], service=vars['service_time'], clss=vars['clss'], k = 1)
26-
reward2 = run_parallel(reward_ins, tours_batch, adj=vars['adj'], service=vars['service_time'], clss=vars['clss'], k = 2)
27-
reward3 = run_parallel(reward_ins, tours_batch, adj=vars['adj'], service=vars['service_time'], clss=vars['clss'], k = 3)
28-
return np.float32([reward1, reward2, reward3]).T
2+
import torch
3+
from common.local_search import lsRL
294

30-
def get_Ts_RL(vars, actions=None, tours_batch=None):
31-
if tours_batch is None:
32-
tours_batch = gen_tours_batch(actions)
33-
34-
if not isinstance(vars, dict):
35-
vars = convert_vars_np(vars)
36-
37-
reward1 = run_parallel(reward_ins, tours_batch, vars['adj'], vars['service_time'], vars['clss'], k = 1)
38-
reward2 = run_parallel(reward_ins, tours_batch, vars['adj'], vars['service_time'], vars['clss'], k = 2)
39-
reward3 = run_parallel(reward_ins, tours_batch, vars['adj'], vars['service_time'], vars['clss'], k = 3)
40-
return np.float32([reward1, reward2, reward3]).T
5+
def action_to_tours(action):
6+
zero_indices = np.where(action == 0)[0]
7+
split_indices = np.concatenate(([-1], zero_indices, [len(action)]))
8+
lengths = np.diff(split_indices) - 1
9+
valid_lengths = lengths[lengths > 0]
10+
nonzero_action = action[action != 0]
11+
tours = np.split(nonzero_action, np.cumsum(valid_lengths)[:-1])
12+
# Tìm độ dài lớn nhất để padding
13+
max_len = max(len(r) for r in tours)
4114

42-
@nb.njit(nb.float32(nb.int32[:, :], nb.float32[:, :], nb.float32[:], nb.int32[:], nb.int32), nogil=True)
43-
def reward_ins(tours, adj, service, clss, k):
44-
r = 0.0
45-
for tour in tours:
46-
pos = np.where(clss[tour] == k)[0]
47-
if len(pos) <= 0:
48-
continue
49-
candidate = tour[:pos[-1] + 1]
50-
length = calc_length(adj, service, candidate)
51-
r = max(r, length)
52-
return r
15+
# Padding để đảm bảo tất cả có cùng kích thước
16+
padded = np.zeros((len(tours), max_len+2), dtype=np.int32)
17+
for idx, tour in enumerate(tours):
18+
padded[idx][1:len(tour)+1] = tour
19+
return padded
5320

54-
@nb.njit(nb.float32(nb.float32[:, :], nb.float32[:], nb.int32[:], nb.int32[:], nb.int32), nogil=True)
55-
def reward_in(adj, service, clss, tour, k):
56-
r = 0.0
57-
pos = np.where(clss[tour] == k)[0]
58-
if len(pos) > 0:
59-
candidate = tour[:pos[-1] + 1]
60-
length = calc_length(adj, service, candidate)
61-
r = max(r, length)
62-
return r
21+
def calc_reward(action, td, pos_val=[1,2,3], **kwargs):
22+
tours = action_to_tours(action)
23+
prior = td['clss'][tours]
24+
total_time = td['service_times'][tours]
25+
shortest_traversal_time = td['adj'][tours[:, :-1], tours[:, 1:]]
26+
total_time[:, 1:] += shortest_traversal_time
27+
total_time = torch.cumsum(total_time, dim=1)
28+
# if kwargs.get("local_search", False):
29+
# tours = lsRL(td, tours)
30+
rs = []
31+
for p in pos_val:
32+
pos = torch.nonzero(prior == p, as_tuple=True)
33+
if len(pos[0]) == 0:
34+
pos = [[0], [0]]
35+
rs.append(total_time[pos].max())
36+
if kwargs.get("return_list", False):
37+
return rs
38+
if kwargs.get("return_numpy", False):
39+
return np.array(rs)
40+
return torch.tensor(rs)

common/inter.py

Lines changed: 135 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,141 +1,138 @@
1-
import sys, os
2-
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
3-
4-
import numba as nb
5-
import numpy as np
6-
from common.nb_utils import calc_length, calc_demand
7-
from common.cal_reward import reward_in
8-
from common.consts import *
9-
10-
@nb.njit(nb.float32(nb.float32[:, :], nb.float32[:], nb.float32[:], nb.float32[:], nb.int32[:], nb.int32[:]), nogil=True)
11-
def once_interP(adj, service, demand, remain_demand, sub1, sub2):
12-
start, end, min_delta = 0, 0, 0
13-
14-
best = max(calc_length(adj, service, sub1[1:]) + adj[sub1[0], sub1[1]],
15-
calc_length(adj, service, sub2[1:]) + adj[sub2[0], sub2[1]])
1+
# import numba as nb
2+
# import numpy as np
3+
# from common.nb_utils import calc_length, calc_demand
4+
# from common.cal_reward import reward_in
5+
# from common.consts import *
6+
7+
# @nb.njit(nb.float32(nb.float32[:, :], nb.float32[:], nb.float32[:], nb.float32[:], nb.int32[:], nb.int32[:]), nogil=True)
8+
# def once_interP(adj, service, demand, remain_demand, sub1, sub2):
9+
# start, end, min_delta = 0, 0, 0
10+
11+
# best = max(calc_length(adj, service, sub1[1:]) + adj[sub1[0], sub1[1]],
12+
# calc_length(adj, service, sub2[1:]) + adj[sub2[0], sub2[1]])
1613

17-
demand_best = calc_demand(demand, sub1[1:]), calc_demand(demand, sub2[1:])
18-
19-
for i in range(1, len(sub1)):
20-
for j in range(1, len(sub2)):
21-
candidate1 = sub1.copy()
22-
candidate2 = sub2.copy()
23-
candidate1[i], candidate2[j] = candidate2[j], candidate1[i]
24-
candidate_demand = calc_demand(demand, candidate1[1:]), calc_demand(demand, candidate2[1:])
25-
exceed_demand = (candidate_demand[0] - demand_best[0] > remain_demand[0]) or \
26-
(candidate_demand[1] - demand_best[1] > remain_demand[1])
27-
if exceed_demand:
28-
continue
29-
30-
length = max(calc_length(adj, service, candidate1[1:]) + adj[candidate1[0], candidate1[1]],
31-
calc_length(adj, service, candidate2[1:]) + adj[candidate2[0], candidate2[1]])
32-
33-
change = length - best
34-
if change < min_delta:
35-
start, end, min_delta, best, demand_best = i, j, change, length, candidate_demand
36-
37-
if min_delta < -1e-6:
38-
sub1[start], sub2[end] = sub2[end], sub1[start]
39-
return min_delta
40-
else:
41-
return 0.0
42-
43-
44-
@nb.njit(nb.float32(nb.float32[:, :], nb.float32[:], nb.int32[:], nb.float32[:], nb.float32[:], nb.int32[:], nb.int32[:], nb.int32), nogil=True)
45-
def once_interU(adj, service, clss, demand, remain_demand, sub1, sub2, k):
46-
start, end, min_delta = 0, 0, 0
47-
48-
best = np.zeros(k)
49-
for t in range(1, k+1):
50-
best[t-1] = max(reward_in(adj, service, clss, sub1, k=t),
51-
reward_in(adj, service, clss, sub2, k=t))
52-
length = np.zeros(k)
53-
demand_best = calc_demand(demand, sub1[1:]), calc_demand(demand, sub2[1:])
54-
for i in range(1, len(sub1)):
55-
for j in range(1, len(sub2)):
56-
candidate1 = sub1.copy()
57-
candidate2 = sub2.copy()
58-
candidate1[i], candidate2[j] = candidate2[j], candidate1[i]
59-
candidate_demand = calc_demand(demand, candidate1[1:]), calc_demand(demand, candidate2[1:])
60-
exceed_demand = (candidate_demand[0] - demand_best[0] > remain_demand[0]) or \
61-
(candidate_demand[1] - demand_best[1] > remain_demand[1])
62-
63-
if exceed_demand:
64-
continue
14+
# demand_best = calc_demand(demand, sub1[1:]), calc_demand(demand, sub2[1:])
15+
16+
# for i in range(1, len(sub1)):
17+
# for j in range(1, len(sub2)):
18+
# candidate1 = sub1.copy()
19+
# candidate2 = sub2.copy()
20+
# candidate1[i], candidate2[j] = candidate2[j], candidate1[i]
21+
# candidate_demand = calc_demand(demand, candidate1[1:]), calc_demand(demand, candidate2[1:])
22+
# exceed_demand = (candidate_demand[0] - demand_best[0] > remain_demand[0]) or \
23+
# (candidate_demand[1] - demand_best[1] > remain_demand[1])
24+
# if exceed_demand:
25+
# continue
26+
27+
# length = max(calc_length(adj, service, candidate1[1:]) + adj[candidate1[0], candidate1[1]],
28+
# calc_length(adj, service, candidate2[1:]) + adj[candidate2[0], candidate2[1]])
29+
30+
# change = length - best
31+
# if change < min_delta:
32+
# start, end, min_delta, best, demand_best = i, j, change, length, candidate_demand
33+
34+
# if min_delta < -1e-6:
35+
# sub1[start], sub2[end] = sub2[end], sub1[start]
36+
# return min_delta
37+
# else:
38+
# return 0.0
39+
40+
41+
# @nb.njit(nb.float32(nb.float32[:, :], nb.float32[:], nb.int32[:], nb.float32[:], nb.float32[:], nb.int32[:], nb.int32[:], nb.int32), nogil=True)
42+
# def once_interU(adj, service, clss, demand, remain_demand, sub1, sub2, k):
43+
# start, end, min_delta = 0, 0, 0
44+
45+
# best = np.zeros(k)
46+
# for t in range(1, k+1):
47+
# best[t-1] = max(reward_in(adj, service, clss, sub1, k=t),
48+
# reward_in(adj, service, clss, sub2, k=t))
49+
# length = np.zeros(k)
50+
# demand_best = calc_demand(demand, sub1[1:]), calc_demand(demand, sub2[1:])
51+
# for i in range(1, len(sub1)):
52+
# for j in range(1, len(sub2)):
53+
# candidate1 = sub1.copy()
54+
# candidate2 = sub2.copy()
55+
# candidate1[i], candidate2[j] = candidate2[j], candidate1[i]
56+
# candidate_demand = calc_demand(demand, candidate1[1:]), calc_demand(demand, candidate2[1:])
57+
# exceed_demand = (candidate_demand[0] - demand_best[0] > remain_demand[0]) or \
58+
# (candidate_demand[1] - demand_best[1] > remain_demand[1])
59+
60+
# if exceed_demand:
61+
# continue
6562

66-
for t in range(1, k+1):
67-
length[t-1] = max(reward_in(adj, service, clss, candidate1, k = t),
68-
reward_in(adj, service, clss, candidate2, k = t))
69-
change = 0
70-
for t in range(k):
71-
c = length[t] - best[t]
72-
if c > 0:
73-
break
74-
change += c*(10**(k-t))
75-
76-
if change < min_delta:
77-
start, end, min_delta, best, demand_best = i, j, change, length, candidate_demand
78-
79-
if min_delta < -1e-6:
80-
sub1[start], sub2[end] = sub2[end], sub1[start]
81-
return min_delta
82-
else:
83-
return 0.0
84-
85-
@nb.njit(nb.int32[:,:](nb.int32[:, :], nb.float32[:, :], nb.float32[:], nb.int32[:], nb.float32[:], nb.int32), nogil=True)
86-
def interP(tours, adj, service, clss, demand, k):
87-
change = True
88-
it = 0
89-
remain_demand = np.ones(2, np.float32)
90-
while change and it < EPS:
91-
change = False
92-
for i in range(len(tours) - 1):
93-
for j in range(i + 1, len(tours)):
94-
pos1 = np.where(clss[tours[i]] == k)[0]
95-
pos2 = np.where(clss[tours[j]] == k)[0]
96-
if len(pos1) <= 0 or len(pos2) <= 0:
97-
continue
98-
99-
sub1 = tours[i][pos1[0] - 1: pos1[-1] + 1]
100-
sub2 = tours[j][pos2[0] - 1: pos2[-1] + 1]
101-
102-
sub_change = -1.0
103-
sub_it = 0
104-
while sub_change < -1e-6 and sub_it < EPS:
105-
remain_demand[0] = 1 - demand[tours[i]].sum()
106-
remain_demand[1] = 1 - demand[tours[j]].sum()
107-
sub_change = once_interP(adj, service, demand, remain_demand, sub1, sub2)
108-
sub_it += 1
109-
if sub_it >= 2:
110-
change = True
111-
it += 1
112-
return tours
113-
114-
@nb.njit(nb.int32[:,:](nb.int32[:, :], nb.float32[:, :], nb.float32[:], nb.int32[:], nb.float32[:], nb.int32), nogil=True)
115-
def interU(tours, adj, service, clss, demand, k):
116-
change = True
117-
it = 0
118-
remain_demand = np.ones(2, np.float32)
119-
while change and it < EPS:
120-
change = False
121-
for i in range(len(tours) - 1):
122-
for j in range(i + 1, len(tours)):
123-
pos1 = np.where(clss[tours[i]] == k)[0]
124-
pos2 = np.where(clss[tours[j]] == k)[0]
125-
if len(pos1) <= 0 or len(pos2) <= 0:
126-
continue
63+
# for t in range(1, k+1):
64+
# length[t-1] = max(reward_in(adj, service, clss, candidate1, k = t),
65+
# reward_in(adj, service, clss, candidate2, k = t))
66+
# change = 0
67+
# for t in range(k):
68+
# c = length[t] - best[t]
69+
# if c > 0:
70+
# break
71+
# change += c*(10**(k-t))
72+
73+
# if change < min_delta:
74+
# start, end, min_delta, best, demand_best = i, j, change, length, candidate_demand
75+
76+
# if min_delta < -1e-6:
77+
# sub1[start], sub2[end] = sub2[end], sub1[start]
78+
# return min_delta
79+
# else:
80+
# return 0.0
81+
82+
# @nb.njit(nb.int32[:,:](nb.int32[:, :], nb.float32[:, :], nb.float32[:], nb.int32[:], nb.float32[:], nb.int32), nogil=True)
83+
# def interP(tours, adj, service, clss, demand, k):
84+
# change = True
85+
# it = 0
86+
# remain_demand = np.ones(2, np.float32)
87+
# while change and it < EPS:
88+
# change = False
89+
# for i in range(len(tours) - 1):
90+
# for j in range(i + 1, len(tours)):
91+
# pos1 = np.where(clss[tours[i]] == k)[0]
92+
# pos2 = np.where(clss[tours[j]] == k)[0]
93+
# if len(pos1) <= 0 or len(pos2) <= 0:
94+
# continue
95+
96+
# sub1 = tours[i][pos1[0] - 1: pos1[-1] + 1]
97+
# sub2 = tours[j][pos2[0] - 1: pos2[-1] + 1]
98+
99+
# sub_change = -1.0
100+
# sub_it = 0
101+
# while sub_change < -1e-6 and sub_it < EPS:
102+
# remain_demand[0] = 1 - demand[tours[i]].sum()
103+
# remain_demand[1] = 1 - demand[tours[j]].sum()
104+
# sub_change = once_interP(adj, service, demand, remain_demand, sub1, sub2)
105+
# sub_it += 1
106+
# if sub_it >= 2:
107+
# change = True
108+
# it += 1
109+
# return tours
110+
111+
# @nb.njit(nb.int32[:,:](nb.int32[:, :], nb.float32[:, :], nb.float32[:], nb.int32[:], nb.float32[:], nb.int32), nogil=True)
112+
# def interU(tours, adj, service, clss, demand, k):
113+
# change = True
114+
# it = 0
115+
# remain_demand = np.ones(2, np.float32)
116+
# while change and it < EPS:
117+
# change = False
118+
# for i in range(len(tours) - 1):
119+
# for j in range(i + 1, len(tours)):
120+
# pos1 = np.where(clss[tours[i]] == k)[0]
121+
# pos2 = np.where(clss[tours[j]] == k)[0]
122+
# if len(pos1) <= 0 or len(pos2) <= 0:
123+
# continue
127124

128-
sub1 = tours[i][: pos1[-1] + 1]
129-
sub2 = tours[j][: pos2[-1] + 1]
130-
131-
sub_change = -1.0
132-
sub_it = 0
133-
while sub_change < -1e-6 and sub_it < EPS:
134-
remain_demand[0] = 1 - demand[tours[i]].sum()
135-
remain_demand[1] = 1 - demand[tours[j]].sum()
136-
sub_change = once_interU(adj, service, clss, demand, remain_demand, sub1, sub2, k)
137-
sub_it += 1
138-
if sub_it >= 2:
139-
change = True
140-
it += 1
141-
return tours
125+
# sub1 = tours[i][: pos1[-1] + 1]
126+
# sub2 = tours[j][: pos2[-1] + 1]
127+
128+
# sub_change = -1.0
129+
# sub_it = 0
130+
# while sub_change < -1e-6 and sub_it < EPS:
131+
# remain_demand[0] = 1 - demand[tours[i]].sum()
132+
# remain_demand[1] = 1 - demand[tours[j]].sum()
133+
# sub_change = once_interU(adj, service, clss, demand, remain_demand, sub1, sub2, k)
134+
# sub_it += 1
135+
# if sub_it >= 2:
136+
# change = True
137+
# it += 1
138+
# return tours

0 commit comments

Comments
 (0)