Loading...
Loading...
Compare original and translation side by side
class SingleStopVehicleLoader:
"""
Optimize loading for single-destination delivery
Uses 3D bin packing with vehicle-specific constraints
"""
def __init__(self, vehicle_length, vehicle_width, vehicle_height,
weight_capacity, front_axle_limit=13000, rear_axle_limit=34000):
"""
Initialize vehicle loader
Parameters:
- vehicle_length, vehicle_width, vehicle_height: cargo area dimensions (inches)
- weight_capacity: max payload weight (lbs)
- front_axle_limit, rear_axle_limit: axle weight limits (lbs)
"""
self.vehicle_dims = (vehicle_length, vehicle_width, vehicle_height)
self.weight_capacity = weight_capacity
self.front_axle_limit = front_axle_limit
self.rear_axle_limit = rear_axle_limit
self.items = []
self.solution = None
def add_item(self, length, width, height, weight, item_id=None):
"""Add item to load"""
if item_id is None:
item_id = f"Item_{len(self.items)}"
self.items.append({
'id': item_id,
'dims': (length, width, height),
'weight': weight
})
def optimize_loading(self, algorithm='weight_balanced'):
"""
Optimize vehicle loading
Algorithms:
- 'weight_balanced': Prioritize weight distribution
- 'space_efficient': Maximize space utilization
- 'easy_unload': Place items for easy access
"""
L, W, H = self.vehicle_dims
if algorithm == 'weight_balanced':
# Sort by weight (heaviest first)
sorted_items = sorted(self.items,
key=lambda x: x['weight'],
reverse=True)
elif algorithm == 'space_efficient':
# Sort by volume
sorted_items = sorted(self.items,
key=lambda x: x['dims'][0] * x['dims'][1] * x['dims'][2],
reverse=True)
else:
sorted_items = self.items
loaded_items = []
current_weight = 0
# Simple layer-based loading
current_y = 0
current_z = 0
current_x = 0
for item in sorted_items:
l, w, h = item['dims']
weight = item['weight']
# Check weight
if current_weight + weight > self.weight_capacity:
continue # Skip item if too heavy
# Try to place item
if current_x + l <= L:
# Place in current row
loaded_items.append({
'item': item,
'position': (current_x, current_y, current_z),
'dims': (l, w, h)
})
current_x += l
current_weight += weight
elif current_y + w <= W:
# Start new row
current_x = 0
current_y += w
loaded_items.append({
'item': item,
'position': (current_x, current_y, current_z),
'dims': (l, w, h)
})
current_x += l
current_weight += weight
elif current_z + h <= H:
# Start new layer
current_x = 0
current_y = 0
current_z += h
loaded_items.append({
'item': item,
'position': (current_x, current_y, current_z),
'dims': (l, w, h)
})
current_x += l
current_weight += weight
# Check axle weights
axle_check = self.check_axle_weights(loaded_items)
self.solution = {
'loaded_items': loaded_items,
'total_weight': current_weight,
'items_loaded': len(loaded_items),
'items_not_loaded': len(self.items) - len(loaded_items),
'utilization': self.calculate_utilization(loaded_items),
'axle_weights': axle_check
}
return self.solution
def check_axle_weights(self, loaded_items):
"""
Calculate axle weight distribution
Assumes:
- Front axle at 0 (front of vehicle)
- Rear axle at 60% of vehicle length
"""
L = self.vehicle_dims[0]
rear_axle_position = L * 0.6
front_axle_weight = 0
rear_axle_weight = 0
for item_data in loaded_items:
pos = item_data['position']
dims = item_data['dims']
weight = item_data['item']['weight']
# Calculate center of mass
com_x = pos[0] + dims[0] / 2
# Distance from axles
distance_from_rear = rear_axle_position - com_x
if distance_from_rear > 0:
# Weight forward of rear axle - distributes to both
front_ratio = distance_from_rear / rear_axle_position
front_axle_weight += weight * front_ratio
rear_axle_weight += weight * (1 - front_ratio)
else:
# Weight behind rear axle - all on rear
rear_axle_weight += weight
return {
'front_axle': front_axle_weight,
'rear_axle': rear_axle_weight,
'front_limit': self.front_axle_limit,
'rear_limit': self.rear_axle_limit,
'front_ok': front_axle_weight <= self.front_axle_limit,
'rear_ok': rear_axle_weight <= self.rear_axle_limit,
'balanced': abs(front_axle_weight - rear_axle_weight) / (front_axle_weight + rear_axle_weight) < 0.3
}
def calculate_utilization(self, loaded_items):
"""Calculate volume utilization"""
L, W, H = self.vehicle_dims
vehicle_volume = L * W * H
loaded_volume = sum(
item_data['dims'][0] * item_data['dims'][1] * item_data['dims'][2]
for item_data in loaded_items
)
return (loaded_volume / vehicle_volume * 100) if vehicle_volume > 0 else 0
def print_solution(self):
"""Print loading solution"""
if not self.solution:
print("No solution available")
return
print("=" * 70)
print("VEHICLE LOADING SOLUTION")
print("=" * 70)
print(f"Vehicle: {self.vehicle_dims[0]}L x {self.vehicle_dims[1]}W x {self.vehicle_dims[2]}H in")
print(f"Weight Capacity: {self.weight_capacity:,} lbs")
print()
print(f"Items Loaded: {self.solution['items_loaded']} / {len(self.items)}")
print(f"Total Weight: {self.solution['total_weight']:,} lbs")
print(f"Utilization: {self.solution['utilization']:.1f}%")
print()
print("Axle Weight Distribution:")
axle = self.solution['axle_weights']
print(f" Front Axle: {axle['front_axle']:,.0f} lbs "
f"({'OK' if axle['front_ok'] else 'OVER LIMIT'})")
print(f" Rear Axle: {axle['rear_axle']:,.0f} lbs "
f"({'OK' if axle['rear_ok'] else 'OVER LIMIT'})")
print(f" Balanced: {'Yes' if axle['balanced'] else 'No - adjust load'}")class SingleStopVehicleLoader:
"""
Optimize loading for single-destination delivery
Uses 3D bin packing with vehicle-specific constraints
"""
def __init__(self, vehicle_length, vehicle_width, vehicle_height,
weight_capacity, front_axle_limit=13000, rear_axle_limit=34000):
"""
Initialize vehicle loader
Parameters:
- vehicle_length, vehicle_width, vehicle_height: cargo area dimensions (inches)
- weight_capacity: max payload weight (lbs)
- front_axle_limit, rear_axle_limit: axle weight limits (lbs)
"""
self.vehicle_dims = (vehicle_length, vehicle_width, vehicle_height)
self.weight_capacity = weight_capacity
self.front_axle_limit = front_axle_limit
self.rear_axle_limit = rear_axle_limit
self.items = []
self.solution = None
def add_item(self, length, width, height, weight, item_id=None):
"""Add item to load"""
if item_id is None:
item_id = f"Item_{len(self.items)}"
self.items.append({
'id': item_id,
'dims': (length, width, height),
'weight': weight
})
def optimize_loading(self, algorithm='weight_balanced'):
"""
Optimize vehicle loading
Algorithms:
- 'weight_balanced': Prioritize weight distribution
- 'space_efficient': Maximize space utilization
- 'easy_unload': Place items for easy access
"""
L, W, H = self.vehicle_dims
if algorithm == 'weight_balanced':
# Sort by weight (heaviest first)
sorted_items = sorted(self.items,
key=lambda x: x['weight'],
reverse=True)
elif algorithm == 'space_efficient':
# Sort by volume
sorted_items = sorted(self.items,
key=lambda x: x['dims'][0] * x['dims'][1] * x['dims'][2],
reverse=True)
else:
sorted_items = self.items
loaded_items = []
current_weight = 0
# Simple layer-based loading
current_y = 0
current_z = 0
current_x = 0
for item in sorted_items:
l, w, h = item['dims']
weight = item['weight']
# Check weight
if current_weight + weight > self.weight_capacity:
continue # Skip item if too heavy
# Try to place item
if current_x + l <= L:
# Place in current row
loaded_items.append({
'item': item,
'position': (current_x, current_y, current_z),
'dims': (l, w, h)
})
current_x += l
current_weight += weight
elif current_y + w <= W:
# Start new row
current_x = 0
current_y += w
loaded_items.append({
'item': item,
'position': (current_x, current_y, current_z),
'dims': (l, w, h)
})
current_x += l
current_weight += weight
elif current_z + h <= H:
# Start new layer
current_x = 0
current_y = 0
current_z += h
loaded_items.append({
'item': item,
'position': (current_x, current_y, current_z),
'dims': (l, w, h)
})
current_x += l
current_weight += weight
# Check axle weights
axle_check = self.check_axle_weights(loaded_items)
self.solution = {
'loaded_items': loaded_items,
'total_weight': current_weight,
'items_loaded': len(loaded_items),
'items_not_loaded': len(self.items) - len(loaded_items),
'utilization': self.calculate_utilization(loaded_items),
'axle_weights': axle_check
}
return self.solution
def check_axle_weights(self, loaded_items):
"""
Calculate axle weight distribution
Assumes:
- Front axle at 0 (front of vehicle)
- Rear axle at 60% of vehicle length
"""
L = self.vehicle_dims[0]
rear_axle_position = L * 0.6
front_axle_weight = 0
rear_axle_weight = 0
for item_data in loaded_items:
pos = item_data['position']
dims = item_data['dims']
weight = item_data['item']['weight']
# Calculate center of mass
com_x = pos[0] + dims[0] / 2
# Distance from axles
distance_from_rear = rear_axle_position - com_x
if distance_from_rear > 0:
# Weight forward of rear axle - distributes to both
front_ratio = distance_from_rear / rear_axle_position
front_axle_weight += weight * front_ratio
rear_axle_weight += weight * (1 - front_ratio)
else:
# Weight behind rear axle - all on rear
rear_axle_weight += weight
return {
'front_axle': front_axle_weight,
'rear_axle': rear_axle_weight,
'front_limit': self.front_axle_limit,
'rear_limit': self.rear_axle_limit,
'front_ok': front_axle_weight <= self.front_axle_limit,
'rear_ok': rear_axle_weight <= self.rear_axle_limit,
'balanced': abs(front_axle_weight - rear_axle_weight) / (front_axle_weight + rear_axle_weight) < 0.3
}
def calculate_utilization(self, loaded_items):
"""Calculate volume utilization"""
L, W, H = self.vehicle_dims
vehicle_volume = L * W * H
loaded_volume = sum(
item_data['dims'][0] * item_data['dims'][1] * item_data['dims'][2]
for item_data in loaded_items
)
return (loaded_volume / vehicle_volume * 100) if vehicle_volume > 0 else 0
def print_solution(self):
"""Print loading solution"""
if not self.solution:
print("No solution available")
return
print("=" * 70)
print("VEHICLE LOADING SOLUTION")
print("=" * 70)
print(f"Vehicle: {self.vehicle_dims[0]}L x {self.vehicle_dims[1]}W x {self.vehicle_dims[2]}H in")
print(f"Weight Capacity: {self.weight_capacity:,} lbs")
print()
print(f"Items Loaded: {self.solution['items_loaded']} / {len(self.items)}")
print(f"Total Weight: {self.solution['total_weight']:,} lbs")
print(f"Utilization: {self.solution['utilization']:.1f}%")
print()
print("Axle Weight Distribution:")
axle = self.solution['axle_weights']
print(f" Front Axle: {axle['front_axle']:,.0f} lbs "
f"({'OK' if axle['front_ok'] else 'OVER LIMIT'})")
print(f" Rear Axle: {axle['rear_axle']:,.0f} lbs "
f"({'OK' if axle['rear_ok'] else 'OVER LIMIT'})")
print(f" Balanced: {'Yes' if axle['balanced'] else 'No - adjust load'}")# Add items
loader.add_item(48, 40, 60, 800, "Pallet_1")
loader.add_item(48, 40, 50, 700, "Pallet_2")
loader.add_item(48, 40, 55, 750, "Pallet_3")
loader.add_item(36, 30, 40, 500, "Box_1")
loader.add_item(36, 30, 40, 500, "Box_2")
# Optimize
solution = loader.optimize_loading(algorithm='weight_balanced')
loader.print_solution()undefined# Add items
loader.add_item(48, 40, 60, 800, "Pallet_1")
loader.add_item(48, 40, 50, 700, "Pallet_2")
loader.add_item(48, 40, 55, 750, "Pallet_3")
loader.add_item(36, 30, 40, 500, "Box_1")
loader.add_item(36, 30, 40, 500, "Box_2")
# Optimize
solution = loader.optimize_loading(algorithm='weight_balanced')
loader.print_solution()undefinedclass MultiStopVehicleLoader:
"""
Optimize vehicle loading for multi-stop delivery routes
Ensures items are accessible in delivery sequence
"""
def __init__(self, vehicle_dims, weight_capacity):
self.vehicle_dims = vehicle_dims
self.weight_capacity = weight_capacity
self.stops = [] # List of delivery stops
self.solution = None
def add_stop(self, stop_id, items, delivery_sequence):
"""
Add delivery stop with items
Parameters:
- stop_id: stop identifier
- items: list of item dicts with 'dims' and 'weight'
- delivery_sequence: order in route (1, 2, 3, ...)
"""
self.stops.append({
'id': stop_id,
'items': items,
'sequence': delivery_sequence
})
def optimize_loading(self):
"""
Optimize loading for multi-stop delivery
Strategy:
- Zone vehicle by delivery sequence
- Last stop loaded first (at door)
- Earlier stops loaded deeper in vehicle
"""
# Sort stops by reverse delivery sequence
sorted_stops = sorted(self.stops,
key=lambda s: s['sequence'],
reverse=True)
L, W, H = self.vehicle_dims
# Calculate zones
num_stops = len(sorted_stops)
zone_length = L / num_stops
zones = []
current_weight = 0
for idx, stop in enumerate(sorted_stops):
zone_start = idx * zone_length
zone_end = (idx + 1) * zone_length
zone_items = []
# Load items for this stop in this zone
for item in stop['items']:
if current_weight + item['weight'] <= self.weight_capacity:
# Simple placement (could be more sophisticated)
zone_items.append({
'item': item,
'stop_id': stop['id'],
'zone': (zone_start, zone_end)
})
current_weight += item['weight']
zones.append({
'stop': stop,
'zone': (zone_start, zone_end),
'items': zone_items
})
self.solution = {
'zones': zones,
'total_weight': current_weight,
'stops_loaded': len(zones),
'total_items': sum(len(z['items']) for z in zones)
}
return self.solution
def print_solution(self):
"""Print multi-stop loading plan"""
if not self.solution:
print("No solution available")
return
print("=" * 70)
print("MULTI-STOP VEHICLE LOADING PLAN")
print("=" * 70)
print(f"Total Weight: {self.solution['total_weight']:,} lbs")
print(f"Stops: {self.solution['stops_loaded']}")
print(f"Total Items: {self.solution['total_items']}")
print()
for zone_data in self.solution['zones']:
stop = zone_data['stop']
zone = zone_data['zone']
print(f"Stop {stop['sequence']}: {stop['id']}")
print(f" Zone: {zone[0]:.0f}-{zone[1]:.0f} inches from front")
print(f" Items: {len(zone_data['items'])}")
print()class MultiStopVehicleLoader:
"""
Optimize vehicle loading for multi-stop delivery routes
Ensures items are accessible in delivery sequence
"""
def __init__(self, vehicle_dims, weight_capacity):
self.vehicle_dims = vehicle_dims
self.weight_capacity = weight_capacity
self.stops = [] # List of delivery stops
self.solution = None
def add_stop(self, stop_id, items, delivery_sequence):
"""
Add delivery stop with items
Parameters:
- stop_id: stop identifier
- items: list of item dicts with 'dims' and 'weight'
- delivery_sequence: order in route (1, 2, 3, ...)
"""
self.stops.append({
'id': stop_id,
'items': items,
'sequence': delivery_sequence
})
def optimize_loading(self):
"""
Optimize loading for multi-stop delivery
Strategy:
- Zone vehicle by delivery sequence
- Last stop loaded first (at door)
- Earlier stops loaded deeper in vehicle
"""
# Sort stops by reverse delivery sequence
sorted_stops = sorted(self.stops,
key=lambda s: s['sequence'],
reverse=True)
L, W, H = self.vehicle_dims
# Calculate zones
num_stops = len(sorted_stops)
zone_length = L / num_stops
zones = []
current_weight = 0
for idx, stop in enumerate(sorted_stops):
zone_start = idx * zone_length
zone_end = (idx + 1) * zone_length
zone_items = []
# Load items for this stop in this zone
for item in stop['items']:
if current_weight + item['weight'] <= self.weight_capacity:
# Simple placement (could be more sophisticated)
zone_items.append({
'item': item,
'stop_id': stop['id'],
'zone': (zone_start, zone_end)
})
current_weight += item['weight']
zones.append({
'stop': stop,
'zone': (zone_start, zone_end),
'items': zone_items
})
self.solution = {
'zones': zones,
'total_weight': current_weight,
'stops_loaded': len(zones),
'total_items': sum(len(z['items']) for z in zones)
}
return self.solution
def print_solution(self):
"""Print multi-stop loading plan"""
if not self.solution:
print("No solution available")
return
print("=" * 70)
print("MULTI-STOP VEHICLE LOADING PLAN")
print("=" * 70)
print(f"Total Weight: {self.solution['total_weight']:,} lbs")
print(f"Stops: {self.solution['stops_loaded']}")
print(f"Total Items: {self.solution['total_items']}")
print()
for zone_data in self.solution['zones']:
stop = zone_data['stop']
zone = zone_data['zone']
print(f"Stop {stop['sequence']}: {stop['id']}")
print(f" Zone: {zone[0]:.0f}-{zone[1]:.0f} inches from front")
print(f" Items: {len(zone_data['items'])}")
print()def optimize_fleet_loading(orders, vehicles):
"""
Optimize loading across multiple vehicles
Assigns orders to vehicles to minimize:
- Number of vehicles used
- Total distance traveled
- Loading/unloading complexity
Parameters:
- orders: list of order dicts with items, destination, priority
- vehicles: list of available vehicle specs
Returns: assignment of orders to vehicles
"""
from pulp import *
n_orders = len(orders)
n_vehicles = len(vehicles)
# Create problem
prob = LpProblem("Fleet_Loading", LpMinimize)
# Decision variables
# x[i,j] = 1 if order i assigned to vehicle j
x = LpVariable.dicts("assign",
[(i, j) for i in range(n_orders) for j in range(n_vehicles)],
cat='Binary')
# y[j] = 1 if vehicle j is used
y = LpVariable.dicts("use_vehicle", range(n_vehicles), cat='Binary')
# Objective: Minimize vehicles used + routing cost
prob += lpSum([y[j] * vehicles[j]['cost']
for j in range(n_vehicles)]), "Total_Cost"
# Constraints
# 1. Each order assigned to exactly one vehicle
for i in range(n_orders):
prob += lpSum([x[i,j] for j in range(n_vehicles)]) == 1, f"Order_{i}"
# 2. Vehicle capacity (weight)
for j in range(n_vehicles):
prob += (lpSum([orders[i]['weight'] * x[i,j] for i in range(n_orders)]) <=
vehicles[j]['weight_capacity']), f"Weight_{j}"
# 3. Vehicle capacity (volume)
for j in range(n_vehicles):
prob += (lpSum([orders[i]['volume'] * x[i,j] for i in range(n_orders)]) <=
vehicles[j]['volume_capacity']), f"Volume_{j}"
# 4. Vehicle used if orders assigned
for j in range(n_vehicles):
for i in range(n_orders):
prob += x[i,j] <= y[j], f"VehicleUsed_{i}_{j}"
# Solve
prob.solve(PULP_CBC_CMD(msg=0))
# Extract solution
assignments = [[] for _ in range(n_vehicles)]
for i in range(n_orders):
for j in range(n_vehicles):
if x[i,j].varValue and x[i,j].varValue > 0.5:
assignments[j].append(i)
return {
'status': LpStatus[prob.status],
'vehicles_used': sum(1 for a in assignments if a),
'assignments': assignments
}def optimize_fleet_loading(orders, vehicles):
"""
Optimize loading across multiple vehicles
Assigns orders to vehicles to minimize:
- Number of vehicles used
- Total distance traveled
- Loading/unloading complexity
Parameters:
- orders: list of order dicts with items, destination, priority
- vehicles: list of available vehicle specs
Returns: assignment of orders to vehicles
"""
from pulp import *
n_orders = len(orders)
n_vehicles = len(vehicles)
# Create problem
prob = LpProblem("Fleet_Loading", LpMinimize)
# Decision variables
# x[i,j] = 1 if order i assigned to vehicle j
x = LpVariable.dicts("assign",
[(i, j) for i in range(n_orders) for j in range(n_vehicles)],
cat='Binary')
# y[j] = 1 if vehicle j is used
y = LpVariable.dicts("use_vehicle", range(n_vehicles), cat='Binary')
# Objective: Minimize vehicles used + routing cost
prob += lpSum([y[j] * vehicles[j]['cost']
for j in range(n_vehicles)]), "Total_Cost"
# Constraints
# 1. Each order assigned to exactly one vehicle
for i in range(n_orders):
prob += lpSum([x[i,j] for j in range(n_vehicles)]) == 1, f"Order_{i}"
# 2. Vehicle capacity (weight)
for j in range(n_vehicles):
prob += (lpSum([orders[i]['weight'] * x[i,j] for i in range(n_orders)]) <=
vehicles[j]['weight_capacity']), f"Weight_{j}"
# 3. Vehicle capacity (volume)
for j in range(n_vehicles):
prob += (lpSum([orders[i]['volume'] * x[i,j] for i in range(n_orders)]) <=
vehicles[j]['volume_capacity']), f"Volume_{j}"
# 4. Vehicle used if orders assigned
for j in range(n_vehicles):
for i in range(n_orders):
prob += x[i,j] <= y[j], f"VehicleUsed_{i}_{j}"
# Solve
prob.solve(PULP_CBC_CMD(msg=0))
# Extract solution
assignments = [[] for _ in range(n_vehicles)]
for i in range(n_orders):
for j in range(n_vehicles):
if x[i,j].varValue and x[i,j].varValue > 0.5:
assignments[j].append(i)
return {
'status': LpStatus[prob.status],
'vehicles_used': sum(1 for a in assignments if a),
'assignments': assignments
}