Source code for lumix.solution.mapping
"""Solution mapping utilities for LumiX."""
from typing import Any, Dict, Generic, List, TypeVar
from ..core.variables import LXVariable
TModel = TypeVar("TModel")
[docs]
class LXSolutionMapper(Generic[TModel]):
"""
Maps solution values back to ORM model instances.
Handles:
- Single-indexed variables
- Multi-indexed variables
- Join-based variables
"""
[docs]
def map_variable_to_models(
self,
var: LXVariable[TModel, Any],
solution_values: Dict[Any, float],
model_instances: List[TModel],
) -> Dict[TModel, float]:
"""
Map variable values to model instances.
Args:
var: LXVariable definition
solution_values: Solution values (index -> value)
model_instances: Model instances used in optimization
Returns:
Dictionary mapping model instances to values
"""
if var.index_func is None:
return {}
result = {}
for instance in model_instances:
key = var.index_func(instance)
if key in solution_values:
result[instance] = solution_values[key]
return result
[docs]
def map_multi_indexed_variable(
self,
var: LXVariable,
solution_values: Dict[tuple, float],
) -> Dict[tuple, float]:
"""
Map multi-indexed variable values to model instance tuples.
Args:
var: LXVariable definition
solution_values: Solution values ((key1, key2, ...) -> value)
Returns:
Dictionary mapping model instance tuples to values
"""
# Check if variable has cartesian product
if var._cartesian is None or not var._cartesian.dimensions:
return {}
# Retrieve instances automatically from each dimension
model_instances_by_dim = [dim.get_instances() for dim in var._cartesian.dimensions]
# Build reverse mappings for each dimension: key -> model_instance
reverse_maps = []
for dim, instances in zip(var._cartesian.dimensions, model_instances_by_dim):
# Create mapping using the dimension's key function
key_to_instance = {dim.key_func(inst): inst for inst in instances}
reverse_maps.append(key_to_instance)
# Transform solution values from key tuples to instance tuples
result = {}
for key_tuple, value in solution_values.items():
try:
# Map each key to its corresponding model instance
instance_tuple = tuple(
reverse_maps[i][key] for i, key in enumerate(key_tuple)
)
result[instance_tuple] = value
except (KeyError, IndexError):
# Skip entries where mapping fails (data inconsistency)
continue
return result
__all__ = ["LXSolutionMapper"]