facility-layout-optimizer
You are facility-layout-optimizer - a specialized skill for optimizing facility layouts to minimize material flow and maximize space utilization.
Overview
This skill enables AI-powered facility layout optimization including:
- From-To chart analysis
- Activity relationship diagramming
- CRAFT and ALDEP algorithm implementation
- Block layout generation
- Aisle design and dimensioning
- Material flow visualization
- Space requirement calculation
- Layout alternative evaluation
Capabilities
1. From-To Chart Analysis
import numpy as np
import pandas as pd
def create_from_to_chart(flow_data: list):
"""
Create From-To chart from material flow data
flow_data: list of (from_dept, to_dept, flow_volume, cost_per_unit)
"""
# Get unique departments
depts = set()
for from_d, to_d, _, _ in flow_data:
depts.add(from_d)
depts.add(to_d)
depts = sorted(list(depts))
# Create matrix
n = len(depts)
flow_matrix = np.zeros((n, n))
cost_matrix = np.zeros((n, n))
dept_idx = {d: i for i, d in enumerate(depts)}
for from_d, to_d, flow, cost in flow_data:
i, j = dept_idx[from_d], dept_idx[to_d]
flow_matrix[i, j] = flow
cost_matrix[i, j] = cost
# Calculate weighted flow
weighted_flow = flow_matrix * cost_matrix
return {
"departments": depts,
"flow_matrix": pd.DataFrame(flow_matrix, index=depts, columns=depts),
"cost_matrix": pd.DataFrame(cost_matrix, index=depts, columns=depts),
"weighted_flow": pd.DataFrame(weighted_flow, index=depts, columns=depts),
"total_flow": flow_matrix.sum(),
"total_weighted_flow": weighted_flow.sum()
}
2. Activity Relationship Diagram
from dataclasses import dataclass
from enum import Enum
class Closeness(Enum):
A = "Absolutely necessary"
E = "Especially important"
I = "Important"
O = "Ordinary"
U = "Unimportant"
X = "Undesirable"
@dataclass
class RelationshipEntry:
dept1: str
dept2: str
closeness: Closeness
reason: str
def create_relationship_chart(relationships: list):
"""
Create Activity Relationship Chart (REL chart)
"""
# Extract departments
depts = set()
for r in relationships:
depts.add(r.dept1)
depts.add(r.dept2)
depts = sorted(list(depts))
# Create relationship matrix
n = len(depts)
rel_matrix = {}
for r in relationships:
key = (r.dept1, r.dept2) if r.dept1 < r.dept2 else (r.dept2, r.dept1)
rel_matrix[key] = {
"closeness": r.closeness.name,
"reason": r.reason
}
# Closeness score for layout optimization
closeness_scores = {
'A': 64, 'E': 16, 'I': 4, 'O': 1, 'U': 0, 'X': -64
}
# Create numeric matrix for algorithms
score_matrix = np.zeros((n, n))
dept_idx = {d: i for i, d in enumerate(depts)}
for (d1, d2), rel in rel_matrix.items():
i, j = dept_idx[d1], dept_idx[d2]
score = closeness_scores[rel['closeness']]
score_matrix[i, j] = score
score_matrix[j, i] = score
return {
"departments": depts,
"relationships": rel_matrix,
"score_matrix": pd.DataFrame(score_matrix, index=depts, columns=depts),
"summary": {
"total_relationships": len(relationships),
"A_count": sum(1 for r in relationships if r.closeness == Closeness.A),
"X_count": sum(1 for r in relationships if r.closeness == Closeness.X)
}
}
3. CRAFT Algorithm
def craft_algorithm(initial_layout: np.ndarray, flow_matrix: np.ndarray,
distance_matrix_func, max_iterations: int = 100):
"""
CRAFT (Computerized Relative Allocation of Facilities Technique)
Improvement algorithm - starts with initial layout and iteratively improves
"""
n = len(flow_matrix)
current_layout = initial_layout.copy()
def calculate_cost(layout, flow, dist_func):
total_cost = 0
for i in range(n):
for j in range(n):
if i != j:
loc_i = np.argwhere(layout == i)[0]
loc_j = np.argwhere(layout == j)[0]
dist = dist_func(loc_i, loc_j)
total_cost += flow[i, j] * dist
return total_cost
current_cost = calculate_cost(current_layout, flow_matrix, distance_matrix_func)
iteration = 0
improvement_history = [{"iteration": 0, "cost": current_cost}]
while iteration < max_iterations:
best_swap = None
best_cost = current_cost
# Try all pairwise exchanges
for i in range(n):
for j in range(i + 1, n):
# Swap departments i and j
test_layout = current_layout.copy()
pos_i = np.argwhere(test_layout == i)[0]
pos_j = np.argwhere(test_layout == j)[0]
test_layout[tuple(pos_i)] = j
test_layout[tuple(pos_j)] = i
test_cost = calculate_cost(test_layout, flow_matrix, distance_matrix_func)
if test_cost < best_cost:
best_cost = test_cost
best_swap = (i, j)
if best_swap is None:
break # No improvement found
# Apply best swap
i, j = best_swap
pos_i = np.argwhere(current_layout == i)[0]
pos_j = np.argwhere(current_layout == j)[0]
current_layout[tuple(pos_i)] = j
current_layout[tuple(pos_j)] = i
current_cost = best_cost
iteration += 1
improvement_history.append({
"iteration": iteration,
"swap": best_swap,
"cost": current_cost
})
return {
"final_layout": current_layout,
"final_cost": current_cost,
"iterations": iteration,
"improvement_history": improvement_history,
"improvement_percent": (improvement_history[0]['cost'] - current_cost) /
improvement_history[0]['cost'] * 100
}
4. Block Layout Generation
def generate_block_layout(departments: list, space_requirements: dict,
facility_dimensions: tuple, rel_chart: dict):
"""
Generate block layout from space requirements
"""
width, height = facility_dimensions
total_space = width * height
# Calculate space allocation
total_required = sum(space_requirements.values())
layouts = []
# Simple strip-based layout
x_pos = 0
y_pos = 0
max_height_in_row = 0
for dept in departments:
required = space_requirements.get(dept, 100)
# Calculate block dimensions (roughly square)
block_width = np.sqrt(required)
block_height = required / block_width
if x_pos + block_width > width:
# Move to next row
x_pos = 0
y_pos += max_height_in_row
max_height_in_row = 0
layouts.append({
"department": dept,
"x": x_pos,
"y": y_pos,
"width": block_width,
"height": block_height,
"area": required
})
x_pos += block_width
max_height_in_row = max(max_height_in_row, block_height)
return {
"blocks": layouts,
"facility_dimensions": facility_dimensions,
"total_space_used": sum(b['area'] for b in layouts),
"utilization": sum(b['area'] for b in layouts) / total_space * 100
}
5. Layout Evaluation
def evaluate_layout(layout: list, flow_data: dict, rel_chart: dict):
"""
Evaluate layout quality
"""
# Calculate centroids
centroids = {}
for block in layout:
centroids[block['department']] = (
block['x'] + block['width'] / 2,
block['y'] + block['height'] / 2
)
# Calculate total mat