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 (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:

  • ax (Axes | None, default: None ) –

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

  • show_walls (bool, default: True ) –

    Draw walls and wall polygon.

  • show_targets (bool, default: True ) –

    Draw target points.

  • show_uncoverable_targets (bool, default: False ) –

    Highlight uncoverable targets.

  • show_dropped_dominated_sensors (bool, default: True ) –

    Draw dominated dropped sensors.

  • show_dropped_degree1_sensors (bool, default: True ) –

    Draw degree-1 dropped sensors.

  • show_dropped_targets (bool, default: True ) –

    Draw dropped targets.

  • show_candidate_sensors (bool, default: True ) –

    Draw candidate sensors.

  • show_coverage_rays (bool, default: False ) –

    Draw all coverage rays.

  • show_sensor_headings (bool, default: True ) –

    Draw sensor heading arrows.

Returns:

  • Axes

    The axes with the plot.

Raises:

  • 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:

  • data (SppData | None, default: None ) –

    Problem data used for geometry and coverage information.

  • ax (Axes | None, default: None ) –

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

  • show_walls (bool, default: True ) –

    Draw walls and wall polygon.

  • show_targets (bool, default: True ) –

    Draw target points.

  • show_uncoverable_targets (bool, default: False ) –

    Highlight uncoverable targets.

  • show_dropped_dominated_sensors (bool, default: True ) –

    Draw dominated dropped sensors.

  • show_dropped_degree1_sensors (bool, default: True ) –

    Draw degree-1 dropped sensors.

  • show_dropped_targets (bool, default: True ) –

    Draw dropped targets.

  • show_candidate_sensors (bool, default: True ) –

    Draw non-selected candidate sensors.

  • show_selected_sensors (bool, default: True ) –

    Draw selected sensors.

  • show_covered_targets (bool, default: True ) –

    Draw covered targets.

  • show_uncovered_targets (bool, default: True ) –

    Draw uncovered targets.

  • show_coverage_rays_all (bool, default: False ) –

    Draw all target-to-candidate coverage rays.

  • show_coverage_rays_selected (bool, default: False ) –

    Draw target-to-selected coverage rays.

  • show_sensor_headings (bool, default: True ) –

    Draw sensor heading arrows.

Returns:

  • Axes

    The axes with the plot.

Raises:

  • 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:

  • 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.

filter_infeasible(max_runtime: float = 3600, *, quiet: bool = True) -> list[bool]

Drop the instances of this collection that have no feasible solution.

Every instance is formulated and handed to SCIP, which stops as soon as it finds the first feasible solution. An instance is removed from the collection when SCIP proves the model infeasible, when no solution turns up within max_runtime, or when formulating it fails altogether. This keeps randomly generated instances from breaking a downstream pipeline.

Parameters:

  • max_runtime (float, default: 3600 ) –

    SCIP time limit per instance in seconds. Must be positive. Defaults to 3600 seconds.

  • quiet (bool, default: True ) –

    Suppress the SCIP solver output.

Returns:

  • list[bool]

    Feasibility mask over the instances as they were before filtering, in that order: True where the instance was kept, False where it was removed.

Raises: