Data
Data pipeline components for bilevel hub location datasets.
Generators create synthetic clients and budgets, processors rank and index clients, and calculators compute Lagrange multipliers.
BilevelClientGenerator(clients_per_route, random_count=False, min_budget_factor=1.2, max_budget_factor=1.8, possible_weights=None, seed=42)
¶
Bases: EntityProcessor
Generate synthetic bilevel clients on each route.
For every route \((i,j)\) with \(i \neq j\), generates a random number of
clients, each with a weight \(a_{ij}^z\) (sampled from possible_weights)
and a budget \(b_{ij}^z = c_{ij} \cdot a_{ij}^z \cdot \text{factor}\),
where the factor is uniformly sampled from
\([\text{min\_budget\_factor}, \text{max\_budget\_factor}]\).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
clients_per_route
|
int
|
Number of clients per route (or max if
|
required |
random_count
|
bool
|
If |
False
|
min_budget_factor
|
float
|
Minimum multiplier for budget generation. |
1.2
|
max_budget_factor
|
float
|
Maximum multiplier for budget generation. |
1.8
|
possible_weights
|
List[float]
|
List of possible client weights to sample from. |
None
|
seed
|
int
|
Random seed for reproducibility. |
42
|
Source code in src/oracle_paper/data/generator/bilevel_client_generator.py
LagrangeCalculator()
¶
Bases: TrackableProcessor
Compute Lagrange multipliers \(\lambda_{ij}^z\) for the PPC-HLP model.
For each route \((i,j)\), the calculator sorts clients by their budget-to-weight ratio and computes the Lagrange multiplier sequence using the recursive formula:
The result is stored in
BilevelDataCol.LAGRANGE.
Uses the track_metric
decorator to measure computation time automatically.
Source code in src/oracle_paper/data/calculator/base.py
calculate_lagrange(dict_a, dict_b)
staticmethod
¶
Compute the Lagrange multiplier sequence for one route's clients.
$\(\lambda_k = b_k + \sum_{t=0}^{k-1} a_t \cdot \Delta_k\)$ where \(\Delta_k = b_k/a_k - b_{k-1}/a_{k-1}\).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dict_a
|
dict[int, float]
|
Client weights \(\{z: a_{ij}^z\}\) sorted by \(z\). |
required |
dict_b
|
dict[int, float]
|
Client budgets \(\{z: b_{ij}^z\}\) sorted by \(z\). |
required |
Returns:
| Type | Description |
|---|---|
dict[int, float]
|
Mapping \(\{z: \lambda_{ij}^z\}\) of Lagrange multipliers. |
Source code in src/oracle_paper/data/calculator/lagrange.py
process(dataset)
¶
Compute Lagrange multipliers and add them to the dataset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataset
|
MultiEntityDataset
|
Dataset with client weights and budgets (modified in-place). |
required |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If required entities are missing. |
Source code in src/oracle_paper/data/calculator/lagrange.py
LinearClientRanker
¶
Bases: EntityProcessor
Sort and index clients by budget-to-weight ratio on each route.
For each route \((i,j)\), clients are sorted in descending order of
\(b_{ij}^z / a_{ij}^z\) and assigned zero-based indices \(z = 0, 1, 2,
\dots\). This ranking is essential for the
[PrecendenceConstraint][oracle_paper.constraints.precedence_constraint.PrecendenceConstraint]
and all Lagrange multiplier calculations.
Replaces the raw client entities (keyed by original client ID) with re-indexed entities keyed by \((i,j,z)\) tuples.
process(dataset)
¶
Rank clients and re-index entities by \((i,j,z)\).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataset
|
MultiEntityDataset
|
Dataset with client routes, budgets, and weights (modified in-place). |
required |
Source code in src/oracle_paper/data/processor/client_ranker.py
RecursiveLagrangeCalculator()
¶
Bases: TrackableProcessor
Compute recursive Lagrange multipliers for the PC-HLP model.
Groups clients on the same route \((i,j)\) that have already been
sorted by
LinearClientRanker,
then merges adjacent client segments where the Lagrange-to-weight
ratio is non-increasing. The merged groups form aggregated clients
indexed by \((i,j,z)\) where \(z\) is now a group index.
Adds four entities to the dataset:
Source code in src/oracle_paper/data/calculator/base.py
process(dataset)
¶
Compute recursive Lagrange multipliers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataset
|
MultiEntityDataset
|
Dataset with Lagrange multipliers, weights, budgets, and client keys (modified in-place). |
required |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If required entities are missing. |
Source code in src/oracle_paper/data/calculator/recursive_lagrange.py
sort_lagrange_multipliers_dict(dict_lagrange, dict_keys, dict_a)
staticmethod
¶
Merge adjacent clients where Lagrange/weight ratio is non-increasing.
Uses a stack-based algorithm: iterates over sorted clients and merges when \(\lambda_k/a_k > \lambda_{k+1}/a_{k+1}\).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dict_lagrange
|
dict[int, float]
|
\(\{z: \lambda_{ij}^z\}\). |
required |
dict_keys
|
dict[int, int]
|
\(\{z: \text{original client IDs}\}\). |
required |
dict_a
|
dict[int, float]
|
\(\{z: a_{ij}^z\}\). |
required |
Returns:
| Type | Description |
|---|---|
dict[int, float]
|
|
dict[int, list[int]]
|
and grouped client ID lists. |