lumix.core.variables.LXVariable¶
- class lumix.core.variables.LXVariable(name, var_type=LXVarType.CONTINUOUS, lower_bound=None, upper_bound=None, model_type=None, index_func=None, cost_func=None, _filter=None, _data=None, _session=None, _cartesian=None, _multi_cost_func=None, _join_config=None)[source]¶
Variable Family - represents multiple solver variables indexed by data models.
IMPORTANT: LXVariable is NOT a single variable, but a FAMILY/TEMPLATE that automatically expands to multiple solver variables based on data.
When you write:
production = LXVariable[Product, float]("production").from_data(products)
This creates ONE LXVariable object that represents MANY solver variables:
production[product1], production[product2], production[product3], ...
The expansion happens automatically during model building - you don’t loop manually.
Supports:
Single-model indexing: LXVariable[Product, float]
Multi-model indexing: LXVariable[Tuple[Driver, Date], int]
Join-based sparse indexing
Cartesian product indexing
Examples:
# Single model - data-driven production = ( LXVariable[Product, float]("production") .continuous() .indexed_by(lambda p: p.id) .bounds(lower=0) .cost(lambda p: p.unit_cost) .from_data(products) # Provide the data directly ) # Or with ORM production = ( LXVariable[Product, float]("production") .continuous() .from_model(Product, session=session) # Query from ORM ) # Multi-model (cartesian product) duty = ( LXVariable[Tuple[Driver, Date], int]("duty") .binary() .indexed_by_product( LXIndexDimension(Driver, lambda d: d.id).from_data(drivers), LXIndexDimension(Date, lambda dt: dt.date).from_data(dates) ) .where_multi(lambda driver, date: driver.is_active) )
- Parameters:
- __init__(name, var_type=LXVarType.CONTINUOUS, lower_bound=None, upper_bound=None, model_type=None, index_func=None, cost_func=None, _filter=None, _data=None, _session=None, _cartesian=None, _multi_cost_func=None, _join_config=None)¶
- Parameters:
- Return type:
None
Methods
__init__(name[, var_type, lower_bound, ...])binary()Set as binary variable.
bounds([lower, upper])Set variable bounds with full type checking.
Set as continuous variable.
cost(func)Define objective coefficient from model.
cost_multi(func)Define cost function for multi-indexed variables.
from_data(data)Provide data instances directly (for non-ORM usage).
from_model(model[, session])Bind to ORM model type for automatic querying.
Get the data instances for this variable family.
indexed_by(func)Define indexing function with full type inference.
indexed_by_join(primary, related, join_func)Index by a relationship/join between models.
indexed_by_product(dim1, dim2, *extra_dims)Index by cartesian product of multiple models.
integer()Set as integer variable.
where(predicate)Filter which model instances to include.
where_multi(predicate)Filter multi-indexed variable combinations.
Attributes
- __deepcopy__(memo)[source]¶
Custom deepcopy that detaches ORM sessions and handles lambda closures.
This method enables what-if analysis on variables using ORM data sources by: 1. Materializing lazy-loaded ORM data before copying 2. Detaching ORM objects from database sessions 3. Safely copying lambda functions (index_func, cost_func, filters, etc.) 4. Deep copying cartesian products and join configurations
- Parameters:
memo – Dictionary for tracking circular references during deepcopy
- Returns:
Deep copy of this variable with all ORM dependencies resolved
Note
After copying, the new variable will have _session=None and all data stored in _data as detached objects safe for pickling.
- __getstate__()[source]¶
Support for pickle protocol - detach ORM sessions before pickling.
- Returns:
Dictionary of instance state safe for pickling
- __setstate__(state)[source]¶
Support for pickle protocol - restore from pickled state.
- Parameters:
state – Dictionary of instance state from pickling
- from_data(data)[source]¶
Provide data instances directly (for non-ORM usage).
- Parameters:
- Return type:
Self- Returns:
Self for chaining
Example
production = Variable[Product, float](“production”).from_data(products)
- from_model(model, session=None)[source]¶
Bind to ORM model type for automatic querying.
- Parameters:
- Return type:
Self- Returns:
Self for chaining
Example
production = Variable[Product, float](“production”).from_model(Product, session)
- get_instances()[source]¶
Get the data instances for this variable family.
- Return type:
- Returns:
List of model instances
- Raises:
ValueError – If no data source configured
- indexed_by(func)[source]¶
Define indexing function with full type inference.
- Parameters:
func (
Callable[[TypeVar(TModel)],TypeVar(TIndex)]) – Function to extract index from model instance- Return type:
Self- Returns:
Self for chaining
Examples
.indexed_by(lambda product: product.id) .indexed_by(lambda route: (route.origin, route.destination))
- indexed_by_product(dim1, dim2, *extra_dims)[source]¶
Index by cartesian product of multiple models. Creates variables for every valid combination.
- Parameters:
dim1 (
LXIndexDimension[TypeVar(TModel1)]) – First dimensiondim2 (
LXIndexDimension[TypeVar(TModel2)]) – Second dimension*extra_dims (
LXIndexDimension) – Additional dimensions for 3D+ indexing
- Return type:
Self- Returns:
Self for chaining
Example:
duty = LXVariable[Tuple[Driver, Date], int]("duty") .indexed_by_product( LXIndexDimension(Driver, lambda d: d.id) .where(lambda d: d.is_active), LXIndexDimension(Date, lambda dt: dt.date) .where(lambda dt: dt >= today) )
- indexed_by_join(primary, related, join_func, key_func=None)[source]¶
Index by a relationship/join between models. Only creates variables where relationship exists (sparse).
- Parameters:
- Return type:
Self- Returns:
Self for chaining
Example:
# Only create variables for valid driver-route assignments assignment = LXVariable[Tuple[Driver, Route], int]("assign") .indexed_by_join( Driver, Route, join_func=lambda d: d.qualified_routes, # ORM relationship key_func=lambda d, r: (d.id, r.id) )
- cost(func)[source]¶
Define objective coefficient from model.
- Parameters:
func (
Callable[[TypeVar(TModel)],float]) – Function to calculate cost from model- Return type:
Self- Returns:
Self for chaining
Example
.cost(lambda product: product.unit_cost)
- cost_multi(func)[source]¶
Define cost function for multi-indexed variables. Function receives all index models as arguments.
- Parameters:
func (
Callable[...,float]) – Function receiving all dimension models- Return type:
Self- Returns:
Self for chaining
Example
.cost_multi(lambda driver, date: driver.daily_rate * date.overtime_multiplier)
- where(predicate)[source]¶
Filter which model instances to include.
- Parameters:
predicate (
Callable[[TypeVar(TModel)],bool]) – Filter function- Return type:
Self- Returns:
Self for chaining
Example
.where(lambda p: p.is_active and p.stock > 0)
- where_multi(predicate)[source]¶
Filter multi-indexed variable combinations.
- Parameters:
predicate (
Callable[...,bool]) – Filter function receiving all dimension models- Return type:
Self- Returns:
Self for chaining
Example:
.where_multi(lambda driver, date, shift: driver.can_work_shift(shift) and date.weekday() not in driver.days_off )
- __init__(name, var_type=LXVarType.CONTINUOUS, lower_bound=None, upper_bound=None, model_type=None, index_func=None, cost_func=None, _filter=None, _data=None, _session=None, _cartesian=None, _multi_cost_func=None, _join_config=None)¶
- Parameters:
- Return type:
None