///|
/// Scale of the external-arrival vector at which the first utilized center
/// reaches the requested utilization. None means there is no offered traffic.
pub(all) struct NetworkLoadLimit {
scale : Double?
bottleneck : Int?
node_utilizations : Array[Double]
} derive(Debug, ToJson)
///|
pub fn JacksonNetwork::load_limit(
self : JacksonNetwork,
maximum_utilization : Double,
) -> NetworkLoadLimit raise QueueError {
probability(maximum_utilization, "network utilization ceiling")
if maximum_utilization >= 1.0 {
raise Invalid("network ceiling must be below one")
}
let flows = self.solve_traffic()
let utilizations = []
let mut best : Double? = None
let mut bottleneck : Int? = None
for i in 0.. 0.0 {
let scale = checked_ratio(
maximum_utilization, utilization, "network load factor",
)
let replace = match best {
None => true
Some(value) => scale < value
}
if replace {
best = Some(scale)
bottleneck = Some(i)
}
}
}
{ scale: best, bottleneck, node_utilizations: utilizations, }
}
///|
/// Copy a network and scale only its external arrivals, retaining routing and
/// service parameters. This operation validates shapes but permits overload;
/// analyze() remains the strict stability gate.
pub fn JacksonNetwork::scaled_load(
self : JacksonNetwork,
factor : Double,
) -> JacksonNetwork raise QueueError {
self.validate()
nonnegative(factor, "network load factor")
let external = self.external.map(x => x * factor)
let copy : JacksonNetwork = {
nodes: self.nodes.copy(),
external,
routing: self.routing.map(row => row.copy()),
}
copy.validate()
copy
}
///|
pub extend NetworkLoadLimit with Debug::{to_repr}
///|
pub extend NetworkLoadLimit with ToJson::{to_json}