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.