[AutoTool | PrimitiveOffer] remove priority_bias in favor of cost_at
This commit is contained in:
parent
0edd735a11
commit
8712398990
4 changed files with 85 additions and 45 deletions
|
|
@ -178,7 +178,7 @@ class PrimitiveWireTool(Tool):
|
||||||
|
|
||||||
def _transition_offers(self, in_ptype: str | None) -> tuple[StraightOffer, ...]:
|
def _transition_offers(self, in_ptype: str | None) -> tuple[StraightOffer, ...]:
|
||||||
offers: list[StraightOffer] = []
|
offers: list[StraightOffer] = []
|
||||||
for index, spec in enumerate(self.transitions):
|
for spec in self.transitions:
|
||||||
if spec.out_port.ptype != self.ptype:
|
if spec.out_port.ptype != self.ptype:
|
||||||
continue
|
continue
|
||||||
if in_ptype not in (None, 'unk', spec.in_port.ptype):
|
if in_ptype not in (None, 'unk', spec.in_port.ptype):
|
||||||
|
|
@ -208,7 +208,6 @@ class PrimitiveWireTool(Tool):
|
||||||
offers.append(StraightOffer(
|
offers.append(StraightOffer(
|
||||||
in_ptype = spec.in_port.ptype,
|
in_ptype = spec.in_port.ptype,
|
||||||
out_ptype = spec.out_port.ptype,
|
out_ptype = spec.out_port.ptype,
|
||||||
priority_bias = index * 1e7,
|
|
||||||
length_domain = (length, length),
|
length_domain = (length, length),
|
||||||
endpoint_planner = endpoint_planner,
|
endpoint_planner = endpoint_planner,
|
||||||
commit_planner = commit_planner,
|
commit_planner = commit_planner,
|
||||||
|
|
@ -220,7 +219,7 @@ class PrimitiveWireTool(Tool):
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
offers: list[StraightOffer] = []
|
offers: list[StraightOffer] = []
|
||||||
for index, spec in enumerate(self.transitions):
|
for spec in self.transitions:
|
||||||
if spec.in_port.ptype != self.ptype:
|
if spec.in_port.ptype != self.ptype:
|
||||||
continue
|
continue
|
||||||
if out_ptype is not None and spec.out_port.ptype != out_ptype:
|
if out_ptype is not None and spec.out_port.ptype != out_ptype:
|
||||||
|
|
@ -255,7 +254,6 @@ class PrimitiveWireTool(Tool):
|
||||||
offers.append(StraightOffer(
|
offers.append(StraightOffer(
|
||||||
in_ptype = self.ptype,
|
in_ptype = self.ptype,
|
||||||
out_ptype = spec.out_port.ptype,
|
out_ptype = spec.out_port.ptype,
|
||||||
priority_bias = index * 1e7,
|
|
||||||
length_domain = (transition_length, numpy.inf),
|
length_domain = (transition_length, numpy.inf),
|
||||||
endpoint_planner = endpoint_planner,
|
endpoint_planner = endpoint_planner,
|
||||||
commit_planner = commit_planner,
|
commit_planner = commit_planner,
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ from .tools import (
|
||||||
PathTool as PathTool,
|
PathTool as PathTool,
|
||||||
RenderStep as RenderStep,
|
RenderStep as RenderStep,
|
||||||
PrimitiveKind as PrimitiveKind,
|
PrimitiveKind as PrimitiveKind,
|
||||||
|
CostCallable as CostCallable,
|
||||||
GeneratedEndpointFn as GeneratedEndpointFn,
|
GeneratedEndpointFn as GeneratedEndpointFn,
|
||||||
PrimitiveOffer as PrimitiveOffer,
|
PrimitiveOffer as PrimitiveOffer,
|
||||||
StraightOffer as StraightOffer,
|
StraightOffer as StraightOffer,
|
||||||
|
|
|
||||||
|
|
@ -350,11 +350,16 @@ class Solver:
|
||||||
)
|
)
|
||||||
|
|
||||||
def offer_key(offer: PrimitiveOffer) -> tuple[Any, ...]:
|
def offer_key(offer: PrimitiveOffer) -> tuple[Any, ...]:
|
||||||
|
cost_key: tuple[str, float | int]
|
||||||
|
if callable(offer.cost):
|
||||||
|
cost_key = ('callable', id(offer.cost))
|
||||||
|
else:
|
||||||
|
cost_key = ('factor', round(float(offer.cost), 9))
|
||||||
return (
|
return (
|
||||||
type(offer).__qualname__,
|
type(offer).__qualname__,
|
||||||
offer.in_ptype,
|
offer.in_ptype,
|
||||||
offer.out_ptype,
|
offer.out_ptype,
|
||||||
round(float(offer.priority_bias), 9),
|
cost_key,
|
||||||
tuple(round(float(value), 9) for value in offer.parameter_domain),
|
tuple(round(float(value), 9) for value in offer.parameter_domain),
|
||||||
getattr(offer, 'ccw', None),
|
getattr(offer, 'ccw', None),
|
||||||
id(offer.endpoint_planner),
|
id(offer.endpoint_planner),
|
||||||
|
|
|
||||||
|
|
@ -112,8 +112,32 @@ CommitCallable = Callable[[float], Any]
|
||||||
BBoxCallable = Callable[[float], NDArray[numpy.float64]]
|
BBoxCallable = Callable[[float], NDArray[numpy.float64]]
|
||||||
DataCallable = Callable[[float], Any]
|
DataCallable = Callable[[float], Any]
|
||||||
BBoxForDataCallable = Callable[[Any], NDArray[numpy.float64]]
|
BBoxForDataCallable = Callable[[Any], NDArray[numpy.float64]]
|
||||||
|
CostCallable = Callable[[float, Port], float]
|
||||||
PrimitiveKind = Literal['straight', 'bend', 's', 'u']
|
PrimitiveKind = Literal['straight', 'bend', 's', 'u']
|
||||||
BUILTIN_PRIORITY_STEP = 1e7
|
|
||||||
|
|
||||||
|
def _validated_cost(cost: CostCallable | float) -> CostCallable | float:
|
||||||
|
"""Return a canonical primitive cost policy or raise `BuildError`."""
|
||||||
|
if callable(cost):
|
||||||
|
return cost
|
||||||
|
try:
|
||||||
|
factor = float(cost)
|
||||||
|
except (TypeError, ValueError, OverflowError) as err:
|
||||||
|
raise BuildError(f'Primitive cost factor must be a number or callable, got {cost!r}') from err
|
||||||
|
if not scalar_isfinite(factor) or factor < 0:
|
||||||
|
raise BuildError(f'Primitive cost factor must be nonnegative and finite, got {factor:g}')
|
||||||
|
return factor
|
||||||
|
|
||||||
|
|
||||||
|
def _validated_cost_value(value: Any) -> float:
|
||||||
|
"""Return a canonical evaluated cost or raise `BuildError`."""
|
||||||
|
try:
|
||||||
|
cost = float(value)
|
||||||
|
except (TypeError, ValueError, OverflowError) as err:
|
||||||
|
raise BuildError(f'Primitive cost must be a number, got {value!r}') from err
|
||||||
|
if not scalar_isfinite(cost) or cost < 0:
|
||||||
|
raise BuildError(f'Primitive cost must be nonnegative and finite, got {cost:g}')
|
||||||
|
return cost
|
||||||
|
|
||||||
|
|
||||||
def _generated_offer_callbacks(
|
def _generated_offer_callbacks(
|
||||||
|
|
@ -188,7 +212,7 @@ class PrimitiveOffer(ABC):
|
||||||
"""
|
"""
|
||||||
in_ptype: str | None
|
in_ptype: str | None
|
||||||
out_ptype: str | None
|
out_ptype: str | None
|
||||||
priority_bias: float = 0.0
|
cost: CostCallable | float = 1.0
|
||||||
bbox_planner: BBoxCallable | None = None
|
bbox_planner: BBoxCallable | None = None
|
||||||
parameterized_bbox: Any | None = None
|
parameterized_bbox: Any | None = None
|
||||||
"""Reserved footprint metadata; the current solver does not inspect it."""
|
"""Reserved footprint metadata; the current solver does not inspect it."""
|
||||||
|
|
@ -201,8 +225,7 @@ class PrimitiveOffer(ABC):
|
||||||
|
|
||||||
if has_endpoint != has_commit:
|
if has_endpoint != has_commit:
|
||||||
raise BuildError('PrimitiveOffer split callbacks require both endpoint_planner and commit_planner')
|
raise BuildError('PrimitiveOffer split callbacks require both endpoint_planner and commit_planner')
|
||||||
if not numpy.isfinite(self.priority_bias) or self.priority_bias < 0:
|
object.__setattr__(self, 'cost', _validated_cost(self.cost))
|
||||||
raise BuildError(f'PrimitiveOffer priority_bias must be nonnegative and finite, got {self.priority_bias:g}')
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
|
@ -234,15 +257,21 @@ class PrimitiveOffer(ABC):
|
||||||
"""
|
"""
|
||||||
Return this primitive's additive planning cost.
|
Return this primitive's additive planning cost.
|
||||||
|
|
||||||
Lower cost is preferred before internal tie-breakers. The default cost
|
Lower cost is preferred before internal tie-breakers. A numeric `cost`
|
||||||
is based on local endpoint displacement plus `priority_bias`.
|
scales the default local-displacement cost; a callable receives the
|
||||||
|
canonical parameter and local endpoint and returns the complete cost.
|
||||||
"""
|
"""
|
||||||
selected = self.canonicalize_parameter(parameter)
|
selected = self.canonicalize_parameter(parameter)
|
||||||
if self.endpoint_planner is not None:
|
if self.endpoint_planner is not None:
|
||||||
out_port = self.endpoint_planner(selected)
|
out_port = self.endpoint_planner(selected)
|
||||||
else:
|
else:
|
||||||
out_port = self.endpoint_at(selected)
|
out_port = self.endpoint_at(selected)
|
||||||
return self.priority_bias + abs(float(out_port.x)) + (pi / 2) * abs(float(out_port.y))
|
if callable(self.cost):
|
||||||
|
value = self.cost(selected, out_port)
|
||||||
|
else:
|
||||||
|
default_cost = abs(float(out_port.x)) + (pi / 2) * abs(float(out_port.y))
|
||||||
|
value = self.cost * default_cost
|
||||||
|
return _validated_cost_value(value)
|
||||||
|
|
||||||
def bbox_at(self, parameter: float) -> NDArray[numpy.float64]:
|
def bbox_at(self, parameter: float) -> NDArray[numpy.float64]:
|
||||||
"""
|
"""
|
||||||
|
|
@ -294,7 +323,7 @@ class StraightOffer(PrimitiveOffer):
|
||||||
ptype: str | None,
|
ptype: str | None,
|
||||||
data_at: DataCallable,
|
data_at: DataCallable,
|
||||||
*,
|
*,
|
||||||
priority_bias: float = 0.0,
|
cost: CostCallable | float = 1.0,
|
||||||
bbox_for_data: BBoxForDataCallable | None = None,
|
bbox_for_data: BBoxForDataCallable | None = None,
|
||||||
length_domain: tuple[float, float] = (0.0, numpy.inf),
|
length_domain: tuple[float, float] = (0.0, numpy.inf),
|
||||||
) -> Self:
|
) -> Self:
|
||||||
|
|
@ -312,7 +341,7 @@ class StraightOffer(PrimitiveOffer):
|
||||||
return cls(
|
return cls(
|
||||||
in_ptype = ptype,
|
in_ptype = ptype,
|
||||||
out_ptype = ptype,
|
out_ptype = ptype,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_planner = bbox_planner,
|
bbox_planner = bbox_planner,
|
||||||
endpoint_planner = endpoint_planner,
|
endpoint_planner = endpoint_planner,
|
||||||
commit_planner = commit_planner,
|
commit_planner = commit_planner,
|
||||||
|
|
@ -327,7 +356,7 @@ class StraightOffer(PrimitiveOffer):
|
||||||
endpoint: Port,
|
endpoint: Port,
|
||||||
data: Any,
|
data: Any,
|
||||||
*,
|
*,
|
||||||
priority_bias: float = 0.0,
|
cost: CostCallable | float = 1.0,
|
||||||
bbox_for_data: BBoxForDataCallable | None = None,
|
bbox_for_data: BBoxForDataCallable | None = None,
|
||||||
) -> Self:
|
) -> Self:
|
||||||
"""
|
"""
|
||||||
|
|
@ -341,7 +370,7 @@ class StraightOffer(PrimitiveOffer):
|
||||||
return cls(
|
return cls(
|
||||||
in_ptype = in_ptype,
|
in_ptype = in_ptype,
|
||||||
out_ptype = out_ptype,
|
out_ptype = out_ptype,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_planner = bbox_planner,
|
bbox_planner = bbox_planner,
|
||||||
endpoint_planner = endpoint_planner,
|
endpoint_planner = endpoint_planner,
|
||||||
commit_planner = commit_planner,
|
commit_planner = commit_planner,
|
||||||
|
|
@ -371,7 +400,7 @@ class BendOffer(PrimitiveOffer):
|
||||||
data_at: DataCallable,
|
data_at: DataCallable,
|
||||||
*,
|
*,
|
||||||
ccw: bool,
|
ccw: bool,
|
||||||
priority_bias: float = 0.0,
|
cost: CostCallable | float = 1.0,
|
||||||
bbox_for_data: BBoxForDataCallable | None = None,
|
bbox_for_data: BBoxForDataCallable | None = None,
|
||||||
length_domain: tuple[float, float] = (0.0, numpy.inf),
|
length_domain: tuple[float, float] = (0.0, numpy.inf),
|
||||||
) -> Self:
|
) -> Self:
|
||||||
|
|
@ -386,7 +415,7 @@ class BendOffer(PrimitiveOffer):
|
||||||
return cls(
|
return cls(
|
||||||
in_ptype = ptype,
|
in_ptype = ptype,
|
||||||
out_ptype = ptype,
|
out_ptype = ptype,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_planner = bbox_planner,
|
bbox_planner = bbox_planner,
|
||||||
endpoint_planner = endpoint_planner,
|
endpoint_planner = endpoint_planner,
|
||||||
commit_planner = commit_planner,
|
commit_planner = commit_planner,
|
||||||
|
|
@ -403,7 +432,7 @@ class BendOffer(PrimitiveOffer):
|
||||||
data: Any,
|
data: Any,
|
||||||
*,
|
*,
|
||||||
ccw: bool,
|
ccw: bool,
|
||||||
priority_bias: float = 0.0,
|
cost: CostCallable | float = 1.0,
|
||||||
bbox_for_data: BBoxForDataCallable | None = None,
|
bbox_for_data: BBoxForDataCallable | None = None,
|
||||||
) -> Self:
|
) -> Self:
|
||||||
"""
|
"""
|
||||||
|
|
@ -417,7 +446,7 @@ class BendOffer(PrimitiveOffer):
|
||||||
return cls(
|
return cls(
|
||||||
in_ptype = in_ptype,
|
in_ptype = in_ptype,
|
||||||
out_ptype = out_ptype,
|
out_ptype = out_ptype,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_planner = bbox_planner,
|
bbox_planner = bbox_planner,
|
||||||
endpoint_planner = endpoint_planner,
|
endpoint_planner = endpoint_planner,
|
||||||
commit_planner = commit_planner,
|
commit_planner = commit_planner,
|
||||||
|
|
@ -446,7 +475,7 @@ class SOffer(PrimitiveOffer):
|
||||||
endpoint_at: EndpointCallable,
|
endpoint_at: EndpointCallable,
|
||||||
data_at: DataCallable,
|
data_at: DataCallable,
|
||||||
*,
|
*,
|
||||||
priority_bias: float = 0.0,
|
cost: CostCallable | float = 1.0,
|
||||||
bbox_for_data: BBoxForDataCallable | None = None,
|
bbox_for_data: BBoxForDataCallable | None = None,
|
||||||
jog_domain: tuple[float, float] = (-numpy.inf, numpy.inf),
|
jog_domain: tuple[float, float] = (-numpy.inf, numpy.inf),
|
||||||
) -> Self:
|
) -> Self:
|
||||||
|
|
@ -461,7 +490,7 @@ class SOffer(PrimitiveOffer):
|
||||||
return cls(
|
return cls(
|
||||||
in_ptype = ptype,
|
in_ptype = ptype,
|
||||||
out_ptype = ptype,
|
out_ptype = ptype,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_planner = bbox_planner,
|
bbox_planner = bbox_planner,
|
||||||
endpoint_planner = endpoint_planner,
|
endpoint_planner = endpoint_planner,
|
||||||
commit_planner = commit_planner,
|
commit_planner = commit_planner,
|
||||||
|
|
@ -476,7 +505,7 @@ class SOffer(PrimitiveOffer):
|
||||||
endpoint: Port,
|
endpoint: Port,
|
||||||
data: Any,
|
data: Any,
|
||||||
*,
|
*,
|
||||||
priority_bias: float = 0.0,
|
cost: CostCallable | float = 1.0,
|
||||||
bbox_for_data: BBoxForDataCallable | None = None,
|
bbox_for_data: BBoxForDataCallable | None = None,
|
||||||
) -> Self:
|
) -> Self:
|
||||||
"""
|
"""
|
||||||
|
|
@ -490,7 +519,7 @@ class SOffer(PrimitiveOffer):
|
||||||
return cls(
|
return cls(
|
||||||
in_ptype = in_ptype,
|
in_ptype = in_ptype,
|
||||||
out_ptype = out_ptype,
|
out_ptype = out_ptype,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_planner = bbox_planner,
|
bbox_planner = bbox_planner,
|
||||||
endpoint_planner = endpoint_planner,
|
endpoint_planner = endpoint_planner,
|
||||||
commit_planner = commit_planner,
|
commit_planner = commit_planner,
|
||||||
|
|
@ -518,7 +547,7 @@ class UOffer(PrimitiveOffer):
|
||||||
endpoint_at: EndpointCallable,
|
endpoint_at: EndpointCallable,
|
||||||
data_at: DataCallable,
|
data_at: DataCallable,
|
||||||
*,
|
*,
|
||||||
priority_bias: float = 0.0,
|
cost: CostCallable | float = 1.0,
|
||||||
bbox_for_data: BBoxForDataCallable | None = None,
|
bbox_for_data: BBoxForDataCallable | None = None,
|
||||||
jog_domain: tuple[float, float] = (-numpy.inf, numpy.inf),
|
jog_domain: tuple[float, float] = (-numpy.inf, numpy.inf),
|
||||||
) -> Self:
|
) -> Self:
|
||||||
|
|
@ -533,7 +562,7 @@ class UOffer(PrimitiveOffer):
|
||||||
return cls(
|
return cls(
|
||||||
in_ptype = ptype,
|
in_ptype = ptype,
|
||||||
out_ptype = ptype,
|
out_ptype = ptype,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_planner = bbox_planner,
|
bbox_planner = bbox_planner,
|
||||||
endpoint_planner = endpoint_planner,
|
endpoint_planner = endpoint_planner,
|
||||||
commit_planner = commit_planner,
|
commit_planner = commit_planner,
|
||||||
|
|
@ -548,7 +577,7 @@ class UOffer(PrimitiveOffer):
|
||||||
endpoint: Port,
|
endpoint: Port,
|
||||||
data: Any,
|
data: Any,
|
||||||
*,
|
*,
|
||||||
priority_bias: float = 0.0,
|
cost: CostCallable | float = 1.0,
|
||||||
bbox_for_data: BBoxForDataCallable | None = None,
|
bbox_for_data: BBoxForDataCallable | None = None,
|
||||||
) -> Self:
|
) -> Self:
|
||||||
"""
|
"""
|
||||||
|
|
@ -562,7 +591,7 @@ class UOffer(PrimitiveOffer):
|
||||||
return cls(
|
return cls(
|
||||||
in_ptype = in_ptype,
|
in_ptype = in_ptype,
|
||||||
out_ptype = out_ptype,
|
out_ptype = out_ptype,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_planner = bbox_planner,
|
bbox_planner = bbox_planner,
|
||||||
endpoint_planner = endpoint_planner,
|
endpoint_planner = endpoint_planner,
|
||||||
commit_planner = commit_planner,
|
commit_planner = commit_planner,
|
||||||
|
|
@ -764,12 +793,14 @@ class AutoTool(Tool):
|
||||||
"""
|
"""
|
||||||
A routing tool assembled from reusable path primitives.
|
A routing tool assembled from reusable path primitives.
|
||||||
|
|
||||||
`AutoTool` chooses among prioritized straight generators, pre-rendered bends,
|
`AutoTool` chooses among straight generators, pre-rendered bends, optional
|
||||||
optional generated S-bend primitives, pre-rendered U-turns, and
|
generated S-bend primitives, pre-rendered U-turns, and
|
||||||
pre-rendered transitions registered through `add_straight()`,
|
pre-rendered transitions registered through `add_straight()`,
|
||||||
`add_bend()`, `add_sbend()`, `add_uturn()`, and `add_transition()`.
|
`add_bend()`, `add_sbend()`, `add_uturn()`, and `add_transition()`.
|
||||||
|
|
||||||
Registration call order defines primitive priority.
|
Primitive selection uses each registration's explicit `cost` policy rather
|
||||||
|
than registration order. Numeric costs scale the default geometric cost;
|
||||||
|
callable costs replace it.
|
||||||
|
|
||||||
Straight and bend offers use one straight and, if turning, one bend.
|
Straight and bend offers use one straight and, if turning, one bend.
|
||||||
`add_sbend()` exposes generated S-bend primitives. `add_uturn()` exposes
|
`add_sbend()` exposes generated S-bend primitives. `add_uturn()` exposes
|
||||||
|
|
@ -972,6 +1003,7 @@ class AutoTool(Tool):
|
||||||
in_port_name: str | None = None,
|
in_port_name: str | None = None,
|
||||||
*,
|
*,
|
||||||
length_range: tuple[float, float] = (0, numpy.inf),
|
length_range: tuple[float, float] = (0, numpy.inf),
|
||||||
|
cost: CostCallable | float = 1.0,
|
||||||
) -> Self:
|
) -> Self:
|
||||||
"""
|
"""
|
||||||
Register a generated straight primitive.
|
Register a generated straight primitive.
|
||||||
|
|
@ -980,8 +1012,8 @@ class AutoTool(Tool):
|
||||||
generated and the missing metadata is inferred from an equivalent
|
generated and the missing metadata is inferred from an equivalent
|
||||||
two-port straight. Metadata inference does not receive route options.
|
two-port straight. Metadata inference does not receive route options.
|
||||||
"""
|
"""
|
||||||
|
cost = _validated_cost(cost)
|
||||||
ptype, in_port_name = self._infer_straight_metadata(fn, length_range, ptype, in_port_name)
|
ptype, in_port_name = self._infer_straight_metadata(fn, length_range, ptype, in_port_name)
|
||||||
priority_bias = len(self._straight_offers) * BUILTIN_PRIORITY_STEP
|
|
||||||
|
|
||||||
def data_at(length: float) -> AutoTool.GeneratedData:
|
def data_at(length: float) -> AutoTool.GeneratedData:
|
||||||
return self.GeneratedData(fn, in_port_name, length)
|
return self.GeneratedData(fn, in_port_name, length)
|
||||||
|
|
@ -989,7 +1021,7 @@ class AutoTool(Tool):
|
||||||
self._straight_offers.append(StraightOffer.generated(
|
self._straight_offers.append(StraightOffer.generated(
|
||||||
ptype,
|
ptype,
|
||||||
data_at,
|
data_at,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_for_data = self._bbox_for_data,
|
bbox_for_data = self._bbox_for_data,
|
||||||
length_domain = length_range,
|
length_domain = length_range,
|
||||||
))
|
))
|
||||||
|
|
@ -1003,6 +1035,7 @@ class AutoTool(Tool):
|
||||||
*,
|
*,
|
||||||
clockwise: bool | None = None,
|
clockwise: bool | None = None,
|
||||||
mirror: bool = True,
|
mirror: bool = True,
|
||||||
|
cost: CostCallable | float = 1.0,
|
||||||
) -> Self:
|
) -> Self:
|
||||||
"""
|
"""
|
||||||
Register a reusable L-bend primitive.
|
Register a reusable L-bend primitive.
|
||||||
|
|
@ -1011,6 +1044,7 @@ class AutoTool(Tool):
|
||||||
direction is inferred from the selected port orientations; `clockwise`,
|
direction is inferred from the selected port orientations; `clockwise`,
|
||||||
when provided, is checked against that inferred direction.
|
when provided, is checked against that inferred direction.
|
||||||
"""
|
"""
|
||||||
|
cost = _validated_cost(cost)
|
||||||
if (in_port_name is None) != (out_port_name is None):
|
if (in_port_name is None) != (out_port_name is None):
|
||||||
raise BuildError('Bend port names must be provided together')
|
raise BuildError('Bend port names must be provided together')
|
||||||
if in_port_name is None or out_port_name is None:
|
if in_port_name is None or out_port_name is None:
|
||||||
|
|
@ -1019,7 +1053,6 @@ class AutoTool(Tool):
|
||||||
raise BuildError(f'Bend port names are required for {len(port_names)}-port abstracts')
|
raise BuildError(f'Bend port names are required for {len(port_names)}-port abstracts')
|
||||||
in_port_name, out_port_name = port_names
|
in_port_name, out_port_name = port_names
|
||||||
|
|
||||||
priority_bias = len(self._bend_offers[0]) * BUILTIN_PRIORITY_STEP
|
|
||||||
in_port = abstract.ports[in_port_name]
|
in_port = abstract.ports[in_port_name]
|
||||||
out_port = abstract.ports[out_port_name]
|
out_port = abstract.ports[out_port_name]
|
||||||
out_ptype = out_port.ptype
|
out_ptype = out_port.ptype
|
||||||
|
|
@ -1044,7 +1077,7 @@ class AutoTool(Tool):
|
||||||
endpoint = endpoint,
|
endpoint = endpoint,
|
||||||
data = reusable_data,
|
data = reusable_data,
|
||||||
ccw = ccw,
|
ccw = ccw,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_for_data = self._bbox_for_data,
|
bbox_for_data = self._bbox_for_data,
|
||||||
))
|
))
|
||||||
return self
|
return self
|
||||||
|
|
@ -1058,6 +1091,7 @@ class AutoTool(Tool):
|
||||||
*,
|
*,
|
||||||
jog_range: tuple[float, float] = (0, numpy.inf),
|
jog_range: tuple[float, float] = (0, numpy.inf),
|
||||||
endpoint: GeneratedEndpointFn | None = None,
|
endpoint: GeneratedEndpointFn | None = None,
|
||||||
|
cost: CostCallable | float = 1.0,
|
||||||
) -> Self:
|
) -> Self:
|
||||||
"""
|
"""
|
||||||
Register a generated S-bend primitive.
|
Register a generated S-bend primitive.
|
||||||
|
|
@ -1070,6 +1104,7 @@ class AutoTool(Tool):
|
||||||
and the missing metadata is inferred from an equivalent two-port S-bend.
|
and the missing metadata is inferred from an equivalent two-port S-bend.
|
||||||
Metadata inference and endpoint planning do not receive route options.
|
Metadata inference and endpoint planning do not receive route options.
|
||||||
"""
|
"""
|
||||||
|
cost = _validated_cost(cost)
|
||||||
ptype, in_port_name, out_port_name = self._infer_sbend_metadata(
|
ptype, in_port_name, out_port_name = self._infer_sbend_metadata(
|
||||||
fn,
|
fn,
|
||||||
jog_range,
|
jog_range,
|
||||||
|
|
@ -1090,8 +1125,6 @@ class AutoTool(Tool):
|
||||||
return out_port
|
return out_port
|
||||||
|
|
||||||
for jog_domain in self._signed_jog_domains(jog_range):
|
for jog_domain in self._signed_jog_domains(jog_range):
|
||||||
priority_bias = len(self._s_offers) * BUILTIN_PRIORITY_STEP
|
|
||||||
|
|
||||||
def data_at(jog: float) -> AutoTool.GeneratedData:
|
def data_at(jog: float) -> AutoTool.GeneratedData:
|
||||||
return self.GeneratedData(
|
return self.GeneratedData(
|
||||||
fn,
|
fn,
|
||||||
|
|
@ -1104,7 +1137,7 @@ class AutoTool(Tool):
|
||||||
ptype,
|
ptype,
|
||||||
endpoint_at,
|
endpoint_at,
|
||||||
data_at,
|
data_at,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_for_data = self._bbox_for_data,
|
bbox_for_data = self._bbox_for_data,
|
||||||
jog_domain = jog_domain,
|
jog_domain = jog_domain,
|
||||||
))
|
))
|
||||||
|
|
@ -1117,10 +1150,12 @@ class AutoTool(Tool):
|
||||||
out_port_name: str,
|
out_port_name: str,
|
||||||
*,
|
*,
|
||||||
mirror: bool = True,
|
mirror: bool = True,
|
||||||
|
cost: CostCallable | float = 1.0,
|
||||||
) -> Self:
|
) -> Self:
|
||||||
"""
|
"""
|
||||||
Register a reusable U-turn primitive.
|
Register a reusable U-turn primitive.
|
||||||
"""
|
"""
|
||||||
|
cost = _validated_cost(cost)
|
||||||
in_port = abstract.ports[in_port_name]
|
in_port = abstract.ports[in_port_name]
|
||||||
out_port = abstract.ports[out_port_name]
|
out_port = abstract.ports[out_port_name]
|
||||||
dxy, angle = in_port.measure_travel(out_port)
|
dxy, angle = in_port.measure_travel(out_port)
|
||||||
|
|
@ -1140,7 +1175,6 @@ class AutoTool(Tool):
|
||||||
mirrored: bool,
|
mirrored: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
reusable_data = self.ReusableData(abstract, in_port_name, mirrored)
|
reusable_data = self.ReusableData(abstract, in_port_name, mirrored)
|
||||||
priority_bias = len(self._u_offers) * BUILTIN_PRIORITY_STEP
|
|
||||||
endpoint = Port((length, offer_jog), rotation=0, ptype=out_ptype)
|
endpoint = Port((length, offer_jog), rotation=0, ptype=out_ptype)
|
||||||
|
|
||||||
self._u_offers.append(UOffer.prebuilt(
|
self._u_offers.append(UOffer.prebuilt(
|
||||||
|
|
@ -1148,7 +1182,7 @@ class AutoTool(Tool):
|
||||||
out_ptype = out_ptype,
|
out_ptype = out_ptype,
|
||||||
endpoint = endpoint,
|
endpoint = endpoint,
|
||||||
data = reusable_data,
|
data = reusable_data,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_for_data = self._bbox_for_data,
|
bbox_for_data = self._bbox_for_data,
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
@ -1164,6 +1198,7 @@ class AutoTool(Tool):
|
||||||
our_port_name: str | None = None,
|
our_port_name: str | None = None,
|
||||||
*,
|
*,
|
||||||
one_way: bool = False,
|
one_way: bool = False,
|
||||||
|
cost: CostCallable | float = 1.0,
|
||||||
) -> Self:
|
) -> Self:
|
||||||
"""
|
"""
|
||||||
Register a reusable port-type transition and expose it as router-visible adapter offers.
|
Register a reusable port-type transition and expose it as router-visible adapter offers.
|
||||||
|
|
@ -1171,6 +1206,7 @@ class AutoTool(Tool):
|
||||||
If the transition has exactly two ports and is bidirectional, port names
|
If the transition has exactly two ports and is bidirectional, port names
|
||||||
may be omitted.
|
may be omitted.
|
||||||
"""
|
"""
|
||||||
|
cost = _validated_cost(cost)
|
||||||
if (their_port_name is None) != (our_port_name is None):
|
if (their_port_name is None) != (our_port_name is None):
|
||||||
raise BuildError('Transition port names must be provided together')
|
raise BuildError('Transition port names must be provided together')
|
||||||
if their_port_name is None or our_port_name is None:
|
if their_port_name is None or our_port_name is None:
|
||||||
|
|
@ -1181,9 +1217,9 @@ class AutoTool(Tool):
|
||||||
raise BuildError(f'Transition port names are required for {len(port_names)}-port abstracts')
|
raise BuildError(f'Transition port names are required for {len(port_names)}-port abstracts')
|
||||||
their_port_name, our_port_name = port_names
|
their_port_name, our_port_name = port_names
|
||||||
|
|
||||||
self._add_transition_direction(abstract, their_port_name, our_port_name)
|
self._add_transition_direction(abstract, their_port_name, our_port_name, cost)
|
||||||
if not one_way:
|
if not one_way:
|
||||||
self._add_transition_direction(abstract, our_port_name, their_port_name)
|
self._add_transition_direction(abstract, our_port_name, their_port_name, cost)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -1261,6 +1297,7 @@ class AutoTool(Tool):
|
||||||
abstract: Abstract,
|
abstract: Abstract,
|
||||||
their_port_name: str,
|
their_port_name: str,
|
||||||
our_port_name: str,
|
our_port_name: str,
|
||||||
|
cost: CostCallable | float,
|
||||||
) -> None:
|
) -> None:
|
||||||
their_port = abstract.ports[their_port_name]
|
their_port = abstract.ports[their_port_name]
|
||||||
our_port = abstract.ports[our_port_name]
|
our_port = abstract.ports[our_port_name]
|
||||||
|
|
@ -1286,14 +1323,13 @@ class AutoTool(Tool):
|
||||||
endpoint = Port((dx, dy), rotation=pi, ptype=our_port.ptype)
|
endpoint = Port((dx, dy), rotation=pi, ptype=our_port.ptype)
|
||||||
|
|
||||||
offers = self._transition_adapter_offers_by_key.setdefault((kind, in_key), [])
|
offers = self._transition_adapter_offers_by_key.setdefault((kind, in_key), [])
|
||||||
priority_bias = len(offers) * BUILTIN_PRIORITY_STEP
|
|
||||||
if kind == 'straight':
|
if kind == 'straight':
|
||||||
offers.append(StraightOffer.prebuilt(
|
offers.append(StraightOffer.prebuilt(
|
||||||
in_ptype = their_port.ptype,
|
in_ptype = their_port.ptype,
|
||||||
out_ptype = our_port.ptype,
|
out_ptype = our_port.ptype,
|
||||||
endpoint = endpoint,
|
endpoint = endpoint,
|
||||||
data = transition_data,
|
data = transition_data,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_for_data = self._bbox_for_data,
|
bbox_for_data = self._bbox_for_data,
|
||||||
))
|
))
|
||||||
return
|
return
|
||||||
|
|
@ -1303,7 +1339,7 @@ class AutoTool(Tool):
|
||||||
out_ptype = our_port.ptype,
|
out_ptype = our_port.ptype,
|
||||||
endpoint = endpoint,
|
endpoint = endpoint,
|
||||||
data = transition_data,
|
data = transition_data,
|
||||||
priority_bias = priority_bias,
|
cost = cost,
|
||||||
bbox_for_data = self._bbox_for_data,
|
bbox_for_data = self._bbox_for_data,
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue