Absolute Value Terms¶
The LXAbsoluteTerm represents absolute value operations x, commonly
used for minimizing deviations and handling penalties.
Overview¶
Absolute value is a fundamental nonlinear operation in optimization:
Common Use Cases:
Minimizing deviations from targets
Robust optimization (L1 norm)
Penalty terms in objective functions
Total variation minimization
Linearization Method¶
LumiX automatically linearizes x by introducing an auxiliary variable z:
Result: z equals x in the optimal solution.
Key Properties:
Adds 1 auxiliary variable per absolute value term
Adds 2 linear constraints per term
Works for both continuous and integer variables
No configuration required
Basic Usage¶
Simple Deviation Minimization¶
Minimize the absolute deviation from a target:
from lumix import LXModel, LXVariable, LXLinearExpression
from lumix.nonlinear import LXAbsoluteTerm
# Define variable
production = (
LXVariable[Product, float]("production")
.continuous()
.bounds(lower=0, upper=1000)
.from_data(products)
)
# Create absolute deviation term
# Minimize |production - target|
abs_deviation = LXAbsoluteTerm(
var=production,
coefficient=1.0
)
# Add to objective (linearization happens automatically)
model = LXModel("minimize_deviation")
# ... build expression and minimize ...
Weighted Penalty¶
Apply different weights to different deviations:
# Heavily penalize deviations
heavy_penalty = LXAbsoluteTerm(
var=critical_var,
coefficient=100.0 # 100x penalty
)
# Light penalty
light_penalty = LXAbsoluteTerm(
var=flexible_var,
coefficient=1.0
)
Complete Examples¶
Example 1: Production Planning with Target Tracking¶
Minimize deviation from production targets:
from dataclasses import dataclass
from typing import List
from lumix import LXModel, LXVariable, LXConstraint, LXLinearExpression
from lumix.nonlinear import LXAbsoluteTerm
@dataclass
class Product:
id: str
target: float
max_capacity: float
products: List[Product] = [
Product("A", target=100, max_capacity=150),
Product("B", target=200, max_capacity=250),
Product("C", target=150, max_capacity=200),
]
# Decision variable: actual production
production = (
LXVariable[Product, float]("production")
.continuous()
.bounds(lower=0)
.indexed_by(lambda p: p.id)
.from_data(products)
)
# Capacity constraints
capacity = (
LXConstraint[Product]("capacity")
.expression(
LXLinearExpression().add_term(production, 1.0)
)
.le()
.rhs(lambda p: p.max_capacity)
.from_data(products)
.indexed_by(lambda p: p.id)
)
# Minimize absolute deviation from targets
# Note: This is conceptual - actual integration with objective needs
# to be done through the expression system
deviations = [
LXAbsoluteTerm(var=production, coefficient=1.0)
for p in products
]
model = (
LXModel("production_targets")
.add_variable(production)
.add_constraint(capacity)
)
# Add deviations to objective through linearization
Example 2: Portfolio Rebalancing¶
Minimize transaction costs (absolute changes):
@dataclass
class Asset:
id: str
current_holding: float
target_holding: float
assets = [...] # Your portfolio
# Decision: new holdings
holdings = (
LXVariable[Asset, float]("holdings")
.continuous()
.bounds(lower=0)
.from_data(assets)
)
# Minimize |holdings - current| (transaction costs)
transaction_costs = [
LXAbsoluteTerm(var=holdings, coefficient=0.01) # 1% transaction cost
for asset in assets
]
# Total value constraint
total_value = (
LXConstraint("total_value")
.expression(
LXLinearExpression().add_term(holdings, 1.0)
)
.eq()
.rhs(1_000_000) # Total portfolio value
)
model = LXModel("rebalance")
# ... complete model ...
Example 3: Robust Regression (L1 Norm)¶
Fit a line minimizing L1 norm of residuals:
@dataclass
class DataPoint:
id: int
x: float
y: float
data_points = [...] # Your data
# Decision variables: slope and intercept
slope = LXVariable("slope").continuous().bounds(-10, 10)
intercept = LXVariable("intercept").continuous().bounds(-100, 100)
# For each point, minimize |y - (slope*x + intercept)|
# This requires computing the residual first
# (simplified example - actual implementation needs expression building)
residuals = [
LXAbsoluteTerm(var=..., coefficient=1.0) # residual variable
for point in data_points
]
model = LXModel("robust_regression")
# ... complete model ...
Advanced Patterns¶
Multiple Absolute Terms in Objective¶
Sum multiple absolute value terms:
# Minimize sum of absolute deviations
deviation_terms = [
LXAbsoluteTerm(var=production, coefficient=weight)
for production, weight in zip(prod_vars, weights)
]
# Build objective expression combining all terms
# (requires integration with expression system)
Asymmetric Penalties¶
Penalize positive and negative deviations differently:
# Use two separate terms with one-sided constraints
# Positive deviation: max(0, x - target)
pos_dev = LXVariable[Product, float]("pos_dev").continuous().bounds(0)
# Add constraint: pos_dev >= production - target
# Negative deviation: max(0, target - x)
neg_dev = LXVariable[Product, float]("neg_dev").continuous().bounds(0)
# Add constraint: neg_dev >= target - production
# Different penalties
pos_penalty = LXAbsoluteTerm(var=pos_dev, coefficient=2.0) # Over-production
neg_penalty = LXAbsoluteTerm(var=neg_dev, coefficient=5.0) # Under-production
Integration with Expressions¶
Absolute value of linear expression:
# Want: |2*x + 3*y - 10|
# Step 1: Create auxiliary variable for the expression value
expr_value = LXVariable("expr_value").continuous()
# Step 2: Constrain expr_value = 2*x + 3*y - 10
expr_constraint = LXConstraint("expr_def").expression(
LXLinearExpression()
.add_term(x, 2.0)
.add_term(y, 3.0)
.add_term(expr_value, -1.0)
).eq().rhs(10.0)
# Step 3: Take absolute value of expr_value
abs_expr = LXAbsoluteTerm(var=expr_value, coefficient=1.0)
Performance Considerations¶
Computational Cost¶
Variables Added: 1 auxiliary variable per term
Constraints Added: 2 constraints per term
Solve Time: Minimal overhead, standard LP relaxation
Recommendation: Absolute value terms are efficient and well-supported by all solvers.
Model Size¶
For models with many absolute value terms:
# 1000 products → 1000 auxiliary vars + 2000 constraints
deviations = [
LXAbsoluteTerm(var=production, coefficient=1.0)
for _ in range(1000)
]
# This is still efficient for modern solvers
Alternative: Eliminate terms that are not needed:
# Only penalize significant deviations
deviations = [
LXAbsoluteTerm(var=prod, coefficient=weight)
for prod, weight in zip(productions, weights)
if weight > threshold # Skip small penalties
]
Common Patterns¶
Minimize Total Absolute Deviation¶
total_deviation = sum(
LXAbsoluteTerm(var=var, coefficient=1.0)
for var in decision_vars
)
Weighted Deviations¶
weighted_deviation = sum(
LXAbsoluteTerm(var=var, coefficient=weight)
for var, weight in zip(decision_vars, weights)
)
Robust Objective (L1 vs L2)¶
# L1 norm (absolute value) - robust to outliers
l1_objective = sum(
LXAbsoluteTerm(var=residual, coefficient=1.0)
for residual in residuals
)
# L2 norm (squared) - sensitive to outliers
# Use LXQuadraticExpression for L2
See Also¶
LXAbsoluteTerm- API referenceExpressions Guide - Building expressions
Linearization Concepts - Linearization details
Next Steps¶
Min/Max Operations - Min/max operations
Bilinear Products - Products of variables
Indicator Constraints - Conditional constraints