routing.core.optimizer#

class routing.core.optimizer.ConvergenceCallback(tolerance: float = 1.0, window: int = 5, max_stop_value: float = 1000000.0, plot_cost_history: bool = False)[source]#

Bases: object

Callback for early stopping of dual annealing optimization based on convergence criteria.

This class does not inherit from any base class, and monitors the cost function history during optimization to detect convergence. When the variation in recent iterations (within a sliding window) falls below a specified tolerance threshold, it signals the optimizer to stop early, preventing unnecessary computation when the optimization has effectively converged.

The callback is called by scipy.optimize.dual_annealing at each iteration and only tracks accepted solutions (context == 1) to avoid noise from rejected proposals.

Parameters:
  • tolerance – Maximum allowed variation in cost function over the window period. If the difference between max and min costs in the recent window is below this value, convergence is detected. Defaults to 1.0.

  • window – Number of recent iterations to consider when checking convergence. A larger window makes convergence detection more stable but less responsive. Defaults to 5.

  • max_stop_value – Maximum acceptable cost value for early stopping. Early stopping is only triggered if the best cost in the window is below this threshold, preventing premature stopping when the optimizer is still exploring high-cost regions. Defaults to 1e6.

  • plot_cost_history – If True, plot the convergence history at the end of optimization. Defaults to False.

get_convergence_statistics() dict[source]#

Compute and return statistics about the convergence history.

Analyzes the stored cost history to compute key metrics: - Initial and final costs - Best cost found - Improvement (absolute and percentage) - Total number of accepted iterations - Convergence status (whether early stopping was triggered)

Returns a dictionary with all statistics, or None values if no history exists.

Returns:

Dictionary containing convergence statistics with keys: - initial_cost: First cost value in history (or None) - final_cost: Last cost value in history (or None) - best_cost: Minimum cost value found (or None) - improvement: Absolute improvement (initial - best) (or None) - improvement_percent: Percentage improvement (or None) - total_iterations: Number of accepted iterations (0 if no history) - converged: Boolean indicating if convergence was detected (False if no history)

load_history(filepath: str) None[source]#

Load convergence history from a file.

Parameters:

filepath – path to load the history from (.npy format)

plot_convergence(title: str = 'Optimization Convergence History', figsize: tuple = (10, 6)) tuple[Figure, Axes][source]#

Plot the convergence history of the optimization process using matplotlib.

Creates a visualization showing: 1. Cost value evolution: Line plot of cost function over accepted iterations 2. Best so far: Rolling minimum showing the best solution found up to each iteration 3. Automatic scaling: Uses log scale if values span multiple orders of magnitude

This helps diagnose convergence behavior and identify potential issues like: - Premature convergence (cost plateaus early) - Oscillations (cost fluctuates without improving) - Slow convergence (gradual improvement over many iterations)

Returns empty plot with debug messages if no history is available.

Parameters:
  • title – Title for the plot. Defaults to “Optimization Convergence History”.

  • figsize – Figure size as (width, height) in inches. Defaults to (10, 6).

Returns:

Tuple of (fig, ax) matplotlib objects for further customization. Returns empty plot if no history is available.

print_statistics(title: str) None[source]#

Print convergence statistics and optionally plot convergence history.

Displays optimization statistics including initial cost, best cost, improvement percentage, and convergence status. Optionally plots the convergence history if plot_cost_history was enabled.

Parameters:

title – Title for the convergence plot (if plotting enabled).

Returns:

None

reset_history() None[source]#

Reset the convergence history to empty.

Clears all stored cost values from previous optimization runs. This is useful when reusing the same callback instance for multiple optimization runs, ensuring each run starts with a clean history.

Returns:

None

save_history(filepath: str) None[source]#

Save the convergence history to a file.

Exports the cost function history as a numpy array in .npy format for later analysis or visualization. If no history exists, logs a debug message and returns without saving.

Parameters:

filepath – Path to save the history file (should end with .npy).

Returns:

None

class routing.core.optimizer.Costs(length: float = 1000, sideways: float = 5000, short_line: float = 5000, gravity: float = 5000, bend: float = 500, constraints: float = 5000, interferences: float = 100000000, name: str = '')[source]#

Bases: DessiaObject

A class representing cost function weights for routing optimization algorithm.

This class inherits from DessiaObject, and defines the relative weights for different cost components in the optimization objective function. Higher weights create stronger preferences for minimizing that cost component.

Parameters:
  • length – The weight for total path length cost (prefer shorter paths). Defaults to 1000.

  • sideways – The weight for sideways movement penalty (prefer forward movement). Defaults to 5000.

  • short_line – The weight for short line segment penalty (prefer longer segments). Defaults to 5000.

  • gravity – The weight for gravity-related routing cost (slope constraints). Defaults to 5000.

  • bend – The weight for path bending penalty (prefer straight paths). Defaults to 500.

  • constraints – The weight for constraint violation penalty (hard constraints). Defaults to 5000.

  • interferences – The weight for interference/collision penalty (avoid collisions). Defaults to 100000000.

  • name – The name to identify this cost configuration. Defaults to ‘’.

to_weights() tuple[float, float, float, float, float, float, float][source]#

Convert cost weights to tuple format for optimization.

Returns all cost weights in the order expected by the optimization cost function: length, short_line, gravity, interferences, sideways, bend, constraints.

Returns:

Tuple of 7 float values representing cost weights in order: (length, short_line, gravity, interferences, sideways, bend, constraints).

class routing.core.optimizer.Optimizer(cadmap: CadMap, hd_voxels: MatrixBasedVoxelization, max_shift: float = 0.2, method: str = 'global_3d', name: str = '')[source]#

Bases: DessiaObject

A class representing an optimizer for post-routing pipe path refinement.

This class inherits from DessiaObject, and uses simulated annealing to refine pipe paths generated by pathfinding, optimizing for length, bends, constraints, and other objectives. It works with high-resolution voxelization for precise optimization.

Parameters:
  • cadmap – The CadMap object containing the routing space, volumes, and design rules for constraint checking.

  • hd_voxels – The high-resolution voxelization (typically finer than pathfinding grid) for precise optimization.

  • max_shift – The maximum allowed displacement (in length units) during one optimization iteration. Controls step size. Defaults to 0.2.

  • method – The optimization method. Currently supports ‘global_3d’ for 3D global optimization. Defaults to ‘global_3d’.

  • name – The name to identify this optimizer. Defaults to ‘’.

static build_ports_index(hd_cadmap: CadMap, points: ndarray) tuple[tuple[int, int, int], tuple[int, int, int]][source]#

Build port voxel indices for input and output ports.

Finds the last active voxel on lines from port extension points to the actual port positions. This identifies where the pipe path connects to the ports in voxel space, which is needed for: - Line-of-sight checking from ports - Constraint validation at port connections - Cost computation for port extension segments

For input port: traces from first point to input port position. For output port: traces from last point to output port position.

Parameters:
  • hd_cadmap – High-resolution CadMap with weight tensor for voxel checking.

  • points – Array of shape (n_points, 3) with point coordinates. Must have at least 2 points (first and last are used).

Returns:

Tuple of (input_port_index, output_port_index) as Index3D tuples (i, j, k) representing the last active voxel on each port extension line.

check_solution(refined_pipes: list[OptimizedPipe], solution: Solution, pipe_index: int) tuple[list[ndarray], dict[str, int]][source]#

Check optimized solution for validity and identify problematic voxels.

Validates the optimized pipes and identifies issues: 1. Checks if any pipes are valid (pass all constraints) 2. If invalid, identifies overweighted voxels (problematic regions) 3. Counts failed constraints (short lines, gravity violations, etc.)

Returns empty lists if solution is valid, otherwise provides diagnostic information about what went wrong.

Parameters:
  • refined_pipes – List of OptimizedPipe objects from optimization.

  • solution – Solution object with pipe_type and constraints.

  • pipe_index – Index of the pipe being checked in solution.optimized_pipes.

Returns:

Tuple of (overweighted_voxels, failed_constraints) where: - overweighted_voxels: List of arrays with voxel indices in problematic

regions (empty if solution is valid)

  • failed_constraints: Dictionary mapping constraint names to violation counts (empty if solution is valid)

compute_total_cost(points: ndarray, voxel_coords: list[tuple[int, int, int]], solution: Solution, index_ports: tuple[tuple[int, int, int], tuple[int, int, int]], lines_box_matrix: ndarray, optimized_lines: list[PipeLine], all_pooled_lines: list[list[PipeLine]], hd_cadmap: CadMap, toggling_constraints: dict[str, tuple[ConstraintRule, ndarray, ndarray]], len_tolerance: float, length_factor: float = 1000, short_line_cost: float = 100000, gravity_cost: float = 1000, interference_cost: float = 1000000, sideways_cost: float = 10000, bend_factor: float = 500, constraint_cost: int = 10000) float[source]#

Compute total optimization cost for a pipe path.

Evaluates the complete cost of a pipe path by summing multiple cost components: 1. Base validation: Returns high cost (1e9) if points are invalid/inactive 2. Line construction: Converts points to line segments 3. For each line segment:

  • Interference detection: Checks collisions with other pipes using bounding boxes and cylinder-to-cylinder distance calculations

  • Voxel analysis: Collects crossed voxels and their weights

  • Cost components: Bends, weighted length, short lines, sideways, gravity

  1. Constraint checking: Validates toggling constraints (clampable, etc.) on all voxels

  2. Final cost: Sums all components with their respective weights

If interferences >= 1.0, returns early with high penalty to avoid invalid solutions.

Parameters:
  • points – Array of shape (n_points, 3) with point coordinates.

  • voxel_coords – List of Index3D tuples (i, j, k) for each point.

  • solution – Solution object with ports, pipe_type, and constraints.

  • index_ports – Tuple of (input_port_index, output_port_index).

  • lines_box_matrix – Array of shape (n_lines, 2, 3) with bounding boxes of previously optimized lines for interference checking.

  • optimized_lines – List of PipeLine objects from previous solutions.

  • all_pooled_lines – List of lists of PipeLine objects in packs (currently unused).

  • hd_cadmap – High-resolution CadMap with weight tensor and pooling rules.

  • toggling_constraints – Dictionary mapping constraint names to tuples of (ConstraintRule, attribute_array, parameter_array).

  • len_tolerance – Minimum length between points to consider distinct.

  • length_factor – Weight for total weighted length cost. Defaults to 1000.

  • short_line_cost – Cost per short line segment. Defaults to 100000.

  • gravity_cost – Weight for gravity constraint violations. Defaults to 1000.

  • interference_cost – Cost per interference (very high to avoid collisions). Defaults to 1000000.

  • sideways_cost – Weight for sideways movement penalty. Defaults to 10000.

  • bend_factor – Cost per bend/turn. Defaults to 500.

  • constraint_cost – Base cost for constraint violations. Defaults to 10000.

Returns:

Total cost value (higher is worse). Returns 1e9 if path is invalid, or interference_cost * interferences if interferences >= 1.0, otherwise sum of all weighted cost components.

static constant_any_turn_cost(dot_product: float) float[source]#

Apply constant turn cost (discrete penalty).

Returns fixed cost values based on turn severity: - No penalty (0) for straight segments (dot_product >= threshold) - Small penalty (_TURN_COST) for moderate turns (between thresholds) - Large penalty (_NEGATIVE_TURN_COST) for sharp negative turns (backtracking)

This is a simple, discrete cost function that counts turns rather than measuring their severity continuously. Used in the main optimization cost computation.

Parameters:

dot_product – Dot product between consecutive segment vectors (ranges from -1 to 1, where 1 = straight, -1 = 180° turn).

Returns:

Turn cost value: - 0 for straight segments (dot_product >= _COLINEARITY_THRESHOLD) - _TURN_COST for moderate turns - _NEGATIVE_TURN_COST for sharp negative turns (backtracking)

static continuous_any_turn_cost(dot_product: float) float[source]#

Apply continuous linear turn cost function.

Computes a continuous penalty based on dot product between consecutive path segments. Uses a piecewise function: - For negative dot products (sharp turns): quadratic penalty

(1 + 10 * dot_product²) that increases rapidly

  • For positive dot products: linear penalty (1 - dot_product) that decreases as segments become more aligned

This provides a smooth cost function that gradually penalizes turns rather than using discrete thresholds.

Parameters:

dot_product – Dot product between consecutive segment vectors (ranges from -1 to 1, where 1 = straight, -1 = 180° turn).

Returns:

Turn cost value: - 1 - dot_product for positive dot products (0 for straight, increases for turns) - 1 + 10 * dot_product² for negative dot products (large penalty for backtracking)

static exponential_cost(value: float, threshold_value: float, coeff: float = 1, tolerance: float = 0.001) float[source]#

Compute exponential cost function.

Returns an exponential penalty that grows rapidly when value exceeds threshold_value. Used for soft constraints that become expensive when violated.

Parameters:
  • value – Current value to evaluate.

  • threshold_value – Threshold above which cost increases rapidly.

  • coeff – Coefficient controlling exponential growth rate. Defaults to 1.

  • tolerance – Small tolerance to avoid division issues. Defaults to 1e-3.

Returns:

Exponential cost value (0 when value <= tolerance, grows exponentially).

classmethod from_cadmap(cadmap: CadMap, hd_voxel_size: float, max_shift: float = 0.2, method: str = 'global_3d') Optimizer[source]#

Create Optimizer from CadMap with high-resolution voxelization.

Generates a high-resolution voxelization from the CadMap and creates an Optimizer instance for post-routing path refinement.

Parameters:
  • cadmap – CadMap object containing routing space and design rules.

  • hd_voxel_size – Size of voxels for high-resolution discretization (typically finer than pathfinding grid).

  • max_shift – Maximum allowed displacement during optimization. Defaults to 0.2.

  • method – Optimization method. Defaults to ‘global_3d’.

Returns:

Optimizer instance with high-resolution voxelization.

static get_last_active_voxel_on_line(hd_cadmap: CadMap, port: tuple[float, float, float], extension: tuple[float, float, float]) tuple[int, int, int][source]#

Get the last active voxel along a line from port to extension point.

Traces a line from extension to port and finds the last voxel with non-zero weight. Extends the line if necessary to find an active voxel. This is used to identify where the pipe path connects to ports in voxel space for line-of-sight checking and constraint validation.

The algorithm: 1. Converts port and extension to voxel indices 2. Gets all voxels crossed by the line segment 3. If the first voxel is inactive, extends the line backward until

an active voxel is found (or bounds are reached)

  1. Returns the last active voxel in the list

Parameters:
  • hd_cadmap – High-resolution CadMap with weight tensor.

  • port – Port coordinates as (x, y, z) tuple.

  • extension – Extension point coordinates as (x, y, z) tuple.

Returns:

Index3D tuple (i, j, k) of the last active voxel on the line.

static get_point_projection_bounds(bounds: ndarray, frame: ndarray) ndarray[source]#

Compute local coordinate bounds from global bounds using frame transformation.

Transforms global coordinate bounds to local frame coordinates by applying the inverse frame transformation. This is used to compute optimization bounds in the local coordinate system of a port, where one axis (typically x) represents distance along the port direction.

The bounds are converted to homogeneous coordinates, transformed through the inverse frame, and then the min/max values are extracted.

Parameters:
  • bounds – Array of shape (n_points, 2) with (min, max) bounds for each coordinate axis in global coordinates. Each row represents one axis (x, y, or z).

  • frame – 4x4 transformation matrix defining the local frame (typically a port frame with z-axis along port direction).

Returns:

Array of shape (2,) with (min, max) bounds in local coordinates for the first axis (typically distance along port direction).

global_3d_point_domains(points: ndarray) tuple[list[ndarray], CadMap][source]#

Build optimization domains for global 3D optimization.

Creates complete optimization domains by: 1. Building point bounds and segment voxelizations via _build_voxel_domains 2. Merging all segment voxelizations into a single voxelization 3. Creating a CadMap from the merged voxelization with design rules

The resulting CadMap contains all active voxels from all segments, allowing constraint checking across the entire path during optimization. This is more efficient than checking each segment separately.

Parameters:

points – Array of shape (n_points, 3) with 3D point coordinates representing the current pipe path.

Returns:

Tuple of (point_bounds, cadmap) where: - point_bounds: List of arrays of shape (3, 2) with (min, max) coordinate

bounds for each point in world coordinates

  • cadmap: Merged CadMap containing all segment voxelizations with design rules and weights for constraint checking

global_3d_setting(solution: Solution, pipe: Pipe) tuple[source]#

Build initial values and optimization settings for global 3D optimization.

Prepares all data structures needed for optimization: 1. Converts pipe to 3D global parameters (points, initial_values, end_frames) 2. Builds point domains and high-resolution CadMap via global_3d_point_domains 3. Sets up port extension bounds:

  • For gravity routing: uses input_length/output_length with 10% margin

  • For non-gravity: projects bounds to port local frames and ensures minimum extension lengths are satisfied

  1. Creates point-to-parameter mapping for pack constraint application

The bounds define the search space for each optimization parameter, ensuring points remain within valid regions while allowing sufficient freedom for optimization to find good solutions.

Parameters:
  • solution – Solution object with ports, pipe_type, is_gravity flag, input_length, output_length, and min_straight_length.

  • pipe – Pipe object to optimize (contains current path points).

Returns:

Tuple of (initial_values, bounds, end_frames, hd_cadmap, point_to_param_mapping) where: - initial_values: Array of optimization parameter starting values - bounds: Array of shape (n_params, 2) with (min, max) bounds for each parameter - end_frames: Tuple of (input_frame, output_frame) as 4x4 matrices - hd_cadmap: High-resolution CadMap for constraint checking - point_to_param_mapping: Dictionary mapping point coordinates to parameter indices

global_cost_3d(flatten_coords: ndarray, solution: Solution, frame_ports: tuple[ndarray, ndarray], index_ports: tuple[tuple[int, int, int], tuple[int, int, int]], lines_box_matrix: ndarray, optimized_lines: list[PipeLine], all_pooled_lines: list[list[PipeLine]], hd_cadmap: CadMap, toggling_constraints: dict[str, tuple[ConstraintRule, ndarray, ndarray]], len_tolerance: float, length_factor: float = 1000, short_line_cost: float = 100000, gravity_cost: float = 1000, interference_cost: float = 1000000, sideways_cost: float = 10000, bend_factor: float = 500, constraint_cost: int = 10000) float[source]#

Compute total cost from flattened optimization coordinates.

This is the main cost function called by scipy.optimize.dual_annealing. It converts flattened optimization parameters to 3D points, then computes the complete optimization cost by:

  1. Reconstructing 3D points from flattened coordinates

  2. Converting points to voxel indices

  3. Calling compute_total_cost with all cost components

The cost function minimizes: - Number of turns (bends) - Total weighted length - Constraint violations (short lines, gravity, etc.)

And validates that: - All points are in walkable voxels - Line segments do not cross unwalkable voxels - Minimum straight lengths are fulfilled - Minimum port extension lengths are fulfilled

Parameters:
  • flatten_coords – Flattened array of optimization parameters (missing some coordinates fixed by port constraints).

  • solution – Solution object with ports, pipe_type, and constraints.

  • frame_ports – Tuple of (input_frame, output_frame) as 4x4 matrices.

  • index_ports – Tuple of (input_port_index, output_port_index).

  • lines_box_matrix – Array of bounding boxes for interference checking.

  • optimized_lines – List of PipeLine objects from previous solutions.

  • all_pooled_lines – List of lists of PipeLine objects in packs.

  • hd_cadmap – High-resolution CadMap with weight tensor.

  • toggling_constraints – Dictionary of constraint rules to check.

  • len_tolerance – Minimum length between points to consider distinct.

  • length_factor – Weight for total length cost. Defaults to 1000.

  • short_line_cost – Cost per short line. Defaults to 100000.

  • gravity_cost – Weight for gravity violations. Defaults to 1000.

  • interference_cost – Cost per interference. Defaults to 1000000.

  • sideways_cost – Weight for sideways movement. Defaults to 10000.

  • bend_factor – Cost per bend. Defaults to 500.

  • constraint_cost – Base cost for constraint violations. Defaults to 10000.

Returns:

Total cost value (higher is worse).

static line_crossed_voxels(index: tuple[int, int, int], next_index: tuple[int, int, int], hd_cadmap: CadMap) tuple[ndarray, ndarray][source]#

Get all voxels crossed by a line segment between two voxel indices.

Uses line-of-sight algorithm to find all voxels intersected by the segment connecting two voxel indices.

Parameters:
  • index – Starting voxel index as Index3D tuple (i, j, k).

  • next_index – Ending voxel index as Index3D tuple (i, j, k).

  • hd_cadmap – High-resolution CadMap with weight tensor.

Returns:

Tuple of (crossed_voxels, crossed_weights) where: - crossed_voxels: Array of shape (n_voxels, 3) with voxel indices - crossed_weights: Array of shape (n_voxels,) with weight values

static linear_cost(value: float, value_at_one: float, tolerance: float = 0.001) float[source]#

Compute linear cost function.

Returns a linear penalty proportional to value. Simple and predictable cost function for constraints.

Parameters:
  • value – Current value to evaluate.

  • value_at_one – Value at which cost equals 1.0.

  • tolerance – Small tolerance to avoid negative costs. Defaults to 1e-3.

Returns:

Linear cost value (0 when value <= tolerance, linear growth).

static logarithmic_cost(value: float, value_at_one: float) float[source]#

Compute logarithmic cost function.

Returns a logarithmic penalty that grows slowly with value. The function is designed so that cost = 1.0 when value = value_at_one. This provides a smooth, gradually increasing penalty that is less aggressive than exponential cost but more than linear cost.

The formula ensures: - cost(0) = 0 - cost(value_at_one) = 1.0 - Growth rate decreases as value increases (logarithmic behavior)

Parameters:
  • value – Current value to evaluate (must be >= 0).

  • value_at_one – Value at which cost equals 1.0. This parameter scales the cost function.

Returns:

Logarithmic cost value (0 when value=0, 1.0 when value=value_at_one, grows logarithmically for larger values).

optimize_global_3d(solution: Solution, costs: Costs, settings: Settings, picked_path: str) tuple[OptimizedPipes, list[ndarray], dict[str, int]][source]#

Optimize a Pipe defined as a pipe index in a Solution running scipy.dual_annealing algorithm.

This is a global random optimization algorithm (meta-heuristic computed within a stochastic iteration process) that allows to search global optimum in a non-derivative function without computing variationals.

Cost function of global optimization process is:

n_bends * bend_factor + short_lines * short_line_cost + total_length * length_factor + sideways * sideway_cost

If the result seems weird (i.e. some things are not optimal) and optimization was fast, increase maxiter number. Also, if the optim_result.fun value is equal to interference_cost, it seems that optimizer did not find any solution not interfering with CAD and the user should increase maxiter parameter.

If the result is too close from the initial result from the PathFinder algorithm, increase initial_temp parameter. Inversely, if the results are too far from the original found path, decrease initial_temp value.

If the algorithm is giving a relevant result but this result is not the one that is expected, the user can adjust numerical parameters of costs and constraints along one’s expectations. For example, if a solution is not violating sideways constraints but is turning a lot, one can reduce the cost of sideways to make the algorithm reducing the amount of turns by allowing sideways.

Parameters:
  • solution – Solution containing the Pipe to optimize

  • costs – Costs object containing all cost parameters: - constraint_cost: base constraint cost - length_factor: multiplication factor for total length value - short_line_cost: cost of each short line in optimized Pipe - gravity_cost: multiplication factor of vertical bias when gravity is not satisfied - interference_cost: cost of an interference. Current cost evaluation breaks when interference is found - sideways_cost: multiplication factor for total sideway_cost - bend_factor: cost of each bend

  • settings

    Settings object containing optimization parameters: - len_tolerance: min length between two points to consider they constitute a Pipe piece. If distance

    between two points is less than len_tolerance, they are considered the same within optimization process. A value that seems quite relevant is len_tolerance = hd_voxel_size. Don’t hesitate to change it but remember to also change it in Pipe.from_optimizer method.

    • maxiter: Max number of iterations for the dual_annealing optimizer

    • restart_temp_ratio: During the annealing process, temperature is decreasing, when it reaches

    initial_temp * restart_temp_ratio, the reannealing process is triggered. Default value of the ratio is 2e-5. Range is (0, 1). - initial_temp: The initial temperature, use higher values to facilitate a wider search of the energy landscape, allowing dual_annealing to escape local minima that it is trapped in. Default value is 5230. Range is (0.01, 5.e4].

  • picked_path – identifier of the path to optimize (can be “best” or “last”)

Returns:

Returns all optimized pipes in a list[OptimizedPipe] and update the current solution. Furthermore,

it returns dead_ends voxels for current generated path and a dict counting how many times constraints are violated within the best optimized pipe.

static pipe_from_global_3d(flatten_coords: ndarray, port_frames: tuple[ndarray, ndarray], solution: Solution) ndarray[source]#

Reconstruct 3D pipe points from flattened optimization coordinates.

Converts flattened optimization parameters back to 3D world coordinates by inserting missing coordinates, transforming through port frames, and prepending/appending port positions.

Parameters:
  • flatten_coords – Flattened array of optimization parameters (missing some coordinates that are fixed by port constraints).

  • port_frames – Tuple of (input_frame, output_frame) as 4x4 transformation matrices for port coordinate systems.

  • solution – Solution object with input_port and output_port.

Returns:

Array of shape (n_points, 3) containing 3D world coordinates of all pipe points including port positions.

static points_are_not_in_voxels(voxel_coords: list[tuple[int, int, int]], hd_cadmap: CadMap) bool[source]#
static polynomial_any_turn_cost(dot_product: float) float[source]#

Compute polynomial turn cost based on dot product between consecutive segments.

Uses a piecewise polynomial function to penalize turns: - For dot_product < 0.5: Quadratic function (3.2 * dot_product² + 0.2)

that gives cost 0.2 at dot_product=0 and cost 1.0 at dot_product=0.5

  • For dot_product >= 0.5: Quartic function (_TURN_FACTOR - _TURN_FACTOR * dot_product⁴) that gives cost 1.0 at dot_product=0.5 and cost 0 at dot_product=1.0

  • For negative dot products (sharp turns): Returns large penalty (10)

This creates a smooth cost function that heavily penalizes sharp turns while allowing gradual direction changes.

Parameters:

dot_product – Dot product between consecutive segment direction vectors (ranges from -1 to 1, where 1 = straight, -1 = 180° turn).

Returns:

Turn cost value (0 for straight segments, increases for turns, large penalty for negative dot products).

static specific_angle_turn_cost(dot_product: float, zero_angle: float) float[source]#

Apply turn cost based on specific angle thresholds.

Computes a periodic cost function that penalizes turns based on angle relative to zero_angle. Returns 0 for straight segments, 2 for angles less than -zero_angle, and a sinusoidal pattern for intermediate angles.

Parameters:
  • dot_product – Dot product between consecutive segment vectors.

  • zero_angle – Reference angle in radians for cost computation.

Returns:

Turn cost value (0 for straight, higher for turns).

static total_cost_counter(flatten_coords: ndarray, frame_ports: tuple[ndarray, ndarray], solution: Solution, len_tolerance: float, hd_cadmap: CadMap, index_ports: tuple[tuple[int, int, int], tuple[int, int, int]], toggling_constraints: dict[str, tuple[ConstraintRule, ndarray, ndarray]]) list[PipeLine][source]#

Convert optimized coordinates to PipeLine objects with detailed indicators.

Reconstructs the pipe path from flattened optimization coordinates and creates PipeLine objects with complete cost and constraint information. Each line includes indicators for: - Crossed voxels and their weights - Weighted length, short line status, bend costs - Interferences (voxels with zero weight) - Sideways cost, gravity slope, deviation - Toggling constraint status (clampable, etc.)

This method is called after optimization to convert the result into a usable format with full diagnostic information.

Parameters:
  • flatten_coords – Flattened array of optimization parameters.

  • frame_ports – Tuple of (input_frame, output_frame) as 4x4 matrices.

  • solution – Solution object with ports and pipe_type.

  • len_tolerance – Minimum length between points to consider distinct.

  • hd_cadmap – High-resolution CadMap with weight tensor.

  • index_ports – Tuple of (input_port_index, output_port_index).

  • toggling_constraints – Dictionary mapping constraint names to tuples of (ConstraintRule, attribute_array, parameter_array).

Returns:

List of PipeLine objects representing the optimized path with complete indicator information for analysis and visualization.

class routing.core.optimizer.Settings(voxel_size: float, max_shift: float, len_tolerance: float | None = None, stabilization_threshold: float = 5.0, n_iterations: int = 5, max_iter: int = 500, initial_temp: float = 50000, restart_temp_ratio: float = 0.0002, convergence_window: int = 5, plot_cost_history: bool = False, name: str = '')[source]#

Bases: DessiaObject

A class representing settings configuration for simulated annealing optimization algorithm.

This class inherits from DessiaObject, and defines all parameters for the optimization process, including voxelization resolution, temperature schedule, and convergence criteria.

Parameters:
  • voxel_size – The size of voxels used for high-resolution spatial discretization.

  • max_shift – The maximum allowed displacement during one optimization iteration.

  • len_tolerance – The minimum length between points to consider them distinct. A value that seems quite relevant is len_tolerance = hd_voxel_size.Don’t hesitate to change it but remember to also change it in Pipe.from_optimizer method Defaults to None (uses voxel_size).

  • stabilization_threshold – The minimal cost difference to consider solutions stable. Optimizer.solve method stops when |cost_now - cost_before| <= stabilization_threshold. Defaults to 5.0.

  • n_iterations – The maximum number of solutions built by the optimization process. Defaults to 5.

  • max_iter – The number of iterations for the dual_annealing optimizer (scipy parameter). Defaults to 500.

  • initial_temp – The initial temperature for simulated annealing. Defaults to 50000.

  • restart_temp_ratio – The temperature restart ratio relative to initial temperature. Defaults to 2e-4.

  • convergence_window – The window size for convergence detection. Defaults to 5.

  • plot_cost_history – Flag indicating whether to plot cost history during optimization. Defaults to False.

  • name – The name identifying this parameter configuration. Defaults to ‘’.