Desktop interface that generates minimum run film slitting plans from parent roll geometry, usable width regions, and customer order demands. By grouping compatible orders, it expands requested quantities into individual lane demands, then uses OR-Tools CP-SAT to minimize production runs and generate physical blade positions from drive side coordinates, selects the exact spacer stack necessary, and verifies feasability to complete the plan.
Built around real film slitting constraints and physical spacer hardware.
The programs main function is to create optimal plans based on demand. It determines the combination of customer lanes that should be cut together in order to minimize runs. After deciding said combination, the program generates real world operator instructions on spacer stack combinations and blade positions.
Doing this manually is time-consuming and error-prone. SWO handles the complete planning pipeline:
- Validate parent-roll, usable-interval, and customer-order data
- Group orders that can share a production run
- Convert order quantities into individual lane demands
- Find a proven minimum-run allocation
- Calculate physical blade coordinates
- Generate exact spacer stacks
- Report used and remaining width for each interval
- Confirm that the required run lengths do not exceed the available parent-roll length
| Input | Fields | Constraints |
|---|---|---|
| Parent Roll | Roll ID, width, available length, material, film type, nominal thickness | Dimensions must be positive; film type must be LDF or HDC |
| Usable Intervals | Region ID, start coordinate, end coordinate | Coordinates are measured from DS; intervals must be unique, non-overlapping, and inside the parent-roll width |
| Customer Orders | Order ID, lane width, quantity, requested length, material, film type, thickness | Material, film type, and thickness must match the parent roll; every lane must fit inside at least one usable interval |
All dimensional calculations use Python Decimal values rather than binary floating-point values. This keeps widths, coordinates, and spacer combinations exact throughout the planning pipeline.
models.py defines immutable dataclasses for:
- Parent-roll metadata
- Usable intervals
- Customer orders
- Compatibility keys
- Compatible batches
- Lane demands
- Lane placements
- Interval allocations
- Production runs
- Complete slitting problems
Validation occurs when each model is constructed. Duplicate IDs, invalid dimensions, overlapping intervals, incompatible orders, and impossible lane widths are rejected before optimization begins.
Orders are grouped according to requested length.
Every lane in one slitting run receives the same longitudinal cut length. Orders with different requested lengths therefore cannot share the same run.
Material, film type, and nominal thickness compatibility are enforced against the parent roll before batching occurs.
Each requested unit becomes an individual LaneDemand.
For example, an order with a quantity of 14 produces 14 separately identifiable lane demands. Each lane retains:
- Its source order
- Its required width
- Its compatibility key
- A unique lane-demand ID
This converts the problem into a complete one-to-one assignment model rather than treating order quantity as an aggregate value.
Before building the exact optimization model, SWO runs a deterministic best-fit decreasing heuristic.
Lane demands are sorted from widest to narrowest. Each lane is placed into the existing run and interval combination that leaves the smallest amount of residual width.
If no existing interval can fit the lane, a new production run is created.
The heuristic provides:
- A known feasible production plan
- An upper bound on the required number of runs
- A limit on the number of CP-SAT candidate runs
- A warm-start solution hint for the exact optimizer
The exact production model is implemented using Google OR-Tools CP-SAT.
Because CP-SAT only supports integer-valued constraints, every Decimal lane width and interval capacity is converted using an exact common scale. The conversion raises an error rather than rounding a value that cannot be represented exactly.
The model uses two primary Boolean variable groups:
y[r] = 1 when candidate run r is active
x[l, r, i] = 1 when lane l is assigned
to interval i in run r
The model enforces the following constraints:
- Every lane must be assigned exactly once.
- Every lane must be assigned to one interval in one run.
- The total lane width assigned to an interval cannot exceed its capacity.
- A lane cannot be assigned to an inactive run.
- Every active run must contain at least one lane.
- Lower-index runs must be activated before higher-index runs.
- Runs are ordered by total assigned width to eliminate equivalent permutations.
The optimization objective is:
minimize Σ y[r]
This minimizes the total number of production runs.
A safe lower bound combines:
- Total required lane width
- Total usable width per run
- Fragmentation-aware lane-slot limits for each distinct lane-width threshold
If the lower bound equals the best-fit decreasing upper bound, the heuristic result is already proven optimal and the full CP-SAT search is skipped.
Otherwise, CP-SAT uses the heuristic allocation as a solution hint.
If the solver reaches its time limit with a feasible but unproven result, SWO raises an OptimizationTimeoutError rather than presenting the result as minimum-run optimal.
Each usable interval is positioned using the drive side, or DS, as the zero coordinate.
Lanes are placed contiguously from the DS boundary of each interval while retaining their optimized order.
Adjacent lanes share a blade coordinate. Any unused interval width remains between the final lane and the control side, or CS, boundary of the interval.
The final production-run layout merges and sorts all unique blade positions across every usable interval.
Consecutive blade coordinates define the required spacer segments from DS toward CS.
The available spacer catalog currently contains the following blocks:
- 1 mm
- 2 mm
- 5 mm
- 10 mm
- 20 mm
- 50 mm
- 1/16 inch
- 1/8 inch
- 1/4 inch
- 1/2 inch
- 1 inch
Spacer widths are converted into integer units using a resolution of:
1 unit = 0.0125 mm
An exact dynamic-programming search then finds a spacer combination that constructs the required distance using the minimum number of physical blocks.
If no exact combination exists, the planner reports the affected blade segment and indicates that a custom spacer may be required.
A separate largest-first greedy spacer selector remains available for comparison, but the generated production plan uses the exact search.
Each compatible batch consumes its requested length once for every generated production run.
For batch b:
required length for batch b
= requested length of batch b
× number of runs for batch b
The total required parent-roll length is:
total required length
= Σ requested_length[b] × run_count[b]
SWO compares this value against the parent roll's available length.
A plan is rejected if the required longitudinal length exceeds the available material, even when every transverse lane allocation is feasible.
frontend.py provides a tkinter interface for entering:
- Parent-roll metadata
- Any number of usable intervals
- Any number of customer orders
The frontend does not perform optimization directly. It constructs validated domain models and passes them into the backend pipeline.
Batching, lane conversion, optimization, blade generation, and spacer selection remain isolated in separate modules.
The generated report includes:
- Compatible batches
- Production-run counts
- Lane coordinates
- Blade positions
- Spacer stacks
- Interval utilization
- Total required length
- Remaining parent-roll length
For each compatible batch and production run, the report includes:
- Global run number
- Batch-local run number
- Source order IDs
- Lane-demand count
- Blade positions measured from DS
- Spacer-segment boundaries
- Spacer block types and quantities
- Lane start and end coordinates
- Used width for each usable interval
- Remaining width for each usable interval
- Total required parent-roll length
- Remaining parent-roll length
SWO currently minimizes the number of production runs.
It does not currently use secondary optimization objectives for:
- Blade movement between runs
- Production-run sequencing
- Changeover similarity
- Operator setup time
- Scrap minimization between equally optimal run-count solutions
Orders with different requested lengths are optimized independently.
The application generates a production plan but does not directly control a slitting machine or export machine-readable commands.
| File | Description |
|---|---|
slitting_backend/frontend.py |
tkinter input interface, plan orchestration, error handling, and formatted report generation |
slitting_backend/models.py |
Immutable domain models and cross-model validation |
slitting_backend/batching.py |
Groups orders by compatible requested length |
slitting_backend/lane_demand.py |
Expands order quantities into individual lane demands |
slitting_backend/heuristic.py |
Best-fit decreasing feasible solution, upper bound, and CP-SAT warm start |
slitting_backend/cp_sat_optimizer.py |
Exact minimum-run OR-Tools CP-SAT model |
slitting_backend/optimizer.py |
Simplified public optimizer imports |
slitting_backend/blade_positions.py |
Converts interval allocations into DS-referenced lane and blade coordinates |
slitting_backend/spacer_selection.py |
Exact spacer-stack selection and per-run spacer layouts |
legacy/ |
Earlier optimizer, sandbox, and integration-test implementations retained for reference |
Install OR-Tools:
pip install ortoolstkinter and the remaining dependencies are part of the Python standard library.
Some Linux distributions require tkinter to be installed separately:
sudo apt install python3-tkRun the desktop interface from the repository root:
python -m slitting_backend.frontendUse Load Demo to populate a complete example problem.
Select Generate Plan to run the optimizer and produce the lane, blade, and spacer report.