11from __future__ import annotations
2- from enum import IntEnum
3- from typing import (
4- Any ,
5- Dict ,
6- Iterator ,
7- List ,
8- Optional ,
9- Set ,
10- Tuple ,
11- Union ,
12- )
13- from ngraph .lib .algorithms import spf
14- from ngraph .lib .algorithms .place_flow import FlowPlacement , place_flow_on_graph
15- from ngraph .lib .graph import NodeID , EdgeID , StrictMultiDiGraph
16- from ngraph .lib .algorithms import base
17- from ngraph .lib .path_bundle import PathBundle
18- from ngraph .lib .flow_policy import FlowPolicy , FlowPolicyConfig , get_flow_policy
19-
20-
21- class DemandStatus (IntEnum ):
22- UNKNOWN = 0
23- NOT_PLACED = 1
24- PARTIAL = 2
25- PLACED = 3
2+
3+ from typing import Optional , Tuple
4+
5+ from ngraph .lib .graph import NodeID , StrictMultiDiGraph
6+ from ngraph .lib .flow_policy import FlowPolicy
267
278
289class Demand :
2910 """
30- Demand class represents a demand between two nodes. It can be realized through one or more Flows.
11+ Represents a network demand between two nodes.
12+
13+ A Demand can be realized through one or more flows.
3114 """
3215
3316 def __init__ (
@@ -36,34 +19,57 @@ def __init__(
3619 dst_node : NodeID ,
3720 volume : float ,
3821 demand_class : int = 0 ,
39- ):
22+ ) -> None :
23+ """
24+ Initializes a Demand instance.
25+
26+ Args:
27+ src_node: The source node identifier.
28+ dst_node: The destination node identifier.
29+ volume: The total volume of the demand.
30+ demand_class: An integer representing the demand's class or priority.
31+ """
4032 self .src_node : NodeID = src_node
4133 self .dst_node : NodeID = dst_node
4234 self .volume : float = volume
4335 self .demand_class : int = demand_class
44- self .placed_demand : float = 0
36+ self .placed_demand : float = 0.0
4537
46- def __lt__ (self , other : Demand ):
38+ def __lt__ (self , other : Demand ) -> bool :
39+ """Compares Demands based on their demand class."""
4740 return self .demand_class < other .demand_class
4841
4942 def __str__ (self ) -> str :
50- return f"Demand(src_node={ self .src_node } , dst_node={ self .dst_node } , volume={ self .volume } , demand_class={ self .demand_class } , placed_demand={ self .placed_demand } )"
51-
52- @property
53- def status (self ):
54- if self .placed_demand < base .MIN_FLOW :
55- return DemandStatus .NOT_PLACED
56- elif self .volume - self .placed_demand < base .MIN_FLOW :
57- return DemandStatus .PLACED
58- return DemandStatus .PARTIAL
43+ """Returns a string representation of the Demand."""
44+ return (
45+ f"Demand(src_node={ self .src_node } , dst_node={ self .dst_node } , "
46+ f"volume={ self .volume } , demand_class={ self .demand_class } , placed_demand={ self .placed_demand } )"
47+ )
5948
6049 def place (
6150 self ,
6251 flow_graph : StrictMultiDiGraph ,
6352 flow_policy : FlowPolicy ,
64- max_fraction : float = 1 ,
53+ max_fraction : float = 1.0 ,
6554 max_placement : Optional [float ] = None ,
6655 ) -> Tuple [float , float ]:
56+ """
57+ Places demand volume onto the network graph using the specified flow policy.
58+
59+ The function computes the remaining volume to place, applies any maximum
60+ placement or fraction constraints, and delegates the flow placement to the
61+ provided flow policy. It then updates the placed demand.
62+
63+ Args:
64+ flow_graph: The network graph on which flows are placed.
65+ flow_policy: The flow policy used to place the demand.
66+ max_fraction: Maximum fraction of the total demand volume to place in this call.
67+ max_placement: Optional absolute limit on the volume to place.
68+
69+ Returns:
70+ A tuple (placed, remaining) where 'placed' is the volume successfully placed,
71+ and 'remaining' is the volume that could not be placed.
72+ """
6773 to_place = self .volume - self .placed_demand
6874
6975 if max_placement is not None :
@@ -72,6 +78,8 @@ def place(
7278 if max_fraction > 0 :
7379 to_place = min (to_place , self .volume * max_fraction )
7480 else :
81+ # When max_fraction is non-positive, place the entire volume only if infinite;
82+ # otherwise, no placement is performed.
7583 to_place = self .volume if self .volume == float ("inf" ) else 0
7684
7785 flow_policy .place_demand (
0 commit comments