interhack26 / baseline.py
danvancea's picture
Upload 34 files
4e22ad8 verified
Raw
History Blame Contribute Delete
3.18 kB
"""Naive comparator: polar sweep + per-van nearest-neighbor.
Sort stops by angle from depot, round-robin assign to vans, then NN-order
each van's stops from the depot. No window or capacity guarantee — that's
the point. The OR-tools solver's "X% better" pitch number is computed
against this baseline.
"""
from __future__ import annotations
import math
from loader import Depot, Driver, Fleet, Stop
from solver import FleetPlan, StopPlan, VanPlan
from travel_time import TravelMatrix
def _polar(s: Stop, depot: Depot) -> float:
return math.atan2(s.lat - depot.lat, s.lng - depot.lng)
def solve_baseline(
depot: Depot,
fleet: Fleet,
drivers: list[Driver],
stops: list[Stop],
matrix: TravelMatrix,
) -> FleetPlan:
if not stops:
return FleetPlan([], 0, 0, True)
K = fleet.num_vans
swept = sorted(stops, key=lambda s: _polar(s, depot))
assigned: list[list[Stop]] = [[] for _ in range(K)]
for i, s in enumerate(swept):
assigned[i % K].append(s)
vans: list[VanPlan] = []
fleet_drive = fleet_total = 0
all_feas = True
depot_i = matrix.index_of("DEPOT")
for vid, van_stops in enumerate(assigned):
order: list[Stop] = []
remaining = {s.id: s for s in van_stops}
cur = depot_i
while remaining:
nxt = min(
remaining.values(),
key=lambda s: float(matrix.time_s[cur, matrix.index_of(s.id)]),
)
order.append(nxt)
cur = matrix.index_of(nxt.id)
del remaining[nxt.id]
# Simulate
t = float(drivers[vid].shift_start_s)
prev = depot_i
plan: list[StopPlan] = []
v_drive = cum_c = cum_k = peak_c = peak_k = 0
late = False
for seq, s in enumerate(order, start=1):
i = matrix.index_of(s.id)
travel = float(matrix.time_s[prev, i])
v_drive += int(travel)
t += travel
if t < s.t_open_s:
t = float(s.t_open_s)
if t > s.t_close_s:
late = True
plan.append(StopPlan(seq, s.id, int(t)))
t += s.service_time_s
cum_c += s.delivery_cells + s.pickup_cells
cum_k += int(round(s.delivery_kg + s.pickup_kg))
peak_c = max(peak_c, cum_c)
peak_k = max(peak_k, cum_k)
prev = i
ret = float(matrix.time_s[prev, depot_i])
v_drive += int(ret)
t += ret
v_total = int(t - drivers[vid].shift_start_s)
shift_ok = t <= drivers[vid].shift_end_s
cap_ok = peak_c <= fleet.capacity_cells and peak_k <= fleet.capacity_kg
feas = shift_ok and cap_ok and not late
all_feas &= feas
vans.append(VanPlan(
van_idx=vid, driver_id=drivers[vid].id, stops=plan,
travel_s=v_drive, total_s=v_total,
peak_cells=peak_c, peak_kg=peak_k, feasible=feas,
))
fleet_drive += v_drive
fleet_total += v_total
return FleetPlan(vans, fleet_drive, fleet_total, all_feas)