Skip to content

Commit b3f203b

Browse files
committed
Added a notebook with examples and further improved resilience of run.sh
1 parent ca373c2 commit b3f203b

File tree

2 files changed

+412
-27
lines changed

2 files changed

+412
-27
lines changed

notebooks/lib_examples.ipynb

Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# NetGraph Library Examples\n",
8+
"\n",
9+
"This notebook contains examples of using the NetGraph library to create and manipulate graphs, calculate maximum flow, and place traffic demands."
10+
]
11+
},
12+
{
13+
"cell_type": "code",
14+
"execution_count": null,
15+
"metadata": {},
16+
"outputs": [],
17+
"source": [
18+
"# Required imports\n",
19+
"from ngraph.lib.graph import MultiDiGraph\n",
20+
"from ngraph.lib.max_flow import calc_max_flow\n",
21+
"\n",
22+
"# Create a graph with parallel edges\n",
23+
"# Metric:\n",
24+
"# [1,1] [1,1]\n",
25+
"# ┌────────►B─────────┐\n",
26+
"# │ │\n",
27+
"# │ ▼\n",
28+
"# A C\n",
29+
"# │ ▲\n",
30+
"# │ [2] [2] │\n",
31+
"# └────────►D─────────┘\n",
32+
"#\n",
33+
"# Capacity:\n",
34+
"# [1,2] [1,2]\n",
35+
"# ┌────────►B─────────┐\n",
36+
"# │ │\n",
37+
"# │ ▼\n",
38+
"# A C\n",
39+
"# │ ▲\n",
40+
"# │ [3] [3] │\n",
41+
"# └────────►D─────────┘\n",
42+
"\n",
43+
"g = MultiDiGraph()\n",
44+
"g.add_edge(\"A\", \"B\", metric=1, capacity=1)\n",
45+
"g.add_edge(\"B\", \"C\", metric=1, capacity=1)\n",
46+
"g.add_edge(\"A\", \"B\", metric=1, capacity=2)\n",
47+
"g.add_edge(\"B\", \"C\", metric=1, capacity=2)\n",
48+
"g.add_edge(\"A\", \"D\", metric=2, capacity=3)\n",
49+
"g.add_edge(\"D\", \"C\", metric=2, capacity=3)\n",
50+
"\n",
51+
"# Calculate MaxFlow between the source and destination nodes\n",
52+
"max_flow = calc_max_flow(g, \"A\", \"C\")\n",
53+
"\n",
54+
"# We can verify that the result is as expected\n",
55+
"assert max_flow == 6.0"
56+
]
57+
},
58+
{
59+
"cell_type": "code",
60+
"execution_count": null,
61+
"metadata": {},
62+
"outputs": [],
63+
"source": [
64+
"# Required imports\n",
65+
"from ngraph.lib.graph import MultiDiGraph\n",
66+
"from ngraph.lib.max_flow import calc_max_flow\n",
67+
"\n",
68+
"# Create a graph with parallel edges\n",
69+
"# Metric:\n",
70+
"# [1,1] [1,1]\n",
71+
"# ┌────────►B─────────┐\n",
72+
"# │ │\n",
73+
"# │ ▼\n",
74+
"# A C\n",
75+
"# │ ▲\n",
76+
"# │ [2] [2] │\n",
77+
"# └────────►D─────────┘\n",
78+
"#\n",
79+
"# Capacity:\n",
80+
"# [1,2] [1,2]\n",
81+
"# ┌────────►B─────────┐\n",
82+
"# │ │\n",
83+
"# │ ▼\n",
84+
"# A C\n",
85+
"# │ ▲\n",
86+
"# │ [3] [3] │\n",
87+
"# └────────►D─────────┘\n",
88+
"g = MultiDiGraph()\n",
89+
"g.add_edge(\"A\", \"B\", metric=1, capacity=1)\n",
90+
"g.add_edge(\"B\", \"C\", metric=1, capacity=1)\n",
91+
"g.add_edge(\"A\", \"B\", metric=1, capacity=2)\n",
92+
"g.add_edge(\"B\", \"C\", metric=1, capacity=2)\n",
93+
"g.add_edge(\"A\", \"D\", metric=2, capacity=3)\n",
94+
"g.add_edge(\"D\", \"C\", metric=2, capacity=3)\n",
95+
"\n",
96+
"# Calculate MaxFlow between the source and destination nodes\n",
97+
"# Flows will be placed only on the shortest paths\n",
98+
"max_flow = calc_max_flow(g, \"A\", \"C\", shortest_path=True)\n",
99+
"\n",
100+
"# We can verify that the result is as expected\n",
101+
"assert max_flow == 3.0"
102+
]
103+
},
104+
{
105+
"cell_type": "code",
106+
"execution_count": null,
107+
"metadata": {},
108+
"outputs": [],
109+
"source": [
110+
"# Required imports\n",
111+
"from ngraph.lib.graph import MultiDiGraph\n",
112+
"from ngraph.lib.max_flow import calc_max_flow\n",
113+
"from ngraph.lib.common import FlowPlacement\n",
114+
"\n",
115+
"# Create a graph with parallel edges\n",
116+
"# Metric:\n",
117+
"# [1,1] [1,1]\n",
118+
"# ┌────────►B─────────┐\n",
119+
"# │ │\n",
120+
"# │ ▼\n",
121+
"# A C\n",
122+
"# │ ▲\n",
123+
"# │ [2] [2] │\n",
124+
"# └────────►D─────────┘\n",
125+
"#\n",
126+
"# Capacity:\n",
127+
"# [1,2] [1,2]\n",
128+
"# ┌────────►B─────────┐\n",
129+
"# │ │\n",
130+
"# │ ▼\n",
131+
"# A C\n",
132+
"# │ ▲\n",
133+
"# │ [3] [3] │\n",
134+
"# └────────►D─────────┘\n",
135+
"g = MultiDiGraph()\n",
136+
"g.add_edge(\"A\", \"B\", metric=1, capacity=1)\n",
137+
"g.add_edge(\"B\", \"C\", metric=1, capacity=1)\n",
138+
"g.add_edge(\"A\", \"B\", metric=1, capacity=2)\n",
139+
"g.add_edge(\"B\", \"C\", metric=1, capacity=2)\n",
140+
"g.add_edge(\"A\", \"D\", metric=2, capacity=3)\n",
141+
"g.add_edge(\"D\", \"C\", metric=2, capacity=3)\n",
142+
"\n",
143+
"# Calculate MaxFlow between the source and destination nodes\n",
144+
"# Flows will be equally balanced across the shortest paths\n",
145+
"max_flow = calc_max_flow(\n",
146+
" g, \"A\", \"C\", shortest_path=True, flow_placement=FlowPlacement.EQUAL_BALANCED\n",
147+
")\n",
148+
"\n",
149+
"# We can verify that the result is as expected\n",
150+
"assert max_flow == 2.0"
151+
]
152+
},
153+
{
154+
"cell_type": "code",
155+
"execution_count": null,
156+
"metadata": {},
157+
"outputs": [],
158+
"source": [
159+
"# Required imports\n",
160+
"from ngraph.lib.graph import MultiDiGraph\n",
161+
"from ngraph.lib.common import init_flow_graph\n",
162+
"from ngraph.lib.demand import FlowPolicyConfig, Demand, get_flow_policy\n",
163+
"from ngraph.lib.flow import FlowIndex\n",
164+
"\n",
165+
"# Create a graph\n",
166+
"# Metric:\n",
167+
"# [1] [1]\n",
168+
"# ┌──────►B◄──────┐\n",
169+
"# │ │\n",
170+
"# │ │\n",
171+
"# │ │\n",
172+
"# ▼ [1] ▼\n",
173+
"# A◄─────────────►C\n",
174+
"#\n",
175+
"# Capacity:\n",
176+
"# [15] [15]\n",
177+
"# ┌──────►B◄──────┐\n",
178+
"# │ │\n",
179+
"# │ │\n",
180+
"# │ │\n",
181+
"# ▼ [5] ▼\n",
182+
"# A◄─────────────►C\n",
183+
"g = MultiDiGraph()\n",
184+
"g.add_edge(\"A\", \"B\", metric=1, capacity=15, label=\"1\")\n",
185+
"g.add_edge(\"B\", \"A\", metric=1, capacity=15, label=\"1\")\n",
186+
"g.add_edge(\"B\", \"C\", metric=1, capacity=15, label=\"2\")\n",
187+
"g.add_edge(\"C\", \"B\", metric=1, capacity=15, label=\"2\")\n",
188+
"g.add_edge(\"A\", \"C\", metric=1, capacity=5, label=\"3\")\n",
189+
"g.add_edge(\"C\", \"A\", metric=1, capacity=5, label=\"3\")\n",
190+
"\n",
191+
"# Initialize a flow graph\n",
192+
"r = init_flow_graph(g)\n",
193+
"\n",
194+
"# Create traffic demands\n",
195+
"demands = [\n",
196+
" Demand(\n",
197+
" \"A\",\n",
198+
" \"C\",\n",
199+
" 20,\n",
200+
" ),\n",
201+
" Demand(\n",
202+
" \"C\",\n",
203+
" \"A\",\n",
204+
" 20,\n",
205+
" ),\n",
206+
"]\n",
207+
"\n",
208+
"# Place traffic demands onto the flow graph\n",
209+
"for demand in demands:\n",
210+
" # Create a flow policy with required parameters or\n",
211+
" # use one of the predefined policies from FlowPolicyConfig\n",
212+
" flow_policy = get_flow_policy(FlowPolicyConfig.TE_UCMP_UNLIM)\n",
213+
"\n",
214+
" # Place demand using the flow policy\n",
215+
" demand.place(r, flow_policy)\n",
216+
"\n",
217+
"# We can verify that all demands were placed as expected\n",
218+
"for demand in demands:\n",
219+
" assert demand.placed_demand == 20\n",
220+
"\n",
221+
"assert r.get_edges() == {\n",
222+
" 0: (\n",
223+
" \"A\",\n",
224+
" \"B\",\n",
225+
" 0,\n",
226+
" {\n",
227+
" \"capacity\": 15,\n",
228+
" \"flow\": 15.0,\n",
229+
" \"flows\": {\n",
230+
" FlowIndex(src_node=\"A\", dst_node=\"C\", flow_class=0, flow_id=1): 15.0\n",
231+
" },\n",
232+
" \"label\": \"1\",\n",
233+
" \"metric\": 1,\n",
234+
" },\n",
235+
" ),\n",
236+
" 1: (\n",
237+
" \"B\",\n",
238+
" \"A\",\n",
239+
" 1,\n",
240+
" {\n",
241+
" \"capacity\": 15,\n",
242+
" \"flow\": 15.0,\n",
243+
" \"flows\": {\n",
244+
" FlowIndex(src_node=\"C\", dst_node=\"A\", flow_class=0, flow_id=1): 15.0\n",
245+
" },\n",
246+
" \"label\": \"1\",\n",
247+
" \"metric\": 1,\n",
248+
" },\n",
249+
" ),\n",
250+
" 2: (\n",
251+
" \"B\",\n",
252+
" \"C\",\n",
253+
" 2,\n",
254+
" {\n",
255+
" \"capacity\": 15,\n",
256+
" \"flow\": 15.0,\n",
257+
" \"flows\": {\n",
258+
" FlowIndex(src_node=\"A\", dst_node=\"C\", flow_class=0, flow_id=1): 15.0\n",
259+
" },\n",
260+
" \"label\": \"2\",\n",
261+
" \"metric\": 1,\n",
262+
" },\n",
263+
" ),\n",
264+
" 3: (\n",
265+
" \"C\",\n",
266+
" \"B\",\n",
267+
" 3,\n",
268+
" {\n",
269+
" \"capacity\": 15,\n",
270+
" \"flow\": 15.0,\n",
271+
" \"flows\": {\n",
272+
" FlowIndex(src_node=\"C\", dst_node=\"A\", flow_class=0, flow_id=1): 15.0\n",
273+
" },\n",
274+
" \"label\": \"2\",\n",
275+
" \"metric\": 1,\n",
276+
" },\n",
277+
" ),\n",
278+
" 4: (\n",
279+
" \"A\",\n",
280+
" \"C\",\n",
281+
" 4,\n",
282+
" {\n",
283+
" \"capacity\": 5,\n",
284+
" \"flow\": 5.0,\n",
285+
" \"flows\": {\n",
286+
" FlowIndex(src_node=\"A\", dst_node=\"C\", flow_class=0, flow_id=0): 5.0\n",
287+
" },\n",
288+
" \"label\": \"3\",\n",
289+
" \"metric\": 1,\n",
290+
" },\n",
291+
" ),\n",
292+
" 5: (\n",
293+
" \"C\",\n",
294+
" \"A\",\n",
295+
" 5,\n",
296+
" {\n",
297+
" \"capacity\": 5,\n",
298+
" \"flow\": 5.0,\n",
299+
" \"flows\": {\n",
300+
" FlowIndex(src_node=\"C\", dst_node=\"A\", flow_class=0, flow_id=0): 5.0\n",
301+
" },\n",
302+
" \"label\": \"3\",\n",
303+
" \"metric\": 1,\n",
304+
" },\n",
305+
" ),\n",
306+
"}"
307+
]
308+
}
309+
],
310+
"metadata": {
311+
"kernelspec": {
312+
"display_name": "Python 3 (ipykernel)",
313+
"language": "python",
314+
"name": "python3"
315+
},
316+
"language_info": {
317+
"codemirror_mode": {
318+
"name": "ipython",
319+
"version": 3
320+
},
321+
"file_extension": ".py",
322+
"mimetype": "text/x-python",
323+
"name": "python",
324+
"nbconvert_exporter": "python",
325+
"pygments_lexer": "ipython3",
326+
"version": "3.13.1"
327+
}
328+
},
329+
"nbformat": 4,
330+
"nbformat_minor": 2
331+
}

0 commit comments

Comments
 (0)