Data Structure
The structure of the IFN package is organized around two main components: network directed graphs and matrices. The dependencies between the packages are illustrated in the figure [here](packages_dependencies.jpg), and the class inheritance is shown in the figure [here](class_inheritances.jpg).
The IFN (Ideal Flow Network) package represents data using two primary formats: Network Directed Graphs and Matrices. These representations allow for flexible modeling of relationships between nodes and links in a network.
1. Network Directed Graph
A network is represented as an adjacency list, which is a nested Python dictionary.
A node is a key in the adjacency list, and each node is represented by its name (a string).
Links between nodes are always directed, meaning they have a starting point and an endpoint. In the adjacency list: - The starting node is the key at the first level. - The ending node is the key at the second level.
The weight of a link is stored as the value in the second level of the adjacency list. The weight can be an integer or a float (such as a probability).
Example of a Directed Graph:
{
'a': {'b': 3, 'c': 1, 'd': 77},
'b': {'c': 1, 'e': 1},
'c': {'e': 1},
'd': {'c': 1},
'e': {'a': 1, 'f': 5}
}
Another example using probabilities:
{
'a': {'b': 0.012, 'c': 0.012, 'd': 0.916},
'b': {'c': 0.012, 'e': 0.012},
'c': {'e': 0.012},
'd': {'c': 0.012},
'e': {'a': 0.012}
}
A real-world example using city names:
{
'Calgary': {},
'Chicago': {'Denver': 1000},
'Denver': {'Houston': 1500, 'Los Angeles': 1000, 'Urbana': 1000},
'Houston': {'Los Angeles': 1500},
'Los Angeles': {},
'New York': {'Chicago': 1000, 'Denver': 1900, 'Toronto': 800},
'Toronto': {'Calgary': 1500, 'Chicago': 500, 'Los Angeles': 1800},
'Urbana': {}
}
2. Matrix Representation
The weighted adjacency matrix is a two-dimensional array (a Python list of lists) that represents connections between nodes. Each element in the matrix represents the weight of the connection between nodes.
The matrix is accompanied by a list of nodes, which represents the names of the nodes corresponding to the matrix rows and columns.
Example of a Weighted Adjacency Matrix:
matrix = [
[0, 1, 1, 77, 0],
[0, 0, 1, 0, 1],
[0, 0, 0, 0, 1],
[0, 0, 1, 0, 0],
[1, 0, 0, 0, 0]
]
nodes = ['a', 'b', 'c', 'd', 'e']
There are functions to convert between adjacency lists and matrices:
- To convert a matrix to an adjacency list, use the function matrix_to_adj_list()
.
- To convert an adjacency list to a matrix, use the function adj_list_to_matrix()
.
A path (or trajectory) through the network is represented as a sequence of node names (a Python list of strings).
Example of a Path:
['a', 'b', 'e']
Naming Conventions
We follow specific naming conventions in the IFN package to maintain consistency and readability:
Each IFN has a name to represent the class.
When saving an IFN, the filename is the same as the name of the IFN.
Private functions start and end with double underscores (__function_name__).
Class names start with a capital letter.
Function names start with a lowercase letter.
### Abbreviations for Matrix Types: - A = Adjacency matrix - B = Incidence matrix - C = Capacity matrix - F = Flow matrix - S = Stochastic matrix - sR = Sum of rows - sC = Sum of columns - kappa = Total flow - pi = Node vector (steady state) - [m, n] = Matrix size (m rows, n columns)
Coding Standards
For clarity and uniformity, we use the following terminologies across the IFN package:
A network consists of nodes (vertices) and links (edges in graph theory).
A trajectory (or path) is a sequence of nodes (or links).
A cycle is a path where the start and end nodes are the same.
Flow refers to the weight on a link, a node, or both.
As per our agreement, all private functions are named using double underscores (__function_name__) to clearly differentiate them from public methods.