1.9 Case Study: Modeling Network Flow using Systems of Linear Equations
Just go with the flow
1What is network flow?¶
Network flow models can be used to capture traffic flowing through a road network, water through a grid of pipes, or information flowing through the internet. In this section, we will use systems of linear equations to understand how to allocate flows (traffic, water, internet packets) across links (roads, pipes, network links) in order to meet demand (how much traffic must flow in and out of a network). We’ll also explore what happens when links are modified or deleted.
A key modeling assumption that we make is that flow is conserved, i.e., flows leaving a node have to equal flows leaving a node. Here we use the term node to describe where different links (roads, pipes, etc.) meet, i.e., nodes are where links intersect. In the figure below, flow conservation means that . This is a very reasonable assumption: for example, if we’re talking about road traffic, it means that all cars that enter a road network eventually leave it, and that no cars can spontaneously appear or disappear within the road network. Similarly, if we’re talking about internet traffic, it means that data can’t appear out of thin air, that all data entering the network eventually leaves it, and that packets can’t be dropped (this is not always true for internet traffic, but we definitely prefer it when no data is lost!).
2What Linear Algebra tools do we need to model network flow?¶
2.1Concepts¶
- Gaussian Elimination / Row Reduction
2.2Computation¶
3Small Example¶
Let’s consider a system of pipes.
Because of our assumption that the total inflows and outflows are conserved, we can say that for each intersection . We make our first observation: each intersection, or node, in the graph above leads to an equation. We can rearrange terms, and get the following equation, that . This is fairly intuitive, and we’ll use this law to create our system of equations. We also know that the total outflows leaving the system must be equal to the total inflows entering the system: we’ll call this total flow conservation.
Each equation above represents an equality that results from our original assumption. The first equation shows the total conservation, and the next 4 lines show the equations for each intersection. Rearranging to have the unknowns on the left, and the knowns on the right, we get the following system of linear equations:
which we can put in form:
We can construct the augmented matrix for this system below:
4Python Implementation¶
We’ll work with SymPy to go through the steps of reducing the augmented matrix into row echelon form, and then solving for the general solutin.
import numpy as np
from numpy.linalg import solve
from sympy import Matrix, latex
augmented_matrix = np.array([
[1 , 0 , 0 , 0, 0, 40],
[-1 , 1 , 1 , 0 , 0, 30],
[0 , 1 , 0 , 1, 0, 50],
[0 , 0 , 1 , 0 , 1, 80],
[0 , 0 , 0 , 1, 1, 60],
])
A = augmented_matrix[:,:-1] # We take the first part of the augmented matrix, which represents A [: <- This means every row, :-1 <- This means all but the last column]
b = augmented_matrix[:, -1] # Now the second part, which represents b [: <- This means every row, -1 <- This means only the last column]
matrix = Matrix(augmented_matrix)
matrix
row_echelon_matrix = matrix.echelon_form(simplify=True)
row_echelon_matrix
Placing this in equation form again, we get the below. There is no pivot in the 5th column, so is free.
Simplifying, we get the following system of equations:
We proceed from the bottom, and express the basic variables in terms of the free variable . To get an expression to start, we can simplify the last equation to
Using back substitution, we can first substitute into our third equation, yielding
Again substituting into the second equation, we get:
Gathering all of these equations, we get the general solution:
Now, we need to apply some human reasoning, namely that none of the traffic flow can be negative! The equality tell us that must be at least 10 (otherwise would be negative!), and the equality tells us that can be at most 60 (otherwise would be negative!).
With that in mind, we pick , which corresponds to putting 30 units of flow on , and get the following specific solution:
Let’s check our solution in the original equation:
x = np.array([40, 20, 50, 30, 30])
print(A@x)
print(b)
A@x == b
[40 30 50 80 60]
[40 30 50 80 60]
array([ True, True, True, True, True])
We got a solution!
5Penn Engineering Road Network¶
We can apply the same sort of thinking to roads!
The above figure shows a road network that looks similar to that around Penn Engineering. We model these road networks the same way, by balancing the inflows and outflows of each node, and by enforcing total flow conservation as well. This yields the following system of linear equations:
To put this in matrix form, we need to do the same as before, and reorganize terms.
This gives us the following augmented matrix
augmented_matrix = np.array([
[-1 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0],
[0 , -1 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 50],
[0 , 0 , -1 , 1 , 0 , 0 , 0 , 0 , 0 , -60],
[0 , 0 , 0 , 1 , 0 , 0 , 0 , -1 , 1 , 0],
[0 , 0 , 0 , 0 , 1 , 0 , -1 , 1 , 0 , 80],
[0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 100],
[1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 190],
])
A = augmented_matrix[:,:-1] # We take the first part of the augmented matrix, which represents A [: <- This means every row, :-1 <- This means all but the last column]
b = augmented_matrix[:, -1] # Now the second part, which represents b [: <- This means every row, -1 <- This means only the last column]
matrix = Matrix(augmented_matrix)
echelon_form = matrix.echelon_form()
echelon_form
Let’s print the row-echelon matrix in a nicer way:
Looking at the row-echelon form, we should notice a few things. First, that the last row is empty. Second, that there are not pivots in every column. In the columns for , there are no pivots. This means there are 3 free variables in this system. This makes sense, because we have only 6 intersections, giving 6 equations, but 9 flows, representing 9 variables. In order to find a solution, let’s set all of those free variables to be zero. We can think of this as closing all of the roads that are free variables.
Let’s solve for the free variables in terms of the basic variables:
First for :
We know that if , then will be negative.
Now for :
We also know that cannot be more than 80.
For :
Now let’s solve for the system, setting to be equal to 0. To do this, we first select all of the columns from the augmented matrix which correspond to basic variables.
smaller_augmented_matrix = np.array(echelon_form[:,[0,1,2,3,4,5,9]]).astype(np.float64)
"""
Above, we just selected all of the rows that correspond to the non-free variables.
If the free variables are zero, then we can freely subtract them from the rest of the equations.
"""
# smaller_augmented_matrix = np.vstack([smaller_augmented_matrix,
# np.array([[0,0,0,0,0,0,0,0,1,0,80]]),
# ])
smaller_augmented_matrix = smaller_augmented_matrix[:-1,:]
smaller_augmented_matrix
array([[ -1., 1., 0., 0., 0., 1., 0.],
[ 0., -1., 1., 0., 1., 0., 50.],
[ 0., 0., -1., 1., 0., 0., -60.],
[ 0., 0., 0., 1., 0., 0., 0.],
[ 0., 0., 0., 0., 1., 0., 80.],
[ 0., 0., 0., 0., 0., 1., 100.]])
Now that there are pivots in all columns, we can try to use numpy’s solve
method to get a solution.
sA = smaller_augmented_matrix[:,:-1] # We take the first part of the augmented matrix, which represents A [: <- This means every row, :-1 <- This means all but the last column]
sb = smaller_augmented_matrix[:, -1] # Now the second part, which represents b [: <- This means every row, -1 <- This means only the last column]
x = solve(sA,sb)
x
array([190., 90., 60., 0., 80., 100.])
Let’s write these solutions down first.
One key thing to remember is that these variables are currently unconstrained. In our road network, a negative number means that traffic is flowing the wrong way. Let’s verify that the free variables we specified are actually zero, and see what we can learn from each solution.
Now let’s check our solution:
x = np.array([190,90,60,0,80,100,0,0,0])
print(A@x)
print(b)
print(A@x == b)
[ 0 50 -60 0 80 100 190]
[ 0 50 -60 0 80 100 190]
[ True True True True True True True]
As an extension, if you want to try to solve the same system, but fix the values for the free variables to different values. One way to do this would be to add equations to the system of equations that fix the values of specific variables. For example, you could add a row fixing like so:
6Related Resources¶
If you’re interested in modeling traffic flow, check out the Cellular Transmission Model and Networked Macroscopic Fundamental Diagram models for more info on how traffic flow is modeled in practice, and some approaches to control traffic lights.