From c3d6863ab6b0c0ccdec69c3ed4c70c0d128d3e81 Mon Sep 17 00:00:00 2001 From: Felix Martin Date: Mon, 6 Jan 2020 17:18:30 -0500 Subject: [PATCH] Add support for opening facilities. --- facility/facility.py | 54 ++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/facility/facility.py b/facility/facility.py index 114b853..a491c73 100755 --- a/facility/facility.py +++ b/facility/facility.py @@ -182,12 +182,12 @@ class Solution(object): x, y = f.location color = 'ro' if f.is_open else 'go' plt.plot(x, y, color) - plt.text(x, y, f"{f}") + # plt.text(x, y, f"{f}") for c in self.cs: x, y = c.location plt.plot(x, y, 'bx') - plt.text(x, y, f"{c}") + # plt.text(x, y, f"{c}") if (f := c.facility) is not None: x_f, y_f = f.location @@ -245,7 +245,8 @@ class Solution(object): return f.add(customer) elif new_length > current_length: return 0 - not_connected.append(customer) + if not customer.facility: + not_connected.append(customer) return 0 delta += sum([connect_better_facility(c) for c in customers]) return delta, not_connected @@ -265,7 +266,7 @@ class Solution(object): elif self.cost < original_cost: delta = original_cost - self.cost logging.info(f"Close {facility} resulted in improvement {delta}.") - return + return True else: logging.debug(f"No improvement. Restore.") @@ -274,43 +275,52 @@ class Solution(object): self.cost += delta assert(not not_connected) assert(abs(original_cost - self.cost) < EPSILON) + return False def open_facility(self, facility): - raise Exception("Has bugs!") - logging.debug(f"Open {facility}.") + logging.debug(f"Opening {facility}.") original_cost = self.cost self.cost += facility.set_open() - delta, not_connected = self.reconnect_greedy(self.cs) - self.cost += delta - if not_connected: - logging.debug("Not all customers connected. Restore.") - elif self.cost < original_cost: + moved = [] + for c in self.cs: + if c.demand < facility.remaining_capacity and \ + length.get(c, c.facility) > length.get(c, facility): + moved.append({"previous_facility": c.facility, "c": c}) + self.cost += facility.add(c) + + if self.cost < original_cost: delta = original_cost - self.cost logging.info(f"Open {facility} resulted in improvement {delta}.") - return + return True else: logging.debug(f"No improvement. Restore.") - self.cost += facility.remove_all_and_close() - delta, not_connected = self.reconnect_greedy(self.cs) - self.cost += delta + for m in moved: + c = m["c"] + f = m["previous_facility"] + self.cost += f.add(c) + self.cost += facility.set_not_open() - assert(not not_connected) assert(abs(original_cost - self.cost) < EPSILON) + return False def local_search(self): fs = [f for f in self.fs if f.is_open] fs.sort(key=lambda f: len(f.customers)) - for f in fs: self.close_facility(f) - # fs = [f for f in self.fs if not f.is_open] - # fs.sort(key=lambda f: f.setup_cost) - # for f in fs: - # self.open_facility(f) + delta, not_connected = self.reconnect_greedy(self.cs) + if not_connected: + raise Exception(f"{not_connected=}") + self.cost += delta + + fs = [f for f in self.fs if not f.is_open] + fs.sort(key=lambda f: f.setup_cost) + for f in fs: + self.open_facility(f) def solve_it(input_data): @@ -321,7 +331,7 @@ def solve_it(input_data): solution.build_greedy() solution.reconnect_greedy(solution.cs) solution.local_search() - # solution.plot_map() + solution.plot_map() output_data = solution.to_output_data() return output_data