inire/inire/router/results.py

68 lines
1.8 KiB
Python

from __future__ import annotations
from dataclasses import dataclass, field
from typing import TYPE_CHECKING
from inire.router.outcomes import RoutingOutcome, infer_routing_outcome
if TYPE_CHECKING:
from inire.geometry.components import ComponentResult
from inire.model import LockedRoute
@dataclass(frozen=True, slots=True)
class RoutingReport:
static_collision_count: int = 0
dynamic_collision_count: int = 0
self_collision_count: int = 0
total_length: float = 0.0
@property
def collision_count(self) -> int:
return self.static_collision_count + self.dynamic_collision_count + self.self_collision_count
@property
def is_valid(self) -> bool:
return self.collision_count == 0
@dataclass(frozen=True, slots=True)
class RouteMetrics:
nodes_expanded: int
moves_generated: int
moves_added: int
pruned_closed_set: int
pruned_hard_collision: int
pruned_cost: int
@dataclass(frozen=True, slots=True)
class RoutingResult:
net_id: str
path: tuple[ComponentResult, ...]
reached_target: bool = False
report: RoutingReport = field(default_factory=RoutingReport)
def __post_init__(self) -> None:
object.__setattr__(self, "path", tuple(self.path))
@property
def collisions(self) -> int:
return self.report.collision_count
@property
def outcome(self) -> RoutingOutcome:
return infer_routing_outcome(
has_path=bool(self.path),
reached_target=self.reached_target,
collision_count=self.report.collision_count,
)
@property
def is_valid(self) -> bool:
return self.outcome == "completed"
def as_locked_route(self) -> LockedRoute:
from inire.model import LockedRoute
return LockedRoute.from_path(self.path)