Skip to content

Commit 4efdb74

Browse files
committed
v0.0.24 Refactor of agents signatures; multi-phase solving fix + example; replanning fix + example; some experiments
1 parent 08af3be commit 4efdb74

24 files changed

+217
-122
lines changed

examples/object_oriented/nqueens/persistence/DomainBuilderNQueens.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def build_domain_from_scratch(self):
3535

3636
return chess_field
3737

38-
def build_from_solution(self, solution):
38+
def build_from_solution(self, solution, initial_domain=None):
3939
raise Exception("build_from_solution() not implemented for DomainBuilderNQueens")
4040

4141
def build_from_domain(self, domain):

examples/object_oriented/nqueens/score/IncrementalScoreCalculatorNQueens.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def all_different(self, planning_entity_dfs, problem_fact_dfs, delta_dfs):
7777
return scores"""
7878

7979
@staticmethod
80-
@jit(nopython=True)
80+
@jit(nopython=True, cache=True)
8181
#@numba.cfunc("float64[:](int64[:], int64[:], int64, int64[:], int64[:], int64[:], int64)")
8282
def compute_score_values(
8383
native_column_ids,

examples/object_oriented/nqueens/scripts/solve_nqueens.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@
2929
#termination_strategy = TimeSpentLimit(time_seconds_limit=60)
3030
#termination_strategy = ScoreNoImprovement(time_seconds_limit=15)
3131
termination_strategy = ScoreLimit(score_to_compare=[0])
32-
agent = TabuSearch(neighbours_count=128, tabu_entity_rate=0.0,
32+
agent = TabuSearch(neighbours_count=20, tabu_entity_rate=0.0,
3333
mutation_rate_multiplier=None, move_probas=[0, 1, 0, 0, 0, 0],
34-
migration_frequency=1, termination_strategy=termination_strategy)
34+
compare_to_global=True, migration_frequency=10, termination_strategy=termination_strategy)
3535
"""agent = GeneticAlgorithm(population_size=128, crossover_probability=0.5, p_best_rate=0.05,
3636
tabu_entity_rate=0.0, mutation_rate_multiplier=1.0, move_probas=[0, 1, 0, 0, 0, 0],
3737
migration_rate=0.00001, migration_frequency=1, termination_strategy=termination_strategy)"""
3838
"""agent = LateAcceptance(late_acceptance_size=1, tabu_entity_rate=0.0,
3939
mutation_rate_multiplier=None, move_probas=[0, 1, 0, 0, 0, 0],
40-
migration_frequency=10, termination_strategy=termination_strategy)"""
40+
termination_strategy=termination_strategy)"""
4141

4242
solver = Solver(domain_builder, cotwin_builder, agent,
4343
ParallelizationBackend.Multiprocessing, LoggingLevel.Info,

examples/object_oriented/tsp/persistence/DomainBuilder.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def build_domain_from_scratch(self):
4747

4848
return domain_model
4949

50-
def build_from_solution(self, solution):
50+
def build_from_solution(self, solution, initial_domain=None):
5151

5252
domain = self.build_domain_from_scratch()
5353
path_stop_ids = []
@@ -69,7 +69,7 @@ def build_from_domain(self, domain):
6969
def _build_distance_matrix(self, locations_list):
7070

7171
@staticmethod
72-
@jit()
72+
@jit(nopython=True, cache=True)
7373
def compute_distance_matrix(latitudes, longitudes, n_locations):
7474
distance_matrix = np.zeros( (n_locations, n_locations), dtype=np.int64 )
7575
for i in range(n_locations):

examples/object_oriented/tsp/score/IncrementalScoreCalculatorTSP.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def all_in_one_constraint(self, planning_entity_dfs, problem_fact_dfs, delta_dfs
5959
return scores
6060

6161
@staticmethod
62-
@jit(nopython=True)
62+
@jit(nopython=True, cache=True)
6363
def compute_penalties(changed_stops, current_df_row_ids, current_loc_ids, distance_matrix, last_id, target_stops_count):
6464
changed_stops[current_df_row_ids] = current_loc_ids
6565

examples/object_oriented/tsp/score/PlainScoreCalculatorTSP.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def no_duplicating_stops_constraint(self, planning_entity_dfs, problem_fact_dfs)
6666
# numba is perfect for writing small pieces of code (that difficult or imposible to express in Polars) with numpy objects
6767
# instead rewriting on Rust (to not increase complexity of project and still take huge performance boost)
6868
@staticmethod
69-
@jit(nopython=True)
69+
@jit(nopython=True, cache=True)
7070
def compute_path_distance(planning_stop_ids, distance_matrix):
7171
current_path_distance = 0
7272
current_path_distance += distance_matrix[0][planning_stop_ids[0]]
@@ -99,7 +99,7 @@ def minimize_distance(self, planning_entity_dfs, problem_fact_dfs):
9999
# numba is perfect for writing small pieces of code (that difficult or imposible to express in Polars) with numpy objects
100100
# instead rewriting on Rust (to not increase complexity of project and still take huge performance boost)
101101
@staticmethod
102-
@jit(nopython=True)
102+
@jit(nopython=True, cache=True)
103103
def compute_path_distances(data_matrix, distance_matrix):
104104

105105
unique_sample_ids = np.unique(data_matrix[:, 0])

examples/object_oriented/tsp/scripts/solve_tsp.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,32 +26,32 @@
2626
#file_path = Path(data_dir_path, "cook", "air", "st70.tsp") # 682.57 - optimum
2727
#file_path = Path(data_dir_path, "belgium", "road-km", "belgium-road-km-n100.tsp") # 1727.262 - optimum, 2089 - first_fit
2828
#file_path = Path(data_dir_path, "tsplib", "a280.tsp") # 2579 - optimal
29-
#file_path = Path(data_dir_path, "cook", "air", "pcb442.tsp") #optimum: 50778; first_fit: ~63k
29+
file_path = Path(data_dir_path, "cook", "air", "pcb442.tsp") #optimum: 50778; first_fit: ~63k
3030
#file_path = Path(data_dir_path, "cook", "air", "lu980.tsp")
3131
#file_path = Path(data_dir_path, "other", "air", "usa_tx_2743.tsp") #optimum: ~282; first_fit: ~338
3232
#file_path = Path(data_dir_path, "belgium", "air", "belgium-n2750.tsp")
3333
#file_path = Path(data_dir_path, "tsplib", "fnl4461.tsp") #optimum: 182566; first_fit: ~230k
34-
file_path = Path(data_dir_path, "cook", "air", "gr9882.tsp") #optimum: 300899; first_fit: ~400k
34+
#file_path = Path(data_dir_path, "cook", "air", "gr9882.tsp") #optimum: 300899; first_fit: ~400k
3535

3636
domain_builder = DomainBuilder(file_path)
3737
cotwin_builder = CotwinBuilder(use_incremental_score_calculator=True)
3838

3939
#termination_strategy = StepsLimit(step_count_limit=1000)
40-
termination_strategy = TimeSpentLimit(time_seconds_limit=60)
41-
#termination_strategy = ScoreNoImprovement(time_seconds_limit=60)
40+
#termination_strategy = TimeSpentLimit(time_seconds_limit=60)
41+
termination_strategy = ScoreNoImprovement(time_seconds_limit=15)
4242
#termination_strategy = ScoreLimit(score_to_compare=[0])
4343
agent = TabuSearch(neighbours_count=128, tabu_entity_rate=0.2,
4444
mutation_rate_multiplier=None, move_probas=[0.0, 0.2, 0.2, 0.2, 0.2, 0.2],
45-
migration_frequency=10, termination_strategy=termination_strategy)
45+
compare_to_global=False, migration_frequency=10, termination_strategy=termination_strategy)
4646
"""agent = GeneticAlgorithm(population_size=128, crossover_probability=0.5, p_best_rate=0.05,
4747
tabu_entity_rate=0.2, mutation_rate_multiplier=1.0, move_probas=[0.0, 0.2, 0.2, 0.2, 0.2, 0.2],
4848
migration_rate=0.00001, migration_frequency=10, termination_strategy=termination_strategy)"""
4949
"""agent = LateAcceptance(late_acceptance_size=64, tabu_entity_rate=0.2,
5050
mutation_rate_multiplier=None, move_probas=[0.0, 0.2, 0.2, 0.2, 0.2, 0.2],
51-
migration_frequency=10000, termination_strategy=termination_strategy)"""
51+
termination_strategy=termination_strategy)"""
5252

5353
solver = Solver(domain_builder, cotwin_builder, agent,
54-
ParallelizationBackend.Multiprocessing, LoggingLevel.Info,
54+
ParallelizationBackend.Multiprocessing, LoggingLevel.FreshOnly,
5555
n_jobs=10, score_precision=[0, 0])
5656
solution = solver.solve()
5757

examples/object_oriented/vrp/cotwin/CotCustomer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11

22

33
class CotCustomer():
4-
def __init__(self, customer_matrix_id, demand, time_window_start, time_window_end, service_time):
4+
def __init__(self, customer_vec_id, demand, time_window_start, time_window_end, service_time):
55

6-
self.customer_matrix_id = customer_matrix_id
6+
self.customer_vec_id = customer_vec_id
77
self.demand = demand
88
self.time_window_start = time_window_start
99
self.time_window_end = time_window_end

examples/object_oriented/vrp/domain/Customer.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
class Customer():
55
def __init__(self, id, name, latitude, longitude, demand=None,
66
time_window_start=None, time_window_end=None, service_time=None,
7-
distances_to_other_customers_dict=None):
7+
distances_to_other_customers_dict=None, frozen=False):
88

99
self.id = id
1010
self.name = name
@@ -15,6 +15,7 @@ def __init__(self, id, name, latitude, longitude, demand=None,
1515
self.time_window_end = time_window_end
1616
self.service_time = service_time
1717
self.distances_to_other_customers_dict = distances_to_other_customers_dict
18+
self.frozen = frozen
1819

1920
pass
2021

examples/object_oriented/vrp/domain/Vehicle.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
class Vehicle():
44

5-
def __init__(self, depot, depot_matrix_id, work_day_start, work_day_end, capacity, customer_list, max_stops):
5+
def __init__(self, depot, depot_vec_id, work_day_start, work_day_end, capacity, customer_list, max_stops):
66

77
self.depot = depot
8-
self.depot_matrix_id = depot_matrix_id
8+
self.depot_vec_id = depot_vec_id
99
self.work_day_start = work_day_start
1010
self.work_day_end = work_day_end
1111
self.capacity = capacity

examples/object_oriented/vrp/domain/VehicleRoutingPlan.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
import matplotlib.pyplot as plt
33

44
class VehicleRoutingPlan():
5-
def __init__(self, name, vehicles, customers_dict, depot_dict, distance_matrix, customers_id_to_matrix_id_map, time_windowed):
5+
def __init__(self, name, vehicles, customers_dict, depot_dict, distance_matrix, customers_id_to_vec_id_map, time_windowed):
66

77
self.name = name
88
self.vehicles = vehicles
99
self.customers_dict = customers_dict
1010
self.depot_dict = depot_dict
1111
self.distance_matrix = distance_matrix
12-
self.customers_id_to_matrix_id_map = customers_id_to_matrix_id_map
12+
self.customers_id_to_vec_id_map = customers_id_to_vec_id_map
1313
self.time_windowed = time_windowed
1414

1515
pass

examples/object_oriented/vrp/persistence/CotwinBuilder.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@
1414

1515
class CotwinBuilder(CotwinBuilderBase):
1616

17-
def __init__(self, use_incremental_score_calculator):
17+
def __init__(self, use_incremental_score_calculator, use_greed_init):
1818
self.use_incremental_score_calculator = use_incremental_score_calculator
19+
self.use_greed_init = use_greed_init
1920
pass
2021

2122
def build_cotwin(self, domain, is_already_initialized):
2223

2324
vrp_cotwin = VRPCotwin()
2425

25-
vrp_cotwin.add_planning_entities_list(self._build_planning_stops(domain), "planning_stops")
26+
vrp_cotwin.add_planning_entities_list(self._build_planning_stops(domain, is_already_initialized), "planning_stops")
2627
vrp_cotwin.add_problem_facts_list(self._build_problem_fact_vehicles(domain), "vehicles")
2728
vrp_cotwin.add_problem_facts_list(self._build_problem_fact_customers(domain), "customers")
2829

@@ -46,11 +47,11 @@ def _build_problem_fact_vehicles(self, domain):
4647
problem_fact_vehicles = []
4748
for i, domain_vehicle in enumerate(domain.vehicles):
4849
vehicle_id = i
49-
depot_matrix_id = domain_vehicle.depot_matrix_id
50+
depot_vec_id = domain_vehicle.depot_vec_id
5051
capacity = domain_vehicle.capacity
5152
work_day_start = domain_vehicle.work_day_start
5253
work_day_end = domain_vehicle.work_day_end
53-
cot_vehicle = CotVehicle( vehicle_id, capacity, depot_matrix_id, work_day_start, work_day_end)
54+
cot_vehicle = CotVehicle( vehicle_id, capacity, depot_vec_id, work_day_start, work_day_end)
5455
problem_fact_vehicles.append( cot_vehicle )
5556

5657
return problem_fact_vehicles
@@ -72,29 +73,42 @@ def _build_problem_fact_customers(self, domain):
7273

7374
return problem_fact_customers
7475

75-
def _build_planning_stops(self, domain):
76+
def _build_planning_stops(self, domain, is_already_initialized):
7677

7778
planning_stops = []
7879
customers_dict = domain.customers_dict
7980
n_depots = len(domain.depot_dict)
8081
n_customers = len(customers_dict)
8182
k_vehicles = len(domain.vehicles)
8283

83-
initial_vehicle_ids, initial_customer_ids = self.build_greed_initial_ids(domain)
84+
initial_vehicle_ids = [None for k in range(n_customers - n_depots)]
85+
initial_customer_ids = [None for i in range(n_customers - n_depots)]
86+
is_frozen = [False for i in range(n_customers - n_depots)]
87+
if is_already_initialized:
88+
i = 0
89+
for k in range(k_vehicles):
90+
vehicle_k = domain.vehicles[k]
91+
for customer in vehicle_k.customer_list:
92+
initial_vehicle_ids[i] = k
93+
initial_customer_ids[i] = domain.customers_id_to_vec_id_map[customer.id]
94+
is_frozen[i] = customer.frozen
95+
i += 1
96+
elif self.use_greed_init:
97+
initial_vehicle_ids, initial_customer_ids = self.build_greed_initial_ids(domain)
8498

8599
for i in range(n_depots, n_customers):
86100

87101
#initial_value=None
88102
#initial_value=i % (k_vehicles-1)
89103
#initial_value=initial_vehicle_ids[i - n_depots]
90104
#semantic_groups=["vehicle_assignment", "common"]
91-
planning_vehicle_id = GJInteger(0, k_vehicles-1, False, initial_vehicle_ids[i - n_depots], semantic_groups=["vehicle_assignment", "common"])
105+
planning_vehicle_id = GJInteger(0, k_vehicles-1, is_frozen[i - n_depots], initial_vehicle_ids[i - n_depots], semantic_groups=["vehicle_assignment", "common"])
92106

93107
#initial_value=None
94108
#initial_value=i
95109
#initial_value=initial_customer_ids[i - n_depots]
96110
#semantic_groups=["customer_assignment", "common"]
97-
planning_customer_id = GJInteger(n_depots, n_customers-1, False, initial_customer_ids[i - n_depots], semantic_groups=["customer_assignment", "common"])
111+
planning_customer_id = GJInteger(n_depots, n_customers-1, is_frozen[i - n_depots], initial_customer_ids[i - n_depots], semantic_groups=["customer_assignment", "common"])
98112

99113
planning_stop = CotStop(planning_vehicle_id, planning_customer_id)
100114
planning_stops.append(planning_stop)
@@ -120,7 +134,7 @@ def build_greed_initial_ids(self, domain):
120134
if len(remaining_customers) <= 0:
121135
break
122136

123-
vehicle_depot_id = vehicle.depot_matrix_id
137+
vehicle_depot_id = vehicle.depot_vec_id
124138
vehicle_capacity = vehicle.capacity
125139
collected_demand = 0
126140
vehicle_stops = []
@@ -191,7 +205,7 @@ def add_incremental_utilities(self, domain, score_calculator):
191205
depot_ids = np.zeros((k_vehicles, ), dtype=np.int64)
192206
capacities = np.zeros((k_vehicles, ), dtype=np.int64)
193207
for k in range(k_vehicles):
194-
depot_ids[k] = domain.vehicles[k].depot_matrix_id
208+
depot_ids[k] = domain.vehicles[k].depot_vec_id
195209
capacities[k] = domain.vehicles[k].capacity
196210
score_calculator.utility_objects["depot_ids"] = depot_ids
197211
score_calculator.utility_objects["vehicle_capacities"] = capacities

0 commit comments

Comments
 (0)