7 March 2025

Optimization modelling is often used to improve the efficiency of supply chains. Where there is vertical integration, an organziation can model and optimize each part of the chain that they control. But how can they coordinate efficiently with independent suppliers and contractors?
One approach is to incentivize behaviours via price signals. A byproduct of solving a linear programming model is a set of "dual values" that indicate the marginal value of constrained resources. For example, some wholesale electricity markets use a linear program to find the least-cost suppliers to meet demand given various constraints. The model's dual values are used as prices for buying and selling of electricity and related services. If the prices are calculated depending on geographic location, then they are called Locational Marginal Prices (LMP) – indicating how the value of electricity varies by location.
In this article, we apply Locational Marginal Pricing to the supply of potatoes to fast-food restaurants. The current supply chain has several issues, including high costs, limited supplier capacity, transportation constraints, and a high spoilage rate during transportation. We want to give the independent suppliers and contractors price signals that incentivize more efficient behaviour, thereby reducing costs for our restaurants and improving the efficiency of the system. We describe the optimization model and calculation of the LMPs. We then explore several scenarios for how the suppliers and contractors may respond to the LMP signals.
Download the models
The models described in this article are built in Python using the Pyomo library.
The files are available on GitHub.
Situation

We operate a chain of fast-food restaurants in six cities located on the island nation shown in Figure 1. To make a key product, French Fries, we purchase potatoes from suppliers on the island and contractors transport the potatoes to our restaurants.
Each supplier sells potatoes at a specified price per kg and has a maximum supply capacity (kg/week). The cost of potatoes varies by location (called "nodes"), ranging from $0.80/kg to $1.15/kg, as shown in Figure 2. The cheapest suppliers are in the north and west of the island, due to factors such as growing conditions, land values, and staff costs. We currently purchase from the cheapest suppliers, at Nodes 1, 2, and 3. Supply is currently not available from the more expensive suppliers at Nodes 4, 5, and 6.
Our largest demand centre is in the southeast. Therefore, in broad terms, potatoes are transported from suppliers in the northwest towards consumers in the southeast, supplying our locations along the way.
The transportation network characteristics are shown in Figure 3. The average cost of transportation is about $0.15/kg per 100 km, though it may be half that or close to double that, depending on the route. Some of the potatoes will spoil, becoming unusable, during transportation. The average spoilage rate is about 2.5% per 100 km, though the rate depends on the route.
To get the required delivered quantity, we need to purchase extra from the suppliers to allow for spoilage. Overall, we purchase 173,646 kg of potatoes per week to meet our demand of 165,000 kg. The difference of 8,646 kg (5.0%) is lost due to spoilage during transportation.
Our total cost for potatoes is $209,376/week. Around 80% of the delivered cost is for the potatoes, with the other 20% being transportation costs.
The current situation is illustrated in Figure 4. We represent the locations of the suppliers and our restaurants as nodes, with transportation links between some nodes. Transportation can occur in either direction on a link, but it makes sense to have transportation in only one direction at a time. Transportation between non-adjacent nodes is via the intermediary nodes, with characteristics that aggregate the individual link characteristics. The distance between nodes is not drawn to scale.
Each node has characteristics in blue text. A node may have a supplier whose capacity is indicated as "^" kg and current supply as "→" kg. Our demand at a node is indicated as "←" kg. That is, currently we have demand at Nodes 2, 3, 4, 5, and 6. Our suppliers are at Nodes 1, 2, and 3.
The link between each pair of nodes, where it exists, has capacity "^" kg and current flow of "~" kg in the indicated direction. The transportation losses due to spoilage are "←" kg and the transportation cost is "$". If a transportation link is constrained, meaning it has flow equal to capacity, then the characteristic values and line are red, otherwise they are green.

Current issues
Our current supply situation has several issues:
- The fast-food restaurant business operates on very thin profit margins, so anything we can do to reduce the current average potato delivered cost of $1.27/kg ($209,376/week for 165,000 kg/week) would be valuable.
- Two of our three suppliers are operating at their supply capacity, so we have only one supplier (at Node 2) who can meet any increase in our demand.
- The transportation network has significant constraints, which limit our ability to meet our demand efficiently. Specifically, our Supplier at Node 2 is limited by transport capacity constraints.
- The overall spoilage rate of 5.0% is high relative to the industry benchmark of 3.0%.
- Spoilage is costing us $11,000/week (8,646 kg loss * $1.27/kg).
- Our transportation costs seem excessive, at over $42,000/week (20% of total delivered cost).
Potatoes are a commodity and the market for potatoes on the island is very competitive. We are one of several large fast-food restaurant chains, plus there are other substantial potato purchasers (including supermarkets). Therefore, we have little or no power when negotiating with the potato suppliers and transportation contractors.
Given this situation, how can we solve our cost and capacity issues? Expressing the question another way: How can we incentivize the potato suppliers and transportation contractors to offer us a better deal?
Locational marginal pricing
LMP as a price signal
One way to create better incentives for the potato suppliers and transportation contractors is to tell them how much potatoes are worth to us. That is, send them a market price signal. Since our situation covers several locations around the island, the price signal may vary by location.
This is where the concept of "locational marginal pricing" or "locational marginal price" (LMP) comes in.
LMP is mostly used in wholesale electricity markets
Locational marginal pricing is an economic concept primarily used in some wholesale electricity markets. The goal is to efficiently price electricity at each location (node) in the transmission grid. The locational prices consist of three main components: electricity generation cost, transmission congestion cost, and cost of transmission electrical losses (due to heating the wires and transformers as electricity flows through them). LMP provides price signals that reflect the cost of meeting electricity demand and the value of electricity generation at each location, considering the characteristics of the system.
In an electricity market, the LMPs are calculated by the optimization model used to clear the market. That is, a linear programming model is used to dispatch electricity generators based on their offers to supply electricity, subject to meeting demand and accounting for losses and constraints in the transmission network. The model minimizes the total cost of running the system. In most markets this process operates in real time or covering intervals such as 5 minutes or 1 hour. Each time the market clears, the marginal price of demand or supply is calculated at each node. The generators are paid the LMP at their node, and the consumers (or their retailer) pay the LMP at their node. The marginal prices, also known as "shadow prices" or "dual values", are a direct byproduct of solving the linear program.
For example, Figure 5 shows the LMPs for the Pennsylvania-Jersey-Maryland (PJM) wholesale electricity market in the northeast USA, averaged over January to June 2024. There is substantial locational variation, with the average prices ranging from $4/MWh to $41/MWh. This LMP variation reflects different demand quantities, generator offer prices, transmission losses, transmissions constraints, and other system operational requirements at each location in the network.

Source: State of the Market Report for PJM, August 2024, page 200
Using LMP for supply of potatoes
The purpose of LMP is to signal locational value to incentivize efficient behaviour. That's what we want. Though note that the incentives apply to both suppliers and us. If the cost of delivered potatoes at a specific location is too high, then we should consider whether continuing to have a restaurant at the location is viable – but that's a longer-term decision for another time.
For addressing the issues in our immediate situation, how do we calculate the locational marginal prices? We can apply essentially the same concept used in electricity markets to our market for potatoes. That is, formulate a linear program that minimizes the cost of purchasing delivered potatoes, given the cost of each supplier and subject to transportation costs and spoilage. When solving the model, the solver can calculate the dual values for each node – that is, the locational marginal prices we want.
Solving a market model for supply of potatoes will tell us two things:
- Which potato suppliers and transportation contractors to choose to minimize our cost of delivered potatoes.
- The marginal price of potatoes at each location.
We can use the marginal prices as a signal to the suppliers and contractors about how much we value delivered potatoes at each node. Given that signal, we expect the suppliers and contractors to change their behaviours to maximize their profits and, as a side-effect, solve our issues.
Model formulation
Figure 6 shows the formulation for our potato supply model. This is a conventional cost minimization model, where the locations are called nodes, links between nodes are called edges, and potatoes flow from node to node. That is:
- Equation (1), Objective function. Minimize the cost by buying potatoes from suppliers and transporting the potatoes to our nodes.
- Equation (2), Supply capacity constraint. The supplier at each node has an upper bound on their capacity.
- Equation (3), Node balance constraint. The flow of potatoes at each node must balance. That is, the supply at a node plus the amount transported into the node less the amount transported out of the node must equal the demand at that node. Equation (3c) is the node balance constraint, with Equations (3a) and (3b) shown separately purely for convenience.
- Equation (4), Transportation capacity constraint. Each link has an upper bound on the transportation capacity.
Implementation
Get LMPs from the model
Implementing the model formulation in Pyomo is straightforward, as shown in our GitHub repository. The only unusual feature is that before solving we tell the solver that we want it to produce the dual values (which are not calculated by default) and then after solving we extract the dual values into a list. These two steps are shown in Figure 7. Note that we're interested in the marginal value of supply at a node, therefore the dual values we want are on the node balance constraint, Equation (3c).
model.dual = Suffix(direction=Suffix.IMPORT_EXPORT)
...
lmp = {n: model.dual[model.flow_balance[n]] for n in model.nodes}
Examples of calculating LMPs
The result of running the model for the current situation in shown in Figure 8. This is the same as Figure 4 except that we've added the LMP for each node (in blue) and dimmed the other information.

So, what do the LMPs mean?
The LMP at Node 2 is simple. Our current demand at Node 2 is 40,000 kg. If we increase demand by a marginal amount of 1 kg to 40,001 kg, then it would be supplied by the supplier at Node 2 – since they have available capacity, and local supply is cheaper than transportation from any other node. Therefore, the marginal price of that extra 1 kg is the local supplier's cost of $1.05/kg (as shown in Figure 2). Provided our marginal change in demand doesn't change any of the binding constraints, then this LMP applies.
Calculating the LMP at Node 1 is a bit more complex. If we increase our demand at Node 1 by 1 kg, then it cannot be supplied by the Supplier at Node 1 because they are already at their capacity. Instead, the Supplier at Node 2 supplies 0.9550 kg which increases costs by $1.0028 (= 0.9550 * 1.05). Why don't they supply 1 kg? Because increasing supply at Node 2 means less flow is needed from Node 1 to Node 2, which reduces the spoilage on Link 1-2. The spoilage for 1 kg sent on the 150 km line between Node 1 and Node 2 is 4.5% (at a rate of 3.0%/100km), which is 0.0450 kg, so only 0.9550 kg extra supply is needed at Node 2 to deliver 1 kg extra at Node 1. The transportation cost also reduces, by $0.1500 (= 1 kg * $0.001/kg/km * 150 km). Therefore, the net change in costs is +$1.0028 - $0.1500 = $0.8528, which is the LMP at Node 1.
Calculating the LMPs at the other nodes follows a similar process, though we need to allow for the constrained links between some nodes. For example, if we increase demand at Node 6, then supply at Node 2 must increase by 1.084 kg, which is more than 1 kg because of the additional spoilage on the links through to Node 6. The extra supply costs $1.1382/kg. The spoilage on Link 1-2 reduces (like the case above), but the spoilage on Links 1-3, 3-4, 4-5, and 5-6 all increase. The net change in spoilage costs $0.5183/kg, giving a total cost change of $1.6565/kg, which is the LMP at Node 6.
Note that Node 6's LMP is roughly double Node 1's LMP, reflecting the impact of the transportation constraints and the spoilage incurred by transporting potatoes the long distance from the northeast to the southwest of the island. That is, extra supply at Node 6 is worth about double the value of extra supply at Node 1. This is the type of price signal that we want to send to our suppliers and transportation contractors.
You can manually replicate the marginal effects by changing the data and solving the model. For example, increase the demand at Node 6 from 0 kg to 1 kg. The optimal objective function will increase by $1.6565. Or change the demand at Node 2 from 40,000 kg to 40,001 kg and see that the objective function value increases by $1.0500.
How do we use the LMPs?
Tell the suppliers and contractors!
Now that we can calculate LMPs for our potato situation, we tell our suppliers and contractors so that they can respond to the price signals. In the next sections we explore a few scenarios for how they might respond.
As a base, our total delivered cost for potatoes is currently $209,376/week, consisting of $167,342 for supply and $42,034 for transportation.
Scenario 1: Double transport capacity on constrained links
An issue with the current situation is that transport is constrained on Links 2-4, 2-5, and 4-6. Figure 9 shows the result of our transport contractors responding by doubling capacity on each of those links.
The effect is to reduce the LMPs at most (though not all) nodes, so this is an improvement. Specifically, our total delivered cost for potatoes reduces to $199,955/week (-4.5%), consisting of $164,751 (-1.5%) for supply and $35,204 (-16.2%) for transportation. Better transportation reduces the direct transport costs and spoilage (so we need to buy less product).
But even with double the capacity, Link 2-5 is still constrained and Link 1-2 becomes constrained whereas it isn't currently. The issue is that we're still transporting large volumes of potatoes over long distances, so the additional link capacity is useful but insufficient to solve all our problems.

Scenario 2: Meet all demand from local suppliers
What if the suppliers respond to our price signals by matching our demand with their supply at each node? The result is shown in Figure 10.
Our total delivered cost for potatoes reduces to $194,112/week (-7.3%), consisting of $194,112 (+16.0%) for supply and $0 for transportation (-100.0%). We pay more for the product but eliminate the transportation cost (including spoilage) entirely. This result is cheaper than Scenario 1, but can we do even better?

Scenario 3: Increase supply at Node 6
The key thing that the LMPs signal is that in the southeast of the island, where our demand is highest, delivered potatoes are especially valuable. So, what happens if a supplier responds to the LMPs by starting to supply potatoes at Node 6? Recall that Node 6 has the highest supply cost of $1.15/kg (c.f. $0.80/kg at Node 1), so this doesn't seem like a useful offer.
The result is shown in Figure 11. All the LMPs reduce, some of them substantially. For example, currently the LMP at Node 6 is $1.6565/kg, but if 60,000 kg/week is supplied to Node 6 then its LMP reduces to $1.1841/kg. Node 6 starts exporting potatoes to Nodes 4 and 5, rather than being an importer.
It turns out that 60,000 kg/week isn't enough – as indicated by the LMP being higher than the supply cost, suggesting that we would benefit from even more supply. Even so, our total delivered cost for potatoes reduces to $188,747/week (-9.9%), consisting of $168,536 (+0.7%) for supply and $20,210 for transportation (-51.9%). We spend slightly more on potatoes but more than halve the transportation costs.
In this scenario, the link between Nodes 2 and 5 becomes constrained. But increasing that link's capacity would make little difference (-$752 overall), so it is hardly worth doing.
Even with the constrained link, this scenario is significantly better than Scenario 2, by a total of -$5,365 (-2.8%). This result shows that transporting potatoes around the network is cheaper than all nodes being supplied locally. In other words, there are gains from trade between the nodes, even though trade incurs transportation costs.

Scenario 4: Increase supply in the south and transport capacity to match
So, trading with other nodes is good. But can we do even better?
What if the suppliers increase their capacity at each node, and each transport contractor changes their capacity so that no link capacity constraints bind? The solution, as shown in Figure 12, is radically different to the current solution. That is:
- The supplier at Node 1 is the cheapest on the island. In this scenario, they supply all demand at Node 1 and Node 2. Allowing for transport and spoilage, it is cheaper for the supplier at Node 1 to supply our demand at Node 2 rather than using the Node 2 supplier directly (Node 2's LMP is $0.9948/kg compared with Node 2 supplier cost of $1.0500/kg), so there is no direct supply at Node 2. Instead, our demand at Node 2 is met by the supplier at Node 1.
- Supply at Node 3 is fairly cheap, at $0.9000/kg, so their volume increases substantially. They supply all the demand at Nodes 3, 4, and 6. The LMP at Node 6 is $1.1451/kg, indicating that supply from Node 3 plus transport and spoilage is slightly cheaper than local supply at Node 6 given the Node 6's supply cost of $1.1500/kg. Similarly for Node 4. Therefore, we have no local supply at Nodes 4 and 6.
- Transport to Node 5 is expensive, so the cheapest option is for the demand at Node 5 to be met entirely from the local supplier at Node 5. That's despite the Node 5 supplier being the second-most expensive supplier on the island, at $1.1200/kg.
This scenario is a substantial improvement, having a total cost that is 17.2% less than the current situation. Since there are no binding capacity constraints, this solution has the minimum cost possible given the current data.

Summary of scenarios
Figure 13 shows a summary of the current situation and the scenarios. The "Saving" column indicates the overall reduction in total cost relative to the current situation.
Our current situation has six issues, all of which are resolved by Scenario 4:
- Our current average potato delivered cost is reduced from $1.27/kg to $1.05/kg, saving $35,934 (17.2%) per week.
- We have two suppliers able to increase supply, rather than one, giving us more flexibility for growth.
- The transportation network has no constraints.
- Spoilage (loss) rate is halved, from 5.0% to 2.5%, to be below the industry benchmark of 3.0%.
- Spoilage costs halve, from around $8,600/week to $4,300/week.
- Transportation costs more than halve, from around $42,000/week to under $20,000/week (from 20% to 11% of total delivered cost).
Scenario 4 is a great outcome for us. Our costs have reduced significantly. It is also good for the economy and environment, as the system is much more efficient with substantially less waste.
In aggregate, the potato suppliers and transport contractors are happy, as they receive the prices they want. However, there are winners and losers, as the suppliers and contractors we use in Scenario 4 are different, or have different quantities, compared with the current situation. But winning by being inefficient is not a long-term sustainable position.
Markets are a wonderful thing
A key point is that we're a relatively small buyer in the potato market. Consequently, we have essentially no ability to dictate the behaviour of our potato suppliers and transportation contractors. That is, we can't just tell them to make capacity available where we want it. Instead, by calculating and sharing our locational marginal prices, we have effectively created a wholesale market to provide price signals. Those prices incentivize our suppliers and contractors to produce a better outcome for us and them.
For example, the supplier at Node 3 currently supplies a maximum of 25,000 kg/week. In Scenario 4, they increase their supply by a factor of more than 4, to 102,422 kg/week, greatly expanding their share of the market and their profitability. We benefit from their increased supply of relatively low cost potatoes.
Our customers will also benefit from our reduced wholesale costs. Competition with other fast-food restaurants will ensure that at least some of our reduced costs will be passed through to our customers as lower retail prices.
Looking forward, market conditions will change over time. For example, our demand at each location may change, or the supply and contractor costs/capacities could change. There may also be seasonal variations to consider in our purchasing decisions. The effects of those changes can be captured by re-solving the model and calculating updated LMPs, enabling us, our suppliers, and the transport contractors to adjust efficiently.
Conclusion
In this article, we apply Locational Marginal Pricing to the supply of potatoes to fast-food restaurants. The goal is to provide the restaurants' suppliers and contractors with price signals to incentivize efficient bahaviour.
The result is a substantial reduction in costs for the restaurants and reduced waste in the system. In addition, while there are winners and losers, the overall system becomes more efficient and sustainable, benefiting the customers, suppliers, contractors, and the environment. As the situation evolves over time, updated locational prices will ensure that everyone can adapt efficiently. Markets, with the help of an optimization model to produce price signals, are indeed a truly wonderful thing.
If you would like to know more about this model, or you want help with your own models, then please contact us.