Skip to content

Sensor Positioning (SP) API Reference

Data

Data model for the Sensor Positioning (SP) use case.

SppData

Bases: UcData

Materialized coverage representation for Sensor Positioning.

This variant assumes coverage was precomputed (e.g., from geometry) and stored as a boolean matrix: targets x positions. Fixed-on/off sets (fixed_on, fixed_off) capture degree-1/dominated preprocessing decisions.

Attributes:

Name Type Description
name Literal['sensor_position_problem']

Identifier.

position_ids list[str]

Identifiers for candidate sensor placements.

target_ids list[str]

Identifiers for targets/street points to cover.

coverage NumPyArray

Boolean matrix shape (n_targets, n_positions): coverage[t, p] is True if position p covers target t.

position_costs NumPyArray

Length n_positions; cost of activating each position (default 1).

min_coverage list[int]

Required coverage per target (broadcasted from int if needed).

budget float | None

Optional cost budget (<= constraint).

max_positions int | None

Optional cardinality cap.

incompatibilities list[tuple[int, int]]

Pairwise exclusions between positions.

must_select list[int]

Positions that must be activated.

forbidden list[int]

Positions that must stay deactivated.

fixed_on list[int]

Positions forced to 1 from preprocessing (e.g., degree-1 reductions).

fixed_off list[int]

Positions forced to 0 from preprocessing (e.g., dominated reductions).

uncoverable_targets list[int] | None

Target indices that cannot be covered by any candidate sensor.

cost_weight float

Weight on cost term (default 1.0).

proximity_penalty_weight float

Optional weight for future pairwise penalties (not used yet).

dropped_dominated_positions NumPyArray | None

Display-only geometry for dominated dropped lidars.

dropped_degree1_positions NumPyArray | None

Display-only geometry for degree-1 dropped lidars.

dropped_target_positions NumPyArray | None

Display-only geometry for targets removed by degree-1 reductions.

walls list[WallLike] | None

Optional wall geometry as tuples in this order: (endpoint_a[x, y], endpoint_b[x, y], wall_height, sensor_density, lidar_height, wall_offset, direction_mode, pitch).

group_ids list[str | None]

Optional mutual-exclusion groups (variants) per position; same group means at most one.

lidar_params list[dict] | None

Per-position coverage overrides (max_radius, half_horizontal_angle, max_vert_angle, min_vert_angle).

position_metadata list[dict] | None

Display metadata per position (labels, source, groupId, coverage params, variantOf, cost).

to_string() -> str

Summarize core counts and reduction metadata.

to_problem_dict(*, include_metadata: bool = True, include_coverage: bool = False) -> dict[str, Any]

Convert the instance to the enriched problem dictionary format.

save_to_json(path: str | Path, *, include_metadata: bool = True, include_coverage: bool = False) -> Path

Persist the problem dictionary to JSON on disk.

with_coverage(coverage: np.ndarray) -> SppData

Return a new instance with updated coverage while retaining metadata.

plot(*, ax: Axes | None = None, show_walls: bool = True, show_targets: bool = True, show_uncoverable_targets: bool = False, show_dropped_dominated_sensors: bool = True, show_dropped_degree1_sensors: bool = True, show_dropped_targets: bool = True, show_candidate_sensors: bool = True, show_coverage_rays: bool = False, show_sensor_headings: bool = True) -> Axes

Plot the SP problem structure on the provided axes.

Parameters:

Name Type Description Default
ax Axes | None

Matplotlib axes to draw on. If None, a new axes is created.

None
show_walls bool

Draw walls and wall polygon.

True
show_targets bool

Draw target points.

True
show_uncoverable_targets bool

Highlight uncoverable targets.

False
show_dropped_dominated_sensors bool

Draw dominated dropped sensors.

True
show_dropped_degree1_sensors bool

Draw degree-1 dropped sensors.

True
show_dropped_targets bool

Draw dropped targets.

True
show_candidate_sensors bool

Draw candidate sensors.

True
show_coverage_rays bool

Draw all coverage rays.

False
show_sensor_headings bool

Draw sensor heading arrows.

True

Returns:

Type Description
Axes

The axes with the plot.

Raises:

Type Description
InvalidProblemStructureError

If required geometry is missing (lidar_positions or target_positions).

generate_random(n_positions: int = 10, n_targets: int = 20, density: float = 0.2, seed: int | None = None) -> SppData staticmethod

Create a random SP instance with guaranteed coverable targets.

Formulation

Formulation for the Sensor Positioning (SP) use case.

SppFormulation

Bases: UcFormulation[SppData, SppSolution]

Min-cost set-cover style formulation using materialized coverage.

to_string(data: SppData) -> str staticmethod

Return a text summary of the formulated model inputs.

formulate(data: SppData) -> Model staticmethod

Build the mixed-integer model for the SP instance.

interpret(solution: Solution, data: SppData) -> SppSolution staticmethod

Map solver output back into an SpSolution with coverage metrics.

Solution

Solution model for the Sensor Positioning use case.

SppSolution

Bases: UcSolution

Selected positions and coverage metrics.

to_string() -> str

Return a formatted summary of the solution.

print() -> str

Return the string representation (alias for to_string).

plot(data: SppData | None = None, *, ax: Axes | None = None, show_walls: bool = True, show_targets: bool = True, show_uncoverable_targets: bool = False, show_dropped_dominated_sensors: bool = True, show_dropped_degree1_sensors: bool = True, show_dropped_targets: bool = True, show_candidate_sensors: bool = True, show_selected_sensors: bool = True, show_covered_targets: bool = True, show_uncovered_targets: bool = True, show_coverage_rays_all: bool = False, show_coverage_rays_selected: bool = False, show_sensor_headings: bool = True) -> Axes

Plot the SP solution structure on the provided axes.

Parameters:

Name Type Description Default
data SppData | None

Problem data used for geometry and coverage information.

None
ax Axes | None

Matplotlib axes to draw on. If None, a new axes is created.

None
show_walls bool

Draw walls and wall polygon.

True
show_targets bool

Draw target points.

True
show_uncoverable_targets bool

Highlight uncoverable targets.

False
show_dropped_dominated_sensors bool

Draw dominated dropped sensors.

True
show_dropped_degree1_sensors bool

Draw degree-1 dropped sensors.

True
show_dropped_targets bool

Draw dropped targets.

True
show_candidate_sensors bool

Draw non-selected candidate sensors.

True
show_selected_sensors bool

Draw selected sensors.

True
show_covered_targets bool

Draw covered targets.

True
show_uncovered_targets bool

Draw uncovered targets.

True
show_coverage_rays_all bool

Draw all target-to-candidate coverage rays.

False
show_coverage_rays_selected bool

Draw target-to-selected coverage rays.

False
show_sensor_headings bool

Draw sensor heading arrows.

True

Returns:

Type Description
Axes

The axes with the plot.

Raises:

Type Description
ValueError

If data is not provided.

InvalidProblemStructureError

If required geometry is missing on data.

DataShapeMismatchError

If data.coverage shape is inconsistent with geometry.

Instance

Instance model for Sp use case.

SppInstance

Bases: UcInstance[SppData, SppFormulation, SppSolution]

Instance combining data and formulation for Sp.

Collection

Collection of Sp instances.

SppCollection

Bases: UcInstanceCollection[SppInstance]

Lightweight SP collection utilities.

from_random(n_positions: int, n_targets: int, density: float = 0.2, num_instances: int = 1, seed: int | None = None) -> SppCollection classmethod

Generate a collection of random SP instances.

from_json_file(path: str, *, max_vert_angle: float = 30, min_vert_angle: float = -80, max_radius: float = 2.5, half_horizontal_angle: float = 180, lidar_wall_offset: float = 0.2, min_coverage: int = 1, budget: float | None = None, max_positions: int | None = None, sensor_reduction: Literal['none', 'drop', 'fix'] = 'none', auto_variants: bool = False, auto_variant_specs: list[str] | None = None, auto_variant_group_mode: Literal['by-label', 'per-base-label'] = 'per-base-label', auto_variant_base_group: bool = True, auto_variant_cost_mult: float = 1.0, save_enriched_path: str | Path | None = None, include_metadata: bool = True, include_coverage: bool = True) -> SppCollection classmethod

Load collection from JSON file.

Args: path: Path to JSON file. max_vert_angle: Maximum vertical viewing angle (degrees). min_vert_angle: Minimum vertical viewing angle (degrees). max_radius: Maximum sensor range. half_horizontal_angle: Half of horizontal field of view (degrees). lidar_wall_offset: Distance from wall endpoints when generating lidars. min_coverage: Required minimum coverage per target. budget: Optional total cost budget. max_positions: Optional cap on selected positions. sensor_reduction: "none" (default), "drop" to remove redundant sensors, "fix" to keep them but mark as fixed on/off.

Returns:

Type Description
SpCollection with one instance from the JSON file.

from_json_obj(problem_dict: dict[str, Any], *, max_vert_angle: float = 30, min_vert_angle: float = -80, max_radius: float = 2.5, half_horizontal_angle: float = 180, lidar_wall_offset: float = 0.2, min_coverage: int = 1, budget: float | None = None, max_positions: int | None = None, sensor_reduction: Literal['none', 'drop', 'fix'] = 'none', auto_variants: bool = False, auto_variant_specs: list[str] | None = None, auto_variant_group_mode: Literal['by-label', 'per-base-label'] = 'per-base-label', auto_variant_base_group: bool = True, auto_variant_cost_mult: float = 1.0, save_enriched_path: str | Path | None = None, include_metadata: bool = True, include_coverage: bool = True) -> SppCollection classmethod

Load collection from an in-memory JSON object.

from_json_str(json_string: str, *, max_vert_angle: float = 30, min_vert_angle: float = -80, max_radius: float = 2.5, half_horizontal_angle: float = 180, lidar_wall_offset: float = 0.2, min_coverage: int = 1, budget: float | None = None, max_positions: int | None = None, sensor_reduction: Literal['none', 'drop', 'fix'] = 'none', auto_variants: bool = False, auto_variant_specs: list[str] | None = None, auto_variant_group_mode: Literal['by-label', 'per-base-label'] = 'per-base-label', auto_variant_base_group: bool = True, auto_variant_cost_mult: float = 1.0, save_enriched_path: str | Path | None = None, include_metadata: bool = True, include_coverage: bool = True) -> SppCollection classmethod

Load collection from JSON string payload.