Corin1998 commited on
Commit
4b02f53
·
verified ·
1 Parent(s): 7a72190

Create optimizer.py

Browse files
Files changed (1) hide show
  1. services/optimizer.py +68 -0
services/optimizer.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+ from typing import List
3
+ from ortools.constraint_solver import pywrapcp, routing_enums_pb2
4
+
5
+ def solve_tsp(time_matrix: List[List[float]]) -> List[int]:
6
+ """
7
+ OSRMのduration行列(秒)を入力に、0番ノード(Start)発→全訪問→Start戻りの巡回順序を返す。
8
+ OR-Toolsで解けない場合は貪欲法でフォールバックします。
9
+ 返り値例: [0, 3, 2, 1, 0]
10
+ """
11
+ n = len(time_matrix) if time_matrix else 0
12
+ if n <= 1:
13
+ return list(range(n))
14
+
15
+ # 行列のサニタイズ(Noneや欠損を大値に、対角は0、int秒へ)
16
+ BIG = 10**9
17
+ matrix: List[List[int]] = []
18
+ for i in range(n):
19
+ row_i = []
20
+ for j in range(n):
21
+ try:
22
+ v = time_matrix[i][j]
23
+ v = float(v) if v is not None else BIG
24
+ except Exception:
25
+ v = BIG
26
+ if i == j:
27
+ v = 0.0
28
+ row_i.append(int(max(0, round(v))))
29
+ matrix.append(row_i)
30
+
31
+ # OR-Tools セットアップ
32
+ manager = pywrapcp.RoutingIndexManager(n, 1, 0) # depot=0
33
+ routing = pywrapcp.RoutingModel(manager)
34
+
35
+ def transit_cb(from_index, to_index):
36
+ i = manager.IndexToNode(from_index)
37
+ j = manager.IndexToNode(to_index)
38
+ return matrix[i][j]
39
+
40
+ transit_idx = routing.RegisterTransitCallback(transit_cb)
41
+ routing.SetArcCostEvaluatorOfAllVehicles(transit_idx)
42
+
43
+ params = pywrapcp.DefaultRoutingSearchParameters()
44
+ params.first_solution_strategy = routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
45
+ params.local_search_metaheuristic = routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH
46
+ params.time_limit.FromSeconds(1) # 1秒で切り上げ(HF Spaces向けに軽量)
47
+
48
+ solution = routing.SolveWithParameters(params)
49
+ if solution:
50
+ index = routing.Start(0)
51
+ order: List[int] = []
52
+ while not routing.IsEnd(index):
53
+ order.append(manager.IndexToNode(index))
54
+ index = solution.Value(routing.NextVar(index))
55
+ order.append(manager.IndexToNode(index)) # 最後にdepot(0)へ戻る
56
+ return order
57
+
58
+ # フォールバック:近傍貪欲
59
+ unvisited = set(range(1, n))
60
+ order = [0]
61
+ cur = 0
62
+ while unvisited:
63
+ nxt = min(unvisited, key=lambda j: matrix[cur][j])
64
+ order.append(nxt)
65
+ unvisited.remove(nxt)
66
+ cur = nxt
67
+ order.append(0)
68
+ return order