-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathutils.py
186 lines (147 loc) · 5.37 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
import os
import json
import numpy as np
from pulp import *
def read_instance(path):
"""
The function takes in input a txt files and return a tuple of the problem's instance
"""
# Read the instance file from the general txt type
f = open(path, 'r')
lines = f.readlines()
distances = []
for i, line in enumerate(lines):
if i == 0:
n_couriers = int(line)
elif i == 1:
n_items = int(line)
elif i == 2:
couriers_size = [int(e) for e in line.split(' ') if e != '\n' and e != '']
elif i == 3:
objects_size = [int(e) for e in line.split(' ') if e != '\n' and e != '']
else:
distances.append([int(e) for e in line.split(' ') if e != '\n' and e != ''])
f.close()
return n_couriers, n_items, couriers_size, objects_size, distances
def load_data(path, instance):
"""
The function for each file in the path, it produces the instance
"""
data = {}
files = sorted(os.listdir(path))
if instance == 0:
for file in files:
data[file] = (read_instance(path + "/" + file))
else:
i = 0
for file in files:
if i == instance:
break
data[file] = (read_instance(path + "/" + file))
i += 1
return data
def saving_file(json_dict, path, filename):
if not os.path.exists(path):
os.makedirs(path)
with open(path + filename, 'w') as file:
json.dump(json_dict, file)
def print_sat(asg):
for k in range(len(asg)):
print("Courier = ", k)
for i in range(len(asg[k])):
print(asg[k][i])
def get_dict(seconds, optimal, obj, res):
return {
'time': seconds,
'optimal': optimal,
'obj': obj,
'sol': res
}
def creating_path(instance,num_items):
"""
Function use to create the list of items for each courier which will be used by the json dict,
In particular taken the dict {start:end} in return the list in the correct order.
Ex input {1:5,4:6,5:4,6:1} where 6 in num_items, the function will return a list
[1,5,4], this list will used to write it in the json dict
"""
if instance == {}:
return []
elem = instance[num_items]
items_for_courier = [elem + 1]
while elem != num_items:
elem = instance[elem]
items_for_courier.append(elem + 1)
return items_for_courier[:-1]
def format_output_smtlib(result, num_items, time, opt):
obj = int(result[0])
time = int(time)
all_dist = []
for i in range(1, len(result)):
all_dist.append(creating_path(result[i], num_items))
return get_dict(time, opt,obj,all_dist)
def sorting_couriers(value):
courier_size = value[2]
size_pos = {}
# Initialization
for i in range(len(courier_size)):
size_pos[courier_size[i]] = []
for i in range(len(courier_size)):
size_pos[courier_size[i]].append(i)
courier_size_copy = courier_size.copy()
courier_size_copy.sort(reverse=True)
corresponding_dict = {}
for i in range(len(courier_size)):
corresponding_dict[i] = size_pos[courier_size_copy[i]][0]
size_pos[courier_size_copy[i]].pop(0)
return corresponding_dict
def sorting_correspondence(res, corresponding_dict):
'''
:param res: list of variables returned by a certain model
:param corresponding_dict: dictionary where the keys are the couriers
couriers in order and the values are the
corresponding couriers before the sorting
:result: the set of result reordered according to the original instance
'''
# We reorder only the result whose first dimension is M
if not isinstance(res, list):
return res
if len(res) != len(corresponding_dict):
return res
final_res = [[] for _ in range(len(res))]
# Assigned the corrispondences with the dictionary
for i in range(len(res)):
courier = corresponding_dict[i]
final_res[courier] = res[i]
return final_res
def set_lower_bound(distances, all_travel):
"""
:param distances: matrix of distances
:result lb: the lower bound for the objective funciton
:result dist_lb: the lower bound for the array of courier distances
"""
last_row = distances[-1]
last_column = [distances[i][-1] for i in range(len(distances[0]))]
value1 = last_column[np.argmax(last_row)] + max(last_row)
value2 = last_row[np.argmax(last_column)] + max(last_column)
lb = max(value1, value2)
if not all_travel:
dist_lb = 0
else:
value1 = last_column[np.argmin(last_row)] + min(last_row)
value2 = last_row[np.argmin(last_column)] + min(last_column)
dist_lb = min(value1, value2)
return (lb, dist_lb)
def set_upper_bound(distances, all_travel, couriers):
'''
:param distances: matrix of distances
:param all_travel: boolean true if max(items_size) <= min(courier_size)
return the two possible upper bounds
'''
items = len(distances) - 1
if not all_travel:
return sum([max(distances[i]) for i in range(items+1)])
else:
dist_np = np.array(distances)
dist_sorted = dist_np[np.max(dist_np, axis=0).argsort()]
max_long_path = sum([max(dist_sorted[i]) for i in range(couriers-1, items+1)])
return int(max_long_path)