| name | operations-research-guide |
| description | Optimization and operations research methods for business and logistics |
| metadata | {"openclaw":{"emoji":"⚙️","category":"domains","subcategory":"business","keywords":["optimization","operations-research","linear-programming","scheduling","supply-chain","simulation"],"source":"wentor"}} |
Operations Research Guide
A skill for applying operations research (OR) methods to business, logistics, and resource allocation problems. Covers linear programming, integer programming, scheduling, network optimization, simulation, and decision analysis using Python optimization libraries.
Linear Programming
Problem Formulation and Solving
from scipy.optimize import linprog
import numpy as np
def solve_production_planning():
"""
Example: A factory produces two products (A and B).
Product A: profit $40, uses 2h labor + 1kg material
Product B: profit $30, uses 1h labor + 2kg material
Constraints: 100h labor available, 80kg material available
Maximize total profit.
"""
c = [-40, -30]
A_ub = [
[2, 1],
[1, 2],
]
b_ub = [100, 80]
bounds = [(0, None), (0, None)]
result = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method="highs")
return {
"product_A": result.x[0],
"product_B": result.x[1],
"max_profit": -result.fun,
"status": "optimal" if result.success else "infeasible",
}
Using PuLP for Readable Models
from pulp import LpProblem, LpMaximize, LpVariable, lpSum, value
def workforce_scheduling():
"""
Workforce scheduling: minimize staffing cost while meeting
demand for each day of the week. Workers work 5 consecutive days.
"""
days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
demand = [17, 13, 15, 19, 14, 16, 11]
cost_per_worker = 1
prob = LpProblem("workforce_scheduling", LpMaximize)
x = {i: LpVariable(f"start_{days[i]}", lowBound=0, cat="Integer")
for i in range(7)}
prob += -lpSum(x[i] for i in range(7))
for d in range(7):
workers_available = lpSum(x[(d - j) % 7] for j in range(5))
prob += workers_available >= demand[d], f"demand_{days[d]}"
prob.solve()
{
: prob.status,
: {days[i]: (value(x[i])) i ()},
: ((value(x[i]) i ())),
}
Integer and Mixed-Integer Programming
Vehicle Routing Problem
from itertools import combinations
def solve_tsp_mtz(distances: np.ndarray) -> dict:
"""
Solve the Traveling Salesman Problem using Miller-Tucker-Zemlin formulation.
distances: n x n distance matrix
Returns optimal tour and total distance.
"""
from pulp import LpProblem, LpMinimize, LpVariable, LpBinary, lpSum, value
n = len(distances)
prob = LpProblem("TSP", LpMinimize)
x = {(i, j): LpVariable(f"x_{i}_{j}", cat=LpBinary)
for i in range(n) for j in range(n) if i != j}
u = {i: LpVariable(f"u_{i}", lowBound=1, upBound=n - 1)
for i in range(1, n)}
prob += lpSum(distances[i][j] * x[i, j] for i, j in x)
for i in range(n):
prob += lpSum(x[i, j] for j in range(n) if j != i) == 1
prob += lpSum(x[j, i] for j in range(n) j != i) ==
i (, n):
j (, n):
i != j:
prob += u[i] - u[j] + (n - ) * x[i, j] <= n -
prob.solve()
tour = []
current =
_ (n - ):
j (n):
j != current (current, j) x value(x[current, j]) > :
tour.append(j)
current = j
{
: tour,
: value(prob.objective),
}
Queuing Theory
M/M/c Queue Analysis
from math import factorial, exp
def mmc_queue(arrival_rate: float, service_rate: float,
n_servers: int) -> dict:
"""
Analyze an M/M/c queue (Poisson arrivals, exponential service, c servers).
arrival_rate: lambda (customers per unit time)
service_rate: mu (customers served per unit time per server)
n_servers: c (number of parallel servers)
"""
rho = arrival_rate / (n_servers * service_rate)
if rho >= 1:
return {"stable": False, "utilization": rho}
a = arrival_rate / service_rate
sum_terms = sum(a ** k / factorial(k) for k in range(n_servers))
erlang_c = (a ** n_servers / factorial(n_servers)) / (
(a ** n_servers / factorial(n_servers)) + (1 - rho) * sum_terms
)
Lq = erlang_c * rho / (1 - rho)
Wq = Lq / arrival_rate
W = Wq + 1 / service_rate
L = arrival_rate * W
return {
"stable": True,
"utilization": round(rho, 4),
"prob_wait": round(erlang_c, 4),
"avg_queue_length": round(Lq, ),
: (Wq, ),
: (W, ),
: (L, ),
}
Simulation Methods
Discrete-Event Simulation
import simpy
import random
def simulate_service_center(n_servers: int, arrival_rate: float,
service_rate: float, sim_time: float = 480):
"""
Discrete-event simulation of a service center using SimPy.
sim_time: simulation duration in minutes (default 8-hour day).
"""
wait_times = []
def customer(env, server):
arrival_time = env.now
with server.request() as req:
yield req
wait = env.now - arrival_time
wait_times.append(wait)
yield env.timeout(random.expovariate(service_rate))
def customer_generator(env, server):
customer_id = 0
while True:
yield env.timeout(random.expovariate(arrival_rate))
customer_id += 1
env.process(customer(env, server))
env = simpy.Environment()
server = simpy.Resource(env, capacity=n_servers)
env.process(customer_generator(env, server))
env.run(until=sim_time)
return {
"customers_served": len(wait_times),
"avg_wait": np.mean(wait_times) if wait_times else 0,
"max_wait": max(wait_times) if wait_times else 0,
"pct_waited": sum(1 w wait_times w > ) / (wait_times) * ,
}
Decision Analysis
Multi-Criteria Decision Making
| Method | Description | Best For |
|---|
| AHP (Analytic Hierarchy Process) | Pairwise comparison matrix | Structured group decisions |
| TOPSIS | Distance to ideal/anti-ideal solution | Ranking alternatives |
| Weighted scoring | Simple weighted sum | Quick comparisons |
| Decision trees | Sequential decision under uncertainty | Multi-stage problems |
Tools and Libraries
- PuLP: Python LP/MIP modeling with multiple solver backends
- OR-Tools (Google): Constraint programming, routing, scheduling
- Gurobi / CPLEX: Commercial high-performance MIP solvers (free academic licenses)
- SimPy: Python discrete-event simulation framework
- SciPy optimize: Linear programming, nonlinear optimization
- Pyomo: Algebraic modeling language for optimization in Python
- AMPL: Commercial algebraic modeling language