Spaces:
Sleeping
Sleeping
File size: 4,371 Bytes
e067c2d 47bba68 e067c2d 47bba68 e067c2d 47bba68 e067c2d 47bba68 e067c2d 47bba68 e067c2d 47bba68 e067c2d 47bba68 e067c2d 47bba68 e067c2d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
"""DeliveryPlanner - Plans which trucks deliver which packages."""
from typing import List, Dict, Tuple, Optional
from .delivery_search import DeliverySearch
from ..models.grid import Grid
from ..models.entities import Store, Destination, Tunnel
from ..models.state import PathResult, PlanResult, DeliveryAssignment, SearchStep
class DeliveryPlanner:
"""
Plans the assignment of destinations to stores/trucks.
For each destination, finds the optimal store to deliver from and computes the delivery path.
"""
def __init__(
self,
grid: Grid,
stores: List[Store],
destinations: List[Destination],
tunnels: Optional[List[Tunnel]] = None,
):
"""
Initialize the delivery planner.
Args:
grid: The city grid with traffic information
stores: List of store locations (each has a truck)
destinations: List of customer destinations
tunnels: Available tunnels
"""
self.grid = grid
self.stores = stores
self.destinations = destinations
self.tunnels = tunnels or []
def plan(
self, strategy: str, visualize: bool = False
) -> Tuple[PlanResult, Optional[Dict[int, List[SearchStep]]]]:
"""
Create delivery plan assigning destinations to stores.
Algorithm:
1. For each destination, compute path cost from each store
2. Assign each destination to the store with minimum path cost
3. Compile results
Args:
strategy: Search strategy to use
visualize: If True, collect visualization steps
Returns:
Tuple of (PlanResult, Optional visualization data)
"""
assignments: List[DeliveryAssignment] = []
all_steps: Dict[int, List[SearchStep]] = {} if visualize else None
total_cost = 0.0
total_nodes = 0
# For each destination, find best store
for dest in self.destinations:
best_store: Optional[Store] = None
best_result: Optional[PathResult] = None
best_steps: Optional[List[SearchStep]] = None
best_cost = float("inf")
# Try each store
for store in self.stores:
result, steps = DeliverySearch.path(
self.grid,
store.position,
dest.position,
self.tunnels,
strategy,
visualize,
)
# Track nodes expanded
total_nodes += result.nodes_expanded
# Check if this is better
if result.cost < best_cost:
best_cost = result.cost
best_store = store
best_result = result
best_steps = steps
# Create assignment
if best_store and best_result:
assignment = DeliveryAssignment(
store_id=best_store.id,
destination_id=dest.id,
path_result=best_result,
)
assignments.append(assignment)
total_cost += best_result.cost
if visualize and best_steps:
all_steps[dest.id] = best_steps
return (
PlanResult(
assignments=assignments,
total_cost=total_cost,
total_nodes_expanded=total_nodes,
),
all_steps,
)
@staticmethod
def plan_from_state(
grid: Grid,
stores: List[Store],
destinations: List[Destination],
tunnels: List[Tunnel],
strategy: str,
visualize: bool = False,
) -> Tuple[PlanResult, Optional[Dict]]:
"""
Static method to create and run planner.
Args:
grid: The city grid
stores: List of stores
destinations: List of destinations
tunnels: Available tunnels
strategy: Search strategy
visualize: If True, collect visualization steps
Returns:
Tuple of (PlanResult, Optional visualization data)
"""
planner = DeliveryPlanner(grid, stores, destinations, tunnels)
return planner.plan(strategy, visualize)
|