A type-safe, IDE-friendly wrapper for optimization solvers with automatic data-driven modeling
Project description
LumiX
A modern, type-safe wrapper for optimization solvers with automatic data-driven modeling
LumiX makes mathematical programming accessible, maintainable, and enjoyable by providing a unified, type-safe interface to multiple optimization solvers.
โจ Key Features
- ๐ฏ Type-Safe & IDE-Friendly โ Full type hints and autocomplete support for a superior development experience
- ๐ Multi-Solver Support โ Seamlessly switch between OR-Tools, Gurobi, CPLEX, GLPK, and CP-SAT
- ๐ Data-Driven Modeling โ Build models directly from your data with automatic indexing and mapping
- ๐ Automatic Linearization โ Automatically linearize non-linear constraints (bilinear, absolute value, piecewise)
- ๐ Advanced Analysis โ Built-in sensitivity analysis, scenario analysis, and what-if analysis tools
- ๐ฏ Goal Programming โ Native support for multi-objective optimization with priorities and weights
- โก ORM Integration โ Map solutions directly to your ORM models for seamless data flow
๐ Quick Start
Installation
# Install core library
pip install lumix
# Install with a solver (e.g., OR-Tools - free and open-source)
pip install lumix[ortools]
# Or install with multiple solvers
pip install lumix[ortools,gurobi,cplex]
Simple Example
from dataclasses import dataclass
from lumix import (
LXModel,
LXVariable,
LXConstraint,
LXLinearExpression,
LXOptimizer,
)
# Define your data
@dataclass
class Product:
id: str
name: str
profit: float
resource_usage: float
products = [
Product("A", "Product A", profit=30, resource_usage=2),
Product("B", "Product B", profit=40, resource_usage=3),
]
# Define decision variables
production = (
LXVariable[Product, float]("production")
.continuous()
.bounds(lower=0)
.indexed_by(lambda p: p.id)
.from_data(products)
)
# Build the model
model = (
LXModel("production_plan")
.add_variable(production)
.maximize(
LXLinearExpression()
.add_term(production, lambda p: p.profit)
)
)
# Add constraints
model.add_constraint(
LXConstraint("resource_limit")
.expression(
LXLinearExpression()
.add_term(production, lambda p: p.resource_usage)
)
.le()
.rhs(100) # Resource capacity
)
# Solve
optimizer = LXOptimizer().use_solver("ortools")
solution = optimizer.solve(model)
# Access results
if solution.is_optimal():
print(f"Optimal profit: ${solution.objective_value:,.2f}")
for product in products:
qty = solution.variables["production"][product.id]
print(f"Produce {qty:.2f} units of {product.name}")
๐ง Supported Solvers
LumiX provides a unified interface to multiple solvers:
| Solver | Linear | Integer | Quadratic | Advanced Features | License | Best For |
|---|---|---|---|---|---|---|
| OR-Tools | โ | โ | โ | SOS, Indicator | Apache 2.0 (Free) | General LP/MIP, Learning |
| Gurobi | โ | โ | โ | SOCP, PWL, Callbacks | Commercial/Academic | Large-scale, Production |
| CPLEX | โ | โ | โ | SOCP, PWL, Callbacks | Commercial/Academic | Large-scale, Production |
| GLPK | โ | โ | โ | Basic | GPL (Free) | Small problems, Teaching |
| CP-SAT | โ | โ | โ | Constraint Programming | Apache 2.0 (Free) | Scheduling, Assignment |
Switching Solvers
# Just change one line to switch solvers
optimizer = LXOptimizer().use_solver("ortools") # Free
optimizer = LXOptimizer().use_solver("gurobi") # Requires license
optimizer = LXOptimizer().use_solver("cplex") # Requires license
optimizer = LXOptimizer().use_solver("glpk") # Free
optimizer = LXOptimizer().use_solver("cpsat") # Free
๐ Core Capabilities
Variables with Automatic Indexing
# Single-dimension indexing
production = (
LXVariable[Product, float]("production")
.continuous()
.indexed_by(lambda p: p.id)
.from_data(products)
)
# Multi-dimension indexing
from lumix import LXCartesianProduct
assignment = (
LXVariable[tuple[Driver, Date, Shift], int]("assignment")
.binary()
.indexed_by(lambda t: (t[0].id, t[1].id, t[2].id))
.from_data(LXCartesianProduct(drivers, dates, shifts))
)
Type-Safe Expressions
# Linear expressions with automatic coefficient extraction
profit_expr = (
LXLinearExpression()
.add_term(production, lambda p: p.profit)
)
# Quadratic expressions
quadratic_expr = (
LXQuadraticExpression()
.add_quadratic_term(x, y, coefficient=0.5)
)
Automatic Linearization
LumiX can automatically linearize non-linear terms:
from lumix import LXBilinearTerm, LXAbsoluteTerm, LXPiecewiseLinearTerm
# Bilinear products (x * y)
bilinear = LXBilinearTerm(x, y, bounds_x=(0, 10), bounds_y=(0, 5))
# Absolute values |x|
absolute = LXAbsoluteTerm(x)
# Piecewise-linear functions
piecewise = LXPiecewiseLinearTerm(
variable=x,
breakpoints=[0, 10, 20, 30],
slopes=[1.0, 0.5, 0.2]
)
Advanced Analysis
from lumix import (
LXSensitivityAnalyzer,
LXScenarioAnalyzer,
LXWhatIfAnalyzer,
)
# Sensitivity analysis
sens = LXSensitivityAnalyzer(model, solution)
report = sens.generate_report()
print(report)
# Scenario analysis
scenario_analyzer = LXScenarioAnalyzer(model, optimizer)
scenario_analyzer.add_scenario("base", {})
scenario_analyzer.add_scenario("high_demand", {"demand": 150})
results = scenario_analyzer.solve_all()
# What-if analysis
whatif = LXWhatIfAnalyzer(model, optimizer)
result = whatif.increase_constraint_rhs("capacity", by=10)
print(f"Impact: ${result.delta_objective:,.2f}")
Goal Programming
from lumix import (
LXGoal,
LXGoalMode,
solve_goal_programming,
)
# Define multiple goals with priorities
goals = [
LXGoal(
name="profit",
target=1000,
priority=1,
weight=1.0,
is_minimization=False,
),
LXGoal(
name="quality",
target=95,
priority=2,
weight=0.8,
),
]
# Solve with goal programming
solution = solve_goal_programming(
model,
goals,
mode=LXGoalMode.SEQUENTIAL,
solver="gurobi",
)
๐ Documentation
- Installation Guide โ Install LumiX and solvers
- Quick Start โ Build your first model
- Solver Guide โ Choose the right solver
- Examples โ 11 comprehensive examples
Examples
The repository includes 11 examples demonstrating various features:
- Production Planning โ Single-model indexing, data-driven modeling
- Driver Scheduling โ Multi-dimensional indexing, scheduling
- Facility Location โ Binary variables, fixed costs
- Basic LP โ Simple linear programming
- CP-SAT Assignment โ Constraint programming solver
- McCormick Bilinear โ Bilinear term linearization
- Piecewise Functions โ Piecewise-linear approximations
- Scenario Analysis โ Multiple scenario comparison
- Sensitivity Analysis โ Parameter sensitivity
- What-If Analysis โ Decision support
- Goal Programming โ Multi-objective optimization
๐ฏ Why LumiX?
Before (Traditional Approach)
# Manual indexing, no type safety
x = {}
for i in range(len(products)):
x[i] = model.addVar(name=f"x_{i}")
# String-based error-prone expressions
model.addConstr(
sum(x[i] * data[i] for i in range(len(products))) <= capacity
)
After (LumiX)
# Type-safe, data-driven, IDE-friendly
production = (
LXVariable[Product, float]("production")
.continuous()
.indexed_by(lambda p: p.id)
.from_data(products)
)
model.add_constraint(
LXConstraint("capacity")
.expression(
LXLinearExpression()
.add_term(production, lambda p: p.usage)
)
.le()
.rhs(capacity)
)
Benefits:
- โ Full IDE autocomplete
- โ Type checking catches errors early
- โ No manual indexing
- โ Data-driven coefficients
- โ Readable, maintainable code
- โ Easy to refactor
๐ ๏ธ Development
Setup Development Environment
git clone https://github.com/tdelphi1981/LumiX.git
cd LumiX
pip install -e .[dev]
Run Tests
pytest
Type Checking
mypy src/lumix
Code Formatting
black src/lumix
ruff check src/lumix
๐ฆ Project Structure
lumix/
โโโ src/lumix/
โ โโโ core/ # Core model building (variables, constraints, expressions)
โ โโโ solvers/ # Solver interfaces (OR-Tools, Gurobi, CPLEX, GLPK, CP-SAT)
โ โโโ analysis/ # Analysis tools (sensitivity, scenario, what-if)
โ โโโ linearization/ # Automatic linearization engine
โ โโโ goal_programming/ # Goal programming support
โ โโโ indexing/ # Multi-dimensional indexing
โ โโโ nonlinear/ # Non-linear terms
โ โโโ solution/ # Solution handling and mapping
โ โโโ utils/ # Utilities (logger, ORM, rational converter)
โโโ examples/ # 11 comprehensive examples
โโโ tests/ # Test suite
โโโ docs/ # Sphinx documentation
๐ค Contributing
Contributions are welcome! Please:
- Open an issue to discuss your idea
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
๐ License
LumiX is licensed under the Academic Free License v3.0.
This is a permissive open-source license that:
- โ Allows commercial use
- โ Allows modification and distribution
- โ Provides patent protection
- โ Is OSI-approved
๐ Acknowledgments
LumiX builds upon the excellent work of:
๐ Support
- Documentation: https://lumix.readthedocs.io
- Issues: https://github.com/tdelphi1981/LumiX/issues
- Discussions: https://github.com/tdelphi1981/LumiX/discussions
๐บ๏ธ Roadmap
- Additional solver support (HiGHS, SCIP)
- Jupyter notebook integration
- Interactive visualization tools
- Cloud solver integration
- Extended ORM support (SQLAlchemy, Django)
- Advanced constraint programming features
- Parallel scenario evaluation
- Model versioning and serialization
Authors
This project is maintained by:
- Tolga BERBER - tolga.berber@fen.ktu.edu.tr
- Beyzanur SฤฐYAH - beyzanursiyah@ktu.edu.tr
For a complete list of contributors, see AUTHORS.
Made with โค๏ธ by the LumiX Contributors
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lumix_opt-0.1.1.tar.gz.
File metadata
- Download URL: lumix_opt-0.1.1.tar.gz
- Upload date:
- Size: 124.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c098ca656c8d5a63f7e62e9afc460b3ecf7571b650d7aa83ff0ab99d87e351c
|
|
| MD5 |
b0de42ed2dbfbbcf492273d22ac2378f
|
|
| BLAKE2b-256 |
67795264878e85ada4245cd944ffed50f6253a358a3938b9f7ea8aea33e9ed95
|
File details
Details for the file lumix_opt-0.1.1-py3-none-any.whl.
File metadata
- Download URL: lumix_opt-0.1.1-py3-none-any.whl
- Upload date:
- Size: 145.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a8683a244a689b5934431345788670e6a24ab26bc43de7ff577aebbdf859c01
|
|
| MD5 |
03fcd6136439120b19afb7b2532443c1
|
|
| BLAKE2b-256 |
26e152be83e3d733c292a7221b7b0bf4e4934f59f40d103f86a7e30ba36c08d6
|