Conversation
| for length, count in sorted(data['lengths'].items()): | ||
| print(f" 길이 {length}: {count}개") | ||
|
|
||
| def avg_loc(all_orders, all_bundles): |
There was a problem hiding this comment.
avg_loc 함수: all_bundles를 넣으면, 각 번들의 픽업 지점과 배송 지점의 중점 좌표를 계산해서 return해주는 함수
(픽업 위도, 픽업 경도), (배송 위도, 배송 경도) 형태
|
|
||
| return bundles_avg_loc | ||
|
|
||
| def haversine_distance(coord1, coord2): |
There was a problem hiding this comment.
haversine_distance 함수: 두 지점의 위도와 경도를 입력하면 두 지점 사이의 거리를 계산해주는 함수
| distance = R * c | ||
| return distance | ||
|
|
||
| def dist_mat_by_loc(all_bundles_avg_loc): |
There was a problem hiding this comment.
dist_mat_by_loc 함수: 모든 번들들의 중점 좌표를 입력하면, 이를 통해 번들 간의 거리 matrix를 return해주는 함수. 이때 거리는 픽업, 배송을 모두 고려하여(회의 때 설명한 0.25 가중치 사용하는 그 공식) 하나의 값으로 계산함.
| for j in range(i+1, N): | ||
| dist = all_bundles_dist_mat[i, j] + all_bundles_dist_mat[i+N, j+N] + (all_bundles_dist_mat[i, i+N] + all_bundles_dist_mat[i, j+N] + all_bundles_dist_mat[i+N, j] + all_bundles_dist_mat[j, j+N])*0.25 | ||
|
|
||
| heapq.heappush(dist_heap, [dist, i, len(all_bundles[i].shop_seq), j, len(all_bundles[j].shop_seq)]) |
There was a problem hiding this comment.
두 번들 간의 거리를 계산하여 heapq에 넣어 거리가 작은 순서로 뽑아낼 수 있게 함
| if len_one >= 3: | ||
| len_one_heap = [item for item in dist_heap if item[2] == 1 or item[4] == 1] | ||
| heapq.heapify(len_one_heap) | ||
| dist_heap = len_one_heap |
There was a problem hiding this comment.
길이가 1인 번들이 있는 경우에 우선권을 주기 위한 코드.
그렇다고 모든 길이가 1인 번들을 처리하려고 하면, 마지막 남은 몇개의 번들이 억지로 묶일 가능성이 있어서, 길이가 1인 번들이 3개 일 때 까지만 우선권을 부여.
| cant_merge_list = [] | ||
|
|
||
| while True : | ||
| no_walk_bundles = [bundle for bundle in all_bundles if bundle.rider.type != 'WALK'] |
There was a problem hiding this comment.
뒤에서 발생하는 Bike 부족 문제로 인해 혹시 맨 처음 할당한 walk들은 안 건드리면 어떻게 될까 싶어 추가했던 코드. 결론적으로는 효용이 크지 않은 것 같음. 다시 원래대로 돌리려면 밑에 나오는 no_walk_bundles를 다 all_bundles로 수정하면 됨.
| while True : | ||
| no_walk_bundles = [bundle for bundle in all_bundles if bundle.rider.type != 'WALK'] | ||
| single_order_bundles = [(-bundle.cost, bundle) for bundle in all_bundles if len(bundle.shop_seq) == 1 and bundle.shop_seq[0] not in cant_merge_list] | ||
| if len(single_order_bundles) <= 3 : |
There was a problem hiding this comment.
중점 때와 마찬가지로, 길이가 1인 번들을 전부 다 없애려고 하면, 억지로 묶이는 비효율이 발생하는 것 같아 적당히 3개 정도에서 멈추게 함.
| while time.time() - start_time < timelimit and len(all_bundles) > 1: | ||
| no_walk_bundles = [bundle for bundle in all_bundles if bundle.rider.type != 'WALK'] | ||
| iter += 1 | ||
| num_less_two = len([bundle for bundle in no_walk_bundles if len(bundle.shop_seq) <= 2]) |
There was a problem hiding this comment.
모든 번들을 다 고려해서 해체 후 재조립을 하려고 하니 큰 번들들이 대상이 되었을 때는 시간을 너무 많이 잡아먹어서, 일단은 길이가 2 이하인 번들들만 우선적으로 해체 후 재조립을 시행하도록 함. 코드 돌려보면 확실히 개선이 빨리빨리 이루어짐.
| no_walk_bundles = [bundle for bundle in all_bundles if bundle.rider.type != 'WALK'] | ||
| iter += 1 | ||
| num_less_two = len([bundle for bundle in no_walk_bundles if len(bundle.shop_seq) <= 2]) | ||
| if num_less_two >= 20: |
There was a problem hiding this comment.
적당히 20개 보다 많을 때 까지만 우선권을 줌
| bundle_triples = sorted(bundle_triples, key=lambda x: x[0]) | ||
| return bundle_triples | ||
|
|
||
| def find_nearest_triples_with_middle(all_orders, all_bundles): |
There was a problem hiding this comment.
중점 아이디어를 이용하여 가장 가까운 세개의 번들을 찾는 함수.
| #print(f'one bundle : {best_bundles}') | ||
|
|
||
| # Try to split into two bundles | ||
| if len(merged_orders) > 1: |
There was a problem hiding this comment.
원래 0이었는데 1보다 클 때로 수정(즉, 2명 이상 남아있어야 함.). 두 개로 나누는 상황에서, 만약 배달원이 1명만 남아 있다면 두 개로 못 쪼개야 하는데, 0을 사용하면 그러한 상황을 걸러낼 수 없음.
| #print(f'two bundles : {best_bundles}') | ||
|
|
||
| # Try to split into three bundles | ||
| if len(merged_orders) > 2: |
There was a problem hiding this comment.
위와 같은 이유에서 0을 2로 수정함.
@Hyelim-P @Hoyeol-Yoon
지난 일요일 회의 때 얘기했던 중점 아이디어 코드