A Python package for declarative optimization that accepts configuration files and performs optimizations using various solvers (CBC, GUROBI, GLPK)
Project description
PyOptima
Declarative Optimization Service - Accept configuration files and perform optimizations
PyOptima is a Python package for declarative optimization that accepts configuration files and performs optimizations using various solvers (CBC, GUROBI, GLPK). It provides a simple, declarative interface for defining optimization problems without writing solver-specific code.
Features
- 🚀 Declarative Configuration - Define optimization problems using JSON configuration files
- 🔧 Multiple Solvers - Support for CBC, GUROBI, and GLPK solvers
- 📋 Type Safety - Full type hints and Pydantic v2 compatibility
- 🎯 Easy to Use - Simple API for running optimizations
- 🔄 Swappable Solvers - Easily switch between different solvers via configuration
Installation
Core Library
pip install pyoptima
With Solver Support
# For CBC and GLPK (using PuLP)
pip install pyoptima[cbc]
pip install pyoptima[glpk]
# For Gurobi (requires Gurobi license)
pip install pyoptima[gurobi]
# Install all solvers
pip install pyoptima[all]
Quick Start
1. Create a Configuration File
Create a JSON file (e.g., portfolio.json) with your optimization problem:
{
"meta": {
"job_id": "portfolio-rebalance-001",
"solver": "CBC",
"time_limit_seconds": 30
},
"variables": [
{ "id": "w_aapl", "type": "Continuous", "lb": 0, "ub": 0.5 },
{ "id": "w_msft", "type": "Continuous", "lb": 0, "ub": 0.5 }
],
"objective": {
"direction": "Maximize",
"terms": [
{ "var": "w_aapl", "coef": 0.12 },
{ "var": "w_msft", "coef": 0.15 }
]
},
"constraints": [
{
"id": "budget_limit",
"upper_bound": 1.0,
"terms": [
{ "var": "w_aapl", "coef": 1 },
{ "var": "w_msft", "coef": 1 }
]
}
]
}
2. Run Optimization
Using CLI
pyoptima optimize portfolio.json
With output file:
pyoptima optimize portfolio.json --output results.json --pretty
Using Python API
from pyoptima import OptimizationEngine
# Create engine
engine = OptimizationEngine()
# Run optimization
result = engine.optimize_from_file("portfolio.json")
# Check results
if result.is_optimal():
print(f"Optimal objective value: {result.objective_value}")
print(f"Variable values: {result.variables}")
else:
print(f"Optimization status: {result.status}")
Configuration Format
Meta
Metadata for the optimization job:
{
"meta": {
"job_id": "unique-job-id",
"solver": "CBC", // "CBC", "GUROBI", or "GLPK"
"time_limit_seconds": 30 // Optional
}
}
Variables
Define optimization variables:
{
"variables": [
{
"id": "w_aapl",
"type": "Continuous", // "Continuous", "Binary", or "Integer"
"lb": 0, // Optional lower bound
"ub": 0.5 // Optional upper bound
},
{
"id": "shift_john_1",
"type": "Binary" // Binary variables don't need bounds
}
]
}
Objective
Define the objective function:
{
"objective": {
"direction": "Maximize", // "Maximize" or "Minimize"
"terms": [
{ "var": "w_aapl", "coef": 0.12 },
{ "var": "shift_john_1", "coef": -10 }
]
}
}
Constraints
Define constraints:
{
"constraints": [
{
"id": "budget_limit",
"lower_bound": null, // Optional
"upper_bound": 1.0, // Optional
"terms": [
{ "var": "w_aapl", "coef": 1 },
{ "var": "w_msft", "coef": 1 }
]
},
{
"id": "min_nurses",
"lower_bound": 2.0,
"upper_bound": null,
"terms": [
{ "var": "shift_john_1", "coef": 1 },
{ "var": "shift_jane_1", "coef": 1 }
]
}
]
}
Examples
Portfolio Optimization
{
"meta": {
"job_id": "portfolio-001",
"solver": "CBC"
},
"variables": [
{ "id": "w_aapl", "type": "Continuous", "lb": 0, "ub": 0.4 },
{ "id": "w_msft", "type": "Continuous", "lb": 0, "ub": 0.4 },
{ "id": "w_goog", "type": "Continuous", "lb": 0, "ub": 0.4 }
],
"objective": {
"direction": "Maximize",
"terms": [
{ "var": "w_aapl", "coef": 0.12 },
{ "var": "w_msft", "coef": 0.15 },
{ "var": "w_goog", "coef": 0.18 }
]
},
"constraints": [
{
"id": "budget",
"upper_bound": 1.0,
"terms": [
{ "var": "w_aapl", "coef": 1 },
{ "var": "w_msft", "coef": 1 },
{ "var": "w_goog", "coef": 1 }
]
}
]
}
Nurse Scheduling
{
"meta": {
"job_id": "nurse-scheduling-001",
"solver": "CBC"
},
"variables": [
{ "id": "shift_john_1", "type": "Binary" },
{ "id": "shift_john_2", "type": "Binary" },
{ "id": "shift_jane_1", "type": "Binary" },
{ "id": "shift_jane_2", "type": "Binary" }
],
"objective": {
"direction": "Minimize",
"terms": [
{ "var": "shift_john_1", "coef": 1 },
{ "var": "shift_john_2", "coef": 1 },
{ "var": "shift_jane_1", "coef": 1 },
{ "var": "shift_jane_2", "coef": 1 }
]
},
"constraints": [
{
"id": "min_nurses_shift1",
"lower_bound": 2.0,
"terms": [
{ "var": "shift_john_1", "coef": 1 },
{ "var": "shift_jane_1", "coef": 1 }
]
},
{
"id": "min_nurses_shift2",
"lower_bound": 2.0,
"terms": [
{ "var": "shift_john_2", "coef": 1 },
{ "var": "shift_jane_2", "coef": 1 }
]
}
]
}
API Reference
OptimizationEngine
Main engine for running optimizations.
from pyoptima import OptimizationEngine
engine = OptimizationEngine()
# From file
result = engine.optimize_from_file("config.json")
# From config object
from pyoptima import parse_config_file
config = parse_config_file("config.json")
result = engine.optimize(config)
OptimizationResult
Result object containing optimization results.
result.is_optimal() # Check if solution is optimal
result.objective_value # Objective function value
result.variables # Dictionary of variable values
result.status # Status string
result.to_dict() # Convert to dictionary
Supported Solvers
CBC (COIN-OR Branch and Cut)
- Installation:
pip install pyoptima[cbc] - Requirements: PuLP library
- Best for: General-purpose linear and integer programming
Gurobi
- Installation:
pip install pyoptima[gurobi] - Requirements: Gurobi license (academic or commercial)
- Best for: Large-scale optimization problems
GLPK (GNU Linear Programming Kit)
- Installation:
pip install pyoptima[glpk] - Requirements: PuLP library
- Best for: Open-source alternative to commercial solvers
Development Setup
Quick Setup
# Clone repository
cd pyoptima
# Install in development mode
pip install -e ".[dev,all]"
# Run tests
pytest
Requirements
- Python 3.10+
- Pydantic >= 2.0.0
- Solver-specific dependencies (see installation section)
License
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Made with ❤️ for the Python optimization community
Project details
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 pyoptima-0.0.1.tar.gz.
File metadata
- Download URL: pyoptima-0.0.1.tar.gz
- Upload date:
- Size: 14.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1e163cca8c6822a1a54aed259c9ace1a37a7e7d1f67ecc305712909575c3f33
|
|
| MD5 |
760237731539f142f38a4caa5653f6b4
|
|
| BLAKE2b-256 |
5df553166601933a56b0cb99c11f2e3e13a257adb3827aaf66cca4188d7e49e5
|
File details
Details for the file pyoptima-0.0.1-py3-none-any.whl.
File metadata
- Download URL: pyoptima-0.0.1-py3-none-any.whl
- Upload date:
- Size: 16.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73d2ebaca0f35a90e2748edbb51855bb50de3886f41524c7b40ce87efc32568b
|
|
| MD5 |
70ab1f5a0015bbd93bb4201aa17a53c2
|
|
| BLAKE2b-256 |
e64ee6f6f08845a838b34690d7f81064366c3bee02a1cf7295cf83f5a4c71acb
|