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.

continuous()

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_instances()

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

name: str
var_type: LXVarType = 'continuous'
lower_bound: Optional[TypeVar(TValue, int, float)] = None
upper_bound: Optional[TypeVar(TValue, int, float)] = None
model_type: Optional[Type[TypeVar(TModel)]] = None
index_func: Optional[Callable[[TypeVar(TModel)], TypeVar(TIndex)]] = None
cost_func: Optional[Callable[[TypeVar(TModel)], float]] = None
__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

continuous()[source]

Set as continuous variable. Returns self for chaining.

Return type:

Self

integer()[source]

Set as integer variable. Returns self for chaining.

Return type:

Self

binary()[source]

Set as binary variable. Returns self for chaining.

Return type:

Self

bounds(lower=None, upper=None)[source]

Set variable bounds with full type checking.

Parameters:
Return type:

Self

Returns:

Self for chaining

from_data(data)[source]

Provide data instances directly (for non-ORM usage).

Parameters:

data (List[TypeVar(TModel)]) – List of model instances

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:

List[TypeVar(TModel)]

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:
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