Transportation & Allocation Network (LP)
| Problem Class | Solver | Key APIs | Links |
|---|---|---|---|
| Linear Programming (LP) | HiGHS (default) | m.continuous(), m.constraint(), c, minimize, dot |
The transportation problem is one of the most fundamental network optimization models: determine how many units to ship from each supply origin (factory) to each destination (store) to minimize total shipping cost while respecting factory supply limits and meeting store demands.
This example demonstrates how to construct a 2D matrix of decision variables using m.continuous(factories, stores) and write aggregated constraints declaratively via dot() and m.constraint(c...).
Problem Inputs
We have 3 factories (Tokyo, Nagoya, Osaka) shipping to 4 regional stores (North, East, West, South):
| Factory \ Store | North ($/unit) | East ($/unit) | West ($/unit) | South ($/unit) | Supply Capacity |
|---|---|---|---|---|---|
| Tokyo | $4 | $2 | $7 | $8 | 120 units |
| Nagoya | $6 | $4 | $3 | $5 | 100 units |
| Osaka | $9 | $7 | $2 | $3 | 80 units |
| Store Demand | 70 units | 90 units | 60 units | 60 units | Total: 280 / 300 |
Mathematical Formulation
Let be the quantity shipped from factory to store , and be the unit shipping cost.
Implementation in WaSHI
typescript
import { Model, sum, dot, c, minimize } from "@ohtaman/washi";
const factories = ["Tokyo", "Nagoya", "Osaka"] as const;
const stores = ["North", "East", "West", "South"] as const;
const shippingCost = {
Tokyo: { North: 4, East: 2, West: 7, South: 8 },
Nagoya: { North: 6, East: 4, West: 3, South: 5 },
Osaka: { North: 9, East: 7, West: 2, South: 3 },
};
const supplies = { Tokyo: 120, Nagoya: 100, Osaka: 80 };
const demands = { North: 70, East: 90, West: 60, South: 60 };
async function runTransportation() {
const m = new Model("TransportationNetwork");
// 1. Create 2D continuous variables: ship[factory][store] >= 0
const ship = m.continuous([...factories], [...stores], { lb: 0 });
// 2. Objective: Minimize total shipping cost across all routes via 2D dot product
m.objective(minimize(dot(shippingCost, ship)));
// 3. Supply constraints (row sums): outgoing from f <= supplies[f]
for (const f of factories) {
m.constraint(
c`${sum(stores, (s) => ship[f][s])} <= ${supplies[f]}`,
`supply_${f}`
);
}
// 4. Demand constraints (column sums): incoming to s >= demands[s]
for (const s of stores) {
m.constraint(
c`${sum(factories, (f) => ship[f][s])} >= ${demands[s]}`,
`demand_${s}`
);
}
const status = await m.solve();
console.log(`Status: ${status}, Total Shipping Cost: $${m.objectiveValue}`);
for (const f of factories) {
const routes = stores
.map((s) => `${s}:${Math.round(ship[f][s].value ?? 0)}`)
.join(", ");
console.log(` ${f.padEnd(7)} -> ${routes}`);
}
}
runTransportation();