Skip to content

LP Transport Solver — User Guide

What Is the LP Transport Solver?

The LP Transport Solver is an alternative supply planning engine that minimizes total transport cost across your entire multi-echelon network. Unlike the default MRP engine (which follows a fixed source priority order), the LP solver evaluates all possible routes simultaneously and picks the cheapest combination.

Key Benefits

  • Lower transport costs: The solver finds the globally cheapest combination of BUY, TRANSFER, and REPAIR orders across all echelons
  • Unified multi-echelon: The entire supply chain (supplier → hub → regional WH → store) is optimized in a single pass — no sequential pass decomposition
  • Smarter repair decisions: The solver decides when to repair vs. scrap bad stock, respecting repair shop capacity
  • Same output format: Results appear in the same supply planning screens as the MRP engine

When to Use It

Situation Recommended Solver
You want the cheapest transport routing LP Transport
You need source priority enforcement (e.g. always repair before buy) MRP
You have a complex multi-echelon network with multiple path options LP Transport
You use MinMax or Period Order Quantity policies MRP
You want to model repair shop capacity as a constraint LP Transport
You rely on the consolidation window feature MRP

How to Enable the LP Solver

Step 1: Install Dependencies

The LP solver requires two additional Python packages:

pip install pyomo highspy

Step 2: Run the Database Migration

Execute the migration SQL on your tenant database:

-- From files/DDL/supply_solver_migration.sql
ALTER TABLE config_supply_scenario
  ADD COLUMN IF NOT EXISTS solver_type VARCHAR(20) DEFAULT 'mrp'
  CHECK (solver_type IN ('mrp', 'lp_transport'));

Step 3: Create or Update a Supply Scenario

Via the API:

// POST /api/supply/scenarios
{
  "name": "LP Transport Optimized",
  "description": "Minimizes transport cost across the full network",
  "solver_type": "lp_transport"
}

Or update an existing scenario:

// PUT /api/supply/scenarios/2
{
  "solver_type": "lp_transport"
}

Link the supply scenario to a pipeline via the Pipeline configuration screen. When the supply step runs, run_pipeline.py will automatically select the LP solver based on the solver_type column.

Step 5: Run Supply Planning

Trigger the supply run as usual (via the UI or API). The pipeline will use the LP solver for this scenario.


How It Differs from the MRP Engine

Source Priority

The MRP engine follows a strict priority order when sourcing: Repair → Return → Transfer → Build → Buy. The LP solver ignores this priority and picks the globally cheapest route.

Example: If a BUY route costs $5/unit and a TRANSFER route costs $8/unit, the MRP will choose TRANSFER if it has higher priority. The LP solver will always choose BUY.

Transfer Allocation

The MRP engine uses a 2-pass approach: 1. Run upstream WHs to generate BUY orders 2. Allocate WH inventory proportionally to stores via _allocate_transfers() 3. Run stores with the allocated transfers

The LP solver models the entire network as one optimization — TRANSFER quantities are first-class decision variables. The solver may choose to send more to one store and less to another if it reduces total cost.

Repair Dispatch

The MRP engine pre-computes repair returns as a fixed parameter. The LP solver treats repair dispatch as a decision: - When repair shop capacity is available, the solver may choose to repair more bad stock - When repair shop is full, the solver prioritizes items with the highest transport-cost savings - The solver may choose to scrap bad stock if holding cost exceeds repair benefit

Lot-Sizing

The MRP engine applies lot-sizing inline during sourcing. The LP solver produces continuous (fractional) quantities and applies lot-sizing as a post-processor: - snap (default): Rounds up to mult_qty, applies min_qty/max_qty bounds — same result as MRP - none: Keeps fractional quantities for analysis


Configuring Solver Parameters

Solver parameters are set via the supply scenario's param_overrides JSONB field:

// PUT /api/supply/scenarios/2/param-overrides
{
  "param_overrides": {
    "solver_time_limit": 600,
    "lot_sizing": "snap",
    "decompose_by_item": true,
    "decomposition_threshold": 5000,
    "safety_stock_penalty": 200.0,
    "shortage_penalty": 100.0,
    "repair_scrap_cost": 5.0
  }
}

See Supply Solver Parameters for the full parameter reference.


Interpreting Results

Orders

LP solver orders appear in the same PIPE_supply_orders table and are displayed in the same supply planning screens. You can identify LP-generated orders by their decision_reason field:

decision_reason Meaning
lp_optimal Route chosen by the LP solver as globally optimal
lp_repair Repair dispatch chosen by the LP solver
expedited Shortage cover generated by the expedite post-processor

Pegging

Pegging links (supply → demand tracing) are generated using proportional allocation. Each demand week is traced back to its supply sources (carry-over, orders, repair arrivals).

Exceptions

The LP solver generates the same exception types as the MRP engine:

Exception Type When It Appears
Shortage Projected inventory < 0 in any week
UnmetDemand Projected inventory < safety stock

Switching Back to MRP

To switch back to the MRP engine, update the scenario:

// PUT /api/supply/scenarios/2
{
  "solver_type": "mrp"
}

The next supply run will use the MRP engine. Previous LP results remain in the database until overwritten.