Skip to content

Quick Start

A condensed reference for using optimex. For the underlying framework, see the Theory page. For detailed explanations, see the User Guide, Examples, or the API Reference.


Install optimex

pip install optimex

For other installation methods (uv, conda) and platform-specific notes, see the Installation guide.


Minimal Working Example

from datetime import datetime
import numpy as np
import bw2data as bd
from bw_temporalis import TemporalDistribution
from optimex import lca_processor, converter, optimizer, postprocessing

# 1. Set up Brightway project
bd.projects.set_current("my_project")

# 2. Define temporal demand
years = range(2020, 2030)
td_demand = TemporalDistribution(
    date=np.array([datetime(y, 1, 1).isoformat() for y in years], dtype='datetime64[s]'),
    amount=np.array([0, 0, 10, 10, 10, 10, 10, 10, 10, 10]),
)
demand = {bd.get_node(code="my_product"): td_demand}

# 3. Configure LCA processing
config = lca_processor.LCAConfig(
    demand=demand,
    temporal={
        "start_date": datetime(2020, 1, 1),
        "temporal_resolution": "year",
        "time_horizon": 100,
    },
    characterization_methods=[
        {"category_name": "climate_change", "brightway_method": ("IPCC", "GWP100")},
    ],
)

# 4. Process LCA data
lca_data = lca_processor.LCADataProcessor(config)

# 5. Convert to optimization inputs
manager = converter.ModelInputManager()
model_inputs = manager.parse_from_lca_processor(lca_data)

# 6. Create and solve model
model = optimizer.create_model(model_inputs, name="my_model", objective_category="climate_change")
solved, objective, results = optimizer.solve_model(model, solver_name="glpk")

# 7. Analyze results
pp = postprocessing.PostProcessor(solved)
pp.plot_impacts()
pp.plot_installation()
pp.plot_capacity_balance()

Database Structure

Brightway Project
├── biosphere3          # Elementary flows (emissions)
├── db_2020             # Background database (year 2020)
├── db_2030             # Background database (year 2030)
└── foreground          # Your processes (required name)

Foreground Process Template

{
    ("foreground", "my_process"): {
        "name": "Process Name",
        "location": "GLO",
        "operation_time_limits": (1, 2),  # (start_tau, end_tau)
        "exchanges": [
            {
                "amount": 1,
                "type": "production",
                "input": ("foreground", "my_product"),
                "temporal_distribution": TemporalDistribution(
                    date=np.array([0, 1, 2], dtype="timedelta64[Y]"),
                    amount=np.array([0, 0.5, 0.5]),
                ),
                "operation": True,
            },
            {
                "amount": 10,
                "type": "technosphere",
                "input": ("db_2020", "electricity"),
                "temporal_distribution": TemporalDistribution(
                    date=np.array([0], dtype="timedelta64[Y]"),
                    amount=np.array([1]),
                ),
            },
            {
                "amount": 5,
                "type": "biosphere",
                "input": ("biosphere3", "CO2"),
                "temporal_distribution": TemporalDistribution(
                    date=np.array([1, 2], dtype="timedelta64[Y]"),
                    amount=np.array([0.5, 0.5]),
                ),
                "operation": True,
            },
        ],
    }
}

Key optimex Additions to Brightway

Element Field Description
Process operation_time_limits (start, end) tuple defining operation phase
Exchange temporal_distribution When the exchange occurs (relative years)
Exchange operation True if scales with operation level
Database representative_time Metadata for background DB timestamp

LCAConfig Quick Reference

lca_processor.LCAConfig(
    demand={product_node: temporal_distribution},
    temporal={
        "start_date": datetime(2020, 1, 1),
        "temporal_resolution": "year",  # or "month", "day"
        "time_horizon": 100,            # years for impact assessment
    },
    characterization_methods=[
        {
            "category_name": "climate_change",
            "brightway_method": ("IPCC", "GWP100"),
            "metric": "CRF",  # Optional: "CRF" or "GWP" for dynamic
        },
    ],
)

Common Constraints

# Limit total capacity
model_inputs.cumulative_process_limits_max = {"process_id": 100.0}

# Limit yearly installation
model_inputs.process_deployment_limits_max = {("process_id", 2025): 50.0}

# Carbon budget (cumulative)
model_inputs.cumulative_category_impact_limits = {"climate_change": 1000000.0}

# Annual carbon limit
model_inputs.category_impact_limits = {("climate_change", 2030): 50000.0}

# Pre-existing capacity
model_inputs.existing_capacity = {("old_plant", 2010): 500.0}

PostProcessor Methods

Method Returns Description
get_impacts() DataFrame Impact by process, category, time
get_installation() DataFrame Capacity installed per time
get_operation() DataFrame Operation level per time
get_production() DataFrame Production by process and product
get_demand() DataFrame Demand fulfillment over time
plot_impacts() Figure Stacked area plot of impacts
plot_installation() Figure Bar chart of installations
plot_capacity_balance() Figure Production vs capacity comparison

Saving & Loading

# Save model inputs
manager.save_inputs("model_inputs.json")  # or .pkl

# Load model inputs
manager.load_inputs("model_inputs.json")
model_inputs = manager.model_inputs

# Save solved model
optimizer.save_solved_model(solved, "solved.pkl", objective_value=objective)

# Load solved model
loaded = optimizer.load_solved_model("solved.pkl")