a-ragab-h-m commited on
Commit
f8ecbbc
·
verified ·
1 Parent(s): b233689

Update google_solver/google_model.py

Browse files
Files changed (1) hide show
  1. google_solver/google_model.py +57 -62
google_solver/google_model.py CHANGED
@@ -1,52 +1,39 @@
1
  from __future__ import print_function
2
- from ortools.constraint_solver import routing_enums_pb2
3
- from ortools.constraint_solver import pywrapcp
4
  import torch
5
  from google_solver.convert_data import convert_data
6
 
7
 
8
- class GoogleActor(object):
 
 
 
9
 
10
  def __init__(self, scale_factor=100):
11
-
12
- if scale_factor is None:
13
- self.scale_factor = 1
14
- else:
15
- self.scale_factor = scale_factor
16
-
17
 
18
  def __call__(self, input):
19
-
20
  drive_times = []
21
  data = convert_data(input, self.scale_factor)
22
- batch_size = len(data)
23
  for datum in data:
24
  routing, assignment = self.compute_route(datum)
25
  total_time = self.compute_total_time(datum, routing, assignment)
26
  drive_times.append(total_time)
27
 
28
- drive_times = torch.tensor(drive_times).float()
29
- return drive_times
30
-
31
-
32
- def compute_distance(self, routing, assignment, num_nodes):
33
- """Prints solution on console."""
34
- cumulative_route_distance = 0
35
- for vehicle_id in range(num_nodes):
36
- index = routing.Start(vehicle_id)
37
- route_distance = 0
38
- while not routing.IsEnd(index):
39
- previous_index = index
40
- index = assignment.Value(routing.NextVar(index))
41
- route_distance += routing.GetArcCostForVehicle(
42
- previous_index, index, vehicle_id)
43
- cumulative_route_distance += route_distance
44
 
45
- cumulative_route_distance = cumulative_route_distance / self.scale_factor
46
- return cumulative_route_distance
 
47
 
 
 
 
 
48
 
49
- def compute_total_time(self, data, routing, assignment):
 
 
50
  time_dimension = routing.GetDimensionOrDie('Time')
51
  total_time = 0
52
  for vehicle_id in range(data['num_vehicles']):
@@ -55,74 +42,82 @@ class GoogleActor(object):
55
  index = assignment.Value(routing.NextVar(index))
56
  time_var = time_dimension.CumulVar(index)
57
  total_time += assignment.Min(time_var)
58
- total_time = total_time/self.scale_factor
59
- return total_time
60
-
61
 
 
62
 
63
  def compute_route(self, input):
 
 
 
 
 
64
 
 
 
 
65
  distance_matrix = input['distance_matrix']
66
  time_matrix = input['time_matrix']
67
  time_windows = input['time_windows']
68
  num_vehicles = input['num_vehicles']
69
  depot = input['depot']
70
 
71
-
72
  manager = pywrapcp.RoutingIndexManager(len(time_matrix), num_vehicles, depot)
73
  routing = pywrapcp.RoutingModel(manager)
74
 
75
  def time_callback(from_index, to_index):
76
- """Returns the travel time between the two nodes."""
77
- # Convert from routing variable Index to time matrix NodeIndex.
78
  from_node = manager.IndexToNode(from_index)
79
  to_node = manager.IndexToNode(to_index)
80
  return time_matrix[from_node][to_node]
81
 
82
  transit_callback_index = routing.RegisterTransitCallback(time_callback)
83
  routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
84
- time = 'Time'
85
  routing.AddDimension(
86
  transit_callback_index,
87
- 10000, # allow waiting time
88
- 10000, # maximum time per vehicle
89
- False, # Don't force start cumul to zero.
90
- time)
91
-
92
- time_dimension = routing.GetDimensionOrDie(time)
93
- # Add time window constraints for each location except depot.
94
- for location_idx, time_window in enumerate(time_windows):
95
- if location_idx == 0:
 
 
96
  continue
97
  index = manager.NodeToIndex(location_idx)
98
- a, b = int(time_window[0]), int(time_window[1])
99
- time_dimension.CumulVar(index).SetRange(a, b)
100
 
101
- # Add time window constraints for each vehicle start node.
 
102
  for vehicle_id in range(num_vehicles):
103
  index = routing.Start(vehicle_id)
104
- a, b = int(time_windows[0][0]), int(time_windows[0][1])
105
- time_dimension.CumulVar(index).SetRange(a, b)
106
 
 
107
  for i in range(num_vehicles):
108
- routing.AddVariableMinimizedByFinalizer(
109
- time_dimension.CumulVar(routing.Start(i)))
110
- routing.AddVariableMinimizedByFinalizer(
111
- time_dimension.CumulVar(routing.End(i)))
112
 
113
- search_parameters = pywrapcp.DefaultRoutingSearchParameters()
114
- search_parameters.first_solution_strategy = (routing_enums_pb2.FirstSolutionStrategy.AUTOMATIC)
115
- assignment = routing.SolveWithParameters(search_parameters)
116
 
 
117
  return routing, assignment
118
 
119
 
 
 
 
120
 
 
 
121
 
122
- def evaluate_google_model(validation_dataset):
 
 
123
  validation_dataset.device = 'cpu'
124
  data = validation_dataset.get_data()
125
  model = GoogleActor(scale_factor=100)
126
- scores = model(data)
127
- return scores
128
-
 
1
  from __future__ import print_function
2
+ from ortools.constraint_solver import routing_enums_pb2, pywrapcp
 
3
  import torch
4
  from google_solver.convert_data import convert_data
5
 
6
 
7
+ class GoogleActor:
8
+ """
9
+ Wrapper class to evaluate VRP solutions using Google's OR-Tools solver.
10
+ """
11
 
12
  def __init__(self, scale_factor=100):
13
+ self.scale_factor = scale_factor if scale_factor is not None else 1
 
 
 
 
 
14
 
15
  def __call__(self, input):
 
16
  drive_times = []
17
  data = convert_data(input, self.scale_factor)
 
18
  for datum in data:
19
  routing, assignment = self.compute_route(datum)
20
  total_time = self.compute_total_time(datum, routing, assignment)
21
  drive_times.append(total_time)
22
 
23
+ return torch.tensor(drive_times).float()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
+ def compute_total_time(self, data, routing, assignment):
26
+ """
27
+ Computes the total time spent across all routes.
28
 
29
+ Args:
30
+ data (dict): Problem data with time matrix and vehicle count.
31
+ routing (RoutingModel): OR-Tools routing model.
32
+ assignment (Assignment): OR-Tools assignment solution.
33
 
34
+ Returns:
35
+ float: Total time (scaled back).
36
+ """
37
  time_dimension = routing.GetDimensionOrDie('Time')
38
  total_time = 0
39
  for vehicle_id in range(data['num_vehicles']):
 
42
  index = assignment.Value(routing.NextVar(index))
43
  time_var = time_dimension.CumulVar(index)
44
  total_time += assignment.Min(time_var)
 
 
 
45
 
46
+ return total_time / self.scale_factor
47
 
48
  def compute_route(self, input):
49
+ """
50
+ Solves the routing problem using OR-Tools.
51
+
52
+ Args:
53
+ input (dict): Data containing distance, time matrix, time windows, and depot index.
54
 
55
+ Returns:
56
+ RoutingModel, Assignment: OR-Tools routing and solution.
57
+ """
58
  distance_matrix = input['distance_matrix']
59
  time_matrix = input['time_matrix']
60
  time_windows = input['time_windows']
61
  num_vehicles = input['num_vehicles']
62
  depot = input['depot']
63
 
 
64
  manager = pywrapcp.RoutingIndexManager(len(time_matrix), num_vehicles, depot)
65
  routing = pywrapcp.RoutingModel(manager)
66
 
67
  def time_callback(from_index, to_index):
 
 
68
  from_node = manager.IndexToNode(from_index)
69
  to_node = manager.IndexToNode(to_index)
70
  return time_matrix[from_node][to_node]
71
 
72
  transit_callback_index = routing.RegisterTransitCallback(time_callback)
73
  routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
74
+
75
  routing.AddDimension(
76
  transit_callback_index,
77
+ 10000, # Allow waiting time
78
+ 10000, # Max time per vehicle
79
+ False, # Don't force start cumul to zero
80
+ 'Time'
81
+ )
82
+
83
+ time_dimension = routing.GetDimensionOrDie('Time')
84
+
85
+ # Time windows for all locations except depot
86
+ for location_idx, (start, end) in enumerate(time_windows):
87
+ if location_idx == depot:
88
  continue
89
  index = manager.NodeToIndex(location_idx)
90
+ time_dimension.CumulVar(index).SetRange(int(start), int(end))
 
91
 
92
+ # Time windows for vehicle start (depot)
93
+ depot_start, depot_end = time_windows[depot]
94
  for vehicle_id in range(num_vehicles):
95
  index = routing.Start(vehicle_id)
96
+ time_dimension.CumulVar(index).SetRange(int(depot_start), int(depot_end))
 
97
 
98
+ # Finalizer hints for optimization
99
  for i in range(num_vehicles):
100
+ routing.AddVariableMinimizedByFinalizer(time_dimension.CumulVar(routing.Start(i)))
101
+ routing.AddVariableMinimizedByFinalizer(time_dimension.CumulVar(routing.End(i)))
 
 
102
 
103
+ search_params = pywrapcp.DefaultRoutingSearchParameters()
104
+ search_params.first_solution_strategy = routing_enums_pb2.FirstSolutionStrategy.AUTOMATIC
 
105
 
106
+ assignment = routing.SolveWithParameters(search_params)
107
  return routing, assignment
108
 
109
 
110
+ def evaluate_google_model(validation_dataset):
111
+ """
112
+ Evaluate the validation dataset using Google OR-Tools model.
113
 
114
+ Args:
115
+ validation_dataset (Dataset): A dataset with a get_data method.
116
 
117
+ Returns:
118
+ torch.Tensor: Scores for each batch item.
119
+ """
120
  validation_dataset.device = 'cpu'
121
  data = validation_dataset.get_data()
122
  model = GoogleActor(scale_factor=100)
123
+ return model(data)