| name | prefab-optimization |
| description | Optimize prefabrication and modular construction workflows. Plan module sequencing, factory scheduling, transportation logistics, and on-site assembly for maximum efficiency. |
| homepage | https://datadrivenconstruction.io |
| metadata | {"openclaw":{"emoji":"🚀","os":["darwin","linux","win32"],"homepage":"https://datadrivenconstruction.io","requires":{"bins":"[Truncated]"}}} |
Prefabrication Optimization
Overview
This skill implements optimization algorithms for prefabricated and modular construction. Maximize factory utilization, minimize transportation costs, and optimize on-site assembly sequences.
Optimization Areas:
- Module design for transport
- Factory production scheduling
- Logistics and transportation
- On-site assembly sequencing
- Crane and equipment planning
- Quality control checkpoints
Quick Start
from dataclasses import dataclass, field
from datetime import date, datetime, timedelta
from typing import List, Dict, Tuple, Optional
from enum import Enum
class ModuleStatus(Enum):
DESIGN = "design"
PRODUCTION = "production"
QC = "quality_control"
STORAGE = "storage"
TRANSPORT = "transport"
ON_SITE = "on_site"
INSTALLED = "installed"
@dataclass
class PrefabModule:
module_id: str
name: str
module_type: str
dimensions: Tuple[float, float, float]
weight_kg: float
status: ModuleStatus = ModuleStatus.DESIGN
production_hours: float = 0
dependencies: List[str] = field(default_factory=list)
@dataclass
class ProductionSlot:
slot_id: str
start_time: datetime
end_time: datetime
bay_id: str
module_id: str
def calculate_transport_constraints(module: PrefabModule) -> Dict:
"""Calculate transport constraints for module"""
L, W, H = module.dimensions
max_width = 4.0
max_height = 4.5
max_length = 12.0
max_weight = 40000
constraints = {
'within_standard': True,
'requires_escort': False,
'requires_permit': False,
'transport_type': 'standard'
}
if W > max_width or H > max_height:
constraints['within_standard'] = False
constraints['requires_escort'] = True
constraints['requires_permit'] = True
constraints['transport_type'] = 'wide_load'
if L > max_length:
constraints['requires_permit'] = True
constraints['transport_type'] = 'long_load'
if module.weight_kg > max_weight:
constraints['requires_permit'] = True
constraints['transport_type'] = 'heavy_load'
return constraints
module = PrefabModule(
module_id="MOD-001",
name="Bathroom Pod Type A",
module_type="bathroom",
dimensions=(4.5, 3.0, 3.2),
weight_kg=8500,
production_hours=40
)
constraints = calculate_transport_constraints(module)
print(f"Module {module.name}: {constraints}")
Comprehensive Prefab System
Module Definition and Analysis
from dataclasses import dataclass, field
from datetime import date, datetime, timedelta
from typing import List, Dict, Tuple, Optional, Set
from enum import Enum
import numpy as np
class ModuleCategory(Enum):
BATHROOM_POD = "bathroom_pod"
KITCHEN_POD = "kitchen_pod"
STRUCTURAL = "structural"
FACADE = "facade"
MEP = "mep"
STAIR = "stair"
ELEVATOR = "elevator"
ROOM_MODULE = "room_module"
@dataclass
class ModuleConnection:
connection_id: str
connection_type: str
from_module: str
to_module: str
from_point: Tuple[float, float, float]
to_point: Tuple[float, float, float]
tolerance_mm: float = 10
@dataclass
class ModuleDesign:
module_id: str
name: str
category: ModuleCategory
version:
length_m:
width_m:
height_m:
weight_kg:
production_hours:
required_skills: []
materials_list: []
connections: [ModuleConnection] = field(default_factory=)
required_modules: [] = field(default_factory=)
blocks_modules: [] = field(default_factory=)
floor_level: =
grid_position: [, ] = (, )
zone: =
() -> :
.length_m * .width_m * .height_m
() -> :
.length_m * .width_m
:
():
.transport_limits = {
: {: , : , : , : },
: {: , : , : , : },
: {: , : , : , : }
}
() -> :
dims = (module.length_m, module.width_m, module.height_m)
transport_type, limits .transport_limits.items():
((dims[], dims[]) <= limits[]
(dims[], dims[]) <= limits[]
dims[] <= limits[]
module.weight_kg <= limits[]):
analysis = {
: ,
: transport_type,
: dims[] >= dims[] ,
: {
: (dims[], dims[]) / limits[],
: (dims[], dims[]) / limits[],
: dims[] / limits[],
: module.weight_kg / limits[]
}
}
transport_type == :
analysis[] =
transport_type == :
analysis[] =
analysis[] = [, , ]
:
analysis[] =
analysis[] = [, , ]
analysis
{
: ,
: ,
: (dims),
:
}
() -> :
safety_factor =
required_capacity = module.weight_kg * safety_factor /
floor_height =
estimated_height = module.floor_level * floor_height +
required_capacity <= estimated_height <= :
crane_type =
required_capacity <= estimated_height <= :
crane_type =
required_capacity <= :
crane_type =
:
crane_type =
{
: required_capacity,
: estimated_height,
: crane_type,
: ._calculate_lift_points(module),
: (module.length_m / , module.width_m / , module.height_m / )
}
() -> [[, ]]:
L, W = module.length_m, module.width_m
offset =
[
(L * offset, W * offset),
(L * ( - offset), W * offset),
(L * offset, W * ( - offset)),
(L * ( - offset), W * ( - offset))
]
Production Scheduling
from datetime import datetime, timedelta
from typing import List, Dict, Optional
import heapq
@dataclass
class ProductionBay:
bay_id: str
bay_type: str
capacity_m2: float
available_from: datetime
skills_available: List[str]
@dataclass
class ProductionOrder:
module_id: str
required_date: date
priority: int
production_hours: float
required_bay_type: str
required_skills: List[str]
class ProductionScheduler:
"""Schedule prefab module production"""
def __init__(self, work_hours_per_day: float = 8):
self.bays: Dict[str, ProductionBay] = {}
self.schedule: Dict[str, List[ProductionSlot]] = {}
self.work_hours = work_hours_per_day
def add_bay(self, bay: ProductionBay):
"""Add production bay"""
self.bays[bay.bay_id] = bay
.schedule[bay.bay_id] = []
() -> :
sorted_orders = (orders, key= o: (o.priority, o.required_date))
scheduled = []
unscheduled = []
order sorted_orders:
slot = ._find_best_slot(order)
slot:
.schedule[slot.bay_id].append(slot)
scheduled.append({
: order.module_id,
: slot.bay_id,
: slot.start_time.isoformat(),
: slot.end_time.isoformat(),
: order.production_hours
})
:
unscheduled.append(order.module_id)
{
: scheduled,
: unscheduled,
: ._calculate_utilization()
}
() -> [ProductionSlot]:
best_slot =
best_end_time = datetime.
bay_id, bay .bays.items():
bay.bay_type != order.required_bay_type:
(order.required_skills).issubset((bay.skills_available)):
existing_slots = .schedule.get(bay_id, [])
existing_slots:
last_end = (s.end_time s existing_slots)
start_time = (bay.available_from, last_end)
:
start_time = bay.available_from
production_days = order.production_hours / .work_hours
end_time = start_time + timedelta(days=production_days)
required_datetime = datetime.combine(order.required_date, datetime..time())
end_time <= required_datetime end_time < best_end_time:
best_end_time = end_time
best_slot = ProductionSlot(
slot_id=,
start_time=start_time,
end_time=end_time,
bay_id=bay_id,
module_id=order.module_id
)
best_slot
() -> [, ]:
utilization = {}
bay_id, slots .schedule.items():
slots:
utilization[bay_id] =
total_time = ((s.end_time s slots) -
(s.start_time s slots)).total_seconds()
used_time = ((s.end_time - s.start_time).total_seconds() s slots)
utilization[bay_id] = used_time / total_time total_time >
utilization
() -> []:
gantt_data = []
bay_id, slots .schedule.items():
slot slots:
gantt_data.append({
: bay_id,
: slot.module_id,
: slot.start_time.isoformat(),
: slot.end_time.isoformat()
})
(gantt_data, key= x: x[])
Assembly Sequence Optimization
from collections import defaultdict, deque
from typing import List, Dict, Set
class AssemblySequencer:
"""Optimize on-site module assembly sequence"""
def __init__(self, modules: List[ModuleDesign]):
self.modules = {m.module_id: m for m in modules}
self.dependency_graph = self._build_dependency_graph()
def _build_dependency_graph(self) -> Dict[str, Set[str]]:
"""Build dependency graph from module dependencies"""
graph = defaultdict(set)
for module_id, module in self.modules.items():
for dep_id in module.required_modules:
graph[module_id].add(dep_id)
return graph
def calculate_sequence(self) -> List[List[str]]:
"""Calculate optimal assembly sequence using topological sort"""
in_degree = defaultdict(int)
for module_id in self.modules:
in_degree[module_id] =
deps .dependency_graph.values():
dep deps:
in_degree[dep] +=
queue = deque([
m_id m_id .modules
(.dependency_graph[m_id]) ==
])
sequence = []
current_level = []
queue:
current_level = (queue)
queue.clear()
sequence.append(current_level)
module_id current_level:
dependent .modules:
module_id .dependency_graph[dependent]:
.dependency_graph[dependent].remove(module_id)
(.dependency_graph[dependent]) == :
queue.append(dependent)
remaining = [m_id m_id .modules m_id
[item sublist sequence item sublist]]
remaining:
()
sequence
() -> []:
base_sequence = .calculate_sequence()
optimized = []
level base_sequence:
level_with_positions = []
module_id level:
module = .modules[module_id]
grid_x = (module.grid_position[]) module.grid_position[]
grid_y = (module.grid_position[]) module.grid_position[].isdigit()
min_dist = ()
cx, cy crane_positions:
dist = ((grid_x - cx) ** + (grid_y - cy) ** ) **
min_dist = (min_dist, dist)
level_with_positions.append({
: module_id,
: module.floor_level,
: min_dist
})
level_with_positions.sort(key= x: (x[], x[]))
optimized.append(level_with_positions)
optimized
() -> []:
sequence = .calculate_sequence()
plan = []
day =
modules_per_day =
level_idx, level (sequence):
i (, (level), modules_per_day):
batch = level[i:i + modules_per_day]
module_id batch:
module = .modules[module_id]
plan.append({
: day,
: (plan) + ,
: module_id,
: module.name,
: module.floor_level,
: module.grid_position,
: module.weight_kg,
: (module.connections),
: level_idx +
})
day +=
plan
Transportation Optimization
from scipy.optimize import linear_sum_assignment
import numpy as np
@dataclass
class TransportVehicle:
vehicle_id: str
capacity_kg: float
max_length_m: float
max_width_m: float
max_height_m: float
cost_per_km: float
available_from: datetime
class TransportOptimizer:
"""Optimize module transportation logistics"""
def __init__(self, factory_location: Tuple[float, float],
site_location: Tuple[float, float]):
self.factory = factory_location
self.site = site_location
self.distance_km = self._calculate_distance()
self.vehicles: List[TransportVehicle] = []
self.routes: List[Dict] = []
def _calculate_distance(self) -> float:
"""Calculate distance between factory and site"""
lat1, lon1 = self.factory
lat2, lon2 = self.site
R = 6371
dlat = np.radians(lat2 - lat1)
dlon = np.radians(lon2 - lon1)
a = (np.sin(dlat/)** +
np.cos(np.radians(lat1)) * np.cos(np.radians(lat2)) *
np.sin(dlon/)**)
c = * np.arctan2(np.sqrt(a), np.sqrt(-a))
R * c
():
.vehicles.append(vehicle)
() -> :
sorted_modules = (
modules,
key= m: required_dates.get(m.module_id, date.)
)
assignments = []
remaining_modules = (sorted_modules)
remaining_modules:
vehicle .vehicles:
batch = ._pack_vehicle(vehicle, remaining_modules)
batch:
assignments.append({
: vehicle.vehicle_id,
: [m.module_id m batch],
: (m.weight_kg m batch),
: (m.weight_kg m batch) / vehicle.capacity_kg,
: vehicle.cost_per_km * .distance_km *
})
m batch:
remaining_modules.remove(m)
:
{
: assignments,
: (assignments),
: (a[] a assignments),
: [m.module_id m remaining_modules]
}
() -> [ModuleDesign]:
packed = []
total_weight =
module modules:
dims = ([module.length_m, module.width_m])
(dims[] <= vehicle.max_width_m
dims[] <= vehicle.max_length_m
module.height_m <= vehicle.max_height_m
total_weight + module.weight_kg <= vehicle.capacity_kg):
packed.append(module)
total_weight += module.weight_kg
(dims) > module.weight_kg > vehicle.capacity_kg * :
packed
() -> []:
schedule = []
site_constraints :
site_constraints = {
: ,
: ,
: ,
:
}
current_date = date.today()
deliveries_today =
current_hour = site_constraints[]
assignment assignments:
deliveries_today >= site_constraints[]:
current_date += timedelta(days=)
deliveries_today =
current_hour = site_constraints[]
current_hour >= site_constraints[]:
current_date += timedelta(days=)
deliveries_today =
current_hour = site_constraints[]
schedule.append({
**assignment,
: current_date.isoformat(),
: ,
:
})
current_hour +=
deliveries_today +=
schedule
Quick Reference
| Module Type | Typical Dimensions (LxWxH) | Typical Weight | Production Time |
|---|
| Bathroom Pod | 3.0 x 2.4 x 2.7m | 4,000-8,000 kg | 30-50 hours |
| Kitchen Pod | 4.0 x 2.4 x 2.7m | 5,000-10,000 kg | 40-60 hours |
| Room Module | 6.0 x 3.0 x 3.0m | 15,000-25,000 kg | 60-100 hours |
| Facade Panel | 6.0 x 3.0 x 0.3m | 2,000-4,000 kg | 15-25 hours |
| Stair Module | 4.0 x 2.5 x 3.5m | 8,000-12,000 kg | 35-50 hours |
Transport Limits by Region
| Region | Max Width | Max Height | Max Length | Max Weight |
|---|
| EU Standard | 2.55m | 4.0m | 12.0m | 40t |
| EU Wide Load | 4.0m | 4.5m | 16.5m | 60t |
| US Standard | 2.6m | 4.1m | 14.6m | 36t |
| US Oversize | 4.3m | 4.6m | 22.0m | 60t |
Resources
Next Steps
- See
site-logistics-optimization for on-site delivery scheduling
- See
4d-simulation for assembly sequence visualization
- See
bim-validation-pipeline for module quality checks