Utilities¶
Helper functions and data structures used internally by solvers, also available for custom implementations.
Overview¶
| Category | Contents |
|---|---|
| Data Structures | FenwickTree, UnionFind - efficient structures for algorithms |
| Validation | Input checking functions with clear error messages |
| Helpers | Debugging, evaluation tracking, progress utilities |
Quick Examples¶
from solvor.utils import FenwickTree, UnionFind, debug
# Fenwick tree for prefix sums
ft = FenwickTree([1, 2, 3, 4, 5])
ft.prefix(2) # 6 (sum of indices 0, 1, 2)
ft.update(1, 10) # add 10 to index 1
ft.range_sum(1, 3) # sum of indices 1, 2, 3
# Union-Find for connected components
uf = UnionFind(10)
uf.union(0, 1)
uf.union(1, 2)
uf.connected(0, 2) # True
uf.component_count # 8
# Debug output (only prints when DEBUG=1)
debug("solving iteration", i)
Validation Functions¶
Used internally by solvers to validate inputs before solving. Provides clear error messages for common mistakes.
from solvor.utils import check_matrix_dims, check_positive, check_bounds
# Validate LP dimensions
check_matrix_dims(c, A, b) # Raises if dimensions mismatch
# Validate parameter ranges
check_positive(n_nodes, name="n_nodes")
check_bounds(bounds) # Validates (low, high) pairs
| Function | Purpose |
|---|---|
check_matrix_dims(c, A, b) |
LP/MILP dimension consistency |
check_positive(val, name) |
val > 0 |
check_non_negative(val, name) |
val >= 0 |
check_in_range(val, lo, hi, name) |
lo <= val <= hi |
check_bounds(bounds) |
Valid (low, high) pairs |
check_edge_nodes(edges, n_nodes) |
Edge endpoints valid |
check_sequence_lengths(seqs, names) |
Parallel sequences same length |
warn_large_coefficients(A) |
Warns if max > 1e10 |
Data Structures¶
solvor.utils.data_structures
¶
Data structures for optimization algorithms.
Efficient data structures used internally by solvers. Also available for custom implementations requiring these classic structures.
from solvor.utils import UnionFind, FenwickTree
uf = UnionFind(10) # Disjoint sets for cycle detection
ft = FenwickTree([1,2,3]) # Prefix sums with point updates
FenwickTree
¶
Fenwick Tree (Binary Indexed Tree) for prefix sums with point updates.
Supports O(log n) prefix sum queries and point updates. Useful for cumulative frequency tables, range sum queries, and inversion counting.
ft = FenwickTree([1, 2, 3, 4, 5])
ft.prefix(2) # 6 (sum of indices 0, 1, 2)
ft.update(1, 10) # add 10 to index 1
ft.prefix(2) # 16
ft.range_sum(1, 3) # sum of indices 1, 2, 3
Source code in solvor/utils/data_structures.py
__init__(values)
¶
Initialize from values list or size (zeros).
Source code in solvor/utils/data_structures.py
__len__()
¶
prefix(i)
¶
range_sum(left, right)
¶
Return sum of elements from left to right (inclusive).
UnionFind
¶
Union-Find (Disjoint Set Union) data structure.
Efficiently tracks connected components with near O(1) operations via path compression and union by rank.
uf = UnionFind(10)
uf.union(0, 1)
uf.union(1, 2)
uf.connected(0, 2) # True
uf.component_count # 8 (started with 10, merged 3 into 1)
Source code in solvor/utils/data_structures.py
component_count
property
¶
Number of disjoint components.
__init__(n)
¶
__len__()
¶
component_sizes()
¶
Return list of component sizes.
Source code in solvor/utils/data_structures.py
connected(x, y)
¶
find(x)
¶
get_components()
¶
Return list of sets, each containing elements of one component.
Source code in solvor/utils/data_structures.py
union(x, y)
¶
Merge components containing x and y. Returns True if merged.
Source code in solvor/utils/data_structures.py
Helpers¶
solvor.utils.helpers
¶
Helper functions for optimization tasks, debugging, and evaluation.
Small, stable helpers used across solvers for common operations like objective function wrapping, progress reporting, and solution manipulation.
from solvor.utils import debug, Evaluator, report_progress
from solvor.utils import random_permutation, pairwise_swap_neighbors
Evaluator
¶
Wraps objective function to track evaluations and handle minimize/maximize.
The internal objective values are sign-adjusted so that minimization always
means finding smaller values. Use to_user() to convert back for reporting.
Example
evaluator = Evaluator(objective_fn, minimize=True) obj = evaluator(solution) # Internal (signed) value user_obj = evaluator.to_user(obj) # User-facing value print(f"Evaluations: {evaluator.evals}")
Source code in solvor/utils/helpers.py
__call__(sol)
¶
assignment_cost(matrix, assignment)
¶
Compute total cost of an assignment.
Source code in solvor/utils/helpers.py
debug(*args, **kwargs)
¶
default_progress(name='', *, interval=100, time_limit=None)
¶
Create a default progress callback with formatted output.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Solver name prefix for output (optional) |
''
|
interval
|
int
|
Print every N iterations (default 100) |
100
|
time_limit
|
float | None
|
Stop after this many seconds (optional) |
None
|
Example
result = solver(func, bounds, on_progress=default_progress("PSO"))
Output: PSO iter=100 obj=1.234 best=0.567 time=0.42s¶
Source code in solvor/utils/helpers.py
is_feasible(A, b, x, tol=1e-09)
¶
Check if x satisfies A @ x <= b within tolerance.
Source code in solvor/utils/helpers.py
pairwise_swap_neighbors(perm)
¶
Generate all neighbors by swapping pairs of elements.
Source code in solvor/utils/helpers.py
random_permutation(n, seed=None)
¶
Generate a random permutation of [0, 1, ..., n-1].
Source code in solvor/utils/helpers.py
reconstruct_path(parent, current)
¶
Reconstruct path from parent dict, used by pathfinding algorithms.
Source code in solvor/utils/helpers.py
report_progress(on_progress, progress_interval, iteration, current_obj, best_obj, evals)
¶
Report progress if interval reached. Returns True if callback requested stop.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
on_progress
|
ProgressCallback | None
|
Progress callback or None |
required |
progress_interval
|
int
|
Report every N iterations (0 = disabled) |
required |
iteration
|
int
|
Current iteration number |
required |
current_obj
|
float
|
Current objective value (user-facing) |
required |
best_obj
|
float
|
Best objective found so far (user-facing) |
required |
evals
|
int
|
Number of objective evaluations |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if callback returned True (stop requested), False otherwise. |
Example
if report_progress(on_progress, progress_interval, iteration, evaluator.to_user(obj), evaluator.to_user(best), evaluator.evals): return Result(solution, evaluator.to_user(best), iteration, evaluator.evals, Status.FEASIBLE)
Source code in solvor/utils/helpers.py
timed_progress(callback)
¶
Wrap a callback to receive elapsed time as second argument.
Use this to add time tracking without modifying solver code.
Example
def my_callback(progress, elapsed): print(f"iter {progress.iteration}, time {elapsed:.2f}s") return elapsed > 60 # Stop after 60 seconds
result = solver(func, bounds, on_progress=timed_progress(my_callback))
Source code in solvor/utils/helpers.py
Validation Reference¶
solvor.utils.validate
¶
Input validation utilities for solvers.
Common validation functions to ensure inputs are well-formed before solving. Provides clear error messages for dimension mismatches, invalid values, and other common mistakes.
from solvor.utils import check_matrix_dims, check_bounds, check_positive
Used internally by solvers but also available for custom validation.
check_bounds(bounds, *, name='bounds')
¶
Validate bounds are (low, high) pairs with low <= high. Returns dimension.
Source code in solvor/utils/validate.py
check_edge_nodes(edges, n_nodes, *, name='edges')
¶
Check that edge endpoints are valid node indices.
Source code in solvor/utils/validate.py
check_graph_nodes(graph, *nodes)
¶
Check that nodes exist in graph.
check_in_range(value, low, high, *, name='value', inclusive=True)
¶
Check that value is within [low, high] or (low, high).
Source code in solvor/utils/validate.py
check_integers_valid(integers, n_vars, *, name='integers')
¶
Check that integer variable indices are valid and unique.
Source code in solvor/utils/validate.py
check_matrix_dims(c, A, b, *, name_c='c', name_A='A', name_b='b')
¶
Validate dimensions of LP/MILP inputs: c (n,), A (m, n), b (m,).
Source code in solvor/utils/validate.py
check_non_negative(value, *, name='value')
¶
check_positive(value, *, name='value')
¶
check_sequence_lengths(*seqs, expected=None)
¶
Check that all sequences have the same length. Returns the length.
Source code in solvor/utils/validate.py
warn_large_coefficients(A, threshold=10000000000.0, *, name='A')
¶
Warn if matrix has very large coefficients that may cause numerical issues.