Package: ngraph
NetGraph🚧 Work in progress! 🚧IntroductionUse Case ExamplesCalculate MaxFlow in a graphPlace traffic demands on a graphPerform basic capacity analysisIntroductionThis library is developed to help with network modeling and capacity analysis use-cases. The graph implementation in this library is a wrapper around MultiDiGraph ofNetworkX. Our implementation makes edges explicitly addressable which is important in traffic engineering applications.The lib provides the following main primitives:MultiDiGraphDemandFlowPolicyBesides, it provides a number of path finding and capacity calculation functions that can be used independently.Use Case ExamplesCalculate MaxFlow in a graphCalculate MaxFlow across all possible paths between the source and destination nodes# Required importsfromngraph.lib.graphimportMultiDiGraphfromngraph.lib.max_flowimportcalc_max_flow# Create a graph with parallel edges# Metric:#      [1,1]      [1,1]#   ┌────────►B─────────┐#   │                   │#   │                   ▼#   A                   C#   │                   ▲#   │   [2]        [2]  │#   └────────►D─────────┘## Capacity:#      [1,2]      [1,2]#   ┌────────►B─────────┐#   │                   │#   │                   ▼#   A                   C#   │                   ▲#   │   [3]        [3]  │#   └────────►D─────────┘g=MultiDiGraph()g.add_edge("A","B",metric=1,capacity=1)g.add_edge("B","C",metric=1,capacity=1)g.add_edge("A","B",metric=1,capacity=2)g.add_edge("B","C",metric=1,capacity=2)g.add_edge("A","D",metric=2,capacity=3)g.add_edge("D","C",metric=2,capacity=3)# Calculate MaxFlow between the source and destination nodesmax_flow=calc_max_flow(g,"A","C")# We can verify that the result is as expectedassertmax_flow==6.0Calculate MaxFlow leveraging only the shortest paths between the source and destination nodes# Required importsfromngraph.lib.graphimportMultiDiGraphfromngraph.lib.max_flowimportcalc_max_flow# Create a graph with parallel edges# Metric:#      [1,1]      [1,1]#   ┌────────►B─────────┐#   │                   │#   │                   ▼#   A                   C#   │                   ▲#   │   [2]        [2]  │#   └────────►D─────────┘## Capacity:#      [1,2]      [1,2]#   ┌────────►B─────────┐#   │                   │#   │                   ▼#   A                   C#   │                   ▲#   │   [3]        [3]  │#   └────────►D─────────┘g=MultiDiGraph()g.add_edge("A","B",metric=1,capacity=1)g.add_edge("B","C",metric=1,capacity=1)g.add_edge("A","B",metric=1,capacity=2)g.add_edge("B","C",metric=1,capacity=2)g.add_edge("A","D",metric=2,capacity=3)g.add_edge("D","C",metric=2,capacity=3)# Calculate MaxFlow between the source and destination nodes# Flows will be placed only on the shortest pathsmax_flow=calc_max_flow(g,"A","C",shortest_path=True)# We can verify that the result is as expectedassertmax_flow==3.0Calculate MaxFlow balancing flows equally across the shortest paths between the source and destination nodes# Required importsfromngraph.lib.graphimportMultiDiGraphfromngraph.lib.max_flowimportcalc_max_flowfromngraph.lib.commonimportFlowPlacement# Create a graph with parallel edges# Metric:#      [1,1]      [1,1]#   ┌────────►B─────────┐#   │                   │#   │                   ▼#   A                   C#   │                   ▲#   │   [2]        [2]  │#   └────────►D─────────┘## Capacity:#      [1,2]      [1,2]#   ┌────────►B─────────┐#   │                   │#   │                   ▼#   A                   C#   │                   ▲#   │   [3]        [3]  │#   └────────►D─────────┘g=MultiDiGraph()g.add_edge("A","B",metric=1,capacity=1)g.add_edge("B","C",metric=1,capacity=1)g.add_edge("A","B",metric=1,capacity=2)g.add_edge("B","C",metric=1,capacity=2)g.add_edge("A","D",metric=2,capacity=3)g.add_edge("D","C",metric=2,capacity=3)# Calculate MaxFlow between the source and destination nodes# Flows will be equally balanced across the shortest pathsmax_flow=calc_max_flow(g,"A","C",shortest_path=True,flow_placement=FlowPlacement.EQUAL_BALANCED)# We can verify that the result is as expectedassertmax_flow==2.0Place traffic demands on a graphPlace traffic demands leveraging all possible paths in a graph# Required importsfromngraph.lib.graphimportMultiDiGraphfromngraph.lib.commonimportinit_flow_graphfromngraph.lib.demandimportFlowPolicyConfig,Demand,get_flow_policyfromngraph.lib.flowimportFlowIndex# Create a graph# Metric:#     [1]        [1]#   ┌──────►B◄──────┐#   │               │#   │               │#   │               │#   ▼      [1]      ▼#   A◄─────────────►C## Capacity:#     [15]      [15]#   ┌──────►B◄──────┐#   │               │#   │               │#   │               │#   ▼      [5]      ▼#   A◄─────────────►Cg=MultiDiGraph()g.add_edge("A","B",metric=1,capacity=15,label="1")g.add_edge("B","A",metric=1,capacity=15,label="1")g.add_edge("B","C",metric=1,capacity=15,label="2")g.add_edge("C","B",metric=1,capacity=15,label="2")g.add_edge("A","C",metric=1,capacity=5,label="3")g.add_edge("C","A",metric=1,capacity=5,label="3")# Initialize a flow graphr=init_flow_graph(g)# Create traffic demandsdemands=[Demand("A","C",20,),Demand("C","A",20,),]# Place traffic demands onto the flow graphfordemandindemands:# Create a flow policy with required parameters or# use one of the predefined policies from FlowPolicyConfigflow_policy=get_flow_policy(FlowPolicyConfig.TE_UCMP_UNLIM)# Place demand using the flow policydemand.place(r,flow_policy)# We can verify that all demands were placed as expectedfordemandindemands:assertdemand.placed_demand==20assertr.get_edges()=={0:("A","B",0,{"capacity":15,"flow":15.0,"flows":{FlowIndex(src_node="A",dst_node="C",flow_class=0,flow_id=1):15.0},"label":"1","metric":1,},),1:("B","A",1,{"capacity":15,"flow":15.0,"flows":{FlowIndex(src_node="C",dst_node="A",flow_class=0,flow_id=1):15.0},"label":"1","metric":1,},),2:("B","C",2,{"capacity":15,"flow":15.0,"flows":{FlowIndex(src_node="A",dst_node="C",flow_class=0,flow_id=1):15.0},"label":"2","metric":1,},),3:("C","B",3,{"capacity":15,"flow":15.0,"flows":{FlowIndex(src_node="C",dst_node="A",flow_class=0,flow_id=1):15.0},"label":"2","metric":1,},),4:("A","C",4,{"capacity":5,"flow":5.0,"flows":{FlowIndex(src_node="A",dst_node="C",flow_class=0,flow_id=0):5.0},"label":"3","metric":1,},),5:("C","A",5,{"capacity":5,"flow":5.0,"flows":{FlowIndex(src_node="C",dst_node="A",flow_class=0,flow_id=0):5.0},"label":"3","metric":1,},),}