Learn minimum cost flow optimization for slotting problems, including network flow theory, mathematical formulation, and practical implementation with OR-Tools. Master resource allocation across time slots, capacity constraints, and cost structures.

This article is part of the free-to-read Machine Learning from Scratch
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Minimum Cost flow Slotting
The Minimum Cost flow (MCF) problem finds the most cost-effective way to transport a specified amount of flow through a network. This problem appears in many real-world applications, from supply chain logistics and telecommunications routing to resource allocation and scheduling. The MCF problem can model complex network structures while remaining computationally tractable, making it useful in operations research and optimization.
In the context of slotting, the MCF problem helps determine optimal resource allocation across time slots, capacity constraints, and cost structures. For example, in workforce scheduling, we might need to assign employees to different time slots while minimizing costs and respecting availability constraints. In manufacturing, we might need to schedule production across different machines and time periods while minimizing operational costs. The MCF formulation provides a mathematically rigorous framework for solving these allocation problems efficiently.
Unlike simpler optimization approaches that might use greedy heuristics or linear programming, the MCF problem can handle complex network structures with multiple sources, sinks, and intermediate nodes. This makes it particularly valuable for real-world problems where resources flow through multiple stages or where there are complex interdependencies between different allocation decisions. The network structure also allows for natural modeling of capacity constraints, time windows, and cost structures that reflect real operational constraints.
Advantages
The Minimum Cost flow approach offers several advantages for slotting problems. First, it provides a mathematically rigorous framework that guarantees optimal solutions when feasible solutions exist. Unlike heuristic approaches that might find good but suboptimal solutions, the MCF formulation ensures that we find the optimal allocation of resources across the network. This optimality guarantee matters in applications where even small improvements in efficiency can lead to significant cost savings.
Second, the MCF problem is computationally efficient and can handle large-scale problems with thousands of nodes and edges. Modern optimization algorithms, particularly those based on network flow theory, can solve MCF problems very quickly, often in milliseconds or seconds even for complex networks. This computational efficiency makes the approach suitable for real-time applications where decisions need to be made quickly, such as dynamic resource allocation or real-time scheduling systems.
Third, the network structure of the MCF problem provides excellent modeling flexibility. We can easily incorporate various types of constraints, including capacity limits, time windows, precedence relationships, and cost structures. The network representation also makes it intuitive to understand and visualize the problem structure, which is valuable for both model development and communication with stakeholders who need to understand the optimization logic.
Disadvantages
Despite its strengths, the Minimum Cost flow approach has some limitations that practitioners should consider. The most significant limitation is that it requires the problem to be formulated as a network flow problem, which may not always be natural or intuitive for all slotting applications. Some real-world constraints, such as complex precedence relationships or non-linear cost structures, may be difficult to model within the network flow framework.
Another limitation is that the MCF problem assumes that flow can be split and combined freely at nodes, which may not always reflect real-world constraints. For example, in workforce scheduling, we might need to ensure that employees work complete shifts rather than being split across multiple time periods. While these constraints can sometimes be handled through problem transformation, they can make the formulation more complex and less intuitive.
Finally, the MCF approach may struggle with problems that have very tight constraint sets or where finding any feasible solution is difficult. In such cases, the solver might need to explore a large portion of the solution space, leading to longer computation times. Additionally, if the problem is infeasible, the MCF solver will simply report that no solution exists, without providing guidance on which constraints might be relaxed to achieve feasibility.
Formula
To solve the Minimum Cost flow problem mathematically, we need to translate our intuitive understanding of networks, flows, and costs into a precise mathematical framework. This process reveals why each component is needed and how they work together to create a solvable optimization problem.
The Intuition: What Are We Really Trying to Do?
Before diving into mathematical notation, let's clarify what we're trying to achieve. Imagine you're managing a supply chain: you have factories producing goods, warehouses storing them, and markets demanding them. You need to route products through this network in a way that:
- Satisfies all demands - Every market gets exactly what it needs
- Respects all capacities - You can't ship more than your trucks, pipelines, or facilities can handle
- Minimizes total cost - Among all feasible routing strategies, you want the cheapest one
The Minimum Cost flow problem formalizes this intuition. But to solve it mathematically, we need to be precise about what "network," "flow," and "cost" actually mean in mathematical terms.
Building the Network: Nodes and Edges
The first step is representing our problem as a directed graph, a mathematical structure that captures the relationships in our system. Graphs naturally model connections: which locations can send to which other locations, which resources can flow through which pathways.
We define our network as a directed graph where:
- : The directed graph representing our network
- : The set of nodes (vertices) - these represent locations, resources, time periods, or any entities between which flow can occur
- : The set of directed edges (arcs) - these represent the pathways through which flow can travel, with direction indicating the allowed flow direction
The directed nature matters: a factory can ship to a warehouse, but the reverse might not make physical sense. The graph structure captures these one-way relationships naturally.
Characterizing Nodes: Supply, Demand, and Transshipment
Not all nodes play the same role in our network. Some nodes are sources - they generate flow (like factories producing goods). Others are sinks - they consume flow (like markets demanding products). Still others are intermediate nodes - they neither generate nor consume, but simply pass flow through (like warehouses or distribution centers).
We capture this distinction mathematically through a supply value for each node :
where:
- : Node index, where (ranges over all nodes in the network)
- : Supply value at node (units of flow)
- If : Node is a supply node (source) that generates units of flow
- If : Node is a demand node (sink) that requires units of flow
- If : Node is a transshipment node that neither generates nor consumes net flow
Why do we need this distinction? Because all flow needs to originate somewhere and terminate somewhere. The supply values tell us exactly how much flow needs to enter the network (from sources) and how much needs to exit (to sinks). This is the mathematical way of saying "we need to satisfy all demands using available supplies."
Characterizing Edges: Capacity and Cost
Just as nodes have different roles, edges have different properties. Each edge represents a pathway from node to node , and we need to describe two key properties:
where:
- : Directed edge from node to node , where
- : Source node of the edge (where flow originates)
- : Destination node of the edge (where flow terminates)
-
Capacity : The maximum amount of flow that can pass through edge . This represents physical or operational limits - a truck can only carry so much, a pipeline has a maximum throughput, a worker can only handle so many tasks per hour. Units: same as flow units.
-
Cost : The cost per unit of flow sent through edge . This captures the expense, time, or penalty associated with using this particular pathway. Units: cost per unit of flow.
Why do we need both? Capacity constraints prevent us from making physically infeasible allocations (you can't ship 1000 units through a pipeline that can only handle 100). Cost values allow us to distinguish between different feasible pathways. Even if multiple routes can handle the flow, we want to choose the cheapest one.
Decision Variables: What Are We Actually Choosing?
Now we come to the heart of the optimization problem: what decisions are we making? In the Minimum Cost flow problem, our decision is simple but powerful: for each edge in the network, we need to decide how much flow to send through it.
We represent these decisions as decision variables for each edge :
where:
- : Decision variable representing the amount of flow sent through edge (units of flow)
- : Edge from node to node , where
- : "For all" - this constraint applies to every edge in the network
The non-negativity constraint () is needed because flow can only go in the direction of the edge. If we wanted to allow reverse flow, we would need a separate edge pointing in the opposite direction.
These decision variables are what the optimization algorithm will determine. Once we've set up our constraints and objective function, the solver will find the values of all that minimize cost while satisfying all constraints.
The Objective: Minimizing Total Cost
Our goal is to find the cheapest way to route flow through the network. But what does "cheapest" mean mathematically?
The total cost of a solution is the sum of costs across all edges, where each edge's contribution is its unit cost multiplied by the amount of flow we send through it. This gives us our objective function:
where:
- : Minimization operator - we seek to minimize the total cost
- : Sum over all edges in the edge set
- : Unit cost per flow on edge (cost per unit of flow)
- : Flow amount on edge (units of flow)
- : Total cost contribution from edge (cost units)
This formula assumes that costs are linear in the amount of flow. Sending 10 units through an edge costs exactly 10 times as much as sending 1 unit. This linearity makes the problem computationally tractable, and it's a reasonable assumption for many real-world scenarios (though not all; some problems require non-linear cost functions, which would need different solution approaches).
The minimization operator tells us we're seeking the solution that makes this sum as small as possible, subject to all the constraints we're about to define.
Flow Conservation: The Fundamental Law
We need to ensure that flow is conserved throughout the network. Flow doesn't magically appear or disappear at nodes. This conservation principle expresses physical reality: what goes into a node needs to come out (or be consumed), and what comes out needs to have come in (or been generated).
For each node , we write the flow conservation constraint:
Let's visualize what this means at a single node:
This visualization shows how flow conservation works at a single node. Blue arrows represent flow entering the node, green arrows represent flow leaving the node. The equation Flow Out - Flow In = Supply must hold for each node type.
where:
- : Node index, where (this constraint applies to every node)
- : Sum of all flow leaving node (flow on edges that start at )
- : Index over all nodes such that edge exists
- : Flow amount on edge leaving node
- : Sum of all flow entering node (flow on edges that end at )
- : Index over all nodes such that edge exists
- : Flow amount on edge entering node
- : Supply value at node (positive for sources, negative for sinks, zero for transshipment)
Let's break this down carefully:
- The first sum represents all flow leaving node (flow on edges that start at )
- The second sum represents all flow entering node (flow on edges that end at )
- Their difference equals , the supply at node
Why is this the right constraint? Consider what happens at different types of nodes:
-
Supply nodes (): More flow leaves than enters. The difference equals the supply generated at this node. For example, if a factory generates 10 units, then , meaning 10 more units leave than enter.
-
Demand nodes (): More flow enters than leaves. The difference is negative, matching the negative demand. For example, if a market needs 10 units, then , meaning 10 more units enter than leave.
-
Transshipment nodes (): Flow in equals flow out. These nodes simply pass flow through without generating or consuming any net amount.
This single constraint type elegantly handles all three node types, ensuring that flow is properly balanced throughout the entire network. Without this constraint, we could have solutions where flow appears or disappears at nodes, which would be physically meaningless.
Capacity Constraints: Respecting Physical Limits
While flow conservation ensures flow is balanced, it doesn't prevent us from trying to send more flow through an edge than it can physically handle. We need capacity constraints to enforce the limits we defined for each edge:
where:
- : Flow amount on edge (units of flow)
- : Capacity (maximum flow) allowed on edge (units of flow)
- : "For all edges" - this constraint applies to every edge in the network
- : Non-negativity constraint (flow cannot be negative)
- : Capacity constraint (flow cannot exceed the edge capacity)
This constraint specifies that the flow on edge should be:
- At least zero (we already had this from the non-negativity of decision variables)
- At most (the capacity limit we defined for this edge)
Why is this necessary? Without capacity constraints, the optimal solution might try to route all flow through a single cheap edge, even if that edge can only handle a fraction of the required flow. Capacity constraints force the solver to distribute flow across multiple pathways, respecting the physical realities of the network.
Together with flow conservation, capacity constraints ensure that our solution is not just mathematically valid, but also physically feasible.
The Complete Mathematical Formulation
Now we can assemble all these pieces into the complete Minimum Cost flow problem:
Objective Function:
Subject to:
Flow Conservation Constraints:
Variable Definitions:
- : Directed graph with node set and edge set
- : Node indices, where
- : Directed edge from node to node , where
- : Decision variable - flow amount on edge (units of flow)
- : Unit cost per flow on edge (cost per unit of flow)
- : Capacity (maximum flow) on edge (units of flow)
- : Supply value at node (positive for sources, negative for sinks, zero for transshipment)
- : "For all" quantifier
This formulation is a linear programming problem, a special type of optimization problem where both the objective function and all constraints are linear in the decision variables. This linearity allows us to use highly efficient specialized algorithms that can solve even large-scale problems quickly.
Why This Formulation Works: Key Mathematical Properties
The Minimum Cost flow formulation has several beautiful mathematical properties that make it both theoretically elegant and practically useful:
-
Linear Programming Structure: The MCF problem is a special case of linear programming with a particularly nice structure. The network topology creates a constraint matrix with special properties (totally unimodular), which enables the use of highly efficient specialized algorithms that are much faster than general-purpose linear programming solvers.
-
Integrality Property: If all supplies , demands, and capacities are integers, then there exists an optimal solution where all flows are also integers. This matters for practical applications where fractional allocations don't make sense; you can't ship 3.7 trucks or assign 2.3 workers to a shift. The integrality property guarantees that we'll get whole-number solutions automatically, without needing to add integer constraints (which would make the problem much harder to solve).
-
Duality and Economic Interpretation: The MCF problem has a natural dual interpretation involving node potentials (often interpreted as prices). The dual variables tell us the marginal value of increasing supply or capacity at different nodes, providing valuable economic insights. If the dual variable at a demand node is high, it means that location is a bottleneck - increasing supply there would significantly reduce total cost.
These properties aren't just mathematical curiosities - they're what make the Minimum Cost flow problem both solvable and interpretable in real-world applications. The linear structure enables fast computation, the integrality property ensures practical solutions, and the duality provides insights for decision-makers.
Visualizing Minimum Cost flow
Let's create visualizations to understand how the Minimum Cost flow problem works in practice. We'll start by setting up the necessary libraries and creating a simple example.
Now let's solve this network using OR-Tools and visualize the optimal flow:
Example
Let's work through a concrete example that brings together all the concepts we've discussed. We'll see how the mathematical formulation translates into a real optimization problem, and we'll trace through the logic to understand why the optimal solution takes the form it does.
Setting Up the Problem: A Supply Chain Scenario
Imagine you're managing a supply chain with the following structure:
- Factory (Node 0): Produces 10 units of product (a supply node with )
- Warehouse (Node 1): A storage facility that neither produces nor consumes (a transshipment node with )
- Distribution Center (Node 2): Another intermediate facility (a transshipment node with )
- Market (Node 3): Requires exactly 10 units to satisfy demand (a demand node with )
The network has five possible shipping routes, each with different capacities and costs:
- Factory → Warehouse: Can handle up to 15 units, costs 4 per unit
- Factory → Distribution: Can handle up to 8 units, costs 6 per unit
- Warehouse → Market: Can handle up to 10 units, costs 2 per unit
- Distribution → Market: Can handle up to 12 units, costs 3 per unit
- Warehouse → Distribution: Can handle up to 5 units, costs 1 per unit (a shortcut route)
Notice that we have multiple pathways from the factory to the market. Our goal is to find the cheapest way to route all 10 units from the factory to the market while respecting capacity limits.
Here's a visual representation of this network:
This diagram shows the network structure we'll analyze. The Factory (node 0) supplies 10 units, the Market (node 3) demands 10 units, and the Warehouse and Distribution Center are transshipment nodes. Each edge is labeled with its unit cost and capacity limit.
Translating to Mathematical Formulation
Step 1: Define Decision Variables
We need to decide how much flow to send through each of the five edges:
- = flow from Factory to Warehouse
- = flow from Factory to Distribution
- = flow from Warehouse to Market
- = flow from Distribution to Market
- = flow from Warehouse to Distribution
Each of these should be non-negative (we can't send negative flow), and we'll determine their optimal values through optimization.
Step 2: Construct the Objective Function
Our goal is to minimize total cost. The objective function follows the general form:
For our specific network, this expands to:
Substituting the unit costs:
where:
- : Unit cost for Factory → Warehouse
- : Unit cost for Factory → Distribution
- : Unit cost for Warehouse → Market
- : Unit cost for Distribution → Market
- : Unit cost for Warehouse → Distribution
Each term represents the cost contribution from one edge: the unit cost multiplied by the flow amount. Notice that the Warehouse → Distribution route () has the lowest unit cost (1), which might make it attractive if we can use it effectively.
Step 3: Apply Flow Conservation Constraints
Flow conservation ensures that flow is balanced at each node. For each node , we apply the general form:
Let's work through each node:
-
Factory (Node 0): This is a supply node with . Applying the flow conservation constraint:
Simplified:
This says: all flow leaving the factory (the two outgoing edges) must equal the 10 units the factory produces. There are no incoming edges to the factory, so this is simply a supply constraint.
-
Warehouse (Node 1): This is a transshipment node with . Applying the flow conservation constraint:
Simplified: , or equivalently
This says: all flow entering the warehouse (from the factory) must equal all flow leaving (to the market and to the distribution center). The warehouse neither creates nor destroys flow.
-
Distribution (Node 2): This is also a transshipment node with . Applying the flow conservation constraint:
Simplified: , or equivalently
This says: flow entering the distribution center (from the factory and from the warehouse) must equal flow leaving (to the market).
-
Market (Node 3): This is a demand node with . Applying the flow conservation constraint:
Simplified: , or equivalently
This says: all flow entering the market (from the warehouse and from the distribution center) must equal the 10 units of demand.
Step 4: Apply Capacity Constraints
Each edge has a maximum capacity that cannot be exceeded. The general form is:
For our specific network, this gives us:
- (Factory → Warehouse)
- (Factory → Distribution)
- (Warehouse → Market)
- (Distribution → Market)
- (Warehouse → Distribution)
where:
- : Capacity of Factory → Warehouse edge
- : Capacity of Factory → Distribution edge
- : Capacity of Warehouse → Market edge
- : Capacity of Distribution → Market edge
- : Capacity of Warehouse → Distribution edge
These constraints prevent us from overloading any shipping route.
Finding the Optimal Solution
Now we have a complete optimization problem. Let's reason through what the optimal solution should look like, then verify with computation.
Intuitive Reasoning:
The cheapest route from Factory to Market is Factory → Warehouse → Market, with total cost per unit. However, the Warehouse → Market edge has capacity 10, which is exactly our demand. So we could send all 10 units this way... but wait, let's check if there's a better strategy.
Actually, we have an interesting option: the Warehouse → Distribution route costs only 1 per unit, and Distribution → Market costs 3 per unit. So Factory → Warehouse → Distribution → Market costs per unit, which is more expensive than the direct Warehouse → Market route.
However, the Factory → Distribution route costs 6 per unit, and Distribution → Market costs 3 per unit, for a total of per unit. This is the most expensive direct path.
The optimal strategy balances these trade-offs. Since Warehouse → Market has capacity 10 (exactly our demand), we could use it fully. But we also need to consider whether splitting flow might be beneficial.
Finding the Optimal Solution:
Now we have a complete optimization problem. Let's think through the solution strategy:
Strategy 1: Use the cheapest path exclusively
The path Factory → Warehouse → Market has total cost per unit calculated as:
If we send all 10 units this way:
- (within capacity )
- (exactly at capacity )
Total cost calculation:
This is feasible and seems attractive. But is it optimal?
Strategy 2: Split between two direct paths
We could send some units Factory → Warehouse → Market and some Factory → Distribution → Market:
- Factory → Warehouse → Market: cost per unit = cost units per flow unit
- Factory → Distribution → Market: cost per unit = cost units per flow unit
Since the first path is cheaper, we'd want to use it to full capacity (10 units), leaving 0 for the second path. This gives us Strategy 1 again.
Strategy 3: Use the shortcut route
What about using the Warehouse → Distribution shortcut? The path Factory → Warehouse → Distribution → Market has cost per unit:
This is more expensive than the direct Warehouse → Market route (cost 6 per unit). So this doesn't help.
The Optimal Solution:
By solving the optimization problem (either algebraically or using a solver), we find that Strategy 1 is optimal:
- (all 10 units: Factory → Warehouse)
- (all 10 units: Warehouse → Market)
- , , (unused routes)
Total Cost Calculation:
The total cost is computed using the objective function:
Why This Makes Sense:
This solution is optimal because:
- The cheapest path (Factory → Warehouse → Market) has sufficient capacity to handle all demand
- Using it exclusively minimizes cost at 6 per unit
- All alternative paths cost more (9 per unit for Factory → Distribution → Market, 8 per unit if we use the shortcut)
The key insight is that when the cheapest path has sufficient capacity, we should use it exclusively. The solver would only split flow across multiple paths if:
- No single path has enough capacity for all demand, OR
- There are additional constraints (like minimum flow requirements) that force splitting, OR
- The cost structure makes splitting beneficial (which doesn't happen in this example)
Verifying the Constraints:
Let's verify this solution satisfies all constraints:
Flow Conservation Constraints:
For each node , we verify that :
-
Factory (Node 0): Flow out - Flow in = Supply
-
Warehouse (Node 1): Flow out - Flow in = Supply
-
Distribution (Node 2): Flow out - Flow in = Supply
-
Market (Node 3): Flow out - Flow in = Supply
For each edge , we verify that :
- :
- :
- : (at capacity)
- :
- :
All constraints are satisfied, and we've achieved the minimum possible cost. This example illustrates how the mathematical formulation guides us to the optimal solution systematically, even when the problem seems simple enough to solve by intuition.
Implementation in OR-Tools
Now that we understand the mathematical formulation, let's see how to implement it in practice. We'll use OR-Tools, Google's open-source optimization library, which provides efficient solvers specifically designed for network flow problems.
Why OR-Tools?
OR-Tools is an excellent choice for Minimum Cost flow problems because:
-
Specialized Algorithms: The
SimpleMinCostFlowsolver uses highly optimized algorithms (like the successive shortest path algorithm or cost scaling) that are much faster than general-purpose linear programming solvers for network flow problems. -
Ease of Use: The API directly maps to our mathematical formulation - we specify nodes, edges, capacities, costs, and supplies, and the solver handles the rest.
-
Robustness: OR-Tools has been battle-tested on real-world problems and handles edge cases (infeasible problems, numerical issues) gracefully.
-
Open Source: Free to use and well-documented, making it accessible for both learning and production applications.
Mapping Mathematics to Code
The key insight is that our mathematical formulation translates directly into OR-Tools API calls:
- Edges →
add_arc_with_capacity_and_unit_cost(start_node, end_node, capacity, cost) - Node Supplies →
set_node_supply(node, supply) - Decision Variables → Automatically handled by the solver (we query the results)
- Objective Function → Automatically minimized by the solver
- Constraints → Automatically enforced by the solver
The solver takes care of all the constraint enforcement and optimization - we just need to specify the problem structure.
Building a Reusable Solver Function
Let's create a function that encapsulates the solution process, making it easy to solve different MCF problems. This function will handle network construction, solving, and solution extraction:
Now let's display the results from the supply chain example:
The solver found an optimal solution with a total cost of 60 cost units. This matches our mathematical analysis from the Example section, where we determined that routing all 10 units through Factory → Warehouse → Market (cost 6 per unit) is optimal. The solution shows that edges (0,1) and (1,3) carry the full flow of 10 units each, while other edges remain unused. This makes operational sense: the cheapest path has sufficient capacity to handle all demand, so there's no need to split flow across multiple routes. The unused edges (0,2), (1,2), and (2,3) have zero flow, indicating they're not part of the optimal solution.
A More Complex Example: Time Slotting
The power of the Minimum Cost flow formulation becomes even clearer when we tackle more complex problems. Let's consider a time slotting problem where we need to allocate resources across multiple time periods to complete various tasks. This demonstrates how MCF can model problems with multiple stages and complex routing requirements.
The key insight is that we can model time as a dimension in our network: resources flow through time slots, and then through tasks, creating a multi-stage network structure.
Now let's display the results from the time slotting example:
The solver found an optimal allocation that routes resources through time slots to tasks while minimizing total cost. The solution balances multiple competing factors: resource capacity limits prevent over-allocation, time slot availability constrains when work can be done, and task requirements ensure all work is completed. Notice that the cost structure (increasing costs for later time slots) encourages the solver to prefer earlier time slots when possible, which aligns with operational preferences for completing work sooner rather than later. The total cost reflects the trade-offs between these constraints, and the allocation shows how resources are efficiently distributed across the network to achieve this optimal balance.
Alternative Implementation: Direct Solver Usage
Sometimes it's useful to work directly with the OR-Tools solver object rather than using a wrapper function. This gives you more control and helps you understand exactly how the solver API maps to our mathematical formulation. Let's see how to build a network step-by-step:
Now let's display the results from the manual network construction:
The solver successfully found an optimal solution for this network. The total cost represents the minimum achievable cost given the network structure, capacities, and unit costs. Each arc's flow value shows how the solver allocated flow to minimize total cost while respecting capacity constraints. Arcs with zero flow indicate that those edges are not part of the optimal solution. The solver determined that routing flow through alternative paths is more cost-effective. This demonstrates how the MCF solver automatically identifies the most efficient routing strategy without requiring manual path selection.
Key Parameters
Below are the main parameters and methods that affect how Minimum Cost Flow problems are solved using OR-Tools.
Key Parameters
The SimpleMinCostFlow solver in OR-Tools doesn't expose many configurable parameters directly, as it uses specialized algorithms optimized for network flow problems. However, the problem structure itself is defined by several key parameters:
-
start_nodes: List of starting nodes for each arc (the "i" in edge ). Each element corresponds to one edge in the network. Should have the same length asend_nodes,capacities, andunit_costs. -
end_nodes: List of ending nodes for each arc (the "j" in edge ). Together withstart_nodes, this defines the network topology. Node indices should be non-negative integers starting from 0. -
capacities: List of capacity values for each arc (maximum flow allowed). Should be non-negative. Use realistic values based on actual operational constraints rather than arbitrarily large numbers. Values should be in the same units as flow variables. -
unit_costs: List of unit cost values for each arc (cost per unit of flow). Can be any real number (positive, negative, or zero). Negative costs can model revenue or benefits. Ensure all costs use consistent units (cost per flow unit). -
supplies: List of supply values for each node. Positive values represent sources (supply nodes), negative values represent sinks (demand nodes), and zero represents transshipment nodes. The sum of all positive supplies should equal the absolute sum of all negative demands for the problem to be feasible.
Key Methods
The following are the most commonly used methods for working with the SimpleMinCostFlow solver:
-
add_arc_with_capacity_and_unit_cost(start_node, end_node, capacity, unit_cost): Adds an edge to the network with specified capacity and unit cost. Call this method once for each edge in your network. The order of addition doesn't affect the solution, but it determines the arc index used for querying results. -
set_node_supply(node, supply): Sets the supply value for a node. Call this method once for each node in your network. Node indices should be consecutive starting from 0. Positive values indicate supply, negative values indicate demand, and zero indicates transshipment. -
solve(): Solves the optimization problem and returns a status code. Returnssolver.OPTIMALif an optimal solution was found,solver.INFEASIBLEif no feasible solution exists, orsolver.UNKNOWNif the solver encountered issues. Check the status before querying solution values. -
optimal_cost(): Returns the minimized total cost (the value of ) after solving. Only valid ifsolve()returnedOPTIMAL. This represents the minimum achievable cost for routing flow through the network. -
flow(arc_index): Returns the optimal flow value for the arc at the given index. Arc indices correspond to the order in which arcs were added usingadd_arc_with_capacity_and_unit_cost(). Only valid after a successful solve. -
num_arcs(): Returns the total number of arcs (edges) in the network. Useful for iterating over all arcs to extract solution information. -
tail(arc_index)andhead(arc_index): Return the start and end nodes of an arc, respectively. Useful for identifying which edge each flow value corresponds to when extracting solutions.
Practical Applications
Practical Implications
The Minimum Cost flow approach is particularly valuable in several practical scenarios where optimal resource allocation is critical. In supply chain management, MCF helps optimize the flow of goods from suppliers through distribution centers to customers, taking into account transportation costs, warehouse capacities, and demand patterns. This is especially important for companies with complex distribution networks where multiple paths exist between sources and destinations. The network structure naturally captures the flow of products through various stages, making it intuitive to model real-world logistics challenges.
In workforce scheduling, MCF can be used to assign employees to shifts while minimizing costs and respecting availability constraints. The network structure naturally models the flow of labor resources through different time periods and job assignments. This approach is particularly effective when there are complex constraints involving skill requirements, labor regulations, and operational needs. The ability to handle multiple time periods and resource types simultaneously makes MCF well-suited for scheduling problems that would be difficult to model with simpler optimization approaches.
For project scheduling and resource allocation, MCF provides a framework for optimally allocating resources across different project phases while minimizing costs. The network can represent the flow of resources (personnel, equipment, materials) through different project stages, with costs reflecting the efficiency or preference for different resource-time combinations. MCF is most appropriate when your problem has a clear network structure with sources (resource availability), sinks (demand points), and intermediate nodes (processing stages or time periods). Avoid MCF when your problem requires non-linear cost functions, complex precedence relationships that don't map naturally to network flows, or when indivisibility constraints prevent flow splitting at nodes.
Best Practices
To achieve optimal results with Minimum Cost flow problems, follow several best practices. First, ensure that your network structure accurately represents the problem domain. Each node should have a clear role as either a source (supply), sink (demand), or transshipment point. When defining capacities, use realistic values based on actual operational constraints rather than arbitrary large numbers, as overly generous capacities can lead to solutions that are mathematically optimal but operationally infeasible. For cost parameters, use consistent units across all edges and ensure that costs reflect the true economic or operational impact of routing flow through each pathway.
When working with OR-Tools, use the SimpleMinCostFlow solver for standard MCF problems, as it provides efficient specialized algorithms. For problems where you need to verify feasibility before optimization, check that the total supply equals the total demand (accounting for signs: positive supplies and negative demands should sum to zero). If your problem has integer supplies, demands, and capacities, you can rely on the integrality property to guarantee integer solutions without explicitly adding integer constraints. For reproducibility, set random seeds if using any randomized preprocessing steps, though the MCF solver itself is deterministic.
When evaluating solutions, verify that all flow conservation constraints are satisfied and that no capacity constraints are violated. The solver will report if the problem is infeasible, but you should also validate that your input data makes physical sense. If you encounter infeasibility, systematically check whether total supply matches total demand, whether capacity constraints are too restrictive, and whether the network structure allows flow to reach all demand nodes from supply nodes. For large problems, consider breaking them into smaller subproblems or using hierarchical approaches where MCF solves subproblems within a larger optimization framework.
Data Requirements and Preprocessing
The MCF approach requires accurate data on network structure, capacities, costs, and supply/demand patterns. The quality of the solution depends heavily on the accuracy of these input parameters. Network structure data should specify all nodes and edges, including their connectivity relationships. For each edge, you need both capacity limits (the maximum flow that can pass through) and unit costs (the cost per unit of flow). These values should be in consistent units: capacities and flows in the same units (e.g., units, hours, workers), and costs in cost units per flow unit.
Before constructing your network, preprocess your data to handle missing values, outliers, and data quality issues. If capacity data is uncertain, consider using conservative estimates or running sensitivity analysis to understand how capacity changes affect the solution. Cost data should reflect the true economic or operational costs, including transportation expenses, time penalties, resource utilization costs, and any preference-based costs. If costs vary with flow volume (non-linear), you may need to approximate with piecewise linear costs or consider alternative formulations.
For supply and demand values, ensure that positive supplies (sources) and negative demands (sinks) are correctly specified. The sum of all supplies should equal the absolute sum of all demands for the problem to be feasible. If your problem has time-based components, structure your network with time periods as separate nodes or layers, ensuring that flow can only move forward in time. When dealing with resource allocation problems, map resources, time slots, and tasks to appropriate network layers, with capacities representing resource availability and task requirements.
Common Pitfalls
Several common pitfalls can undermine the effectiveness of Minimum Cost flow solutions if not carefully addressed. One frequent mistake is mismatched supply and demand totals, where the sum of positive supplies does not equal the absolute sum of negative demands. This will cause the solver to report infeasibility even when a solution might seem possible. Verify that before solving. Another issue arises when capacity constraints are set too restrictively, preventing flow from reaching demand nodes even when sufficient supply exists. Review your capacity values to ensure they allow feasible flow paths through the network.
Neglecting to account for all relevant costs can lead to solutions that are mathematically optimal but operationally suboptimal. For example, if you only include transportation costs but ignore time penalties or resource utilization costs, the solution may route flow through paths that are cheap in terms of transportation but expensive in other ways. Include all significant cost components in your edge cost parameters. Similarly, using inconsistent units for capacities and costs can produce misleading results. Ensure that all capacity values use the same units as flow variables, and that all cost values represent cost per unit of flow in consistent currency or utility units.
Another common mistake is creating network structures that don't accurately represent the problem constraints. For instance, if your problem requires that certain resources cannot be split (indivisibility), the standard MCF formulation may not be appropriate since it allows flow to be split and combined freely at nodes. In such cases, you may need to use integer programming extensions or reformulate the problem. Finally, failing to validate solutions can lead to implementing infeasible or suboptimal allocations. Check that the solution satisfies flow conservation at all nodes, respects capacity constraints on all edges, and makes operational sense in your specific context.
Computational Considerations
MCF problems are computationally efficient compared to general linear programming problems due to their special network structure. The OR-Tools SimpleMinCostFlow solver uses specialized algorithms (such as cost scaling or successive shortest path) that typically solve problems with thousands of nodes and edges in seconds or milliseconds. For problems with up to approximately 10,000 nodes and 100,000 edges, the solver usually performs well on modern hardware. Beyond this scale, you may need to consider problem decomposition, network simplification, or approximate methods.
Memory requirements are generally modest for MCF problems, as the solver only needs to store the network structure (nodes, edges, capacities, costs) and the solution (flow values). For very large problems (millions of edges), consider using sparse data structures and avoid storing full dense matrices. If memory becomes a constraint, you can process the network in chunks or use iterative refinement approaches where you solve subproblems and combine solutions.
For problems that need to be solved repeatedly (such as real-time scheduling or dynamic resource allocation), the MCF solver's speed makes it suitable for online applications. However, if your problem structure changes frequently, you may need to rebuild the network each time, which adds overhead. In such cases, consider maintaining a base network structure and updating only the changed parameters (capacities, costs, or supplies) rather than reconstructing the entire network. For problems with similar structure but different parameter values, you can often reuse network construction code and simply update the parameter arrays.
Performance and Deployment Considerations
Evaluating MCF solution quality involves checking both mathematical optimality and operational feasibility. The solver reports whether an optimal solution was found, but you should also verify that the solution makes sense in your specific context. Key metrics to consider include total cost (the minimized objective value), flow utilization (what percentage of available capacity is used), and solution balance (how evenly flow is distributed across available paths). For operational validation, compare the solution against known good solutions or historical allocations to ensure it aligns with domain expectations.
When deploying MCF solutions in production, consider how frequently the problem needs to be solved and how quickly solutions are required. The solver's speed makes it suitable for real-time applications, but you should account for data preparation time, network construction overhead, and solution interpretation. For batch processing applications, you can solve multiple problem instances in parallel if they are independent. If problems are related (e.g., daily scheduling where today's solution affects tomorrow's starting state), you may need to solve them sequentially and update initial conditions between solves.
Monitoring deployed MCF solutions involves tracking both solution quality and solver performance. If solution costs increase unexpectedly, investigate whether input parameters (costs, capacities, demands) have changed or whether the problem structure no longer accurately represents the operational reality. If solver times increase significantly, check whether the problem size has grown or whether the network structure has become more complex. For critical applications, implement validation checks that flag solutions with unusual characteristics (e.g., very high or very low capacity utilization, unexpected flow patterns) for human review before implementation.
Summary
The Minimum Cost flow problem provides a powerful and efficient framework for solving resource allocation and slotting problems. By modeling problems as network flows with sources, sinks, and capacity constraints, we can leverage specialized algorithms that guarantee optimal solutions while remaining computationally tractable for many real-world applications.
The mathematical foundation of MCF, based on flow conservation and capacity constraints, provides both theoretical rigor and practical flexibility. The network representation makes it intuitive to understand and visualize, while the linear programming structure ensures efficient solution algorithms. The integrality property of MCF problems is particularly valuable for applications where fractional allocations don't make sense.
For practitioners, OR-Tools provides an excellent implementation of MCF algorithms that can handle complex networks with thousands of nodes and edges. The framework's flexibility allows for easy incorporation of various constraints and cost structures, making it suitable for a wide range of applications from supply chain optimization to workforce scheduling. When your problem naturally fits a network flow structure, MCF often provides the most efficient and effective solution approach.
Quiz
Ready to test your understanding? Take this quick quiz to reinforce what you've learned about minimum cost flow optimization and network flow problems.









Comments