DNA //evolutions

Manufacturing Planning via Pickup & Delivery

On-demand production planning inside the route optimizer

JOpt.TourOptimizer extends classical pickup and delivery (PND) beyond fixed-quantity transportation. Through its FlexLoad system, the optimizer can decide how much a production site should produce, which site should produce it, and when the goods need to be ready. This turns the PND module into a manufacturing planning tool: production quantities are not predetermined by the user but optimized alongside routing, scheduling, and capacity constraints.

This capability is, to our knowledge, unique among route optimization engines. Neither Google OR-Tools, OptaPlanner/Timefold, nor other common VRP solvers offer a built-in mechanism where the optimizer dynamically determines production quantities as part of the routing solution. In these engines, supply quantities must be fixed before optimization begins. JOpt does not have this limitation.


Overview


Why manufacturing planning inside a route optimizer?

In many real-world supply chains, production and delivery are tightly coupled. A bakery does not want to produce bread that nobody ordered. A pizza restaurant chain needs to decide which branch prepares which order. A pharmaceutical distributor needs to balance production across facilities while meeting delivery windows.

Traditionally, these decisions are made in two separate steps: first, a production planner decides quantities per facility, then a route optimizer plans the deliveries. This separation leads to suboptimal results because production decisions are made without knowledge of routing costs, and routing decisions are made without flexibility on supply.

JOpt eliminates this separation. The optimizer considers production quantities, facility assignments, routing, time windows, and capacity constraints as a single problem. The result is a plan where production and delivery are jointly optimal, not separately acceptable.

How it works: FlexLoads

The key mechanism is the SupplyFlexLoad. Unlike a SimpleLoad (where the user defines a fixed quantity), a SupplyFlexLoad allows the optimizer to determine the supply quantity at a given node.

In practice, this means:

  • A node is modeled as a production site (factory, bakery, warehouse).
  • The node carries a SupplyFlexLoad with a load type (e.g. "Bread") but no fixed quantity.
  • The optimizer decides how many units this node should produce, based on what is globally optimal for routing, capacity, time windows, and demand.
  • The production quantity appears in the optimization result alongside the route schedule.

The user defines what can be produced and where. The optimizer decides how much and distributes it across the network.

For a full explanation of all PND load types, see the Pickup & Delivery feature guide.

The bakery example

A bakery company has two production sites: Bakery Aachen and Bakery Cologne. Each production site has one delivery driver (Resource) and a truck with a maximum capacity of 20 bread trays. Several supermarkets in the region need bread deliveries, each with a defined demand.

Bakery chain PND setup

Figure 1: Two bakeries, multiple supermarkets with demand, and the question: how much should each bakery produce?

The company does not want to overproduce (waste) or underproduce (missed demand). Instead of deciding production quantities manually, two SupplyFlexLoad nodes are added, one near each bakery. These nodes act as factories that can produce bread. The optimizer determines the optimal production quantity for each factory based on total demand, truck capacity, route distances, and time windows.

Bakery chain PND result

Figure 2: Optimized result. Bakery Aachen produces 10 trays, Bakery Cologne produces 17 trays. The optimizer made the production decision.

The result is a complete plan: how much each bakery produces, which truck delivers to which supermarket, and in what order. Production planning and route optimization are solved simultaneously.

Implementation sketch

A SupplyFlexLoad is created with a load ID and attached to a NodeDepot at the production node:

// Create a supply flex load for bread production
ILoad breadSupply = new SupplyFlexLoad("Bread", 20, true);

// Create a node depot and add the flex load
INodeDepot bakeryDepot = new SimpleNodeDepot("BakeryDepot");
bakeryDepot.add(breadSupply);

// Attach to the bakery node
bakeryNode.setNodeDepot(bakeryDepot);

The second parameter (20) defines the maximum capacity the SupplyFlexLoad can provide. The third parameter (true) enables fuzzy behavior, allowing partial supply. The optimizer will determine the actual quantity during optimization.

On the demand side, supermarkets carry standard SimpleLoads with their request:

ILoad breadRequest = new SimpleLoad("Bread", 5, true, true);

INodeDepot supermarketDepot = new SimpleNodeDepot("SupermarketDepot");
supermarketDepot.add(breadRequest);

supermarketNode.setNodeDepot(supermarketDepot);

The optimizer matches supply to demand across the entire network, deciding which bakery produces how much and which truck delivers to which supermarket.

Dynamic production planning inside a route optimizer is a hard problem. The optimizer must simultaneously decide quantities, assignments, and routes. This works in JOpt because the engine uses a multi-phase pipeline with dedicated operators for PND problems:

  1. Construction phase. The starting solution allocates demands to resources and estimates initial supply quantities using savings-based heuristics or clustering.
  2. Simulated annealing. The solution is refined through neighborhood moves that include both route changes and supply adjustments. FlexLoad quantities are modified alongside node ordering.
  3. Genetic algorithm with dedicated PND operators. The genetic algorithm uses both random operators (mutations and crossings, as in nature) and intelligent operators that evaluate solutions before and after modification. For PND problems, these operators understand goods tracking: they can adjust production quantities, swap supply assignments between facilities, and rebalance loads across routes. This is not a generic constraint solver trying random moves. The operators are specifically designed to explore the production-routing search space efficiently.
  4. Feasibility tracking. Throughout all phases, JOpt tracks goods in vehicles at every point in the route. Overloading and underloading are detected and penalized through cost, giving the optimizer a strong incentive to find balanced solutions while still allowing it to explore intermediate states that temporarily violate capacity. This cost-based approach is deliberate: it gives the genetic operators the freedom to rearrange production quantities and delivery assignments without being locked out of promising regions of the search space.

Because the genetic algorithm evaluates many solution candidates in parallel and the dedicated operators make intelligent production-aware moves, the optimizer converges to good production plans even in large instances with dozens of facilities and hundreds of delivery points.

Other FlexLoad types

Manufacturing planning is one application of the FlexLoad family. JOpt provides several FlexLoad types for different scenarios:

FlexLoad typeWhat the optimizer decidesTypical use case
SupplyFlexLoadHow much a node producesFactory output planning, bakery production
RequestFlexLoadHow much a node requestsFlexible demand, partial fulfillment
MixedFlexLoadWhether a node supplies or requests, and how muchWarehouse buffers, reload/unload points
TimedSupplyFlexLoadProduction quantity + delivery SLAPizza delivery chains, time-critical production

These types can be combined in the same optimization. A scenario might include fixed deliveries (SimpleLoad), flexible production (SupplyFlexLoad), warehouse buffers (MixedFlexLoad), and timed delivery promises (TimedSupplyFlexLoad) all in one problem instance.

Example on GitHub: PNDTimedPizzaDeliveryExample.java (timed supply flex load with SLA).

Split delivery optimization

The FlexLoad concept extends further into split delivery optimization (SDO). In many real-world scenarios, a single large order does not have to be delivered in one piece. A supermarket ordering 50 pallets of goods might accept two deliveries of 25 on different days or from different trucks. A construction site receiving building materials might have multiple unloading bays at different positions on the site. Splitting a delivery can dramatically improve overall route efficiency, vehicle utilization, and schedule feasibility.

JOpt supports this through coupled FlexLoads. Multiple nodes, each with their own NodeDepot and loads, are coupled together. When the optimizer increases the load at one node, the coupled node's load decreases by the same amount. This mechanism allows a single demand to be split across multiple delivery points, each of which acts as a fully independent node with its own location, time window, and visit duration.

The user can define the maximum number of splits allowed for a single load. Each split node can be placed at a different geographical position if the delivery scenario requires it. Optionally, the visit duration at each split node can be defined as a function of the delivered quantity, so that a partial delivery of 10 pallets takes less time than a full delivery of 50. This makes the model realistic: smaller deliveries are faster to unload.

The advantage is significant. Classical VRP solvers treat each delivery as an atomic unit: one customer, one visit, one fixed quantity. If a single large order blocks an entire truck for a full shift, the rest of the route suffers. With split delivery optimization, the optimizer can distribute that order across vehicles, shifts, or partial visits in a way that is globally optimal. It reduces vehicle overload situations, improves capacity utilization across the fleet, and opens scheduling options that are simply invisible to solvers without this capability.

Technically, the mechanism is called CoupledRequestFlexLoad. It builds on the same FlexLoad infrastructure used for manufacturing planning, reusing the dedicated PND operators in the genetic algorithm. The coupling is bidirectional: the optimizer explores different split ratios as part of its search, evaluating many candidate distributions through the same multi-phase pipeline (construction, simulated annealing, genetic search) that handles all other PND decisions.

CoupledRequestFlexLoads can be combined, for example, with SupplyFlexLoad nodes. This is particularly powerful for multi-day scenarios. When the optimizer splits a delivery across different days, the resource starts empty at its base each morning and needs to load exactly the right quantity before visiting the split delivery node. A SupplyFlexLoad at a warehouse or production site provides this: the optimizer loads 10 units on the first day and 20 on the second, matching the split it has chosen. For example, a customer requests 30 pallets. The optimizer decides to split this into 10 on day one and 20 on day two. On day one, the truck starts empty at the base, loads 10 at the SupplyFlexLoad, and serves the CoupledRequestFlexLoad for 10. On day two, it loads 20 and delivers the remainder. Both the split ratio and the loading quantities are determined by the optimizer as a single coordinated decision.

What other engines cannot do

We surveyed the most widely used open-source VRP solvers to understand how they handle dynamic supply decisions.

Google OR-Tools provides a solid routing library with support for capacitated VRP, time windows, and standard pickup/delivery pairs. However, all quantities are fixed before optimization. There is no mechanism for the solver to decide how much a node should supply. Production planning is not part of the model.

OptaPlanner / Timefold uses a score-based constraint satisfaction approach. It handles standard VRP well, but its PND model operates with fixed quantities and fixed pickup-delivery pairs. To our best knowledge, there is no built-in mechanism for the solver to dynamically determine production quantities or adjust supply as part of the optimization process. Achieving this would require the user to model production decisions as additional planning variables and write custom constraint logic on top of the VRP model. The engine does not provide first-class support for goods creation, flexible supply, or coupled load balancing within the routing search.

The fundamental difference: In JOpt, production quantities are planning variables that the optimizer controls. In other engines, they are input data that must be fixed before optimization starts. This means JOpt can answer questions that other engines cannot even formulate:

  • How much should each factory produce?
  • Which production site should serve which customer?
  • What is the jointly optimal production and delivery plan?
  • Should a large order be split across multiple vehicles or visits, and if so, in what ratio?

These are not routing questions. They are production and distribution planning questions solved inside a route optimizer. This integration is possible because JOpt has dedicated genetic operators for PND that understand goods creation, goods tracking, load splitting, and load balancing as first-class concepts in the search process.


Closing Words

Manufacturing planning via PND is a powerful extension of JOpt.TourOptimizer's pickup and delivery system. It bridges the gap between production planning and route optimization, solving both as a single integrated problem. Split delivery optimization takes this further by allowing the optimizer to distribute individual orders across multiple visits, vehicles, or time slots for globally better solutions.

For simpler PND scenarios (fixed deliveries, fixed pickups, standard capacity tracking), see the Pickup & Delivery feature guide. For the full list of PND examples, visit the PND examples on GitHub.


Authors

A product by dna-evolutions ©