Spaces:
Sleeping
Sleeping
| """State models for search and planning results.""" | |
| from dataclasses import dataclass, field | |
| from typing import List, Optional, Tuple | |
| from .grid import Grid | |
| from .entities import Store, Destination, Tunnel | |
| class SearchState: | |
| """Represents the complete state for a delivery search problem.""" | |
| grid: Grid | |
| stores: List[Store] | |
| destinations: List[Destination] | |
| tunnels: List[Tunnel] | |
| def get_tunnel_at(self, pos: Tuple[int, int]) -> Optional[Tunnel]: | |
| """Get tunnel with entrance at given position.""" | |
| for tunnel in self.tunnels: | |
| if tunnel.has_entrance_at(pos): | |
| return tunnel | |
| return None | |
| def to_dict(self) -> dict: | |
| return { | |
| "grid": self.grid.to_dict(), | |
| "stores": [s.to_dict() for s in self.stores], | |
| "destinations": [d.to_dict() for d in self.destinations], | |
| "tunnels": [t.to_dict() for t in self.tunnels], | |
| } | |
| class PathResult: | |
| """Result of finding a path from start to goal.""" | |
| plan: str # Comma-separated actions: "up,down,left,right,tunnel" | |
| cost: float # Total traffic cost | |
| nodes_expanded: int # Number of nodes expanded during search | |
| path: List[Tuple[int, int]] = field( | |
| default_factory=list | |
| ) # Actual positions in path | |
| def to_string(self) -> str: | |
| """Format as required: plan;cost;nodesExpanded""" | |
| return f"{self.plan};{self.cost};{self.nodes_expanded}" | |
| def to_dict(self) -> dict: | |
| return { | |
| "plan": self.plan, | |
| "cost": self.cost, | |
| "nodes_expanded": self.nodes_expanded, | |
| "path": [{"x": p[0], "y": p[1]} for p in self.path], | |
| } | |
| class DeliveryAssignment: | |
| """Assignment of a destination to a store/truck.""" | |
| store_id: int | |
| destination_id: int | |
| path_result: PathResult | |
| def to_dict(self) -> dict: | |
| return { | |
| "store_id": self.store_id, | |
| "destination_id": self.destination_id, | |
| "path": self.path_result.to_dict(), | |
| } | |
| class PlanResult: | |
| """Result of the complete delivery planning.""" | |
| assignments: List[DeliveryAssignment] | |
| total_cost: float | |
| total_nodes_expanded: int | |
| def to_string(self) -> str: | |
| """Format output as specified.""" | |
| parts = [] | |
| for assignment in self.assignments: | |
| parts.append( | |
| f"({assignment.store_id},{assignment.destination_id}):{assignment.path_result.to_string()}" | |
| ) | |
| return ";".join(parts) | |
| def to_dict(self) -> dict: | |
| return { | |
| "assignments": [a.to_dict() for a in self.assignments], | |
| "total_cost": self.total_cost, | |
| "total_nodes_expanded": self.total_nodes_expanded, | |
| } | |
| class SearchStep: | |
| """Represents a single step in the search process for visualization.""" | |
| step_number: int | |
| current_node: Tuple[int, int] | |
| action: Optional[str] | |
| frontier: List[Tuple[int, int]] | |
| explored: List[Tuple[int, int]] | |
| current_path: List[Tuple[int, int]] | |
| path_cost: float | |
| def to_dict(self) -> dict: | |
| return { | |
| "stepNumber": self.step_number, | |
| "currentNode": {"x": self.current_node[0], "y": self.current_node[1]}, | |
| "action": self.action, | |
| "frontier": [{"x": p[0], "y": p[1]} for p in self.frontier], | |
| "explored": [{"x": p[0], "y": p[1]} for p in self.explored], | |
| "currentPath": [{"x": p[0], "y": p[1]} for p in self.current_path], | |
| "pathCost": self.path_cost, | |
| } | |
| class SearchMetrics: | |
| """Performance metrics for a search execution.""" | |
| runtime_ms: float | |
| memory_kb: float | |
| cpu_percent: float | |
| nodes_expanded: int | |
| path_cost: float | |
| path_length: int | |
| def to_dict(self) -> dict: | |
| return { | |
| "runtime_ms": self.runtime_ms, | |
| "memory_kb": self.memory_kb, | |
| "cpu_percent": self.cpu_percent, | |
| "nodes_expanded": self.nodes_expanded, | |
| "path_cost": self.path_cost, | |
| "path_length": self.path_length, | |
| } | |