@@ -10,19 +10,40 @@ Quick links:
1010
1111This section provides a curated guide to NetGraph's Python API, organized by typical usage patterns.
1212
13- ## Performance Notes
13+ ## 1. Programmatic Quickstart
1414
15- NetGraph uses a ** hybrid Python+C++ architecture ** :
15+ Minimal, copy-pastable start: build a tiny network, run max-flow, and reuse a bound context.
1616
17- - ** High-level APIs** (Network, Scenario, Workflow) are pure Python with ergonomic interfaces
18- - ** Core algorithms** (shortest paths, max-flow, K-shortest paths) execute in optimized C++ via NetGraph-Core
19- - ** GIL released** during algorithm execution for true parallel processing
20- - ** Transparent integration** : You work with Python objects; Core acceleration is automatic
21-
22- All public APIs accept and return Python types (Network, Node, Link, FlowSummary, etc.).
23- The C++ layer is an implementation detail you generally don't interact with directly.
17+ ``` python
18+ from ngraph import Network, Node, Link, analyze, Mode
19+
20+ # Build a small directed network
21+ net = Network()
22+ net.add_node(Node(name = " A" ))
23+ net.add_node(Node(name = " B" ))
24+ net.add_node(Node(name = " C" ))
25+ net.add_link(Link(source = " A" , target = " B" , capacity = 10.0 , cost = 1.0 ))
26+ net.add_link(Link(source = " B" , target = " C" , capacity = 5.0 , cost = 1.0 ))
27+
28+ # One-off max-flow (unbound context)
29+ flow = analyze(net).max_flow(" ^A$" , " ^C$" , mode = Mode.COMBINE )
30+ print (flow) # {('^A$', '^C$'): 5.0}
31+
32+ # Detailed flow with cost distribution
33+ detailed = analyze(net).max_flow_detailed(" ^A$" , " ^C$" , mode = Mode.COMBINE )
34+ (_, _), summary = next (iter (detailed.items()))
35+ print (summary.total_flow, summary.cost_distribution)
36+
37+ # Bound context for repeated runs with exclusions
38+ ctx = analyze(net, source = " ^A$" , sink = " ^C$" , mode = Mode.COMBINE )
39+ baseline = ctx.max_flow()
40+ # Exclude first link by getting its ID from the network
41+ first_link_id = next (iter (net.links.keys()))
42+ degraded = ctx.max_flow(excluded_links = {first_link_id})
43+ print (" baseline" , baseline, " degraded" , degraded)
44+ ```
2445
25- ## 1 . Fundamentals
46+ ## 2 . Fundamentals
2647
2748The core components that form the foundation of most NetGraph programs.
2849
@@ -66,9 +87,9 @@ from ngraph import Network, Node, Link, analyze
6687
6788# Create a tiny network
6889network = Network()
69- network.add_node(Node(name = " n1" ))
70- network.add_node(Node(name = " n2" ))
71- network.add_link(Link(source = " n1" , target = " n2" , capacity = 100.0 ))
90+ network.add_node(Node(name = " n1" , risk_groups = { " rack1 " } ))
91+ network.add_node(Node(name = " n2" , risk_groups = { " rack2 " } ))
92+ network.add_link(Link(source = " n1" , target = " n2" , capacity = 100.0 , risk_groups = { " fiber_bundle_A " } ))
7293
7394# Calculate maximum flow using analyze()
7495flow_result = analyze(network).max_flow(" ^n1$" , " ^n2$" )
@@ -83,6 +104,7 @@ print(flow_result) # {("^n1$", "^n2$"): 100.0}
83104** Key Concepts:**
84105
85106- ** disabled flags:** Node.disabled and Link.disabled mark components as inactive in the scenario topology (use ` excluded_nodes ` /` excluded_links ` parameters for temporary analysis-time exclusion)
107+ - ** Risk Groups:** Nodes and links can be tagged with risk group names (e.g., "rack1", "fiber_bundle") to model shared failure domains.
86108- ** Node selection:** Use regex patterns anchored at start (e.g., ` "^datacenter.*" ` ) or attribute directives (` "attr:role" ` ) to select and group nodes (see DSL Node Selection)
87109
88110### Results
@@ -110,7 +132,7 @@ print(list(all_data["steps"].keys()))
110132
111133** Integration:** Used by all workflow steps for result storage. Provides consistent access pattern for analysis outputs.
112134
113- ## 2 . Basic Analysis
135+ ## 3 . Basic Analysis
114136
115137Essential analysis capabilities for network evaluation.
116138
@@ -145,11 +167,11 @@ print(summary.cost_distribution) # Dict[float, float] mapping cost to flow volu
145167** Key Functions:**
146168
147169- ` analyze(network, *, source=None, sink=None, mode=Mode.COMBINE) ` - Create analysis context
148- - ` ctx.max_flow(source, sink, *, mode, flow_placement, shortest_path , excluded_nodes, excluded_links) ` - Maximum flow
149- - ` ctx.max_flow_detailed(...) ` - Maximum flow with cost distribution and optional min-cut
170+ - ` ctx.max_flow(source, sink, *, mode, shortest_path, require_capacity, flow_placement , excluded_nodes, excluded_links) ` - Maximum flow
171+ - ` ctx.max_flow_detailed(..., include_min_cut=False ) ` - Maximum flow with cost distribution and optional min-cut
150172- ` ctx.sensitivity(...) ` - Identify critical edges and their impact on flow
151- - ` ctx.shortest_path_cost(source, sink, *, mode, excluded_nodes, excluded_links) ` - Shortest path cost
152- - ` ctx.shortest_paths(source, sink, *, mode) ` - Full Path objects
173+ - ` ctx.shortest_path_cost(source, sink, *, mode, edge_select=ALL_MIN_COST, excluded_nodes, excluded_links) ` - Shortest path cost
174+ - ` ctx.shortest_paths(source, sink, *, mode, edge_select, split_parallel_edges ) ` - Full Path objects
153175
154176** Key Concepts:**
155177
@@ -159,6 +181,8 @@ print(summary.cost_distribution) # Dict[float, float] mapping cost to flow volu
159181- ** FlowPlacement.EQUAL_BALANCED (ECMP):** Equal split across parallel paths
160182- ** shortest_path=True:** Restricts flow to lowest-cost paths only (IP/IGP routing semantics)
161183- ** shortest_path=False:** Uses all paths progressively (TE/SDN semantics)
184+ - ** require_capacity=True:** Flow cannot exceed link capacity (default)
185+ - ** require_capacity=False:** Unconstrained flow for capacity-free analysis
162186
163187### Efficient Repeated Analysis (Bound Context)
164188
@@ -217,9 +241,9 @@ k_paths = analyze(network).k_shortest_paths(
217241
218242** Key Functions:**
219243
220- - ` ctx.shortest_path_cost(source, sink, *, mode, edge_select) ` - Cost only, no path objects
221- - ` ctx.shortest_paths(source, sink, *, mode, edge_select, split_parallel_edges) ` - Full Path objects
222- - ` ctx.k_shortest_paths(source, sink, *, max_k, max_path_cost, max_path_cost_factor) ` - Multiple paths per pair
244+ - ` ctx.shortest_path_cost(source, sink, *, mode, edge_select=ALL_MIN_COST ) ` - Cost only, no path objects
245+ - ` ctx.shortest_paths(source, sink, *, mode, edge_select=ALL_MIN_COST , split_parallel_edges=False ) ` - Full Path objects
246+ - ` ctx.k_shortest_paths(source, sink, *, mode=PAIRWISE, max_k=3 , max_path_cost, max_path_cost_factor, excluded_nodes, excluded_links ) ` - Multiple paths per pair
223247
224248### Sensitivity Analysis
225249
@@ -242,7 +266,7 @@ for pair, edge_impacts in sensitivity.items():
242266 print (f " { edge_key} : - { flow_reduction:.2f } " )
243267```
244268
245- ## 3 . Monte Carlo Analysis
269+ ## 4 . Monte Carlo Analysis
246270
247271Probabilistic failure analysis using FailureManager.
248272
@@ -251,30 +275,44 @@ Probabilistic failure analysis using FailureManager.
251275** Purpose:** Execute Monte Carlo failure scenarios and aggregate results across multiple iterations.
252276
253277``` python
254- from ngraph import Network, FailureManager
278+ from ngraph import Network, Node, Link, FailureManager
279+ from ngraph.model.failure.policy import FailurePolicy, FailureMode, FailureRule
255280from ngraph.model.failure.policy_set import FailurePolicySet
256281
282+ # Build a simple network
283+ network = Network()
284+ for name in [" A" , " B" , " C" ]:
285+ network.add_node(Node(name = name))
286+ network.add_link(Link(" A" , " B" , capacity = 100.0 ))
287+ network.add_link(Link(" B" , " C" , capacity = 100.0 ))
288+
289+ # Define failure policy: randomly choose 1 link to fail
290+ rule = FailureRule(entity_scope = " link" , rule_type = " choice" , count = 1 ) # scope can be "node", "link", or "risk_group"
291+ mode = FailureMode(weight = 1.0 , rules = [rule])
292+ policy = FailurePolicy(modes = [mode])
293+ policy_set = FailurePolicySet(policies = {" single_link" : policy})
294+
257295# Create failure manager
258296fm = FailureManager(
259297 network = network,
260- failure_policy_set = failure_policy_set ,
261- policy_name = " single_link_failure "
298+ failure_policy_set = policy_set ,
299+ policy_name = " single_link "
262300)
263301
264302# Run max-flow Monte Carlo analysis
265303results = fm.run_max_flow_monte_carlo(
266- source_path = " ^dc/.* " ,
267- sink_path = " ^edge/.* " ,
304+ source_path = " ^A$ " ,
305+ sink_path = " ^C$ " ,
268306 mode = " combine" ,
269- iterations = 1000 ,
270- parallelism = " auto " ,
307+ iterations = 100 ,
308+ parallelism = 1 ,
271309 baseline = True , # Include no-failure baseline
272- seed = 42 # For reproducibility
310+ seed = 42 # For reproducibility
273311)
274312
275313# Access results
276314for iter_result in results[" results" ]:
277- print (f " Flow: { iter_result.summary.total_placed} " )
315+ print (f " Flow: { iter_result.summary.total_placed:.1f } " )
278316```
279317
280318** Key Methods:**
@@ -283,7 +321,7 @@ for iter_result in results["results"]:
283321- ` run_demand_placement_monte_carlo(...) ` - Traffic demand placement under failures
284322- ` run_monte_carlo_analysis(analysis_func, ...) ` - Generic Monte Carlo with custom function
285323
286- ## 4 . Workflow Steps
324+ ## 5 . Workflow Steps
287325
288326Pre-built analysis steps for YAML-driven workflows.
289327
@@ -324,11 +362,33 @@ workflow:
324362 - step_type : MaximumSupportedDemand
325363 name : " find_alpha_star"
326364 matrix_name : " peak_traffic"
327- search_strategy : " bisection"
328- precision : 0.01
365+ alpha_start : 1.0
366+ growth_factor : 2.0
367+ resolution : 0.01
368+ seeds_per_alpha : 1
329369` ` `
330370
331- ## 5. Types Reference
371+ ### NetworkStats Step
372+
373+ ` ` ` yaml
374+ workflow :
375+ - step_type : NetworkStats
376+ name : " baseline_stats"
377+ include_disabled : false
378+ excluded_nodes : ["n1"]
379+ ` ` `
380+
381+ ### CostPower Step
382+
383+ ` ` ` yaml
384+ workflow :
385+ - step_type : CostPower
386+ name : " cost_power_analysis"
387+ include_disabled : false
388+ aggregation_level : 2
389+ ` ` `
390+
391+ ## 6. Types Reference
332392
333393### Enums
334394
@@ -375,10 +435,10 @@ iter_result.flows # List[FlowEntry]
375435iter_result.summary # FlowSummary
376436```
377437
378- ## 6 . Complete Example
438+ ## 7 . Complete Example
379439
380440``` python
381- from ngraph import Network, Node, Link, analyze, Mode, FlowPlacement
441+ from ngraph import Network, Node, Link, analyze, Mode
382442
383443# Build network
384444network = Network()
@@ -419,3 +479,15 @@ for pair, impacts in sensitivity.items():
419479 for edge, impact in sorted (impacts.items(), key = lambda x : - x[1 ])[:3 ]:
420480 print (f " { edge} : { impact:.1f } " )
421481```
482+
483+ ## 8. Performance Notes
484+
485+ NetGraph uses a hybrid Python+C++ architecture:
486+
487+ - ** High-level APIs** (Network, Scenario, Workflow) are pure Python
488+ - ** Core algorithms** (shortest paths, max-flow, K-shortest paths) execute in optimized C++ via NetGraph-Core
489+ - ** GIL released** during algorithm execution for parallel processing
490+ - ** Transparent integration** : You work with Python objects; Core acceleration is automatic
491+
492+ All public APIs accept and return Python types (Network, Node, Link, FlowSummary, etc.).
493+ The C++ layer is an implementation detail you generally don't interact with directly.
0 commit comments