Secondary Network Strategies#

New in v0.7.0

Pluggable secondary network strategies allow you to control how loads are connected to their serving transformer.

Overview#

The secondary (low-voltage) network connects individual customer loads to their distribution transformer. Different topologies suit different deployment contexts — dense urban areas may follow road paths, while rural residential areas typically use simple radial connections.

Each strategy implements the SecondaryNetworkStrategy interface and can be passed to PRSG via the secondary_strategy parameter.


Available Strategies#

MeshSteinerStrategy (default)#

Rectangular mesh grid + Steiner tree reduction. The original SHIFT algorithm.

  • Algorithm: Build 2D grid in group bounding box, find Steiner tree to connect load points

  • Topology: Grid-aligned tree (right-angle connections)

  • Parameters: spacing (default 50m)

  • Trade-off: Works well for uniform areas; produces right-angle artifacts


RadialStrategy#

Direct star connection from transformer to each load.

  • Algorithm: Create center node at transformer location, connect each load directly

  • Topology: Pure radial star (1 hop from transformer to each load)

  • Trade-off: Simplest and most common real-world residential lateral topology; no intermediate nodes

Reference: Ali et al. [APM+23]


DelaunayStrategy#

Delaunay triangulation of load points with MST pruning.

  • Algorithm: (1) Triangulate all points (loads + center), (2) Weight edges by geodesic distance, (3) Extract MST

  • Topology: Organic, non-grid tree following natural point clusters

  • Trade-off: More natural-looking than mesh; requires ≥3 non-collinear points (falls back to radial otherwise)


OpenStreetSecondaryStrategy#

Road-aware secondary routing using local OpenStreetMap roads.

  • Algorithm: Fetch local road network for group area, route using a configurable RoutingStrategy (default: WeightedSteinerTreeStrategy)

  • Parameters: routing_strategy, buffer (default 50m)

  • Topology: Follows actual street layout

  • Trade-off: Most realistic for urban areas; requires network fetch per group (slower)

References: Ali et al. [APM+23], Caetano et al. [CGdO+26]


HubLineStrategy#

k-nearest-neighbor consumer-to-transformer assignment.

  • Algorithm: Sort loads by distance to transformer center (hub), connect each directly

  • Topology: Star topology with loads ordered by proximity

  • Trade-off: Similar output to RadialStrategy but preserves distance-ordering information; mirrors utility hub-line assignment practice

Reference: Ali et al. [APM+23]


Usage Examples#

Radial secondary (simplest)#

from shift import PRSG, RadialStrategy, GeoLocation

builder = PRSG(
    groups=clusters,
    source_location=GeoLocation(-97.3, 32.75),
    secondary_strategy=RadialStrategy(),
)
graph = builder.get_distribution_graph()

Road-aware secondary#

from shift import PRSG, OpenStreetSecondaryStrategy, GeoLocation

builder = PRSG(
    groups=clusters,
    source_location=GeoLocation(-97.3, 32.75),
    secondary_strategy=OpenStreetSecondaryStrategy(),
)
graph = builder.get_distribution_graph()

Combining strategies#

from shift import (
    PRSG,
    WeightedSteinerTreeStrategy,
    HubLineStrategy,
    GeoLocation,
)

builder = PRSG(
    groups=clusters,
    source_location=GeoLocation(-97.3, 32.75),
    routing_strategy=WeightedSteinerTreeStrategy(),  # primary
    secondary_strategy=HubLineStrategy(),            # secondary
)
graph = builder.get_distribution_graph()

API Reference#

class shift.SecondaryNetworkStrategy#

Abstract base class for secondary network construction strategies.

A secondary network strategy determines how load points within a group (cluster) are connected to their serving transformer location.

abstract build(group: GroupModel) Graph#

Build the secondary network for a group of loads.

Parameters:

group (GroupModel) – Group containing load points and a center (transformer location).

Returns:

A connected graph with node attributes ‘x’ and ‘y’ representing the secondary network topology.

Return type:

nx.Graph

class shift.MeshSteinerStrategy(spacing: ~infrasys.quantities.Distance = <Quantity(50, 'meter')>)#

Bases: SecondaryNetworkStrategy

Rectangular mesh grid + Steiner tree (current default behavior).

Builds a 2D rectangular grid within the bounding box of the group’s points, then computes a Steiner tree connecting the nearest grid nodes to each load point.

Parameters:

spacing (Distance, optional) – Grid spacing. Defaults to 50 meters.

build(group: GroupModel) Graph#

Build the secondary network for a group of loads.

Parameters:

group (GroupModel) – Group containing load points and a center (transformer location).

Returns:

A connected graph with node attributes ‘x’ and ‘y’ representing the secondary network topology.

Return type:

nx.Graph

class shift.RadialStrategy#

Bases: SecondaryNetworkStrategy

Direct radial (star) connection from transformer to each load.

Connects each load point directly to the group center (transformer location) with a straight-line edge. This is the most common topology for residential distribution laterals and eliminates the jagged mesh artifacts.

References

  • All papers confirm radial = most common distribution topology

build(group: GroupModel) Graph#

Build the secondary network for a group of loads.

Parameters:

group (GroupModel) – Group containing load points and a center (transformer location).

Returns:

A connected graph with node attributes ‘x’ and ‘y’ representing the secondary network topology.

Return type:

nx.Graph

class shift.DelaunayStrategy#

Bases: SecondaryNetworkStrategy

Delaunay triangulation of load points + MST pruning.

Builds a Delaunay triangulation of the group points (including the center), then prunes it to a minimum spanning tree using geodesic distance as edge weights. Produces organic, non-grid layouts.

build(group: GroupModel) Graph#

Build the secondary network for a group of loads.

Parameters:

group (GroupModel) – Group containing load points and a center (transformer location).

Returns:

A connected graph with node attributes ‘x’ and ‘y’ representing the secondary network topology.

Return type:

nx.Graph

class shift.OpenStreetSecondaryStrategy(routing_strategy: ~shift.graph.routing.RoutingStrategy | None = None, buffer: ~infrasys.quantities.Distance = <Quantity(50, 'meter')>)#

Bases: SecondaryNetworkStrategy

Road-aware secondary network using local OpenStreetMap roads.

Fetches the local road network for the group’s bounding area and routes the secondary network along actual roads using a configurable routing strategy (defaults to weighted Steiner tree).

Parameters:
  • routing_strategy (RoutingStrategy, optional) – Strategy for routing within the fetched road network. Defaults to WeightedSteinerTreeStrategy (geodesic distance).

  • buffer (Distance, optional) – Buffer around group bounding box for road fetching. Defaults to 50 meters.

References

  • Ali et al. 2023: “power lines follow road paths”

  • Caetano et al. 2026: “distribution networks are usually routed along the streets”

build(group: GroupModel) Graph#

Build the secondary network for a group of loads.

Parameters:

group (GroupModel) – Group containing load points and a center (transformer location).

Returns:

A connected graph with node attributes ‘x’ and ‘y’ representing the secondary network topology.

Return type:

nx.Graph

class shift.HubLineStrategy#

Bases: SecondaryNetworkStrategy

k-nearest-neighbor consumer-to-transformer assignment.

Based on the hub-line algorithm from Ali et al. 2023. Connects each consumer to the transformer (hub) via the shortest road-network path, or directly if no road network is provided.

The hub-line algorithm ranks consumers by spatial distance to the transformer and connects the nearest consumers to each hub.

This produces a star topology per transformer where consumers are assigned based on proximity.

References

  • Ali et al. 2023: Hub-line algorithm for determining number of consumers connected to a single transformer (k-nearest neighbor)

build(group: GroupModel) Graph#

Build the secondary network for a group of loads.

Parameters:

group (GroupModel) – Group containing load points and a center (transformer location).

Returns:

A connected graph with node attributes ‘x’ and ‘y’ representing the secondary network topology.

Return type:

nx.Graph


References#