skills/multi-objective-optimization/SKILL.md
When the user wants to optimize multiple conflicting objectives, find Pareto-optimal solutions, or balance trade-offs between cost, service, quality, and sustainability. Also use when the user mentions "multi-objective," "Pareto optimization," "NSGA-II," "trade-off analysis," "scalarization," "weighted objectives," "goal programming," or "multiple criteria optimization." For single objective, see optimization-modeling.
npx skillsauth add kishorkukreja/awesome-supply-chain multi-objective-optimizationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are an expert in multi-objective optimization for supply chain. Your goal is to help find and analyze Pareto-optimal solutions that balance conflicting objectives like cost vs service, profit vs sustainability, or efficiency vs resilience.
Pareto Dominance: Solution x dominates y if x is better in all objectives
Pareto Front: Set of non-dominated solutions
Trade-off: Improving one objective worsens another
# Combine objectives with weights
objective = w1 * cost + w2 * (-service_level) + w3 * carbon
# Vary weights to get different Pareto points
for w1 in [0.2, 0.5, 0.8]:
w2, w3 = (1-w1)/2, (1-w1)/2
solve_with_weights(w1, w2, w3)
# Optimize one objective, constrain others
minimize cost
subject to:
service_level ≥ 0.95
carbon ≤ 1000
from pymoo.algorithms.moo.nsga2 import NSGA2
from pymoo.optimize import minimize
from pymoo.problems import get_problem
# Multi-objective problem
problem = SupplyChainMO()
algorithm = NSGA2(pop_size=100)
res = minimize(problem,
algorithm,
('n_gen', 200),
verbose=True)
# Get Pareto front
pareto_front = res.F
# Set target for each objective, minimize deviations
targets = {'cost': 100000, 'service': 0.98, 'carbon': 500}
minimize sum(d_minus[obj] + d_plus[obj] for obj in objectives)
subject to:
actual[obj] + d_plus[obj] - d_minus[obj] = targets[obj]
from pulp import *
import numpy as np
import matplotlib.pyplot as plt
def multi_objective_network_design(customers, facilities, weights):
"""
Network design with cost and service objectives
Objective 1: Minimize total cost
Objective 2: Minimize average distance (maximize service)
"""
model = LpProblem("MultiObj_Network", LpMinimize)
# Variables
open_facility = LpVariable.dicts("Open", facilities, cat='Binary')
flow = LpVariable.dicts("Flow",
[(i,j) for i in customers for j in facilities],
lowBound=0)
# Objective: weighted combination
w_cost, w_service = weights
cost_obj = lpSum([fixed_cost[j] * open_facility[j] for j in facilities]) + \
lpSum([transport_cost[i,j] * flow[i,j]
for i in customers for j in facilities])
service_obj = lpSum([distance[i,j] * flow[i,j]
for i in customers for j in facilities])
# Normalize objectives
max_cost = estimate_max_cost()
max_distance = estimate_max_distance()
model += w_cost * (cost_obj / max_cost) + \
w_service * (service_obj / max_distance), "Weighted_Objective"
# Constraints
for i in customers:
model += lpSum([flow[i,j] for j in facilities]) >= demand[i]
for j in facilities:
model += lpSum([flow[i,j] for i in customers]) <= \
capacity[j] * open_facility[j]
model.solve()
return {
'cost': value(cost_obj),
'service': value(service_obj),
'open_facilities': [j for j in facilities if open_facility[j].varValue > 0.5]
}
# Generate Pareto frontier
pareto_solutions = []
for w_cost in np.linspace(0, 1, 20):
w_service = 1 - w_cost
sol = multi_objective_network_design(customers, facilities, (w_cost, w_service))
pareto_solutions.append(sol)
# Plot Pareto front
costs = [s['cost'] for s in pareto_solutions]
services = [s['service'] for s in pareto_solutions]
plt.figure(figsize=(10, 6))
plt.plot(costs, services, 'o-', linewidth=2, markersize=8)
plt.xlabel('Total Cost ($)')
plt.ylabel('Average Distance (Service)')
plt.title('Pareto Frontier: Cost vs Service Trade-off')
plt.grid(True, alpha=0.3)
plt.show()
class TripleBottomLineOptimization:
"""
Optimize Economic, Environmental, and Social objectives
"""
def __init__(self, network_data):
self.data = network_data
def optimize_pareto(self, method='weighted_sum'):
"""
Find Pareto-optimal solutions for triple bottom line
Objectives:
1. Economic: Minimize cost
2. Environmental: Minimize carbon emissions
3. Social: Maximize local employment
"""
if method == 'weighted_sum':
solutions = []
# Systematically vary weights
for w1 in [0.2, 0.4, 0.6, 0.8]:
for w2 in [0.2, 0.4, 0.6, 0.8]:
w3 = max(0, 1 - w1 - w2)
if w1 + w2 + w3 > 0.99: # Valid weight combination
sol = self.solve_weighted(w1, w2, w3)
solutions.append(sol)
# Filter non-dominated solutions
pareto_front = self.extract_pareto_front(solutions)
return pareto_front
elif method == 'epsilon_constraint':
# Fix two objectives, optimize third
pareto_front = []
for carbon_limit in np.linspace(min_carbon, max_carbon, 10):
for employment_target in np.linspace(min_emp, max_emp, 10):
sol = self.solve_epsilon_constraint(
carbon_limit=carbon_limit,
employment_target=employment_target
)
if sol['feasible']:
pareto_front.append(sol)
return pareto_front
def solve_weighted(self, w_economic, w_environmental, w_social):
"""Solve with weighted objectives"""
model = LpProblem("Triple_Bottom_Line", LpMinimize)
# Variables and constraints
# ...
# Weighted objective
model += (
w_economic * economic_cost +
w_environmental * carbon_emissions +
w_social * (-local_employment) # Maximize employment
)
model.solve()
return {
'economic': value(economic_cost),
'environmental': value(carbon_emissions),
'social': value(local_employment),
'weights': (w_economic, w_environmental, w_social)
}
def extract_pareto_front(self, solutions):
"""Filter non-dominated solutions"""
pareto = []
for sol in solutions:
dominated = False
for other in solutions:
if self.dominates(other, sol):
dominated = True
break
if not dominated:
pareto.append(sol)
return pareto
def dominates(self, sol1, sol2):
"""Check if sol1 Pareto-dominates sol2"""
# sol1 dominates if better in all objectives
better_economic = sol1['economic'] <= sol2['economic']
better_environmental = sol1['environmental'] <= sol2['environmental']
better_social = sol1['social'] >= sol2['social'] # Maximize
at_least_one_strictly_better = (
sol1['economic'] < sol2['economic'] or
sol1['environmental'] < sol2['environmental'] or
sol1['social'] > sol2['social']
)
return (better_economic and better_environmental and better_social and
at_least_one_strictly_better)
def interactive_pareto_exploration(problem, decision_maker):
"""
Interactive method: present solutions, get feedback, refine
"""
# Generate initial Pareto front
pareto_front = problem.generate_initial_pareto_front()
iteration = 0
max_iterations = 10
while iteration < max_iterations:
# Present solutions to decision maker
print(f"\nIteration {iteration + 1}")
print("Current Pareto Solutions:")
for i, sol in enumerate(pareto_front):
print(f" {i}: Cost=${sol['cost']}, Service={sol['service']:.2%}, Carbon={sol['carbon']}")
# Get feedback
preferred_region = decision_maker.get_preference(pareto_front)
if decision_maker.is_satisfied():
break
# Generate more solutions in preferred region
new_solutions = problem.explore_region(preferred_region, n_solutions=10)
pareto_front.extend(new_solutions)
# Update Pareto front
pareto_front = filter_non_dominated(pareto_front)
iteration += 1
# Final selection
best_solution = decision_maker.select_final_solution(pareto_front)
return best_solution
def visualize_3d_pareto_front(solutions):
"""
Visualize 3-objective Pareto front
"""
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(12, 10))
ax = fig.add_subplot(111, projection='3d')
costs = [s['cost'] for s in solutions]
services = [s['service'] for s in solutions]
carbons = [s['carbon'] for s in solutions]
scatter = ax.scatter(costs, services, carbons,
c=carbons, cmap='RdYlGn_r',
s=100, alpha=0.6, edgecolors='black')
ax.set_xlabel('Cost ($)', fontsize=12)
ax.set_ylabel('Service Level', fontsize=12)
ax.set_zlabel('Carbon Emissions (tons)', fontsize=12)
ax.set_title('3D Pareto Frontier', fontsize=14, fontweight='bold')
plt.colorbar(scatter, label='Carbon Emissions')
plt.show()
def visualize_parallel_coordinates(pareto_front):
"""
Parallel coordinates plot for many objectives
"""
from pandas.plotting import parallel_coordinates
import pandas as pd
df = pd.DataFrame(pareto_front)
df['Solution'] = range(len(df))
plt.figure(figsize=(12, 6))
parallel_coordinates(df, 'Solution', colormap='viridis')
plt.title('Pareto Solutions - Parallel Coordinates')
plt.ylabel('Normalized Objective Value')
plt.legend(loc='upper right')
plt.grid(True, alpha=0.3)
plt.show()
Python:
pymoo: Multi-objective optimizationplatypus: Evolutionary multi-objectivejmetal: Multi-objective metaheuristicsCommercial:
modeFRONTIER: Multi-objective designCPLEX Multi-Objectivedocumentation
When the user wants to optimize yard operations, manage trailer parking, or improve dock door utilization. Also use when the user mentions "yard management," "trailer tracking," "yard jockey," "drop trailer program," "trailer pool," "dock scheduling," or "gate management." For cross-dock operations, see cross-docking. For warehouse design, see warehouse-design.
tools
When the user wants to optimize workforce scheduling, create shift plans, or balance labor demand. Also use when the user mentions "staff scheduling," "labor planning," "shift optimization," "crew scheduling," "roster optimization," or "employee scheduling." For task assignment, see task-assignment-problem. For wave planning labor, see wave-planning-optimization.
testing
When the user wants to optimize pick wave planning, schedule warehouse operations, or improve order fulfillment efficiency. Also use when the user mentions "wave management," "batch picking," "pick wave scheduling," "order release optimization," "wave design," or "pick wave strategy." For order batching, see order-batching-optimization. For workforce scheduling, see workforce-scheduling.
testing
When the user wants to optimize warehouse slot assignments, improve pick efficiency, or design warehouse layouts. Also use when the user mentions "slotting optimization," "slot assignment," "ABC slotting," "pick path optimization," "storage location assignment," "warehouse layout optimization," or "forward pick locations." For picker routing, see picker-routing-optimization. For warehouse design, see warehouse-design.