Sensitivity Analysis Example¶
Overview¶
This example demonstrates LumiX’s sensitivity analysis capabilities for understanding optimal solutions through shadow prices, reduced costs, and bottleneck identification.
Sensitivity analysis reveals which constraints are limiting profitability, which resources are most valuable, and how sensitive the solution is to parameter changes - essential for investment decisions and resource prioritization.
Problem Description¶
After solving a production planning problem, a manufacturing company wants to understand:
Shadow Prices: What is the marginal value of each resource?
Reduced Costs: What is the opportunity cost of each variable?
Bottlenecks: Which constraints are limiting profitability?
Investment Priorities: Where should we invest to maximize ROI?
Mathematical Foundation¶
Primal Problem:
Dual Problem:
Shadow Prices (\(y\)): Dual variables representing marginal value of relaxing constraints.
Reduced Costs: Opportunity cost of forcing a variable to change from its optimal value.
Key Features¶
Shadow Price Analysis¶
Analyze marginal value of constraints:
This function performs a complete sensitivity analysis workflow that reveals
the economic insights hidden in the optimal solution:
1. Build and solve the production model with sensitivity enabled
2. Analyze shadow prices (dual values) for all constraints
3. Identify binding constraints that limit profitability
4. Find bottlenecks with high marginal values
5. Compute reduced costs for decision variables
6. Rank constraints by sensitivity impact
7. Generate comprehensive sensitivity reports
The analysis provides actionable insights for resource investment decisions,
Interpretation:
Shadow price > 0: Constraint is binding (at capacity)
Shadow price = 0: Constraint has slack (not binding)
Shadow price = $2.50: Each additional unit increases profit by $2.50
Bottleneck Identification¶
Find constraints limiting profitability:
Interpretation: Each additional labor hour increases profit by 2.50
...
Notes:
Sensitivity analysis requires:
- The optimizer must support dual values (.enable_sensitivity())
- The optimal solution must be available (not infeasible/unbounded)
- Only works with LP models (not MIP)
Key concepts demonstrated:
- Shadow prices: marginal value of relaxing a constraint by one unit
Bottlenecks are binding constraints with significant shadow prices.
Most Sensitive Constraints¶
Rank constraints by sensitivity:
invalid (though this example doesn't compute ranges).
"""
print("=" * 80)
print("SENSITIVITY ANALYSIS: Production Planning Solution Insights")
print("=" * 80)
# Build and solve model
Prioritize relaxing constraints with highest shadow prices.
Reduced Cost Analysis¶
Analyze variable opportunity costs:
print("\n" + "-" * 80)
print("OPTIMAL SOLUTION SUMMARY")
print("-" * 80)
print(solution.summary())
# Generate full sensitivity report
Interpretation:
Reduced cost = 0: Variable in optimal basis
Reduced cost > 0: Increasing variable would decrease objective
Running the Example¶
Prerequisites:
pip install lumix
pip install ortools # or cplex, gurobi
Run:
cd examples/09_sensitivity_analysis
python sensitivity_analysis.py
Expected Output:
====================================================================
SENSITIVITY ANALYSIS: Production Planning Solution Insights
====================================================================
OPTIMAL SOLUTION SUMMARY
--------------------------------------------------------------------
Status: optimal
Objective: $12,345.68
Solve time: 0.123s
====================================================================
CONSTRAINT SENSITIVITY ANALYSIS
====================================================================
capacity_Labor Hours:
Shadow Price: $2.5000
Binding: YES
➜ Interpretation: Each additional labor hour increases profit by $2.50
capacity_Machine Hours:
Shadow Price: $1.2500
Binding: YES
➜ Interpretation: Each additional machine hour increases profit by $1.25
capacity_Raw Materials:
Shadow Price: $0.0000
Binding: NO
--------------------------------------------------------------------
BINDING CONSTRAINTS (At Capacity)
--------------------------------------------------------------------
Found 2 binding constraints:
• capacity_Labor Hours
Shadow Price: $2.5000
• capacity_Machine Hours
Shadow Price: $1.2500
--------------------------------------------------------------------
TOP 5 MOST VALUABLE CONSTRAINTS TO RELAX
--------------------------------------------------------------------
1. capacity_Labor Hours
Shadow Price: $2.5000
Expected ROI: $2.50 per unit relaxation
2. capacity_Machine Hours
Shadow Price: $1.2500
Expected ROI: $1.25 per unit relaxation
Complete Code Walkthrough¶
Step 1: Solve Model with Sensitivity Enabled¶
model.add_constraint(
LXConstraint(f"capacity_{resource.name}")
.expression(usage_expr)
Note: .enable_sensitivity() requests dual values from solver.
Step 2: Create Sensitivity Analyzer¶
)
Step 3: Analyze Individual Constraints¶
"""Run comprehensive sensitivity analysis on the optimal solution.
This function performs a complete sensitivity analysis workflow that reveals
the economic insights hidden in the optimal solution:
1. Build and solve the production model with sensitivity enabled
2. Analyze shadow prices (dual values) for all constraints
3. Identify binding constraints that limit profitability
4. Find bottlenecks with high marginal values
5. Compute reduced costs for decision variables
6. Rank constraints by sensitivity impact
7. Generate comprehensive sensitivity reports
The analysis provides actionable insights for resource investment decisions,
Step 4: Identify Bottlenecks¶
============================================================
CONSTRAINT SENSITIVITY ANALYSIS
Shadow Price: 2.50 per unit (Labor Hours)
Interpretation: Each additional labor hour increases profit by 2.50
...
Notes:
Sensitivity analysis requires:
- The optimizer must support dual values (.enable_sensitivity())
- The optimal solution must be available (not infeasible/unbounded)
- Only works with LP models (not MIP)
Key concepts demonstrated:
- Shadow prices: marginal value of relaxing a constraint by one unit
Step 5: Generate Business Insights¶
print(f"\nIdentified {len(bottlenecks)} bottlenecks:")
print("\nThese constraints are limiting profitability:")
for name in bottlenecks:
sens = analyzer.analyze_constraint(name)
print(f"\n {name}:")
print(f" Shadow Price: ${sens.shadow_price:.4f}")
print(f" Impact: Relaxing by 1 unit → +${sens.shadow_price:.2f} profit")
else:
print("\nNo significant bottlenecks identified")
# Top sensitive constraints
print("\n" + "-" * 80)
print("TOP 5 MOST VALUABLE CONSTRAINTS TO RELAX")
print("-" * 80)
top_constraints = analyzer.get_most_sensitive_constraints(top_n=5)
if top_constraints:
Learning Objectives¶
After completing this example, you should understand:
Shadow Prices: Marginal value of relaxing constraints
Reduced Costs: Opportunity cost of changing variables
Binding Constraints: Identifying active constraints (bottlenecks)
Duality Theory: Relationship between primal and dual problems
Investment Analysis: Using sensitivity for ROI calculations
Complementary Slackness: Why slack constraints have zero shadow price
Common Patterns¶
Pattern 1: Constraint Sensitivity Check¶
sens = analyzer.analyze_constraint("constraint_name")
if sens.is_binding:
print(f"Bottleneck: ${sens.shadow_price:.2f} per unit")
else:
print(f"Has slack: {sens.slack:.2f} units available")
Pattern 2: Investment Decision¶
labor_sens = analyzer.analyze_constraint("capacity_Labor")
# Decision logic
if labor_sens.shadow_price > hiring_cost_per_hour:
print("✓ HIRE: Shadow price exceeds cost")
roi = labor_sens.shadow_price - hiring_cost_per_hour
print(f" Expected profit: ${roi:.2f} per hour")
else:
print("✗ DON'T HIRE: Cost exceeds value")
Pattern 3: Prioritize Improvements¶
# Get top constraints to relax
top_constraints = analyzer.get_most_sensitive_constraints(top_n=5)
for i, (name, sens) in enumerate(top_constraints, 1):
print(f"{i}. {name}: ${sens.shadow_price:.2f} per unit")
Business Insights Generated¶
Resource Investment Priorities¶
Based on shadow prices, prioritize investment in:
1. Labor Hours
Marginal Value: $2.50 per unit
Status: BINDING (at capacity)
✓ HIGH PRIORITY: Strong ROI expected
2. Machine Hours
Marginal Value: $1.25 per unit
Status: BINDING (at capacity)
→ MODERATE PRIORITY: Positive ROI
3. Raw Materials
Marginal Value: $0.00 per unit
Status: NOT BINDING (excess capacity)
✗ LOW PRIORITY: No value from expansion
Hiring Recommendation¶
► HIRING RECOMMENDATION:
- Labor capacity is constraining profit
- Each additional labor hour adds $2.50 profit
- Consider hiring if cost per hour < $2.50
Risk Assessment¶
⚠ HIGH SENSITIVITY:
- 2 constraints are binding
- Solution highly sensitive to parameter changes
- Small capacity variations significantly impact profit
- Recommendation: Build buffer capacity
Sensitivity Metrics Explained¶
Shadow Prices (Dual Values)¶
Definition: Marginal value of relaxing a constraint by one unit.
Example: Labor has shadow price = $2.50
Increasing labor by 1 hour → Profit increases by $2.50
Decreasing labor by 1 hour → Profit decreases by $2.50
Business Use:
Maximum price to pay for one more unit
Value of capacity expansion
Investment prioritization
Reduced Costs¶
Definition: Opportunity cost of forcing a variable to change.
Example: Production variable has reduced cost = $0.50
Forcing production up by 1 unit → Profit decreases by $0.50
Variable currently at lower bound
Not economical to increase
Business Use:
Identify products worth producing more
Understand why some products not produced
Product portfolio decisions
Complementary Slackness¶
At optimality:
If constraint has slack → Shadow price = 0
If shadow price > 0 → Constraint is binding (no slack)
If variable at bound → Reduced cost may be non-zero
If reduced cost = 0 → Variable in basis (not at bound)
Extending the Example¶
Try These Modifications¶
Multi-Period: Analyze sensitivity over time
Stochastic: Probabilistic sensitivity analysis
Range Analysis: Valid ranges for shadow prices
Parametric: How shadow prices change with RHS
Interactive Dashboard: Real-time sensitivity visualization
Next Steps¶
After mastering this example:
Example 08 (Scenario Analysis): Strategic planning scenarios
Example 10 (What-If Analysis): Quick tactical decisions
Advanced Duality Theory: Linear programming duality
See Also¶
Related Examples:
Scenario Analysis Example - Testing multiple scenarios
What-If Analysis Example - Quick parameter changes
Production Planning Example - Base model for analysis
API Reference:
lumix.analysis.LXSensitivityAnalyzerlumix.solution.LXSolution
Files in This Example¶
sensitivity_analysis.py- Main sensitivity analysis demonstrationsample_data.py- Data models (Product, Resource) and sample dataREADME.md- Detailed documentation and usage guide