Skip to content

Commit 2f239a0

Browse files
committed
finishing migration for 0.9.0
1 parent 3133514 commit 2f239a0

File tree

12 files changed

+150
-359
lines changed

12 files changed

+150
-359
lines changed

docs/getting-started/tutorial.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Let's start by defining a simple two-tier Clos (leaf-spine) fabric:
1010
from ngraph.scenario import Scenario
1111

1212
scenario_yaml = """
13+
seed: 42 # Optional: ensures reproducible results for debugging/testing
14+
1315
network:
1416
name: "Two-Tier Clos Fabric"
1517
groups:
@@ -76,9 +78,10 @@ blueprints:
7678
capacity: 40
7779
cost: 1
7880
81+
seed: 42 # Optional: ensures reproducible results for debugging/testing
82+
7983
network:
8084
name: "Three-Tier Clos Fabric"
81-
seed: 42 # Optional: ensures reproducible results for debugging/testing
8285
groups:
8386
pod[1-2]: # Creates pod1 and pod2
8487
use_blueprint: clos_pod

docs/reference/api-full.md

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Quick links:
1212
- [CLI Reference](cli.md)
1313
- [DSL Reference](dsl.md)
1414

15-
Generated from source code on: August 11, 2025 at 21:22 UTC
15+
Generated from source code on: August 12, 2025 at 16:01 UTC
1616

1717
Modules auto-discovered: 67
1818

@@ -114,6 +114,34 @@ Example (YAML-like):
114114
- `get(self, name: 'str') -> 'Optional[Component]'` - Retrieves a Component by its name from the library.
115115
- `merge(self, other: 'ComponentsLibrary', override: 'bool' = True) -> 'ComponentsLibrary'` - Merges another ComponentsLibrary into this one. By default (override=True),
116116

117+
### resolve_hw_component(attrs: 'Dict[str, Any]', library: 'ComponentsLibrary') -> 'Tuple[Optional[Component], float]'
118+
119+
Resolve hardware component and multiplier from entity attributes.
120+
121+
Looks up ``attrs['hw_component']`` in the provided ``library``. If present,
122+
also reads an optional ``attrs['hw_count']`` multiplier. The multiplier
123+
defaults to 1 if not provided.
124+
125+
Args:
126+
attrs: Attribute mapping from a node or link.
127+
library: Component library used for lookups.
128+
129+
Returns:
130+
A tuple ``(component, hw_count)`` where ``component`` is ``None`` if
131+
``hw_component`` is absent or unknown, and ``hw_count`` is a positive
132+
float multiplier (defaults to 1.0).
133+
134+
### totals_with_multiplier(comp: 'Component', hw_count: 'float') -> 'Tuple[float, float, float]'
135+
136+
Return (capex, power_watts, capacity) totals multiplied by ``hw_count``.
137+
138+
Args:
139+
comp: Component definition (may include nested children and internal ``count``).
140+
hw_count: External multiplier (e.g., number of modules used for a link or node).
141+
142+
Returns:
143+
Tuple of total capex, total power (typical), and total capacity as floats.
144+
117145
---
118146

119147
## ngraph.config
@@ -974,7 +1002,7 @@ Returns:
9741002

9751003
Maximum-flow computation via iterative shortest-path augmentation.
9761004

977-
Implements a practical EdmondsKarp-like procedure using SPF with capacity
1005+
Implements a practical Edmonds-Karp-like procedure using SPF with capacity
9781006
constraints and configurable flow-splitting across equal-cost parallel edges.
9791007
Provides helpers for saturated-edge detection and simple sensitivity analysis.
9801008

@@ -2083,7 +2111,9 @@ or by risk-group children.
20832111

20842112
### FailureCondition
20852113

2086-
Alias for the shared condition dataclass for backward compatibility.
2114+
Alias to the shared condition dataclass.
2115+
2116+
This maintains a consistent import path within the failure policy module.
20872117

20882118
**Attributes:**
20892119

@@ -2641,10 +2671,15 @@ Attributes:
26412671

26422672
## ngraph.workflow.cost_power_efficiency
26432673

2644-
Workflow step to compute cost/power efficiency metrics.
2674+
Workflow step to compute cost/power efficiency metrics and optional HW inventory.
2675+
2676+
Computes total capex and power for the selected network inventory (all or only
2677+
active), and normalizes by a provided delivered-bandwidth figure (e.g., BAC at
2678+
availability target).
26452679

2646-
Computes total capex and power for the active network inventory, and normalizes
2647-
by a provided delivered-bandwidth figure (e.g., BAC at availability target).
2680+
Optionally collects node and/or link hardware entries to provide an inventory
2681+
view of hardware usage. Each entry includes hardware capacity, allocated
2682+
capacity, typical and maximum power, component name, and component count.
26482683

26492684
This step does not compute BAC itself; it expects callers to pass the delivered
26502685
bandwidth value explicitly or to point to a prior step result.
@@ -2657,16 +2692,27 @@ YAML Configuration Example:
26572692
name: "cost_power_efficiency" # Optional custom name
26582693
delivered_bandwidth_gbps: 10000 # Optional explicit denominator (float)
26592694
delivered_bandwidth_key: "delivered_bandwidth_gbps" # Lookup key in results
2660-
include_disabled: true # Whether to include disabled nodes/links in totals
2695+
include_disabled: true # Whether to include disabled nodes/links
2696+
collect_node_hw_entries: true # Optional: collect per-node HW entries
2697+
collect_link_hw_entries: false # Optional: collect per-link HW entries
26612698
```
26622699

2663-
Results stored in `scenario.results` under the step name:
2700+
Results stored in `scenario.results`:
26642701

26652702
- total_capex: Sum of component capex (float)
26662703
- total_power_watts: Sum of component power (float)
26672704
- delivered_bandwidth_gbps: Denominator used for normalization (float)
26682705
- dollars_per_gbit: Normalized capex (float, inf if denominator <= 0)
26692706
- watts_per_gbit: Normalized power (float, inf if denominator <= 0)
2707+
- node_hw_entries: Optional list of node-level hardware dicts with keys:
2708+
2709+
node, hw_component, hw_count, hw_capacity, allocated_capacity,
2710+
power_watts, power_watts_max
2711+
2712+
- link_hw_entries: Optional list of link-level hardware dicts with keys:
2713+
2714+
link_id, source, target, capacity, hw_component, hw_count, hw_capacity,
2715+
power_watts, power_watts_max
26702716

26712717
### CostPowerEfficiency
26722718

@@ -2681,6 +2727,10 @@ Attributes:
26812727
not present, the key is treated as a global results key.
26822728
include_disabled: If False, only enabled nodes/links are counted for totals.
26832729
Default ``True`` aggregates regardless of disabled flags.
2730+
collect_node_hw_entries: If True, store per-node hardware entries with
2731+
component, count, capacity, allocated capacity, and power metrics.
2732+
collect_link_hw_entries: If True, store per-link hardware entries with
2733+
component, count, capacity, and power metrics.
26842734

26852735
**Attributes:**
26862736

@@ -2689,6 +2739,8 @@ Attributes:
26892739
- `delivered_bandwidth_gbps` (Optional[float])
26902740
- `delivered_bandwidth_key` (str) = delivered_bandwidth_gbps
26912741
- `include_disabled` (bool) = True
2742+
- `collect_node_hw_entries` (bool) = False
2743+
- `collect_link_hw_entries` (bool) = False
26922744

26932745
**Methods:**
26942746

docs/reference/api.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ from ngraph.scenario import Scenario
2626
scenario = Scenario.from_yaml(yaml_content)
2727

2828
# Or build programmatically
29-
from ngraph.network import Network
29+
from ngraph.model.network import Network
3030
scenario = Scenario(network=Network(), workflow=[])
3131

3232
# Execute the scenario
@@ -50,7 +50,7 @@ print(scenario.results.get("NetworkStats", "node_count"))
5050
**When to use:** Core component for representing network structure. Used directly for programmatic topology creation or accessed via `scenario.network`.
5151

5252
```python
53-
from ngraph.network import Network, Node, Link
53+
from ngraph.model.network import Network, Node, Link
5454

5555
# Create network topology
5656
network = Network()
@@ -126,7 +126,7 @@ Essential analysis capabilities for network evaluation.
126126
**When to use:** Fundamental analysis for understanding network capacity, bottlenecks, and traffic engineering scenarios.
127127

128128
```python
129-
from ngraph.core.algorithms.base import FlowPlacement
129+
from ngraph.algorithms.base import FlowPlacement
130130

131131
# Basic maximum flow (returns dict)
132132
max_flow = network.max_flow(
@@ -177,7 +177,7 @@ print(f"Cost distribution: {summary.cost_distribution}")
177177
**When to use:** Simulate component failures, analyze degraded network states, or perform parallel analysis with different exclusions.
178178

179179
```python
180-
from ngraph.network_view import NetworkView
180+
from ngraph.model.view import NetworkView
181181

182182
# Create view with failed components (for failure simulation)
183183
failed_view = NetworkView.from_excluded_sets(
@@ -212,9 +212,9 @@ Sophisticated analysis capabilities using Monte Carlo methods and parallel proce
212212
**When to use:** Capacity envelope analysis, demand placement studies, component sensitivity analysis, or custom Monte Carlo simulations.
213213

214214
```python
215-
from ngraph.failure_manager import FailureManager
216-
from ngraph.failure_policy import FailurePolicy, FailureRule
217-
from ngraph.results_artifacts import FailurePolicySet
215+
from ngraph.failure.manager.manager import FailureManager
216+
from ngraph.failure.policy import FailurePolicy, FailureRule
217+
from ngraph.results.artifacts import FailurePolicySet
218218

219219
# Setup failure policies
220220
policy_set = FailurePolicySet()
@@ -297,7 +297,7 @@ Working with analysis outputs and implementing custom result storage.
297297
**When to use:** Working with stored analysis results, implementing custom workflow steps, or exporting data for external analysis.
298298

299299
```python
300-
from ngraph.results_artifacts import CapacityEnvelope, FailurePatternResult
300+
from ngraph.results.artifacts import CapacityEnvelope, FailurePatternResult
301301

302302
# Access capacity envelopes from analysis results
303303
envelope_dict = scenario.results.get("CapacityEnvelopeAnalysis", "capacity_envelopes")
@@ -389,9 +389,9 @@ Advanced capabilities for custom analysis and low-level operations.
389389
**When to use:** Custom analysis requiring NetworkX integration, performance-critical algorithms, or when you need direct control over graph operations.
390390

391391
```python
392-
from ngraph.core.util import to_digraph, from_digraph
393-
from ngraph.core.algorithms.spf import spf
394-
from ngraph.core.algorithms.max_flow import calc_max_flow
392+
from ngraph.graph.convert import to_digraph, from_digraph
393+
from ngraph.algorithms.spf import spf
394+
from ngraph.algorithms.max_flow import calc_max_flow
395395

396396
# Convert to NetworkX for custom algorithms
397397
nx_graph = to_digraph(scenario.network.to_strict_multidigraph())

docs/reference/dsl.md

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ network:
6161
hw_type: "router_model_B"
6262
```
6363

64+
Recognized keys for each node entry:
65+
66+
- `disabled`: boolean (optional)
67+
- `attrs`: mapping of attributes (optional)
68+
- `risk_groups`: list of risk-group names (optional)
69+
6470
**Individual Links:**
6571

6672
```yaml
@@ -76,6 +82,12 @@ network:
7682
media_type: "fiber"
7783
```
7884

85+
Recognized keys for each link entry:
86+
87+
- `source`, `target`: node names (required)
88+
- `link_params`: mapping with only these keys allowed: `capacity`, `cost`, `disabled`, `risk_groups`, `attrs`
89+
- `link_count`: integer number of parallel links to create (optional; default 1)
90+
7991
### Group-Based Definitions
8092

8193
**Node Groups:**
@@ -106,9 +118,12 @@ network:
106118
link_params:
107119
capacity: 10
108120
cost: 1
121+
# Only the following keys are allowed inside link_params:
122+
# capacity, cost, disabled, risk_groups, attrs
109123
- source: /switches
110124
target: /switches
111125
pattern: "one_to_one" # Connect switches pairwise
126+
link_count: 2 # Create 2 parallel links per adjacency (optional)
112127
link_params:
113128
capacity: 40
114129
cost: 1
@@ -148,11 +163,16 @@ network:
148163
Notes:
149164

150165
- `path` uses the same semantics as before: regex on node name or `attr:<name>` directive grouping.
151-
- Supported operators: `==`, `!=`, `<`, `<=`, `>`, `>=`, `contains`, `not_contains`, `any_value`, `no_value`.
166+
- `match.conditions` uses the failure-policy language (same operators as below): `==`, `!=`, `<`, `<=`, `>`, `>=`, `contains`, `not_contains`, `any_value`, `no_value`.
152167
- Conditions evaluate over a flat view of node attributes combining top-level fields (`name`, `disabled`, `risk_groups`) and `node.attrs`.
168+
- `logic` in the `match` block accepts `"and"` or `"or"` (default `"or"`).
153169
- Selectors filter node candidates before the adjacency `pattern` is applied.
154170
- Cross-endpoint predicates (e.g., comparing a source attribute to a target attribute) are not supported.
155171

172+
Path semantics inside blueprints:
173+
174+
- Within a blueprint's `adjacency`, a leading `/` is treated as relative to the blueprint instantiation path, not a global root. For example, if a blueprint is used under group `pod1`, then `source: /leaf` resolves to `pod1/leaf`.
175+
156176
Example with OR logic to match multiple roles:
157177

158178
```yaml
@@ -191,15 +211,14 @@ Create multiple similar groups using bracket notation:
191211
```yaml
192212
network:
193213
groups:
194-
dc[1-3]/rack[a-b]: # Creates dc1/racka, dc1/rackb, dc2/racka, etc.
214+
dc[1-3]/rack[a,b]: # Creates dc1/racka, dc1/rackb, dc2/racka, etc.
195215
node_count: 4
196216
name_template: "srv-{node_num}"
197217
```
198218

199219
**Expansion Types:**
200220

201221
- Numeric ranges: `[1-4]` → 1, 2, 3, 4
202-
- Character ranges: `[a-c]` → a, b, c
203222
- Explicit lists: `[red,blue,green]` → red, blue, green
204223

205224
### Variable Expansion in Adjacency
@@ -280,14 +299,20 @@ network:
280299
link_overrides:
281300
- source: "^pod1/leaf/.*$"
282301
target: "^pod1/spine/.*$"
283-
capacity: 100 # Override capacity
302+
link_params:
303+
capacity: 100 # Override capacity
284304
- source: ".*/spine/.*"
285305
target: ".*/spine/.*"
286306
any_direction: true # Bidirectional matching
287307
link_params:
288308
cost: 5
289309
attrs:
290310
link_type: "backbone"
311+
312+
Notes:
313+
314+
- For `link_overrides`, only the keys `source`, `target`, `link_params`, and optional `any_direction` are allowed at the top level. All parameter changes must be nested under `link_params`.
315+
- `any_direction` defaults to `true` if omitted.
291316
```
292317
293318
## `components` - Hardware Library
@@ -444,29 +469,35 @@ Define failure policies for resilience testing:
444469
```yaml
445470
failure_policy_set:
446471
single_link_failure:
447-
rules:
448-
- entity_scope: "link"
449-
rule_type: "choice"
450-
count: 1
472+
modes: # Weighted modes; exactly one mode fires per iteration
473+
- weight: 1.0
474+
rules:
475+
- entity_scope: "link"
476+
rule_type: "choice"
477+
count: 1
451478
452479
random_failures:
453-
fail_risk_groups: true
454-
rules:
455-
- entity_scope: "node"
456-
rule_type: "random"
457-
probability: 0.001
458-
- entity_scope: "link"
459-
rule_type: "random"
460-
probability: 0.002
480+
fail_risk_groups: true # Optional expansion by shared-risk groups
481+
modes:
482+
- weight: 1.0
483+
rules:
484+
- entity_scope: "node"
485+
rule_type: "random"
486+
probability: 0.001
487+
- entity_scope: "link"
488+
rule_type: "random"
489+
probability: 0.002
461490
462491
maintenance_scenario:
463-
rules:
464-
- entity_scope: "node"
465-
conditions:
466-
- attr: "maintenance_mode"
467-
operator: "=="
468-
value: "scheduled"
469-
rule_type: "all"
492+
modes:
493+
- weight: 1.0
494+
rules:
495+
- entity_scope: "node"
496+
conditions:
497+
- attr: "maintenance_mode"
498+
operator: "=="
499+
value: "scheduled"
500+
rule_type: "all"
470501
```
471502

472503
**Rule Types:**
@@ -475,6 +506,12 @@ failure_policy_set:
475506
- `choice`: Select specific count of entities
476507
- `random`: Select entities with given probability
477508

509+
Notes:
510+
511+
- Policies are mode-based. Each mode has a non-negative `weight`. One mode is chosen per iteration with probability proportional to weights, then all rules in that mode are applied and their selections are unioned.
512+
- Each rule has `entity_scope` ("node" | "link" | "risk_group"), optional `logic` ("and" | "or"; defaults to "or"), optional `conditions`, and one of `rule_type` parameters (`count` for choice, `probability` for random). `weight_by` can be provided for weighted sampling in `choice` rules.
513+
- Condition language is the same as used in adjacency `match` selectors (see below) and supports: `==`, `!=`, `<`, `<=`, `>`, `>=`, `contains`, `not_contains`, `any_value`, `no_value`. Conditions evaluate on a flat attribute mapping that includes top-level fields and `attrs`.
514+
478515
**Conditions:**
479516

480517
- Target entities based on attributes

ngraph/algorithms/max_flow.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Maximum-flow computation via iterative shortest-path augmentation.
22
3-
Implements a practical EdmondsKarp-like procedure using SPF with capacity
3+
Implements a practical Edmonds-Karp-like procedure using SPF with capacity
44
constraints and configurable flow-splitting across equal-cost parallel edges.
55
Provides helpers for saturated-edge detection and simple sensitivity analysis.
66
"""

0 commit comments

Comments
 (0)