API Documentation

This section provides detailed API documentation for all LINE Solver Python modules.

Distribution Module (line_solver.distributions)

Pure Python probability distributions for LINE queueing network models.

This package provides all probability distributions without requiring pure Python without Java dependencies and converted to Java only when needed (e.g., when running a solver

Usage:

from line_solver.distributions import Exp, Erlang, HyperExp from line_solver.distributions import Poisson, Geometric from line_solver.distributions import PH, MAP, Coxian

# Create distributions in pure Python service = Exp(rate=2.0) arrival = Erlang(mean=1.0, phases=3)

# Distributions can be converted to Java when needed

class Distribution[source]

Bases: ABC

Base class for all probability distributions.

This class provides the common interface for all probability distributions in LINE, including service time distributions and inter-arrival time distributions.

Initialize a new distribution.

__init__()[source]

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the cumulative distribution function at point x.

evalPDF(x)[source]

Evaluate the probability density function at point x.

eval_pmf(x)[source]

Evaluate the probability mass function at point x (snake_case alias for evalPMF; dispatches to the concrete distribution’s override).

abstractmethod getMean()[source]

Get the mean (expected value) of the distribution.

getRate()[source]

Get the rate parameter (1/mean).

For immediate (zero-mean) distributions, returns GlobalConstants.Immediate (a large but finite value) to avoid numerical issues with infinite rates. This matches MATLAB’s behavior.

getSCV()[source]

Get the squared coefficient of variation (SCV).

SCV = Var[X] / E[X]^2

getSkew()[source]

Get the skewness of the distribution.

getSupport()[source]

Get the support range [min, max] of the distribution.

abstractmethod getVar()[source]

Get the variance of the distribution.

get_mean()[source]

Get the mean (expected value) of the distribution.

get_rate()

Get the rate parameter (1/mean).

For immediate (zero-mean) distributions, returns GlobalConstants.Immediate (a large but finite value) to avoid numerical issues with infinite rates. This matches MATLAB’s behavior.

get_scv()

Get the squared coefficient of variation (SCV).

SCV = Var[X] / E[X]^2

get_skew()

Get the skewness of the distribution.

get_support()

Get the support range [min, max] of the distribution.

get_var()[source]

Get the variance of the distribution.

isContinuous()[source]

Check if this distribution is continuous.

isDisabled()[source]

Check if this distribution is equivalent to a Disabled distribution.

Mirrors MATLAB Distribution.isDisabled (isnan(getMean(self))): a distribution whose mean is not a number carries no usable process representation, so the struct records it as disabled rather than mislabelling it. Returning a hardcoded False, as this did, made refreshStruct treat such a distribution as an ordinary one.

isDiscrete()[source]

Check if this distribution is discrete.

isImmediate()[source]

Check if this distribution represents immediate service.

property name: str

Get the distribution name.

sample(n=1, rng=None)[source]

Generate random samples from this distribution.

Parameters:
Returns:

Array of n random samples.

Return type:

numpy.ndarray

class ContinuousDistribution[source]

Bases: Distribution

Base class for continuous probability distributions.

Initialize a new distribution.

evalLST(s)[source]

Laplace-Stieltjes transform E[e^{-sX}] evaluated at s.

Generic numerical fallback: rectangle-rule integration of evalPDF over [0, 20*mean] with 1000 points. Subclasses with a closed form or a MATLAB-matching numerical scheme (Pareto/Lognormal/Weibull) override this. Used by the G/M/1 MVA solver’s sigma-root for non-PH arrivals.

evalLaplaceTransform(s)

Laplace-Stieltjes transform E[e^{-sX}] evaluated at s.

Generic numerical fallback: rectangle-rule integration of evalPDF over [0, 20*mean] with 1000 points. Subclasses with a closed form or a MATLAB-matching numerical scheme (Pareto/Lognormal/Weibull) override this. Used by the G/M/1 MVA solver’s sigma-root for non-PH arrivals.

isContinuous()[source]

Check if this distribution is continuous.

isDiscrete()[source]

Check if this distribution is discrete.

class DiscreteDistribution[source]

Bases: Distribution

Base class for discrete probability distributions.

Initialize a new distribution.

evalPMF(x)[source]

Evaluate the probability mass function at point x.

isContinuous()[source]

Check if this distribution is continuous.

isDiscrete()[source]

Check if this distribution is discrete.

class Markovian[source]

Bases: Distribution

Base class for Markovian (phase-type) distributions.

Markovian distributions can be represented in terms of initial probability vectors and transition rate matrices.

Initialize a new distribution.

getD0()[source]

Get the D0 matrix (for MAP representations).

getD1()[source]

Get the D1 matrix (for MAP representations).

getInitProb()[source]

Get the initial probability vector.

getMu()[source]

Get the service rates in each phase.

getNumberOfPhases()[source]

Get the number of phases.

getPH()[source]

Return the phase-type representation as a dict {0: D0, 1: D1}, matching the JAR Map<Integer, Matrix> shape.

getPhi()[source]

Get the completion probabilities from each phase.

getRepresentation()[source]

Return the (D0, D1) matrix representation used in the theory of Markovian arrival processes, as a list [D0, D1] (element k corresponds to matrix D_k).

get_d0()

Get the D0 matrix (for MAP representations).

get_d1()

Get the D1 matrix (for MAP representations).

get_init_prob()

Get the initial probability vector.

get_mu()

Get the service rates in each phase.

get_number_of_phases()

Get the number of phases.

get_ph()

Return the phase-type representation as a dict {0: D0, 1: D1}, matching the JAR Map<Integer, Matrix> shape.

get_phi()

Get the completion probabilities from each phase.

get_representation()[source]

snake_case alias for getRepresentation().

class Exp(rate)[source]

Bases: ContinuousDistribution, Markovian

Exponential distribution.

The exponential distribution is the simplest continuous distribution for modeling service times in queueing systems. It has the memoryless property and SCV = 1.

Parameters:

rate (float) – The rate parameter (lambda = 1/mean).

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPDF(x)[source]

Evaluate the PDF at point x.

classmethod fitMean(mean)

Create an exponential distribution with the given mean.

Parameters:

mean (float) – Target mean.

Returns:

Exp distribution with rate = 1/mean.

Return type:

Exp

classmethod fitRate(rate)[source]

Create an exponential distribution with the given rate.

Parameters:

rate (float) – The rate parameter (lambda).

Returns:

Exp distribution with specified rate.

Return type:

Exp

classmethod fit_mean(mean)[source]

Create an exponential distribution with the given mean.

Parameters:

mean (float) – Target mean.

Returns:

Exp distribution with rate = 1/mean.

Return type:

Exp

classmethod fit_rate(rate)

Create an exponential distribution with the given rate.

Parameters:

rate (float) – The rate parameter (lambda).

Returns:

Exp distribution with specified rate.

Return type:

Exp

getD0()[source]

Get the D0 matrix for MAP representation.

getD1()[source]

Get the D1 matrix for MAP representation.

getInitProb()[source]

Get the initial probability vector.

getMean()[source]

Get the mean (1/rate).

getMu()[source]

Get the service rates in each phase.

getNumberOfPhases()[source]

Get the number of phases (1 for exponential).

getPhi()[source]

Get the completion probabilities from each phase.

getSCV()[source]

Get the squared coefficient of variation (always 1 for exponential).

getSkew()[source]

Get the skewness (always 2 for exponential).

getVar()[source]

Get the variance (1/rate^2).

get_rate()

Get the rate parameter (1/mean).

For immediate (zero-mean) distributions, returns GlobalConstants.Immediate (a large but finite value) to avoid numerical issues with infinite rates. This matches MATLAB’s behavior.

property rate: float

Get the rate parameter.

sample(n=1, rng=None)[source]

Generate random samples.

class Det(value)[source]

Bases: ContinuousDistribution

Deterministic (constant) distribution.

All service times are exactly equal to the specified value. Has SCV = 0 (no variability).

Parameters:

value (float) – The constant service time value.

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalLST(s)[source]

LST of a deterministic time: exp(-s*t). Matches MATLAB Det.evalLST.

evalPDF(x)[source]

Evaluate the PDF at point x (delta function, return inf at value).

classmethod fitMean(mean)

Create a deterministic distribution with the given mean.

Since Det has zero variance, the mean equals the constant value.

Parameters:

mean (float) – The mean (and constant value) of the distribution.

Returns:

Det distribution with the specified mean.

Return type:

Det

classmethod fit_mean(mean)[source]

Create a deterministic distribution with the given mean.

Since Det has zero variance, the mean equals the constant value.

Parameters:

mean (float) – The mean (and constant value) of the distribution.

Returns:

Det distribution with the specified mean.

Return type:

Det

getMean()[source]

Get the mean (equals the constant value).

getSCV()[source]

Get the SCV (always 0).

getSkew()[source]

Get the skewness (undefined, return 0).

getVar()[source]

Get the variance (always 0).

isImmediate()[source]

Check if this is an immediate (zero) service.

sample(n=1, rng=None)[source]

Generate random samples (all equal to value).

property value: float

Get the constant value.

class Immediate[source]

Bases: Det

Immediate (zero delay) distribution.

Represents instantaneous service with zero delay.

Initialize a new distribution.

classmethod getInstance()[source]

Get singleton instance of Immediate distribution.

classmethod get_instance()

Get singleton instance of Immediate distribution.

isImmediate()[source]

Check if this is immediate service.

class Disabled[source]

Bases: ContinuousDistribution

Disabled distribution.

Represents a disabled service (no service at all). Used for nodes that don’t serve a particular job class.

Initialize a new distribution.

classmethod getInstance()[source]

Get singleton instance of Disabled distribution.

getMean()[source]

Get the mean (infinity for disabled).

getVar()[source]

Get the variance.

classmethod get_instance()

Get singleton instance of Disabled distribution.

isDisabled()[source]

Check if this distribution is disabled.

class Erlang(phase_rate, nphases)[source]

Bases: ContinuousDistribution, Markovian

Erlang distribution (sum of k exponentials).

The Erlang distribution is the distribution of the sum of k independent exponential random variables with the same rate. It has SCV = 1/k.

Parameters:
  • phase_rate (float) – Rate parameter for each exponential phase (alpha).

  • nphases (int) – Number of sequential exponential phases (r).

Mean = nphases / phase_rate = r / alpha

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPDF(x)[source]

Evaluate the PDF at point x.

classmethod fitMeanAndOrder(mean, phases)

Create an Erlang distribution from mean and number of phases.

Parameters:
  • mean (float) – Target mean.

  • phases (int) – Number of phases (order).

Returns:

Erlang distribution with given mean and phases.

Return type:

Erlang

classmethod fitMeanAndSCV(mean, scv)

Create an Erlang distribution from mean and SCV.

For Erlang, SCV = 1/k where k is number of phases. So phases = round(1/SCV), constrained to be >= 1.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Erlang distribution with given mean and closest achievable SCV.

Return type:

Erlang

classmethod fitMeanAndScv(mean, scv)

Create an Erlang distribution from mean and SCV.

For Erlang, SCV = 1/k where k is number of phases. So phases = round(1/SCV), constrained to be >= 1.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Erlang distribution with given mean and closest achievable SCV.

Return type:

Erlang

classmethod fit_mean_and_order(mean, phases)[source]

Create an Erlang distribution from mean and number of phases.

Parameters:
  • mean (float) – Target mean.

  • phases (int) – Number of phases (order).

Returns:

Erlang distribution with given mean and phases.

Return type:

Erlang

classmethod fit_mean_and_scv(mean, scv)[source]

Create an Erlang distribution from mean and SCV.

For Erlang, SCV = 1/k where k is number of phases. So phases = round(1/SCV), constrained to be >= 1.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Erlang distribution with given mean and closest achievable SCV.

Return type:

Erlang

getD0()[source]

Get the D0 matrix for MAP representation.

getD1()[source]

Get the D1 matrix for MAP representation.

getInitProb()[source]

Get the initial probability vector.

getMean()[source]

Get the mean.

getMu()[source]

Get the service rates in each phase.

getNumberOfPhases()[source]

Get the number of phases.

getPhi()[source]

Get the completion probabilities from each phase.

getSCV()[source]

Get the SCV (1/phases).

getSkew()[source]

Get the skewness.

getVar()[source]

Get the variance.

property phases: int

Get the number of phases.

sample(n=1, rng=None)[source]

Generate random samples.

class HyperExp(p_or_probs, rate1_or_rates, rate2=None)[source]

Bases: ContinuousDistribution, Markovian

Hyperexponential distribution (mixture of exponentials).

The hyperexponential distribution is a mixture of exponential distributions. It has SCV >= 1.

Supports two calling conventions (matching MATLAB API):
  • HyperExp(p, rate1, rate2): 2-phase with probability p of rate1, probability (1-p) of rate2

  • HyperExp(probs, rates): n-phase with vectors of probabilities and rates

Parameters:
  • p_or_probs (float | list | numpy.ndarray) – For 2-phase: probability of first component (scalar). For n-phase: list/array of probabilities.

  • rate1_or_rates (float | list | numpy.ndarray) – For 2-phase: rate of first component (scalar). For n-phase: list/array of rates.

  • rate2 (float | None) – For 2-phase only: rate of second component.

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPDF(x)[source]

Evaluate the PDF at point x.

classmethod fitMeanAndSCV(mean, scv, p=0.99)

Create a 2-phase hyperexponential distribution from mean and SCV.

Uses the same algorithm as MATLAB’s map_hyperexp function.

Parameters:
  • mean (float) – Target mean (MEAN).

  • scv (float) – Target squared coefficient of variation (must be >= 1).

  • p (float) – Probability of being served in phase 1 (default: 0.99).

Returns:

HyperExp distribution with given mean and SCV.

Return type:

HyperExp

classmethod fitMeanAndSCVBalanced(mean, scv)

Create a 2-phase hyperexponential distribution with balanced means.

Uses balanced means representation where p/mu1 = (1-p)/mu2.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation (must be >= 1).

Returns:

HyperExp distribution with given mean and SCV.

Return type:

HyperExp

classmethod fitMeanAndScv(mean, scv, p=0.99)

Create a 2-phase hyperexponential distribution from mean and SCV.

Uses the same algorithm as MATLAB’s map_hyperexp function.

Parameters:
  • mean (float) – Target mean (MEAN).

  • scv (float) – Target squared coefficient of variation (must be >= 1).

  • p (float) – Probability of being served in phase 1 (default: 0.99).

Returns:

HyperExp distribution with given mean and SCV.

Return type:

HyperExp

classmethod fitMeanAndScvBalanced(mean, scv)

Create a 2-phase hyperexponential distribution with balanced means.

Uses balanced means representation where p/mu1 = (1-p)/mu2.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation (must be >= 1).

Returns:

HyperExp distribution with given mean and SCV.

Return type:

HyperExp

classmethod fit_mean_and_scv(mean, scv, p=0.99)[source]

Create a 2-phase hyperexponential distribution from mean and SCV.

Uses the same algorithm as MATLAB’s map_hyperexp function.

Parameters:
  • mean (float) – Target mean (MEAN).

  • scv (float) – Target squared coefficient of variation (must be >= 1).

  • p (float) – Probability of being served in phase 1 (default: 0.99).

Returns:

HyperExp distribution with given mean and SCV.

Return type:

HyperExp

classmethod fit_mean_and_scv_balanced(mean, scv)[source]

Create a 2-phase hyperexponential distribution with balanced means.

Uses balanced means representation where p/mu1 = (1-p)/mu2.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation (must be >= 1).

Returns:

HyperExp distribution with given mean and SCV.

Return type:

HyperExp

getD0()[source]

Get the D0 matrix for MAP representation.

getD1()[source]

Get the D1 matrix for MAP representation.

getInitProb()[source]

Get the initial probability vector.

getMean()[source]

Get the mean.

getMu()[source]

Get the service rates in each phase.

getNumberOfPhases()[source]

Get the number of phases.

getPhi()[source]

Get the completion probabilities from each phase.

getVar()[source]

Get the variance.

property means: numpy.ndarray

Get the means of each component.

property probs: numpy.ndarray

Get the probabilities of each component.

property rates: numpy.ndarray

Get the rates of each component.

sample(n=1, rng=None)[source]

Generate random samples.

class Gamma(shape, scale)[source]

Bases: ContinuousDistribution

Gamma distribution.

The gamma distribution is a two-parameter continuous distribution that generalizes the exponential and Erlang distributions.

Parameters:
  • shape (float) – Shape parameter (k or alpha).

  • scale (float) – Scale parameter (theta).

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPDF(x)[source]

Evaluate the PDF at point x.

classmethod fitMeanAndSCV(mean, scv)

Create a Gamma distribution from mean and SCV.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Gamma distribution with given mean and SCV.

Return type:

Gamma

classmethod fitMeanAndScv(mean, scv)

Create a Gamma distribution from mean and SCV.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Gamma distribution with given mean and SCV.

Return type:

Gamma

classmethod fit_mean_and_scv(mean, scv)[source]

Create a Gamma distribution from mean and SCV.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Gamma distribution with given mean and SCV.

Return type:

Gamma

getMean()[source]

Get the mean (shape * scale).

getSCV()[source]

Get the SCV (1/shape).

getSkew()[source]

Get the skewness.

getVar()[source]

Get the variance (shape * scale^2).

sample(n=1, rng=None)[source]

Generate random samples.

property scale: float

Get the scale parameter.

property shape: float

Get the shape parameter.

class Lognormal(mu, sigma)[source]

Bases: ContinuousDistribution

Lognormal distribution.

A random variable X has a lognormal distribution if log(X) is normally distributed.

Parameters:
  • mu (float) – Mean of the underlying normal distribution.

  • sigma (float) – Standard deviation of the underlying normal distribution.

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalLST(s)[source]

Numerical LST (rectangle rule, n=1000) matching MATLAB Lognormal.evalLST.

evalPDF(x)[source]

Evaluate the PDF at point x.

classmethod fitMeanAndSCV(mean, scv)

Construct a Lognormal from a target mean and squared coefficient of variation (SCV = variance/mean^2), converting to log-space (mu, sigma).

Port of MATLAB Lognormal.fitMeanAndSCV.

classmethod fitMeanAndScv(mean, scv)

Construct a Lognormal from a target mean and squared coefficient of variation (SCV = variance/mean^2), converting to log-space (mu, sigma).

Port of MATLAB Lognormal.fitMeanAndSCV.

classmethod fit_mean_and_scv(mean, scv)[source]

Construct a Lognormal from a target mean and squared coefficient of variation (SCV = variance/mean^2), converting to log-space (mu, sigma).

Port of MATLAB Lognormal.fitMeanAndSCV.

getMean()[source]

Get the mean.

getSkew()[source]

Get the skewness.

getVar()[source]

Get the variance.

property mu: float

Get the mu parameter.

sample(n=1, rng=None)[source]

Generate random samples.

property sigma: float

Get the sigma parameter.

class Pareto(alpha, scale)[source]

Bases: ContinuousDistribution

Pareto distribution.

The Pareto distribution is a power-law distribution often used to model heavy-tailed phenomena.

Parameters:
  • alpha (float) – Shape parameter (tail index).

  • scale (float) – Scale parameter (minimum value).

Initialize a new distribution.

property alpha: float

Get the alpha parameter.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalLST(s)[source]

Numerical LST (rectangle rule, n=1000) matching MATLAB Pareto.evalLST.

evalPDF(x)[source]

Evaluate the PDF at point x.

classmethod fitMeanAndSCV(mean, scv)

Create a Pareto distribution from mean and SCV.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Pareto distribution with given mean and SCV.

Return type:

Pareto

Note

For Pareto with alpha > 2: mean = alpha * scale / (alpha - 1) var = scale^2 * alpha / ((alpha - 1)^2 * (alpha - 2)) scv = var / mean^2 = 1 / (alpha * (alpha - 2))

Solving for alpha: alpha = (1 + sqrt(1 + 4*scv)) / (2*scv) Then: scale = mean * (alpha - 1) / alpha

classmethod fitMeanAndScv(mean, scv)

Create a Pareto distribution from mean and SCV.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Pareto distribution with given mean and SCV.

Return type:

Pareto

Note

For Pareto with alpha > 2: mean = alpha * scale / (alpha - 1) var = scale^2 * alpha / ((alpha - 1)^2 * (alpha - 2)) scv = var / mean^2 = 1 / (alpha * (alpha - 2))

Solving for alpha: alpha = (1 + sqrt(1 + 4*scv)) / (2*scv) Then: scale = mean * (alpha - 1) / alpha

classmethod fit_mean_and_scv(mean, scv)[source]

Create a Pareto distribution from mean and SCV.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Pareto distribution with given mean and SCV.

Return type:

Pareto

Note

For Pareto with alpha > 2: mean = alpha * scale / (alpha - 1) var = scale^2 * alpha / ((alpha - 1)^2 * (alpha - 2)) scv = var / mean^2 = 1 / (alpha * (alpha - 2))

Solving for alpha: alpha = (1 + sqrt(1 + 4*scv)) / (2*scv) Then: scale = mean * (alpha - 1) / alpha

getMean()[source]

Get the mean.

getSupport()[source]

Get the support [scale, inf).

getVar()[source]

Get the variance.

sample(n=1, rng=None)[source]

Generate random samples.

property scale: float

Get the scale parameter.

class Uniform(min_val, max_val)[source]

Bases: ContinuousDistribution

Uniform distribution on [min, max].

Parameters:
  • min_val (float) – Minimum value.

  • max_val (float) – Maximum value.

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalLST(s)[source]

LST of Uniform[min,max]: (e^{-s*min}-e^{-s*max})/(s*(max-min)). Matches MATLAB.

evalPDF(x)[source]

Evaluate the PDF at point x.

getMean()[source]

Get the mean.

getSkew()[source]

Get the skewness (always 0 for uniform).

getSupport()[source]

Get the support [min, max].

getVar()[source]

Get the variance.

property max_val: float

Get the maximum value.

property min_val: float

Get the minimum value.

sample(n=1, rng=None)[source]

Generate random samples.

class Weibull(shape, scale)[source]

Bases: ContinuousDistribution

Weibull distribution.

The Weibull distribution is commonly used in reliability engineering to model time to failure.

Parameters:
  • shape (float) – Shape parameter (k).

  • scale (float) – Scale parameter (lambda).

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalLST(s)[source]

Numerical LST (rectangle rule, n=1000) matching MATLAB Weibull.evalLST.

evalPDF(x)[source]

Evaluate the PDF at point x.

getMean()[source]

Get the mean.

getVar()[source]

Get the variance.

sample(n=1, rng=None)[source]

Generate random samples.

property scale: float

Get the scale parameter.

property shape: float

Get the shape parameter.

class Normal(mean, std)[source]

Bases: ContinuousDistribution

Normal (Gaussian) distribution.

Note: For queueing applications, a truncated or shifted version may be needed since normal distributions can take negative values.

Parameters:
  • mean (float) – Mean of the distribution.

  • std (float) – Standard deviation.

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPDF(x)[source]

Evaluate the PDF at point x.

eval_cdf(x)

Evaluate the CDF at point x.

eval_pdf(x)

Evaluate the PDF at point x.

classmethod fitMean(mean, std=1.0)[source]

Create a Normal distribution with given mean and std.

classmethod fitMeanAndStd(mean, std)[source]

Create a Normal distribution with given mean and std.

classmethod fitMeanAndVar(mean, var)[source]

Create a Normal distribution with given mean and variance.

classmethod fit_mean(mean, std=1.0)

Create a Normal distribution with given mean and std.

classmethod fit_mean_and_std(mean, std)

Create a Normal distribution with given mean and std.

classmethod fit_mean_and_var(mean, var)

Create a Normal distribution with given mean and variance.

getMean()[source]

Get the mean.

getSCV()[source]

Get the squared coefficient of variation (var/mean^2).

getSkew()[source]

Get the skewness (always 0 for normal).

getSkewness()[source]

Get the skewness (always 0 for normal).

getStd()[source]

Get the standard deviation.

getSupport()[source]

Get the support (-inf, inf).

getVar()[source]

Get the variance.

get_mean()

Get the mean (expected value) of the distribution.

get_scv()

Get the squared coefficient of variation (var/mean^2).

get_skewness()

Get the skewness (always 0 for normal).

get_std()

Get the standard deviation.

get_var()

Get the variance.

sample(n=1, rng=None)[source]

Generate random samples.

property std: float

Get the standard deviation.

class MultivariateNormal(mu, Sigma)[source]

Bases: ContinuousDistribution

Multivariate Normal (Gaussian) distribution.

Represents a d-dimensional normal distribution with mean vector mu and covariance matrix Sigma.

Parameters:

Initialize a new distribution.

property dimension: int

Get the dimensionality.

evalPDF(x)[source]

Evaluate the multivariate normal PDF at point(s) x.

Parameters:

x (list | numpy.ndarray) – Single point (1D array of length d) or multiple points (2D array of shape n x d)

Returns:

Single float for one point, or numpy array for multiple points.

Return type:

float | numpy.ndarray

eval_pdf(x)[source]

Evaluate the multivariate normal PDF at point(s) x.

classmethod fitMeanAndCovariance(mu, Sigma)[source]

Create a MultivariateNormal distribution with given mean and covariance.

classmethod fit_mean_and_covariance(mu, Sigma)

Create a MultivariateNormal distribution with given mean and covariance.

getCorrelation()[source]

Get the correlation matrix.

getCovariance()[source]

Get the covariance matrix.

getDimension()[source]

Get the dimensionality.

getMarginal(indices)[source]

Extract a marginal distribution for a subset of dimensions.

getMarginalUniv(index)[source]

Extract a univariate marginal distribution.

getMean()[source]

Get the mean of the first component (for compatibility).

getMeanVector()[source]

Get the mean vector.

getSkew()[source]

Get skewness (0 for normal).

getVar()[source]

Get the variance of the first component.

get_correlation()[source]

Get the correlation matrix.

get_covariance()[source]

Get the covariance matrix.

get_dimension()[source]

Get the dimensionality.

get_marginal(indices)[source]

Extract a marginal distribution for a subset of dimensions.

get_marginal_univ(index)[source]

Extract a univariate marginal distribution.

get_mean_vector()[source]

Get the mean vector.

sample(n=1, rng=None)[source]

Generate n samples from the multivariate normal.

Returns:

n x d matrix of samples.

Return type:

numpy.ndarray

class Prior(distributions, probabilities)[source]

Bases: ContinuousDistribution

Discrete prior distribution over alternative distributions.

Prior represents parameter uncertainty by specifying a discrete set of alternative distributions with associated probabilities. Used with the UQ solver for Bayesian-style analysis.

This is NOT a mixture distribution - each alternative represents a separate model realization.

Parameters:
  • distributions (list) – List of Distribution objects.

  • probabilities (list | numpy.ndarray) – List of probabilities (must sum to 1).

Initialize a new distribution.

property distributions: list

Get the alternative distributions.

evalCDF(t)[source]

Evaluate mixture CDF at t.

getAlternative(idx)[source]

Get the distribution at index idx.

getMean()[source]

Get prior-weighted mean (expected mean over alternatives).

getNumAlternatives()[source]

Get the number of alternative distributions.

getProbabilities()[source]

Get all probabilities.

getProbability(idx)[source]

Get the probability of alternative idx.

getSCV()[source]

Get prior-weighted SCV.

getVar()[source]

Get prior-weighted variance using law of total variance.

get_alternative(idx)

Get the distribution at index idx.

get_num_alternatives()

Get the number of alternative distributions.

get_probabilities()

Get all probabilities.

get_probability(idx)

Get the probability of alternative idx.

isPrior()[source]

Return True (used for detection by UQ solver).

isPriorDistribution()[source]

Alias for isPrior (used for detection by UQ solver).

is_prior()

Return True (used for detection by UQ solver).

is_prior_distribution()

Alias for isPrior (used for detection by UQ solver).

property probabilities: numpy.ndarray

Get the probabilities.

sample(n=1, rng=None)[source]

Sample from prior (mixture sampling).

class Expolynomial(density, eft, lft)[source]

Bases: ContinuousDistribution

Expolynomial distribution with density f(x) = sum ci * x^ai * exp(-li*x).

Represents an expolynomial density over a bounded domain [eft, lft], matching the Sirio/ORIS GEN expolynomial format.

Parameters:
  • density (str) – Density expression string in Sirio format.

  • eft (float) – Earliest firing time (lower bound of support).

  • lft (float) – Latest firing time (upper bound of support, use math.inf for unbounded).

Initialize a new distribution.

property density: str

Get the density expression string.

property eft: float

Get the earliest firing time.

evalCDF(x)[source]

Evaluate the CDF at point x (returns NaN - not supported).

getMean()[source]

Get the mean (returns NaN - numerical integration not supported in Python).

getRate()[source]

Get the rate 1/mean (returns NaN).

getSCV()[source]

Get the squared coefficient of variation (returns NaN).

getSupport()[source]

Get the support [eft, lft].

getVar()[source]

Get the variance (returns NaN).

property lft: float

Get the latest firing time.

sample(n=1, rng=None)[source]

Generate random samples (returns NaN - not supported).

class NHPP(breakpoints, rates, cyclic=True)[source]

Bases: ContinuousDistribution

Non-homogeneous Poisson process (NHPP) with a piecewise-constant intensity.

The intensity is a step function of the wall clock: segment i covers [breakpoints[i], breakpoints[i+1]) and carries rate rates[i], so breakpoints has one more entry than rates. With cyclic=True the schedule repeats, giving a cyclic Poisson process.

Two horizon conventions:
cyclicthe schedule repeats with period

T = breakpoints[-1] - breakpoints[0]; the active segment at time t follows from (t - breakpoints[0]) % T.

non-cyclicthe intensity is zero outside

[breakpoints[0], breakpoints[-1]), so the process emits nothing once the schedule is exhausted. A non-cyclic NHPP is therefore a transient construct: run to steady state it converges to the empty system, so callers should use a time span within the horizon.

This is NOT a renewal process. Successive intervals are dependent, because the position within the schedule carries over from one event to the next. Accordingly the scalar summaries that presuppose an i.i.d. interval distribution – getSCV, getSkew, getVar, evalCDF – are undefined and return NaN rather than a representative exponential value, which would silently misreport the process as Poisson. The schedule is the parameterisation: read it with getRateSchedule. getMean is well defined and returns the arrival-stationary (Palm) mean interval 1/timeAverageRate.

Solver support: the LDES simulation engine honours the exact schedule in both steady state (cyclic only) and transient analysis. SolverFLD honours it in getTranAvg, by injecting the intensity as a time-varying rate multiplier on the closing ODE; SolverFLD.getAvg uses the time-average rate, which is the steady state of a cyclic schedule. Every other solver rejects a model using it via the standard unsupported-feature check.

Parameters:
  • breakpoints – strictly increasing segment boundaries, length n+1.

  • rates – non-negative rate on each segment, length n.

  • cyclic (bool) – whether the schedule repeats with the horizon as period.

Initialize a new distribution.

property breakpoints: numpy.ndarray

Segment boundaries, length n+1.

property cyclic: bool

Whether the schedule repeats.

evalCDF(x)[source]

NaN; see getSCV.

evalLST(s)[source]

NaN: no i.i.d. interval distribution, so no Laplace-Stieltjes transform. Overrides the base numerical quadrature, which would integrate against an undefined CDF.

getBreakpoints()[source]

Segment boundaries, length n+1 (MATLAB/JAR accessor name).

getMean()[source]

Arrival-stationary (Palm) mean interval.

getNumSegments()[source]
getPeriod()[source]

Horizon length, which is the period when cyclic.

getProcess()[source]
getRate()[source]

Get the rate parameter (1/mean).

For immediate (zero-mean) distributions, returns GlobalConstants.Immediate (a large but finite value) to avoid numerical issues with infinite rates. This matches MATLAB’s behavior.

getRateAt(t)[source]

Rate in force at t; zero past a non-cyclic horizon.

getRateSchedule()[source]

The parameterisation of the process; the scalar summaries are not.

Model compilation recognises a schedule-bearing process by this method rather than by class name.

getRates()[source]

Per-segment rates, length n (MATLAB/JAR accessor name).

getSCV()[source]

NaN: an NHPP is not a renewal process, so there is no i.i.d. interval distribution for an SCV to summarise. Returning a representative value would report a time-varying process as an exponential one to every consumer of sn.scv.

getSkew()[source]

NaN; see getSCV.

getSkewness()[source]

NaN; see getSCV (MATLAB/JAR accessor name).

getTimeAverageRate()[source]

sum(rates*widths)/sum(widths) over the horizon.

getVar()[source]

NaN; see getSCV.

isCyclic()[source]

Whether the schedule repeats (MATLAB/JAR accessor name).

nextInterval(frm, residual)[source]

Solve int_{frm}^{frm+x} lambda(u) du = residual for x.

Walks the schedule forward, consuming the budget segment by segment. Returns 0 when a non-cyclic horizon is exhausted first, which callers read as “no further event”.

Exact for an NHPP: conditional on no event since the last one, the residual is governed by the intensity from the current instant onward, so a holding time drawn under a rate that has since changed is not a sample from this process.

property rates: numpy.ndarray

Per-segment rates, length n.

resetSampleClock()[source]

Restart the sample path at the schedule start.

sample(n=1, rng=None)[source]

Draw n successive interarrival times along ONE sample path.

The intensity depends on absolute time, so this advances an internal clock across calls: consecutive samples form a realisation of the process starting at breakpoints[0], not independent draws from a marginal. Use resetSampleClock() to restart. A non-cyclic schedule that runs out returns 0 for every remaining sample, the intensity there being zero.

class Poisson(lambda_)[source]

Bases: DiscreteDistribution

Poisson distribution.

The Poisson distribution models the number of events occurring in a fixed interval of time or space.

Parameters:

lambda – Rate parameter (mean = variance = lambda).

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPMF(x)[source]

Evaluate the probability mass function at point x.

getMean()[source]

Get the mean (equals lambda).

getSCV()[source]

Get the SCV (1/lambda).

getSkew()[source]

Get the skewness.

getSupport()[source]

Get the support [0, inf).

getVar()[source]

Get the variance (equals lambda).

property lambda_: float

Get the rate parameter.

sample(n=1, rng=None)[source]

Generate random samples.

class Geometric(p)[source]

Bases: DiscreteDistribution

Geometric distribution.

The geometric distribution models the number of failures before the first success in a sequence of Bernoulli trials.

Parameters:

p (float) – Probability of success on each trial (0 < p <= 1).

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPMF(x)[source]

Evaluate the PMF at point x (number of trials until first success).

getMean()[source]

Get the mean (1/p for number of trials).

getSkew()[source]

Get the skewness.

getSupport()[source]

Get the support [1, inf).

getVar()[source]

Get the variance.

property p: float

Get the probability of success.

sample(n=1, rng=None)[source]

Generate random samples.

class Binomial(n, p)[source]

Bases: DiscreteDistribution

Binomial distribution.

The binomial distribution models the number of successes in n independent Bernoulli trials.

Parameters:
  • n (int) – Number of trials.

  • p (float) – Probability of success on each trial.

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPMF(x)[source]

Evaluate the PMF at point x.

getMean()[source]

Get the mean (n * p).

getSkew()[source]

Get the skewness.

getSupport()[source]

Get the support [0, n].

getVar()[source]

Get the variance (n * p * (1 - p)).

property n: int

Get the number of trials.

property p: float

Get the probability of success.

sample(n=1, rng=None)[source]

Generate random samples.

class NegBinomial(r, p)[source]

Bases: DiscreteDistribution

Negative Binomial distribution.

Models the number of failures before r successes in a sequence of Bernoulli trials.

Parameters:
  • r (int) – Number of successes required.

  • p (float) – Probability of success on each trial.

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPMF(x)[source]

Evaluate the PMF at point x.

getMean()[source]

Get the mean (r * (1 - p) / p).

getSkew()[source]

Get the skewness.

getSupport()[source]

Get the support [0, inf).

getVar()[source]

Get the variance.

property p: float

Get the probability of success.

property r: int

Get the number of successes required.

sample(n=1, rng=None)[source]

Generate random samples.

class Zipf(s, n=10000)[source]

Bases: DiscreteDistribution

Zipf distribution.

The Zipf distribution is a power-law distribution often used to model rank-frequency relationships (e.g., word frequencies).

Parameters:
  • s (float) – Shape parameter (s > 0).

  • n (int) – Upper bound on support (optional, defaults to large value).

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPMF(x)[source]

Evaluate the PMF at point x.

getMean()[source]

Get the mean.

getSupport()[source]

Get the support [1, n].

getVar()[source]

Get the variance.

property n: int

Get the upper bound.

property s: float

Get the shape parameter.

sample(n=1, rng=None)[source]

Generate random samples using inverse transform.

class Empirical(data)[source]

Bases: DiscreteDistribution

Empirical discrete distribution from data.

Creates a distribution from observed data by computing the empirical probability mass function.

Parameters:

data (list | numpy.ndarray) – Array of observed values.

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPMF(x)[source]

Evaluate the PMF at point x.

getMean()[source]

Get the mean.

getSupport()[source]

Get the support [min, max].

getVar()[source]

Get the variance.

property probs: numpy.ndarray

Get the probabilities for each value.

sample(n=1, rng=None)[source]

Generate random samples.

property values: numpy.ndarray

Get the unique values.

class Bernoulli(p)[source]

Bases: DiscreteDistribution

Bernoulli distribution.

The simplest discrete distribution with two outcomes: success (1) with probability p and failure (0) with probability 1-p.

Parameters:

p (float) – Probability of success (0 <= p <= 1).

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPMF(x)[source]

Evaluate the PMF at point x.

getMean()[source]

Get the mean (equals p).

getSkew()[source]

Get the skewness.

getSupport()[source]

Get the support {0, 1}.

getVar()[source]

Get the variance (p * (1 - p)).

property p: float

Get the probability of success.

sample(n=1, rng=None)[source]

Generate random samples.

class DiscreteUniform(a, b)[source]

Bases: DiscreteDistribution

Discrete Uniform distribution.

Assigns equal probability to all integers in [a, b].

Parameters:
  • a (int) – Lower bound (inclusive).

  • b (int) – Upper bound (inclusive).

Initialize a new distribution.

property a: int

Get the lower bound.

property b: int

Get the upper bound.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPMF(x)[source]

Evaluate the PMF at point x.

getMean()[source]

Get the mean ((a + b) / 2).

getSkew()[source]

Get the skewness (0 for symmetric distribution).

getSupport()[source]

Get the support [a, b].

getVar()[source]

Get the variance ((n^2 - 1) / 12).

sample(n=1, rng=None)[source]

Generate random samples.

class DiscreteSampler(p, x=None)[source]

Bases: DiscreteDistribution

General discrete distribution from values and probabilities.

Allows specifying an arbitrary discrete distribution by providing the possible values and their probabilities.

Supports two calling conventions (matching the MATLAB/JAR API):
  • DiscreteSampler(p): values are implicitly 1, 2, …, n (MATLAB-style)

  • DiscreteSampler(p, x): explicit probabilities and values, in this order (MATLAB DiscreteSampler(p,x) / JAR DiscreteSampler(p,x))

Parameters:
  • p (list | numpy.ndarray) – Array of probabilities (weights) of each item.

  • x (list | numpy.ndarray | None) – Array of possible values (only in the two-argument form).

Initialize a new distribution.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPMF(x)[source]

Evaluate the PMF at point x.

getMean()[source]

Get the mean.

getSupport()[source]

Get the support [min, max].

getVar()[source]

Get the variance.

property probs: numpy.ndarray

Get the probabilities.

sample(n=1, rng=None)[source]

Generate random samples.

property values: numpy.ndarray

Get the possible values.

class EmpiricalCdf(values, cdf)[source]

Bases: DiscreteDistribution

Empirical distribution from CDF data.

Creates a distribution from specified CDF points (values and cumulative probabilities).

Parameters:

Initialize a new distribution.

property cdf_values: numpy.ndarray

Get the CDF values.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalPMF(x)[source]

Evaluate the PMF at point x.

getMean()[source]

Get the mean.

getSupport()[source]

Get the support [min, max].

getVar()[source]

Get the variance.

sample(n=1, rng=None)[source]

Generate random samples using inverse transform.

property values: numpy.ndarray

Get the values.

EmpiricalCDF

alias of EmpiricalCdf

class Replayer(trace, loop=True)[source]

Bases: DiscreteDistribution

Trace-based distribution that replays recorded values.

Used for simulation where inter-arrival or service times are read from a trace file or data array.

Parameters:
  • trace (str | list | numpy.ndarray) – Array of values to replay.

  • loop (bool) – Whether to loop when trace is exhausted (default: True).

Initialize a new distribution.

evalCDF(x)[source]

Evaluate CDF based on trace.

evalPMF(x)[source]

Evaluate PMF based on trace frequency.

fit_aph()[source]

Fit an acyclic phase-type (APH) distribution to the trace data.

Uses 3-moment matching (mean, SCV, skewness) to determine the optimal APH representation, matching MATLAB’s behavior.

Returns:

APH distribution fitted to the trace data.

getMean()[source]

Get the mean of the trace.

getSkewness()[source]

Get the skewness of the trace.

getSupport()[source]

Get the support [min, max] of trace values.

getVar()[source]

Get the variance of the trace.

property loop: bool

Check if looping is enabled.

next_value()[source]

Get the next value in the trace.

reset()[source]

Reset the replay index to the beginning.

sample(n=1, rng=None)[source]

Get the next n values from the trace.

property trace: numpy.ndarray

Get the trace data.

class Trace(data, loop=True)[source]

Bases: Replayer

Empirical time series from a trace file.

Alias for Replayer with additional moment computation for histogram-style trace data (value, count pairs).

Parameters:
  • data (list | numpy.ndarray) – Array of values to replay, or 2-column array of (x, cdf) pairs.

  • loop (bool) – Whether to loop when trace is exhausted (default: True).

Initialize a new distribution.

getMoments()[source]

Compute moments from histogram-style trace data.

Returns:

Tuple of (m1, m2, m3, scv, skew) - first three moments, SCV, and skewness.

Return type:

Tuple[float, float, float, float, float]

class Coxian(means_or_rates, probs=None)[source]

Bases: PH

Coxian distribution.

A Coxian distribution is a special case of phase-type distributions where transitions can only go to the next phase or to absorption.

Parameters:
  • means_or_rates (list | numpy.ndarray) – Service rates (mu) for each phase. Rates are converted to means internally.

  • probs (list | numpy.ndarray | None) – Transition probabilities (phi). If length equals number of phases, the last element (which should be 1.0 for absorption) is dropped. If length is n-1, used as-is.

Initialize a new distribution.

classmethod fitCentral(mean, scv, skew=None)

Create a Coxian distribution from central moments.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

  • skew (float) – Target skewness (ignored, uses 2-moment matching).

Returns:

Coxian distribution with given moments.

Return type:

Coxian

classmethod fitMeanAndSCV(mean, scv)

Create a Coxian distribution from mean and SCV.

Uses moment matching to construct a Coxian distribution. Matches MATLAB Coxian.fitMeanAndSCV.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Coxian distribution with given mean and SCV.

Return type:

Coxian

classmethod fitMeanAndScv(mean, scv)

Create a Coxian distribution from mean and SCV.

Uses moment matching to construct a Coxian distribution. Matches MATLAB Coxian.fitMeanAndSCV.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Coxian distribution with given mean and SCV.

Return type:

Coxian

classmethod fit_central(mean, scv, skew=None)[source]

Create a Coxian distribution from central moments.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

  • skew (float) – Target skewness (ignored, uses 2-moment matching).

Returns:

Coxian distribution with given moments.

Return type:

Coxian

classmethod fit_mean_and_scv(mean, scv)[source]

Create a Coxian distribution from mean and SCV.

Uses moment matching to construct a Coxian distribution. Matches MATLAB Coxian.fitMeanAndSCV.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Coxian distribution with given mean and SCV.

Return type:

Coxian

property means: numpy.ndarray

Get the phase means.

property probs: numpy.ndarray

Get the continuation probabilities.

class Cox2(mu1, mu2, phi1)[source]

Bases: Coxian

2-phase Coxian distribution.

Convenience class for the common 2-phase case. Mirrors jline.lang.processes.Cox2 and MATLAB Cox2: the phases are given by their RATES, and phi1 is the COMPLETION probability of phase 1 (the job absorbs after phase 1 with probability phi1 and continues to phase 2 with probability 1 - phi1), matching Coxian’s phi convention.

Parameters:
  • mu1 (float) – Rate of phase 1.

  • mu2 (float) – Rate of phase 2.

  • phi1 (float) – Completion probability after phase 1.

Initialize a new distribution.

classmethod fitCentral(mean, var, skew=None)

Fit a 2-phase Coxian to the first three central moments.

Port of jline.lang.processes.Cox2.fitCentral and MATLAB Cox2.fitCentral. This override is REQUIRED for a different reason than fit_mean_and_scv: Coxian.fit_central discards skew and forwards to a two-moment fit, so an inherited Cox2.fitCentral would silently ignore the third moment that the JAR and MATLAB fit exactly.

Falls back to a two-moment fit when the three-moment solution is infeasible, and to a mean-only fit when SCV < 0.5, as the JAR does.

Parameters:
  • mean (float) – Target mean.

  • var (float) – Target variance (NOT SCV – matches the JAR/MATLAB signature).

  • skew (float) – Target skewness. When omitted, reduces to a two-moment fit.

classmethod fitMean(mean)

Fit a 2-phase Coxian to a mean alone.

Port of jline.lang.processes.Cox2.fitMean and MATLAB Cox2.fitMean.

classmethod fitMeanAndSCV(mean, scv)

Fit a 2-phase Coxian to a mean and SCV.

Port of jline.lang.processes.Cox2.fitMeanAndSCV and MATLAB Cox2.fitMeanAndSCV, which agree branch for branch.

This override is REQUIRED: Coxian.fit_mean_and_scv builds its result as cls(mu_list, phi_list), a signature Cox2 does not have, so the inherited classmethod raises TypeError on every call. It also may return an Erlang-like fit with more than two phases, which a Cox2 cannot represent.

A 2-phase Coxian cannot achieve SCV < 0.5; there phi1 comes out negative and the constructor rejects it. MATLAB and the JAR build the infeasible object silently instead.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Cox2 with the given mean and SCV.

Return type:

Cox2

classmethod fitMeanAndScv(mean, scv)

Fit a 2-phase Coxian to a mean and SCV.

Port of jline.lang.processes.Cox2.fitMeanAndSCV and MATLAB Cox2.fitMeanAndSCV, which agree branch for branch.

This override is REQUIRED: Coxian.fit_mean_and_scv builds its result as cls(mu_list, phi_list), a signature Cox2 does not have, so the inherited classmethod raises TypeError on every call. It also may return an Erlang-like fit with more than two phases, which a Cox2 cannot represent.

A 2-phase Coxian cannot achieve SCV < 0.5; there phi1 comes out negative and the constructor rejects it. MATLAB and the JAR build the infeasible object silently instead.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Cox2 with the given mean and SCV.

Return type:

Cox2

classmethod fit_central(mean, var, skew=None)[source]

Fit a 2-phase Coxian to the first three central moments.

Port of jline.lang.processes.Cox2.fitCentral and MATLAB Cox2.fitCentral. This override is REQUIRED for a different reason than fit_mean_and_scv: Coxian.fit_central discards skew and forwards to a two-moment fit, so an inherited Cox2.fitCentral would silently ignore the third moment that the JAR and MATLAB fit exactly.

Falls back to a two-moment fit when the three-moment solution is infeasible, and to a mean-only fit when SCV < 0.5, as the JAR does.

Parameters:
  • mean (float) – Target mean.

  • var (float) – Target variance (NOT SCV – matches the JAR/MATLAB signature).

  • skew (float) – Target skewness. When omitted, reduces to a two-moment fit.

classmethod fit_mean(mean)[source]

Fit a 2-phase Coxian to a mean alone.

Port of jline.lang.processes.Cox2.fitMean and MATLAB Cox2.fitMean.

classmethod fit_mean_and_scv(mean, scv)[source]

Fit a 2-phase Coxian to a mean and SCV.

Port of jline.lang.processes.Cox2.fitMeanAndSCV and MATLAB Cox2.fitMeanAndSCV, which agree branch for branch.

This override is REQUIRED: Coxian.fit_mean_and_scv builds its result as cls(mu_list, phi_list), a signature Cox2 does not have, so the inherited classmethod raises TypeError on every call. It also may return an Erlang-like fit with more than two phases, which a Cox2 cannot represent.

A 2-phase Coxian cannot achieve SCV < 0.5; there phi1 comes out negative and the constructor rejects it. MATLAB and the JAR build the infeasible object silently instead.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation.

Returns:

Cox2 with the given mean and SCV.

Return type:

Cox2

class MMPP(Q, lambda_)[source]

Bases: MAP

Markov-Modulated Poisson Process.

A special case of MAP where arrivals occur according to Poisson processes with rates that depend on an underlying Markov chain state.

Parameters:
  • Q (list | numpy.ndarray) – Generator matrix of the modulating Markov chain.

  • lambda – Vector of Poisson rates for each state.

Initialize a new distribution.

property Q: numpy.ndarray

Get the modulating Markov chain generator.

property lambda_: numpy.ndarray

Get the Poisson rates for each state.

class DMAP(D0, D1)[source]

Bases: ContinuousDistribution, Markovian

Discrete-time Markovian Arrival Process.

A DMAP models discrete-time arrival streams with correlation. D0 + D1 is a stochastic matrix (row sums = 1).

Parameters:

Initialize a new distribution.

property D0: numpy.ndarray
property D1: numpy.ndarray
getD0()[source]

Get the D0 matrix (for MAP representations).

getD1()[source]

Get the D1 matrix (for MAP representations).

getInitProb()[source]

Get the initial probability vector.

getMean()[source]

Mean inter-arrival time: pi * (I-D0)^{-1} * e

getMu()[source]

Get the service rates in each phase.

getNumberOfPhases()[source]

Get the number of phases.

getPhi()[source]

Get the completion probabilities from each phase.

getRate()[source]

Get the rate parameter (1/mean).

For immediate (zero-mean) distributions, returns GlobalConstants.Immediate (a large but finite value) to avoid numerical issues with infinite rates. This matches MATLAB’s behavior.

getVar()[source]

Variance of inter-arrival times.

property pi: numpy.ndarray
classmethod rand(n=2, seed=None)[source]

Create a random DMAP with n phases.

sample(n=1, rng=None)[source]

Generate random inter-arrival times (integer-valued).

setMean(target_mean)

Scale DMAP to match target mean.

set_mean(target_mean)[source]

Scale DMAP to match target mean.

class ME(alpha, A, checkDensity=True)[source]

Bases: ContinuousDistribution, Markovian

Matrix Exponential distribution.

ME distributions generalize Phase-Type distributions by allowing the initial vector alpha to have entries outside [0,1] and the matrix A to have arbitrary structure (not necessarily a sub-generator).

Parameters:
  • alpha (list | numpy.ndarray) – Initial vector (may have negative entries).

  • A (list | numpy.ndarray) – Matrix parameter (eigenvalues must have negative real parts).

  • checkDensity (bool) – Scan the density for a negative value (default True). It is set to False only by subclasses whose representation is a density by construction, such as CME, where the scan would cost O(1e5) propagations of a large matrix and can never fire.

Initialize a new distribution.

property A: numpy.ndarray

Get the matrix parameter.

property alpha: numpy.ndarray

Get the initial vector.

evalCDF(x)[source]

Evaluate the CDF at point x.

evalLST(s)[source]

Evaluate the Laplace-Stieltjes transform at s.

LST(s) = alpha * (s*I - A)^(-1) * (-A) * e, mirroring MATLAB ME.evalLST.

evalPDF(x)[source]

Evaluate the PDF at point x.

eval_cdf(x)[source]

Evaluate CDF at point x.

eval_lst(s)[source]

Evaluate the Laplace-Stieltjes transform at s.

eval_pdf(x)[source]

Evaluate PDF at point x.

static fitMoments(moments)

Create ME distribution matching given moments.

Uses the van de Liefvoort algorithm to construct a matrix-exponential distribution that has the specified moments.

Parameters:

moments (list | numpy.ndarray) – List of moments. To obtain an ME of order M, provide 2*M-1 moments (e.g., 3 moments for order 2, 5 for order 3).

Returns:

ME distribution matching the given moments.

Raises:

ValueError – If moments cannot be matched (e.g., invalid structure).

Return type:

ME

static fit_moments(moments)[source]

Create ME distribution matching given moments.

Uses the van de Liefvoort algorithm to construct a matrix-exponential distribution that has the specified moments.

Parameters:

moments (list | numpy.ndarray) – List of moments. To obtain an ME of order M, provide 2*M-1 moments (e.g., 3 moments for order 2, 5 for order 3).

Returns:

ME distribution matching the given moments.

Raises:

ValueError – If moments cannot be matched (e.g., invalid structure).

Return type:

ME

static fromErlang(k, rate)

Create ME from Erlang distribution.

static fromExp(rate)

Create ME from exponential distribution.

static fromHyperExp(p, rates, rate2=None)

Create ME from HyperExp distribution.

Can be called as: - from_hyper_exp(p, rate1, rate2) for 2-phase - from_hyper_exp([p1, p2, …], [r1, r2, …]) for n-phase

static from_erlang(k, rate)[source]

Create ME from Erlang distribution.

static from_exp(rate)[source]

Create ME from exponential distribution.

static from_hyper_exp(p, rates, rate2=None)[source]

Create ME from HyperExp distribution.

Can be called as: - from_hyper_exp(p, rate1, rate2) for 2-phase - from_hyper_exp([p1, p2, …], [r1, r2, …]) for n-phase

getA()[source]

Get the matrix parameter (getter method for API compatibility).

getAlpha()[source]

Get the initial vector (getter method for API compatibility).

getD0()[source]

Get the D0 matrix of the process representation (equals A).

getD1()[source]

Get the D1 matrix of the process representation, -A*e*alpha.

getInitProb()[source]

Get the initial vector alpha (entries may be negative for an ME).

getMean()[source]

Get the mean.

getMu()[source]

Get the rate out of each phase.

getNumberOfPhases()[source]

Get the number of phases.

getPhi()[source]

Get the completion probability out of each phase.

getProcess()[source]

Get the process representation as [D0, D1] = [A, -A*e*alpha].

Same convention as MATLAB ME.getProcess (a {D0,D1} cell) and jline.lang.processes.ME.getProcess (a two-entry MatrixCell).

getSCV()[source]

Get the squared coefficient of variation, var / mean^2.

getVar()[source]

Get the variance.

get_a()[source]

Get the matrix parameter.

get_alpha()[source]

Get the initial vector.

get_mean()[source]

Get the mean.

get_number_of_phases()[source]

Get the number of phases.

get_process()[source]

snake_case alias for getProcess().

get_scv()[source]

Get the squared coefficient of variation.

get_var()[source]

Get the variance.

sample(n=1, rng=None)[source]

Generate n samples by inverting the CDF.

A PH-style walk over the phase process is not applicable: alpha may have negative entries and A need not be a sub-generator, so there is no Markov chain to walk. Instead the CDF F(x) = 1 - alpha*exp(A*x)*e is tabulated on a grid covering the tail, inverted by binary search on the table and refined by safeguarded Newton steps against the exact density -alpha*exp(A*x)*A*e. Uniforms beyond the last tabulated point are mapped through the exponential tail of the dominant eigenvalue of A rather than clamped to the grid endpoint, which would truncate the tail and bias the mean low.

class CME(mean, order)[source]

Bases: ME

Concentrated Matrix Exponential distribution.

A CME is the matrix-exponential distribution of odd order 2*n+1 whose squared coefficient of variation is (numerically) minimal for that order, from the tables of Horvath, Horvath and Telek. Its SCV decays as O(1/n^2), so it goes far below the Erlang bound 1/order reachable by a phase-type distribution of the same order: order 101 gives SCV 3.9e-4, where Erlang-101 gives 9.9e-3.

The density of the unit-mean CME with n harmonic terms is

f(x) = mu1 * exp(-mu1*x) * (c + sum_k [a_k*cos(k*w*mu1*x) + b_k*sin(k*w*mu1*x)])

with w = omega, which is exactly alpha*expm(A*x)*(-A*e) for the block-diagonal A = blkdiag(-mu1, mu1*[[-1,-k*w],[k*w,-1]] for k=1..n). The parameters a, b, c, omega and mu1 are read from the same iltcme.json table used by the CME inverse Laplace transform.

Parameters:
  • mean (float) – Mean of the distribution (the tabulated CME has unit mean and is rescaled by A/mean).

  • order (int) – Number of phases, an odd integer 2*n+1 with n present in the table.

Initialize a new distribution.

static fitMeanAndSCV(mean, scv)[source]

Create the lowest-order CME with the given mean and SCV at most scv.

Parameters:
  • mean (float) – Target mean.

  • scv (float) – Target squared coefficient of variation, an upper bound. The lowest tabulated order whose minimal SCV does not exceed it is selected, so the returned distribution is at least as concentrated as requested.

Returns:

The CME of that order, rescaled to the requested mean.

Raises:

ValueError – if no tabulated order reaches the requested SCV.

Return type:

CME

static fit_mean_and_scv(mean, scv)[source]

snake_case alias for fitMeanAndSCV().

static getMinSCV(order)[source]

Get the tabulated minimal SCV attained by a CME of the given order.

getOrder()[source]

Get the CME order, i.e. the number of phases.

static getSupportedOrders()[source]

Get the sorted list of CME orders (phase counts) in the table.

get_order()[source]

snake_case alias for getOrder().

class MarkedMAP(process)[source]

Bases: ContinuousDistribution, Markovian

Marked Markovian Arrival Process.

A MarkedMAP extends MAP to support multiple arrival types (marks/classes). It is defined by matrices D0, D1, D2, …, Dk where: - D0: transitions without arrivals - Dk (k >= 1): transitions with arrivals of type k

Parameters:

process (list | numpy.ndarray) – List or array of matrices [D0, D1, D2, …, Dk].

Initialize a new distribution.

D(k)[source]

Get the k-th matrix (D0, D1, …, Dk).

getMean()[source]

Get the mean inter-arrival time.

getNumberOfPhases()[source]

Get the number of phases.

getNumberOfTypes()[source]

Get the number of arrival types (MATLAB/JAR API parity).

getVar()[source]

Get the variance.

property num_types: int

Get the number of arrival types.

sample(n=1, rng=None)[source]

Generate random inter-arrival times and their types.

Returns:

Tuple of (times, types) arrays.

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

to_m3a()[source]

Return the process in the canonical M3A layout [D0, D1_agg, D11, …, D1K] used by the mam API (mmap_* functions) and by the NetworkStruct proc entries, where D1_agg = sum of the per-type matrices. The internal _process stays in the constructor layout [D0, D11, …, D1K].

to_map()[source]

Aggregate MAP over all marks: MAP(D0, sum(D1k)). Mirrors MATLAB toMAP.

to_marginal_map(k)[source]

Marginal MAP of mark k (1-based): arrivals fire only on D1k, with the other marks’ transitions folded into the hidden part, i.e. MAP(D0 + D1_agg - D1k, D1k). Mirrors MATLAB MarkedMAP.toMAPs for a single type.

class MarkedMMPP(process, num_types)[source]

Bases: ContinuousDistribution, Markovian

Marked Markov-Modulated Poisson Process (M3PP).

A MarkedMMPP extends MMPP to support multiple arrival types (marks). In each state, arrivals of different types occur according to Poisson processes. The D1k matrices must be diagonal (MMPP constraint).

Uses the M3A representation format: D = {D0, D1, D11, D12, …, D1K} where K is the number of marking types.

Parameters:
  • process (list | numpy.ndarray) – List of matrices [D0, D1, D11, D12, …, D1K] or [D0, D11, D12, …, D1K] (D1 computed as sum).

  • num_types (int) – Number of marking types K.

Initialize a new distribution.

D(i, j=0)[source]

Get representation matrix.

Parameters:
  • i (int) – Primary index (0 for D0, 1 for D1)

  • j (int) – Secondary index for D1j (0 for aggregate D1, k for D1k)

Returns:

The requested matrix.

Return type:

numpy.ndarray

getMarkedMeans()[source]

Get mean inter-arrival times for each marking type.

getMean()[source]

Get the mean inter-arrival time.

getNumberOfPhases()[source]

Get the number of phases.

getNumberOfTypes()[source]

Get the number of marking types.

getRate()[source]

Get the aggregate arrival rate.

getVar()[source]

Get the variance.

property num_types: int

Get the number of marking types.

static rand(order=2, num_classes=2)[source]

Generate a random MarkedMMPP.

sample(n=1, rng=None)[source]

Generate random inter-arrival times and their types.

Returns:

Tuple of (times, types) arrays.

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

toMAP()[source]

Convert to aggregate MAP (ignoring marks).

class BMAP(process)[source]

Bases: MarkedMAP

Batch Markovian Arrival Process.

BMAP is a point process where arrivals occur in batches. Each matrix Dk represents transitions generating k arrivals.

Parameters:

process (list | numpy.ndarray) – List of matrices [D0, D1, D2, …, Dk] where Dk is the rate matrix for batch size k.

Initialize a new distribution.

static from_map_with_batch_pmf(D0, D1, batch_sizes, pmf)[source]

Create BMAP from base MAP and batch size distribution.

Parameters:
  • D0 (numpy.ndarray) – Base MAP D0 matrix.

  • D1 (numpy.ndarray) – Base MAP D1 matrix.

  • batch_sizes (list) – List of possible batch sizes.

  • pmf (list) – Probability mass function for batch sizes.

Returns:

BMAP with specified batch distribution.

Return type:

BMAP

getBatchRates()[source]

Get arrival rates for each batch size.

getMeanBatchSize()[source]

Get the mean batch size.

property max_batch_size: int

Get the maximum batch size.

class RAP(H0, H1)[source]

Bases: ContinuousDistribution, Markovian

Rational Arrival Process.

RAP generalizes MAP by allowing the representation matrices to have entries that may lead to complex eigenvalues, as long as the resulting distribution is valid (non-negative PDF and CDF in [0,1]).

Similar to MAP, RAP is defined by two matrices H0 and H1 where: - H0: Rate transitions without arrivals (like D0 in MAP) - H1: Rate transitions with arrivals (like D1 in MAP)

Parameters:

Initialize a new distribution.

property H0: numpy.ndarray

Get the H0 matrix.

property H1: numpy.ndarray

Get the H1 matrix.

evalCDF(x)[source]

Evaluate the CDF of the inter-arrival time at point x.

evalLST(s)[source]

Evaluate the Laplace-Stieltjes transform of the inter-arrival time.

LST(s) = pie * (s*I - H0)^(-1) * (-H0) * e, mirroring MATLAB RAP.evalLST.

evalPDF(x)[source]

Evaluate the PDF of the inter-arrival time at point x.

eval_cdf(x)[source]

Evaluate CDF at point x.

eval_pdf(x)[source]

Evaluate PDF at point x.

static fromErlang(k, rate)

Create RAP from Erlang distribution.

static fromExp(rate)

Create RAP from exponential distribution.

static fromMAP(map_dist)

Create RAP from MAP distribution.

static fromPoisson(rate)

Create RAP from Poisson process (same as exponential).

static from_erlang(k, rate)[source]

Create RAP from Erlang distribution.

static from_exp(rate)[source]

Create RAP from exponential distribution.

static from_map(map_dist)[source]

Create RAP from MAP distribution.

static from_poisson(rate)[source]

Create RAP from Poisson process (same as exponential).

getACF(lags=1)[source]

Get the autocorrelation of the inter-arrival times at the given lags.

getD0()[source]

Get the D0 matrix of the process representation (equals H0).

getD1()[source]

Get the D1 matrix of the process representation (equals H1).

getH0()[source]

Get the H0 matrix.

getH1()[source]

Get the H1 matrix.

getIDC()[source]

Get the asymptotic index of dispersion for counts.

getInitProb()[source]

Get the phase vector embedded at arrival epochs.

getMean()[source]

Get the mean inter-arrival time.

getMu()[source]

Get the total outgoing rate from each phase.

mu_i = -H0(i,i), the same MATLAB Markovian.getMu formula MAP uses. A RAP whose matrices happen to be nonnegative IS a MAP, so the two classes have to answer identically on such a pair; summing H1 instead counts only the arrival transitions and contradicted MAP on exactly that degenerate case.

getNumberOfPhases()[source]

Get the number of phases.

getPhi()[source]

Get the probability that a transition out of a phase is an arrival.

phi_i = (H1*e)_i / -H0(i,i), matching MATLAB Markovian.getPhi and MAP. The H0(0,0) == 0 guard mirrors the MATLAB special case for an immediate process.

getPie()[source]

Get the phase vector embedded at arrival epochs.

This is the equilibrium distribution of the embedded DTMC P = (-H0)^(-1) H1, i.e. pie = pi*H1 / (pi*H1*e). It, and not the time-stationary pi, is the vector that governs the inter-arrival time marginal, matching MATLAB map_pie.

getProcess()[source]

Get the process representation [H0, H1], as MATLAB RAP.getProcess.

getRate()[source]

Get the arrival rate (1/mean).

getSCV()[source]

Get the squared coefficient of variation of the inter-arrival time.

getVar()[source]

Get the variance.

get_acf(lags=1)[source]

snake_case alias for getACF().

get_h0()[source]

Get the H0 matrix.

get_h1()[source]

Get the H1 matrix.

get_idc()[source]

snake_case alias for getIDC().

get_mean()[source]

Get the mean.

get_number_of_phases()[source]

Get the number of phases.

get_pie()[source]

snake_case alias for getPie().

get_process()[source]

snake_case alias for getProcess().

get_rate()[source]

Get the arrival rate.

get_var()[source]

Get the variance.

property pi: numpy.ndarray

Get the stationary distribution.

sample(n=1, rng=None)[source]

Generate n successive inter-arrival times along one sample path.

A RAP has no underlying Markov chain over phases to walk, so sampling carries the conditional phase vector v (normalized so that v*e = 1) instead. Starting from the arrival-embedded vector pie, each draw inverts the conditional survival function v*exp(H0*x)*e at a uniform variate and then updates v <- v*exp(H0*x)*H1 / (v*exp(H0*x)*H1*e). This reproduces the autocorrelation of the process; drawing from the ME marginal alone would produce independent inter-arrival times.

class MMDP(Q, R)[source]

Bases: ContinuousDistribution, Markovian

Markov-Modulated Deterministic Process.

MMDP models a process where a deterministic RATE is modulated by an underlying Markov chain: in state i arrivals occur deterministically at rate r_i, i.e. one every 1/r_i time units.

Parameterized by rates, mirroring MATLAB MMDP.m and the JAR MMDP.java (MMDP(Q, R), R = diag(r)). This class previously took inter-arrival TIMES d, which made it a different process sharing a name: it reported getMean() = pi.d (the state-averaged time), whereas averaging rates gives 1/(pi.r). The two differ whenever the rates are not all equal, so the same model meant different things per codebase. MATLAB is the reference.

Parameters:
  • Q (list | numpy.ndarray) – Generator matrix of the modulating Markov chain (row sums 0).

  • R (list | numpy.ndarray) – n x n diagonal matrix of deterministic rates, or an n-vector of them.

Initialize a new distribution.

property Q: numpy.ndarray

Get the generator matrix.

R()[source]

Diagonal rate matrix. Mirrors MATLAB MMDP.R.

getMean()[source]

Mean inter-arrival time, the inverse of the mean rate.

Mirrors MATLAB MMDP.getMean. This is 1/(pi.r), not the state-averaged inter-arrival time pi.(1/r): the rate is what the chain modulates.

getMeanRate()[source]

Stationary mean rate pi.r. Mirrors MATLAB MMDP.getMeanRate.

getNumberOfPhases()[source]

Get the number of phases.

getRate()[source]

Alias of getMeanRate, as in MATLAB MMDP.getRate.

getSCV()[source]

SCV of the modulated rate. Mirrors MATLAB MMDP.getSCV.

getVar()[source]

Variance, as MATLAB’s Distribution base derives it: SCV * mean^2.

MMDP.m does not override getVar, so this reproduces the inherited relation rather than re-deriving a variance from the rates.

r()[source]

Vector of deterministic rates, one per state. Mirrors MATLAB MMDP.r.

class MMDP2(r0, r1, sigma0, sigma1)[source]

Bases: MMDP

Markov-Modulated Deterministic Process with 2 states.

Convenience class for the common 2-state case.

Parameterized by deterministic RATES, mirroring MATLAB MMDP2.m and the JAR MMDP2.java (which build R = diag([r0, r1])). This class previously took deterministic TIMES d0/d1, which made it a different stochastic object sharing a name: averaging times as pi.d yields the arithmetic mean of the per-state times, whereas the rate parameterization averages rates and reports 1/(pi.r). The two disagree whenever r0 ~= r1, so a model written by one codebase and read by another silently changed meaning. MATLAB is the reference, so the rate form is canonical here too; the JSON wire keys are r0/r1 accordingly.

Parameters:
  • r0 (float) – Deterministic rate in state 0.

  • r1 (float) – Deterministic rate in state 1.

  • sigma0 (float) – Transition rate from state 0 to state 1.

  • sigma1 (float) – Transition rate from state 1 to state 0.

Initialize a new distribution.

getMeanRate()[source]

Stationary mean rate (closed form). Mirrors MATLAB MMDP2.getMeanRate.

getSCV()[source]

SCV of the modulated rate. Mirrors MATLAB MMDP2.getSCV.

property r0: float

Get deterministic rate in state 0.

property r1: float

Get deterministic rate in state 1.

property sigma0: float

Get transition rate from state 0 to 1.

property sigma1: float

Get transition rate from state 1 to 0.

dist_scale_rate(distrib, factor)[source]

Return a new distribution whose rate is FACTOR times the rate of DISTRIB, i.e. the time-scaled variable X/FACTOR. The scaling is exact: every moment of order n is divided by FACTOR^n, so the mean is divided by FACTOR while the SCV, the skewness and the whole shape of the distribution are preserved.

The scaled object is rebuilt from the parameters of the original, rather than by rescaling its Markovian representation, so that the parameter list stays coherent with the distribution family. Solvers that serialize the model (JMT, LDES) read the parameters, and would otherwise export the unscaled process.

This is the perturbation primitive of the finite-difference branch of getSensitivityTable: scaling the rate at a station-class by (1+h) is exactly the perturbation the derivative d(.)/d(rate) is taken along.

Parameters:
  • distrib – A Distribution object.

  • factor – Positive scaling factor for the rate.

Returns:

A new Distribution of the same family with rate*FACTOR.

distScaleRate(distrib, factor)

Return a new distribution whose rate is FACTOR times the rate of DISTRIB, i.e. the time-scaled variable X/FACTOR. The scaling is exact: every moment of order n is divided by FACTOR^n, so the mean is divided by FACTOR while the SCV, the skewness and the whole shape of the distribution are preserved.

The scaled object is rebuilt from the parameters of the original, rather than by rescaling its Markovian representation, so that the parameter list stays coherent with the distribution family. Solvers that serialize the model (JMT, LDES) read the parameters, and would otherwise export the unscaled process.

This is the perturbation primitive of the finite-difference branch of getSensitivityTable: scaling the rate at a station-class by (1+h) is exactly the perturbation the derivative d(.)/d(rate) is taken along.

Parameters:
  • distrib – A Distribution object.

  • factor – Positive scaling factor for the rate.

Returns:

A new Distribution of the same family with rate*FACTOR.

API Submodules

Cache API (line_solver.api.cache)

Cache Analysis Algorithms.

Native Python implementations for analyzing cache systems, including exact recursive methods, singular perturbation methods, importance sampling, TTL-based caches, and various approximation techniques.

Key algorithms:

cache_erec: Exact recursive normalizing constant cache_prob_erec: Exact recursive state probabilities cache_spm: Singular perturbation method cache_miss: Miss rate computation cache_is: Importance sampling cache_ttl_*: TTL-based cache analysis cache_rrm_*: Random replacement model

cache_lrum_map_levelstats(D0, D1, T)[source]

Level statistics of one item’s embedded (list, phase) chain under the LRU(m)-MAP TTL approximation (Gast and Van Houdt, PEVA 2017, eqs. 5-9).

Parameters:
Returns:

time-stationary level probabilities (h+1,), list occupancies (h,), request-weighted hit fractions (h,)

Return type:

(prob, occ, hitfrac)

References

Original MATLAB: matlab/src/api/cache/cache_lrum_map_levelstats.m

cache_t_lrum_map(D0c, D1c, m)[source]

Characteristic times for the LRU(m)-MAP TTL approximation.

Parameters:
  • D0c (list) – list of per-item (d,d) hidden-transition matrices

  • D1c (list) – list of per-item (d,d) arrival matrices

  • m (numpy.ndarray) – cache capacity vector (h,)

Returns:

Characteristic times (h,)

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/cache/cache_t_lrum_map.m

cache_ttl_lrum_map(D0c, D1c, m)[source]

Request-weighted hit/miss probabilities for LRU(m) with per-item MAP request streams (Gast and Van Houdt, PEVA 2017). Intended for items with genuinely distinct or correlated request processes (e.g. marked MAP arrivals); when items are i.i.d. marks of a common stream the request sequence is IRM and the Poisson-based TTL approximations already apply.

Parameters:
  • D0c (list) – list of per-item (d,d) hidden-transition matrices

  • D1c (list) – list of per-item (d,d) arrival matrices

  • m (numpy.ndarray) – cache capacity vector (h,)

Returns:

(n,h+1) request-weighted probabilities (column 0 = miss) and (n,h+1) time-stationary level occupancy probabilities

Return type:

(pij, pijtime)

References

Original MATLAB: matlab/src/api/cache/cache_ttl_lrum_map.m

cache_erec(gamma, m)[source]

Compute the cache normalizing constant using exact recursive method.

This method serves as a wrapper that calls the auxiliary function to perform the actual computation.

Parameters:
  • gamma (numpy.ndarray) – Cache access factors matrix (n x h), where n is number of items and h is number of cache levels.

  • m (numpy.ndarray) – Cache capacity vector (1 x h or h,).

Returns:

Normalizing constant E.

Return type:

float

cache_erec_aux(gamma, m, k)[source]

Auxiliary method for computing cache normalizing constant using exact recursive method.

This method performs the core computation recursively, adjusting the size of the input matrix.

Parameters:
  • gamma (numpy.ndarray) – Cache access factors matrix (n x h).

  • m (numpy.ndarray) – Cache capacity vector (h,).

  • k (int) – Current number of rows in the recursive step.

Returns:

Normalizing constant for the given configuration.

Return type:

float

cache_prob_erec(gamma, m)[source]

Compute cache state probabilities using exact recursive method.

This method calculates the probabilities of the cache being in different states based on the cache access factors and capacity.

Parameters:
  • gamma (numpy.ndarray) – Cache access factors matrix (n x h), where n is number of items and h is number of cache levels.

  • m (numpy.ndarray) – Cache capacity vector (1 x h or h,).

Returns:

Matrix (n x h+1) containing cache state probabilities. Column 0 is miss probability, columns 1..h are hit probabilities at each cache level.

Return type:

numpy.ndarray

cache_mva(gamma, m)[source]

Mean Value Analysis for cache systems.

Computes cache performance metrics using MVA approach.

Parameters:
Returns:

  • pi: Steady-state probabilities

  • pi0: Miss probabilities per item

  • pij: Hit probabilities per item per level (n x h)

  • x: Throughput vector

  • u: Utilization vector

  • E: Normalizing constant

Return type:

Tuple of (pi, pi0, pij, x, u, E) containing

cache_xi_iter(gamma, m, tol=1e-12, max_iter=1000)[source]

Compute cache xi terms using iterative method from Gast-van Houdt.

This method calculates the xi values which are important for understanding the distribution of items in the cache. The algorithm assumes that the access factors are monotone with the list index.

Parameters:
  • gamma (numpy.ndarray) – Cache access factors matrix (n x h).

  • m (numpy.ndarray) – Cache capacity vector (h,).

  • tol (float) – Convergence tolerance (default: 1e-12).

  • max_iter (int) – Maximum iterations (default: 1000).

Returns:

Vector of xi values (h,).

Return type:

numpy.ndarray

cache_spm(gamma, m)[source]

Approximate the normalizing constant using SPM method.

Computes the normalizing constant of the cache steady state distribution using the singular perturbation method (also known as ray integration).

Parameters:
Returns:

  • Z: Approximated normalizing constant

  • lZ: Log of normalizing constant

  • xi: Xi terms vector

Return type:

Tuple of (Z, lZ, xi) where

cache_prob_spm(gamma, m)[source]

Compute cache miss probabilities using singular perturbation method.

Uses the SPM (ray integration) method to compute miss probabilities for cache systems.

Parameters:
Returns:

Vector of miss probabilities for each item.

Return type:

numpy.ndarray

cache_prob_fpi(gamma, m, tol=1e-8, max_iter=1000)[source]

Compute cache hit probabilities using fixed point iteration (FPI method).

Matches MATLAB cache_prob_fpi: Uses fixed point iteration to compute cache hit probability distribution.

Parameters:
  • gamma (numpy.ndarray) – Cache access factors matrix (n x h).

  • m (numpy.ndarray) – Cache capacity vector (h,).

  • tol (float) – Convergence tolerance (unused, kept for API compatibility).

  • max_iter (int) – Maximum iterations (unused, kept for API compatibility).

Returns:

  • Column 0: miss probabilities

  • Columns 1:h: hit probabilities at each level

Return type:

Matrix (n x h+1) where

cache_miss(gamma, m, lambd=None)[source]

Compute miss rates for a cache system using exact recursive method.

Parameters:
  • gamma (numpy.ndarray) – Item popularity probabilities (n x h matrix)

  • m (numpy.ndarray) – Cache capacity vector (h,)

  • lambd (numpy.ndarray | None) – Optional arrival rates per user per item (u x n x h+1)

Returns:

  • M: Global miss rate

  • MU: Per-user miss rate (u,) or None

  • MI: Per-item miss rate (n,) or None

  • pi0: Per-item miss probability (n,) or None

Return type:

Tuple of (M, MU, MI, pi0) where

References

Original MATLAB: matlab/src/api/cache/cache_miss.m

cache_xi_fp(gamma, m, xi_init=None, tol=1e-14, max_iter=10000)[source]

Fixed-point iteration for computing cache performance metrics.

Computes cache performance metrics including Lagrange multipliers, miss probabilities, and hit probabilities.

Parameters:
  • gamma (numpy.ndarray) – Item popularity probabilities (n x h)

  • m (numpy.ndarray) – Cache capacity vector (h,)

  • xi_init (numpy.ndarray | None) – Optional initial guess for Lagrange multipliers

  • tol (float) – Convergence tolerance (default: 1e-14)

  • max_iter (int) – Maximum iterations (default: 10000)

Returns:

  • xi: Converged Lagrange multipliers (h,)

  • pi0: Miss probability per item (n,)

  • pij: Hit probability per item per list (n x h)

  • it: Number of iterations

Return type:

Tuple of (xi, pi0, pij, it) where

References

Original MATLAB: matlab/src/api/cache/cache_xi_fp.m

cache_miss_fpi(gamma, m, lambd=None)[source]

Compute cache miss rates using fixed-point iteration method.

Parameters:
  • gamma (numpy.ndarray) – Item popularity probabilities (n x h)

  • m (numpy.ndarray) – Cache capacity vector (h,)

  • lambd (numpy.ndarray | None) – Optional arrival rates per user per item (u x n x h+1)

Returns:

  • M: Global miss rate

  • MU: Per-user miss rate or None

  • MI: Per-item miss rate or None

  • pi0: Per-item miss probability or None

Return type:

Tuple of (M, MU, MI, pi0) where

References

Original MATLAB: matlab/src/api/cache/cache_miss_fpi.m

cache_miss_spm(gamma, m, lambd=None)[source]

Compute cache miss rates using singular perturbation method.

Parameters:
  • gamma (numpy.ndarray) – Item popularity probabilities (n x h)

  • m (numpy.ndarray) – Cache capacity vector (h,)

  • lambd (numpy.ndarray | None) – Optional arrival rates per user per item (u x n x h+1)

Returns:

  • M: Global miss rate

  • MU: Per-user miss rate or None

  • MI: Per-item miss rate or None

  • pi0: Per-item miss probability or None

  • lE: Log of normalizing constant

Return type:

Tuple of (M, MU, MI, pi0, lE) where

References

Original MATLAB: matlab/src/api/cache/cache_miss_spm.m

cache_mva_miss(p, m, R)[source]

Compute cache miss rates using Mean Value Analysis.

Parameters:
Returns:

  • M: Global miss rate

  • Mk: Per-item miss rate (n,)

Return type:

Tuple of (M, Mk) where

References

Original MATLAB: matlab/src/api/cache/cache_mva_miss.m

cache_miss_rmf(gamma, m, lambd, tspan=None, x0init=None)[source]

RMF (1/N-accurate) miss rates for RANDOM(m) caches.

Mirrors the cache_miss_fpi contract. gamma is accepted for interface compatibility (used for sizing only); the popularity is recovered from lambd, the (u, n, h+1) per-user per-item arrival rates.

Parameters:
  • gamma – item access factors (unused beyond sizing).

  • m – cache capacity vector (h,).

  • lambd – arrival rates per user per item per list (u, n, >=1).

  • tspan – optional [t0, t1]. When given, also integrates the plain mean-field drift over the window and returns the transient trajectory (the same drift that _fixed_point drives to steady state). Omitting tspan preserves the steady-state-only contract.

  • x0init – optional initial occupancy (dim,) for the transient; defaults to the standard first-m-in-list initial state. Used to carry the cache mean occupancy across environment switches.

Returns:

Tuple (M, MU, MI, pi0) when tspan is None, else (M, MU, MI, pi0, tout, pi0_t, MU_t, xtraj) with tout (nt,), pi0_t (n, nt) per-item list-0 occupancy, MU_t (u, nt) per-user miss rate, and xtraj (dim, nt) full DDPP occupancy trajectory.

cache_is(gamma, m, samples=100000)[source]

Importance sampling estimation of cache normalizing constant.

Estimates the normalizing constant for cache models using Monte Carlo importance sampling.

Parameters:
  • gamma (numpy.ndarray) – Item popularity probabilities (n x h matrix)

  • m (numpy.ndarray) – Cache capacity vector (h,)

  • samples (int) – Number of Monte Carlo samples (default: 100000)

Returns:

  • E: Normalizing constant estimate

  • lE: Log of normalizing constant

Return type:

Tuple of (E, lE) where

References

Original MATLAB: matlab/src/api/cache/cache_is.m

cache_prob_is(gamma, m, samples=100000)[source]

Importance sampling estimation of cache hit probabilities.

Estimates cache hit probability distribution using Monte Carlo importance sampling.

Parameters:
  • gamma (numpy.ndarray) – Item popularity probabilities (n x h matrix)

  • m (numpy.ndarray) – Cache capacity vector (h,)

  • samples (int) – Number of Monte Carlo samples (default: 100000)

Returns:

prob[i, 0] = miss probability for item i prob[i, 1+j] = hit probability for item i at level j

Return type:

Cache hit probability matrix (n x h+1)

References

Original MATLAB: matlab/src/api/cache/cache_prob_is.m

cache_miss_is(gamma, m, lambd=None, samples=100000)[source]

Importance sampling estimation of cache miss rates.

Computes global, per-user, and per-item miss rates using Monte Carlo importance sampling.

Parameters:
  • gamma (numpy.ndarray) – Item popularity probabilities (n x h matrix)

  • m (numpy.ndarray) – Cache capacity vector (h,)

  • lambd (numpy.ndarray | None) – Optional arrival rates per user per item (u x n x h+1)

  • samples (int) – Number of Monte Carlo samples (default: 100000)

Returns:

  • M: Global miss rate

  • MU: Per-user miss rate or None

  • MI: Per-item miss rate or None

  • pi0: Per-item miss probability or None

  • lE: Log of normalizing constant

Return type:

Tuple of (M, MU, MI, pi0, lE) where

References

Original MATLAB: matlab/src/api/cache/cache_miss_is.m

logmeanexp(x)[source]

Compute log(mean(exp(x))) in a numerically stable way.

Uses the log-sum-exp trick for numerical stability.

cache_t_hlru(gamma, m)[source]

Characteristic time of each list of an h-LRU / LRU(m) cache.

Solves the TTL (characteristic-time) fixed point of the list-based h-LRU (LRU(m)) policy: sum_k pi_l(k;T) = m[l] for each list l, where the level probabilities follow the birth-death form pi_l ~ prod_{s<=l} (1-e_s)/e_s with e_s = exp(-gamma_k*T_s) (Gast and Van Houdt, SIGMETRICS 2015). Solved by per-list bisection with Gauss-Seidel sweeps.

Parameters:
  • gamma (numpy.ndarray) – (n,) per-item request rates; an (n x h) matrix is accepted for backward compatibility (first column used)

  • m (numpy.ndarray) – Cache capacity vector (h,)

Returns:

Characteristic time for each cache list (h,)

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/cache/cache_t_hlru.m

cache_ttl_hlru(gamma, m)[source]

Steady-state list occupancy probabilities for an h-LRU / LRU(m) cache.

Characteristic-time (TTL) approximation of the list-based h-LRU policy: h LRU lists of capacities m[0..h-1], a miss inserts at the head of list 1, a hit in list l exchanges the item with the tail of list l+1 (Gast and Van Houdt, SIGMETRICS 2015). For h=1 this reduces exactly to the Che approximation for LRU.

Parameters:
  • gamma (numpy.ndarray) – Per-item request rates. Accepts (n,), (n x h), or the MVA analyzer layout (u x n x h+1) which is aggregated over users.

  • m (numpy.ndarray) – Cache capacity vector (h,)

Returns:

(n x h+1) probabilities; column 0 = not cached, column 1+l = in list l

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/cache/cache_ttl_hlru.m

cache_ttl_lrua(lambd, R, m, seed=23000, ttl=None)[source]

Compute steady-state probabilities for TTL-LRU cache with arrival routing.

Uses fixed-point iteration with DTMC solving for cache systems with multiple users, items, and levels with routing.

Parameters:
  • lambd (numpy.ndarray) – Arrival rates per user per item per list (u x n x h+1)

  • R (list) – Routing probability structure. Can be either: - 1D list: R[i] is the (h+1 x h+1) routing matrix for item i - 2D list: R[v][i] is the routing matrix for user v, item i

  • m (numpy.ndarray) – Cache capacity vector (h,)

  • seed (int) – Random seed for initialization (default: 23000)

  • ttl (numpy.ndarray | None) – Optional real TTL per cache level (h,). Caps the characteristic time at each level: items expire after ttl[l] time units even if the cache is not full. Units are in model time (request epochs when arrival rates sum to 1). Use np.inf for levels with no TTL. When TTL is binding, effective occupancy may be less than m[l].

Returns:

Steady-state probability distribution (n x h+1)

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/cache/cache_ttl_lrua.m

cache_rrm_meanfield_ode(t, x, lambd, m, n, h)[source]

ODE function for RRM mean-field cache dynamics.

Defines the differential equations for the Random Replacement Model mean-field cache dynamics.

Parameters:
  • t (float) – Time variable (unused, for ODE solver compatibility)

  • x (numpy.ndarray) – State vector of length n*(h+1), representing probabilities

  • lambd (numpy.ndarray) – Arrival rates per item (n,)

  • m (numpy.ndarray) – Cache capacity vector (h,)

  • n (int) – Number of items

  • h (int) – Number of cache levels

Returns:

Time derivative of state vector

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/cache/cache_rrm_meanfield_ode.m

cache_rrm_meanfield(lambd, m, t_end=10000.0, seed=23000)[source]

Solve RRM mean-field steady state using ODE integration.

Computes the steady-state probability distribution for a cache with random replacement policy using mean-field ODE dynamics.

Parameters:
  • lambd (numpy.ndarray) – Arrival rates per item (n,)

  • m (numpy.ndarray) – Cache capacity vector (h,)

  • t_end (float) – End time for ODE integration (default: 10000.0)

  • seed (int) – Random seed for initial conditions (default: 23000)

Returns:

  • prob: Steady-state probability matrix (n x h+1)

  • missrate: Global miss rate (lambda * miss_prob)

  • missratio: Miss ratio (missrate / sum(lambda))

Return type:

Tuple of (prob, missrate, missratio) where

References

Original MATLAB: matlab/src/api/cache/cache_rrm_meanfield.m

cache_gamma_lp(lambd, R)[source]

Compute gamma parameters for cache models using linear programming approach.

Computes item popularity probabilities at each cache level based on arrival rates and routing probabilities.

Parameters:
  • lambd (numpy.ndarray) – Arrival rates per user per item per list (u x n x h+1)

  • R (list) – Routing probability structure (list of lists, R[v][i] is matrix for user v, item i)

Returns:

  • gamma: Item popularity probabilities at each level (n x h)

  • u: Number of users

  • n: Number of items

  • h: Number of cache levels

Return type:

Tuple of (gamma, u, n, h) where

References

Original MATLAB: matlab/src/api/cache/cache_gamma_lp.m

Product-Form Queueing Networks (line_solver.api.pfqn)

Product-form queueing network (PFQN) algorithms.

Native Python implementations of analytical algorithms for product-form queueing networks, including Mean Value Analysis (MVA), normalizing constant methods, and various approximation techniques.

Key algorithms:

pfqn_mva: Standard Mean Value Analysis pfqn_ca: Convolution Algorithm pfqn_nc: Normalizing Constant methods pfqn_bs: Balanced System analysis pfqn_aql: Approximate queue lengths

pfqn_mva(L, N, Z=None, mi=None)[source]

Mean Value Analysis for multi-class closed product-form network.

Implements the exact MVA algorithm using population recursion. Computes exact performance measures for closed product-form networks with load-independent stations.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R) where M is stations, R is classes

  • N (numpy.ndarray) – Population vector (1 x R or R,) - number of jobs per class

  • Z (numpy.ndarray) – Think time vector (1 x R or R,) - think time per class (default 0)

  • mi (numpy.ndarray) – Multiplicity vector (1 x M or M,) - servers per station (default 1)

Returns:

  • XN: Throughputs per class (1 x R)

  • CN: Response times per class (1 x R) - total cycle time

  • QN: Queue lengths (M x R)

  • UN: Utilizations (M x R)

  • RN: Residence times (M x R)

  • TN: Node throughputs (M x R)

  • AN: Arrival rates (M x R)

Return type:

Tuple of (XN, CN, QN, UN, RN, TN, AN) where

pfqn_mva_single_class(N, L, Z=0.0, mi=None)[source]

Mean Value Analysis for single-class closed network.

Simplified MVA for single customer class, with optional multi-server stations specified via mi (multiplicity).

Parameters:
  • N (int) – Number of customers

  • L (numpy.ndarray) – Service demands at each station (1D array of length M)

  • Z (float) – Think time (default 0)

  • mi (numpy.ndarray | None) – Number of servers at each station (default all 1)

Returns:

  • ‘X’: Throughput

  • ’Q’: Queue lengths (array of length M)

  • ’R’: Residence times (array of length M)

  • ’U’: Utilizations (array of length M)

  • ’lG’: Log of normalizing constant

Return type:

dict with keys

pfqn_bs(L, N, Z=None, tol=1e-6, maxiter=1000, QN0=None, type_sched=None)[source]

Bard-Schweitzer Approximate Mean Value Analysis (MVA).

Iterative approximate MVA algorithm that uses the (N-1)/N correction for the arrival theorem, providing good accuracy for most networks.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector

  • Z (numpy.ndarray) – Think time vector (default 0)

  • tol (float) – Convergence tolerance (default 1e-6)

  • maxiter (int) – Maximum iterations (default 1000)

  • QN0 (numpy.ndarray) – Initial queue lengths (default: uniform distribution)

  • type_sched (numpy.ndarray) – Scheduling strategy per station (default: PS)

Returns:

XN: System throughputs (1 x R) QN: Mean queue lengths (M x R) UN: Utilizations (M x R) RN: Residence times (M x R) it: Number of iterations performed

Return type:

Tuple (XN, QN, UN, RN, it) matching MATLAB’s pfqn_bs

pfqn_aql(L, N, Z=None, max_iter=1000, tol=1e-6, QN0=None)[source]

Approximate Queue Length (AQL) algorithm.

Uses iterative approximation to compute queue lengths for large populations where exact MVA would be computationally expensive.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector

  • Z (numpy.ndarray) – Think time vector (default 0)

  • max_iter (int) – Maximum iterations (default 1000)

  • tol (float) – Convergence tolerance (default 1e-6)

Returns:

Same format as pfqn_mva

Return type:

Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray]

pfqn_sqni(L, N, Z=None)[source]

Square-root Non-iterative (SQNI) approximate MVA.

Implements a fast approximation for multi-class closed queueing networks that reduces the system to single-queue representations with interpolation-based corrections.

This method is particularly efficient for networks where one station dominates (bottleneck analysis), providing a good trade-off between accuracy and computational speed.

Parameters:
  • L (numpy.ndarray) – Service demand vector (1 x R or R,) - demands at the bottleneck queue

  • N (numpy.ndarray) – Population vector (1 x R or R,) - number of jobs per class

  • Z (numpy.ndarray) – Think time vector (1 x R or R,) - think time per class (default 0)

Returns:

  • Q: Queue lengths (2 x R) - first row for queue, second placeholder

  • U: Utilizations (2 x R) - first row for queue, second placeholder

  • X: Throughputs (1 x R)

Return type:

Tuple of (Q, U, X) where

Reference:

Based on the SQNI method for approximate MVA analysis.

pfqn_qd(L, N, ga=None, be=None, Q0=None, tol=1e-6, max_iter=1000)[source]

Queue-Dependent (QD) Approximate MVA.

Implements the QD-AMVA algorithm that uses queue-dependent correction factors to improve accuracy of approximate MVA for closed networks.

The algorithm iteratively computes queue lengths using: - A correction factor delta = (N_tot - 1) / N_tot - Per-class correction factor delta_r = (N_r - 1) / N_r - Optional scaling functions ga(A) and be(A) for advanced corrections

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R) - rows are stations, columns are classes

  • N (numpy.ndarray) – Population vector (R,) - number of jobs per class

  • ga (callable) – Gamma scaling function ga(A) -> array(M,) (default: ones) A is the arrival queue seen by class, A[k] = 1 + delta * sum(Q[k,:])

  • be (callable) – Beta scaling function be(A) -> array(M, R) (default: ones) A is the arrival queue per class, A[k,r] = 1 + delta_r * Q[k,r]

  • Q0 (numpy.ndarray) – Initial queue length estimate (M x R) (default: proportional)

  • tol (float) – Convergence tolerance (default 1e-6)

  • max_iter (int) – Maximum iterations (default 1000)

Returns:

Q: Mean queue lengths (M x R) X: Class throughputs (R,) U: Utilizations (M x R) iter: Number of iterations performed

Return type:

Tuple of (Q, X, U, iter) where

Reference:

Schweitzer, P.J. “Approximate analysis of multiclass closed networks of queues.” Proceedings of the International Conference on Stochastic Control and Optimization (1979).

pfqn_qdlin(L, N, Z=None, tol=1e-6, max_iter=1000)[source]

QD-Linearizer (QDLIN) Approximate MVA.

Combines Queue-Dependent (QD) correction with Linearizer iteration for improved accuracy in multi-class closed networks.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,) (default: zeros)

  • tol (float) – Convergence tolerance (default 1e-6)

  • max_iter (int) – Maximum iterations (default 1000)

Returns:

Q: Mean queue lengths (M x R) U: Utilizations (M x R) R: Residence times (M x R) X: Class throughputs (1 x R) C: Cycle times (1 x R) iter: Number of iterations performed

Return type:

Tuple of (Q, U, R, X, C, iter) where

pfqn_qli(L, N, Z=None, tol=1e-6, max_iter=1000)[source]

Queue-Line (QLI) Approximate MVA (Wang-Sevcik).

Implements the Wang-Sevcik Queue-Line approximation which provides improved accuracy for multi-class networks by better estimating the queue length seen by arriving customers.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,) (default: zeros)

  • tol (float) – Convergence tolerance (default 1e-6)

  • max_iter (int) – Maximum iterations (default 1000)

Returns:

Q: Mean queue lengths (M x R) U: Utilizations (M x R) R: Residence times (M x R) X: Class throughputs (1 x R) C: Cycle times (1 x R) iter: Number of iterations performed

Return type:

Tuple of (Q, U, R, X, C, iter) where

Reference:

Wang, W. and Sevcik, K.C. “Performance Models for Multiprogrammed Systems.” IBM Research Report RC 5925 (1976).

pfqn_fli(L, N, Z=None, tol=1e-6, max_iter=1000)[source]

Fraction-Line (FLI) Approximate MVA (Wang-Sevcik).

Implements the Wang-Sevcik Fraction-Line approximation, an alternative to Queue-Line that uses a different formula for estimating the queue length seen by arriving customers.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,) (default: zeros)

  • tol (float) – Convergence tolerance (default 1e-6)

  • max_iter (int) – Maximum iterations (default 1000)

Returns:

Q: Mean queue lengths (M x R) U: Utilizations (M x R) R: Residence times (M x R) X: Class throughputs (1 x R) C: Cycle times (1 x R) iter: Number of iterations performed

Return type:

Tuple of (Q, U, R, X, C, iter) where

Reference:

Wang, W. and Sevcik, K.C. “Performance Models for Multiprogrammed Systems.” IBM Research Report RC 5925 (1976).

pfqn_bsfcfs(L, N, Z=None, tol=1e-6, max_iter=1000, QN=None, weight=None)[source]

Bard-Schweitzer approximate MVA for FCFS scheduling with weighted priorities.

Implements AMVA with FCFS approximation where classes can have relative priority weights affecting the expected waiting times.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R) where M is stations, R is classes

  • N (numpy.ndarray) – Population vector (1 x R) - number of jobs per class

  • Z (numpy.ndarray) – Think time vector (1 x R) - default: zeros

  • tol (float) – Convergence tolerance (default 1e-6)

  • max_iter (int) – Maximum iterations (default 1000)

  • QN (numpy.ndarray) – Initial queue length matrix (M x R) - default: uniform distribution

  • weight (numpy.ndarray) – Weight matrix (M x R) for relative priorities - default: ones

Returns:

XN: System throughput per class (1 x R) QN: Mean queue lengths (M x R) UN: Utilizations (M x R) RN: Residence times (M x R) it: Number of iterations performed

Return type:

Tuple of (XN, QN, UN, RN, it) where

Reference:

Bard, Y. and Schweitzer, P.J. “Analyzing Closed Queueing Networks with Multiple Job Classes and Multiserver Stations.” Performance Evaluation Review 7.1-2 (1978).

pfqn_joint(n, L, N, Z=None, lGN=None)[source]

Compute joint queue-length probability distribution.

Computes the joint probability for a given queue-length state vector in a closed product-form queueing network.

Parameters:
  • n (numpy.ndarray) – Queue-length state vector (M,) for total or (M x R) for per-class - If 1D (M,): n[i] is the total number of jobs at station i - If 2D (M x R): n[i,r] is the number of class-r jobs at station i

  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (1 x R)

  • Z (numpy.ndarray) – Think time vector (1 x R) - default: zeros

  • lGN (float) – Log normalizing constant (optional, computed if not provided)

Returns:

Joint probability of state n

Return type:

pjoint

Examples

# Total queue-lengths (Z > 0) >>> p = pfqn_joint([2, 1], [[10, 2], [5, 4]], [2, 2], [91, 92])

# Per-class queue-lengths >>> p = pfqn_joint([[1, 0], [0, 1]], [[10, 2], [5, 4]], [2, 2], [91, 92])

pfqn_ca(L, N, Z=None)[source]

Convolution Algorithm for normalizing constant computation.

Computes the normalizing constant G(N) for a closed product-form queueing network using Buzen’s convolution algorithm.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R) where M is stations, R is classes

  • N (numpy.ndarray) – Population vector (1 x R or R,) - number of jobs per class

  • Z (numpy.ndarray) – Think time vector (1 x R or R,) - think time per class (default 0)

Returns:

  • G: Normalizing constant

  • lG: log(G)

Return type:

Tuple (G, lG) where

pfqn_is(L, N, Z=None, options=None)[source]

Importance-sampling (IS) estimate of the normalizing constant of a closed LOAD-INDEPENDENT product-form queueing network with M single-server queues of per-class demand L and an aggregated delay of think time Z.

This is the load-independent case of pfqn_ld_is() (capacities mu_i(k)=1), and the ordinary-network counterpart of the order-independent pfqn_oi_is and the pass-and-swap pfqn_pas_is: all four are the same sample-an-ordering estimator, differing only in the per-position factor of each station’s balance function. For a single-server queue that factor is the demand of the class at that position, L(i,q_p); for the delay it is Z(q_p)/p; for an OI/P&S station it is the reciprocal rank rate 1/mu_i(supp(q_1..q_p)).

With ell = sum(N), an ordering c of all ell jobs is drawn by placing a uniformly random present class at each step (probability p(c) = product of the reciprocal branching factors), and the sum over ALL ways of cutting c into contiguous per-station segments is computed exactly by dynamic programming:

G(N) = E_{C~p}[ S(C)/p(C) ],
S(c) = sum_{cuts} prod_m prod_p L(m, seg_m(p))

which is unbiased for the exact constant of pfqn_nc().

Parameters:
  • L ((M, R) array) – Per-class service demands at the M single-server queues.

  • N ((R,) array) – Closed population vector, finite.

  • Z ((R,) array, optional) – Aggregated think time (delay) demand; None or zeros if none.

  • options (dict or options object, optional) – Fields samples (default 1e4) and seed (optional).

Returns:

(G, lG) – IS estimate of the normalizing constant and its logarithm.

Return type:

tuple of float

Examples

>>> L = np.array([[0.5, 0.3], [0.2, 0.4]]); N = np.array([3, 2]); Z = np.array([1.0, 1.0])
>>> G, lG = pfqn_is(L, N, Z, {'samples': 100000})

See also

pfqn_ld_is, pfqn_nc

pfqn_nc(L, N, Z=None, method='ca', options=None)[source]

Normalizing constant computation dispatcher.

Selects appropriate algorithm based on method parameter.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,) (default: zeros)

  • method (str) – Algorithm to use: - ‘ca’, ‘exact’: Convolution algorithm - ‘default’: Auto-select based on problem size - ‘le’: Leading eigenvalue asymptotic - ‘cub’: Controllable upper bound - ‘imci’: Importance sampling Monte Carlo integration - ‘panacea’: Hybrid convolution/MVA - ‘propfair’: Proportionally fair allocation - ‘mmint2’: Gauss-Legendre quadrature - ‘gleint’: Gauss-Legendre integration - ‘sampling’: Monte Carlo sampling - ‘kt’: Knessl-Tier expansion - ‘comom’: Conditional moments - ‘rd’: Reduction heuristic - ‘ls’: Linearizer

Returns:

Tuple (G, lG) - normalizing constant and its log

Return type:

Tuple[float, float]

pfqn_nc_resolved_method(method)[source]

The algorithm pfqn_nc actually runs for METHOD.

pfqn_nc substitutes a different algorithm for some method names, so the requested name is not always the one that ran. Callers that report the method to the user must resolve it through here, otherwise the banner names an algorithm that never executed.

Currently only ‘comom’ substitutes: the native pfqn_comomrm port is not numerically robust for R>1, so convolution is used instead, which is exact for the single-station product-form models CoMoM-RM targets. The substitution is unconditional, hence resolvable without solving. Note this is BROADER than MATLAB, whose pfqn_nc reports ‘ca’ only for the R==1 case and genuinely runs CoMoM-RM for R>1 with a single queue.

pfqn_panacea(L, N, Z=None)[source]

PANACEA algorithm (hybrid convolution/MVA).

Currently implemented as wrapper around convolution algorithm.

Parameters:
Returns:

Tuple (G, lG) - normalizing constant and its log

Return type:

Tuple[float, float]

pfqn_propfair(L, N, Z=None)[source]

Proportionally Fair allocation approximation for normalizing constant.

Estimates the normalizing constant using a convex optimization program that is asymptotically exact in models with single-server PS queues only.

This method is based on Schweitzer’s approach and Walton’s proportional fairness theory for multi-class networks.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R) where M is stations, R is classes

  • N (numpy.ndarray) – Population vector (1 x R or R,) - number of jobs per class

  • Z (numpy.ndarray) – Think time vector (1 x R or R,) - think time per class (default 0)

Returns:

  • G: Estimated normalizing constant

  • lG: log(G)

  • X: Asymptotic throughputs per class (1 x R)

Return type:

Tuple (G, lG, X) where

References

Schweitzer, P. J. (1979). Approximate analysis of multiclass closed networks of queues. In Proceedings of the International Conference on Stochastic Control and Optimization.

Walton, N. (2009). Proportional fairness and its relationship with multi-class queueing networks.

pfqn_ls(L, N, Z=None, I=100000)[source]

Logistic sampling approximation for normalizing constant.

Approximates the normalizing constant using importance sampling from a multivariate normal distribution fitted at the leading eigenvalue mode.

This method is particularly effective for large networks where convolution becomes computationally expensive.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,) (default: zeros)

  • I (int) – Number of samples for Monte Carlo integration (default: 100000)

Returns:

G: Estimated normalizing constant lG: log(G)

Return type:

Tuple (G, lG) where

Reference:

G. Casale. “Accelerating performance inference over closed systems by asymptotic methods.” ACM SIGMETRICS 2017.

pfqn_clw(L, N, Z=None, m=None, l=None, gamma=None)[source]

Choudhury-Leung-Whitt normalization constant by numerical inversion of the generating function (JACM 42(5):935-970, 1995).

Computes g(K) of a multichain closed product-form network with single-server and (optionally) infinite-server queues by numerically inverting its p-dimensional generating function (eq. 4.5)

G(z) = exp(sum_j rho_{j0} z_j) / prod_i (1 - sum_j rho_{ji} z_j)^{m_i}

where j=1..p indexes chains, i=1..q’ the distinct single-server queues with multiplicity m_i. g(K) is recovered by p nested one-dimensional lattice-Poisson inversions (eq. 2.3) with restrictive static scaling (eqs. 5.41-5.46) and log-domain recovery (eq. 7.1).

Parameters:
  • L (numpy.ndarray) – (q’ x p) single-server relative traffic intensities, L[i,j]=rho_{ji}.

  • N (numpy.ndarray) – (p,) closed-chain population vector K.

  • Z (numpy.ndarray) – (p,) aggregate infinite-server relative intensities rho_{j0}. Default 0.

  • m (numpy.ndarray) – (q’,) queue multiplicities m_i. Default ones.

  • l (numpy.ndarray) – (p,) inner lattice parameters l_j. Default 1,2,2,3,3,…

  • gamma (numpy.ndarray) – (p,) aliasing parameters gamma_j. Default 11,13,13,15,15,…

Returns:

normalization constant (inf if it overflows double) and its natural logarithm (always finite).

Return type:

Tuple (G, lG)

Note: exact nested inversion of cost prod_j 2 l_j K_j; practical for moderate populations and few chains. The paper’s Euler summation and dimension reduction speed-ups are not applied here.

pfqn_clw_lld(L, N, Z=None, mu=None, l=None, gamma=None)[source]

Choudhury-Leung-Whitt normalization constant by numerical inversion of the generating function (JACM 42(5):935-970, 1995), extended to limited load-dependent (LLD) stations via the per-center transforms of Bertozzi and McKenna (SIAM Review 35(2):239-268, 1993).

The generating function is (Bertozzi-McKenna eqs. 2.17/2.23)

G(z) = exp(sum_j rho_{j0} z_j) prod_i F_i(sum_j rho_{ji} z_j)

where F_i is the transform of the station factor of queue i (eq. 2.16) with load-dependent rate scalings S_i(k) = mu[i,k]. For an LLD queue, S_i(k) = c_i constant for k >= l_i, and F_i is the rational function (eq. 2.19)

F_i(x) = [c_i + sum_{n=1}^{l_i-1} (c_i - S_i(n))

/ prod_{k=1}^n S_i(k) * x^n] / (c_i - x),

analytic except for a simple pole at x = c_i. Multiserver and load-independent queues are special cases. Since g(K) depends on S_i(k) only for k <= sum(K), general load-dependent input is truncated to LLD at sum(K) without loss of exactness.

g(K) is recovered by p nested one-dimensional lattice-Poisson inversions (CLW eq. 2.3) with restrictive static scaling adapted from CLW eqs. 5.41-5.46 (each queue normalized by its pole c_i, simple pole) and log-domain recovery (eq. 7.1).

Parameters:
  • L (numpy.ndarray) – (q’ x p) single-server relative traffic intensities, L[i,j]=rho_{ji}.

  • N (numpy.ndarray) – (p,) closed-chain population vector K.

  • Z (numpy.ndarray) – (p,) aggregate infinite-server relative intensities rho_{j0}. Default 0.

  • mu (numpy.ndarray) – (q’ x n) load-dependent rate scalings mu[i,k] = S_i(k+1); if fewer than sum(N) columns are given the last column is extended (LLD assumption). Default ones (all queues load-independent).

  • l (numpy.ndarray) – (p,) inner lattice parameters l_j. Default 1,2,2,3,3,…

  • gamma (numpy.ndarray) – (p,) aliasing parameters gamma_j. Default 11,13,13,15,15,…

Returns:

normalization constant (inf if it overflows double) and its natural logarithm (always finite).

Return type:

Tuple (G, lG)

Note: cost is prod_j 2 l_j K_j contour points, each of cost O(sum_i l_i); practical for moderate populations and few chains.

pfqn_linearizer(L, N, Z, sched_type, tol=1e-8, maxiter=1000, QN0=None)[source]

Linearizer approximate MVA algorithm.

Parameters:
  • L (numpy.ndarray) – Demand matrix (M x R) - rows are stations, columns are classes

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,)

  • sched_type (List[str]) – List of scheduling strategies per station (‘FCFS’, ‘PS’, etc.)

  • tol (float) – Convergence tolerance

  • maxiter (int) – Maximum iterations

Returns:

Q: Queue lengths (M x R) U: Utilizations (M x R) W: Waiting times (M x R) T: Station throughputs (M x R) C: Response times (1 x R) X: Class throughputs (1 x R) iterations: Number of iterations

Return type:

Tuple of (Q, U, W, T, C, X, iterations)

pfqn_gflinearizer(L, N, Z, sched_type, tol=1e-8, maxiter=1000, alpha=1.0, QN0=None)[source]

General-form linearizer approximate MVA.

Parameters:
  • L (numpy.ndarray) – Demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,)

  • sched_type (List[str]) – List of scheduling strategies per station

  • tol (float) – Convergence tolerance

  • maxiter (int) – Maximum iterations

  • alpha (float) – Linearization parameter (scalar)

Returns:

Same as pfqn_linearizer

Return type:

Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, int]

pfqn_egflinearizer(L, N, Z, sched_type, tol=1e-8, maxiter=1000, alpha=None, QN0=None)[source]

Extended general-form linearizer with class-specific parameters.

Parameters:
  • L (numpy.ndarray) – Demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,)

  • sched_type (List[str]) – List of scheduling strategies per station

  • tol (float) – Convergence tolerance

  • maxiter (int) – Maximum iterations

  • alpha (numpy.ndarray) – Class-specific linearization parameters (R,)

Returns:

Tuple of (Q, U, W, T, C, X, iterations)

Return type:

Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, int]

pfqn_momlin(L, N, Z=None, tol=1e-8, maxiter=1000)[source]

Approximate first and second queue-length moments of a closed product-form network, scalable to large populations and many classes.

Parameters:
  • L ((M, R) array) – Service demand matrix.

  • N ((R,) array) – Closed population per class.

  • Z ((R,) array, optional) – Think time per class (default zeros).

  • tol (float) – Convergence tolerance on the queue-length fixed point.

  • maxiter (int) – Maximum iterations.

Return type:

PfqnMomlin

class PfqnMomlin(Q, X, U, R, QVar, QCov, dQ)[source]

Bases: object

Result container for pfqn_momlin().

Q

Mean queue length.

Type:

np.ndarray (M x R)

X

Throughput per class.

Type:

np.ndarray (1 x R)

U, R

Utilization and residence time.

Type:

np.ndarray (M x R)

QVar

Queue-length variance.

Type:

np.ndarray (M x R)

QCov

Queue-length covariance, QCov[i, r, j, s] = Cov[n_ir, n_js].

Type:

np.ndarray (M x R x M x R)

dQ

Demand derivatives, dQ[i, r, j, s] = dQ_ir/dD_js.

Type:

np.ndarray (M x R x M x R)

class SchedStrategy(*values)[source]

Bases: Enum

Scheduling strategies for queueing stations.

pfqn_sens(L, N, Z=None, mi=None)[source]

Exact derivatives of {X, Q, U, R} w.r.t. demands L and think times Z.

Derivatives are analytic (exact to machine precision), not finite differences. The CoMoM-backed kernel is selected for the repairman model (a single single-server queue, M=1, plus a think-time delay where every populated class has positive think time and demand); it is polynomial in the number of classes R. Every other model uses forward-mode differentiation of the exact MVA recursion.

Parameters:
  • L ((M, R) array) – Service demand matrix, L[i, r] = visits_ir / rate_ir.

  • N ((R,) array) – Population per class.

  • Z ((R,) array, optional) – Think time per class (default zeros).

  • mi ((M,) array, optional) – Station residence multiplicity (default ones).

Return type:

PfqnSens

class PfqnSens(X, Q, U, R, params, dX, dQ, dU, dR, QCov=None, QVar=None, QTotVar=None, QCovAsym=None)[source]

Bases: object

Result container for pfqn_sens().

X, Q, U, R

Base MVA measures. X is (1 x R) system throughput per class, Q (M x R) mean queue length, U (M x R) utilization, R (M x R) residence time per visit.

Type:

np.ndarray

params

One entry per differentiation parameter p with keys type (‘L’ or ‘Z’), station (i, or -1 for Z) and jobclass (r).

Type:

list of dict

dX
Type:

np.ndarray (R x P)

dQ, dU, dR

Derivative of each base measure w.r.t. parameter p.

Type:

np.ndarray (M x R x P)

QCov

Queue-length covariance, QCov[i, r, j, s] = Cov[n_ir, n_js] = D_js dQ_ir/dD_js. The same-station blocks (i == j) come from pfqn_sens_mva(); the cross-station ones are read off the Jacobian.

Type:

np.ndarray (M x R x M x R)

QVar

Queue-length variance, QVar[i, r] = QCov[i, r, i, r].

Type:

np.ndarray (M x R)

QTotVar

Variance of the total queue length per station, QTotVar[i] = Var[sum_r n_ir].

Type:

np.ndarray (M,)

QCovAsym

Roundoff-level residual of the moment recursion, see pfqn_sens_mva().

Type:

float

pfqn_sens_mva(L, N, Z=None, mi=None)[source]

Exact second moments of the queue lengths of a closed product-form network.

The moments are obtained by an MVA-type recursion evaluated on the same population lattice as pfqn_mva(), so no derivative of the model is ever formed and the cost is O(M*R^2) per lattice point rather than the O(M^2*R^2) of the differentiated-MVA kernel used by pfqn_sens().

The recursion is obtained by differentiating the Reiser-Lavenberg MVA equation Q(j,v|N) = X(v|N) L(j,v) (mi(j) + Qtot(j|N-e_v)) with respect to the visit ratio theta(i,k) of class k at station i and rescaling. Writing W(k,i;v,j|N) = Cov[n(i,k), n(j,v)] at population N,

W(k,i;v,j|N) = Q(j,v|N) (Q(i,k|N-e_v) - Q(i,k|N))
  • [i==j & k==v] Q(j,v|N)

  • X(v|N) L(j,v) sum_t W(k,i;t,j|N-e_v)

with W(.|0) = 0. This routine evaluates the same-station case i==j, which is self-contained: the inner sum then only involves same-station terms, so a single scalar Ssum(j,k|N) = sum_t W(k,j;t,j|N) carried along the lattice closes the recursion. The cross-station case i != j is not self-contained (it couples every station pair) and costs as much as the full Jacobian, so it is left to pfqn_sens().

Setting i == j and mi == 1 reproduces Corollary 1 of de Souza e Silva and Muntz, i.e. its equations (2.9a) for the variance and (2.10) for the covariance; the station multiplicity mi cancels identically because X(v|N) L(j,v) (mi(j) + Qtot(j|N-e_v)) = Q(j,v|N) is the MVA equation for any mi. The equivalent statement for an infinite-server station, equation (2.9b), is recovered automatically because LINE folds the delay into the think time Z, which enters only through X(v|N) and carries no queue-length moment of its own.

Parameters:
  • L ((M, R) array) – Service demand matrix, L[i, r] = visits_ir / rate_ir.

  • N ((R,) array) – Population per class. Must be finite (closed populations only).

  • Z ((R,) array, optional) – Think time per class (default zeros).

  • mi ((M,) array, optional) – Server multiplicity per station (default ones).

Return type:

PfqnSensMva

Notes

Restricted to closed populations. Mixed and load-dependent models are handled by pfqn_sens_mvaldmx().

For a station of multiplicity mi[i] > 1, which LINE treats as mi[i] identical replicas sharing the demand row L[i, :], the moments returned are those of the aggregate queue length over the replicas.

class PfqnSensMva(X, Q, U, R, QCov, QVar, QTotVar, QCovAsym)[source]

Bases: object

Result container for pfqn_sens_mva().

X, Q, U, R

Base MVA measures, identical entry by entry to pfqn_mva(L, N, Z, mi). X is (1 x R) system throughput per class, Q (M x R) mean queue length, U (M x R) utilization, R (M x R) residence time per visit.

Type:

np.ndarray

QCov

QCov[i, r, s] = Cov[n(i,r), n(i,s)], the queue-length covariance of classes r and s at station i. Symmetric in (r, s).

Type:

np.ndarray (M x R x R)

QVar

QVar[i, r] = QCov[i, r, r] = Var[n(i,r)].

Type:

np.ndarray (M x R)

QTotVar

QTotVar[i] = Var[sum_r n(i,r)], i.e. sum_{r,s} QCov[i, r, s]. This is Theorem 3 of de Souza e Silva and Muntz, obtained here without a capacity derivative.

Type:

np.ndarray (M,)

QCovAsym

max |W(r,s) - W(s,r)| over the covariance entries before symmetrization. The two triangles come from differentiating two different classes’ MVA equations, so this is an independent residual of the recursion and should sit at roundoff; a large value signals a bug.

Type:

float

pfqn_sens_ldmx_ec(lam, D, mu)[source]

Effective capacity terms of the mixed load-dependent MVA and their exact derivatives with respect to the open-class load.

Computes the terms EC, E and Eprime of the mixed load-dependent MVA of Bruell-Balbo-Afshari, exactly as pfqn_ldmx_ec() does, and additionally their exact analytic derivatives with respect to the open-class load Lo[i] of each station.

Lo[i] = sum_r lambda[r] D[i, r] is the only channel through which a service demand enters E, Eprime and EC: the load-dependent rates mu are independent of the demands. Station i’s terms depend on Lo[i] alone, so a single derivative per station is enough, and the chain rule then yields the derivative with respect to any demand-scaling parameter. This is the factorization behind equations (19), (21) and (24)-(31) of Akyildiz and Strelen, which are reproduced here term by term.

Parameters:
  • lam ((R,) array) – Arrival rate vector. Zero for closed classes.

  • D ((M, R) array) – Service demand matrix.

  • mu ((M, Nt) array) – Load-dependent rate matrix, limited load dependence.

Returns:

  • EC ((M, Nt) array) – Effective capacity matrix.

  • E ((M, 1 + Nt) array) – E-function values, E[i, n] holding the MATLAB E(i, 1+n).

  • Eprime ((M, 1 + Nt) array) – E-prime function values, indexed as E.

  • Lo ((M,) array) – Open class load vector.

  • dEC ((M, Nt) array) – dEC[i, n] = dEC(i, n)/dLo(i).

  • dE ((M, 1 + Nt) array) – dE[i, n] = dE(i, n)/dLo(i).

  • dEprime ((M, 1 + Nt) array) – dEprime[i, n] = dEprime(i, n)/dLo(i).

Return type:

Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray]

pfqn_sens_mvaldmx(lam, D, N, Z, mu=None, S=None)[source]

Exact second moments of the queue lengths of a mixed open/closed product-form network with limited load-dependent service rates.

This is the load-dependent and mixed counterpart of pfqn_sens_mva(), which is restricted to closed load-independent models.

The method is the moment analysis of Akyildiz and Strelen. Their Theorem 1, equation (11), states that multiplying a queue-length moment by one further factor Q_jT costs one derivative with respect to a parameter y_j that scales the service demands s_ir of the classes r in T at station j:

E[Q_jT^k …] = d/dy_j E[Q_jT^(k-1) …]|_{y_j=1}
  • nbar_jT E[Q_jT^(k-1) …]

Taking k=2 and T={s} gives the second moment, hence

Cov[n(i,r), n(j,s)] = d nbar(i,r) / dy_(j,s) |_{y=1}

which is evaluated here by forward-mode differentiation of the mixed load-dependent MVA of Bruell-Balbo-Afshari, i.e. of exactly the recursion implemented by pfqn_mvaldmx(). The differentiated equations are (13) for the residence times, (15)-(17) for the conditional marginal probabilities, (18) for the throughputs, (19) and (24)-(31) for the effective capacities (delegated to pfqn_sens_ldmx_ec()), (32) for the closed-class queue lengths and (33) for the open-class ones.

Because a demand-scaling parameter perturbs the whole network through the closed-class throughputs, the derivatives must be propagated for every parameter, so the cross-station covariances come out at no extra cost and are returned in QCovFull. This is unlike pfqn_sens_mva(), whose cheaper same-station recursion cannot reach them.

Parameters:
  • lam ((R,) array) – Arrival rate vector. Must be zero on closed classes.

  • D ((M, R) array) – Service demand matrix.

  • N ((R,) array) – Population vector. inf entries denote open classes.

  • Z ((R,) array) – Think time vector.

  • mu ((M, sum(N)) array, optional) – Load-dependent rate matrix, limited load dependence (default ones).

  • S ((M,) array, optional) – Number of servers per station. Accepted for signature compatibility with pfqn_mvaldmx(), which likewise does not read it: the multiserver behaviour is carried entirely by the rates mu.

Return type:

PfqnSensMvaldmx

Notes

Open classes are supported: an open class contributes to the load Lo[i] that drives the effective capacities, and equation (21) supplies the corresponding dLo/dy.

The moments of an open class are those of its queue length at a station, which is finite even though its population is infinite.

class PfqnSensMvaldmx(X, Q, U, R, QCov, QCovFull, QVar, QTotVar, QCovAsym)[source]

Bases: object

Result container for pfqn_sens_mvaldmx().

X, Q, U, R

Base measures, identical to pfqn_mvaldmx(lambda, D, N, Z, mu, S). X is (R,) throughput per class, Q (M x R) mean queue length, U (M x R) utilization, R (M x R) residence time.

Type:

np.ndarray

QCov

QCov[i, r, s] = Cov[n(i,r), n(i,s)], the same-station block.

Type:

np.ndarray (M x R x R)

QCovFull

QCovFull[i, r, j, s] = Cov[n(i,r), n(j,s)].

Type:

np.ndarray (M x R x M x R)

QVar

QVar[i, r] = Var[n(i,r)].

Type:

np.ndarray (M x R)

QTotVar

QTotVar[i] = Var[sum_r n(i,r)].

Type:

np.ndarray (M,)

QCovAsym

max |QCovFull[i, r, j, s] - QCovFull[j, s, i, r]| before symmetrization. The two entries are produced by differentiating two different classes’ equations, so this residual is an independent check of the recursion and should sit at roundoff.

Type:

float

pfqn_sens_mom(L, N, Z=None, mi=None, groups=None)[source]

Exact moments E[Q_i], E[Q_i^2], E[Q_i^3] and the covariances Cov[Q_i,Q_j] of the TOTAL queue lengths Q_i = sum_r n(i,r) of a closed product-form (BCMP) queueing network.

The method is the moment analysis of Strelen. Its Theorem 3.1 states that one further factor Q_i in a moment costs one differentiation with respect to x_i, the reciprocal of the capacity of station i, i.e. a parameter that scales the service times of ALL classes at station i:

E[Q_i^j] = m_i E[Q_i^(j-1)] + x_i d/dx_i E[Q_i^(j-1)],   Q_i^0 = 1

Iterating from E[Q_i^0] = 1 gives, with m_i = E[Q_i], equation (3.2):

Var[Q_i]     = x_i dm_i/dx_i
Cov[Q_i,Q_j] = x_j dm_i/dx_j = x_i dm_j/dx_i
E[Q_i^2]     = x_i dm_i/dx_i + m_i^2
E[Q_i^3]     = x_i^2 d^2m_i/dx_i^2 + (x_i + 3 x_i m_i) dm_i/dx_i + m_i^3

so the third moment requires the SECOND derivative of the MVA recursion, which is what this routine adds over pfqn_sens_mva() and pfqn_sens() (both first order only). The derivatives are obtained by second-order forward-mode differentiation of the Reiser-Lavenberg recursion, i.e. by carrying, for each parameter, the value together with its first and second derivative along the population lattice (Theorem 3.2 for one class, Theorem 3.5 for several).

The parameter need not scale a whole column. Theorem 1 of Akyildiz and Strelen states the same recursion for a parameter that scales the service times of an arbitrary class subset T at station i, and the moments it generates are then those of Q_(i,T) = sum_(r in T) n(i,r). groups supplies that subset structure: it partitions the classes, and the routine reports the moments of each group’s queue length at each station. The three useful settings are:

groups = ones(R)   the whole column: per-station TOTALS (default, this
                   is Strelen's x_i)
groups = 1..R      one class per group: PER-CLASS moments, so that even
                   the third moment is per class
groups = chain(r)  one group per chain: PER-CHAIN moments

Strelen states only the first; the generalization is Akyildiz and Strelen’s T. The per-class setting reproduces pfqn_sens_mva()’s second moments exactly.

Parameters:
  • L ((M, R) array) – Service demand matrix, L[i, r] = visits_ir / rate_ir.

  • N ((R,) array) – Population per class. Must be finite (closed populations only).

  • Z ((R,) array, optional) – Think time per class (default zeros).

  • mi ((M,) array, optional) – Server multiplicity per station (default ones).

  • groups ((R,) array, optional) – Class-to-group map, a partition of the classes into G = max(groups) groups labelled consecutively 1..G with no empty group. Default ones(R), i.e. one group holding every class, the per-station total. Labels are 1-based, as in MATLAB.

Return type:

PfqnSensMom

Notes

Restricted to closed populations, as is the moment analysis of the reference. Mixed and load-dependent second moments are in pfqn_sens_mvaldmx().

Moments of the sojourn times at FCFS centers are built on top of these queue-length moments by pfqn_sens_respt(), following Theorem 4.1.

The exact recursion costs O(prod(N+1)) lattice points; pfqn_sens_linearizer() approximates the same quantities in polynomial time.

class PfqnSensMom(X, Q, U, R, m, dm, d2m, Var, Cov, M2, M3, Skew, CovAsym)[source]

Bases: object

Result container for pfqn_sens_mom().

X, Q, U, R

Base MVA measures, identical entry by entry to pfqn_mva(L, N, Z, mi). X is (1 x R), Q, U and R are (M x R).

Type:

np.ndarray

m

m[i, g] = E[Q_(i,g)], the mean queue length of group g at station i. COLLAPSED to (M,) in the default single-group case, where it is the per-station total.

Type:

np.ndarray (M, G)

dm

dm[i, g, j, g2], the scaled first derivative of m_(i,g) with respect to the parameter of (j, g2). Collapsed to (M, M) when G == 1.

Type:

np.ndarray (M, G, M, G)

d2m

d2m[i, g], the scaled pure second derivative with respect to the parameter of (i, g). Only that entry is needed by (3.2); the mixed second derivatives are not required for moments of a single Q_(i,g) and would cost an extra factor M*G to carry. Collapsed to (M,) when G == 1.

Type:

np.ndarray (M, G)

Var

Var[Q_(i,g)]. Collapsed to (M,) when G == 1.

Type:

np.ndarray (M, G)

Cov

Cov[i, g, j, g2] = Cov[Q_(i,g), Q_(j,g2)]. Collapsed to (M, M) when G == 1, where the group index carries no information.

Type:

np.ndarray (M, G, M, G)

M2

E[Q_(i,g)^2]. Collapsed to (M,) when G == 1.

Type:

np.ndarray (M, G)

M3

E[Q_(i,g)^3]. Collapsed to (M,) when G == 1.

Type:

np.ndarray (M, G)

Skew

Skewness of Q_(i,g), i.e. the third central moment divided by Var^(3/2). NaN where the variance is zero (a deterministic queue length). Collapsed to (M,) when G == 1.

Type:

np.ndarray (M, G)

CovAsym

max |x_j dm_i/dx_j - x_i dm_j/dx_i| before symmetrization of Cov. The two are distinct expressions that must agree, so this is a live residual of the recursion; expect roundoff.

Type:

float

pfqn_sens_respt(S, V, N, Z=None, b=None, tmax=3)[source]

Exact raw moments E[W_(i,l)^t], t = 1..tmax, of the sojourn time of a class-l job at an FCFS b-server center i of a closed product-form queueing network, together with the variance of that sojourn time.

This is Theorem 4.1 of the reference. Its mechanism is the arrival theorem of Lavenberg-Reiser and Sevcik-Mitrani: a class-l job arriving at center i finds j jobs already there with probability p_i(j, N - 1_l). Conditioning the sojourn time on j and inverting the Laplace transform of the conditional density gives:

E[W_(i,l)^t] = t!/mu^t + sum_{tau=0..t} a_(t,tau)(0) E[Qt_i^tau]
               - sum_{j=0..b-1} p_i(j,N-1_l) sum_{tau=0..t} a_(t,tau)(0) j^tau

where mu = 1/S(i) is the rate of each of the b servers, Qt_i is the total queue length at center i at population N - 1_l (so its moments are those of pfqn_sens_mom() evaluated one job down in class l), and the coefficients a_(t,tau)(0) depend only on b and mu, not on the network (Remark 4.3 of the reference). The moments E[Qt_i^tau] up to tau = 3 need the second derivative of the MVA recursion, so this routine carries a second-order forward-mode pass exactly as pfqn_sens_mom() does, but over the b-server recursion (4.1)-(4.2) rather than the single-server one.

For b = 1 the coefficients a_(t,0)(0) vanish identically and the double-sum correction disappears, so no marginal probabilities are needed (Remark 4.2 of the reference); the routine still evaluates the general expression, which reduces to that case on its own.

Only FCFS centers are covered. The reference is explicit that the sojourn-time distribution at PS and LCFS centers is in general not known, so no analogue exists there. FCFS in a BCMP network further requires the service time to be exponential and class-independent, which is why this routine takes a per-station service time S(i) and a separate visit-ratio matrix V rather than a demand matrix: the sojourn time is per visit, so the per-visit rate mu = 1/S(i) must be known and cannot be recovered from the demand L(i,l) = S(i)*V(i,l) alone.

Parameters:
  • S ((M,) array) – Service time at each station, common to all classes.

  • V ((M, R) array) – Visit ratio matrix. The demand is L[i, r] = S[i] * V[i, r].

  • N ((R,) array) – Population per class. Must be finite (closed populations only).

  • Z ((R,) array, optional) – Think time per class (default zeros).

  • b ((M,) array, optional) – Number of servers at each station (default ones).

  • tmax (int, optional) – Highest sojourn-time moment to return, 1..3 (default 3). The coefficients a_(t,tau)(0) are tabulated in the reference up to t = 3.

Return type:

PfqnSensRespt

Notes

Restricted to closed populations. Load-dependent rates are not covered here; the b-server dependence is the only state dependence, and it is carried exactly by (4.1)-(4.2).

class PfqnSensRespt(X, Q, U, m, Var, p, W, WM, Wresid, WVar, WSkew)[source]

Bases: object

Result container for pfqn_sens_respt().

X, Q, U

Base measures at population N. X is (1 x R), Q and U are (M x R).

Type:

np.ndarray

W

W[i, l] = E[W_(i,l)], the mean sojourn time per visit of a class-l job at station i. Zero where class l does not visit i.

Type:

np.ndarray (M, R)

WM

WM[i, l, t-1] = E[W_(i,l)^t].

Type:

np.ndarray (M, R, tmax)

WVar

Var[W_(i,l)] = E[W^2] - E[W]^2. Requires tmax >= 2.

Type:

np.ndarray (M, R)

WSkew

Skewness of W_(i,l). Requires tmax >= 3; NaN if the variance is zero.

Type:

np.ndarray (M, R)

m

E[Q_i] at population N, the total queue length.

Type:

np.ndarray (M,)

Var

Var[Q_i] at population N.

Type:

np.ndarray (M,)

p

p[i, j] = P[Q_i = j] at population N, for j = 0..b_i-1. These are the only marginal probabilities the b-server recursion needs, so the matrix is RAGGED: row i is meaningful only up to column b_i and is zero-padded out to max(b). A padded entry is not P[Q_i = j]; it is simply not computed. Read row i as p[i, :b[i]].

Type:

np.ndarray (M, max(b))

Wresid

The residence time w_i(l) of the MVA recursion. The identity W[i, l] = Wresid[i, l] / V[i, l] is an independent check of the t = 1 case of (4.5).

Type:

np.ndarray (M, R)

pfqn_sens_linearizer(L, N, Z=None, tol=None, maxiter=200)[source]

Approximate moments E[Q_i], Var[Q_i], Cov[Q_i,Q_j], E[Q_i^2] and E[Q_i^3] of the per-station total queue lengths of a closed product-form queueing network, by the LINEARIZER-2 / LINEARIZER-3 algorithms of the reference (Section 5).

Motivation. The exact moment analysis of pfqn_sens_mom() evaluates the MVA recursion on the whole population lattice, so it costs O(prod(N+1)) and is unusable once the populations are large. The Linearizer replaces that lattice by a fixed point over a handful of populations, and the reference observes that the same trick applies to the derivatives: differentiate the Linearizer equations, append the differentiated equations to the originals, and iterate all of them together. This routine does that, carrying both the first and the second derivative, so it returns everything (3.2) needs, including the third moment. Carrying only the first derivative is the reference’s LINEARIZER-2; carrying the second as well is its LINEARIZER-3.

The approximation. CORE (equations (5.1)-(5.2)) estimates the queue lengths at population n - 1_l from those at n by:

v_i(l)          = m_i^(n)(l) / n(l)
m_i^(n-1_l')(l) = (n - 1_l')_l * ( v_i(l) + delta_i(l',l) )

and substitutes them into the exact MVA equations. Setting the delta terms to zero gives Bard-Schweitzer; Linearizer instead estimates them from (5.3), delta_i^(N)(l',l) = v_i^(N-1_l')(l) - v_i^(N)(l), by running CORE at each of the N - 1_l populations, and holds them fixed across populations (the heuristic (5.4)). Differentiating (5.1)-(5.3) gives (5.5)-(5.8), which are carried alongside.

Accuracy. The reference reports, over 51 networks including 34 stress cases, relative errors below 2.1% on E[Q], 4.1% on E[Q^2] and 6.2% on E[Q^3]. The tests measure the error against the exact pfqn_sens_mom() on models small enough for both, and assert bands of that order rather than machine precision: this routine is an approximation and is expected to disagree with the exact answer.

Parameters:
  • L ((M, R) array) – Service demand matrix, L[i, r] = visits_ir / rate_ir.

  • N ((R,) array) – Population per class. Must be finite (closed populations only).

  • Z ((R,) array, optional) – Think time per class (default zeros).

  • tol (float, optional) – Convergence tolerance of the CORE fixed point on the mean queue lengths. Default: the test of the reference, 1/(4000+16*sum(n)), which is also applied to the variances at 1e-3.

  • maxiter (int, optional) – Maximum CORE iterations (default 200).

Return type:

PfqnSensLinearizer

Notes

Single-server stations plus an optional delay Z, matching pfqn_linearizer().

The exact counterpart is pfqn_sens_mom(); the per-class exact second moments are in pfqn_sens_mva().

class PfqnSensLinearizer(X, Q, U, W, m, dm, d2m, Var, Cov, M2, M3, Skew, CovAsym, iter)[source]

Bases: object

Result container for pfqn_sens_linearizer().

X, Q, U, W

Approximate base measures. X is (1 x R); Q, U and W are (M x R).

Type:

np.ndarray

m

Approximate E[Q_i], the total queue length at station i.

Type:

np.ndarray (M,)

dm

dm[i, h] = x_h dm_i/dx_h, the scaled first derivative.

Type:

np.ndarray (M, M)

d2m

d2m[i] = x_i^2 d^2m_i/dx_i^2.

Type:

np.ndarray (M,)

Var, Cov, M2, M3, Skew

The moments of (3.2), formed exactly as in pfqn_sens_mom() but from the approximate derivatives. Var, M2, M3 and Skew are (M,); Cov is (M x M).

Type:

np.ndarray

CovAsym

Raw asymmetry of Cov before symmetrization. Unlike the exact routines, this is NOT expected to sit at roundoff: the Linearizer fixed point does not enforce the symmetry that the product form guarantees, so this is a useful measure of the approximation error.

Type:

float

iter

Total CORE iterations performed.

Type:

int

pfqn_mvald(L, N, Z, mu, stabilize=True)[source]

Exact MVA for load-dependent closed queueing networks.

This algorithm extends standard MVA to handle stations where the service rate depends on the number of jobs present.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R) - rows are stations, columns are classes.

  • N (numpy.ndarray) – Population vector (R,).

  • Z (numpy.ndarray) – Think time vector (R,).

  • mu (numpy.ndarray) – Load-dependent rate matrix (M x Ntot) where mu[i,k] is the service rate at station i when k jobs are present.

  • stabilize (bool) – Force non-negative probabilities (default: True).

Returns:

XN: Class throughputs (1 x R). QN: Mean queue lengths (M x R). UN: Utilizations (M,), per STATION, i.e. 1-P_j(0). Matches MATLAB

pfqn_mvald, which likewise reports utilization per station and not per class.

CN: Cycle times (1 x R). lGN: Log normalizing constant evolution. isNumStable: True if numerically stable. pi: Marginal queue-length probabilities (M x Ntot+1).

Return type:

Tuple of (XN, QN, UN, CN, lGN, isNumStable, pi)

pfqn_mvams(lambda_arr, L, N, Z, mi=None, S=None)[source]

General-purpose MVA for mixed networks with multiserver nodes.

This function handles networks with open/closed classes and multi-server stations, routing to the appropriate specialized algorithm.

Parameters:
  • lambda_arr (numpy.ndarray) – Arrival rate vector (R,). Use 0 for closed classes.

  • L (numpy.ndarray) – Service demand matrix (M x R).

  • N (numpy.ndarray) – Population vector (R,). Use np.inf for open classes.

  • Z (numpy.ndarray) – Think time vector (R,).

  • mi (numpy.ndarray | None) – Queue replication factors (M,) (default: ones).

  • S (numpy.ndarray | None) – Number of servers per station (M,) (default: ones).

Returns:

XN: Class throughputs (1 x R). QN: Mean queue lengths (M x R). UN: Utilizations. Per STATION-CLASS (M x R) on every branch except

the closed multiserver one, which delegates to pfqn_mvald and so reports per STATION (M,). This shape inconsistency is inherited from MATLAB pfqn_mvams, which behaves identically; the only caller (api/solvers/mva/handler.py) discards UN and recomputes utilization analytically, as solver_mva.m does.

CN: Residence times per STATION-CLASS (M x R), as in MATLAB

pfqn_mvams and pfqn_mva. Note this is NOT what pfqn_mva returns as its own CN in Python (that is the (1 x R) cycle time); the residence time is pfqn_mva’s RN.

lG: Log normalizing constant.

Return type:

Tuple of (XN, QN, UN, CN, lG)

References

Original MATLAB: matlab/src/api/pfqn/pfqn_mvams.m

pfqn_mvamx(lambda_arr, L, N, Z, mi=None)[source]

Exact MVA for mixed open/closed single-server networks.

Handles networks with both open classes (infinite population, external arrivals) and closed classes (fixed population, no external arrivals).

Parameters:
  • lambda_arr (numpy.ndarray) – Arrival rate vector (R,). Use 0 for closed classes.

  • L (numpy.ndarray) – Service demand matrix (M x R).

  • N (numpy.ndarray) – Population vector (R,). Use np.inf for open classes.

  • Z (numpy.ndarray) – Think time vector (R,).

  • mi (numpy.ndarray | None) – Queue replication factors (M,) (default: ones).

Returns:

XN: Class throughputs (1 x R). QN: Mean queue lengths (M x R). UN: Utilizations (M x R). CN: Cycle times (M x R). lGN: Log normalizing constant.

Return type:

Tuple of (XN, QN, UN, CN, lGN)

pfqn_xzabalow(L, N, Z)[source]

Lower ABA (asymptotic bound analysis) bound on throughput.

Returns N / (Z + sum(L)*N), the ABA lower throughput bound for single-class closed queueing networks. This is NOT the classical Zahorjan-Balanced (balanced job bounds) lower bound; that one is pfqn_xzgsblow, which is tighter.

Parameters:
Returns:

Lower bound on throughput.

Return type:

float

pfqn_xzabaup(L, N, Z)[source]

Upper asymptotic bound on throughput (Zahorjan-Balanced).

Provides a simple upper bound on system throughput for single-class closed queueing networks based on bottleneck analysis.

Parameters:
Returns:

Upper bound on throughput.

Return type:

float

pfqn_qzgblow(L, N, Z, i)[source]

Lower asymptotic bound on queue length (Zahorjan-Gittelsohn-Bryant).

Parameters:
  • L (numpy.ndarray) – Service demand vector (M,).

  • N (int | float) – Population (scalar).

  • Z (float) – Think time.

  • i (int) – Station index (0-based).

Returns:

Lower bound on mean queue length at station i.

Return type:

float

pfqn_qzgbup(L, N, Z, i)[source]

Upper asymptotic bound on queue length (Zahorjan-Gittelsohn-Bryant).

Parameters:
  • L (numpy.ndarray) – Service demand vector (M,).

  • N (int | float) – Population (scalar).

  • Z (float) – Think time.

  • i (int) – Station index (0-based).

Returns:

Upper bound on mean queue length at station i.

Return type:

float

pfqn_xzgsblow(L, N, Z)[source]

Lower asymptotic bound on throughput (Zahorjan-Gittelsohn-Schweitzer-Bryant).

Provides a tighter lower bound than pfqn_xzabalow by accounting for queue length bounds.

Parameters:
Returns:

Lower bound on throughput.

Return type:

float

pfqn_xzgsbup(L, N, Z)[source]

Upper asymptotic bound on throughput (Zahorjan-Gittelsohn-Schweitzer-Bryant).

Provides a tighter upper bound than pfqn_xzabaup by accounting for queue length bounds.

Parameters:
Returns:

Upper bound on throughput.

Return type:

float

pfqn_mwrbb(V, S, N, Z=None, sched=None, prio=None)[source]

Majumdar-Woodside robust box bounds on throughput for closed multiclass queueing networks with mixed scheduling disciplines.

Computes distribution-insensitive (NBUE) upper and lower bounds on the per-class system throughput of a closed multiclass queueing network, per S. Majumdar and C.M. Woodside, “Robust bounds and throughput guarantees for closed multiclass queueing networks”, Performance Evaluation 32 (1998) 101-136. The upper bound intersects the no-contention bound (eq. 2) with the utilization-based bound (eq. 3) and is discipline-independent. The lower bound is the multiclass throughput guarantee of Theorem 2 (eq. 15): X_c >= N_c / (Z_c + sum_k V_kc (S_kc + d_kc+)), where d_kc+ depends on the discipline at station k – FIFO (Theorem 1 / Lemma 1), processor sharing (Lemma 2), preemptive priority (Lemma 3), non-preemptive priority (Lemmas 4-5). The coupled inequalities are resolved by the interval- narrowing fixed point reproducing the BNR-Prolog robust box bounds; for a single FIFO class it reduces to the Muntz-Wong bounds. Only queueing stations are passed; Z aggregates the pure-delay stations.

Parameters:
  • V (numpy.ndarray) – (K, C) mean visits of class c at queueing station k.

  • S (numpy.ndarray) – (K, C) mean service demand per visit of class c at station k.

  • N (numpy.ndarray) – (C,) population of class c.

  • Z (numpy.ndarray) – (C,) think time of class c (default zeros).

  • sched (numpy.ndarray) – (K,) discipline code per station (0=FIFO, 1=PS, 2=non-preemptive priority, 3=preemptive priority, 4=ABA full-contention discipline-independent); default all FIFO.

  • prio (numpy.ndarray) – (C,) class priority, lower value = higher priority; default equal.

Returns:

(C,) lower bound on class throughput (Theorem 2). Xup: (C,) upper bound on class throughput (eqs. 2-3). Wlo: (K, C) per-visit residence time consistent with the lower bound.

Return type:

Xlo

pfqn_pbh(L, N, Z=0.0, level=1)[source]

Performance Bound Hierarchy (Eager-Sevcik 1983), single-class.

Returns (Xlo, Xhi, Qlo, Qhi). Level-level throughput/queue bounds; level 1 (Z=0) equals the BJB optimistic bound, and the bracket tightens to exact MVA as level -> N.

pfqn_pbk(L, N, Z=0.0, k=1)[source]

Iterative PB(k) proportional bounds (Eager-Sevcik / CMS08). Backed by the PBH recursion at level k. Returns (Xlo, Xhi).

pfqn_bjbk(L, N, Z=0.0, k=1)[source]

Iterative BJB(k) balanced job bounds (CMS08). BJB(1) recovers the noniterative balanced job bound. Returns (Xlo, Xhi).

pfqn_cbh(L, N, Z=0.0, level=2)[source]

Convolutional Bound Hierarchy (Dowdy et al. 1984), single-class.

level exactly-convolved servers (1..M); the bracket tightens monotonically and equals exact at level M. Returns (Xlo, Xhi).

pfqn_mcub(L, N, Z=None)[source]

Multiclass Composite Upper Bound (Kerola 1986). L is M x R.

Returns (Xub, Xlb): Xub the per-class composite UPPER bound (eqs 13-16), Xlb the per-class multiclass Balanced Job Bounds LOWER bound (eq 10) that seeds it. Both are 1 x R arrays.

pfqn_ssd(L, N, Z=0.0, nservers=None)[source]

Server-Station Disaggregation bounds (Suri-Dallery 1986, Thm 5), single-class multiserver. Returns (Xlo, Xhi).

pfqn_sib(L, N, Z=0.0, level=3)[source]

Successively Improving Bounds (Srinivasan 1985), single-class, Z=0 only.

Returns (Xlo, Xhi, Wlo, Whi). Raises ValueError for Z>0 (delay needs the Section-3.2 demand substitution, not yet implemented).

pfqn_ldbcmp(L, N, Z=0.0, c=None, tol=1e-10)[source]

Anselmi-Cremonesi (2008) lower throughput bound for closed single-class BCMP networks with load-dependent stations. Returns (Xlo, Rhi, Qhat).

c[i]=0 marks a fixed-rate (LI) station; c[i]>0 a Heffes LD station with open queue (c[i]+1)*rho/(1-rho). Bottleneck assumed fixed-rate. NaN if N < Qhat.

pfqn_marie(L, N, Z=None, scv=None, tol=1e-8, maxiter=1000, nservers=None)[source]

Marie’s method (single-class). L is M x 1 demands, N scalar population, Z scalar think time, scv per-station SCV (M,). Returns (X, Q, U, C, it, mu): X scalar chain throughput, Q/U/C per-station (M,), it iterations, mu the converged LD multiplier matrix (M x N).

Multiclass (L with >1 column) raises NotImplementedError.

pfqn_le(L, N, Z=None)[source]

Logistic Expansion (LE) asymptotic approximation for normalizing constant.

Provides an asymptotic estimate of the normalizing constant for closed product-form queueing networks. Useful for large populations where exact methods become computationally expensive.

Parameters:
Returns:

Gn: Estimated normalizing constant. lGn: Logarithm of normalizing constant.

Return type:

Tuple of (Gn, lGn)

Reference:

G. Casale. “Accelerating performance inference over closed systems by asymptotic methods.” ACM SIGMETRICS 2017.

pfqn_cub(L, N, Z=None, order=None, atol=1e-8)[source]

Cubature method for normalizing constant using Grundmann-Moeller rules.

Uses numerical integration over simplices to compute the normalizing constant exactly (for sufficient order) or approximately.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R).

  • N (numpy.ndarray) – Population vector (R,).

  • Z (numpy.ndarray | None) – Think time vector (R,). Optional.

  • order (int | None) – Degree of cubature rule (default: ceil((sum(N)-1)/2)).

  • atol (float) – Absolute tolerance (default: 1e-8).

Returns:

Gn: Estimated normalizing constant. lGn: Logarithm of normalizing constant.

Return type:

Tuple of (Gn, lGn)

Reference:

G. Casale. “Accelerating performance inference over closed systems by asymptotic methods.” ACM SIGMETRICS 2017.

pfqn_mci(D, N, Z=None, I=100000, variant='imci')[source]

Monte Carlo Integration (MCI) for normalizing constant estimation.

Provides a Monte Carlo estimate of the normalizing constant for closed product-form queueing networks.

Parameters:
  • D (numpy.ndarray) – Service demand matrix (M x R).

  • N (numpy.ndarray) – Population vector (R,).

  • Z (numpy.ndarray | None) – Think time vector (R,). Optional, defaults to zeros.

  • I (int) – Number of samples (default: 100000).

  • variant (str) – MCI variant - ‘mci’, ‘imci’ (improved), or ‘rm’ (repairman). Default: ‘imci’.

Returns:

G: Estimated normalizing constant. lG: Logarithm of normalizing constant. lZ: Individual random sample log values.

Return type:

Tuple of (G, lG, lZ)

Reference:

Implementation based on MonteQueue methodology.

pfqn_grnmol(L, N)[source]

Normalizing constant using Grundmann-Moeller quadrature.

Computes the normalizing constant for closed product-form queueing networks using Grundmann-Moeller cubature rules on simplices.

This is an exact method that uses polynomial quadrature to compute the normalizing constant integral representation.

Parameters:
Returns:

G: Normalizing constant. lG: Logarithm of normalizing constant.

Return type:

Tuple of (G, lG)

Reference:

Grundmann, A. and Moller, H.M. “Invariant Integration Formulas for the N-Simplex by Combinatorial Methods”, SIAM J Numer. Anal. 15 (1978), pp. 282-290.

pfqn_le_fpi(L, N)[source]

Fixed-point iteration to find mode location (no think time).

Public wrapper for the internal _pfqn_le_fpi function.

Parameters:
Returns:

Mode location vector u (M,).

Return type:

numpy.ndarray

pfqn_le_fpiZ(L, N, Z)[source]

Fixed-point iteration to find mode location (with think time).

Public wrapper for the internal _pfqn_le_fpiZ function.

Parameters:
Returns:

u: Mode location vector (M,). v: Scale factor.

Return type:

Tuple of (u, v)

pfqn_le_hessian(L, N, u)[source]

Compute Hessian matrix (no think time case).

Public wrapper for the internal _pfqn_le_hessian function.

Parameters:
Returns:

Hessian matrix (M-1 x M-1).

Return type:

numpy.ndarray

pfqn_le_hessianZ(L, N, Z, u, v)[source]

Compute Hessian matrix (with think time case).

Public wrapper for the internal _pfqn_le_hessianZ function.

Parameters:
Returns:

Hessian matrix (M x M).

Return type:

numpy.ndarray

pfqn_ncld(L, N, Z, mu, options=None)[source]

Main method to compute normalizing constant of a load-dependent model.

Provides the main entry point for computing normalizing constants in load-dependent queueing networks with automatic method selection and preprocessing.

Parameters:
  • L (numpy.ndarray) – Service demands at all stations (M x R)

  • N (numpy.ndarray) – Number of jobs for each class (1 x R)

  • Z (numpy.ndarray) – Think times for each class (1 x R)

  • mu (numpy.ndarray) – Load-dependent scalings (M x Ntot)

  • options (Dict[str, Any] | None) – Solver options with keys: - method: ‘default’, ‘exact’, ‘rd’, ‘comomld’, etc. - tol: Numerical tolerance

Returns:

PfqnNcResult with G (normalizing constant), lG (log), and method used

Return type:

PfqnNcResult

pfqn_ld_is(L, N, Z=None, mu=None, options=None)[source]

Importance-sampling (IS) estimate of the normalizing constant of a closed LOAD-DEPENDENT product-form queueing network. Load-dependent counterpart of pfqn_pas_is / pfqn_oi_is: the same sample-an-ordering estimator, with the order-independent rank rate replaced by the load-dependent capacity.

Identity. Every product-form station’s balance function is the sum, over the orderings q of a given per-class count vector n, of an ordered product of a per-position factor:

F_i(n) = |n|!/prod_r(n_r!) * prod_r L(i,r)^{n_r} / prod_{k=1}^{|n|} mu_i(k)
       = sum_{q: |q|=n} prod_{p=1}^{|n|} L(i,q_p) / mu_i(p)

since the multiset has |n|!/prod_r(n_r!) orderings, each contributing the same ordered product. The delay (infinite-server) node is the special case mu_Z(k)=k, giving F_Z(n)=prod_r Z_r^{n_r}/n_r!; a single-server queue is mu_i(k)=1; a c-server queue is mu_i(k)=min(k,c).

Consequently, with ell = sum(N) and a “cut vector” splitting an ordering c of all ell jobs into S contiguous segments (one per station):

G(N) = sum_{c} sum_{cuts} prod_{m=1}^{S} w_m(seg_m),
w_m(q) = prod_{p=1}^{|q|} L(m,q_p) / mu_m(p)

because summing over the orderings of each segment independently reproduces prod_m F_m(n_m), and each count split is realized exactly once.

Estimator. An ordering c is drawn by placing, at each step, a uniformly random present class; p(c) is the product of the reciprocal branching factors. For the sampled c the inner sum over ALL cut vectors is computed exactly by the dynamic program A_0(0)=1, A_m(k) = sum_{j<=k} A_{m-1}(j) * w_m(c_{j+1..k}), so S(c)=A_S(ell) in O(S*ell^2) time (no cut enumeration). Then G = E_{C~p}[S(C)/p(C)] is unbiased, estimated by the sample mean.

Parameters:
  • L ((M, R) array) – Per-class service demands at the M queueing stations.

  • N ((R,) array) – Closed population vector, finite.

  • Z ((R,) array, optional) – Aggregated think time (delay) demand; None or zeros if none.

  • mu ((M, ell) array or sequence of callables, optional) – Load-dependent capacities; mu[i][k-1] is the capacity of station i holding k jobs. None for the load-independent case mu(i,k)=1 (see pfqn_is()).

  • options (dict or options object, optional) – Fields samples (default 1e4) and seed (optional).

Returns:

  • PfqnNcResult with ``G` the IS estimate` of the normalizing constant and

  • lG = log(G).

Return type:

PfqnNcResult

Examples

>>> L = np.array([[0.5, 0.3], [0.2, 0.4]]); N = np.array([3, 2]); Z = np.array([1.0, 1.0])
>>> mu = np.array([[1, 2, 2, 2, 2], [1, 1, 1, 1, 1]], dtype=float)
>>> res = pfqn_ld_is(L, N, Z, mu, {'samples': 100000, 'seed': 7})
pfqn_ncldmx(lam, D, N, Z=None, mu=None, S=None, options=None)[source]

Normalizing constant for mixed open/closed networks with limited load dependence.

Parameters:
  • lam (numpy.ndarray) – Arrival rate vector (R,) - 0 on closed classes

  • D (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,) - inf for open classes

  • Z (numpy.ndarray | None) – Think time vector (R,), optional

  • mu (numpy.ndarray | None) – Load-dependent rate matrix (M x >= sum(N_closed)), optional

  • S (numpy.ndarray | None) – Number of servers per station (M,), kept for signature parity

  • options (Dict[str, Any] | None) – Solver options forwarded to pfqn_ncld

Returns:

PfqnNcldmxResult with the closed-conditional constant (G, lG), the open-class normalizing prefactor lGopen and the method used for the closed-conditional solve.

Return type:

PfqnNcldmxResult

class PfqnNcldmxResult(G, lG, lGopen, method='default')[source]

Bases: object

Result of a mixed limited load-dependent normalizing constant computation.

method: str = 'default'
G: float
lG: float
lGopen: float
pfqn_gld(L, N, mu, options=None)[source]

Compute normalizing constant of a load-dependent closed queueing network.

Uses the generalized convolution algorithm for computing normalizing constants in load-dependent closed queueing networks.

Parameters:
Returns:

PfqnNcResult with G (normalizing constant) and lG (log)

Return type:

PfqnNcResult

pfqn_gldsingle(L, N, mu, options=None)[source]

Compute normalizing constant for single-class load-dependent model.

Auxiliary function used by pfqn_gld to compute the normalizing constant in a single-class load-dependent model using dynamic programming.

Parameters:
  • L (numpy.ndarray) – Service demands at all stations (M x 1)

  • N (numpy.ndarray) – Number of jobs (scalar or 1x1 array)

  • mu (numpy.ndarray) – Load-dependent scaling factors (M x Ntot)

  • options (Dict[str, Any] | None) – Solver options (unused, for API compatibility)

Returns:

PfqnNcResult with G (normalizing constant) and lG (log)

Raises:

RuntimeError – If multiclass model is detected

Return type:

PfqnNcResult

pfqn_mushift(mu, k)[source]

Shift a load-dependent scaling vector by one position.

Used in recursive normalizing constant computations.

Parameters:
  • mu (numpy.ndarray) – Load-dependent scalings matrix (M x N)

  • k (int) – Row index to shift

Returns:

Shifted mu matrix (M x N-1)

Return type:

numpy.ndarray

pfqn_comomrm_ld(L, N, Z, mu, options=None)[source]

Run the COMOM normalizing constant method on a load-dependent repairman model.

Implements the Class-Oriented Method of Moments (COMOM) for computing normalizing constants in load-dependent repairman queueing models.

Parameters:
Returns:

PfqnComomrmLdResult with G, lG, and marginal probabilities

Return type:

PfqnComomrmLdResult

pfqn_fnc(alpha, c=None)[source]

Compute scaling factor of a load-dependent functional server.

Used to calculate the mean queue length in load-dependent systems by computing functional scaling factors from load-dependent service rate parameters.

Parameters:
  • alpha (numpy.ndarray) – Load-dependent scalings (M x N)

  • c (numpy.ndarray | None) – Scaling constants (1 x M), optional. If None, auto-selected.

Returns:

PfqnFncResult with mu (functional server scalings) and c (scaling constants)

Return type:

PfqnFncResult

pfqn_oi_nc(Z, N, mu=None, options=None)[source]

Normalizing constant of a closed OI + single-delay product-form network.

The OI stations are analyzed by the balanced-fairness recursion of Bonald and Proutiere (2003) combined with the multichain convolution over stations. The exact G(N) is obtained by recursive peeling: peel the last OI station (empty), then per class r with N_r>0 place one class-r job at that station and recurse on N - e_r with the station rate function shifted by e_r.

Parameters:
  • Z ((R,) think-time demand vector of the aggregated delay node.)

  • N ((R,) closed population vector, finite.)

  • mu (list of callables, one per OI station. Each ``mu[m](n)` returns the`) – total service rate of station m given the per-class occupancy (count) vector n. May be empty/None to model a pure delay network.

  • options (accepted for signature parity; unused.)

Returns:

(G, lG)

Return type:

normalizing constant and its natural log.

pfqn_oi_fnc(Phi, N=None, f=None, options=None)[source]

OI generalization of the load-dependent functional server.

Builds an auxiliary OI station whose balance function Psi satisfies the convolution identity (Psi * Phi)(n) = (1 + f(n)) Phi(n), then inverts Psi to the FNC rate mu_f(n) = (sum_{r: n_r>0} Psi(n-e_r)) / Psi(n).

Parameters:
  • Phi (balance function of the existing OI station over the lattice, an) – R-dimensional array of shape (N_1+1, …, N_R+1), or a flat column-major vector.

  • N ((R,) closed population vector. Optional when Phi is a full) – R-dimensional array (then N = shape(Phi) - 1).

  • f (target queue-dependent function f(n), f(0)=0 (default f = sum(n)).)

  • options (accepted for signature parity; unused.)

Returns:

(muf, Psi, mu) – balance array (lattice shape), and tabulated FNC rate array.

Return type:

callable rate handle (Inf outside the lattice), FNC

pfqn_oi_insvc(oirate, N, options=None)[source]

Conditional mean number of in-service jobs per class at an OI station.

This is the quantity underlying the LINE utilization convention at order-independent stations, U_r = E[sir_r] / c with c the number of servers and sir_r the number of class-r jobs receiving a strictly positive service rate.

In an OI station the state is the ordered list c = (c_1,...,c_n) of job classes (position 1 = head) and the job in position p is served at the rank rate increment Delta_p(c) = mu(c_1..c_p) - mu(c_1..c_{p-1}), so the total rate telescopes to mu(c). Position p is in service when Delta_p(c) > 0, and sir_r(c) = #{p : c_p = r, Delta_p(c) > 0}. Note that sir_r counts JOBS, not servers: a single job served concurrently by several compatible servers counts once. This matches the definition used by the exact CTMC solver (State.to_marginal, PAS branch) and by LDES.

Because mu is permutation-invariant, the unnormalized weight of an ordering c of the multiset n factorizes over its prefixes as w(c) = prod_p 1/mu(n(c_1..c_p)), and Phi(n) = sum_c w(c) obeys the balanced-fairness recursion (condition on the tail element):

Phi(0) = 1,   Phi(n) = (1/mu(n)) sum_{r: n_r>0} Phi(n - e_r)

Conditioning the same way and using sir_r(c) = sir_r(c_1..c_{|n|-1}) + [c_{|n|} = r] * 1{mu(n) > mu(n - e_r)} gives the companion recursion for Xi_r(n) = sum_c w(c) sir_r(c):

Xi_r(0) = 0
Xi_r(n) = (1/mu(n)) [ sum_{s: n_s>0} Xi_r(n - e_s)
                      + 1{n_r > 0} 1{mu(n) > mu(n - e_r)} Phi(n - e_r) ]

Given n every ordering carries the same class-weight factor, so the conditional law of the ordering is w(c)/Phi(n) and E[sir_r | n] = Xi_r(n)/Phi(n) =: g_r(n), a function of the count vector alone. The station mean then follows from the count marginal pM as E[sir_r] = sum_n pM(n) g_r(n), or in normalizing-constant form from the functional-server identity of pfqn_oi_fnc() applied to f(n) = g_r(n) (note g_r(0) = 0, as required).

Parameters:
  • oirate (function ``mu(n)` returning the OI total service rate for the`) – per-class count vector n (length R). mu(0) is taken as 0.

  • N ((R,) closed population vector, finite.)

  • options (accepted for signature parity, currently unused.)

Returns:

  • g ((prod(N+1), R) table, column-major over the lattice 0 <= n <= N, with) – g[1 + sum(n * stride), r] = E[sir_r | n].

  • Xi ((prod(N+1), R) table with the sir-weighted balance ``Xi_r(n)`.`)

  • Phi ((prod(N+1),) table with the OI balance function ``Phi(n)`.`)

Return type:

Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]

pfqn_pas_is(N, mu, H=None, options=None)[source]

Importance-sampling estimate of G_C and mean queue lengths of a closed two-station P&S tandem with swap graph H.

G_C = sum_{c in D} sum_{k=0}^{ell} Phi_1(c[:k]) Phi_2(reverse(c[k:])), where D is the set of orderings non-decreasing w.r.t. H and Phi_m(q) = prod_p 1/mu_m(supp(q[:p])). Orderings are drawn from D by placing, at each step, a uniformly random placement-order-minimal present class (auto-normalized IS, notebook generator IS_3); E[xi] = G_C[xi]/G_C[1] reuses the same samples. Taking xi = class-r count in the prefix gives the station-1 mean queue length of class r.

Parameters:
  • N ((R,) closed population vector (macrostate), finite.)

  • mu (list of exactly two callables. mu[m](n) is the total OI rank rate of) – station m given the per-class occupancy (count) vector n (depends only on supp(n)); this is the count-based svcRateFun of an OI/PAS node.

  • H ((R, R) swap-graph adjacency (H[b, a] != 0 forbids a before b). Empty ->) – pure OI (all orderings feasible).

  • options (dict or options object; fields ``samples` (default 1e4),`) – seed (optional), verbose (default False).

Returns:

(G, lG, Q) – station-1 mean queue lengths and Q[1] = N - Q[0].

Return type:

G is the IS estimate of G_C, lG = log(G), Q is (2, R) with the

pas_placement(H)[source]

Placement-order logic of a P&S / OI network with swap graph H.

An ordering c is feasible iff it is non-decreasing w.r.t. H, i.e. class a never appears before class b whenever H[b, a] != 0 (Comte and Dorsman, 2021); equivalently H[b, a] != 0 means b must precede a. The transitive closure P[i, j] = 1 iff i must precede j makes the full order explicit.

Parameters:

H ((R, R) swap-graph adjacency. Empty/all-zero -> no constraint.)

Returns:

(P, placeable) – placeable(x) returns the array of class indices drawable next given the remaining per-class count vector x (present classes with no remaining predecessor still to be placed).

Return type:

P is the (R, R) precedence closure (or None if H is empty);

pas_swap2order(swap, listRate, N0=None)[source]

Global placement-order DAG H of a closed two-station P&S tandem 1->2->1.

With a non-empty swap graph the ordered chain is reducible; the recurrent communicating class is the set of splits of the orderings that are the linear extensions of a single placement partial order (Comte and Dorsman, 2021). pfqn_pas_is samples those orderings from H, so it needs this GLOBAL order. The order is class-level (multiplicity-independent): enumerate the reachable class from the all-in-queue-1 single-job-per-class state; each reachable state (l1; l2) exposes the full ordering c = l1 + reverse(l2); then H[i, j] = 1 iff i precedes j in every such c (forced precedence).

Parameters:
  • swap ((R, R) swap graph, or list [G1, G2] of the two per-queue graphs) – (G[a, b] != 0 means class a chases class b). Empty/all-zero -> H = 0.

  • listRate (list of two callables; listRate[m](c) is the total service rate) – of queue m on the ordered prefix c (0-based). Prunes zero-rate (non- head) completions.

  • N0 ((R,) minimal probing population; defaults to ones(R).)

Returns:

H

Return type:

(R, R) global placement-order DAG; H[i, j] = 1 iff i must precede j.

pfqn_mvaoi(Z, N, mu, Dli=None, options=None)[source]

Mean-value analysis of a closed product-form OI network.

Mean-value counterpart of pfqn_oi_nc() and the marginal form pfqn_mvaoi_marg(): for a closed product-form network of an aggregated infinite-server (delay) node, any number of load-independent (LI) single-server product-form queues, and any number of order-independent (OI) stations, it returns the same exact per-class throughput and queue-lengths WITHOUT computing any normalizing constant or joint marginal, using only mean quantities. It is the composition-dependent generalization of the Conditional MVA (CMVA) of Casale, “A Note on Stable Flow-Equivalent Aggregation in Closed Networks” (QUESTA 2009), extended to MULTIPLE OI stations by carrying one rate-shift vector s_i per OI station i (row i of the shift matrix S).

Throughout, r and s index job classes; i indexes OI stations; j indexes LI queues. State (S, Nn) is processed by increasing sum(Nn); each OI station keeps its own D^i, rho^i and Q^i recursions driven by the common throughput X^{(S)}(Nn), and the population conservation aggregates every station’s contribution:

Nn_r = X_r Z_r + sum_j Q^{(j)}_r + sum_i Q^{(i)}_r,

with the LI queue term Q^{(j)}_r = X_r D_{j,r}(1 + sum_s Q^{(j)}_s(Nn - e_r)).

Parameters:
  • Z ((R,) think-time demand vector of the aggregated delay node.)

  • N ((R,) closed population vector, finite.)

  • mu (callable or list of callables ``mu_i(n)` returning the OI total service`) – rate of station i for the per-class occupancy (count) vector n. A bare callable is accepted as the single-station shorthand.

  • Dli ((J, R) per-class demand matrix of the LI single-server queues; None or) – empty when J = 0.

  • options (accepted for signature parity; unused.)

Returns:

(X, Qoi, Qli, Qdelay, Soi) – (K, R), LI queue-lengths (J, R), delay queue-length (R,) = X * Z, and the per-class mean number of IN-SERVICE jobs at each OI station (K, R). Soi[i, r] = E[sir_r] counts the class-r jobs receiving a strictly positive rank rate (see pfqn_oi_insvc()); the utilization of OI station i is Soi[i, r] / c_i. Unlike X/Qoi/Qli, which are pure mean-value quantities, Soi is a distributional statistic and is obtained from the OI count marginal assembled from the zero-shift throughputs X^{(0)}(k) already cached by the mean-value recursion above (no normalizing constant is formed).

Return type:

per-class throughput (R,), OI queue-lengths

pfqn_mvaoi_marg(D, N, isDelay, mu)[source]

Exact marginal load-dependent MVA for OI networks.

Marginal-distribution counterpart of pfqn_mvaoi(). Carries, for each OI station, its joint count-vector marginal pM_i(n | k) and closes the per-class throughput by population conservation. Handles delay + LI product-form queues + any number of OI stations.

Parameters:
  • D ((M, R) per-class demand at every station (OI rows ignored).)

  • N ((R,) closed population vector, finite.)

  • isDelay ((M,) True for infinite-server (delay) stations.)

  • mu (length-M list; ``mu[i]` is the OI rate callable` of the count vector n, or) – None for non-OI stations.

Returns:

(XN, QN)

Return type:

per-class throughput (R,) and per-station queue-lengths (M, R).

class PfqnNcResult(G, lG, method='default')[source]

Bases: object

Result of normalizing constant computation.

method: str = 'default'
G: float
lG: float
class PfqnComomrmLdResult(G, lG, prob)[source]

Bases: object

Result of COMOM load-dependent computation.

G: float
lG: float
prob: numpy.ndarray
class PfqnFncResult(mu, c)[source]

Bases: object

Result of functional server scaling computation.

mu: numpy.ndarray
c: numpy.ndarray
pfqn_unique(L, mu=None, gamma=None, tol=1e-14)[source]

Consolidate replicated stations into unique stations with multiplicity.

Identifies stations with identical demand rows L[i,:] and (if present) identical load-dependent rates mu[i,:] or class-dependent rates gamma[i,:]. Returns reduced matrices with only unique stations plus a multiplicity vector.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • mu (numpy.ndarray | None) – Load-dependent rate matrix (M x Ntot), optional - pass None if not used

  • gamma (numpy.ndarray | None) – Class-dependent service rate matrix (M x R), optional - pass None if not used

  • tol (float) – Tolerance for floating point comparison (default 1e-14)

Returns:

PfqnUniqueResult containing reduced matrices and mapping information

Return type:

PfqnUniqueResult

pfqn_expand(QN, UN, CN, mapping)[source]

Expand per-station metrics from reduced model to original dimensions.

Expands performance metrics computed on a reduced model (with unique stations) back to the original model dimensions by replicating values according to mapping.

Parameters:
  • QN (numpy.ndarray) – Queue lengths from reduced model (M’ x R)

  • UN (numpy.ndarray) – Utilizations from reduced model (M’ x R)

  • CN (numpy.ndarray) – Cycle times from reduced model (M’ x R)

  • mapping (numpy.ndarray) – Mapping vector from pfqn_unique (length M), mapping[i] = unique station index

Returns:

Tuple of (QN_full, UN_full, CN_full) in original dimensions (M x R)

Return type:

Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]

pfqn_combine_mi(mi, mapping, M_unique)[source]

Combine user-provided multiplicity vector with detected replica multiplicity.

For each unique station j, sums the mi values of all original stations mapping to it.

Parameters:
  • mi (numpy.ndarray) – User-provided multiplicity vector (1 x M_original or M_original,)

  • mapping (numpy.ndarray) – Mapping vector from pfqn_unique (length M_original)

  • M_unique (int) – Number of unique stations

Returns:

Combined multiplicity vector (1 x M_unique)

Return type:

numpy.ndarray

class PfqnUniqueResult(L_unique, mu_unique, gamma_unique, mi, mapping)[source]

Bases: NamedTuple

Result class for pfqn_unique containing all output matrices and mapping information.

L_unique

Reduced demand matrix (M’ x R) with M’ <= M unique stations

Type:

numpy.ndarray

mu_unique

Reduced load-dependent rates (M’ x Ntot), None if mu was empty

Type:

numpy.ndarray | None

gamma_unique

Reduced class-dependent rates (M’ x R), None if gamma was empty

Type:

numpy.ndarray | None

mi

Multiplicity vector (1 x M’), mi[j] = count of stations mapping to unique station j

Type:

numpy.ndarray

mapping

Mapping vector (1 x M), mapping[i] = unique station index for original station i

Type:

numpy.ndarray

Create new instance of PfqnUniqueResult(L_unique, mu_unique, gamma_unique, mi, mapping)

L_unique: numpy.ndarray

Alias for field number 0

gamma_unique: numpy.ndarray | None

Alias for field number 2

mapping: numpy.ndarray

Alias for field number 4

mi: numpy.ndarray

Alias for field number 3

mu_unique: numpy.ndarray | None

Alias for field number 1

pfqn_lldfun(n, lldscaling=None, nservers=None)[source]

AMVA-QD load and queue-dependent scaling function.

Computes the scaling factor for load-dependent queueing stations, accounting for multi-server stations and general load-dependent service rate scaling.

Parameters:
  • n (numpy.ndarray) – Queue population vector (M,)

  • lldscaling (numpy.ndarray | None) – Load-dependent scaling matrix (M x Nmax), optional

  • nservers (numpy.ndarray | None) – Number of servers per station (M,), optional

Returns:

Scaling factor vector (M,)

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/pfqn/pfqn_lldfun.m

pfqn_mu_ms(N, m, c)[source]

Compute load-dependent rates for m identical c-server FCFS stations.

Calculates the effective service rate as a function of the number of jobs in the system for a network of m identical stations, each with c parallel servers.

Parameters:
  • N (int) – Maximum population

  • m (int) – Number of identical stations

  • c (int) – Number of servers per station

Returns:

Load-dependent service rate vector (1 x N)

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/pfqn/pfqn_mu_ms.m

pfqn_nc_sanitize(lam, L, N, Z, atol=1e-8)[source]

Sanitize and preprocess network parameters for NC solvers.

Removes empty/ill-defined classes, rescales demands for numerical stability, and reorders classes by think time.

Parameters:
Returns:

  • lambda: Sanitized arrival rates

  • L: Sanitized service demands (rescaled)

  • N: Sanitized populations

  • Z: Sanitized think times (rescaled)

  • lGremaind: Log normalization factor from removed classes

Return type:

Tuple of (lambda, L, N, Z, lGremaind) where

References

Original MATLAB: matlab/src/api/pfqn/pfqn_nc_sanitize.m

pfqn_cdfun(nvec, cdscaling=None, class_idx=0)[source]

AMVA-QD class-dependence function for queue-dependent scaling.

Returns, for every station i, the reciprocal of the class-dependent scaling

beta_{i,r}(n_i1, …, n_iR)

evaluated at the per-class population vector nvec[i, :], for class r = class_idx.

cdscaling[i] is a callable of the per-class population vector at station i. It may return either

  • a scalar, i.e. a chain-independent scaling beta_i(n) shared by every class (the common case, and the historical contract), or

  • an array of length R, i.e. the per-class scalings [beta_{i,1}(n), …, beta_{i,R}(n)], of which element class_idx is taken.

The per-class form expresses Sauer’s chain-dependent service rates mu_{r,i}(n) (Sauer 1983, “Computational Algorithms for State-Dependent Queueing Networks”, eq. (40)), so a single class-dependence mechanism covers both the chain-independent and the chain-specific cases.

An empty (None) entry means station i declares no class dependence and is left at the neutral scaling 1.

Parameters:
  • nvec (numpy.ndarray) – Population state matrix (M x R) or vector (M,)

  • cdscaling (List | None) – List of class-dependence callables, one per station

  • class_idx (int) – 0-based class index selecting beta_{i,r} (default: 0)

Returns:

Scaling factor vector (M,)

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/pfqn/pfqn_cdfun.m

factln(n)[source]

Compute log(n!) using log-gamma function.

Parameters:

n (float) – Non-negative number

Returns:

log(n!) = log(Gamma(n+1))

Return type:

float

factln_vec(arr)[source]

Compute log(n!) element-wise for an array.

Parameters:

arr (numpy.ndarray) – Array of non-negative numbers

Returns:

Array of log(n!) values

Return type:

numpy.ndarray

softmin(a, b, alpha=20.0)[source]

Compute a smooth approximation to min(a, b) using weighted average.

Matches MATLAB formula: (x*exp(-alpha*x) + y*exp(-alpha*y)) / (exp(-alpha*x) + exp(-alpha*y))

Parameters:
  • a (float) – First value

  • b (float) – Second value

  • alpha (float) – Smoothing parameter (larger = sharper approximation)

Returns:

Smooth approximation of min(a, b)

Return type:

float

oner(n, s)[source]

Return a copy of n with position s reduced by 1.

Parameters:
  • n (numpy.ndarray) – Population vector

  • s (int) – Index to decrement (0-based)

Returns:

Copy of n with n[s] -= 1

Return type:

numpy.ndarray

multichoose(r, n)[source]

Generate all combinations with repetition.

Returns all ways to choose n items from r categories with repetition, where the result is a matrix with each row being a combination.

Parameters:
  • r (int) – Number of categories

  • n (int) – Number of items to choose

Returns:

Matrix (C x r) where C = C(n+r-1, r-1) is the number of combinations

Return type:

numpy.ndarray

matchrow(matrix, row)[source]

Find the index of a row in a matrix.

Parameters:
Returns:

1-based index of the matching row, or 0 if not found

Return type:

int

pfqn_comom(L, N, Z=None, atol=1e-8)[source]

CoMoM algorithm for computing the normalizing constant.

Implements the Composite Method of Moments algorithm for computing normalizing constants in closed product-form queueing networks.

Parameters:
Returns:

Logarithm of the normalizing constant

Return type:

lG

References

Original MATLAB: matlab/src/api/pfqn/pfqn_comom.m

pfqn_comomrm(L, N, Z, m=1, atol=1e-8)[source]

CoMoM for finite repairman model.

Computes the normalizing constant for a closed network with a single queueing station and delay stations (repairman model).

Parameters:
  • L (numpy.ndarray) – Service demand matrix (1 x R) - single station

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,)

  • m (int) – Replication factor (default: 1)

  • atol (float) – Absolute tolerance

Returns:

ComomResult with lG (log normalizing constant) and lGbasis

Return type:

ComomResult

References

Original MATLAB: matlab/src/api/pfqn/pfqn_comomrm.m

pfqn_comomrm_orig(L, N, Z, m=1, atol=1e-8)[source]

Original CoMoM implementation for repairman model.

This is the original implementation of CoMoM without optimizations. Kept for reference and validation.

Parameters:
Returns:

ComomResult with lG and lGbasis

Return type:

ComomResult

References

Original MATLAB: matlab/src/api/pfqn/pfqn_comomrm_orig.m

pfqn_comomrm_ms(L, N, Z, m, c, atol=1e-8)[source]

CoMoM for multi-server repairman model.

Computes the normalizing constant for a repairman model where the queueing station has multiple servers.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (1 x R)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,)

  • m (int) – Number of identical stations

  • c (int) – Number of servers per station

  • atol (float) – Absolute tolerance

Returns:

ComomResult with lG and lGbasis

Return type:

ComomResult

References

Original MATLAB: matlab/src/api/pfqn/pfqn_comomrm_ms.m

pfqn_procomom(L, N, Z=None, atol=1e-14)[source]

ProCoMoM algorithm for computing marginal queue-length probabilities.

Computes the marginal queue-length probability distribution at each station using the Probabilistic Class-Oriented Method of Moments. Uses matrix recursion with SVD/QR decomposition for numerical stability, with automatic perturbation on rank deficiency.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R).

  • N (numpy.ndarray) – Population vector (R,).

  • Z (numpy.ndarray) – Think time vector (R,), default zeros.

  • atol (float) – Absolute numerical tolerance (default 1e-14).

Returns:

Marginal probability matrix (M x sumN+1).

Pr[k, j] = P(n_k = j) for station k, queue length j.

Q: Mean queue length vector (M,).

Return type:

Pr

References

Original MATLAB: matlab/src/api/pfqn/pfqn_procomom.m

pfqn_procomom2(L, N, Z=None, atol=1e-8)[source]

Projected CoMoM method for normalizing constant.

Uses a projection-based approach to compute the normalizing constant, which can be more efficient for certain model structures.

Parameters:
Returns:

Logarithm of the normalizing constant

Return type:

lG

References

Original MATLAB: matlab/src/api/pfqn/pfqn_procomom2.m

class ComomResult(lG, lGbasis=None)[source]

Bases: NamedTuple

Result of CoMoM normalizing constant computation.

Create new instance of ComomResult(lG, lGbasis)

lG: float

Alias for field number 0

lGbasis: numpy.ndarray | None

Alias for field number 1

pfqn_mmint2(L, N, Z, m=1)[source]

McKenna-Mitra integral form using scipy.integrate.

Computes the normalizing constant using numerical integration of the McKenna-Mitra integral representation.

Parameters:
Returns:

  • G: Normalizing constant

  • lG: Logarithm of normalizing constant

Return type:

Tuple of (G, lG)

References

Original MATLAB: matlab/src/api/pfqn/pfqn_mmint2.m

pfqn_mmint2_gausslegendre(L, N, Z, m=1)[source]

McKenna-Mitra integral with Gauss-Legendre quadrature.

Uses Gauss-Legendre quadrature for improved accuracy in computing the McKenna-Mitra integral.

Parameters:
Returns:

  • G: Normalizing constant

  • lG: Logarithm of normalizing constant

Return type:

Tuple of (G, lG)

References

Original MATLAB: matlab/src/api/pfqn/pfqn_mmint2_gausslegendre.m

pfqn_mmint2_gausslaguerre(L, N, Z, m=1)[source]

McKenna-Mitra integral with Gauss-Laguerre quadrature.

Uses Gauss-Laguerre quadrature which is naturally suited for integrals with exponential decay.

Parameters:
Returns:

  • G: Normalizing constant

  • lG: Logarithm of normalizing constant

Return type:

Tuple of (G, lG)

References

Original MATLAB: matlab/src/api/pfqn/pfqn_mmint2_gausslaguerre.m

pfqn_mmsample2(L, N, Z, m=1, n_samples=10000)[source]

Monte Carlo sampling approximation for normalizing constant.

Uses Monte Carlo sampling to approximate the McKenna-Mitra integral. Useful for very large populations where quadrature becomes expensive.

Parameters:
  • L (numpy.ndarray) – Service demand vector (R,)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,)

  • m (int) – Replication factor (default: 1)

  • n_samples (int) – Number of Monte Carlo samples (default: 10000)

Returns:

  • G: Normalizing constant (approximate)

  • lG: Logarithm of normalizing constant

Return type:

Tuple of (G, lG)

References

Original MATLAB: matlab/src/api/pfqn/pfqn_mmsample2.m

logsumexp(x)[source]

Compute log(sum(exp(x))) in a numerically stable way.

Parameters:

x (numpy.ndarray) – Array of values

Returns:

log(sum(exp(x)))

Return type:

float

pfqn_schmidt(D, N, S, sched, v=None)[source]

Schmidt’s exact MVA for networks with general scheduling disciplines.

Implements Schmidt’s exact Mean Value Analysis algorithm for product-form queueing networks with PS, FCFS, or INF scheduling disciplines, including support for multi-server stations.

Parameters:
  • D (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • S (numpy.ndarray) – Number of servers per station (M,) or (M x R)

  • sched (numpy.ndarray) – Scheduling discipline per station (M,) - SchedStrategy values

  • v (numpy.ndarray | None) – Visit ratio matrix (M x R), optional (default: ones)

Returns:

XN: System throughput (M x R) - same per station for closed networks QN: Mean queue lengths (M, R) UN: Utilization (M, R), per station-class, D*X/nservers CN: Cycle times / response times (M, R)

Return type:

Tuple of (XN, QN, UN, CN)

References

Original MATLAB: matlab/src/api/pfqn/pfqn_schmidt.m

pfqn_schmidt_ext(D, N, S, sched, v=None)[source]

Extended Schmidt MVA algorithm with queue-aware alpha corrections.

A queue-aware version of the Schmidt algorithm that precomputes alpha values for improved accuracy in networks with class-dependent FCFS scheduling.

Reference:

R. Schmidt, “An approximate MVA algorithm for exponential, class-dependent multiple server stations,” Performance Evaluation, vol. 29, no. 4, pp. 245-254, 1997.

Parameters:
  • D (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • S (numpy.ndarray) – Number of servers per station (M,) or (M x R)

  • sched (numpy.ndarray) – Scheduling discipline per station (M,) - SchedStrategy values

  • v (numpy.ndarray | None) – Visit ratio matrix (M x R), optional (default: ones)

Returns:

XN: System throughput (M x R) QN: Mean queue lengths (M, R) UN: Utilization (M, R) CN: Cycle times / response times (M, R)

Return type:

Tuple of (XN, QN, UN, CN)

class SchmidtResult(XN, QN, UN, CN)[source]

Bases: object

Result from Schmidt’s exact MVA.

XN: numpy.ndarray
QN: numpy.ndarray
UN: numpy.ndarray
CN: numpy.ndarray
pprod(N, Nmax=None)[source]

Generate population vectors for MVA recursion.

When called with one argument, initializes to zero vector. When called with two arguments, increments to next population vector. Returns -1 when iteration is complete.

Parameters:
  • N (numpy.ndarray) – Current population vector or max population

  • Nmax (numpy.ndarray | None) – Maximum population per class (if incrementing)

Returns:

Next population vector, or array of -1 if done

Return type:

numpy.ndarray

hashpop(nvec, Nc, C, prods)[source]

Hash population vector to linear index.

Parameters:
Returns:

Linear index (1-based for MATLAB compatibility)

Return type:

int

pfqn_dac(L, N, Z=None, mu=None)[source]

DAC (Distribution Analysis by Chain) method for joint queue-length distributions.

Computes the joint queue-length distribution of a closed product-form network by a chain-by-chain recursion over a related network in which every chain holds a single customer, a transformation that leaves the aggregate queue-length distribution unchanged. Given the distribution of a network with k-1 such chains, adding one customer of a chain with demands r gives

c_j = sum_{n=1..k} (n/mu_j(n)) * P_j^{k-1}(n-1) lambda_k = 1 / sum_j r_j c_j P^k(n) = lambda_k * sum_j r_j (n_j/mu_j(n_j)) * P^{k-1}(n-e_j)

where lambda_k is the throughput of the customer being added and 1/c_j is the throughput of a chain visiting center j only. The recursion conserves probability mass by construction, hence it is numerically stable.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray | None) – Think time vector (R,), optional (default: zeros). If sum(Z)>0 an extra infinite-server station is appended, so that states has M+1 columns and its last column holds the think-station population.

  • mu (numpy.ndarray | None) – Load-dependent rate matrix (M x Nt), Nt=sum(N), optional (default: ones, i.e. single-server fixed rate). Use mu[j,:]=1..Nt for infinite server and mu[j,n]=min(n+1,c) for a c-server station.

Returns:

Pjoint: Probability of the aggregate state in the corresponding row

of states, of length nchoosek(Nt+J-1, J-1)

states: Aggregate states (S x J), states[s,j] = jobs at center j XN: Throughput of chain r (R,) QN: Mean number of chain-r customers at station j (M x R) UN: Utilization of station j (M,), i.e. 1-P_j(0) CN: Cycle time of chain r, exclusive of think time (R,) pi: Marginal probabilities, pi[j,n] = P(n jobs at station j),

shape (M, Nt+1)

Return type:

Tuple of (Pjoint, states, XN, QN, UN, CN, pi)

References

E. de Souza e Silva, “Distribution Analysis of Product Form Queueing Networks”, UCLA Computer Science Department, CSD-870023, April 1987.

pfqn_recal(L, N, Z=None, m0=None)[source]

RECAL (REcursive CALculation) method for normalizing constant.

Computes the normalizing constant G(N) using the RECAL recursive method, which is efficient for networks with moderate population sizes.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray | None) – Think time vector (R,), optional (default: zeros)

  • m0 (numpy.ndarray | None) – Initial multiplicity vector (M,), optional (default: ones)

Returns:

G: Normalizing constant lG: Logarithm of normalizing constant

Return type:

Tuple of (G, lG)

References

Original MATLAB: matlab/src/api/pfqn/pfqn_recal.m Conway, A.E. and Georganas, N.D. “RECAL - A New Efficient Algorithm for the Exact Analysis of Multiple-Chain Closed Queueing Networks”, JACM, 1986.

pfqn_mvac(L, N, Z=None)[source]

MVAC (Mean Value Analysis by Chain) for closed product-form networks.

Exact mean value analysis of a closed multichain product-form queueing network composed of single-server fixed-rate (SSFR) queues and infinite-server (IS) centers. Unlike the classic MVA recursion of pfqn_mva, which recurs on the population vector and costs O(prod(N+1)), MVAC recurs on the chains: each class is reduced to single-customer chains and the removed chains are replaced by self-looping single-customer (SCSL) chains pinned at a service center, so the multiplicity vector v = (v_1,…,v_J), with v_j the number of SCSL chains at center j, indexes the recursion in place of the population vector. MVAC is thus attractive for networks with few centers and many chains, and is the mean-value counterpart of the RECAL normalizing-constant recursion of pfqn_recal. Since no normalizing constant is formed, MVAC does not suffer the floating-point underflow/overflow that complicates RECAL and convolution.

With j, i indexing centers (j = 1,…,J1 SSFR and j = J1+1,…,J IS), k, l indexing single-customer chains, a_jk the relative utilization (service demand) of chain k at center j, a_k = sum_j a_jk, K the total number of single-customer chains, and I_k = {v : sum_j v_j = K - k}, the recursion of Section II of the paper reads

lambda^k_k(v) = 1 / (a_k + sum_{j=1}^{J1} a_jk (L^{k-1}_j(v) + v_j)) (10) L^k_{jk}(v) = lambda^k_k(v) a_jk (1 + L^{k-1}_j(v) + v_j), j SSFR (9a) L^k_{jk}(v) = lambda^k_k(v) a_jk, j IS (9b) L^k_i(v) = sum_j L^k_{jk}(v) L^{k-1}_i(v + 1_j) + L^k_{ik}(v) (7) L^k_{il}(v) = sum_j L^k_{jk}(v) L^{k-1}_{il}(v + 1_j), l = 1..k-1 (6)

with L^0_j(v) = 0, where L^k_j(v) is the mean number of customers at center j (SCSL customers excluded), L^k_{jl}(v) the mean number of chain-l customers at center j, and lambda^k_k(v) the throughput of chain k, all for the network with normalizing constant G_k(v). Equation (10) is the arrival-theorem closure obtained by summing (9a)-(9b) over all centers, since chain k holds a single customer. The measures of the original network are read off at k = K and v = 0.

Part 1 of the basic step evaluates (10), (9) and (7) and yields the measures of chain K; part 2 evaluates (6) and yields those of the chains that visit at least one IS center, whose throughput then follows from Little’s law at that center. Chains visiting only SSFR centers require a re-execution of part 1 with their label interchanged with K, which is cheap because the levels below the interchanged label are unaffected and are reused. Classes with N_r > 1, and classes with identical demand columns, collapse into a single subset of identical single-customer chains: only one representative per subset is analyzed and its per-chain measures are scaled by the class population, so the cost depends on the number D of distinct chains, not K.

Parameters:
  • L (numpy.ndarray) – Service demand matrix of the SSFR queues (M x R)

  • N (numpy.ndarray) – Population vector (R,), finite and nonnegative

  • Z (numpy.ndarray | None) – Service demand matrix of the IS centers, (R,) or (Mz x R), one row per IS center, optional (default: zeros)

Returns:

XN: Per-class throughput at the reference station (R,) QN: Per-class mean queue-length at the SSFR queues (M x R) UN: Per-class utilization, XN[r] * L[i,r] (M x R) CN: Per-class residence time, QN[i,r] / XN[r] (M x R)

Return type:

Tuple of (XN, QN, UN, CN)

References

A. E. Conway, E. de Souza e Silva and S. S. Lavenberg, “Mean Value Analysis by Chain of Product Form Queueing Networks”, IEEE Trans. Computers, 38(3):432-442, 1989. Original MATLAB: matlab/src/api/pfqn/pfqn_mvac.m

pfqn_mvacld(L, N, Z=None, mu=None)[source]

MVAC for closed product-form networks with queue-length dependent centers.

Exact mean value analysis by chain of a closed multichain product-form queueing network that may contain queue-length dependent (QLD) service centers. This is the Section V extension of Conway, de Souza e Silva and Lavenberg (1989); pfqn_mvac implements Sections II-IV, which cover single-server fixed-rate (SSFR) and infinite-server (IS) centers only.

Where pfqn_mvac propagates the MEAN queue-lengths L^k_j(v) through eq. (7) and closes the recursion with the arrival-theorem identity (10), the QLD extension propagates the MARGINAL queue-length DISTRIBUTIONS P^k_j(n,v) instead. That is forced by load dependence – the rate seen by a job depends on the whole occupancy, so a mean no longer suffices – but it also SIMPLIFIES the recursion: eq. (21)-(25) read level k-1 only at the shifted vectors v + 1_i, so the basic step sweeps v in I_k alone, where pfqn_mvac must sweep the larger I_k u … u I_K. The marginals come almost for free and are returned as a first-class output.

Notation follows pfqn_mvac: j, i index centers (j = 1,…,J1 the QLD centers of L, j = J1+1,…,J the IS centers of Z), k, l index the single-customer chains, a_jk = theta_jk T_jk is the demand of chain k at center j, K = sum(N) and I_k = {v : sum_j v_j = K - k} with v_j the number of self-looping single-customer (SCSL) chains pinned at center j. P^k_j(n,v) is the probability of n customers at center j – EXCLUDING the v_j SCSL customers there – in the network with normalizing constant G_k(v). Writing tau_k(v,i) for the throughput of an SCSL chain that replaces chain k at center i:

tau_k(v,i) = T_ik^-1 sum_{n=0}^{k-1} P^{k-1}_i(n,v+1_i)
  • mu_i(n+v_i+1)/(n+v_i+1) (21)

tau_k(v,i) = T_ik^-1, i IS (22) L^k_{jk}(v) = theta_jk tau_k(v,j)^-1 / sum_m theta_mk tau_k(v,m)^-1 (23) lambda^k_k(v) = tau_k(v,j(k)) L^k_{j(k)k}(v) (24) P^k_j(n,v) = L^k_{jk}(v) P^{k-1}_j(n-1,v+1_j)

  • sum_{m != j} L^k_{mk}(v) P^{k-1}_j(n,v+1_m) (25)

with P^0_j(0,v) = 1 and P^{k-1}_j(n,.) = 0 for n < 0 or n > k-1. Eq. (21) is just “the mean rate at which an SCSL chain is served”: given n other customers the processor-sharing rate share is mu_i(n+v_i+1)/(n+v_i+1), averaged over the distribution of those others. The queueing discipline may be assumed PS with no loss of generality, since product-form measures do not depend on it.

This implementation writes (23)-(24) in the reference-station-free form

c_i(k,v) = sum_{n=0}^{k-1} P^{k-1}_i(n,v+1_i)
  • mu_i(n+v_i+1)/(n+v_i+1)

L^k_{jk}(v) = (a_jk/c_j) / sum_m (a_mk/c_m) lambda^k_k(v) = 1 / sum_m (a_mk/c_m)

which follows from theta_jk tau_k(v,j)^-1 = a_jk/c_j and theta_{j(k)k} = 1, so only the demands a_jk are needed and the visit ratios never appear separately. For an IS center c_i = 1 identically, which is exactly (22). Eq. (25) is self-normalizing, sum_n P^k_j(n,v) = sum_m L^k_{mk}(v) = 1, so no normalizing constant is formed and the recursion involves only positive quantities: unlike the classic load-dependent MVA of pfqn_mvald it cannot produce negative probabilities and needs no stabilization.

Parts 2 and 3 are unchanged from pfqn_mvac, since eq. (6) holds verbatim in the presence of QLD centers: part 2 resolves the chains that visit at least one IS center, and the chains that visit no IS center are resolved by re-executing part 1 with their label interchanged with K.

Parameters:
  • L (numpy.ndarray) – Service demand matrix of the QLD centers (M x R)

  • N (numpy.ndarray) – Population vector (R,), finite and nonnegative

  • Z (numpy.ndarray | None) – Demand matrix of the IS centers, (R,) or (Mz x R), one row per center, optional (default: zeros)

  • mu (numpy.ndarray | None) – Load-dependent rates (M x Nt) with Nt >= sum(N); mu[j,n-1] is the total service rate of center j with n jobs present. mu[j,:] = 1 is a single-server fixed-rate queue, mu[j,n-1] = min(n,c) a c-server queue, mu[j,n-1] = n an infinite server. Optional (default: ones, i.e. all centers SSFR, in which case results agree with pfqn_mvac)

Returns:

XN: Per-class throughput at the reference station (R,) QN: Per-class mean queue-length at the QLD centers (M x R) UN: Utilization of each center (M,), 1 - P_j(0). PER-STATION, not

per-class, as in pfqn_mvald and pfqn_dac: for a load-dependent center the per-class product XN[r]*L[j,r] of pfqn_mvac is NOT the utilization

CN: Per-class cycle time exclusive of think time (R,),

N[r]/XN[r]-Z[r], as in pfqn_mvald and pfqn_dac. NOT the (M x R) per-station residence time of pfqn_mvac: the whole LD family reports a cycle time here

pij: Marginal queue-length probabilities (M x (sum(N)+1)),

pij[j,n] = P(n jobs at center j)

Return type:

Tuple of (XN, QN, UN, CN, pij)

References

A. E. Conway, E. de Souza e Silva and S. S. Lavenberg, “Mean Value Analysis by Chain of Product Form Queueing Networks”, IEEE Trans. Computers, 38(3):432-442, 1989, Section V. Original MATLAB: matlab/src/api/pfqn/pfqn_mvacld.m

pfqn_mvaldmx(lam, D, N, Z, mu=None, S=None)[source]

Load-dependent MVA for mixed open/closed networks with limited load dependence.

Implements the MVALDMX algorithm for analyzing mixed queueing networks with load-dependent service rates using limited load dependence.

Parameters:
  • lam (numpy.ndarray) – Arrival rate vector (R,) - non-zero for open classes

  • D (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,) - inf for open classes

  • Z (numpy.ndarray) – Think time vector (R,)

  • mu (numpy.ndarray | None) – Load-dependent rate matrix (M x Nt), optional

  • S (numpy.ndarray | None) – Number of servers per station (M,), optional

Returns:

XN: System throughput (R,) QN: Mean queue lengths (M, R) UN: Utilization (M, R) CN: Cycle times (M, R) lGN: Logarithm of normalizing constant Pc: Marginal queue-length probabilities (M, 1+Ntot, prod(1+Nc))

Return type:

Tuple of (XN, QN, UN, CN, lGN, Pc)

References

Original MATLAB: matlab/src/api/pfqn/pfqn_mvaldmx.m

pfqn_ldmx_ec(lam, D, mu)[source]

Compute effective capacity terms for MVALDMX solver.

Calculates the effective capacity E, E’, and EC terms needed for load-dependent MVA with limited load dependence.

Parameters:
Returns:

EC: Effective capacity matrix (M x Nt) E: E-function values (M x (1+Nt)) Eprime: E-prime function values (M x (1+Nt)) Lo: Open class load vector (M,)

Return type:

Tuple of (EC, E, Eprime, Lo)

References

Original MATLAB: matlab/src/api/pfqn/pfqn_ldmx_ec.m

pfqn_mvaldms(lam, D, N, Z, S)[source]

Load-dependent MVA for multiserver mixed networks.

Wrapper for pfqn_mvaldmx that adjusts utilizations to account for multi-server stations.

Parameters:
Returns:

XN: System throughput (R,) QN: Mean queue lengths (M, R) UN: Utilization (M, R) - adjusted for multiservers CN: Cycle times (M, R) lGN: Logarithm of normalizing constant

Return type:

Tuple of (XN, QN, UN, CN, lGN)

References

Original MATLAB: matlab/src/api/pfqn/pfqn_mvaldms.m

pfqn_linearizerms(L, N, Z, nservers, type_sched=None, tol=1e-8, maxiter=1000, QN0=None)[source]

Multiserver Linearizer (Krzesinski/Conway/De Souza-Muntz).

Extends the Linearizer algorithm to handle multi-server stations in product-form queueing networks.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,)

  • nservers (numpy.ndarray) – Number of servers per station (M,)

  • type_sched (numpy.ndarray | None) – Scheduling strategy per station (M,), optional (default: PS)

  • tol (float) – Convergence tolerance (default: 1e-8)

  • maxiter (int) – Maximum iterations (default: 1000)

Returns:

Q: Mean queue lengths (M, R) U: Utilization (M, R) R: Residence times (M, R) C: Cycle times (R,) X: System throughput (R,) totiter: Total iterations performed

Return type:

Tuple of (Q, U, R, C, X, totiter)

References

Original MATLAB: matlab/src/api/pfqn/pfqn_linearizerms.m

pfqn_linearizermx(lambda_arr, L, N, Z, nservers, sched_type, tol=1e-8, maxiter=1000, method='egflin', QN0=None)[source]

Linearizer for mixed open/closed queueing networks.

This function extends the linearizer algorithm to handle networks with both open classes (with external arrivals) and closed classes (with fixed populations).

Parameters:
  • lambda_arr (numpy.ndarray) – Arrival rate vector (R,). For closed classes, should be 0 or inf.

  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,). Inf for open classes, finite for closed.

  • Z (numpy.ndarray) – Think time vector (R,) or matrix

  • nservers (numpy.ndarray) – Number of servers per station (M,)

  • sched_type (List[str]) – Scheduling strategy per station (list of strings)

  • tol (float) – Convergence tolerance

  • maxiter (int) – Maximum iterations

  • method (str) – Linearizer variant (‘lin’, ‘gflin’, ‘egflin’)

Returns:

Mean queue lengths (M x R) UN: Utilization (M x R) WN: Waiting times (M x R) TN: Throughputs (M x R) CN: Cycle times (1 x R) XN: System throughput (R,) totiter: Total iterations

Return type:

QN

References

MATLAB: matlab/src/api/pfqn/pfqn_linearizermx.m

pfqn_conwayms(L, N, Z, nservers, type_sched=None, tol=1e-8, maxiter=1000, QN0=None)[source]

Conway (1989) multiserver Linearizer approximation for FCFS queues.

Implements the algorithm from Conway (1989), “Fast Approximate Solution of Queueing Networks with Multi-Server Chain-Dependent FCFS Queues”.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (R,)

  • Z (numpy.ndarray) – Think time vector (R,)

  • nservers (numpy.ndarray) – Number of servers per station (M,)

  • type_sched (numpy.ndarray | None) – Scheduling strategy per station (M,), optional (default: FCFS)

  • tol (float) – Convergence tolerance (default: 1e-8)

  • maxiter (int) – Maximum iterations (default: 1000)

Returns:

Q: Mean queue lengths (M, R) U: Utilization (M, R) R: Residence times (M, R) C: Cycle times (R,) X: System throughput (R,) totiter: Total iterations performed

Return type:

Tuple of (Q, U, R, C, X, totiter)

References

Conway, A. E., “Fast Approximate Solution of Queueing Networks with Multi-Server Chain-Dependent FCFS Queues”, Performance Evaluation, Vol. 8, 1989, pp. 141-159.

ljd_linearize(nvec, cutoffs)[source]

Convert per-class population vector to linearized index.

Maps a multi-dimensional population vector to a single linear index for efficient lookups in tabulated scaling tables.

Index formula: idx = 1 + n1 + n2*(N1+1) + n3*(N1+1)*(N2+1) + …

Parameters:
  • nvec (numpy.ndarray) – Per-class populations [n1, n2, …, nK]

  • cutoffs (numpy.ndarray) – Per-class cutoffs [N1, N2, …, NK]

Returns:

1-based linearized index

Return type:

int

References

Original MATLAB: matlab/src/api/pfqn/ljd_linearize.m

infradius_h(x, L, N, alpha)[source]

Helper function for infinite radius computation with logistic transformation.

Used in normalizing constant computation via integration methods.

Parameters:
Returns:

Evaluated function value for integration

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/pfqn/infradius_h.m

infradius_hnorm(x, L, N, alpha)[source]

Helper function for infinite radius computation with normal CDF (probit) transformation.

Uses normcdf/normpdf transformation instead of logistic (used in infradius_h).

Parameters:
Returns:

Evaluated function value for integration

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/pfqn/infradius_hnorm.m

pfqn_kt(L, N, Z=None)[source]

Knessl-Tier asymptotic expansion for normalizing constant.

Computes the normalizing constant using Knessl-Tier’s asymptotic expansion, which is particularly accurate for large populations.

Parameters:
Returns:

G: Normalizing constant lG: Logarithm of normalizing constant X: System throughput (R,) Q: Mean queue lengths (M, R)

Return type:

Tuple of (G, lG, X, Q)

References

Original MATLAB: matlab/src/api/pfqn/pfqn_kt.m

pfqn_ab_amva(D, N, V, nservers, sched, fcfs_schmidt=False, marginal_prob_method='ab')[source]

Akyildiz-Bolch AMVA method for multi-server BCMP networks.

Parameters:
  • D (numpy.ndarray) – Service time matrix (M x K)

  • N (numpy.ndarray) – Population vector (1 x K)

  • V (numpy.ndarray) – Visit ratio matrix (M x K)

  • nservers (numpy.ndarray) – Number of servers at each station (M x 1)

  • sched (numpy.ndarray) – Scheduling strategies for each station (M x 1)

  • fcfs_schmidt (bool) – Whether to use Schmidt formula for FCFS stations

  • marginal_prob_method (str) – Method for marginal probability (‘ab’ or ‘scat’)

Returns:

AbAmvaResult containing queue lengths, utilization, residence times, cycle times, throughput, and iteration count.

Return type:

AbAmvaResult

pfqn_ab_core(K, M, population, nservers, sched_type, v, s, maxiter, D_frac, l_in, fcfs_schmidt=False, marginal_prob_method='ab')[source]

Akyildiz-Bolch core method for multi-server BCMP networks.

Public wrapper for the internal core algorithm of the Akyildiz-Bolch linearizer method.

Parameters:
  • K (int) – Number of classes

  • M (int) – Number of stations

  • population (numpy.ndarray) – Population vector (K,)

  • nservers (numpy.ndarray) – Number of servers at each station (M,)

  • sched_type (numpy.ndarray) – Scheduling strategies for each station (M,)

  • v (numpy.ndarray) – Visit ratio matrix (M x K)

  • s (numpy.ndarray) – Service time matrix (M x K)

  • maxiter (int) – Maximum iterations

  • D_frac (numpy.ndarray) – Fractional changes matrix (M x K x K)

  • l_in (numpy.ndarray) – Initial queue length matrix (M x K)

  • fcfs_schmidt (bool) – Whether to use Schmidt formula for FCFS stations

  • marginal_prob_method (str) – Method for marginal probability (‘ab’ or ‘scat’)

Returns:

QN: Queue lengths (M x K) UN: Utilization (M x K) RN: Residence times (M x K) CN: Cycle times (K,) XN: Throughput (K,) totiter: Total iterations

Return type:

Tuple of (QN, UN, RN, CN, XN, totiter)

References

Akyildiz, I.F. and Bolch, G., “Mean Value Analysis Approximation for Multiple Server Queueing Networks”, Performance Evaluation, 1988.

class AbAmvaResult(QN, UN, RN, CN, XN, totiter)[source]

Bases: object

Result from Akyildiz-Bolch AMVA algorithm.

QN: numpy.ndarray
UN: numpy.ndarray
RN: numpy.ndarray
CN: numpy.ndarray
XN: numpy.ndarray
totiter: int
pfqn_rd(L, N, Z, mu=None, options=None)[source]

Reduction Heuristic (RD) method for load-dependent networks.

Computes the logarithm of the normalizing constant using the reduction heuristic method, which handles load-dependent service rates.

Parameters:
  • L (numpy.ndarray) – Service demand matrix (M x R)

  • N (numpy.ndarray) – Population vector (1 x R)

  • Z (numpy.ndarray) – Think time vector (1 x R)

  • mu (numpy.ndarray | None) – Load-dependent rate matrix (M x sum(N)). If None, assumes load-independent rates (all 1.0).

  • options (RdOptions | None) – Solver options

Returns:

lGN: Logarithm of normalizing constant Cgamma: Gamma correction factor

Return type:

Tuple of (lGN, Cgamma) where

class RdOptions(tol=1e-06, method='default')[source]

Bases: object

Options for RD algorithm.

method: str = 'default'
tol: float = 1e-06
class RdResult(lGN, Cgamma)[source]

Bases: object

Result from Reduction Heuristic algorithm.

lGN: float
Cgamma: float
pfqn_nrl(L, N, Z=None, alpha=None)[source]

Norlund-Rice Logit (NRL) approximation for normalizing constant.

Computes the logarithm of the normalizing constant using Laplace approximation with logistic transformation.

Parameters:
Returns:

Logarithm of normalizing constant

Return type:

lG

References

Original MATLAB: matlab/src/api/pfqn/pfqn_nrl.m

pfqn_nrp(L, N, Z=None, alpha=None)[source]

Norlund-Rice Probit (NRP) approximation for normalizing constant.

Computes the logarithm of the normalizing constant using Laplace approximation with probit (normalized) transformation.

Parameters:
Returns:

Logarithm of normalizing constant

Return type:

lG

References

Original MATLAB: matlab/src/api/pfqn/pfqn_nrp.m

pfqn_lap(L, N, Z)[source]

Laplace approximation for normalizing constant.

Computes the logarithm of the normalizing constant using the classical Laplace approximation with root finding.

This method uses a saddle-point approximation to estimate the normalizing constant integral representation.

Parameters:
Returns:

Logarithm of normalizing constant approximation

Return type:

lG

References

Original MATLAB: matlab/src/api/pfqn/pfqn_lap.m

laplaceapprox(h, x0, tol=1e-5)[source]

Laplace approximation for multidimensional integrals.

Approximates I = ∫ h(x) dx using the Laplace method:

I ≈ h(x0) * sqrt((2π)^d / det(-H))

where H is the Hessian of log(h) at x0.

Parameters:
  • h (Callable) – Function to integrate (must be positive)

  • x0 (numpy.ndarray) – Point for Laplace approximation (typically the mode)

  • tol (float) – Tolerance for numerical Hessian computation

Returns:

I: Approximate integral value H: Hessian matrix at x0 logI: Logarithm of integral value (more stable)

Return type:

Tuple (I, H, logI) where

num_hess(f, x0, tol=1e-5)[source]

Compute numerical Hessian matrix using finite differences.

Uses central differences for improved accuracy.

Parameters:
  • f (Callable) – Function to differentiate (maps x -> scalar)

  • x0 (numpy.ndarray) – Point at which to compute Hessian

  • tol (float) – Step size for finite differences

Returns:

Hessian matrix (d x d) where d = len(x0)

Return type:

numpy.ndarray

pfqn_stdf(L, N, Z, S, fcfs_nodes, rates, tset)[source]

Compute sojourn time distribution for multiserver FCFS nodes.

Implements McKenna’s method for computing the response time distribution at multiserver FCFS stations in closed queueing networks.

Parameters:
  • L (numpy.ndarray) – Load matrix (M x R) - service demands

  • N (numpy.ndarray) – Population vector (R,) - number of jobs per class

  • Z (numpy.ndarray) – Think time vector (R,) or matrix (1 x R)

  • S (numpy.ndarray) – Number of servers at each station (M,)

  • fcfs_nodes (numpy.ndarray) – Array of FCFS station indices (1-indexed as in MATLAB)

  • rates (numpy.ndarray) – Service rates matrix (M x R)

  • tset (numpy.ndarray) – Time points at which to evaluate the distribution

Returns:

Dictionary with (station, class) tuples as keys and response time distribution arrays as values. Each array has shape (len(tset), 2) with:

  • column 0: CDF values

  • column 1: time points

Return type:

Dict[Tuple[int, int], numpy.ndarray]

Examples

>>> L = np.array([[0.5, 0.3], [0.2, 0.4]])
>>> N = np.array([2, 3])
>>> Z = np.array([1.0, 1.0])
>>> S = np.array([2, 1])
>>> fcfs_nodes = np.array([0])  # 0-indexed
>>> rates = np.array([[1.0, 1.0], [2.0, 2.0]])
>>> tset = np.linspace(0.1, 5.0, 50)
>>> RD = pfqn_stdf(L, N, Z, S, fcfs_nodes, rates, tset)
pfqn_stdf_heur(L, N, Z, S, fcfs_nodes, rates, tset)[source]

Heuristic sojourn time distribution for multiserver FCFS nodes.

Implements a variant of McKenna’s 1987 method that uses per-class service rate weighting for improved accuracy in multiclass networks.

Unlike pfqn_stdf which uses a simpler Erlang model for the waiting component, this heuristic accounts for class-dependent waiting times based on the expected queue composition.

Parameters:
  • L (numpy.ndarray) – Load matrix (M x R) - service demands

  • N (numpy.ndarray) – Population vector (R,) - number of jobs per class

  • Z (numpy.ndarray) – Think time vector (R,) or matrix (1 x R)

  • S (numpy.ndarray) – Number of servers at each station (M,)

  • fcfs_nodes (numpy.ndarray) – Array of FCFS station indices (0-indexed)

  • rates (numpy.ndarray) – Service rates matrix (M x R)

  • tset (numpy.ndarray) – Time points at which to evaluate the distribution

Returns:

Dictionary with (station, class) tuples as keys and response time distribution arrays as values. Each array has shape (len(tset), 2) with:

  • column 0: CDF values

  • column 1: time points

Return type:

Dict[Tuple[int, int], numpy.ndarray]

References

McKenna, J. “Mean Value Analysis for networks with service-time-dependent queue disciplines.” Performance Evaluation, 1987.

pfqn_cftp(L, N, S=None, nsamples=1, method='cftp')[source]

Exact (perfect) stationary state sampling for closed single-class multiserver product-form networks via monotone Coupling From The Past.

Parameters:
  • L (numpy.ndarray) – Service demands (stations,), L[i] = theta_i / mu_i

  • N (int) – Total closed population (scalar)

  • S (numpy.ndarray) – Number of servers per station (default 1; use np.inf for infinite server). If None, defaults to ones.

  • nsamples (int) – Number of independent samples to draw (default 1)

  • method (str) – ‘cftp’ for exact/perfect sampling (default) or ‘approx’ for rapidly-mixing approximate sampler M_A

Returns:

Empirical mean queue length per station (1 x stations) X: Sampled states, one per row (nsamples x stations), each row sums to N T: Per-sample coalescence horizon (‘cftp’) or mixing steps used

(‘approx’), as (nsamples,)

Return type:

Q

Raises:

ValueError – If less than 2 stations or non-positive demands

Matrix-Analytic Methods (line_solver.api.mam)

Matrix-Analytic Methods (MAM) for MAP/PH distributions.

Native Python implementations for analyzing Markovian Arrival Processes (MAPs), Phase-Type (PH) distributions, and related matrix-analytic methods.

Key algorithms:

map_piq: CTMC steady-state of MAP map_pie: Embedded DTMC steady-state map_lambda: Arrival rate computation map_mean, map_var, map_scv: Moment computations solver_mam_map_bmap_1: MAP/BMAP/1 queue solver using GI/M/1-type ETAQA solver_mam_bmap_map_1: BMAP/MAP/1 queue solver using M/G/1-type ETAQA

map_infgen(D0, D1)[source]

Compute the infinitesimal generator of a MAP.

The generator Q = D0 + D1 represents the underlying CTMC.

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix (non-arrival transitions)

  • D1 (numpy.ndarray) – Visible transition matrix (arrival transitions)

Returns:

Infinitesimal generator matrix Q = D0 + D1

Return type:

numpy.ndarray

map_piq(D0, D1=None)[source]

Compute steady-state distribution of the underlying CTMC of a MAP.

Solves πQ = 0 where Q = D0 + D1 is the generator.

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix, or stacked [D0, D1] if D1 is None

  • D1 (numpy.ndarray) – Visible transition matrix (optional)

Returns:

Steady-state probability vector π

Return type:

numpy.ndarray

map_prob(D0, D1=None)[source]

Stationary distribution of the underlying CTMC of a MAP (alias of map_piq(), matching the MATLAB map_prob name).

map_pie(D0, D1=None)[source]

Compute equilibrium distribution of embedded DTMC.

The embedded DTMC has transition matrix P = (-D0)^{-1} * D1. Its steady-state is π_e = π * D1 / (π * D1 * e).

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix, or stacked [D0, D1] if D1 is None

  • D1 (numpy.ndarray) – Visible transition matrix (optional)

Returns:

Equilibrium distribution of embedded DTMC

Return type:

numpy.ndarray

map_lambda(D0, D1=None)[source]

Compute the arrival rate (λ) of a MAP.

The arrival rate is λ = π * D1 * e where π is the steady-state and e is the column vector of ones.

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix, or stacked [D0, D1] if D1 is None

  • D1 (numpy.ndarray) – Visible transition matrix (optional)

Returns:

Arrival rate λ

Return type:

float

map_mean(D0, D1=None)[source]

Compute mean inter-arrival time of a MAP.

The mean is 1/λ where λ is the arrival rate.

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix, or stacked [D0, D1] if D1 is None

  • D1 (numpy.ndarray) – Visible transition matrix (optional)

Returns:

Mean inter-arrival time

Return type:

float

map_var(D0, D1=None)[source]

Compute variance of inter-arrival times of a MAP.

Var[X] = E[X²] - E[X]²

Uses map_moment for consistency with Kotlin implementation.

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix, or stacked [D0, D1] if D1 is None

  • D1 (numpy.ndarray) – Visible transition matrix (optional)

Returns:

Variance of inter-arrival times

Return type:

float

map_scv(D0, D1=None)[source]

Compute squared coefficient of variation (SCV) of a MAP.

SCV = Var[X] / E[X]² = (E[X²] - E[X]²) / E[X]²

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix, or stacked [D0, D1] if D1 is None

  • D1 (numpy.ndarray) – Visible transition matrix (optional)

Returns:

Squared coefficient of variation

Return type:

float

map_moment(D0, D1, k)[source]

Compute the k-th moment of inter-arrival time distribution.

E[X^k] = k! * π_e * (-D0)^{-k} * e

where π_e is the embedded DTMC steady-state.

Parameters:
Returns:

k-th raw moment

Return type:

float

map_scale(D0, D1, factor)[source]

Scale a MAP by a given factor.

Scaling changes the time scale: D0’ = factor * D0, D1’ = factor * D1.

Parameters:
Returns:

Tuple of scaled (D0’, D1’)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_normalize(D0, D1)[source]

Normalize a MAP to have unit mean inter-arrival time.

Parameters:
Returns:

Tuple of normalized (D0’, D1’)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_isfeasible(D0, D1, tolerance=1e-10)[source]

Check if (D0, D1) form a valid MAP.

A valid MAP requires: - D0 has non-positive diagonal and non-negative off-diagonal - D1 has non-negative elements - D0 + D1 is a valid generator (row sums = 0)

Parameters:
Returns:

True if valid MAP

Return type:

bool

exp_map(lambda_rate)[source]

Create a MAP representation of an exponential distribution.

Parameters:

lambda_rate (float) – Rate parameter (λ > 0)

Returns:

Tuple of (D0, D1) matrices representing Exp(λ)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

erlang_map(k, lambda_rate)[source]

Create a MAP representation of an Erlang-k distribution.

Parameters:
  • k (int) – Number of phases (k >= 1)

  • lambda_rate (float) – Overall rate parameter

Returns:

Tuple of (D0, D1) matrices representing Erlang(k, k*λ)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

hyperexp_map(probs, rates)[source]

Create a MAP representation of a hyperexponential distribution.

Parameters:
Returns:

Tuple of (D0, D1) matrices representing hyperexponential

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_exponential(mean)[source]

Create a MAP representation of an exponential distribution (MATLAB-style).

This is a MATLAB-compatible wrapper that takes mean instead of rate.

Parameters:

mean (float) – Mean inter-arrival time (= 1/λ)

Returns:

Tuple of (D0, D1) matrices representing Exp(1/mean)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

Examples

>>> D0, D1 = map_exponential(2)  # Poisson process with rate λ=0.5
map_erlang(mean, k)[source]

Create a MAP representation of an Erlang-k distribution (MATLAB-style).

This is a MATLAB-compatible wrapper that takes mean as first argument.

Parameters:
  • mean (float) – Mean inter-arrival time

  • k (int) – Number of phases

Returns:

Tuple of (D0, D1) matrices representing Erlang-k with given mean

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

Examples

>>> D0, D1 = map_erlang(2, 3)  # Erlang-3 with mean 2
map_hyperexp(probs, means)[source]

Create a MAP representation of a hyperexponential distribution (MATLAB-style).

This is a MATLAB-compatible wrapper that takes means instead of rates.

Parameters:
  • probs (numpy.ndarray) – Probability vector for choosing each phase

  • means (numpy.ndarray) – Mean values for each phase (1/rates)

Returns:

Tuple of (D0, D1) matrices representing hyperexponential

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_gamma(D0, D1, limit=1000)[source]

Estimate the autocorrelation decay rate of a MAP.

Mirrors MATLAB map_gamma. For MAPs of order higher than 2 the ACF is not geometric, so the decay rate is obtained by fitting rho_k = RHO0*gamma^k in the least-squares sense, with RHO0 = (1 - 1/SCV)/2 held fixed.

This is NOT a Gamma-distribution constructor; use map_erlang for that. It is also distinct from map_gamma2, which returns the second largest eigenvalue of the embedded DTMC (the two agree for order 2 only).

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix

  • D1 (numpy.ndarray) – Visible transition matrix

  • limit (int) – Maximum lag considered when fitting (default: 1000)

Returns:

Autocorrelation decay rate

Return type:

float

map_sumind(maps)[source]

Compute the sum of independent MAPs.

Creates a MAP representing the sum (concatenation) of independent random variables represented by the input MAPs.

Parameters:

maps (list) – List of MAPs, each as (D0, D1) tuple

Returns:

Tuple of (D0, D1) matrices representing the sum

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

Examples

>>> # Sum of exponential and Erlang-2
>>> MAP1 = map_exponential(1.0)
>>> MAP2 = map_erlang(1.0, 2)
>>> D0, D1 = map_sumind([MAP1, MAP2])
map_cdf(D0, D1, points)[source]

Compute cumulative distribution function of inter-arrival times.

F(t) = 1 - π_e * exp(D0*t) * e

Parameters:
Returns:

CDF values at specified points

Return type:

numpy.ndarray

Examples

>>> map_cdf(D0, D1, 1.0)  # Returns P(T <= 1)
>>> map_cdf(D0, D1, [1.0, 5.0])  # Returns [P(T<=1), P(T<=5)]
map_pdf(D0, D1, points)[source]

Compute probability density function of inter-arrival times.

f(t) = π_e * exp(D0*t) * (-D0) * e

Parameters:
Returns:

PDF values at specified points

Return type:

numpy.ndarray

Examples

>>> map_pdf(D0, D1, [0.5, 1.0, 2.0])
map_sample(D0, D1, n_samples, rng=None)[source]

Generate random samples from a MAP distribution.

Parameters:
Returns:

Array of inter-arrival times

Return type:

numpy.ndarray

map_skew(D0, D1)[source]

Compute skewness of inter-arrival times.

Parameters:
Returns:

Skewness of inter-arrival times

Return type:

float

map_kurt(D0, D1)[source]

Compute kurtosis of inter-arrival times.

Parameters:
Returns:

Kurtosis of inter-arrival times

Return type:

float

map_acf(D0, D1, lags=1)[source]

Compute autocorrelation coefficients of inter-arrival times.

Parameters:
Returns:

Array of autocorrelation coefficients at specified lags

Return type:

numpy.ndarray

Examples

>>> map_acf(D0, D1)  # lag-1 autocorrelation
>>> map_acf(D0, D1, np.arange(1, 11))  # first 10 autocorrelations
map_acfc(D0, D1, kset, u)[source]

Compute autocorrelation of counting process at given lags.

Parameters:
Returns:

Autocorrelation coefficients at specified lags

Return type:

numpy.ndarray

map_idc(D0, D1)[source]

Compute the asymptotic index of dispersion.

I = SCV * (1 + 2 * sum_{k=1}^{inf} rho_k)

where SCV is the squared coefficient of variation and rho_k is the lag-k autocorrelation coefficient.

Parameters:
Returns:

Asymptotic index of dispersion

Return type:

float

map_count_mean(D0, D1, t)[source]

Compute mean of counting process at resolution t.

Parameters:
Returns:

Mean arrivals in (0, t]

Return type:

numpy.ndarray

map_count_var(D0, D1, t)[source]

Compute variance of counting process at resolution t.

Parameters:
Returns:

Variance of arrivals in (0, t]

Return type:

numpy.ndarray

Reference:

He and Neuts, “Markov chains with marked transitions”, 1998

map_count_idc(D0, D1, t)[source]

Index of dispersion for counts (IDC) of a MAP at time point(s) t.

The IDC of the counting process A(t) associated to the MAP is I_a(t) = Var(A(t)) / E[A(t)], t > 0, i.e. the scaled variance-time curve. It interpolates between I_a(0+) = SCV of the interarrival time (renewal MAP) and the asymptotic value I_a(inf) = map_idc(MAP).

Reference:

W. Whitt and W. You, “A Robust Queueing Network Analyzer Based on Indices of Dispersion”, eq. (1).

Parameters:
Returns:

Column vector of IDC values, one per element of t.

Return type:

numpy.ndarray

map_varcount(D0, D1, tset)[source]

Compute variance of counting process (alternative implementation).

Parameters:
Returns:

Variance at each time point

Return type:

numpy.ndarray

map_count_moment(D0, D1, t, orders)[source]

Compute power moments of counts at resolution t.

Uses numerical differentiation of the moment generating function.

Parameters:
Returns:

Power moments of counts

Return type:

numpy.ndarray

map_mmpp2(mean, scv, skew=-1, acf1=-1)[source]

Fit an MMPP(2) as a MAP.

Matches the requested mean, SCV, skewness and lag-1 autocorrelation exactly. Raises ValueError when the request lies outside the MMPP(2) feasible set rather than returning a non-MAP.

Parameters:
  • mean (float) – Mean inter-arrival time

  • scv (float) – Squared coefficient of variation (>= 1)

  • skew (float) – Skewness (-1 for automatic minimization)

  • acf1 (float) – Lag-1 autocorrelation (-1 for maximum feasible)

Returns:

Tuple of (D0, D1) matrices

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

Examples

>>> D0, D1 = map_mmpp2(1, 2, -1, 0.2)  # Minimal skewness, ACF=0.2
>>> D0, D1 = map_mmpp2(1, 2, -1, -1)   # Minimal skewness, max ACF
map_gamma2(D0, D1)[source]

Compute the second largest eigenvalue of embedded DTMC.

This is the autocorrelation decay rate.

Parameters:
Returns:

Second largest eigenvalue (gamma_2)

Return type:

float

map_rand(k=2)[source]

Generate a random MAP of order k.

Parameters:

k (int) – Order of the MAP (default: 2)

Returns:

Tuple of (D0, D1) matrices

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_randn(k, mu=(1.0, 1.0), sigma=(0.5, 0.5))[source]

Generate a random MAP with normally distributed elements.

Parameters:
Returns:

Tuple of (D0, D1) matrices

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_renewal(D0, D1)[source]

Remove all correlations from a MAP, creating a renewal process.

Parameters:
Returns:

Renewal MAP with same CDF but no correlations

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_embedded(D0, D1)[source]

Compute embedded discrete-time transition matrix.

P = (-D0)^{-1} * D1

Parameters:
Returns:

Transition matrix of embedded DTMC

Return type:

numpy.ndarray

map_sum(D0, D1, n)[source]

Create MAP for sum of n IID random variables.

Parameters:
Returns:

Tuple of (D0_new, D1_new) for the sum

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_super(D0_a, D1_a, D0_b, D1_b)[source]

Create superposition of two MAPs.

Parameters:
Returns:

Superposed MAP (D0, D1)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_mixture(alpha, maps)[source]

Create probabilistic mixture of MAPs.

Parameters:
  • alpha (numpy.ndarray) – Probability vector for choosing each MAP

  • maps (list) – List of MAPs as (D0, D1) tuples

Returns:

Mixture MAP (D0, D1)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_max(D0_a, D1_a, D0_b, D1_b)[source]

Create MAP for max(X, Y) where X ~ MAP_A and Y ~ MAP_B.

The phase space is ordered as [(i,j) pairs, B-only phases, A-only phases]: in the first block both A and B are still running, in the second block A has already completed and B is awaited, in the third block B has completed and A is awaited. An arrival is recorded when the second of the two completes, i.e. only out of the last two blocks.

Parameters:
Returns:

MAP for the maximum (D0, D1)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_timereverse(D0, D1)[source]

Compute time-reversed MAP.

Parameters:
Returns:

Time-reversed MAP (D0_r, D1_r)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_mark(D0, D1, prob)[source]

Mark arrivals from a MAP according to given probabilities.

Parameters:
Returns:

MMAP as list [D0, D1_class1, D1_class2, …]

Return type:

list

map_stochcomp(D0, D1, retain_idx)[source]

Stochastic complementation to reduce MAP order.

Parameters:
Returns:

Reduced MAP (D0_new, D1_new)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_kpc(maps)[source]

Kronecker product composition of MAPs.

Parameters:

maps (list) – List of MAPs as (D0, D1) tuples

Returns:

Composed MAP (D0, D1)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_bernstein(f, n=20)[source]

Convert distribution to MAP via Bernstein approximation.

Parameters:
  • f – PDF function handle

  • n (int) – Number of phases (default: 20)

Returns:

MAP representation (D0, D1)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_pntiter(D0, D1, na, t, M=None)[source]

Compute probability of na arrivals in interval [0, t].

Uses iterative bisection method (Neuts and Li).

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix

  • D1 (numpy.ndarray) – Visible transition matrix

  • na (int) – Number of arrivals

  • t (float) – Time interval length

  • M (int | None) – Bisection depth (auto-computed if None)

Returns:

Matrix of probabilities

Return type:

numpy.ndarray

map_pntquad(D0, D1, na, t)[source]

Compute probability of na arrivals using ODE solver.

Parameters:
Returns:

Matrix P_n(t)

Return type:

numpy.ndarray

map2_fit(e1, e2, e3=-1.0, g2=0.0)[source]

Fit a MAP(2) distribution to moments and autocorrelation.

Based on: A. Heindl, G. Horvath, K. Gross “Explicit inverse characterization of acyclic MAPs of second order”

Parameters:
  • e1 (float) – First moment E[X]

  • e2 (float) – Second moment E[X^2]

  • e3 (float) – Third moment E[X^3], or -1 for automatic selection, -2 for minimum, -3 for maximum, or negative fraction for interpolation

  • g2 (float) – Autocorrelation decay rate (gamma_2)

Returns:

  • MAP: Tuple (D0, D1) if successful, None if failed

  • error_code: 0 for success, >0 for various errors

Return type:

Tuple of (MAP, error_code) where

Error codes:

0: Success 10: Mean out of bounds 20: Correlated exponential 30: h2 out of bounds 40: h3 out of bounds 51-54: g2 out of bounds

map_joint(D0, D1, a, i)[source]

Compute joint moments of a MAP.

E[(X_{a1})^{i1} * (X_{a1+a2})^{i2} * …]

Parameters:
Returns:

Joint moment

Return type:

float

map_issym(D0, D1=None)[source]

Check if MAP contains symbolic elements.

In Python, this always returns False as we use numpy arrays.

Parameters:
Returns:

False (Python arrays are always numeric)

Return type:

bool

map_feastol()[source]

Get the feasibility tolerance exponent for MAPs.

This is the exponent k of the toolbox feasibility tolerance 10^-k, so the tolerance itself is 10^-8. It is NOT the tolerance: map_feastol() == 8.

Returns:

Tolerance exponent k, to be used as 10**(-map_feastol())

Return type:

int

map_feasblock(E1, E2, E3, G2, opt='')[source]

Fit the most similar feasible MAP(2).

Parameters:
  • E1 (float) – First moment (mean)

  • E2 (float) – Second moment (or SCV if opt=’scv’)

  • E3 (float) – Third moment

  • G2 (float) – Autocorrelation decay rate

  • opt (str) – ‘scv’ if E2 is SCV instead of second moment

Returns:

Feasible MAP (D0, D1)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_block(E1, E2, E3, G2, opt='')[source]

Construct a MAP(2) from moments and autocorrelation.

Parameters:
  • E1 (float) – First moment

  • E2 (float) – Second moment (or SCV if opt=’scv’)

  • E3 (float) – Third moment

  • G2 (float) – Autocorrelation decay rate

  • opt (str) – ‘scv’ if E2 is SCV

Returns:

MAP (D0, D1)

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

map_largemap()[source]

Get threshold for “large” MAP where exact computation is expensive.

Returns:

Return type:

Order threshold (default

mmap_infgen(D0, D_list)[source]

Compute the infinitesimal generator of an MMAP.

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix (non-arrival transitions)

  • D_list (List[numpy.ndarray]) – List of arrival marking matrices [D1, D2, …, Dm]

Returns:

Infinitesimal generator Q = D0 + D1 + D2 + … + Dm

Return type:

numpy.ndarray

mmap_normalize(D0, D_list)[source]

Fix MMAP feasibility by clamping negative values and closing the generator.

Port of matlab/src/api/mam/mmap_normalize.m (mirrored by the JAR jline.api.mam.Mmap_normalize). The MMAP is [D0] + D_list with D_list = [D1, D21, …, D2C], i.e. the aggregate D1 followed by the C per-class marking matrices, so C = len(D_list) - 1. This is the layout produced by _mmap_to_tuple and by the mmap_super / mmap_max callers, which pass result[1:].

The aggregate D1 is recomputed as the sum of the per-class matrices, and the diagonal of D0 closes each row of the generator D0 + D1:

D0[k,k] = -sum_{j!=k} D0[k,j] - sum_j D1[k,j]

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix

  • D_list (List[numpy.ndarray]) – [D1, D21, …, D2C], the aggregate followed by the per-class marking matrices

Returns:

Tuple of (normalized_D0, normalized_D_list) in the same layout

Return type:

Tuple[numpy.ndarray, List[numpy.ndarray]]

mmap_super_safe(mmap_list, maxorder=1000, method='default')[source]

Safely superpose multiple MMAPs into a single MMAP.

Combines multiple MMAPs while ensuring the order of the resulting MMAP does not exceed maxorder. If combining would exceed maxorder, alternative methods are used (fitting to exponential or simplified MAP).

Parameters:
  • mmap_list (List[Tuple[numpy.ndarray, List[numpy.ndarray]]]) – List of (D0, D_list) tuples, one per MMAP

  • maxorder (int) – Maximum allowed order (state space size) for result

  • method (str) – Combination method (“default” or “match”)

Returns:

Tuple of (D0_super, D_list_super) for the superposed MMAP

Return type:

Tuple[numpy.ndarray, List[numpy.ndarray]]

Algorithm:
  1. Sort MMAPs by squared coefficient of variation (SCV) of unmarked process

  2. Iteratively combine: start with simplest, add others in order

  3. If Kronecker product would exceed maxorder, use simpler approximations

mmap_mark(D0, D_list, prob)[source]

Reclassify arrivals in an MMAP according to a probability matrix.

Converts an MMAP with K classes to one with R classes based on a KxR probability matrix that describes how arrivals are reclassified.

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix

  • D_list (List[numpy.ndarray]) – List of K arrival marking matrices [D1, D2, …, DK]

  • prob (numpy.ndarray) – K x R probability matrix where prob[k,r] is the probability that a class-k arrival in the original MMAP becomes a class-r arrival in the new MMAP

Returns:

Tuple of (D0_new, D_list_new) where D_list_new has R matrices

Return type:

Tuple[numpy.ndarray, List[numpy.ndarray]]

Example

If prob = [[0.8, 0.2], [0.3, 0.7]], a 2-class MMAP becomes a 2-class MMAP where 80% of class-1 arrivals are now class-1, 20% become class-2, etc.

mmap_scale(D0, D_list, M, max_iter=30)[source]

Scale the mean inter-arrival times of an MMAP.

Adjusts all matrices to achieve specified mean inter-arrival times.

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix

  • D_list (List[numpy.ndarray]) – List of arrival marking matrices

  • M (float | numpy.ndarray) – Desired mean inter-arrival times. Can be: - Single float: uniform scaling of all classes - Array of K values: individual scaling per class

  • max_iter (int) – Maximum iterations for optimization (only for vector M)

Returns:

Tuple of (D0_scaled, D_list_scaled)

Return type:

Tuple[numpy.ndarray, List[numpy.ndarray]]

Algorithm:

For single M: Scale all matrices uniformly by ratio = M_old / M For vector M: Use iterative coordinate descent to find scaling factors

mmap_hide(D0, D_list, types)[source]

Hide (remove) specified arrival classes from an MMAP.

The hidden classes are set to zero matrices, effectively removing them from observation while maintaining the underlying stochastic process.

Parameters:
Returns:

Tuple of (D0_hidden, D_list_hidden) where specified classes are zero

Return type:

Tuple[numpy.ndarray, List[numpy.ndarray]]

Example

mmap_hide(D0, [D1, D2, D3], types=[1]) hides class 2 (index 1)

aph2_assemble(l1, l2, p1)[source]

Build the APH(2) with the given parameters. Mirrors aph2_assemble.m.

Parameters:
  • l1 (float) – mean of the first phase (the MATLAB source parameterizes by 1/rate)

  • l2 (float) – mean of the second phase

  • p1 (float) – probability of continuing to the second phase

Returns:

The APH(2) as [D0, D1].

Return type:

List[numpy.ndarray]

aph2_fitall(M1, M2, M3)[source]

Fit every APH(2) matching the given first three moments. Mirrors aph2_fitall.m.

Returns a list of 1 or 2 APH(2) fits. It is never empty: when no APH(2) solution is feasible the general APH fitter aph_fit(M1, M2, M3, 2) supplies a fallback, exactly as in the MATLAB and JAR sources.

aph2_adjust(M1, M2, M3, method='simple')[source]

Find the APH(2)-feasible (M2, M3) closest to the given pair, holding M1 fixed. Mirrors the ‘simple’ branch of aph2_adjust.m [Telek and Heindl, 2002], which is the only branch aph2_fit uses.

Returns:

(M2a, M3a), the adjusted moments. M1 is never altered.

Return type:

Tuple[float, float]

aph2_fit(M1, M2, M3)[source]

Fit an APH(2) to the first three moments, adjusting M2/M3 if they are infeasible. Mirrors aph2_fit.m.

M1 is always matched exactly: aph2_adjust never alters it, and the aph_fit fallback rescales its result to mean M1.

Parameters:
  • M1 (float) – the first three raw moments.

  • M2 (float) – the first three raw moments.

  • M3 (float) – the first three raw moments.

Returns:

The fitted APH(2) as [D0, D1].

Return type:

List[numpy.ndarray]

mmap_compress(D0, D_list, method='default', target_order=None)[source]

Compress an MMAP using various approximation methods.

Reduces the state space of an MMAP while preserving key statistical properties (moments, inter-arrival time distribution, etc.).

The MMAP is [D0] + D_list with D_list = [D1, D11, …, D1C], i.e. the aggregate D1 followed by the C per-class marking matrices, so C = len(D_list) - 1. This is the layout of mmap_normalize and of every caller (npfqn_traffic_merge, mmap_fj), which pass mmap[1:].

Parameters:
  • D0 (numpy.ndarray) – Hidden transition matrix

  • D_list (List[numpy.ndarray]) – [D1, D11, …, D1C], the aggregate followed by the per-class marking matrices

  • method (str) – Compression method. Options: - “default”, “mixture”, “mixture.order1”: order-1 mixture fitting - “exponential”: Fit to single-state Poisson

  • target_order (int | None) – If given, skip compression when the MMAP order is already at most this value. There is no implicit size guard: the order-1 mixture is a lossy approximation with a contract (see _compress_mixture_order1), and callers rely on it holding regardless of the input order.

Returns:

Tuple of (D0_compressed, D_list_compressed) in the same layout.

Return type:

Tuple[numpy.ndarray, List[numpy.ndarray]]

mmap_exponential(lambda_rate, nclasses=None)[source]

Create an exponential MMAP (Poisson arrival process).

Parameters:
  • lambda_rate (float | numpy.ndarray) – Arrival rate (scalar) or rate per class (vector)

  • nclasses (int | None) – Number of classes (if lambda_rate is scalar)

Returns:

Tuple of (D0, D_list) representing exponential MMAP

Return type:

Tuple[numpy.ndarray, List[numpy.ndarray]]

mmap_issym(mmap)[source]

Check if an MMAP contains symbolic elements.

Parameters:

mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

Returns:

True if any matrix in the MMAP contains sympy symbolic expressions

Return type:

bool

mmap_isfeasible(mmap, tol=None)[source]

Check whether an MMAP is feasible up to the given tolerance.

Checks: - Elements are real (no imaginary parts) - D0 + D1 rows sum to zero (generator property) - Diagonal of D0 is negative - Off-diagonal of D0 is non-negative - All D1c matrices are non-negative - D1 = D11 + D12 + … + D1C

Parameters:
  • mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

  • tol (float) – Tolerance for feasibility checks (default: 1e-6)

Returns:

True if MMAP is feasible, False otherwise

Return type:

bool

mmap_lambda(mmap)[source]

Compute the arrival rate of each class in an MMAP.

Parameters:

mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

Returns:

Array of arrival rates, one per class

Return type:

numpy.ndarray

mmap_count_lambda(mmap)[source]

Compute the arrival rate of the counting process for each class.

The rate for class k is λ_k = π * D_k * e where π is the steady-state of the underlying CTMC.

Parameters:

mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

Returns:

Array of arrival rates, one per class

Return type:

numpy.ndarray

mmap_pie(mmap)[source]

Compute the stationary probability of the DTMC embedded at restart instants after an arrival of each class.

Parameters:

mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

Returns:

Matrix of shape (m, n) where row c is the steady-state for class c

Return type:

numpy.ndarray

mmap_pc(mmap)[source]

Compute the arrival probabilities of each class for the given MMAP.

Parameters:

mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

Returns:

Array of arrival probabilities, one per class

Return type:

numpy.ndarray

mmap_embedded(mmap)[source]

Compute the embedded DTMC transition matrices for each class.

For class k, the embedded matrix is Pc_k = (-D0)^{-1} * D_{2+k}

Parameters:

mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

Returns:

List of embedded DTMC transition matrices, one per class

Return type:

List[numpy.ndarray]

mmap_sample(mmap, n_samples, pi=None, seed=None)[source]

Generate samples from a Marked MAP.

Parameters:
  • mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

  • n_samples (int) – Number of random samples to collect

  • pi (numpy.ndarray) – Initial probability (if None, uses steady-state)

  • seed (int) – Random seed for reproducibility

Returns:

  • T: Array of inter-arrival times

  • A: Array of class labels (1-indexed for MATLAB compatibility)

Return type:

Tuple of (T, A) where

mmap_rand(order, classes)[source]

Generate a random MMAP with given order and number of classes.

Parameters:
  • order (int) – Number of states

  • classes (int) – Number of arrival classes

Returns:

List of matrices [D0, D1, D21, D22, …, D2K]

Return type:

List[numpy.ndarray]

mmap_timereverse(mmap)[source]

Compute the time-reversed MMAP.

Parameters:

mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

Returns:

Time-reversed MMAP

Return type:

List[numpy.ndarray]

mmap_sum(mmap, n)[source]

Create an MMAP representing the sum of n identical MMAPs (n-fold sum).

This creates an MMAP whose inter-arrival times are distributed as the sum of n inter-arrival times from the original MMAP.

Parameters:
Returns:

Summed MMAP

Return type:

List[numpy.ndarray]

mmap_super(mmap_a, mmap_b=None, opt='default')[source]

Superpose two or more MMAPs.

Parameters:
  • mmap_a (List[numpy.ndarray]) – First MMAP (or list of MMAPs if mmap_b is None)

  • mmap_b (List[numpy.ndarray]) – Second MMAP (optional)

  • opt (str) – “default” - each class in MMAPa and MMAPb is distinct in result “match” - class c in both maps is mapped to class c in result

Returns:

Superposed MMAP

Return type:

List[numpy.ndarray]

mmap_mixture(alpha, maps)[source]

Create a probabilistic mixture of MAPs.

Each MAP in the list is selected with probability alpha[i].

Parameters:
  • alpha (numpy.ndarray) – Array of mixing probabilities

  • maps (List) – List of MAPs (each MAP is [D0, D1])

Returns:

Mixed MMAP with len(maps) classes

Return type:

List[numpy.ndarray]

mmap_max(mmap_a, mmap_b, k)[source]

Create MMAP for the maximum of arrivals from two synchronized MMAPs.

This models a synchronization queue where arrivals from both sources must be paired before release.

Parameters:
Returns:

MMAP for the synchronized (maximum) process

Return type:

List[numpy.ndarray]

mmap_maps(mmap)[source]

Extract K MAPs, one for each class of the MMAP[K] process.

For class k, the MAP is {D0 + D1 - D_{2+k}, D_{2+k}}

Parameters:

mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D21, D22, …, D2K]

Returns:

List of MAPs, one per class

Return type:

List[Tuple[numpy.ndarray, numpy.ndarray]]

mmap_count_mean(mmap, t)[source]

Compute the mean of the counting process at resolution t.

Parameters:
  • mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

  • t (float) – Time period for counting

Returns:

Array of mean counts, one per class

Return type:

numpy.ndarray

mmap_count_var(mmap, t)[source]

Compute the variance of the counting process at resolution t.

Parameters:
  • mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

  • t (float) – Time period for counting

Returns:

Array of variances, one per class

Return type:

numpy.ndarray

mmap_count_idc(mmap, t)[source]

Compute the per-class Index of Dispersion of Counts at resolution t.

IDC = Var[N(t)] / E[N(t)]

Parameters:
Returns:

Array of IDC values, one per class

Return type:

numpy.ndarray

mmap_count_mcov(mmap, t)[source]

Compute the count covariance between each pair of classes at time scale t.

Parameters:
Returns:

m x m covariance matrix

Return type:

numpy.ndarray

mmap_idc(mmap)[source]

Compute the asymptotic Index of Dispersion of Counts for each class.

This is the limit of IDC(t) as t -> infinity.

Parameters:

mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

Returns:

Array of asymptotic IDC values, one per class

Return type:

numpy.ndarray

mmap_sigma(mmap)[source]

Compute one-step class transition probabilities.

p_{i,j} = P(C_k = j | C_{k-1} = i)

Parameters:

mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

Returns:

C x C matrix of transition probabilities

Return type:

numpy.ndarray

mmap_sigma2(mmap)[source]

Compute two-step class transition probabilities.

p_{i,j,h} = P(C_k = h | C_{k-1} = j, C_{k-2} = i)

Parameters:

mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

Returns:

C x C x C 3D array of transition probabilities

Return type:

numpy.ndarray

mmap_forward_moment(mmap, orders, norm=True)[source]

Compute the theoretical forward moments of an MMAP.

Forward moments are E[X^k | previous arrival was class c].

Parameters:
  • mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

  • orders (numpy.ndarray) – Array of moment orders to compute

  • norm (bool) – If True, normalize by class probability

Returns:

Matrix of shape (C, len(orders)) where element (c, k) is the order-k forward moment for class c

Return type:

numpy.ndarray

mmap_backward_moment(mmap, orders, norm=True)[source]

Compute the theoretical backward moments of an MMAP.

Backward moments are E[X^k | next arrival will be class c].

Parameters:
  • mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

  • orders (numpy.ndarray) – Array of moment orders to compute

  • norm (bool) – If True, normalize by class probability

Returns:

Matrix of shape (C, len(orders)) where element (c, k) is the order-k backward moment for class c

Return type:

numpy.ndarray

mmap_cross_moment(mmap, k)[source]

Compute the k-th order moment of inter-arrival times between class pairs.

Computes E[X^k | previous = class i, next = class j] for all i, j.

Parameters:
  • mmap (List[numpy.ndarray]) – List of matrices [D0, D1, D2, …, Dm]

  • k (int) – Order of the moment

Returns:

C x C matrix where element (i, j) is the k-th moment for transitions i->j

Return type:

numpy.ndarray

mmap_modulate(P, HT, MMAP)[source]

Modulate MMAPs in continuous time according to holding time distributions.

Creates an MMAP that switches between different MMAPs according to a continuous-time Markov modulated process.

Parameters:
  • P (numpy.ndarray) – J x J transition probability matrix between states

  • HT (List) – List of phase-type distributions for holding time in each state

  • MMAP (List) – List of MMAPs, one for each state

Returns:

Modulated MMAP

Return type:

List[numpy.ndarray]

ldqbd(Q0, Q1, Q2, options=None)[source]

Solve a level-dependent QBD process.

Parameters:
  • Q0 (List[numpy.ndarray]) – List of upward transition matrices [Q0^(0), Q0^(1), …, Q0^(N-1)] Q0^(n) has shape (states_n, states_{n+1})

  • Q1 (List[numpy.ndarray]) – List of local transition matrices [Q1^(0), Q1^(1), …, Q1^(N)] Q1^(n) has shape (states_n, states_n)

  • Q2 (List[numpy.ndarray]) – List of downward transition matrices [Q2^(1), Q2^(2), …, Q2^(N)] Q2^(n) has shape (states_n, states_{n-1})

  • options (LdqbdOptions | None) – LdqbdOptions instance (uses defaults if None)

Returns:

LdqbdResult containing rate matrices R and stationary distribution pi

Return type:

LdqbdResult

Algorithm:
  1. Compute rate matrices backward using continued fraction recursion

  2. Compute stationary distribution forward using R matrices

class LdqbdResult(R, pi)[source]

Bases: object

Result of LDQBD solver.

R

List of rate matrices R^(1), R^(2), …, R^(N)

Type:

List[numpy.ndarray]

pi

Stationary distribution vector [pi_0, pi_1, …, pi_N]

Type:

numpy.ndarray

R: List[numpy.ndarray]
pi: numpy.ndarray
class LdqbdOptions(epsilon=1e-10, max_iter=1000, verbose=False)[source]

Bases: object

Options for LDQBD solver.

epsilon

Convergence tolerance (default: 1e-10)

Type:

float

max_iter

Maximum number of iterations (default: 1000)

Type:

int

verbose

Print debug information (default: False)

Type:

bool

epsilon: float = 1e-10
max_iter: int = 1000
verbose: bool = False
class MAPBMAP1Result(mean_queue_length, utilization, mean_response_time, throughput, pi, R, mean_batch_size)[source]

Bases: object

Result of MAP/BMAP/1 queue analysis.

mean_queue_length: float

Mean queue length E[N]

utilization: float

Server utilization rho

mean_response_time: float

Mean response time E[R]

throughput: float

Throughput (arrival rate)

pi: numpy.ndarray

Aggregated stationary probabilities [pi0, pi1, piStar]

R: numpy.ndarray

R matrix

mean_batch_size: float

Mean batch size of service

solver_mam_map_bmap_1(C0, C1, D)[source]

Solve a MAP/BMAP/1 queue using GI/M/1-type matrix-analytic methods.

The MAP is specified by matrices (C0, C1) where: - C0: transitions without arrivals - C1: transitions triggering arrivals

The BMAP for service is specified by matrices {D0, D1, D2, …, DK} where: - D0: transitions without service completions - Dk: transitions triggering batch service of k customers (k >= 1)

The GI/M/1-type structure for MAP/BMAP/1 is: ```

B1 A0 0 0 … B2 A1 A0 0 …

Q = B3 A2 A1 A0 …

```

Where:

A0 = C1 otimes I_ms (MAP arrival, level +1) A1 = C0 otimes I_ms + I_ma otimes D0 (phase changes, level 0) A_{k+1} = I_ma otimes D_k (batch size k service, level -k)

Parameters:
Returns:

MAPBMAP1Result with performance metrics

Return type:

MAPBMAP1Result

class BMAPMAP1Result(mean_queue_length, utilization, mean_response_time, throughput, pi, G, mean_batch_size)[source]

Bases: object

Result of BMAP/MAP/1 queue analysis.

mean_queue_length: float

Mean queue length E[N]

utilization: float

Server utilization rho

mean_response_time: float

Mean response time E[R]

throughput: float

Throughput (total customer arrival rate)

pi: numpy.ndarray

Aggregated stationary probabilities [pi0, pi1, piStar]

G: numpy.ndarray

G matrix

mean_batch_size: float

Mean batch size of arrivals

solver_mam_bmap_map_1(D, S0, S1)[source]

Solve a BMAP/MAP/1 queue using M/G/1-type matrix-analytic methods.

The BMAP is specified by matrices {D0, D1, D2, …, DK} where: - D0: transitions without arrivals - Dk: transitions triggering batch size k arrivals (k >= 1)

The MAP for service is specified by matrices (S0, S1) where: - S0: transitions without service completions - S1: transitions triggering service completions

The M/G/1-type structure for BMAP/MAP/1 is: ```

A0 = I_ma otimes S1 (service completion, level -1) A1 = D0 otimes I_ms + I_ma otimes S0 (phase changes, level 0) A_{k+1} = D_k otimes I_ms (batch arrival size k, level +k)

```

Parameters:
  • D (List[numpy.ndarray]) – BMAP matrices as list [D0, D1, D2, …, DK]

  • S0 (numpy.ndarray) – MAP service matrix for transitions without service completions

  • S1 (numpy.ndarray) – MAP service matrix for service completions

Returns:

BMAPMAP1Result with performance metrics

Return type:

BMAPMAP1Result

class QBDResult(R, G=None, U=None, eta=None)[source]

Bases: object

Result of QBD analysis.

G: numpy.ndarray | None = None
U: numpy.ndarray | None = None
eta: float | None = None
R: numpy.ndarray
class QbdRapResult(levelProb, QN, R, G, U, spr, pqueue, pi0)[source]

Bases: object

Result of the equilibrium analysis of a QBD with RAP components.

levelProb

Marginal level probabilities, levels 0..numLevels

Type:

numpy.ndarray

QN

Mean queue length, computed exactly as pi0*R*inv(I-R)^2*e

Type:

float

R

Rate matrix R = A0*inv(-U)

Type:

numpy.ndarray

G

Matrix G solving A0*G^2 + A1*G + A2 = 0

Type:

numpy.ndarray

U

Matrix U = A1 + A0*G

Type:

numpy.ndarray

spr

Spectral radius Sp(R); positive recurrent iff Sp(R) < 1

Type:

float

pqueue

(numLevels+1) x m array whose n-th row is the level vector pi_n

Type:

numpy.ndarray

pi0

Level-0 vector pi_0, the boundary vector of Theorem 7

Type:

numpy.ndarray

levelProb: numpy.ndarray
QN: float
R: numpy.ndarray
G: numpy.ndarray
U: numpy.ndarray
spr: float
pqueue: numpy.ndarray
pi0: numpy.ndarray
qbd_R(B, L, F, iter_max=100000, tol=1e-12)[source]

Compute QBD rate matrix R using successive substitutions.

Solves the matrix quadratic equation:

R^2 * A_{-1} + R * A_0 + A_1 = 0

where A_{-1} = B, A_0 = L, A_1 = F.

Parameters:
  • B (numpy.ndarray) – Backward transition block A_{-1}

  • L (numpy.ndarray) – Local transition block A_0

  • F (numpy.ndarray) – Forward transition block A_1

  • iter_max (int) – Maximum iterations (default: 100000)

  • tol (float) – Convergence tolerance (default: 1e-12)

Returns:

Rate matrix R

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/mam/qbd_R.m

qbd_R_logred(B, L, F, iter_max=1000, tol=1e-14)[source]

Compute QBD rate matrix R using logarithmic reduction.

Uses the logarithmic reduction algorithm which has quadratic convergence compared to linear convergence of successive substitutions.

Parameters:
  • B (numpy.ndarray) – Backward transition block A_{-1}

  • L (numpy.ndarray) – Local transition block A_0

  • F (numpy.ndarray) – Forward transition block A_1

  • iter_max (int) – Maximum iterations (default: 1000)

  • tol (float) – Convergence tolerance (default: 1e-14)

Returns:

Rate matrix R

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/mam/qbd_R_logred.m Latouche & Ramaswami, Ch. 8

qbd_rg(B, L, F, method='logred', iter_max=1000, tol=1e-14)[source]

Compute both R and G matrices for a QBD process.

G is the minimal non-negative solution to:

A_1 * G^2 + A_0 * G + A_{-1} = 0

R is the minimal non-negative solution to:

R^2 * A_{-1} + R * A_0 + A_1 = 0

Parameters:
  • B (numpy.ndarray) – Backward transition block A_{-1}

  • L (numpy.ndarray) – Local transition block A_0

  • F (numpy.ndarray) – Forward transition block A_1

  • method (str) – ‘logred’ or ‘successive’ (default: ‘logred’)

  • iter_max (int) – Maximum iterations

  • tol (float) – Convergence tolerance

Returns:

QBDResult with R, G, U, and eta (caudal characteristic)

Return type:

QBDResult

References

Original MATLAB: matlab/src/api/mam/qbd_rg.m

qbd_blocks_mapmap1(D0_arr, D1_arr, D0_srv, D1_srv)[source]

Construct QBD blocks for a MAP/MAP/1 queue.

Builds the backward (B), local (L), and forward (F) transition blocks for the QBD representation of a MAP/MAP/1 queue.

Parameters:
Returns:

Tuple of (B, L, F) QBD blocks

Return type:

Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]

References

Original MATLAB: matlab/src/api/mam/qbd_mapmap1.m

qbd_bmapbmap1(MAPa, pbatcha, MAPs)[source]

Compute QBD blocks for a BMAP/BMAP/1 queue.

Constructs the QBD (Quasi-Birth-Death) transition blocks for a BMAP/BMAP/1 queue with batch arrivals.

Parameters:
Returns:

A0: Local transition block A_1: Downward transition block A1_list: List of upward transition blocks for each batch size B0: Initial boundary local block B1_list: List of boundary upward blocks for each batch size

Return type:

Tuple of (A0, A_1, A1_list, B0, B1_list) where

References

Original MATLAB: matlab/src/api/mam/qbd_bmapbmap1.m

qbd_mapmap1(MAPa, MAPs, util=None)[source]

Analyze a MAP/MAP/1 queue using QBD methods.

Solves a MAP/MAP/1 queue using Quasi-Birth-Death process methods, computing throughput, queue length, utilization, and other metrics.

Parameters:
Returns:

Tuple of (XN, QN, UN, pqueue, R, eta, G, A_1, A0, A1, U, MAPs_scaled) where:

XN: System throughput QN: Mean queue length UN: Utilization pqueue: Queue length distribution R: Rate matrix R eta: Caudal characteristic (spectral radius of R) G: Rate matrix G A_1: Downward transition block A0: Local transition block A1: Upward transition block U: Matrix U MAPs_scaled: Scaled service process

Return type:

Tuple[float, float, float, numpy.ndarray, numpy.ndarray, float | None, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, Tuple[numpy.ndarray, numpy.ndarray]]

References

Original MATLAB: matlab/src/api/mam/qbd_mapmap1.m

qbd_rap(A0, A1, A2, B0=None, B1=None, numLevels=20)[source]

Equilibrium analysis of a Quasi-Birth-and-Death process with Rational Arrival Process (RAP) components.

The process is specified directly by its level-independent blocks (A0,A1,A2) and its boundary blocks (B0,B1), where A0 drives level increases, A2 drives level decreases and A1 the within-level evolution. Unlike a Markovian QBD the blocks need not be nonnegative: they are only required to be conservative, (A0+A1+A2)*e = 0, and to define a genuine RAP through the prediction-process interpretation. This makes qbd_rap strictly more general than qbd_raprap1, which builds a product-space QBD from two INDEPENDENT RAPs; here the arrival process and the sequence of service times may be driven from a shared phase space and therefore be cross-correlated.

This is the block-level core of the RAP QBD family. qbd_raprap1 is the thin wrapper over it that builds the product-space blocks of two independent RAPs; callers with a coupled model must call qbd_rap directly because no product form exists to factor out.

Algorithm (Theorem 7 of the reference):
  1. Solve A0*G^2 + A1*G + A2 = 0 for G.

  2. U = A1 + A0*G.

  3. R = A0*inv(-U).

  4. Find the row vector pihat0 with pihat0*(B1 + R*A2) = 0, pihat0*e = 1.

  5. pi0 = K*pihat0 with K chosen so that pi0*inv(I-R)*e = 1.

  6. pi_n = pi0*R^n, and the marginal level probability is pi_n*e.

The process is positive recurrent iff Sp(R) < 1 and step 4 has a solution.

Computation of G: the blocks are not nonnegative, so the probabilistic iterations used for Markovian QBDs (logarithmic reduction, cyclic reduction) carry no convergence guarantee here, and the paper explicitly leaves the general case open (“The issue of justifying algorithms for the evaluation of the matrix G for such processes has not been undertaken”, Section 6). See qbd_rap_g: the rank-one closed form is used when it applies, otherwise functional iteration followed by Newton’s method, and an unconverged G is never returned.

References

N. G. Bean and B. F. Nielsen, “Quasi-Birth-and-Death Processes with Rational Arrival Process Components”, Stochastic Models, 26(3), 2010, pp. 309-334 (DTU technical report IMM-2007-20). The argument rests on the prediction-process interpretation of a RAP due to Asmussen and Bladt, which is what allows a QBD argument to be carried over to matrices that are not nonnegative; the same prediction process underlies the conditional-vector RAP sampler in RAP.sample.

Original MATLAB: matlab/src/api/mam/qbd_rap.m

Parameters:
Returns:

QbdRapResult with levelProb, QN, R, G, U, spr, pqueue and pi0

Raises:

ValueError – if the blocks are not conservative, if the process is not positive recurrent, or if G cannot be computed

Return type:

QbdRapResult

qbd_rap_g(A0, A1, A2, block_scale)[source]

Solve A0*G^2 + A1*G + A2 = 0 for the matrix G.

Uses the exact rank-one closed form when A2 has rank one, and otherwise natural functional iteration as a warm start followed by Newton’s method on the Sylvester-form Jacobian. Never returns an unconverged iterate.

Parameters:
Returns:

The matrix G

Raises:

ValueError – if G cannot be computed to roundoff level

Return type:

numpy.ndarray

qbd_raprap1(RAPa, RAPs, util=None)[source]

Analyze a RAP/RAP/1 queue using QBD methods.

Solves a RAP/RAP/1 queue (Rational Arrival Process) using QBD methods, computing throughput, queue length, utilization, and other metrics.

References

N. G. Bean and B. F. Nielsen, “Quasi-Birth-and-Death Processes with Rational Arrival Process Components”, Stochastic Models, 26(3), 2010, pp. 309-334. The analysis rests on the prediction-process interpretation of a RAP due to Asmussen and Bladt, which is what allows a QBD argument to be carried over to matrices that are not nonnegative. The same prediction process underlies the conditional-vector RAP sampler in RAP.sample.

Parameters:
Returns:

XN: System throughput QN: Mean queue length UN: Utilization pqueue: Queue length distribution R: Rate matrix R eta: Caudal characteristic G: Rate matrix G B: Backward transition block L: Local transition block F: Forward transition block

Return type:

Tuple of (XN, QN, UN, pqueue, R, eta, G, B, L, F) where

References

Original MATLAB: matlab/src/api/mam/qbd_raprap1.m

qbd_setupdelayoff(lambda_val, mu, alpharate, alphascv, betarate, betascv)[source]

Analyze queue with setup delay and turn-off phases.

Performs queue-length analysis for a queueing system with setup delay (warm-up) and turn-off periods using QBD methods.

The system operates as follows: 1. When empty and job arrives, server enters setup phase 2. After setup, server becomes active and serves jobs 3. When queue empties, server enters turn-off phase 4. After turn-off, server becomes idle

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • alpharate (float) – Rate of setup delay phase

  • alphascv (float) – Squared coefficient of variation for setup delay

  • betarate (float) – Rate of turn-off phase

  • betascv (float) – Squared coefficient of variation for turn-off period

Returns:

Average queue length QN

Return type:

float

References

Original MATLAB: matlab/src/api/mam/qbd_setupdelayoff.m

qbd_depproc_etaqa(MAPa, MAPs, n)[source]

Construct MAP departure process for MAP/MAP/1-FCFS via ETAQA truncation.

Builds a Markovian Arrival Process (MAP) approximation of the departure process from a single-server FCFS queue with MAP arrival process and MAP service process. The QBD is truncated at level n using ETAQA boundary corrections.

Parameters:
  • MAPa – Arrival MAP as list [D0, D1] of numpy arrays.

  • MAPs – Service MAP as list [D0, D1] of numpy arrays.

  • n – Truncation level (number of QBD levels beyond level 0).

Returns:

List [D0, D1] representing the departure MAP, where D0 and D1 are numpy arrays of size (n+1)*lvlsz x (n+1)*lvlsz.

qbd_depproc_etaqa_ps(MAPa, MAPs, n)[source]

Construct MAP departure process for MAP/MAP/1-PS via ETAQA truncation.

Same as qbd_depproc_etaqa but for Processor Sharing (PS) discipline. Under PS, when j customers are present, each is served at rate mu/j. This leads to rate-dependent service completion splitting in D0 and D1.

Parameters:
  • MAPa – Arrival MAP as list [D0, D1] of numpy arrays.

  • MAPs – Service MAP as list [D0, D1] of numpy arrays.

  • n – Truncation level (number of QBD levels beyond level 0).

Returns:

List [D0, D1] representing the departure MAP, where D0 and D1 are numpy arrays of size (n+1)*lvlsz x (n+1)*lvlsz.

qbd_depproc_jointmom(MAPa, MAPs, iset)[source]

Compute joint moments E[X_0^i * X_1^j] of consecutive inter-departure times.

Uses matrix-analytic methods on the QBD representation of a MAP/MAP/1 queue to compute joint factorial moments of pairs of consecutive inter-departure times.

Parameters:
  • MAPa – Arrival MAP as list [D0, D1] of numpy arrays.

  • MAPs – Service MAP as list [D0, D1] of numpy arrays.

  • iset – Array of shape (K, 2) where each row [i, j] specifies the moment orders for E[X_0^i * X_1^j].

Returns:

1D numpy array of length K with the computed joint moments.

map_ccdf_derivative(MAP, i)[source]

Compute derivative at zero of a MAP’s complementary CDF.

Calculates the i-th derivative at t=0 of the complementary cumulative distribution function (CCDF) of the inter-arrival time distribution.

Formula: ν_i = π_e * D_0^i * e

where π_e is the embedded stationary vector and e is the column vector of ones.

Parameters:
  • MAP (List[numpy.ndarray]) – Markovian Arrival Process as [D0, D1]

  • i (int) – Order of the derivative

Returns:

Value of the i-th derivative at zero

Return type:

float

References

Original MATLAB: matlab/src/api/mam/map_ccdf_derivative.m A. Horvath et al., “A Joint Moments Based Analysis of Networks of MAP/MAP/1 Queues”

map_jointpdf_derivative(MAP, iset)[source]

Compute partial derivative at zero of a MAP’s joint PDF.

Calculates the partial derivative at t=0 of the joint probability density function of consecutive inter-arrival times.

For index set {i_1, i_2, …, i_k}: γ = π_e * D_0^{i_1} * D_1 * D_0^{i_2} * D_1 * … * D_0^{i_k} * D_1 * e

Parameters:
Returns:

Value of the partial derivative at zero

Return type:

float

References

Original MATLAB: matlab/src/api/mam/map_jointpdf_derivative.m A. Horvath et al., “A Joint Moments Based Analysis of Networks of MAP/MAP/1 Queues”

map_factorial_moment(MAP, k)[source]

Compute the k-th factorial moment of a MAP.

The k-th factorial moment is computed using derivatives of the inter-arrival time distribution.

Parameters:
  • MAP (List[numpy.ndarray]) – Markovian Arrival Process as [D0, D1]

  • k (int) – Order of the factorial moment

Returns:

k-th factorial moment

Return type:

float

References

Based on MAP moment formulas from matrix-analytic methods

map_joint_moment(MAP, k, l)[source]

Compute the (k,l)-th joint moment of consecutive inter-arrival times.

E[X_n^k * X_{n+1}^l] for a MAP with inter-arrival times X_n.

Parameters:
  • MAP (List[numpy.ndarray]) – Markovian Arrival Process as [D0, D1]

  • k (int) – Power for first inter-arrival time

  • l (int) – Power for second inter-arrival time

Returns:

Joint moment E[X_n^k * X_{n+1}^l]

Return type:

float

References

Based on joint moment formulas for MAPs

map_m1ps_cdf_respt(C, D, mu, x, epsilon=1e-11, epsilon_prime=1e-10)[source]

Compute complementary sojourn time CDF for MAP/M/1-PS queue.

Based on:

Masuyama, H., & Takine, T. (2003). Sojourn time distribution in a MAP/M/1 processor-sharing queue.

Parameters:
  • C (numpy.ndarray | list) – MAP C matrix (transitions without arrivals).

  • D (numpy.ndarray | list) – MAP D matrix (transitions with arrivals).

  • mu (float) – Service rate (must be > 0).

  • x (numpy.ndarray | list) – Time points for CDF evaluation.

  • epsilon (float) – Queue length truncation parameter.

  • epsilon_prime (float) – Uniformization truncation parameter.

Returns:

Complementary CDF values W_bar(x) = Pr[W > x] at each point in x.

Return type:

numpy.ndarray

Example

>>> # Exponential arrivals (Poisson process with rate lambda=0.5)
>>> C = np.array([[-0.5]])
>>> D = np.array([[0.5]])
>>> mu = 1.0
>>> x = np.array([0.0, 0.5, 1.0, 2.0, 5.0])
>>> cdf = map_m1ps_cdf_respt(C, D, mu, x)
map_compute_R(C, D, mu)[source]

Compute rate matrix R for MAP/M/1 queue.

Computes the minimal nonnegative solution of the matrix equation:

D + R(C - mu*I) + mu*R^2 = 0

This matrix is used in the analysis of MAP/M/1 queues based on quasi-birth-death processes.

Parameters:
  • C (numpy.ndarray | list) – M x M matrix governing MAP transitions without arrivals

  • D (numpy.ndarray | list) – M x M matrix governing MAP transitions with arrivals

  • mu (float) – Service rate (scalar)

Returns:

M x M rate matrix (minimal nonnegative solution)

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/map/map_compute_R.m Masuyama, H., & Takine, T. (2003). Sojourn time distribution in a MAP/M/1 processor-sharing queue.

map_m1ps_h_recursive(C, D, mu, N, K)[source]

Recursive computation of h_{n,k} coefficients for MAP/M/1-PS.

The h_{n,k} vectors satisfy the recursion (Theorem 1 in paper):

h_{n,0} = e (vector of ones), for n = 0, 1, … h_{n,k+1} = 1/(theta+mu) * [n*mu/(n+1) * h_{n-1,k} + (theta*I + C) * h_{n,k}

  • D * h_{n+1,k}]

where h_{-1,k} = 0 for all k

Parameters:
  • C (numpy.ndarray | list) – M x M matrix governing MAP transitions without arrivals

  • D (numpy.ndarray | list) – M x M matrix governing MAP transitions with arrivals

  • mu (float) – Service rate (scalar)

  • N (int) – Maximum value of n to compute (determines rows)

  • K (int) – Maximum value of k to compute (determines columns)

Returns:

2D list h[n][k] of (M,1) arrays containing h_{n,k}

Return type:

list

References

Original MATLAB: matlab/src/api/map/map_m1ps_h_recursive.m Masuyama, H., & Takine, T. (2003).

map_m1ps_sojourn(C, D, mu, x, epsilon=1e-11, epsilon_prime=1e-10)[source]

Compute sojourn time distribution in MAP/M/1-PS queue.

Alias for map_m1ps_cdf_respt.

Parameters:
  • C (numpy.ndarray | list) – MAP C matrix (transitions without arrivals)

  • D (numpy.ndarray | list) – MAP D matrix (transitions with arrivals)

  • mu (float) – Service rate (must be > 0)

  • x (numpy.ndarray | list) – Time points for CDF evaluation

  • epsilon (float) – Queue length truncation parameter

  • epsilon_prime (float) – Uniformization truncation parameter

Returns:

Complementary CDF values W_bar(x) = Pr[W > x]

Return type:

numpy.ndarray

References

Original MATLAB: matlab/src/api/map/map_m1ps_sojourn.m

mmdp_isfeasible(Q, R, tol=1e-10)[source]

Check if (Q, R) defines a valid MMDP.

Requirements: - Q must be a valid generator (square, row sums = 0, proper signs) - R must be diagonal with non-negative entries - Q and R must have compatible dimensions

Parameters:
  • Q (numpy.ndarray) – Generator matrix (n x n)

  • R (numpy.ndarray) – Rate matrix (n x n diagonal) or rate vector (n,)

  • tol (float) – Numerical tolerance for validation

Returns:

True if (Q, R) defines a valid MMDP, False otherwise

Return type:

bool

Examples

>>> Q = np.array([[-0.5, 0.5], [0.3, -0.3]])
>>> R = np.array([[2.0, 0], [0, 5.0]])
>>> mmdp_isfeasible(Q, R)
True

Markov Chain API (line_solver.api.mc)

Markov Chain analysis algorithms.

Native Python implementations for continuous-time and discrete-time Markov chain analysis.

Key algorithms:

ctmc_solve: CTMC steady-state distribution ctmc_transient: CTMC transient analysis ctmc_uniformization: Uniformization method for transient analysis ctmc_foxglynn: Fox-Glynn uniformization for transient analysis ctmc_gmres: Restarted GMRES with ILUT preconditioning ctmc_stochcomp: Stochastic complementation dtmc_solve: DTMC steady-state distribution

ctmc_solve(Q, method=None)[source]

Solve for steady-state probabilities of a CTMC.

Computes the stationary distribution π by solving πQ = 0 with normalization constraint Σπ = 1.

Handles reducible CTMCs by decomposing into strongly connected components and solving each separately.

Parameters:
  • Q (numpy.ndarray) – Infinitesimal generator matrix (row sums should be zero)

  • method (str | None) – ‘gmres’ or ‘direct’ to force a solution method; None or ‘default’ selects by size, GMRES above GMRES_MIN_STATES states

Returns:

Steady-state probability distribution (1D array)

Return type:

numpy.ndarray

ctmc_solve_reducible(Q, pin=None)[source]

Solve reducible CTMCs by converting to DTMC via uniformization.

Port of MATLAB ctmc_solve_reducible.m, which is a thin delegate to dtmc_solve_reducible(ctmc_randomization(Q), pin, tol=1e-12). The whole convention for a reducible chain therefore lives in dtmc_solve_reducible: the limiting vector of a chain with several closed communicating classes is NOT unique, and it is resolved by starting uniformly over the SCCs and propagating through the lumped limiting matrix (so, when every SCC is closed, each class carries equal weight).

This formerly delegated to ctmc_solve, which just returns whichever null vector the linear solver happens to land on – for two closed classes that is all the mass on the first, disagreeing with MATLAB and the JAR.

Parameters:
  • Q (numpy.ndarray) – Infinitesimal generator matrix (possibly reducible)

  • pin (numpy.ndarray | None) – Initial probability vector, or None when not available

Returns:

Steady-state probability vector

Return type:

numpy.ndarray

ctmc_makeinfgen(Q)[source]

Convert a matrix into a valid infinitesimal generator for a CTMC.

An infinitesimal generator has: - Row sums equal to zero - Non-positive diagonal elements - Non-negative off-diagonal elements

Parameters:

Q – Candidate infinitesimal generator matrix

Returns:

Valid infinitesimal generator matrix with corrected diagonal

ctmc_transient(Q, initial_dist, time_points, method='expm')[source]

Compute transient probabilities of a CTMC.

Calculates time-dependent state probabilities π(t) for specified time points using matrix exponential methods.

Parameters:
  • Q (numpy.ndarray) – Infinitesimal generator matrix

  • initial_dist (numpy.ndarray) – Initial probability distribution π(0)

  • time_points (float | numpy.ndarray) – Array of time points to evaluate, or single time value

  • method (str) – ‘expm’ for matrix exponential, ‘ode’ for ODE solver

Returns:

Transient probabilities at each time point. Shape: (len(time_points), n) if multiple times, (n,) if single time

Return type:

numpy.ndarray

ctmc_timeaverage(pi0, Q, t, tol=1e-12, maxiter=100)[source]

Time-averaged transient distribution of a CTMC over [0, t] via uniformization.

Companion of the endpoint pi0*exp(Q*t); additionally returns the time average

piTimeAvg = pi0 * (1/t) * int_0^t exp(Q*tau) d(tau)

as well as the endpoint piExit = pi0*exp(Q*t), both from the same Jensen uniformization series. Used by the SolverENV state-vector analyzer (deterministic-sojourn option). Mirrors matlab ctmc_timeaverage.m.

Returns:

(piTimeAvg, piExit) as 1D arrays.

ctmc_uniformization(Q, lambda_rate=None)[source]

Uniformize CTMC generator matrix.

Converts CTMC to an equivalent uniformized discrete-time chain for numerical analysis and simulation purposes.

The uniformized DTMC has transition matrix P = I + Q/λ where λ is the uniformization rate (max exit rate).

Parameters:
  • Q (numpy.ndarray) – Infinitesimal generator matrix

  • lambda_rate (float | None) – Uniformization rate (optional, auto-computed if None)

Returns:

  • ‘P’: Uniformized transition matrix

  • ’lambda’: Uniformization rate

Return type:

dict containing

ctmc_foxglynn(pi0, Q, t, tol=1e-12, maxiter=-1)[source]

Transient distribution of a CTMC by Fox-Glynn uniformization.

Parameters:
  • pi0 (numpy.ndarray) – Initial probability distribution

  • Q (numpy.ndarray) – Infinitesimal generator matrix

  • t (float) – Transient analysis period boundary [0,t]

  • tol (float) – Poisson tail-mass truncation tolerance

  • maxiter (int) – Maximum truncation depth; pass a nonpositive value to let the Fox-Glynn right truncation point size it

Returns:

Transient probability vector at time t

Return type:

numpy.ndarray

ctmc_foxglynn_weights(lam, tol=1e-12, maxiter=-1)[source]

Fox-Glynn truncation window and normalized Poisson weights.

Following Fox-Glynn, the weights are built by the two-sided recursion w[k-1] = w[k]*k/lam and w[k+1] = w[k]*lam/(k+1) anchored at the mode, so neither exp(-lam) nor lam^k/k! is ever evaluated and the overflow and underflow that limit the direct series cannot occur. Anchoring at w[mode] = 1 keeps the extreme weights near tol, far above the denormal threshold, making Fox and Glynn’s rescaling of the mode weight unnecessary here. The normalizing sum is accumulated in increasing order of magnitude.

Parameters:
  • lam (float) – Poisson rate, that is the uniformization constant times the horizon

  • tol (float) – Poisson tail-mass truncation tolerance

  • maxiter (int) – Cap on the right truncation point; nonpositive leaves it uncapped

Returns:

Tuple of (left truncation point, right truncation point, weights)

Return type:

Tuple[int, int, numpy.ndarray]

ctmc_gmres(A, b, tol=None, restart=None, maxit=None, x0=None)[source]

Solve the sparse nonsymmetric system A*x = b by restarted GMRES.

Parameters:
  • A – Coefficient matrix, dense or sparse. Converted to CSC internally.

  • b – Right-hand side

  • tol (float | None) – Relative residual tolerance (default 1e-12)

  • restart (int | None) – Krylov subspace dimension between restarts (default min(n, 50))

  • maxit (int | None) – Maximum number of restart cycles (default ceil(n/restart))

  • x0 – Initial guess (default uniform 1/n)

Returns:

(x, flag, relres, iter), where flag follows the MATLAB gmres convention: 0 converged, 1 iteration limit reached, 2 preconditioner ill-conditioned, 3 stagnation or breakdown. Callers must check flag and fall back to the direct solve when it is nonzero.

Return type:

Tuple[numpy.ndarray, int, float, int]

ctmc_gmres_multi(A, B, tol=None, restart=None, maxit=None)[source]

Solve A*X = B for every column of B, reusing one ILUT factorization across all of them and starting each column from the previous solution.

This is the shape of the stochastic complement, whose right-hand side is a whole block of the generator: refactorizing per column would cost more than the direct solve it replaces.

Parameters:
  • A – Coefficient matrix, dense or sparse

  • B – Right-hand sides, one per column

  • tol (float | None) – Relative residual tolerance (default 1e-12)

  • restart (int | None) – Krylov subspace dimension between restarts

  • maxit (int | None) – Maximum number of restart cycles

Returns:

(X, flag). flag is 0 only if every column converged; on any other value X is None and the caller must fall back to the direct solve. Returning a partial block would leave that fallback ambiguous.

ctmc_randomization(Q, initial_dist, time_points, precision=1e-10)[source]

Compute CTMC transient probabilities using randomization.

Uses Jensen’s randomization method (uniformization) to compute transient probabilities by converting the CTMC to a uniformized DTMC.

This method is numerically stable and avoids matrix exponentials.

Parameters:
  • Q (numpy.ndarray) – Infinitesimal generator matrix

  • initial_dist (numpy.ndarray) – Initial probability distribution

  • time_points (numpy.ndarray) – Array of time points to evaluate

  • precision (float) – Numerical precision for truncation (Poisson tail)

Returns:

Transient probabilities at each time point

Return type:

numpy.ndarray

ctmc_stochcomp(Q, I=None)[source]

Compute stochastic complement of CTMC.

Reduces the CTMC by eliminating states not in I while preserving the steady-state distribution restricted to the kept states.

Parameters:
  • Q (numpy.ndarray) – Infinitesimal generator matrix

  • I (numpy.ndarray | None) – States to retain (array of indices). If None, defaults to 0..ceil(n/2)-1 (matching JAR/MATLAB).

Returns:

  • ‘S’: Stochastic complement (reduced generator)

  • ’Q11’: Submatrix for kept states

  • ’Q12’: Transitions from kept to eliminated

  • ’Q21’: Transitions from eliminated to kept

  • ’Q22’: Submatrix for eliminated states

  • ’T’: Transient contribution matrix

Return type:

dict containing

ctmc_timereverse(Q, pi=None)[source]

Compute time-reversed CTMC generator.

The time-reversed generator Q* has elements: Q*_{ij} = π_j * Q_{ji} / π_i

Parameters:
  • Q (numpy.ndarray) – Original infinitesimal generator matrix

  • pi (numpy.ndarray | None) – Steady-state distribution (optional, computed if None)

Returns:

Time-reversed generator matrix

Return type:

numpy.ndarray

ctmc_rand(n, density=0.3, max_rate=10.0)[source]

Generate random CTMC generator matrix.

Parameters:
  • n (int) – Number of states

  • density (float) – Sparsity density (0 to 1, default 0.3)

  • max_rate (float) – Maximum transition rate (default 10.0)

Returns:

Random infinitesimal generator matrix

Return type:

numpy.ndarray

ctmc_simulate(Q, initial_state, max_time, max_events=10000, seed=None)[source]

Simulate CTMC sample path using Gillespie algorithm.

Generates a realization of the continuous-time Markov chain using the next-reaction method.

Parameters:
  • Q (numpy.ndarray) – Infinitesimal generator matrix

  • initial_state (int) – Starting state (integer index)

  • max_time (float) – Maximum simulation time

  • max_events (int) – Maximum number of transitions (default: 10000)

  • seed (int | None) – Random seed for reproducibility (optional)

Returns:

  • ‘states’: Array of visited states

  • ’times’: Array of transition times

  • ’sojourn_times’: Time spent in each state

Return type:

dict with

ctmc_isfeasible(Q, tolerance=1e-10)[source]

Check if matrix is a valid CTMC infinitesimal generator.

Validates: - Off-diagonal elements are non-negative - Row sums are zero - Diagonal elements are non-positive

Parameters:
  • Q (numpy.ndarray) – Candidate generator matrix

  • tolerance (float) – Numerical tolerance (default: 1e-10)

Returns:

True if matrix is valid CTMC generator

Return type:

bool

ctmc_ssg(sn, options=None)[source]

Generate complete CTMC state space for a queueing network.

Creates all possible network states including those not reachable from the initial state. For open classes, a cutoff parameter limits the maximum population to keep state space finite.

The state space is aggregated to show per-station-class job counts.

Parameters:
  • sn (Any) – NetworkStruct object (from getStruct())

  • options (Dict | None) – Solver options dict with fields: - cutoff: Population cutoff for open classes (required if open) - config.hide_immediate: Hide immediate transitions (default True)

Returns:

  • state_space: Complete state space matrix (rows=states, cols=state components)

  • state_space_aggr: Aggregated state space (rows=states, cols=stations*classes)

  • state_space_hashed: Hashed state indices for lookup

  • node_state_space: Dictionary of per-node state spaces

  • sn: Updated network structure with space field populated

Return type:

CtmcSsgResult containing

References

MATLAB: matlab/src/api/mc/ctmc_ssg.m

ctmc_ssg_reachability(sn, options=None)[source]

Generate reachable CTMC state space for a queueing network.

Creates only the states reachable from the initial state through valid transitions. This is more efficient than ctmc_ssg for networks with constrained reachability.

Parameters:
  • sn (Any) – NetworkStruct object (from getStruct())

  • options (Dict | None) – Solver options dict with fields: - config.hide_immediate: Hide immediate transitions (default True)

Returns:

  • state_space: Reachable state space matrix

  • state_space_aggr: Aggregated state space (per station-class)

  • state_space_hashed: Hashed state indices

  • node_state_space: Dictionary of per-node state spaces

  • sn: Updated network structure

Return type:

CtmcSsgResult containing

References

MATLAB: matlab/src/api/mc/ctmc_ssg_reachability.m

ctmc_memory_gate(log_nstates, force=False, verbose=False, safety_fraction=0.6)[source]

Hardware-aware, profiling-calibrated CTMC memory pre-gate.

Decides whether a CTMC steady-state solve of a state space of worst-case size exp(log_nstates) is safe on the current host. The budget is a fraction of available memory; the per-state cost is calibrated by profiling sparse LU factorization and cached per machine.

Parameters:
  • log_nstates (float) – log(number of states) in the CTMC

  • force (bool) – If True, override the memory limit and proceed anyway

  • verbose (bool) – If True, print calibration and memory predictions

  • safety_fraction (float) – Fraction of available memory to use as safe budget (default 0.6)

Returns:

  • ok (bool): True if solve is safe, False if memory exceeded (and force=False)

  • msg (str): Status or warning message

Return type:

Tuple (ok, msg) where

class CtmcSsgResult(state_space, state_space_aggr, state_space_hashed, node_state_space, sn)[source]

Bases: object

Result from CTMC state space generation.

state_space: numpy.ndarray
state_space_aggr: numpy.ndarray
state_space_hashed: numpy.ndarray
node_state_space: Dict[int, numpy.ndarray]
sn: Any
dtmc_solve(P)[source]

Solve for steady-state probabilities of a DTMC.

Computes the stationary distribution π by solving π(P - I) = 0 with normalization constraint Σπ = 1.

This leverages the CTMC solver by treating (P - I) as an infinitesimal generator.

Parameters:

P (numpy.ndarray) – Transition probability matrix (row stochastic)

Returns:

Steady-state probability distribution (1D array)

Return type:

numpy.ndarray

dtmc_solve_reducible(P, pin=None)[source]

Solve reducible DTMCs with transient states.

Handles DTMCs with multiple recurrent classes and transient states by: 1. Decomposing into strongly connected components (SCCs) 2. Identifying recurrent vs transient SCCs 3. Computing limiting distribution considering absorption from transient states

For a reducible DTMC with a single transient SCC, this computes the limiting distribution when starting from the transient states (e.g., class switching networks where jobs start in a transient class).

Parameters:
  • P (numpy.ndarray) – Transition probability matrix (possibly reducible)

  • pin (numpy.ndarray) – Initial probability vector (optional)

Returns:

Steady-state probability vector

Return type:

numpy.ndarray

dtmc_makestochastic(A)[source]

Convert matrix to row-stochastic transition matrix.

Normalizes each row to sum to 1. Rows with zero sum are replaced with uniform distribution.

Parameters:

A (numpy.ndarray) – Input matrix to normalize

Returns:

Row-stochastic matrix

Return type:

numpy.ndarray

dtmc_isfeasible(P, tolerance=1e-10)[source]

Check if matrix is a valid DTMC transition matrix.

Validates: - All elements are non-negative - All row sums equal 1

Parameters:
  • P (numpy.ndarray) – Candidate transition matrix

  • tolerance (float) – Numerical tolerance (default: 1e-10)

Returns:

True if matrix is valid DTMC transition matrix

Return type:

bool

dtmc_simulate(P, initial_state, num_steps, seed=None)[source]

Simulate DTMC sample path.

Generates a realization of the discrete-time Markov chain for a specified number of steps.

Parameters:
  • P (numpy.ndarray) – Transition probability matrix

  • initial_state (int) – Starting state index

  • num_steps (int) – Number of simulation steps

Returns:

Array of visited states (length num_steps + 1)

Return type:

numpy.ndarray

dtmc_rand(n, density=0.5)[source]

Generate random DTMC transition matrix.

Parameters:
  • n (int) – Number of states

  • density (float) – Sparsity density (0 to 1, default 0.5)

Returns:

Random transition probability matrix

Return type:

numpy.ndarray

dtmc_timereverse(P, pi=None)[source]

Compute time-reversed DTMC transition matrix.

The time-reversed chain has transition probabilities: P*_{ij} = π_j * P_{ji} / π_i

Parameters:
  • P (numpy.ndarray) – Original transition matrix

  • pi (numpy.ndarray | None) – Steady-state distribution (optional, computed if None)

Returns:

Time-reversed transition matrix

Return type:

numpy.ndarray

dtmc_stochcomp(P, keep_states, eliminate_states=None)[source]

Compute stochastic complement of DTMC.

Reduces the DTMC by eliminating specified states while preserving the steady-state distribution restricted to the kept states.

Parameters:
  • P (numpy.ndarray) – Transition probability matrix

  • keep_states (numpy.ndarray) – States to retain in reduced model

  • eliminate_states (numpy.ndarray | None) – States to eliminate (optional, inferred if None)

Returns:

Reduced transition matrix (stochastic complement)

Return type:

numpy.ndarray

dtmc_transient(P, initial_dist, steps)[source]

Compute transient probabilities of a DTMC.

Calculates π(n) = π(0) * P^n for each step from 0 to steps.

Parameters:
  • P (numpy.ndarray) – Transition probability matrix

  • initial_dist (numpy.ndarray) – Initial probability distribution π(0)

  • steps (int) – Number of time steps

Returns:

Array of shape (steps+1, n) with transient probabilities

Return type:

numpy.ndarray

dtmc_hitting_time(P, target_states)[source]

Compute mean hitting times to target states.

Calculates the expected number of steps to reach any target state from each starting state.

Parameters:
Returns:

Array of mean hitting times from each state

Return type:

numpy.ndarray

class CourtoisResult(p, Qperm, Qdec, eps, epsMAX, P, B, q)[source]

Bases: object

Result of Courtois decomposition.

p: numpy.ndarray
Qperm: numpy.ndarray
Qdec: numpy.ndarray
eps: float
epsMAX: float
P: numpy.ndarray
B: numpy.ndarray
q: float
class KMSResult(p, p_1, Qperm, eps, epsMAX, pcourt)[source]

Bases: object

Result of KMS aggregation-disaggregation.

p: numpy.ndarray
p_1: numpy.ndarray
Qperm: numpy.ndarray
eps: float
epsMAX: float
pcourt: numpy.ndarray
class TakahashiResult(p, p_1, pcourt, Qperm, eps, epsMAX)[source]

Bases: object

Result of Takahashi aggregation-disaggregation.

p: numpy.ndarray
p_1: numpy.ndarray
pcourt: numpy.ndarray
Qperm: numpy.ndarray
eps: float
epsMAX: float
ctmc_courtois(Q, MS, q=None)[source]

Courtois decomposition for near-completely decomposable CTMCs.

Decomposes a large CTMC into macrostates and computes approximate steady-state probabilities using hierarchical aggregation.

Parameters:
  • Q (numpy.ndarray) – Infinitesimal generator matrix

  • MS (List[List[int]]) – List where MS[i] is the list of state indices in macrostate i

  • q (float | None) – Randomization coefficient (optional)

Returns:

CourtoisResult with approximate solution and diagnostics

Return type:

CourtoisResult

References

Original MATLAB: matlab/src/api/mc/ctmc_courtois.m Courtois, “Decomposability: Queueing and Computer System Applications”, 1977

ctmc_kms(Q, MS, numSteps=10)[source]

Koury-McAllister-Stewart aggregation-disaggregation method.

Iteratively refines the Courtois decomposition solution using aggregation and disaggregation steps.

Parameters:
  • Q (numpy.ndarray) – Infinitesimal generator matrix

  • MS (List[List[int]]) – List where MS[i] is the list of state indices in macrostate i

  • numSteps (int) – Number of iterative steps (default: 10)

Returns:

KMSResult with refined solution

Return type:

KMSResult

References

Original MATLAB: matlab/src/api/mc/ctmc_kms.m Koury, McAllister, Stewart, “Iterative Methods for Computing Stationary Distributions of Nearly Completely Decomposable Markov Chains”, 1984

ctmc_takahashi(Q, MS, numSteps=10)[source]

Takahashi’s aggregation-disaggregation method.

Iteratively refines the Courtois decomposition solution using a different aggregation-disaggregation scheme.

Parameters:
  • Q (numpy.ndarray) – Infinitesimal generator matrix

  • MS (List[List[int]]) – List where MS[i] is the list of state indices in macrostate i

  • numSteps (int) – Number of iterative steps (default: 10)

Returns:

TakahashiResult with refined solution

Return type:

TakahashiResult

References

Original MATLAB: matlab/src/api/mc/ctmc_takahashi.m Takahashi, “A Lumping Method for Numerical Calculations of Stationary Distributions of Markov Chains”, 1975

ctmc_multi(Q, MS, MSS)[source]

Multigrid aggregation-disaggregation method.

Two-level hierarchical decomposition using nested macrostates.

Parameters:
  • Q (numpy.ndarray) – Infinitesimal generator matrix

  • MS (List[List[int]]) – List where MS[i] is the list of state indices in macrostate i

  • MSS (List[List[int]]) – List where MSS[i] is the list of macrostate indices in macro-macrostate i

Returns:

TakahashiResult with multigrid solution

Return type:

TakahashiResult

References

Original MATLAB: matlab/src/api/mc/ctmc_multi.m

Queueing Systems (line_solver.api.qsys)

Native Python implementations for queueing system analysis.

This module provides pure Python/NumPy implementations for analyzing single queueing systems, including basic queues (M/M/1, M/M/k, M/G/1), G/G/1 approximations, MAP-based queues, and scheduling disciplines.

Key algorithms:

Basic queues: qsys_mm1, qsys_mmk, qsys_mg1, qsys_gm1, qsys_mminf, qsys_mginf G/G/1 approximations: Allen-Cunneen, Kingman, Marchal, Whitt, Heyman, etc. G/G/k approximations: qsys_gigk_approx MAP/D queues: qsys_mapdc, qsys_mapd1 MAP/PH queues: qsys_phph1, qsys_mapph1, qsys_mapm1, qsys_mapmc, qsys_mapmap1 Scheduling: qsys_mg1_prio, qsys_mg1_srpt, qsys_mg1_fb, etc. Loss systems: qsys_mm1k_loss, qsys_mg1k_loss, qsys_mxm1 Discrete time (slotted): qsys_geogeo1, qsys_geoxgeo1

qsys_mapdc(D0, D1, s, c, max_num_comp=1000, num_steps=1, verbose=0)[source]

Analyze MAP/D/c queue (MAP arrivals, deterministic service, c servers).

Uses Non-Skip-Free (NSF) Markov chain analysis embedding at deterministic service intervals. Multiple arrivals can occur per interval.

Parameters:
  • D0 (numpy.ndarray) – MAP hidden transition matrix (n x n).

  • D1 (numpy.ndarray) – MAP arrival transition matrix (n x n).

  • s (float) – Deterministic service time (positive scalar).

  • c (int) – Number of servers.

  • max_num_comp (int) – Maximum number of queue length components (default 1000).

  • num_steps (int) – Number of waiting time distribution points per interval (default 1).

  • verbose (int) – Verbosity level (default 0).

Returns:

Performance metrics including:
  • mean_queue_length: Mean number of customers in system

  • mean_waiting_time: Mean waiting time in queue

  • mean_sojourn_time: Mean sojourn time (waiting + service)

  • utilization: Server utilization (per server)

  • queue_length_dist: Queue length distribution P(Q=n)

  • waiting_time_dist: Waiting time CDF at discrete points

  • analyzer: Analyzer identifier

Return type:

dict

qsys_mapd1(D0, D1, s, max_num_comp=1000, num_steps=1)[source]

Analyze MAP/D/1 queue (single-server convenience function).

Parameters:
  • D0 (numpy.ndarray) – MAP hidden transition matrix.

  • D1 (numpy.ndarray) – MAP arrival transition matrix.

  • s (float) – Deterministic service time.

  • max_num_comp (int) – Maximum number of queue length components.

  • num_steps (int) – Number of waiting time points per interval.

Returns:

Performance metrics (see qsys_mapdc).

Return type:

dict

qsys_mdc_crommelin(lambda_arr, s, c, truncation=-1)[source]

Solve M/D/c via Crommelin’s embedded DTMC.

Parameters:
  • lambda_arr (float) – Poisson arrival rate.

  • s (float) – Deterministic service time (>0).

  • c (int) – Number of servers (>=1).

  • truncation (int) – Optional state-space truncation level. If <=0, chosen automatically to keep dense LU manageable.

Returns:

mean_queue_length: E[N] (number in system) mean_waiting_queue: Lq = E[(N-c)+] mean_waiting_time: Wq = Lq / lambda mean_sojourn_time: W = Wq + s utilization: rho = lambda * s / c

Return type:

dict with keys

qsys_dmc(lambda_arr, mu, c, truncation=-1, quad_steps=200)[source]

Solve D/M/c via embedded DTMC at arrival epochs.

Parameters:
  • lambda_arr (float) – Arrival rate (deterministic interarrivals of mean 1/lambda).

  • mu (float) – Service rate per server.

  • c (int) – Number of servers.

  • truncation (int) – Optional state-space truncation. Auto-chosen if <=0.

  • quad_steps (int) – Number of trapezoidal-rule steps for cycle integration.

Returns:

dict with mean_queue_length, mean_waiting_queue, mean_waiting_time, mean_sojourn_time, utilization.

Return type:

Dict

qsys_phm1(alpha, T, mu)[source]

Solve PH/M/1 via the GI/M/1 sigma-root.

Parameters:
  • alpha – PH entry probability vector (length k).

  • T – PH sub-generator matrix (k x k), row sums <= 0.

  • mu (float) – Exponential service rate (>0).

Returns:

dict with mean_queue_length, mean_waiting_queue, mean_waiting_time, mean_sojourn_time, utilization, sigma.

Return type:

Dict

qsys_phmc(alpha, T, mu, c, max_iter=50000, tol=1e-14)[source]

Solve PH/M/c via matrix-geometric.

Parameters:
  • alpha – PH entry probability vector (length k).

  • T – PH sub-generator matrix (k x k), row sums <= 0.

  • mu (float) – Exponential service rate per server (>0).

  • c (int) – Number of servers (>=1).

  • max_iter (int) – Maximum iterations for R fixed-point.

  • tol (float) – Convergence tolerance for R.

Returns:

dict with mean_queue_length, mean_waiting_queue, mean_waiting_time, mean_sojourn_time, utilization.

Return type:

Dict

qsys_geogeo1(a, s, convention=LAS_DA)[source]

Analyze a discrete-time Geo/Geo/1 queue.

In each slot an arrival occurs with probability a and, if the server is engaged, a service completion occurs with probability s, independently of everything else. The system content at slot boundaries is a discrete birth-death chain with a geometric stationary distribution.

The two conventions are not two systems. They are one system, Daduna’s LA-rule (events at the end of their slot) with the D/A-rule (departure resolved before arrival), observed at two instants. With X(t+1) = X(t) - D(t) + A(t), LAS_DA is the law of X, taken after both events, and EAS is the law of Y(t) = X(t) - D(t), taken after the departure and before the arrival. They are one departure apart, so the mean contents differ by exactly a and the sojourn times by one slot; the queueing delay is the same under both.

Parameters:
  • a (float) – Per-slot arrival probability, 0 < a < s

  • s (float) – Per-slot service completion probability, 0 < s <= 1

  • convention (str) – Observation epoch, ‘LAS_DA’ (default) or ‘EAS’

Returns:

  • convention: epoch used

  • arrivalProb, serviceProb: the inputs

  • utilization: a/s

  • throughput: a

  • emptyProb: probability the system is empty at the epoch

  • ratio: geometric decay ratio r = a(1-s)/(s(1-a))

  • meanQueueLength, meanWaitingQueue

  • meanSojournTime, meanWaitingTime, meanServiceTime

  • pmf: callable n -> stationary probability of n jobs

  • analyzer: ‘qsys_geogeo1’

Return type:

dict with keys

Example

>>> r = qsys_geogeo1(0.2, 0.5)
>>> print(f"{r['meanSojournTime']:.4f}")
2.6667
qsys_geoxgeo1(a, beta, s, convention=LAS_DA)[source]

Analyze a discrete-time Geo^X/Geo/1 queue with geometric batch sizes.

In each slot a batch arrives with probability a; the batch size is geometric on {1,2,…} with parameter beta, so E[X] = 1/beta and E[X(X-1)] = 2(1-beta)/beta**2. Stability requires lambda = a*E[X] < s. At beta == 1 the batch is always a single job and the result equals qsys_geogeo1().

Parameters:
  • a (float) – Per-slot probability that a batch arrives, 0 < a <= 1

  • beta (float) – Batch-size geometric parameter, 0 < beta <= 1

  • s (float) – Per-slot service completion probability, 0 < s <= 1

  • convention (str) – Observation epoch, ‘LAS_DA’ (default) or ‘EAS’

Returns:

dict, see qsys_geoxgeo1_moments()

Return type:

Dict[str, object]

Example

>>> r = qsys_geoxgeo1(0.1, 0.5, 0.9)
>>> print(f"{r['arrivalRate']:.4f}")
0.2000
qsys_geoxgeo1_moments(a, batch_mean, batch_second_factorial, s, convention=LAS_DA)[source]

Analyze a discrete-time Geo^X/Geo/1 queue for an arbitrary batch law.

The batch enters the solution only through its first two factorial moments, so specifying those is fully general. With A(z) = 1-a+a*X(z) the pgf of the number of jobs arriving in one slot, the slot-boundary content obeys X(t+1) = X(t) - D(t) + A(t) with the departure resolved first, giving:

P(z) = p0 s (z-1) A(z) / ( z - A(z)(s+(1-s)z) ),  p0 = 1 - lambda/s
E[N] = lambda + ( a E[X(X-1)]/2 + lambda(1-s) ) / (s - lambda)
Parameters:
  • a (float) – Per-slot probability that a batch arrives, 0 < a <= 1

  • batch_mean (float) – E[X], at least 1 since an arriving batch carries a job

  • batch_second_factorial (float) – E[X(X-1)], non-negative and at least batch_mean**2 - batch_mean

  • s (float) – Per-slot service completion probability, 0 < s <= 1

  • convention (str) – Observation epoch, ‘LAS_DA’ (default) or ‘EAS’

Returns:

  • convention, batchArrivalProb, batchMean, batchSecondFactorialMoment, serviceProb

  • arrivalRate, throughput: lambda = a*E[X]

  • utilization: lambda/s

  • boundaryEmptyProb: 1 - lambda/s, the empty probability AT THE SLOT BOUNDARY under both conventions

  • meanQueueLength, meanWaitingQueue

  • meanSojournTime, meanWaitingTime, meanServiceTime

  • pgf: callable (z, A_of_z) -> P(z), defined for 0 < z <= 1

  • analyzer: ‘qsys_geoxgeo1’

Return type:

dict with keys

No pmf is returned: for a general batch law the stationary distribution has no elementary closed form, so only the generating function is exact.

qsys_mm1(lambda_val, mu)[source]

Analyze M/M/1 queue (Poisson arrivals, exponential service).

Parameters:
  • lambda_val (float) – Arrival rate (lambda)

  • mu (float) – Service rate

Returns:

Performance measures including:
  • L: Mean number in system

  • Lq: Mean number in queue

  • W: Mean response time (time in system)

  • Wq: Mean waiting time (time in queue)

  • rho: Utilization (lambda/mu)

Return type:

dict

Example

>>> result = qsys_mm1(0.5, 1.0)
>>> print(f"Utilization: {result['rho']:.2f}")
Utilization: 0.50
qsys_mmk(lambda_val, mu, k)[source]

Analyze M/M/k queue (Poisson arrivals, k exponential servers).

Parameters:
  • lambda_val (float) – Arrival rate (lambda)

  • mu (float) – Service rate per server

  • k (int) – Number of parallel servers

Returns:

Performance measures including:
  • L: Mean number in system

  • Lq: Mean number in queue

  • W: Mean response time

  • Wq: Mean waiting time

  • rho: Utilization per server (lambda/(k*mu))

  • P0: Probability of empty system

Return type:

dict

Example

>>> result = qsys_mmk(2.0, 1.0, 3)
>>> print(f"Utilization: {result['rho']:.2f}")
Utilization: 0.67
qsys_mmck(lambda_val, mu, c, K)[source]

Exact closed-form analysis of an M/M/c/K queue (finite capacity K, c servers).

Port of MATLAB qsys_mmck.m. Stationary distribution (truncated Erlang form):

a = lambda/mu, rho = a/c p_n = a^n/n! * p0 for 0 <= n <= c p_n = a^c/c! * rho^(n-c) * p0 for c <= n <= K

with p0 normalizing the (K+1)-point distribution.

Parameters:
  • lambda_val (float) – Poisson arrival rate (> 0)

  • mu (float) – Per-server exponential service rate (> 0)

  • c (int) – Number of servers (>= 1)

  • K (int) – System capacity, total jobs allowed (K >= c)

Returns:

dict with L, Lq, W, Wq, rho, P0 plus MATLAB-style aliases (meanQueueLength, meanQueueLengthQ, meanWaitingTime, meanSojournTime, utilization, throughput, lossProbability, queueLengthDist).

Return type:

Dict[str, float]

qsys_mg1(lambda_val, mu, cs)[source]

Analyze M/G/1 queue using Pollaczek-Khinchine formula.

Parameters:
  • lambda_val (float) – Arrival rate (lambda)

  • mu (float) – Service rate (mean service time = 1/mu)

  • cs (float) – Coefficient of variation of service time (std/mean)

Returns:

Performance measures including:
  • L: Mean number in system

  • Lq: Mean number in queue

  • W: Mean response time

  • Wq: Mean waiting time

  • rho: Utilization (lambda/mu)

Return type:

dict

Example

>>> result = qsys_mg1(0.5, 1.0, 1.0)  # cs=1 is exponential (M/M/1)
qsys_gm1(sigma, mu)[source]

Analyze G/M/1 queue (general arrivals, exponential service).

Matches MATLAB qsys_gm1(sigma, mu) and JAR Qsys_gm1: the number of customers found by an arrival is geometric with parameter sigma, so the mean response time (time in system) is W = 1/(mu*(1-sigma)).

Parameters:
  • sigma (float) – Root in (0,1) of sigma = A*(mu*(1-sigma)), where A* is the Laplace-Stieltjes transform of the interarrival-time distribution.

  • mu (float) – Service rate

Returns:

{‘W’: mean response time}

Return type:

dict

Note

To obtain sigma from the first two moments of the interarrival time, use qsys_gg1(lambda_val, mu, ca2, 1.0), which fits a two-moment renewal process and solves the fixed point.

qsys_mminf(lambda_val, mu)[source]

Analyze M/M/inf queue (infinite servers / delay station).

Parameters:
  • lambda_val (float) – Arrival rate (lambda)

  • mu (float) – Service rate

Returns:

Performance measures including:
  • L: Mean number in system (= lambda/mu)

  • Lq: Mean number in queue (= 0)

  • W: Mean time in system (= 1/mu)

  • Wq: Mean waiting time (= 0)

  • P0: Probability of empty system

Return type:

dict

qsys_mginf(lambda_val, mu, k=None)[source]

Analyze M/G/inf queue (infinite servers, general service).

Performance is independent of service time distribution shape. Number of customers follows Poisson distribution.

Parameters:
  • lambda_val (float) – Arrival rate (lambda)

  • mu (float) – Service rate (mean service time = 1/mu)

  • k (int | None) – Optional state for probability computation

Returns:

Performance measures including:
  • L: Mean number in system

  • Lq: Mean number in queue (= 0)

  • W: Mean time in system (= 1/mu)

  • Wq: Mean waiting time (= 0)

  • P0: Probability of empty system

  • Pk: Probability of k customers (if k provided)

Return type:

dict

qsys_mmcc_retrial_fp(lambda_val, mu, c, tol=1e-10, maxiter=10000)[source]

Fixed-point approximation for M/M/c/c retrial queue.

Customers arrive at rate lambda to a system with c servers (no waiting room), each with service rate mu. Blocked customers join an orbit and retry. Under the assumption that the retrial rate is small relative to the service rate, the total arrival flow (fresh + retrial) is approximated by a Poisson process with rate lambda + r, where r satisfies the fixed-point equation:

r = (lambda + r) * B((lambda + r) / mu, c)

and B(a, c) is the Erlang-B blocking probability for offered load a and c servers.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate per server

  • c (int) – Number of servers (= capacity, no waiting room)

  • tol (float) – Convergence tolerance (default: 1e-10)

  • maxiter (int) – Maximum iterations (default: 10000)

Returns:

Performance measures including:
  • blocProb: Blocking probability

  • r: Additional arrival rate due to retrials

  • niter: Number of iterations to converge

  • rho: Offered load (lambda / (c * mu))

  • L: Mean number of busy servers

Return type:

dict

References

Cohen (1957), fixed-point approximation for M/M/c/c retrial queues. Phung-Duc, “Retrial Queueing Models: A Survey on Theory and Applications”, 2019, Eq. (1).

Example

>>> result = qsys_mmcc_retrial_fp(2.0, 1.0, 3)
>>> print(f"Blocking: {result['blocProb']:.4f}")
qsys_gig1_rq(rho, mu, cs2, IaFun)[source]

Robust Queueing (RQ) approximation for a single G/GI/1 queue partially characterized by its arrival rate, index of dispersion for counts (IDC) and the first two moments of the service time. Implements the mean steady-state workload

Z* = sup_{x>=0} { -(1-rho) x + sqrt( 2 rho x (I_a(x) + c2_s) / mu ) }

and the derived steady-state performance measures.

Reference:

W. Whitt and W. You (2018), “A Robust Queueing Network Analyzer Based on Indices of Dispersion”, eqs. (13),(16)-(18).

Parameters:
  • rho (float) – Traffic intensity lambda/mu (0<rho<1)

  • mu (float) – Service rate

  • cs2 (float) – Service SCV c2_s

  • IaFun – callable, IaFun(x) -> arrival IDC I_a(x) at time argument x>0

Returns:

Tuple (Z, W, Q, X) with mean workload E[Z], waiting time E[W], queue length E[Q] (waiting + in service), and number in system E[X].

qsys_gig1_approx_allencunneen(lambda_val, mu, ca, cs)[source]

Allen-Cunneen approximation for G/G/1 queue.

Matches MATLAB qsys_gig1_approx_allencunneen.m exactly.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

Returns:

W: Mean response time (time in system) rhohat: Effective utilization (so that M/M/1 formulas still hold)

Return type:

Tuple of (W, rhohat) where

qsys_gig1_approx_kingman(lambda_val, mu, ca, cs)[source]

Kingman’s upper bound approximation for G/G/1 queue.

Note: alias of qsys_gig1_ubnd_kingman (‘gig1.kingman’ method).

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

Returns:

W: Upper bound on mean response time (time in system) rhohat: Effective utilization (so that M/M/1 formulas still hold)

Return type:

Tuple of (W, rhohat) where

qsys_gig1_approx_marchal(lambda_val, mu, ca, cs)[source]

Marchal’s approximation for G/G/1 queue.

Matches MATLAB qsys_gig1_approx_marchal.m exactly. Note: MATLAB formula uses ca (not ca^2) in the numerator factor.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

Returns:

W: Mean response time (time in system) rhohat: Effective utilization (so that M/M/1 formulas still hold)

Return type:

Tuple of (W, rhohat) where

qsys_gig1_approx_whitt(lambda_val, mu, ca, cs)[source]

Whitt’s approximation for G/G/1 queue.

Uses QNA (Queueing Network Analyzer) approximation. Note: No direct MATLAB counterpart (qsys_gig1_approx_whitt.m does not exist).

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

Returns:

W: Mean response time (time in system) rhohat: Effective utilization (so that M/M/1 formulas still hold)

Return type:

Tuple of (W, rhohat) where

qsys_gig1_approx_heyman(lambda_val, mu, ca, cs)[source]

Heyman’s approximation for G/G/1 queue.

Matches MATLAB qsys_gig1_approx_heyman.m exactly.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

Returns:

W: Mean response time (time in system) rhohat: Effective utilization (so that M/M/1 formulas still hold)

Return type:

Tuple of (W, rhohat) where

qsys_gig1_approx_kobayashi(lambda_val, mu, ca, cs)[source]

Kobayashi’s approximation for G/G/1 queue.

Matches MATLAB qsys_gig1_approx_kobayashi.m exactly.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

Returns:

W: Mean response time (time in system) rhohat: Effective utilization

Return type:

Tuple of (W, rhohat) where

qsys_gig1_approx_klb(lambda_val, mu, ca, cs)[source]

Kraemer-Langenbach-Belz (KLB) approximation for G/G/1 queue.

Matches MATLAB qsys_gig1_approx_klb.m exactly.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

Returns:

W: Mean response time (time in system) rhohat: Effective utilization (so that M/M/1 formulas still hold)

Return type:

Tuple of (W, rhohat) where

qsys_gig1_approx_gelenbe(lambda_val, mu, ca, cs)[source]

Gelenbe’s diffusion approximation for G/G/1 with instantaneous-return boundary:

p(0) = 1-rho, p(n) = rho*(1-rhat)*rhat^(n-1), n>=1 rhat = exp(-2*(1-rho)/(rho*ca^2+cs^2))

hence E[N] = rho/(1-rhat) and the mean response time (time in system) is W = E[N]/lambda = 1/(mu*(1-rhat)).

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

Returns:

W: Mean response time (time in system) rhohat: Effective utilization (so that M/M/1 formulas still hold)

Return type:

Tuple of (W, rhohat) where

References

Gelenbe, E. (1975). “On approximate computer system models”. Journal of the ACM 22(2), 261-269.

qsys_gig1_approx_kimura(lambda_val, mu, ca, cs)[source]
Kimura’s diffusion-interpolation approximation for G/G/1:

Wq = rho*(ca^2+cs^2)/(mu*(1-rho)*(1+ca^2))

exact for M/M/1 and M/G/1. The returned W adds the mean service time (response time, time in system).

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

Returns:

W: Mean response time (time in system) rhohat: Effective utilization (so that M/M/1 formulas still hold)

Return type:

Tuple of (W, rhohat) where

References

Kimura, T. (1986). “A two-moment approximation for the mean waiting time in the GI/G/s queue”. Management Science 32(6), 751-763.

qsys_gig1_approx_myskja(lambda_val, mu, ca, cs, q0, qa)[source]
Myskja’s third-moment approximation for G/G/1:

Wq = rho/(2*mu*(1-rho))*((1+cs^2)+(q0/qa)^(1/rho-rho)*(1/rho)*(ca^2-1))

exact for M/G/1 (ca=1). The returned W adds the mean service time (response time, time in system).

Reference: Myskja, A. (1991). “An Experimental Study of a H₂/H₂/1 Queue”. Stochastic Models, 7(4), 571-595.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

  • q0 (float) – Lowest relative third moment for given mean and SCV

  • qa (float) – Third relative moment E[X^3]/6/E[X]^3 of inter-arrival time

Returns:

W: Mean response time (time in system) rhohat: Effective utilization (so that M/M/1 formulas still hold)

Return type:

Tuple of (W, rhohat) where

qsys_gig1_approx_myskja2(lambda_val, mu, ca, cs, q0, qa)[source]

Modified Myskja (Myskja2) approximation for G/G/1, returning the mean response time (time in system). For ca=1 the interpolation parameter theta is a 0/0 form, so the exact M/G/1 result is returned instead (also the interpolation anchor of the method).

Reference: Myskja, A. (1991). “An Experimental Study of a H₂/H₂/1 Queue”. Stochastic Models, 7(4), 571-595.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

  • q0 (float) – Lowest relative third moment for given mean and SCV

  • qa (float) – Third relative moment E[X^3]/6/E[X]^3 of inter-arrival time

Returns:

W: Mean response time (time in system) rhohat: Effective utilization (so that M/M/1 formulas still hold)

Return type:

Tuple of (W, rhohat) where

qsys_gg1(lambda_val, mu, ca2, cs2)[source]

G/G/1 queue analysis using exact methods for special cases and Allen-Cunneen approximation for the general case. In the G/M/1 case, the interarrival-time distribution is fitted from (lambda, ca2) by a two-moment renewal process (H2 with balanced means for ca2>1, mixed Erlang for ca2<1) and sigma is the root of sigma = A*(mu*(1-sigma)), with A* the interarrival-time LST.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca2 (float) – Squared coefficient of variation of inter-arrival time

  • cs2 (float) – Squared coefficient of variation of service time

Returns:

W: Mean response time (time in system) rhohat: Effective utilization

Return type:

Tuple of (W, rhohat) where

References

Original MATLAB: matlab/src/api/qsys/qsys_gg1.m

qsys_gig1_lbnd(lambda_val, mu, ca, cs)[source]

Fundamental theoretical lower bounds for G/G/1 queues.

These are the minimum possible values that performance measures cannot fall below for any realization of the arrival and service processes.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

Returns:

W: Lower bound on mean response time (= 1/mu) rhohat: Effective utilization

Return type:

Tuple of (W, rhohat) where

References

Original JAR: jar/src/main/kotlin/jline/api/qsys/Qsys_gig1_lbnd.kt

qsys_gigk_approx(lambda_val, mu, ca, cs, k)[source]

Approximation for G/G/k queue.

Matches MATLAB qsys_gigk_approx.m formula using alpha-factor correction.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate per server

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

  • k (int) – Number of servers

Returns:

W: Approximate mean response time rhohat: Effective utilization

Return type:

Tuple of (W, rhohat) where

qsys_gigk_approx_cosmetatos(lambda_val, mu, ca, cs, k)[source]

GI/G/k approximation by interpolation of the M/M/k, M/D/k and D/M/k queues (Cosmetatos 1982; Page 1982):

Wq = [ca^2*cs^2 + ca^2*(1-cs^2)*phi1/2
  • (1-ca^2)*cs^2*phi3/2] * Wq(M/M/k)

where phi1 and phi3 are the Cosmetatos (1975) correction factors for M/D/k and D/M/k, with the safeguards of Whitt (1993). The D/D/k corner has Wq=0. The interpolation requires ca^2<=1 and cs^2<=1; outside this region the Lee-Longton scaling Wq = ((ca^2+cs^2)/2)*Wq(M/M/k) is used.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate per server

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

  • k (int) – Number of servers

Returns:

W: Approximate mean response time (time in system) rhohat: Effective utilization

Return type:

Tuple of (W, rhohat) where

References

Cosmetatos, G.P. (1975). “Approximate explicit formulae for the average queueing time in the processes (M/D/r) and (D/M/r)”. INFOR 13, 328-331. Page, E. (1982). “Tables of waiting times for M/M/n, M/D/n and D/M/n and their use to give approximate waiting times in more general queues”. J. Opl. Res. Soc. 33, 453-473.

qsys_gigk_approx_whitt(lambda_val, mu, ca, cs, k)[source]
GI/G/k approximation of Whitt (1993), eqs. (2.16)-(2.25):

Wq = phi(rho,ca^2,cs^2,k) * ((ca^2+cs^2)/2) * Wq(M/M/k)

where phi interpolates the Cosmetatos M/D/k (phi1) and D/M/k (phi3) correction factors. Exact for M/M/k; reduces to the Cosmetatos M/D/k approximation for cs=0. Implements eq. (2.25) as printed, which was validated against the paper’s Tables 5-7 (New column).

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate per server

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

  • k (int) – Number of servers

Returns:

W: Approximate mean response time (time in system) rhohat: Effective utilization

Return type:

Tuple of (W, rhohat) where

References

Whitt, W. (1993). “Approximations for the GI/G/m queue”. Production and Operations Management 2(2), 114-161.

qsys_gig1_ubnd_kingman(lambda_val, mu, ca, cs)[source]
Kingman’s upper bound on the mean waiting time of a G/G/1 queue:

Wq <= lambda*(sa^2+ss^2)/(2*(1-rho)),

with sa^2=ca^2/lambda^2 and ss^2=cs^2/mu^2. The returned W adds the mean service time, so it upper-bounds the mean response time (time in system).

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

Returns:

W: Upper bound on mean response time rhohat: Effective utilization (so M/M/1 formulas still hold)

Return type:

Tuple of (W, rhohat) where

References

Kingman, J.F.C. (1962). “Some inequalities for the queue GI/G/1”. Biometrika 49(3/4), 315-324. Original MATLAB: matlab/src/api/qsys/qsys_gig1_ubnd_kingman.m

qsys_gigk_approx_kingman(lambda_val, mu, ca, cs, k)[source]

Kingman’s approximation for G/G/k queue waiting time.

Extends Kingman’s approximation to multi-server queues using M/M/k waiting time as a base.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate per server

  • k (int) – Number of servers

  • ca (float) – Coefficient of variation of inter-arrival time

  • cs (float) – Coefficient of variation of service time

Returns:

W: Approximate mean response time rhohat: Effective utilization

Return type:

Tuple of (W, rhohat) where

References

Original MATLAB: matlab/src/api/qsys/qsys_gigk_approx_kingman.m

qsys_mg1_prio(lambda_vec, mu_vec, cs_vec)[source]

Analyze M/G/1 queue with non-preemptive (Head-of-Line) priorities.

Matches MATLAB qsys_mg1_prio.m exactly.

Parameters:
  • lambda_vec (numpy.ndarray) – Vector of arrival rates per priority class (class 1 = highest)

  • mu_vec (numpy.ndarray) – Vector of service rates per priority class

  • cs_vec (numpy.ndarray) – Vector of coefficients of variation per priority class

Returns:

W: Vector of mean response times per priority class rho: System utilization (rhohat = Q/(1+Q) format)

Return type:

Tuple of (W, rho)

qsys_mm1_dps(lambda_vec, mu_vec, w_vec, tol=1e-10, max_cutoff=2048)[source]

Numerically exact M/M/1 Discriminatory Processor Sharing (DPS) queue.

Solves the multiclass DPS continuous-time Markov chain on the per-class population vector (n_1..n_K): arrivals lambda_k, class-k service completion rate mu_k * n_k * w_k / sum_j n_j * w_j. The state space is truncated at a total population level chosen from the geometric tail bound (the total-count process is stochastically dominated by the M/M/1 with rate min_k mu_k), and the truncation level is doubled until the mean queue lengths are stable to the requested tolerance – so the result is exact to solver precision and conserves the M/M/1 total for equal service rates by construction.

Parameters:
  • lambda_vec (numpy.ndarray) – Per-class Poisson arrival rates (K,)

  • mu_vec (numpy.ndarray) – Per-class exponential service rates (K,)

  • w_vec (numpy.ndarray) – Per-class DPS weights (K,), positive

  • tol (float) – Convergence tolerance on the per-class mean counts

  • max_cutoff (int) – Hard bound on the total-population truncation level

Returns:

per-class mean response times (K,) via Little’s law, and the total utilization sum_k lambda_k/mu_k.

Return type:

Tuple of (T, rho)

qsys_mg1_srpt(lambda_vec, mu_vec, cs_vec)[source]

Analyze M/G/1 queue with Shortest Remaining Processing Time (SRPT).

SRPT is a size-based policy: it always serves the job with the smallest remaining processing time, preempting whenever a shorter job arrives. The class-conditional mean response time follows the Schrage-Miller formula (Bansal-Harchol-Balter, SIGMETRICS 2001, Sec. 4, Eqs (1)-(3), after Schrage-Miller 1966). For a job of size x:

E[T(x)] = E[W(x)] + E[R(x)] E[W(x)] = lambda*(m2(x) + x^2*(1-F(x))) / (2*(1-rho(x))^2) E[R(x)] = integral_0^x dt/(1-rho(t))

with f the mixture job-size density, F its CDF, rho(x)=lambda*int_0^x t f(t)dt and m2(x)=int_0^x t^2 f(t)dt. The per-class mean is E[T_r]=int_0^inf E[T(x)] f_r(x) dx; since E[T(x)] depends only on the job size (SRPT is size-based) this is exact. Integrals use cumulative trapezoidal quadrature on a common grid. Each class is matched to its (mean=1/mu, scv=cs^2): exponential for cs=1, a two-phase balanced hyperexponential for cs>1, and a Tijms Erlang-(k-1)/Erlang-k mixture for cs<1. The fully exponential case reproduces the exact M/M/1/SRPT result.

Matches MATLAB qsys_mg1_srpt.m.

Parameters:
  • lambda_vec (numpy.ndarray) – Vector of arrival rates per class

  • mu_vec (numpy.ndarray) – Vector of service rates per class

  • cs_vec (numpy.ndarray) – Vector of coefficients of variation per class

Returns:

W: Vector of mean response times per class (original class order) rho: System load measure Q/(1+Q) with Q = sum(lambda.*W)

Return type:

Tuple of (W, rho)

qsys_mg1_fb(lambda_vec, mu_vec, cs_vec)[source]

Analyze M/G/1 queue with Foreground-Background (FB/LAS) scheduling.

Matches MATLAB qsys_mg1_fb.m exactly: - Exponential case: numerical integration of E[T(x)] * f_k(x) - General case: class-based approximation

Parameters:
  • lambda_vec (numpy.ndarray) – Vector of arrival rates per class

  • mu_vec (numpy.ndarray) – Vector of service rates per class

  • cs_vec (numpy.ndarray) – Vector of coefficients of variation per class

Returns:

W: Vector of mean response times per class rho: System utilization (rhohat format)

Return type:

Tuple of (W, rho)

qsys_mg1_lrpt(lambda_vec, mu_vec, cs_vec)[source]

Analyze M/G/1 queue with Longest Remaining Processing Time (LRPT).

Matches MATLAB qsys_mg1_lrpt.m exactly: - Exponential case: numerical integration of E[T(x)] * f_k(x) - General case: preemptive priority with descending service time ordering

Parameters:
  • lambda_vec (numpy.ndarray) – Vector of arrival rates per class

  • mu_vec (numpy.ndarray) – Vector of service rates per class

  • cs_vec (numpy.ndarray) – Vector of coefficients of variation per class

Returns:

W: Vector of mean response times per class rho: System utilization (rhohat format)

Return type:

Tuple of (W, rho)

qsys_mg1_psjf(lambda_vec, mu_vec, cs_vec)[source]

Analyze M/G/1 queue with Preemptive Shortest Job First (PSJF).

Matches MATLAB qsys_mg1_psjf.m exactly: - Exponential case: numerical integration of E[T(x)] * f_k(x) - General case: class-based truncated moment formula

Parameters:
  • lambda_vec (numpy.ndarray) – Vector of arrival rates per class

  • mu_vec (numpy.ndarray) – Vector of service rates per class

  • cs_vec (numpy.ndarray) – Vector of coefficients of variation per class

Returns:

W: Vector of mean response times per class rho: System utilization (rhohat format)

Return type:

Tuple of (W, rho)

qsys_mg1_setf(lambda_vec, mu_vec, cs_vec)[source]

Analyze M/G/1 queue with Shortest Expected Time First (SETF).

Matches MATLAB qsys_mg1_setf.m exactly: SETF = FB/LAS + residual service time penalty (non-preemptive).

Parameters:
  • lambda_vec (numpy.ndarray) – Vector of arrival rates per class

  • mu_vec (numpy.ndarray) – Vector of service rates per class

  • cs_vec (numpy.ndarray) – Vector of coefficients of variation per class

Returns:

W: Vector of mean response times per class rho: System utilization (rhohat format)

Return type:

Tuple of (W, rho)

qsys_mm1k_loss(lambda_val, mu, K)[source]

Compute loss probability for M/M/1/K queue.

Uses the closed-form formula for the M/M/1/K loss system where customers are rejected when the buffer (capacity K) is full.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • K (int) – Buffer capacity (including customer in service)

Returns:

lossprob: Probability that an arriving customer is rejected rho: Offered load (lambda/mu)

Return type:

Tuple of (lossprob, rho)

References

Original MATLAB: matlab/src/api/qsys/qsys_mm1k_loss.m

qsys_mg1k_loss(lambda_val, service_pdf, K, max_t=None)[source]

Exact M/G/1/K loss probability via the Markov chain embedded at service-start epochs (transform-free analysis in the spirit of Niu-Cooper).

State: number of customers waiting in the queue immediately after a service start, q in {0,…,K-2} (capacity K includes the job in service; just after a departure at most K-1 jobs remain, one of which enters service). With a_j = P(j Poisson arrivals during a service time):

q=0if no arrival occurs during the service the system empties and

the next service starts with the next arrival (q’=0), so both a_0 and a_1 lead to q’=0 and j>=2 arrivals lead to q’=j-1;

q>=1: q’ = q-1+j, with arrivals beyond the free capacity lost

(aggregated in the last column).

The loss probability follows from the renewal-reward argument

E[cycle] = E[S] + sigma_0*a_0/lambda, lambda_eff = 1/E[cycle], P_loss = 1 - lambda_eff/lambda = 1 - 1/(rho + sigma_0*a_0)

where sigma is the stationary distribution at service-start epochs.

Parameters:
  • lambda_val (float) – Arrival rate

  • service_pdf (Callable[[float], float]) – Probability density function of service time f(t)

  • K (int) – Buffer capacity (including the customer in service)

  • max_t (float | None) – Maximum integration time (default: smallest horizon covering the service-time distribution mass to within 1e-10)

Returns:

sigma0: Stationary probability of an empty queue at service-start

epochs

rho: Offered load lossprob: Probability of loss

Return type:

Tuple of (sigma0, rho, lossprob)

References

Original MATLAB: matlab/src/api/qsys/qsys_mg1k_loss.m Niu-Cooper, “Transform-Free Analysis of M/G/1/K”, 1993

qsys_mg1k_loss_mgs(lambda_val, mu, mu_scv, K)[source]

Compute loss probability for M/G/1/K using MacGregor Smith approximation.

Matches MATLAB qsys_mg1k_loss_mgs.m exactly.

Parameters:
  • lambda_val (float) – Arrival rate

  • mu (float) – Service rate

  • mu_scv (float) – Squared coefficient of variation of service time

  • K (int) – Buffer capacity

Returns:

lossprob: Probability of loss rho: Offered load

Return type:

Tuple of (lossprob, rho)

References

Original MATLAB: matlab/src/api/qsys/qsys_mg1k_loss_mgs.m J. MacGregor Smith, “Optimal Design and Performance Modelling of M/G/1/K Queueing Systems”

qsys_mxm1(lambda_batch, mu, E_X_or_batch_sizes, E_X2_or_pmf, mode=None)[source]

Analyze MX/M/1 queue with batch arrivals.

Matches MATLAB qsys_mxm1.m exactly.

Three input formats:
  1. Moment-based: qsys_mxm1(lambda_batch, mu, E_X, E_X2)

  2. PMF-based: qsys_mxm1(lambda_batch, mu, batch_sizes, pmf)

  3. Variance: qsys_mxm1(lambda_batch, mu, E_X, Var_X, ‘variance’)

Parameters:
  • lambda_batch (float) – Batch arrival rate

  • mu (float) – Service rate

  • E_X_or_batch_sizes – Mean batch size (scalar) or array of batch sizes

  • E_X2_or_pmf – Second moment of batch size, PMF, or variance

  • mode (str | None) – Optional ‘variance’ flag for variance-based input

Returns:

W: Mean time in system Wq: Mean waiting time in queue U: Server utilization Q: Mean queue length (including service)

Return type:

Tuple of (W, Wq, U, Q)

References

Original MATLAB: matlab/src/api/qsys/qsys_mxm1.m

class QueueResult(meanQueueLength, meanWaitingTime, meanSojournTime, utilization, queueLengthDist=None, queueLengthMoments=None, sojournTimeMoments=None, analyzer='native')[source]

Bases: object

Result structure for queue analysis.

analyzer: str = 'native'
queueLengthDist: numpy.ndarray | None = None
queueLengthMoments: numpy.ndarray | None = None
sojournTimeMoments: numpy.ndarray | None = None
meanQueueLength: float
meanWaitingTime: float
meanSojournTime: float
utilization: float
ph_to_map(alpha, T)[source]

Convert a PH distribution to its equivalent MAP representation.

For a PH renewal process, the MAP has:

D0 = T (transitions within the PH, no arrival) D1 = t * alpha where t = -T*e (exit rates times restart distribution)

Parameters:
Returns:

D0: MAP hidden transition matrix D1: MAP observable transition matrix

Return type:

Tuple of (D0, D1)

qsys_phph1(alpha, T, beta, S, numQLMoms=3, numQLProbs=100, numSTMoms=3)[source]

Analyze a PH/PH/1 queue using matrix-analytic methods.

Converts the arrival PH to MAP representation and uses the MMAPPH1FCFS solver from BuTools.

Parameters:
  • alpha (numpy.ndarray) – Arrival PH initial probability vector (1 x n)

  • T (numpy.ndarray) – Arrival PH generator matrix (n x n)

  • beta (numpy.ndarray) – Service PH initial probability vector (1 x m)

  • S (numpy.ndarray) – Service PH generator matrix (m x m)

  • numQLMoms (int) – Number of queue length moments to compute (default: 3)

  • numQLProbs (int) – Number of queue length probabilities (default: 100)

  • numSTMoms (int) – Number of sojourn time moments (default: 3)

Returns:

QueueResult with queue performance metrics

Return type:

QueueResult

References

Original MATLAB: matlab/src/api/qsys/qsys_phph1.m

qsys_mapph1(D0, D1, beta, S, numQLMoms=3, numQLProbs=100, numSTMoms=3)[source]

Analyze a MAP/PH/1 queue.

Parameters:
  • D0 (numpy.ndarray) – MAP hidden transition matrix

  • D1 (numpy.ndarray) – MAP observable transition matrix

  • beta (numpy.ndarray) – Service PH initial probability vector

  • S (numpy.ndarray) – Service PH generator matrix

  • numQLMoms (int) – Number of queue length moments

  • numQLProbs (int) – Number of queue length probabilities

  • numSTMoms (int) – Number of sojourn time moments

Returns:

QueueResult with queue performance metrics

Return type:

QueueResult

References

Original MATLAB: matlab/src/api/qsys/qsys_mapph1.m

qsys_mapm1(D0, D1, mu)[source]

Analyze a MAP/M/1 queue.

Parameters:
Returns:

QueueResult with queue performance metrics

Return type:

QueueResult

References

Original MATLAB: matlab/src/api/qsys/qsys_mapm1.m

qsys_mapmc(D0, D1, mu, c)[source]

Analyze a MAP/M/c queue.

Parameters:
  • D0 (numpy.ndarray) – MAP hidden transition matrix

  • D1 (numpy.ndarray) – MAP observable transition matrix

  • mu (float) – Service rate per server

  • c (int) – Number of servers

Returns:

QueueResult with queue performance metrics

Return type:

QueueResult

References

Original MATLAB: matlab/src/api/qsys/qsys_mapmc.m

qsys_mapmap1(D0_arr, D1_arr, D0_srv, D1_srv)[source]

Analyze a MAP/MAP/1 queue.

Both arrival and service processes are Markovian Arrival Processes.

Parameters:
  • D0_arr (numpy.ndarray) – Arrival MAP hidden transition matrix

  • D1_arr (numpy.ndarray) – Arrival MAP observable transition matrix

  • D0_srv (numpy.ndarray) – Service MAP hidden transition matrix

  • D1_srv (numpy.ndarray) – Service MAP observable transition matrix

Returns:

QueueResult with queue performance metrics

Return type:

QueueResult

References

Original MATLAB: matlab/src/api/qsys/qsys_mapmap1.m

qsys_mapg1(D0, D1, service_moments, num_ql_moms=3, num_ql_probs=100, num_st_moms=3)[source]

Analyze a MAP/G/1 queue using BuTools MMAPPH1FCFS.

The general service time distribution is fitted to a Phase-Type (PH) distribution using moment matching before analysis.

Parameters:
  • D0 (numpy.ndarray) – MAP hidden transition matrix (n x n)

  • D1 (numpy.ndarray) – MAP arrival transition matrix (n x n)

  • service_moments (numpy.ndarray) – First k raw moments of service time [E[S], E[S^2], …] (k = 2 or 3 for best accuracy)

  • num_ql_moms (int) – Number of queue length moments to compute (default: 3)

  • num_ql_probs (int) – Number of queue length probabilities (default: 100)

  • num_st_moms (int) – Number of sojourn time moments to compute (default: 3)

Returns:

QueueResult with queue performance metrics

Return type:

QueueResult

References

Original MATLAB: matlab/src/api/qsys/qsys_mapg1.m

Note

Uses the MMAPPH1FCFS solver from BuTools after fitting the general service distribution to a PH distribution.

class QueueType(*values)[source]

Bases: Enum

Queueing system topology types.

STANDARD = 'standard'
RETRIAL = 'retrial'
RENEGING = 'reneging'
RETRIAL_RENEGING = 'retrial_reneging'
class BmapMatrix(D0, D_batch)[source]

Bases: object

Batch Markovian Arrival Process matrix representation.

D₀ = drift matrix (no arrivals) D₁, D₂, …, Dₖ = batch arrival matrices for batch sizes 1, 2, …, K

Properties:

order: Dimension of the BMAP num_batches: Maximum batch size arrival_rate: Overall arrival rate

__post_init__()[source]

Validate BMAP structure.

property arrival_rate: float

Compute overall arrival rate of the BMAP.

lambda = theta * (-D0) * e where theta is stationary distribution of BMAP Markov chain and e is unit vector.

property fundamental_arrival_rate: float

Arrival rate from fundamental matrix.

D0: numpy.ndarray
D_batch: List[numpy.ndarray]
class PhDistribution(beta, S)[source]

Bases: object

Phase-Type (PH) distribution representation.

Beta = initial probability vector (shape: m,) S = transient generator matrix (shape: m x m)

where m is the number of phases.

Properties:

mean: Mean of PH distribution (1/mu in queue notation) scv: Squared coefficient of variation num_phases: Number of phases

__post_init__()[source]

Validate PH distribution structure.

property mean: float

Compute mean of PH distribution.

E[X] = -beta * S^{-1} * e

property mean_squared: float

Compute second moment of PH distribution.

E[X²] = 2 * beta * S^{-2} * e

property scv: float

Squared coefficient of variation of PH distribution.

SCV = (E[X²] / E[X]²) - 1

beta: numpy.ndarray
S: numpy.ndarray
class QbdStatespace(A0, A1, A2, B0, max_level)[source]

Bases: object

Quasi-Birth-Death Markov chain state space representation.

For a QBD process, states are of the form (n, i) where: - n = level (number of retrying customers in orbit) - i = phase (service phase or phase-type stage)

Generator matrix has block structure: Q = | B_0 A_0 0 0 … |

A_2 A_1 A_0 0 … |
0 A_2 A_1 A_0 … |
… |
Properties:

max_level: Maximum retrial orbit size (truncation level) phase_dim: Number of phases at each level total_states: Total state space dimension

__post_init__()[source]

Validate QBD state space.

property binomial_state_dimension: int

Compute state space dimension using binomial coefficient formula.

For a retrial queue with N total customers and m servers, dimension = C(N + m - 1, m - 1)

This is a rough upper bound for QBD truncation.

get_level_phase(idx)[source]

Map linear state index to (level, phase).

Parameters:

idx (int) – Linear state index

Returns:

Tuple (level, phase)

Return type:

Tuple[int, int]

get_state_index(level, phase)[source]

Map (level, phase) to linear state index.

Parameters:
  • level (int) – Retrial orbit size (0 ≤ level ≤ max_level)

  • phase (int) – Phase within level (0 ≤ phase < phase_dim)

Returns:

Linear state index

Return type:

int

A0: numpy.ndarray
A1: numpy.ndarray
A2: numpy.ndarray
B0: numpy.ndarray
max_level: int
class RetrialQueueResult(queue_type, L_orbit, N_server, utilization, throughput, P_idle, P_empty_orbit, stationary_dist=None, truncation_level=0, converged=False, iterations=0, error=numpy.inf)[source]

Bases: object

Analysis results for BMAP/PH/N/N retrial queue.

queue_type

Type of queue (retrial, reneging, etc.)

Type:

line_solver.api.qsys.retrial.QueueType

L_orbit

Expected number of customers in orbit

Type:

float

N_server

Expected number of customers being served

Type:

float

utilization

Server utilization

Type:

float

throughput

System throughput

Type:

float

P_idle

Probability that server is idle

Type:

float

P_empty_orbit

Probability that orbit is empty

Type:

float

stationary_dist

Stationary distribution vector

Type:

numpy.ndarray | None

truncation_level

QBD truncation level used

Type:

int

converged

Whether numerical solution converged

Type:

bool

iterations

Number of iterations to convergence

Type:

int

error

Final error estimate

Type:

float

converged: bool = False
iterations: int = 0
stationary_dist: numpy.ndarray | None = None
truncation_level: int = 0
queue_type: QueueType
L_orbit: float
N_server: float
utilization: float
throughput: float
P_idle: float
P_empty_orbit: float
class RetrialQueueAnalyzer(sn, options=None)[source]

Bases: object

Framework for analyzing BMAP/PH/N/N retrial queues.

This class provides the foundation for future full solver implementation, including topology detection, parameter extraction, and QBD setup.

Example

analyzer = RetrialQueueAnalyzer(model) queue_type = analyzer.detect_queue_type() if queue_type == QueueType.RETRIAL:

result = analyzer.analyze()

Initialize retrial queue analyzer.

Parameters:
  • sn (Any) – NetworkStruct with queue configuration

  • options (Dict | None) – Analysis options (tolerance, max iterations, etc.)

__init__(sn, options=None)[source]

Initialize retrial queue analyzer.

Parameters:
  • sn (Any) – NetworkStruct with queue configuration

  • options (Dict | None) – Analysis options (tolerance, max iterations, etc.)

analyze()[source]

Analyze the retrial queue.

This is the main entry point for analysis: 1. Detect queue type 2. Extract arrival and service parameters 3. Build QBD state space 4. Solve for stationary distribution using matrix-analytic methods 5. Compute performance metrics

Returns:

RetrialQueueResult with performance metrics

Return type:

RetrialQueueResult

build_qbd_statespace(bmap, ph_service, retrial_params)[source]

Build QBD state space for the retrial queue.

This constructs the generator matrix blocks for the QBD process following the BMAP/PH/N/N retrial queue formulation.

Parameters:
  • bmap (BmapMatrix) – BMAP arrival process

  • ph_service (PhDistribution) – PH service distribution

  • retrial_params (Dict[str, float]) – Retrial parameters (alpha, gamma, p, R, N)

Returns:

QbdStatespace instance or None if construction fails

Return type:

QbdStatespace | None

detect_queue_type()[source]

Detect the type of queueing system from topology.

Returns:

QueueType enum indicating retrial, reneging, or combination

Return type:

QueueType

extract_bmap()[source]

Extract BMAP parameters from arrival process.

LINE stores arrival processes in MAP format: {D0, D1, D2, …} where D0 is the “hidden” generator and D1, D2, … are arrival matrices.

Returns:

BmapMatrix instance or None if arrival is not BMAP/MAP

Return type:

BmapMatrix | None

extract_ph_service()[source]

Extract Phase-Type service parameters.

LINE stores PH in MAP format: {D0, D1} D0 = T (subgenerator matrix) D1 = S0 * alpha (exit rate times initial prob)

Returns:

PhDistribution instance or None if service is not PH

Return type:

PhDistribution | None

extract_retrial_parameters()[source]

Extract retrial-specific parameters.

Returns:

  • alpha: Retrial rate (rate at which customers retry)

  • gamma: Orbit impatience rate (reneging rate)

  • p: Batch rejection probability

  • R: Threshold for admission control

  • N: Number of servers

Return type:

Dict with keys

qsys_bmapphnn_retrial(arrival_matrix, service_params, N, retrial_params=None, options=None)[source]

Analyze BMAP/PH/N/N bufferless retrial queue.

Implements the algorithm from Dudin et al., “Analysis of BMAP/PH/N-Type Queueing System with Flexible Retrials Admission Control”, Mathematics 2025, 13(9), 1434.

Parameters:
  • arrival_matrix (Dict[str, numpy.ndarray]) – Dict with ‘D0’, ‘D1’, … for BMAP matrices. D0: hidden transition matrix (V x V). D1, …, DK: arrival matrices for batch sizes 1, …, K.

  • service_params (Dict[str, numpy.ndarray]) – Dict with ‘beta’ (initial prob vector, 1xM) and ‘S’ (PH subgenerator matrix, MxM).

  • N (int) – Number of servers (also capacity, hence bufferless).

  • retrial_params (Dict[str, float] | None) – Dict with ‘alpha’ (retrial rate per customer), ‘gamma’ (impatience/abandonment rate), ‘p’ (batch rejection probability), ‘R’ (admission threshold, scalar or 1xV).

  • options (Dict | None) – Dict with optional keys: ‘MaxLevel’: max orbit level for truncation (default: auto). ‘Tolerance’: convergence tolerance (default: 1e-10). ‘Verbose’: print progress (default: False).

Returns:

RetrialQueueResult with performance metrics.

Return type:

RetrialQueueResult

References

Dudin, A., Klimenok, V., & Vishnevsky, V. (2020). Port from: matlab/src/api/qsys/qsys_bmapphnn_retrial.m

qsys_is_retrial(sn)[source]

Check if network is a valid BMAP/PH/N/N bufferless retrial queue.

Validates that the network structure matches the requirements for the BMAP/PH/N/N retrial queue solver: - Single bufferless queue (capacity == number of servers) - Retrial drop strategy configured - BMAP/MAP arrival process at source - PH/Exp service at queue - Open class model

Based on: Dudin et al., “Analysis of BMAP/PH/N-Type Queueing System with Flexible Retrials Admission Control”, Mathematics 2025, 13(9), 1434.

Parameters:

sn (Any) – NetworkStruct object

Returns:

is_retrial: True if network is valid BMAP/PH/N/N retrial topology retrial_info: RetrialInfo with parameters for the retrial solver

Return type:

Tuple of (is_retrial, retrial_info) where

References

Original MATLAB: matlab/src/api/qsys/qsys_is_retrial.m

class RetrialInfo(is_retrial, station_idx=None, node_idx=None, source_idx=None, class_idx=None, error_msg='', N=None, alpha=0.1, gamma=0.0, p=0.0, R=None)[source]

Bases: object

Information about a valid retrial queue topology.

N: int | None = None
R: int | None = None
alpha: float = 0.1
class_idx: int | None = None
error_msg: str = ''
gamma: float = 0.0
node_idx: int | None = None
p: float = 0.0
source_idx: int | None = None
station_idx: int | None = None
is_retrial: bool
class RenegingInfo(is_reneging, source_idx=None, queue_idx=None, class_idx=None, n_servers=None, service_rate=None, error_msg='')[source]

Bases: object

Information about a valid reneging queue topology.

class_idx: int | None = None
error_msg: str = ''
n_servers: int | None = None
queue_idx: int | None = None
service_rate: float | None = None
source_idx: int | None = None
is_reneging: bool
detect_reneging_topology(sn)[source]

Detect if model is suitable for MAP/M/s+G (MAPMsG) reneging solver.

Requirements: - Open model, single class - Single queue station with reneging/patience configured - MAP/BMAP arrival at source - Exponential service at queue (single-phase PH) - FCFS scheduling

Parameters:

sn (Any) – NetworkStruct object

Returns:

Tuple of (is_reneging, reneging_info)

Return type:

Tuple[bool, RenegingInfo]

References

Original MATLAB: matlab/src/solvers/MAM/solver_mam_retrial.m (detectRenegingTopology)

has_reneging_patience(sn)[source]

Check if model has reneging/patience configured on any queue station.

Returns True if any queue station has ImpatienceType.RENEGING configured with a patience distribution.

Parameters:

sn (Any) – NetworkStruct object

Returns:

True if reneging patience is configured

Return type:

bool

References

Original MATLAB: matlab/src/solvers/MAM/solver_mam_analyzer.m (hasRenegingPatience)

extract_bmap_matrices(proc)[source]

Extract BMAP matrices {D0, D1, …} from LINE process representation.

LINE stores arrival processes in MAP format: {D0, D1, D2, …} where D0 is the “hidden” generator and D1, D2, … are arrival matrices. May also be in PH format {alpha, T} which is converted to MAP.

Parameters:

proc (Any) – Process representation from sn.proc[station][class]

Returns:

List of numpy arrays [D0, D1, …] or None if extraction fails

Return type:

List[numpy.ndarray] | None

References

Original MATLAB: matlab/src/solvers/MAM/solver_mam_retrial.m (extractBMAPMatrices)

extract_ph_params(proc)[source]

Extract PH parameters (beta, S) from LINE process representation.

LINE stores PH in MAP format: {D0, D1} where D0=T (subgenerator), D1=S0*alpha (exit rate times initial prob).

Parameters:

proc (Any) – Process representation from sn.proc[station][class]

Returns:

Tuple of (beta, S) where beta is initial probability vector and S is subgenerator matrix. Returns (None, None) if extraction fails.

Return type:

Tuple[numpy.ndarray | None, numpy.ndarray | None]

References

Original MATLAB: matlab/src/solvers/MAM/solver_mam_retrial.m (extractPHParams)

convert_patience_to_regimes(patience_proc, options=None)[source]

Convert patience distribution to piecewise-constant abandonment regimes for MAPMsG.

Converts a patience distribution (in MAP/PH format) to boundary levels and abandonment function values for the MRMFQ solver.

Parameters:
  • patience_proc (Any) – Patience distribution from sn.patienceProc[station, class]

  • options (Dict | None) – Dict with optional ‘mapmsg_quantization’ key (default 11)

Returns:

boundary_levels: Array of regime boundary time points ga: Array of abandonment probabilities at each regime quantization: Number of regimes

Return type:

Tuple of (boundary_levels, ga, quantization) where

References

Original MATLAB: matlab/src/solvers/MAM/solver_mam_retrial.m (convertPatienceToRegimes)

solver_mam_retrial(sn, options=None)[source]

Solve queueing models with customer impatience (retrial or reneging).

Dispatches to either: 1. RETRIAL: BMAP/PH/N/N bufferless retrial solver 2. RENEGING: MAP/M/s+G solver (MAPMsG)

Parameters:
  • sn (Any) – NetworkStruct object

  • options (Dict | None) – Solver options dict with optional keys: ‘iter_max’: Maximum truncation level (default 150) ‘tol’: Convergence tolerance (default 1e-10) ‘verbose’: Print progress messages (default False) ‘config’: Dict with ‘mapmsg_quantization’ (default 11)

Returns:

QN: (M, K) queue lengths UN: (M, K) server utilizations RN: (M, K) response times TN: (M, K) throughputs CN: (1, K) cycle times XN: (1, K) system throughputs totiter: iteration/truncation level count

Return type:

Tuple of (QN, UN, RN, TN, CN, XN, totiter) where

References

Original MATLAB: matlab/src/solvers/MAM/solver_mam_retrial.m

qsys_ldps_workload(lambd, B, alpha, N, t=None, ngrid=None)[source]

Stationary distribution of the quantity of work in a single-stage load-dependent processor sharing station with Poisson arrivals and blocking.

Assumed model (Cohen 1979, Sect. 9; the model of Sect. 7 with one stage): a single service stage fed by a Poisson arrival stream of rate lambd; a blocking capacity N, so that a request arriving when N requests are already present is lost and leaves no trace on the state; generalized processor sharing, so that when x requests are present each accrues service at rate f(x) and the stage completes work at total rate x*f(x); and required service times i.i.d. with absolutely continuous distribution B of finite mean beta. The station is parametrized by the LINE load-dependent total rate scaling alpha(x)=x*f(x), the argument of setLoadDependence at a PS station.

With psi the total amount of service still to be given to the requests present, Cohen eqs. (9.1)-(9.3) give

Pr{psi < y} = sum_{h=0}^{N} p_h Psi^{h*}(y) p_h = (rho^h/h!) phi(h) / sum_k (rho^k/k!) phi(k), rho = lambd*beta phi(h) = 1/prod_{k=1}^{h} f(k), phi(0)=1 Psi(y) = int_0^y (1-B(v))/beta dv

with Psi^{h*} the h-fold convolution of Psi and Psi^{0*} degenerate at zero. Substituting f(k)=alpha(k)/k the factorial cancels, leaving p_h proportional to rho^h/prod_{k=1}^{h} alpha(k), the familiar load-dependent birth-death form. Psi is the equilibrium (residual life) distribution of B, so psi is a mixture of h-fold convolutions of residual service times with an atom p_0 at zero.

This is the model of Cohen (1979) Sect. 9 only. It is not the weighted GPS/DPS discipline of SchedStrategy.GPS, whose per-class weights this formula does not represent.

Parameters:
  • lambd – rate of the Poisson arrival stream (finite, positive)

  • B – required service time Distribution (continuous, finite positive mean)

  • alpha – rate scaling alpha(n)=n*f(n) for n=1..N (finite, positive)

  • N – blocking capacity (finite positive integer)

  • t – optional grid at which the CDF is returned. Default: an automatically sized grid covering the bulk of the distribution.

  • ngrid – optional number of points of the internal uniform quadrature grid on which the convolutions are formed. Default 2001. Accuracy is second order in the step for an absolutely continuous B, the case Cohen assumes, and falls back to first order when B has an atom so that 1-B is discontinuous; raise ngrid for those.

Returns:

(F, t, p) where F[j] = Pr{psi <= t[j]}, t is the grid F is reported on, and p[h] = Pr{x = h} for h = 0..N. Note F[0] = p[0] = Pr{psi = 0} when t[0] = 0, since the workload has an atom at zero.

Stochastic Networks (line_solver.api.sn)

Service Network (SN) utilities.

Native Python implementations for stochastic network structure analysis, validation, and parameter extraction.

Key classes:

NetworkStruct: Data structure summarizing network characteristics SnGetDemandsResult: Result of sn_get_demands_chain calculation

Key functions:

sn_get_demands_chain: Aggregate class-level parameters into chain-level sn_has_*: Network property predicates sn_is_*: Model type checks sn_get_*: Parameter extraction sn_validate: Network validation

class MatrixArray(input_array)[source]

Bases: ndarray

Numpy array subclass with .get() and .set() methods for API compatibility.

This class provides compatibility with the wrapper mode that uses JLine’s Matrix class which has get(i, j) and set(i, j, value) methods.

Create MatrixArray from existing array.

__array_finalize__(obj)[source]

Handle view casting and new-from-template.

__getitem__(key)[source]

Override indexing to handle 2D indexing on 1D arrays.

This provides compatibility with MATLAB-style row/column vectors where a 1D array can be indexed as (0, j) or (i, 0).

static __new__(cls, input_array)[source]

Create MatrixArray from existing array.

__setitem__(key, value)[source]

Override item setting to handle 2D indexing on 1D arrays.

get(i, j=None)[source]

Get element at index (i, j) or just i if 1D.

Parameters:
  • i – Row index (or element index for 1D)

  • j – Column index (optional, for 2D arrays)

Returns:

Element value at the specified index

set(i, j, value=None)[source]

Set element at index (i, j) or just i if 1D.

Parameters:
  • i – Row index (or element index for 1D)

  • j – Column index or value (for 1D arrays)

  • value – Value to set (optional, for 2D arrays)

class NetworkStruct(nstations=0, nstateful=0, nnodes=0, nclasses=0, nchains=0, nclosedjobs=0, njobs=<factory>, nservers=<factory>, cap=None, classcap=None, rates=<factory>, scv=<factory>, phases=None, phasessz=None, phaseshift=None, visits=<factory>, nodevisits=<factory>, inchain=<factory>, chains=<factory>, refstat=<factory>, refclass=<factory>, sched=<factory>, schedparam=None, routing=<factory>, rt=None, rtnodes=None, nodetype=<factory>, isstation=<factory>, isstateful=<factory>, isstatedep=None, isfunction=<factory>, nodeToStation=<factory>, nodeToStateful=<factory>, stationToNode=<factory>, stationToStateful=<factory>, statefulToNode=<factory>, statefulToStation=<factory>, state=<factory>, stateprior=<factory>, space=<factory>, lldscaling=None, cdscaling=None, cdscalingpeak=None, classprio=None, classdeadline=None, isslc=None, issignal=None, signaltarget=None, signaltype=None, syncreply=None, immfeed=None, signalremdist=None, signalrempolicy=None, iscatastrophe=None, connmatrix=None, nodenames=<factory>, classnames=<factory>, mu=None, phi=None, proc=None, pie=None, procid=None, lst=None, fj=None, fjsync=None, fjclassmap=None, isfjaugmented=False, droprule=None, nregions=0, region=None, regionrule=None, regionweight=None, regionsz=None, regionmaxmem=None, regionmembers=None, sync=None, gsync=None, nodeparam=None, routingweights=None, reward=None, rtorig=None, csmask=None, nvars=None, isbasblocking=None, impatienceType=None, impatienceMu=None, impatienceClass=None, impatiencePhi=None, impatiencePhases=None, impatienceProc=None, impatiencePie=None, impatienceDist=None, balkingStrategy=None, balkingThresholds=None, retrialType=None, retrialMu=None, retrialPhi=None, retrialProc=None, retrialMaxAttempts=None, orbitImpatience=None, varsparam=None, markidx=None)[source]

Bases: object

Data structure summarizing network characteristics.

This class is the Python equivalent in native Python. It contains all parameters needed by solvers to analyze a queueing network.

nstations

Number of stations (queues, delays, sources, joins, places)

Type:

int

nstateful

Number of stateful nodes

Type:

int

nnodes

Total number of nodes

Type:

int

nclasses

Number of job classes

Type:

int

nchains

Number of chains (routing chains)

Type:

int

nclosedjobs

Total number of jobs in closed classes

Type:

int

njobs

(1, K) Population per class (inf for open classes)

Type:

numpy.ndarray

nservers

(M, 1) Number of servers per station

Type:

numpy.ndarray

rates

(M, K) Service rates

Type:

numpy.ndarray

scv

(M, K) Squared coefficient of variation

Type:

numpy.ndarray

visits

Dict[int, ndarray] - Chain ID -> (M, K) visit ratios

Type:

Dict[int, numpy.ndarray]

inchain

Dict[int, ndarray] - Chain ID -> class indices in chain

Type:

Dict[int, numpy.ndarray]

chains

(K, 1) Chain membership per class

Type:

numpy.ndarray

refstat

(K, 1) Reference station per class

Type:

numpy.ndarray

refclass

(1, C) Reference class per chain

Type:

numpy.ndarray

sched

Dict[int, SchedStrategy] - Station ID -> scheduling strategy

Type:

Dict[int, int]

routing

(N, K) Routing strategy matrix

Type:

numpy.ndarray

rt

Routing probability matrix

Type:

numpy.ndarray | None

nodetype

List[NodeType] - Node types

Type:

List[int]

isstation

(N, 1) Boolean mask for stations

Type:

numpy.ndarray

isstateful

(N, 1) Boolean mask for stateful nodes

Type:

numpy.ndarray

isfunction

(M, 1) Boolean mask, STATION-indexed: queue stations that carry setup/delay-off times (function stations)

Type:

numpy.ndarray

nodeToStation

(N, 1) Node index -> station index mapping

Type:

numpy.ndarray

nodeToStateful

(N, 1) Node index -> stateful index mapping

Type:

numpy.ndarray

stationToNode

(M, 1) Station index -> node index mapping

Type:

numpy.ndarray

stationToStateful

(M, 1) Station index -> stateful index mapping

Type:

numpy.ndarray

statefulToNode

(S, 1) Stateful index -> node index mapping

Type:

numpy.ndarray

statefulToStation

(S, 1) Stateful index -> station index mapping

Type:

numpy.ndarray

state

Dict State per stateful node

Type:

Dict[int, numpy.ndarray]

lldscaling

(M, Nmax) Load-dependent scaling matrix

Type:

numpy.ndarray | None

cdscaling

Class-dependent scaling functions

Type:

Dict | None

cap

(M, 1) Station capacities

Type:

numpy.ndarray | None

classcap

(M, K) Per-class capacities

Type:

numpy.ndarray | None

connmatrix

(N, N) Connection matrix

Type:

numpy.ndarray | None

nodenames

List[str] - Node names

Type:

List[str]

classnames

List[str] - Class names

Type:

List[str]

__post_init__()[source]

Ensure arrays are MatrixArray (numpy arrays with .get()/.set() methods).

__repr__()[source]

String representation.

__setattr__(name, value)[source]

Override to convert numpy arrays to MatrixArray for API compatibility.

balkingStrategy: numpy.ndarray | None = None
balkingThresholds: List[List[Any]] | None = None
cap: numpy.ndarray | None = None
cdscaling: Dict | None = None
cdscalingpeak: numpy.ndarray | None = None
classcap: numpy.ndarray | None = None
classdeadline: numpy.ndarray | None = None
classprio: numpy.ndarray | None = None
connmatrix: numpy.ndarray | None = None
copy()[source]

Create a deep copy of this NetworkStruct.

csmask: numpy.ndarray | None = None
droprule: Dict | None = None
fj: numpy.ndarray | None = None
fjclassmap: numpy.ndarray | None = None
fjsync: List | None = None
get_chain_population(chain_id)[source]

Get total population in a chain.

Parameters:

chain_id (int) – Chain index (0-based)

Returns:

Total number of jobs in the chain

Return type:

float

get_closed_class_indices()[source]

Get indices of closed classes.

get_open_class_indices()[source]

Get indices of open classes.

get_scheduling_at_station(station_id)[source]

Get scheduling strategy at a station.

Parameters:

station_id (int) – Station index (0-based)

Returns:

SchedStrategy value

Return type:

int

get_stateful_indices()[source]

Get indices of stateful nodes.

Returns:

Array of node indices that are stateful

Return type:

numpy.ndarray

get_station_indices()[source]

Get indices of station nodes.

Returns:

Array of node indices that are stations

Return type:

numpy.ndarray

get_total_population()[source]

Get total population across all closed classes.

gsync: Dict | None = None
has_class_dependence()[source]

Check if model has class-dependent scaling.

has_closed_classes()[source]

Check if model has closed (finite population) classes.

has_load_dependence()[source]

Check if model has load-dependent service rates.

has_multi_server()[source]

Check if any station has multiple servers.

has_open_classes()[source]

Check if model has open (infinite population) classes.

immfeed: numpy.ndarray | None = None
impatienceClass: numpy.ndarray | None = None
impatienceDist: List[List[Any]] | None = None
impatienceMu: numpy.ndarray | None = None
impatiencePhases: numpy.ndarray | None = None
impatiencePhi: numpy.ndarray | None = None
impatiencePie: List[List[Any]] | None = None
impatienceProc: List[List[Any]] | None = None
impatienceType: numpy.ndarray | None = None
is_closed_chain(chain_id)[source]

Check if a chain is closed (finite population).

Parameters:

chain_id (int) – Chain index (0-based)

Returns:

True if chain is closed, False if open

Return type:

bool

is_open_chain(chain_id)[source]

Check if a chain is open (infinite population).

Parameters:

chain_id (int) – Chain index (0-based)

Returns:

True if chain is open, False if closed

Return type:

bool

is_valid()[source]

Check if structure is valid.

Returns:

True if structure passes validation, False otherwise

Return type:

bool

isbasblocking: numpy.ndarray | None = None
iscatastrophe: numpy.ndarray | None = None
isfjaugmented: bool = False
issignal: numpy.ndarray | None = None
isslc: numpy.ndarray | None = None
isstatedep: numpy.ndarray | None = None
lldscaling: numpy.ndarray | None = None
lst: Dict | None = None
markidx: numpy.ndarray | None = None
mu: Dict | None = None
nchains: int = 0
nclasses: int = 0
nclosedjobs: int = 0
nnodes: int = 0
nodeparam: Dict | None = None
nregions: int = 0
nstateful: int = 0
nstations: int = 0
nvars: numpy.ndarray | None = None
property obj

Return self for compatibility with wrapper code that accesses .obj

orbitImpatience: List[List[Any]] | None = None
phases: numpy.ndarray | None = None
phaseshift: numpy.ndarray | None = None
phasessz: numpy.ndarray | None = None
phi: Dict | None = None
pie: Dict | None = None
proc: Dict | None = None
procid: Dict | None = None
region: List | None = None
regionmaxmem: List | None = None
regionmembers: List | None = None
regionrule: numpy.ndarray | None = None
regionsz: numpy.ndarray | None = None
regionweight: numpy.ndarray | None = None
retrialMaxAttempts: numpy.ndarray | None = None
retrialMu: numpy.ndarray | None = None
retrialPhi: numpy.ndarray | None = None
retrialProc: List[List[Any]] | None = None
retrialType: numpy.ndarray | None = None
reward: Dict | None = None
routingweights: Dict | None = None
rt: numpy.ndarray | None = None
rtnodes: numpy.ndarray | None = None
rtorig: Dict | None = None
schedparam: numpy.ndarray | None = None
signalremdist: List | None = None
signalrempolicy: List | None = None
signaltarget: numpy.ndarray | None = None
signaltype: List | None = None
sync: Dict | None = None
syncreply: numpy.ndarray | None = None
validate()[source]

Validate structural consistency.

Raises:

ValueError – If structural consistency is violated

varsparam: numpy.ndarray | None = None
njobs: numpy.ndarray
nservers: numpy.ndarray
rates: numpy.ndarray
scv: numpy.ndarray
visits: Dict[int, numpy.ndarray]
nodevisits: Dict[int, numpy.ndarray]
inchain: Dict[int, numpy.ndarray]
chains: numpy.ndarray
refstat: numpy.ndarray
refclass: numpy.ndarray
sched: Dict[int, int]
routing: numpy.ndarray
nodetype: List[int]
isstation: numpy.ndarray
isstateful: numpy.ndarray
isfunction: numpy.ndarray
nodeToStation: numpy.ndarray
nodeToStateful: numpy.ndarray
stationToNode: numpy.ndarray
stationToStateful: numpy.ndarray
statefulToNode: numpy.ndarray
statefulToStation: numpy.ndarray
state: Dict[int, numpy.ndarray]
stateprior: Dict[int, numpy.ndarray]
space: Dict[int, numpy.ndarray]
nodenames: List[str]
classnames: List[str]
class NodeType(*values)[source]

Bases: IntEnum

Node types in a queueing network.

NOTE: Values must match lang/base.py NodeType enum.

static toText(node_type)[source]

Convert node type to text representation.

SOURCE = 0
SINK = 1
QUEUE = 2
DELAY = 3
JOIN = 5
CACHE = 6
ROUTER = 7
CLASSSWITCH = 8
PLACE = 9
TRANSITION = 10
LOGGER = 11
FINITE_CAPACITY_REGION = 12
class SchedStrategy(*values)[source]

Bases: IntEnum

Scheduling strategies.

LCFSPI = 3
HOL = 9
LPS = 17
SETF = 18
FCFSPR = 22
EDF = 23
JOIN = 25
EDD = 27
SRPT = 28
SRPTPRIO = 29
LCFSPRIO = 30
LCFSPRPRIO = 31
LCFSPIPRIO = 32
FCFSPRPRIO = 33
FCFSPIPRIO = 34
FSP = 36
PAS = 37
OI = 38
class RoutingStrategy(*values)[source]

Bases: IntEnum

Routing strategies.

Values must match MATLAB’s RoutingStrategy constants for JMT compatibility.

RL = 7
class DropStrategy(*values)[source]

Bases: IntEnum

Drop strategies for finite capacity.

Values match the MATLAB DropStrategy constants and the JAR jline.lang.constant.DropStrategy ids, which are the interchange encoding of sn.droprule and sn.regionrule. Keep the three Python definitions of this enum (here, lang/base.py, constants.py) numerically identical: they are written and read by different modules over the same sn fields.

WAITQ = -1
DROP = 1
BAS = 2
BBS = 3
RSRD = 4
RETRIAL = 5
RETRIAL_WITH_LIMIT = 6
sn_region_members(sn, f, Rmat, memvec)[source]

Station membership mask of finite capacity region f, as a bool array of length M.

Membership is read from sn.regionmembers[f], which the region refresh records directly from the region’s node list. It cannot be derived from sn.region[f]: -1 there means “unbounded”, which is indistinguishable from “not a member”, so a region constrained only by regionlincon (or only by a memory budget) reads as empty and is silently ignored.

Rmat and memvec provide the legacy derivation, used only for an sn built before regionmembers existed (for instance one deserialised from an older model file). That derivation carries the ambiguity above and is not equivalent.

sn_get_demands_chain(sn)[source]

Calculate new queueing network parameters after aggregating classes into chains.

This function computes chain-level demands, service times, visit ratios, and other parameters by aggregating class-level data based on chain membership.

Parameters:

sn (NetworkStruct) – NetworkStruct object for the queueing network model

Returns:

  • Lchain: (M, C) chain-level demand matrix

  • STchain: (M, C) chain-level service time matrix

  • Vchain: (M, C) chain-level visit ratio matrix

  • alpha: (M, K) class-to-chain weighting matrix

  • Nchain: (1, C) population per chain

  • SCVchain: (M, C) chain-level squared coefficient of variation

  • refstatchain: (C, 1) reference station per chain

Return type:

SnGetDemandsResult containing chain parameters

class SnGetDemandsResult(Lchain, STchain, Vchain, alpha, Nchain, SCVchain, refstatchain)[source]

Bases: object

Result of sn_get_demands_chain calculation.

Lchain

(M, C) Chain-level demand matrix

Type:

numpy.ndarray

STchain

(M, C) Chain-level service time matrix

Type:

numpy.ndarray

Vchain

(M, C) Chain-level visit ratio matrix

Type:

numpy.ndarray

alpha

(M, K) Class-to-chain weighting matrix

Type:

numpy.ndarray

Nchain

(1, C) Population per chain

Type:

numpy.ndarray

SCVchain

(M, C) Chain-level squared coefficient of variation

Type:

numpy.ndarray

refstatchain

(C, 1) Reference station per chain

Type:

numpy.ndarray

Lchain: numpy.ndarray
STchain: numpy.ndarray
Vchain: numpy.ndarray
alpha: numpy.ndarray
Nchain: numpy.ndarray
SCVchain: numpy.ndarray
refstatchain: numpy.ndarray
sn_deaggregate_chain_results(sn, Lchain, ST, STchain, Vchain, alpha, Qchain, Uchain, Rchain, Tchain, Cchain, Xchain)[source]

Calculate class-based performance metrics from chain-level performance measures.

This function disaggregates chain-level performance metrics (queue lengths, utilizations, response times, throughputs) to class-level metrics using the aggregation factors (alpha).

Parameters:
  • sn (NetworkStruct) – NetworkStruct object for the queueing network model

  • Lchain (numpy.ndarray) – (M, C) Service demands per chain

  • ST (numpy.ndarray | None) – (M, K) Mean service times per class (optional, computed from rates if None)

  • STchain (numpy.ndarray) – (M, C) Mean service times per chain

  • Vchain (numpy.ndarray) – (M, C) Mean visits per chain

  • alpha (numpy.ndarray) – (M, K) Class aggregation coefficients

  • Qchain (numpy.ndarray | None) – (M, C) Mean queue-lengths per chain (optional)

  • Uchain (numpy.ndarray | None) – (M, C) Mean utilization per chain (optional)

  • Rchain (numpy.ndarray) – (M, C) Mean response time per chain

  • Tchain (numpy.ndarray) – (M, C) Mean throughput per chain

  • Cchain (numpy.ndarray | None) – (1, C) Mean system response time per chain. MATLAB (sn_deaggregate_chain_results.m) rejects a non-empty Cchain and always derives C from Little’s law; callers therefore pass None/empty and C is computed as njobs/X, matching MATLAB. A non-empty Cchain is accepted here as an optional extension (disaggregated via alpha at the reference station) but is never supplied on the standard solver paths.

  • Xchain (numpy.ndarray) – (1, C) Mean system throughput per chain

Returns:

  • Q: (M, K) queue lengths

  • U: (M, K) utilizations

  • R: (M, K) response times

  • T: (M, K) throughputs

  • C: (1, K) system response times (Little’s law: njobs/X)

  • X: (1, K) system throughputs

Return type:

SnDeaggregateResult containing class-level performance metrics

class SnDeaggregateResult(Q, U, R, T, C, X)[source]

Bases: object

Result of sn_deaggregate_chain_results calculation.

Q

(M, K) Class-level queue lengths

Type:

numpy.ndarray

U

(M, K) Class-level utilizations

Type:

numpy.ndarray

R

(M, K) Class-level response times

Type:

numpy.ndarray

T

(M, K) Class-level throughputs

Type:

numpy.ndarray

C

(1, K) Class-level system response times

Type:

numpy.ndarray

X

(1, K) Class-level system throughputs

Type:

numpy.ndarray

Q: numpy.ndarray
U: numpy.ndarray
R: numpy.ndarray
T: numpy.ndarray
C: numpy.ndarray
X: numpy.ndarray
class ProductFormParams(lam, D, N, Z, mu, S, V)[source]

Bases: NamedTuple

Result of sn_get_product_form_params calculation.

Create new instance of ProductFormParams(lam, D, N, Z, mu, S, V)

D: numpy.ndarray

Alias for field number 1

N: numpy.ndarray

Alias for field number 2

S: numpy.ndarray

Alias for field number 5

V: numpy.ndarray

Alias for field number 6

Z: numpy.ndarray

Alias for field number 3

lam: numpy.ndarray

Alias for field number 0

mu: numpy.ndarray

Alias for field number 4

sn_get_product_form_params(sn)[source]

Extract standard product-form parameters from the network structure.

This function extracts class-level parameters from a network structure for use in product-form queueing network analysis.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

  • lam: Arrival rates for open classes

  • D: Service demands at queueing stations

  • N: Population vector

  • Z: Think times (service demands at delay stations)

  • mu: Load-dependent service capacity scaling factors

  • S: Number of servers at queueing stations

  • V: Visit ratios

Return type:

ProductFormParams containing

References

MATLAB: matlab/src/api/sn/sn_get_product_form_params.m

sn_get_residt_from_respt(sn, RN, WH=None)[source]

Compute residence times from response times.

This function converts response times to residence times by accounting for visit ratios at each station.

Parameters:
  • sn (NetworkStruct) – NetworkStruct object

  • RN (numpy.ndarray) – Average response times (M, K)

  • WH (Dict | None) – Residence time handles (optional)

Returns:

Average residence times (M, K)

Return type:

WN

References

MATLAB: matlab/src/api/sn/sn_get_residt_from_respt.m

sn_get_state_aggr(sn)[source]

Get aggregated state representation.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

Dictionary mapping stateful node index to aggregated state

Return type:

Dict[int, numpy.ndarray]

References

MATLAB: matlab/src/api/sn/sn_get_state_aggr.m

sn_set_arrival(sn, station_idx, class_idx, rate)[source]

Set arrival rate for a class at a station.

Parameters:
  • sn (NetworkStruct) – NetworkStruct object (modified in place)

  • station_idx (int) – Station index (0-based)

  • class_idx (int) – Class index (0-based)

  • rate (float) – Arrival rate

References

MATLAB: matlab/src/api/sn/sn_set_arrival.m

sn_set_service(sn, station_idx, class_idx, rate, scv=1.0)[source]

Set service rate for a class at a station.

Parameters:
  • sn (NetworkStruct) – NetworkStruct object (modified in place)

  • station_idx (int) – Station index (0-based)

  • class_idx (int) – Class index (0-based)

  • rate (float) – Service rate

  • scv (float) – Squared coefficient of variation (default 1.0 for exponential)

References

MATLAB: matlab/src/api/sn/sn_set_service.m

sn_set_servers(sn, station_idx, nservers)[source]

Set number of servers at a station.

Parameters:
  • sn (NetworkStruct) – NetworkStruct object (modified in place)

  • station_idx (int) – Station index (0-based)

  • nservers (int) – Number of servers

References

MATLAB: matlab/src/api/sn/sn_set_servers.m

sn_set_population(sn, class_idx, njobs)[source]

Set population for a class.

Parameters:
  • sn (NetworkStruct) – NetworkStruct object (modified in place)

  • class_idx (int) – Class index (0-based)

  • njobs (float) – Number of jobs (inf for open class)

References

MATLAB: matlab/src/api/sn/sn_set_population.m

sn_set_priority(sn, class_idx, priority)[source]

Set priority for a class.

Parameters:
  • sn (NetworkStruct) – NetworkStruct object (modified in place)

  • class_idx (int) – Class index (0-based)

  • priority (int) – Priority level (lower = more priority; 0 is highest)

References

MATLAB: matlab/src/api/sn/sn_set_priority.m

sn_set_routing(sn, source_node, dest_node, source_class, dest_class, prob)[source]

Set routing probability between nodes and classes.

Parameters:
  • sn (NetworkStruct) – NetworkStruct object (modified in place)

  • source_node (int) – Source node index (0-based)

  • dest_node (int) – Destination node index (0-based)

  • source_class (int) – Source class index (0-based)

  • dest_class (int) – Destination class index (0-based)

  • prob (float) – Routing probability

References

MATLAB: matlab/src/api/sn/sn_set_routing.m

sn_refresh_visits(sn)[source]

Refresh visit ratios from routing matrix.

This function solves traffic equations to compute visit ratios at each station from the routing probability matrix.

Parameters:

sn (NetworkStruct) – NetworkStruct object (modified in place)

References

MATLAB: matlab/src/api/sn/sn_refresh_visits.m

sn_set_fork_fanout(sn, fork_node_idx, fan_out)[source]

Set fork fanout (tasksPerLink) for a Fork node.

Updates the fanOut field in nodeparam for a Fork node.

Parameters:
  • sn (NetworkStruct) – NetworkStruct object

  • fork_node_idx (int) – Node index of the Fork node (0-based)

  • fan_out (int) – Number of tasks per output link (>= 1)

Returns:

Modified NetworkStruct

Raises:

ValueError – If the specified node is not a Fork node

Return type:

NetworkStruct

References

MATLAB: matlab/src/api/sn/sn_set_fork_fanout.m

sn_set_service_batch(sn, rates, scvs=None, auto_refresh=False)[source]

Set service rates for multiple station-class pairs.

Batch update of service rates. NaN values are skipped (not updated). More efficient than calling sn_set_service multiple times.

Parameters:
  • sn (NetworkStruct) – NetworkStruct object

  • rates (numpy.ndarray) – Matrix of new rates (nstations x nclasses), NaN = skip

  • scvs (numpy.ndarray | None) – Matrix of new SCVs (optional)

  • auto_refresh (bool) – If True, refresh process fields (default False)

Returns:

Modified NetworkStruct

Return type:

NetworkStruct

References

MATLAB: matlab/src/api/sn/sn_set_service_batch.m

sn_nonmarkov_toph(sn, options=None)[source]

Convert non-Markovian distributions to Phase-Type using approximation.

This function scans all service and arrival processes in the network structure and converts non-Markovian distributions to Markovian Arrival Processes (MAPs) using the specified approximation method.

Supported non-Markovian distributions: - GAMMA: Gamma distribution - WEIBULL: Weibull distribution - LOGNORMAL: Lognormal distribution - PARETO: Pareto distribution - UNIFORM: Uniform distribution - DET: Deterministic (converted to Erlang)

Parameters:
  • sn (NetworkStruct) – NetworkStruct object (from getStruct())

  • options (Dict[str, Any] | None) – Solver options dict with fields: - config.nonmkv: Method for conversion (‘none’, ‘bernstein’) - config.nonmkvorder: Number of phases for approximation (default 20) - config.preserveDet: Keep deterministic distributions (for MAP/D/c)

Returns:

Modified NetworkStruct with converted processes

Return type:

NetworkStruct

References

MATLAB: matlab/src/api/sn/sn_nonmarkov_toph.m

class ChainParams(lambda_vec, D, N, Z, mu, S, V)[source]

Bases: object

Chain-aggregated product-form parameters.

lambda_vec: numpy.ndarray
D: numpy.ndarray
N: numpy.ndarray
Z: numpy.ndarray
mu: numpy.ndarray
S: numpy.ndarray
V: numpy.ndarray
sn_get_arvr_from_tput(sn, TN, TH=None)[source]

Compute average arrival rates at stations from throughputs.

Calculates the average arrival rate at each station in steady-state from the station throughputs and routing matrix.

Parameters:
Returns:

Average arrival rates at stations (M x R)

Return type:

AN

References

Original MATLAB: matlab/src/api/sn/sn_get_arvr_from_tput.m

sn_get_node_arvr_from_tput(sn, TN, TH=None, AN=None)[source]

Compute node arrival rates from station throughputs.

This function handles: - Station nodes: Uses station arrival rates directly - Cache nodes: Only requesting classes arrive (not hit/miss classes) - Non-station nodes (ClassSwitch, Sink): Uses nodevisits-based computation

Parameters:
Returns:

Node arrival rates (I x R)

Return type:

ANn

References

Original MATLAB: matlab/src/api/sn/sn_get_node_arvr_from_tput.m

sn_get_node_tput_from_tput(sn, TN, TH=None, ANn=None)[source]

Compute node throughputs from station throughputs.

This function handles: - Station nodes: Uses station throughputs directly - Cache nodes: Uses actual hit/miss probabilities if available - Non-station nodes: Uses routing matrix (rtnodes) for computation

Parameters:
Returns:

Node throughputs (I x R)

Return type:

TNn

References

Original MATLAB: matlab/src/api/sn/sn_get_node_tput_from_tput.m

sn_get_product_form_chain_params(sn)[source]

Extract product-form parameters aggregated by chain.

Extracts parameters from a network structure and aggregates them by chain for use in product-form analysis methods.

Parameters:

sn (NetworkStruct) – Network structure

Returns:

ChainParams with lambda_vec, D, N, Z, mu, S, V

Return type:

ChainParams

References

Original MATLAB: matlab/src/api/sn/sn_get_product_form_chain_params.m

sn_set_routing_prob(sn, from_stateful, from_class, to_stateful, to_class, prob, auto_refresh=False)[source]

Set a routing probability between two stateful node-class pairs.

Updates a single entry in the rt matrix.

Parameters:
  • sn (NetworkStruct) – Network structure

  • from_stateful (int) – Source stateful node index (0-based)

  • from_class (int) – Source class index (0-based)

  • to_stateful (int) – Destination stateful node index (0-based)

  • to_class (int) – Destination class index (0-based)

  • prob (float) – Routing probability [0, 1]

  • auto_refresh (bool) – If True, refresh visit ratios (default False)

Returns:

Modified network structure

Return type:

NetworkStruct

References

Original MATLAB: matlab/src/api/sn/sn_set_routing_prob.m

sn_is_closed_model(sn)[source]

Check if the network model is closed (all finite populations).

A closed model has all finite job populations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if the network is a closed model

Return type:

bool

sn_is_open_model(sn)[source]

Check if the network model is open (all infinite populations).

An open model has only infinite (open) job classes.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if the network is an open model

Return type:

bool

sn_is_mixed_model(sn)[source]

Check if the network model is mixed (both open and closed classes).

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if the network has both open and closed classes

Return type:

bool

sn_is_population_model(sn)[source]

Check if the network model is a population model.

A population model uses only delay-like scheduling strategies (INF, PS, PSPRIO, DPS, GPS, GPSPRIO, DPSPRIO, EXT), has no priorities, and no fork-join topology.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if model is population-based

Return type:

bool

sn_has_closed_classes(sn)[source]

Check if the network has closed (finite population) classes.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one closed class

Return type:

bool

sn_has_open_classes(sn)[source]

Check if the network has open (infinite population) classes.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one open class

Return type:

bool

sn_has_mixed_classes(sn)[source]

Check if the network has both open and closed classes.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has both open and closed classes

Return type:

bool

sn_has_single_class(sn)[source]

Check if the network has exactly one class.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has exactly one class

Return type:

bool

sn_has_multi_class(sn)[source]

Check if the network has multiple classes.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has more than one class

Return type:

bool

sn_has_multiple_closed_classes(sn)[source]

Check if the network has multiple closed classes.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has more than one closed class

Return type:

bool

sn_has_single_chain(sn)[source]

Check if the network has exactly one chain.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has exactly one chain

Return type:

bool

sn_has_multi_chain(sn)[source]

Check if the network has multiple chains.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has more than one chain

Return type:

bool

sn_has_fcfs(sn)[source]

Check if the network has any FCFS (First-Come First-Served) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one FCFS station

Return type:

bool

sn_has_ps(sn)[source]

Check if the network has any PS (Processor Sharing) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one PS station

Return type:

bool

sn_has_inf(sn)[source]

Check if the network has any INF (Infinite Server/Delay) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one INF station

Return type:

bool

sn_has_lcfs(sn)[source]

Check if the network has any LCFS (Last-Come First-Served) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one LCFS station

Return type:

bool

sn_has_lcfspr(sn)[source]

Check if the network has any LCFS-PR (LCFS Preemptive Resume) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one LCFS-PR station

Return type:

bool

sn_has_lcfs_pr(sn)[source]

Check if the network has any LCFS-PR (LCFS Preemptive Resume) stations.

This is an alias for sn_has_lcfspr, matching the MATLAB function name.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one LCFS-PR station

Return type:

bool

sn_has_lcfs_pi(sn)[source]

Check if the network has any LCFS-PI (LCFS Preemptive Identical) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one LCFS-PI station

Return type:

bool

sn_has_siro(sn)[source]

Check if the network has any SIRO (Service In Random Order) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one SIRO station

Return type:

bool

sn_has_dps(sn)[source]

Check if the network has any DPS (Discriminatory Processor Sharing) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one DPS station

Return type:

bool

sn_has_dps_prio(sn)[source]

Check if the network has any DPS with priority stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one DPS-PRIO station

Return type:

bool

sn_has_gps(sn)[source]

Check if the network has any GPS (Generalized Processor Sharing) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one GPS station

Return type:

bool

sn_has_gps_prio(sn)[source]

Check if the network has any GPS with priority stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one GPS-PRIO station

Return type:

bool

sn_has_ps_prio(sn)[source]

Check if the network has any PS with priority stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one PS-PRIO station

Return type:

bool

sn_has_hol(sn)[source]

Check if the network has any HOL (Head of Line) priority stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one HOL station

Return type:

bool

sn_has_lps(sn)[source]

Check if the network has any LPS (Least Progress Scheduling) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one LPS station

Return type:

bool

sn_has_setf(sn)[source]

Check if the network has any SETF (Shortest Elapsed Time First) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one SETF station

Return type:

bool

sn_has_sept(sn)[source]

Check if the network has any SEPT (Shortest Expected Processing Time) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one SEPT station

Return type:

bool

sn_has_lept(sn)[source]

Check if the network has any LEPT (Longest Expected Processing Time) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one LEPT station

Return type:

bool

sn_has_sjf(sn)[source]

Check if the network has any SJF (Shortest Job First) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one SJF station

Return type:

bool

sn_has_ljf(sn)[source]

Check if the network has any LJF (Longest Job First) stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one LJF station

Return type:

bool

sn_has_polling(sn)[source]

Check if the network has any polling stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has at least one polling station

Return type:

bool

sn_has_homogeneous_scheduling(sn, strategy)[source]

Check if the network uses an identical scheduling strategy at every station.

Parameters:
  • sn (NetworkStruct) – NetworkStruct object

  • strategy (int) – SchedStrategy value to check for

Returns:

True if all stations use the specified strategy

Return type:

bool

sn_has_multi_class_fcfs(sn)[source]

Check if the network has an FCFS station that serves multiple classes.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if any FCFS station serves more than one class

Return type:

bool

sn_has_multi_class_heter_fcfs(sn)[source]

Check if network has multiclass heterogeneous FCFS stations.

A heterogeneous FCFS station has different service rates for different classes. Uses MATLAB’s range() check: max(rates) - min(rates) > 0 across all classes at each FCFS station.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has FCFS stations with heterogeneous class rates

Return type:

bool

sn_has_multi_class_heter_exp_fcfs(sn)[source]

Check if network has multiclass heterogeneous exponential FCFS stations.

Returns true if any FCFS station has heterogeneous rates AND all service time SCVs at that station are approximately 1.0 (exponential).

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has FCFS stations with heterogeneous exponential service

Return type:

bool

sn_has_multi_server(sn)[source]

Check if the network has any multi-server stations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if any station has more than one server

Return type:

bool

sn_has_load_dependence(sn)[source]

Check if the network has load-dependent service.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has load-dependent scaling

Return type:

bool

sn_has_fork_join(sn)[source]

Check if the network uses fork and/or join nodes.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has fork-join topology

Return type:

bool

sn_has_priorities(sn)[source]

Check if the network uses class priorities.

In LINE, priority 0 is default (no priority). Values > 0 indicate priority classes are in use.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if any class has priority > 0

Return type:

bool

sn_has_class_switching(sn)[source]

Check if the network has class switching.

Class switching is indicated by the number of classes differing from the number of chains.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if number of classes differs from number of chains

Return type:

bool

sn_has_fractional_populations(sn)[source]

Check if the network has fractional (non-integer) populations.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if any class has fractional population

Return type:

bool

sn_has_sd_routing(sn)[source]

Check if the network has state-dependent routing strategies.

State-dependent routing strategies violate the product-form assumption. These include Round-Robin, Weighted Round-Robin, Join Shortest Queue, Power of K Choices, and Reinforcement Learning.

Product-form requires state-independent (Markovian) routing. PROB and RAND are product-form compatible.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has state-dependent routing

Return type:

bool

sn_has_product_form(sn)[source]

Check if the network has a known product-form solution.

A network has product form if: - All stations use INF, PS, FCFS, LCFS-PR, or EXT scheduling - No multiclass heterogeneous FCFS - No priorities - No fork-join

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network has product-form solution

Return type:

bool

sn_has_bursty_arrival(sn)[source]

Check whether any external arrival process is bursty (non-renewal).

Returns True if any Source station has an arrival process with autocorrelated inter-arrival times (a non-renewal Markovian arrival process such as an MMPP/MAP), as opposed to a renewal process (Poisson, or any i.i.d. renewal process such as Erlang/HyperExp/Coxian/APH). Detection is exact: a MAP with matrices (D0,D1) is renewal iff D1 equals its rank-one renewal form t0*pie, where t0 = -D0*e and pie is the embedded stationary vector; any departure signals correlation between inter-arrival times.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if some external arrival process is non-renewal (bursty).

Return type:

bool

sn_has_product_form_not_het_fcfs(sn)[source]

Check if network has product form except for heterogeneous FCFS.

This checks: - All stations use INF, PS, FCFS, LCFSPR, or EXT scheduling - No priorities, no fork-join, no state-dependent routing - At FCFS stations, all active class SCVs are approximately 1 (exponential)

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network would have product form without heterogeneous FCFS

Return type:

bool

sn_has_product_form_except_multi_class_heter_exp_fcfs(sn)[source]

Check if network has product form except for multiclass heterogeneous exponential FCFS.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if network would have product form without multiclass heter exp FCFS

Return type:

bool

sn_is_state_valid(sn)[source]

Check if the network state is valid.

Parameters:

sn (NetworkStruct) – NetworkStruct object

Returns:

True if state is valid

Return type:

bool

sn_fj_visits_spn(sn)[source]

Compute fork-join node visit ratios via auxiliary SPN models.

For each class that passes through a fork-join pair, builds an auxiliary closed SPN with population B (max leaf count across outermost forks). The SPN is solved with SolverCTMC and the throughput ratios give the per-node visit ratios.

Parameters:

sn (NetworkStruct) – NetworkStruct describing the queueing network.

Returns:

List of numpy arrays (one per chain), each of shape (nnodes, nclasses) with visit ratios normalized so the reference station has value 1.

Return type:

List[numpy.ndarray]

sn_print(sn, file=None)[source]

Print comprehensive information about a NetworkStruct object.

This function displays all fields, matrices, lists, and maps in a formatted manner useful for debugging and inspection of network structures.

Parameters:
  • sn (NetworkStruct) – Network structure to inspect

  • file – Output file (default: sys.stdout)

References

MATLAB: matlab/src/api/sn/sn_print.m

sn_print_routing_matrix(sn, onlyclass=None, file=None)[source]

Print the routing matrix of the network.

This function displays the routing probabilities between nodes and classes in a human-readable format.

Parameters:
  • sn (NetworkStruct) – Network structure

  • onlyclass (Any | None) – Optional filter for a specific class (object with ‘name’ attribute)

  • file – Output file (default: sys.stdout)

References

MATLAB: matlab/src/api/sn/sn_print_routing_matrix.m

sn_refresh_process_fields(sn, station_idx, class_idx)[source]

Refresh process fields based on rate and SCV values.

Updates mu, phi, proc, pie, phases based on current rate and SCV values. - SCV = 1.0: Exponential (1 phase) - SCV < 1.0: Erlang approximation - SCV > 1.0: Hyperexponential(2) approximation

Parameters:
  • sn (NetworkStruct) – Network structure (modified in place)

  • station_idx (int) – Station index (0-based)

  • class_idx (int) – Class index (0-based)

Returns:

Modified network structure

Return type:

NetworkStruct

References

MATLAB: matlab/src/api/sn/sn_refresh_process_fields.m

sn_rtnodes_to_rtorig(sn)[source]

Convert node routing matrix to the original routing matrix format.

This function converts the node-level routing matrix to the original routing matrix format, excluding class-switching nodes.

Parameters:

sn (NetworkStruct) – Network structure

Returns:

rtorigcell: Dictionary representation {(r,s): ndarray} rtorig: Sparse/dense matrix representation

Return type:

Tuple of (rtorigcell, rtorig) where

References

MATLAB: matlab/src/api/sn/sn_rtnodes_to_rtorig.m

Non-Product-Form Networks (line_solver.api.npfqn)

Non-Product-Form Queueing Network (NPFQN) algorithms.

Native Python implementations for approximating performance of non-product-form queueing networks.

Key algorithms:

npfqn_nonexp_approx: Non-exponential distribution approximation npfqn_traffic_merge: Merge multiple MMAP traffic flows npfqn_traffic_merge_cs: Merge traffic flows with class switching npfqn_traffic_split_cs: Split traffic flows with class switching

npfqn_nonexp_approx(method, sn, ST, V, SCV, Tin, Uin, gamma, nservers)[source]

Approximates non-product-form queueing networks using the specified method.

This function adjusts service times and other parameters to account for non-exponential service time distributions in product-form analysis.

Parameters:
  • method (str) – Approximation method (“default”, “none”, “hmva”, “interp”)

  • sn (NetworkStruct) – Network structure

  • ST (numpy.ndarray) – Service time matrix (M x K)

  • V (numpy.ndarray | None) – Visit ratios matrix (M x K), optional

  • SCV (numpy.ndarray) – Squared coefficient of variation matrix (M x K)

  • Tin (numpy.ndarray) – Initial throughput matrix (M x K)

  • Uin (numpy.ndarray) – Initial utilization matrix (M x K)

  • gamma (numpy.ndarray) – Gamma correction matrix (M x 1)

  • nservers (numpy.ndarray) – Number of servers matrix (M x 1)

Returns:

NpfqnNonexpApproxResult with updated matrices

Raises:

ValueError – If unknown approximation method is specified

Return type:

NpfqnNonexpApproxResult

class NpfqnNonexpApproxResult(ST, gamma, nservers, rho, scva, scvs, eta)[source]

Bases: object

Result of non-exponential approximation.

ST: numpy.ndarray
gamma: numpy.ndarray
nservers: numpy.ndarray
rho: numpy.ndarray
scva: numpy.ndarray
scvs: numpy.ndarray
eta: numpy.ndarray
npfqn_traffic_merge(MMAPa, config_merge='default', config_compress=None)[source]

Merge multiple MMAP traffic flows.

Combines multiple MMAPs using specified aggregation strategies. Supports various merge configurations for different network topologies.

Parameters:
  • MMAPa (Dict[int, List[numpy.ndarray] | None]) – Dictionary of MMAP traffic flows to be merged. Keys are integer indices, values are MMAP lists [D0, D1, …].

  • config_merge (str) – Merge configuration. Options: - “default”, “super”: Use MMAP superposition - “mixture”: Apply mixture fitting after superposition - “interpos”: Interposition method (falls back to super)

  • config_compress (str | None) – Compression configuration. Options: - None, “none”: No compression - “default”: Apply default compression

Returns:

Merged and normalized MMAP, or None if input is empty.

Raises:

RuntimeError – If unsupported merge configuration is provided.

Return type:

List[numpy.ndarray] | None

Example

>>> mmap1 = [np.array([[-1.0]]), np.array([[1.0]])]
>>> mmap2 = [np.array([[-2.0]]), np.array([[2.0]])]
>>> result = npfqn_traffic_merge({0: mmap1, 1: mmap2})
npfqn_traffic_merge_cs(MMAPs, prob, config='default')[source]

Merge MMAP traffic flows with class switching.

Combines multiple MMAPs while applying class switching transformations based on the probability matrix.

Parameters:
  • MMAPs (Dict[int, List[numpy.ndarray]]) – Dictionary of MMAP traffic flows indexed by source.

  • prob (numpy.ndarray) –

    Class switching probability matrix ((n*R) x R) where: - n is the number of sources - R is the number of classes - prob[(i-1)*R + r, s] = probability that class r from source i

    becomes class s in the merged stream

  • config (str) – Merge configuration (“default” or “super”).

Returns:

Merged MMAP with class switching applied, or None if empty.

Return type:

List[numpy.ndarray] | None

Algorithm:
  1. Apply mmap_mark to each source MMAP to encode class switching

  2. Superpose all marked MMAPs

  3. Return result

Example

>>> mmap1 = [np.array([[-1.0]]), np.array([[0.5]]), np.array([[0.5]])]
>>> mmap2 = [np.array([[-2.0]]), np.array([[1.0]]), np.array([[1.0]])]
>>> prob = np.array([[0.8, 0.2], [0.3, 0.7], [0.6, 0.4], [0.5, 0.5]])
>>> result = npfqn_traffic_merge_cs({0: mmap1, 1: mmap2}, prob)
npfqn_traffic_split_cs(MMAP_input, P)[source]

Split MMAP traffic flows with class switching.

Decomposes a single MMAP into multiple MMAPs based on routing probabilities and class switching matrix.

Parameters:
  • MMAP_input (List[numpy.ndarray]) – Input MMAP as list [D0, D1, D2, …].

  • P (numpy.ndarray) –

    Class switching probability matrix (R x J) where: - R is the number of arrival classes - J = M * R where M is the number of destinations - P[r, (jst-1)*R + s] = probability that class r arrival

    becomes class s at destination jst

Returns:

Dictionary mapping destination index to split MMAP. Keys are 0-indexed destination indices.

Return type:

Dict[int, List[numpy.ndarray] | None]

Algorithm:
  1. Parse dimensions from P matrix

  2. For each destination, create MMAP with weighted marking matrices

  3. Normalize each result

Example

>>> mmap = [np.array([[-3.0]]), np.array([[1.0]]), np.array([[2.0]])]
>>> P = np.array([[0.8, 0.2, 0.5, 0.5], [0.3, 0.7, 0.6, 0.4]])
>>> result = npfqn_traffic_split_cs(mmap, P)
npfqn_sqd(sn, N=None, calibration_mode=0, server_blocking_time=True, neighbor_mode='downstream', v1_policy='compound', initial_v1=None)[source]

Solve a BAS closed network from its NetworkStruct.

Parameters:
  • sn (NetworkStruct) – chain-aggregated network structure

  • N (int | None) – total closed-class population (defaults to sn.nclosedjobs)

  • calibration_mode (int) – 0=base, 1=fixed heuristic, 2=blocking-aware

  • server_blocking_time (bool) – add a manufacturing-blocking term to server time

  • neighbor_mode (str) – ‘downstream’ (routed) or ‘ownserver’ blocking aggregation

  • v1_policy (str) – ‘compound’ or ‘fresh’ load-dependent rate-scale update

  • initial_v1 (numpy.ndarray | None) – optional per-station initial V1 (None = _INITIAL_V1)

Returns:

NpfqnSqdResult with per-station X, Q, U, R.

Return type:

NpfqnSqdResult

class NpfqnSqdResult(X, Q, U, R)[source]

Bases: object

Per-station results of the BAS approximation (single chain).

X

(M,) per-station throughput

Type:

numpy.ndarray

Q

(M,) per-station queue length

Type:

numpy.ndarray

U

(M,) per-station utilization

Type:

numpy.ndarray

R

(M,) per-station residence time

Type:

numpy.ndarray

X: numpy.ndarray
Q: numpy.ndarray
U: numpy.ndarray
R: numpy.ndarray
npfqn_rqna_weight(t)[source]

Canonical RBM correlation weight function w*(t) used by the RQNA.

w*(t) = 1 - (1 - c*(t))/(2 t), where c*(t) is the correlation function of the stationary version of canonical reflected Brownian motion (drift -1, diffusion coefficient 1),

c*(t) = 2(1 - 2t - t^2) Phi^c(sqrt(t)) + 2 sqrt(t) phi(sqrt(t)) (1 + t),

with Phi^c the standard-normal complementary cdf and phi its density. The weight is monotonically increasing with w*(0)=0 and w*(Inf)=1.

Reference: Whitt and You (2018), eqs. (24)-(25).

Parameters:

t – scalar or array of nonnegative time arguments

Returns:

Weight(s) w*(t) in [0,1], same shape as t (scalar in -> float out).

npfqn_traffic_idc(lambda0, P, c2a0, a0IdcFun, mu, cs2, sIdcFun, corrections=None)[source]
Traffic variability equations for the RQNA. Assembles and solves:
  • the limiting variability equations (eq. 42/44) for the asymptotic total-arrival variability parameters c2_{a,i} = I_{a,i}(Inf);

  • a solver (ctx.IaFun) for the time-dependent IDC equations (eq. 40/43), returning I_{a,i}(t) for all internal arrival flows, using the default correction terms alpha_{i,j} (eq. 34) and beta_i (eqs. 38-39) and tuning function h(rho)=rho^2.

Models a single-class open network of K single-server FCFS queues with Markovian routing P (P[i,j]=p_{i,j}).

Parameters:
  • lambda0 – (K,) external arrival rate into each queue

  • P – (K,K) routing matrix among queues

  • c2a0 – (K,) asymptotic IDC (SCV) of each external arrival process

  • a0IdcFun – callable a0IdcFun(t) -> (K,) external arrival IDC I_{a,0,i}(t)

  • mu – (K,) service rate at each queue

  • cs2 – (K,) service SCV c2_{s,i}

  • sIdcFun – callable sIdcFun(t) -> (K,) service IDC I_{s,i}(t)

  • corrections – optional dict with ‘alpha’/’beta’ bool toggles

Returns:

_TrafficIdcContext with lambda, rho, Xi, c2a, c2d, c2aij, c2x fields and method IaFun(t).

Polling Systems (line_solver.api.polling)

Polling System Analysis Algorithms.

Native Python implementations for analyzing polling/vacation queue systems with various disciplines.

Key algorithms:

polling_qsys_exhaustive: Exhaustive polling discipline polling_qsys_gated: Gated polling discipline polling_qsys_1limited: 1-Limited polling discipline

polling_qsys_exhaustive(arvMAPs, svcMAPs, switchMAPs)[source]

Compute exact mean waiting times for exhaustive polling system.

In exhaustive polling, the server continues to serve a queue until it becomes empty before moving to the next queue.

Based on Takagi, ACM Computing Surveys, Vol. 20, No. 1, 1988, eq (15).

Parameters:
Returns:

Array of mean waiting times for each queue.

Return type:

numpy.ndarray

polling_qsys_gated(arvMAPs, svcMAPs, switchMAPs)[source]

Compute exact mean waiting times for gated polling system.

In gated polling, the server serves all customers present at the beginning of a visit period.

Based on Takagi, ACM Computing Surveys, Vol. 20, No. 1, 1988, eq (20).

Parameters:
Returns:

Array of mean waiting times for each queue.

Return type:

numpy.ndarray

polling_qsys_1limited(arvMAPs, svcMAPs, switchMAPs)[source]

Compute exact mean waiting times for 1-limited polling system.

In 1-limited polling, the server serves at most one customer from each queue before moving to the next queue.

Based on Takagi, ACM Computing Surveys, Vol. 20, No. 1, 1988, eq (20).

Parameters:
Returns:

Array of mean waiting times for each queue.

Return type:

numpy.ndarray

polling_qsys_decrementing(arvMAPs, svcMAPs, switchMAPs)[source]

Compute exact mean waiting times for a symmetric decrementing (semiexhaustive) polling system with open (Poisson) arrivals.

In decrementing service, the server serves a queue until the number of jobs present drops to one less than the number found at the polling instant. The symmetric system admits the exact closed form of Pittel (1973) and Takagi (1984); see Takagi, ACM Computing Surveys, Vol. 20, No. 1, 1988, eq (28). No exact closed form for the individual E[W_i] is known for asymmetric decrementing systems, so this analysis is restricted to the symmetric case.

Parameters:
Returns:

Array of mean waiting times for each queue (all equal, symmetric case).

Return type:

numpy.ndarray

Loss Networks (line_solver.api.lossn)

Loss Network Analysis Algorithms.

Native Python implementations for analyzing loss networks using Erlang formulas and related methods.

Key algorithms:

lossn_erlangfp: Erlang fixed-point algorithm for loss networks erlang_b: Erlang B blocking probability erlang_c: Erlang C delay probability

lossn_erlangfp(nu, A, c, tol=1e-8, max_iter=1000)[source]

Erlang fixed point approximation for loss networks.

Calls (jobs) on route (class) r arrive according to Poisson rate nu_r. Call service times on route r have unit mean.

The link capacity requirements are:

sum_r A[j,r] * n[j,r] < c[j]

for all links j, where n[j,r] counts calls on route r on link j.

Parameters:
  • nu (numpy.ndarray) – Arrival rates vector (R,) for each route.

  • A (numpy.ndarray) – Capacity requirement matrix (J, R) - A[j,r] is capacity required on link j by route r.

  • c (numpy.ndarray) – Capacity vector (J,) - c[j] is capacity of link j.

  • tol (float) – Convergence tolerance.

  • max_iter (int) – Maximum iterations.

Returns:

  • qlen: Mean queue-length for each route (R,)

  • loss: Loss probability for each route (R,)

  • eblock: Blocking probability for each link (J,)

  • niter: Number of iterations

Return type:

Tuple of (qlen, loss, eblock, niter) where

Example

>>> nu = np.array([0.3, 0.1])
>>> A = np.array([[1, 1], [1, 4]])  # 2 links, 2 routes
>>> c = np.array([1, 3])
>>> qlen, loss, eblock, niter = lossn_erlangfp(nu, A, c)
erlang_b(offered_load, servers)[source]

Compute Erlang B blocking probability.

The Erlang B formula gives the probability that an arriving call is blocked in an M/M/c/c loss system.

Parameters:
  • offered_load (float) – Traffic intensity (arrival rate * service time).

  • servers (int) – Number of servers.

Returns:

Blocking probability.

Return type:

float

Example

>>> erlang_b(10.0, 12)  # Offered load 10 Erlang, 12 channels
0.1054...
erlang_c(offered_load, servers)[source]

Compute Erlang C delay probability.

The Erlang C formula gives the probability that an arriving call must wait in an M/M/c queue.

Parameters:
  • offered_load (float) – Traffic intensity (arrival rate * service time).

  • servers (int) – Number of servers.

Returns:

Delay probability (probability of waiting).

Return type:

float

Example

>>> erlang_c(10.0, 12)  # Offered load 10 Erlang, 12 agents
lossn_mci(nu, A, C, samples=100000, gamma=None, seed=None, alpha=0.05)[source]

Monte Carlo importance-sampling summation for loss networks.

A loss network has links j=1..J with capacity C[j] and classes r=1..R with offered load nu[r] and per-link circuit requirement A[j,r]. The state n is feasible iff A @ n <= C (set Omega). The product-form normalization constant is g(C) = sum_{n in Omega} prod_r nu[r]**n_r/n_r!. Class-r acceptance is g(C-A[:,r])/g(C) = 1 - beta_r.

States are drawn from the importance distribution (Eq. 6)

p(n) = (1/c) prod_r gamma_r**n_r / n_r!

over the box {0..N_1} x … x {0..N_R}, N_r = min_j floor(C_j/A_jr). Ratio estimators (Eq. 8) yield g and blocking with delta-method confidence intervals.

Parameters:
  • nu (numpy.ndarray) – Offered load per class (R,).

  • A (numpy.ndarray) – Circuit requirement matrix (J, R).

  • C (numpy.ndarray) – Link capacity vector (J,).

  • samples (int) – Number of Monte Carlo samples.

  • gamma (numpy.ndarray | None) – Importance-sampling parameters (R,); default is the Section 3.4 heuristic.

  • seed (int | None) – RNG seed for reproducibility.

  • alpha (float) – Confidence-interval significance level (default 0.05).

Returns:

  • qlen: Mean carried load E[n_r] per class (R,).

  • loss: Blocking probability beta_r per class (R,).

  • lG: Log of the estimated normalization constant g(C).

  • ci: dict with ‘accept’ (R,2), ‘loss’ (R,2), ‘acceptPoint’ (R,), ‘lossPoint’ (R,), ‘level’.

  • nsamples: Number of samples used.

Return type:

Tuple (qlen, loss, lG, ci, nsamples) where

Layered Stochastic Networks (line_solver.api.lsn)

Layered Stochastic Network (LSN) utilities.

Native Python implementations for layered queueing network analysis.

Key functions:

lsn_max_multiplicity: Compute maximum multiplicity for tasks in a layered network.

Key classes:

LayeredNetworkStruct: Structure representing a layered network. LayeredNetworkElement: Enumeration of layered network element types.

class LayeredNetworkElement(*values)[source]

Bases: IntEnum

Types of elements in a layered network.

TASK = 1
ENTRY = 2
ACTIVITY = 3
PROCESSOR = 4
HOST = 5
class LayeredNetworkStruct(dag, mult, type, isref)[source]

Bases: object

Structure representing a layered network for LSN analysis.

dag

Directed acyclic graph adjacency matrix (n x n). dag[i,j] > 0 indicates an edge from node i to node j.

Type:

numpy.ndarray

mult

Multiplicity (max concurrent instances) for each node (n,).

Type:

numpy.ndarray

type

Node type for each node (n,), using LayeredNetworkElement values.

Type:

numpy.ndarray

isref

Reference task flags (n,). Non-zero indicates a reference task.

Type:

numpy.ndarray

dag: numpy.ndarray
mult: numpy.ndarray
type: numpy.ndarray
isref: numpy.ndarray
kahn_topological_sort(adjacency)[source]

Perform Kahn’s algorithm for topological sorting.

Parameters:

adjacency (numpy.ndarray) – Adjacency matrix where adjacency[i,j] > 0 means edge i -> j.

Returns:

List of node indices in topological order.

Raises:

ValueError – If the graph contains a cycle.

Return type:

List[int]

lsn_max_multiplicity(lsn)[source]

Compute the maximum multiplicity for each task in a layered network.

This function uses flow analysis based on Kahn’s topological sorting algorithm to determine the maximum sustainable throughput for each task, considering both the incoming flow and the multiplicity constraints.

Parameters:

lsn (LayeredNetworkStruct) – The layered network structure containing task dependencies and constraints.

Returns:

Matrix of maximum multiplicities for each task in the network (n x 1).

Return type:

numpy.ndarray

Algorithm:
  1. Build binary adjacency graph from DAG

  2. Apply Kahn’s topological sort to determine processing order

  3. Initialize inflow from reference tasks

  4. For each node in topological order: - outflow = min(inflow, multiplicity constraint) - Propagate outflow to downstream nodes

  5. Handle unreachable tasks (infinite multiplicity)

Example

>>> lsn = LayeredNetworkStruct(
...     dag=np.array([[0, 1, 0], [0, 0, 1], [0, 0, 0]]),
...     mult=np.array([2, 3, 5]),
...     type=np.array([1, 1, 1]),
...     isref=np.array([1, 0, 0])
... )
>>> max_mult = lsn_max_multiplicity(lsn)

Trace Analysis (line_solver.api.trace)

Trace Analysis Functions.

Native Python implementations for statistical analysis of empirical trace data including means, variances, correlations, and index of dispersion.

Key functions:

trace_mean: Mean of trace data trace_var: Variance of trace data trace_scv: Squared coefficient of variation trace_acf: Autocorrelation function trace_summary: Comprehensive summary statistics

trace_mean(trace)[source]

Compute the arithmetic mean of trace data.

Parameters:

trace (numpy.ndarray | list) – Array of trace values.

Returns:

Mean value of the trace.

Return type:

float

Example

>>> trace_mean([1.0, 2.0, 3.0, 4.0, 5.0])
3.0
trace_var(trace)[source]

Compute the variance of trace data.

Uses population variance (ddof=0) for consistency with Kotlin.

Parameters:

trace (numpy.ndarray | list) – Array of trace values.

Returns:

Variance of the trace.

Return type:

float

Example

>>> trace_var([1.0, 2.0, 3.0, 4.0, 5.0])
2.0
trace_scv(trace)[source]

Compute the squared coefficient of variation (SCV).

SCV = Var(X) / E[X]^2

Parameters:

trace (numpy.ndarray | list) – Array of trace values.

Returns:

Squared coefficient of variation.

Return type:

float

Example

>>> trace_scv([1.0, 2.0, 3.0])  # Var=0.667, Mean=2, SCV=0.167
trace_acf(trace, lags=None)[source]

Compute the autocorrelation function at specified lags.

Parameters:
Returns:

Array of autocorrelation values at each lag.

Return type:

numpy.ndarray

Example

>>> trace = np.random.randn(100)
>>> acf = trace_acf(trace, [1, 2, 3])
trace_gamma(trace, limit=1000)[source]

Estimate the autocorrelation decay rate of a trace.

Parameters:
Returns:

Array containing [GAMMA, RHO0, RESIDUALS].

Return type:

numpy.ndarray

Example

>>> gamma, rho0, residuals = trace_gamma(trace_data)
trace_iat2counts(trace, scale)[source]

Compute the counting process from inter-arrival times.

Parameters:
Returns:

Array of counts after scale units of time from each arrival.

Return type:

numpy.ndarray

Example

>>> iat = [0.5, 0.3, 0.8, 0.2, 0.4]
>>> counts = trace_iat2counts(iat, 1.0)
trace_idi(trace, kset, option=None, n=1)[source]

Compute the Index of Dispersion for Intervals.

Parameters:
  • trace (numpy.ndarray | list) – Array of trace values.

  • kset (numpy.ndarray | list) – Set of k values to compute IDI for.

  • option (str) – Aggregation option (None, ‘aggregate’, ‘aggregate-mix’).

  • n (int) – Aggregation parameter.

Returns:

Tuple of (IDI values, support values).

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

Example

>>> idi, support = trace_idi(trace_data, [10, 20, 50])
trace_idc(trace)[source]

Compute the Index of Dispersion for Counts.

Asymptotically equal to IDI.

Parameters:

trace (numpy.ndarray | list) – Array of trace values.

Returns:

IDC value.

Return type:

float

Example

>>> idc = trace_idc(inter_arrival_times)
trace_pmf(X)[source]

Compute the probability mass function of discrete data.

Parameters:

X (numpy.ndarray | list) – Array of discrete values.

Returns:

Tuple of (PMF values, unique values).

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

Example

>>> pmf, values = trace_pmf([1, 2, 2, 3, 3, 3])
trace_shuffle(trace)[source]

Shuffle trace data randomly.

Parameters:

trace (numpy.ndarray | list) – Array of trace values.

Returns:

Shuffled trace array.

Return type:

numpy.ndarray

Example

>>> shuffled = trace_shuffle([1, 2, 3, 4, 5])
trace_joint(trace, lag, order)[source]

Compute joint moments E[X^{k_1}_{i} * X^{k_2}_{i+j} * …].

Parameters:
Returns:

Joint moment value.

Return type:

float

Example

>>> jm = trace_joint(trace, [0, 1], [1, 1])  # E[X_i * X_{i+1}]
trace_iat2bins(trace, scale)[source]

Compute counts in bins with specified timescale.

Parameters:
Returns:

Tuple of (counts per bin, bin membership for each element).

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

Example

>>> counts, bins = trace_iat2bins(iat_data, 1.0)
trace_summary(trace)[source]

Compute comprehensive summary statistics for a trace.

Parameters:

trace (numpy.ndarray | list) – Array of trace values.

Returns:

Array containing [MEAN, SCV, MAD, SKEW, KURT, Q25, Q50, Q75, P95, MIN, MAX, IQR, ACF1, ACF2, ACF3, ACF4, IDC_SCV_RATIO].

Return type:

numpy.ndarray

Example

>>> summary = trace_summary(trace_data)
>>> print(f"Mean: {summary[0]}, SCV: {summary[1]}")
trace_bicov(trace, grid)[source]

Compute bicovariance of a trace.

Bicovariance measures third-order correlation structure at multiple lag combinations.

Parameters:
Returns:

  • bicov: Array of bicovariance values

  • bicov_lags: 2D array of lag combinations (each row is [1, i, j])

Return type:

Tuple of (bicov, bicov_lags) where

Example

>>> trace = np.random.randn(1000)
>>> bicov, lags = trace_bicov(trace, [1, 2, 3, 4, 5])
mtrace_mean(trace, ntypes, types)[source]

Compute the mean of a trace, divided by types.

Parameters:
Returns:

Array containing the mean values for each type.

Return type:

numpy.ndarray

Example

>>> trace = [1.0, 2.0, 3.0, 4.0]
>>> types = [0, 1, 0, 1]
>>> means = mtrace_mean(trace, 2, types)
mtrace_var(trace, ntypes, types)[source]

Compute the variance of a trace, divided by types.

Parameters:
Returns:

Array containing the variance values for each type.

Return type:

numpy.ndarray

Example

>>> var_by_type = mtrace_var(trace, 2, types)
mtrace_count(trace, ntypes, types)[source]

Count elements per type in a trace.

Parameters:
Returns:

Array containing counts for each type.

Return type:

numpy.ndarray

Example

>>> counts = mtrace_count(trace, 2, types)
mtrace_sigma(T, L)[source]

Compute one-step class transition probabilities from a marked trace.

Computes P(C_k = j | C_{k-1} = i) empirically from the trace.

Parameters:
Returns:

C x C matrix where element (i,j) is the probability of observing class j after class i.

Return type:

numpy.ndarray

mtrace_sigma2(T, L)[source]

Compute two-step class transition probabilities from a marked trace.

Computes P(C_k = h | C_{k-1} = j, C_{k-2} = i) empirically.

Parameters:
Returns:

C x C x C 3D array of transition probabilities.

Return type:

numpy.ndarray

mtrace_cross_moment(T, L, k)[source]

Compute the k-th order moment of inter-arrival times between class pairs.

Parameters:
Returns:

C x C matrix where element (i,j) is E[T^k | C_{t-1} = i, C_t = j]

Return type:

numpy.ndarray

mtrace_forward_moment(T, A, orders, norm=True)[source]

Compute forward moments of a marked trace.

Forward moment for class c is E[T_{k+1}^order | C_k = c].

Parameters:
Returns:

Matrix of shape (C, len(orders)) containing forward moments.

Return type:

numpy.ndarray

mtrace_backward_moment(T, A, orders, norm=True)[source]

Compute backward moments of a marked trace.

Backward moment for class c is E[T_k^order | C_k = c].

Parameters:
Returns:

Matrix of shape (C, len(orders)) containing backward moments.

Return type:

numpy.ndarray

mtrace_cov(T, A)[source]

Compute lag-1 covariance between classes in a marked trace.

Parameters:
Returns:

C x C matrix of 2x2 covariance matrices.

Return type:

numpy.ndarray

mtrace_pc(T, L)[source]

Compute the probability of arrival for each class.

Parameters:
Returns:

Array of class probabilities.

Return type:

numpy.ndarray

mtrace_summary(T, L)[source]

Compute comprehensive summary statistics for a marked trace.

Parameters:
Returns:

  • M: First 5 aggregate moments

  • ACF: Autocorrelation for lags 1-100

  • F1, F2: Forward moments of order 1 and 2

  • B1, B2: Backward moments of order 1 and 2

  • C1, C2: Cross moments of order 1 and 2

  • Pc: Class probabilities

  • Pab: One-step transition probabilities

Return type:

Dictionary containing

mtrace_split(T, L)[source]

Split a multi-class trace into per-class traces.

For each class, computes inter-arrival times between consecutive events of that class.

Parameters:
Returns:

List of arrays, one per class, containing inter-arrival times.

Return type:

list

mtrace_merge(t1, t2)[source]

Merge two traces into a single marked (multi-class) trace.

Parameters:
Returns:

  • T: Merged inter-arrival times

  • L: Class labels (1 for t1, 2 for t2)

Return type:

Tuple of (T, L) where

mtrace_joint(T, A, i)[source]

Compute class-dependent joint moments.

Computes E[(X^(a)_j)^i[0] * (X^(a)_{j+1})^i[1]] for all classes a.

Parameters:
Returns:

Array of joint moments, one per class.

Return type:

numpy.ndarray

mtrace_moment(T, A, orders, after=False, norm=False)[source]

Compute class-dependent moments of a multi-class trace.

Parameters:
  • T (numpy.ndarray | list) – Array of inter-arrival times

  • A (numpy.ndarray | list) – Array of class labels

  • orders (numpy.ndarray | list) – Array of moment orders to compute

  • after (bool) – If True, compute moments of Bucholz variables (forward) If False, compute moments of Horvath variables (backward)

  • norm (bool) – If True, normalize by class probability

Returns:

Matrix of shape (C, len(orders)) containing moments per class.

Return type:

numpy.ndarray

mtrace_moment_simple(T, A, k)[source]

Simple interface to compute k-th order moments per class.

Parameters:
Returns:

Array of k-th order moments, one per class.

Return type:

numpy.ndarray

mtrace_bootstrap(T, A, n_samples=100, seed=None)[source]

Generate bootstrap samples from a marked trace.

Parameters:
Returns:

Tuple of (T_boot, A_boot) containing bootstrap samples.

Return type:

Tuple[numpy.ndarray, numpy.ndarray]

mtrace_iat2counts(T, L, scale)[source]

Compute counting process from marked inter-arrival times.

For each class, counts arrivals in windows of specified scale.

Parameters:
Returns:

Array of counts per class per window.

Return type:

numpy.ndarray

Reinforcement Learning (line_solver.api.rl)

Reinforcement Learning (RL) agents for queueing control.

Native Python implementations of RL agents for queueing network control and optimization.

Key classes:

RLTDAgent: Temporal Difference learning agent RLEnvironment: Queueing network environment

Port from:

matlab/src/api/rl/rl_td_agent.m matlab/src/api/rl/rl_env.m

class RLEnvironment(model, queue_indices, source_indices, state_size, gamma=0.99)[source]

Bases: object

Reinforcement Learning environment for queueing networks.

This class wraps a queueing network model and provides an interface for RL agents to interact with it through sampling and state updates.

model

The queueing network model

gamma

Discount factor for future rewards

queue_indices

Indices of queue nodes in model.nodes

source_indices

Indices of source nodes in model.nodes

state_size

Maximum state size to consider

action_size

Number of possible actions (number of queues)

Initialize the RL environment.

Parameters:
  • model (Any) – Queueing network model

  • queue_indices (List[int]) – Indices of queue nodes in model.nodes

  • source_indices (List[int]) – Indices of source nodes in model.nodes

  • state_size (int) – Maximum number of jobs per queue to consider

  • gamma (float) – Discount factor (0 < gamma <= 1)

__init__(model, queue_indices, source_indices, state_size, gamma=0.99)[source]

Initialize the RL environment.

Parameters:
  • model (Any) – Queueing network model

  • queue_indices (List[int]) – Indices of queue nodes in model.nodes

  • source_indices (List[int]) – Indices of source nodes in model.nodes

  • state_size (int) – Maximum number of jobs per queue to consider

  • gamma (float) – Discount factor (0 < gamma <= 1)

is_in_state_space(state)[source]

Check if current state is within the defined state space.

Parameters:

state (ndarray) – Array of queue lengths

Returns:

True if all queue lengths are within state_size bounds

Return type:

bool

is_in_action_space(state)[source]

Check if actions are valid from current state.

Parameters:

state (ndarray) – Array of queue lengths

Returns:

True if all queues can accept new jobs (not at capacity)

Return type:

bool

sample()[source]

Sample the next event from the environment.

Uses the SSA solver to sample a single system event.

Returns:

Tuple of (time_delta, departure_node_index)

Return type:

Tuple[float, int]

update(new_state)[source]

Update the model state after an event.

Parameters:

new_state (ndarray) – New queue lengths for each queue

reset()[source]

Reset the environment to initial state.

Returns:

Initial state (zeros)

Return type:

ndarray

class RLTDAgent(learning_rate=0.05, epsilon=1.0, epsilon_decay=0.99)[source]

Bases: object

Temporal Difference (TD) learning agent for queueing control.

Implements average-reward TD learning for optimal routing decisions in queueing networks. The agent learns a value function V(s) that estimates the long-run average cost from each state.

learning_rate

Step size for value function updates

epsilon

Exploration rate for epsilon-greedy policy

epsilon_decay

Decay factor for exploration rate

V

Value function array

Q

Q-function array (state-action values)

Initialize the TD agent.

Parameters:
  • learning_rate (float) – Learning rate (step size) for updates

  • epsilon (float) – Initial exploration rate (0 to 1)

  • epsilon_decay (float) – Decay factor applied to epsilon each episode

__init__(learning_rate=0.05, epsilon=1.0, epsilon_decay=0.99)[source]

Initialize the TD agent.

Parameters:
  • learning_rate (float) – Learning rate (step size) for updates

  • epsilon (float) – Initial exploration rate (0 to 1)

  • epsilon_decay (float) – Decay factor applied to epsilon each episode

reset(env)[source]

Reset agent and environment.

Parameters:

env (RLEnvironment) – The RL environment

get_value_function()[source]

Get the learned value function.

get_q_function()[source]

Get the learned Q-function.

solve(env, num_episodes=10000, verbose=True)[source]

Train the agent using TD learning.

Runs TD(0) learning for the specified number of episodes, learning an optimal routing policy for the queueing network.

Parameters:
  • env (RLEnvironment) – The RL environment

  • num_episodes (int) – Number of training episodes

  • verbose (bool) – Whether to print progress

Returns:

  • ‘V’: Learned value function

  • ’Q’: Learned Q-function

  • ’mean_cost_rate’: Final estimated average cost rate

Return type:

Dictionary with training results

class RLEnvironmentGeneral(model, queue_indices, action_node_indices, state_size, gamma=0.99)[source]

Bases: object

General RL environment for queueing networks with flexible action spaces.

Unlike RLEnvironment which assumes sources dispatch to queues, this class supports arbitrary action nodes with configurable routing destinations. Actions are dispatching decisions at specific nodes that route jobs to connected downstream nodes.

model

The queueing network model

gamma

Discount factor for future rewards

queue_indices

Indices of queue nodes in model.nodes

nqueues

Number of queues

action_node_indices

Indices of nodes where routing actions are needed

state_size

Maximum state size to consider

action_space

Dict mapping action_node -> list of possible destination nodes

MATLAB: matlab/src/api/rl/rl_env_general.m

Initialize the general RL environment.

Parameters:
  • model (Any) – Queueing network model

  • queue_indices (List[int]) – Indices of queue nodes in model.nodes

  • action_node_indices (List[int]) – Indices of nodes where dispatch actions are taken

  • state_size (int) – Maximum number of jobs per queue to consider

  • gamma (float) – Discount factor (0 < gamma <= 1)

__init__(model, queue_indices, action_node_indices, state_size, gamma=0.99)[source]

Initialize the general RL environment.

Parameters:
  • model (Any) – Queueing network model

  • queue_indices (List[int]) – Indices of queue nodes in model.nodes

  • action_node_indices (List[int]) – Indices of nodes where dispatch actions are taken

  • state_size (int) – Maximum number of jobs per queue to consider

  • gamma (float) – Discount factor (0 < gamma <= 1)

is_in_state_space(state)[source]

Check if the given state is within the defined state space.

Parameters:

state (ndarray) – Array of queue lengths (one per queue)

Returns:

True if all queue lengths are within state_size bounds

Return type:

bool

is_in_action_space(state)[source]

Check if actions are valid from the given state.

Parameters:

state (ndarray) – Array of queue lengths

Returns:

True if at least one queue can accept a new job

Return type:

bool

sample()[source]

Sample the next event from the environment.

Uses the SSA solver to sample a single system event.

Returns:

Tuple of (time_delta, departure_node, arrival_node, sample_data)

Return type:

Tuple[float, int, int, Any]

update(sample_data)[source]

Update the model state using the sample event data.

Applies the state transitions from the sampled events to the model.

Parameters:

sample_data (Any) – Sample data from the SSA solver

reset()[source]

Reset the environment to initial state.

Returns:

Initial state (zeros)

Return type:

ndarray

class RLTDAgentGeneral(learning_rate=0.1, epsilon=1.0, epsilon_decay=0.9999)[source]

Bases: object

General TD learning agent for queueing control with flexible policies.

Supports multiple solve methods: - solve(): TD control with tabular value function - solve_for_fixed_policy(): TD learning (evaluation) with fixed heuristic - solve_by_hashmap(): TD control with hash-map value function - solve_by_linear(): TD control with linear function approximation - solve_by_quad(): TD control with quadratic function approximation

Works with RLEnvironmentGeneral for arbitrary action spaces.

MATLAB: matlab/src/api/rl/rl_td_agent_general.m

Initialize the general TD agent.

Parameters:
  • learning_rate (float) – Learning rate for updates

  • epsilon (float) – Initial exploration rate (0 to 1)

  • epsilon_decay (float) – Decay factor applied to epsilon each episode

__init__(learning_rate=0.1, epsilon=1.0, epsilon_decay=0.9999)[source]

Initialize the general TD agent.

Parameters:
  • learning_rate (float) – Learning rate for updates

  • epsilon (float) – Initial exploration rate (0 to 1)

  • epsilon_decay (float) – Decay factor applied to epsilon each episode

reset(env)[source]

Reset agent and environment.

Parameters:

env (RLEnvironmentGeneral) – The RL environment

get_value_function()[source]

Get the learned value function.

solve_for_fixed_policy(env, num_episodes=10000, verbose=True)[source]

TD learning for value function evaluation with heuristic routing.

Evaluates the value function under the existing (model-defined) routing policy without modifying routing decisions.

Parameters:
  • env (RLEnvironmentGeneral) – The general RL environment

  • num_episodes (int) – Number of training episodes

  • verbose (bool) – Whether to print progress

Returns:

Learned value function array

Return type:

ndarray

MATLAB: rl_td_agent_general.solve_for_fixed_policy

solve(env, num_episodes=10000, verbose=True)[source]

TD control with tabular value function.

Learns an optimal routing policy using epsilon-greedy exploration. At each action node departure, the agent selects the best downstream destination based on the current value function.

Parameters:
  • env (RLEnvironmentGeneral) – The general RL environment

  • num_episodes (int) – Number of training episodes

  • verbose (bool) – Whether to print progress

Returns:

Learned value function array

Return type:

ndarray

MATLAB: rl_td_agent_general.solve

solve_by_hashmap(env, num_episodes=10000, verbose=True)[source]

TD control using hash-map value function.

Uses a dictionary to store value estimates only for visited states, with an ‘external’ default for unvisited states.

Parameters:
  • env (RLEnvironmentGeneral) – The general RL environment

  • num_episodes (int) – Number of training episodes

  • verbose (bool) – Whether to print progress

Returns:

X: State features matrix (n_states x (1 + nqueues)) Y: Value estimates (n_states x 1)

Return type:

Tuple of (X, Y) where

MATLAB: rl_td_agent_general.solve_by_hashmap

solve_by_linear(env, num_episodes=10000, verbose=True)[source]

TD control with linear function approximation.

Learns a linear value function: v(q1,…,qn) = w0 + w1*q1 + … + wn*qn

Parameters:
  • env (RLEnvironmentGeneral) – The general RL environment

  • num_episodes (int) – Number of training episodes

  • verbose (bool) – Whether to print progress

Returns:

X: State features matrix Y: Value estimates coefficients: Linear regression coefficients

Return type:

Tuple of (X, Y, coefficients) where

MATLAB: rl_td_agent_general.solve_by_linear

solve_by_quad(env, num_episodes=10000, verbose=True)[source]

TD control with quadratic function approximation.

Learns a quadratic value function: v(q1,…,qn) = sum_{i,j} w_{ij} * q_i * q_j

Parameters:
  • env (RLEnvironmentGeneral) – The general RL environment

  • num_episodes (int) – Number of training episodes

  • verbose (bool) – Whether to print progress

Returns:

X_quad: Augmented features (linear + quadratic terms) Y: Value estimates coefficients: Quadratic regression coefficients

Return type:

Tuple of (X_quad, Y, coefficients) where

MATLAB: rl_td_agent_general.solve_by_quad

Utilities Module (line_solver.utils)

Mock module that can handle any attribute access

Constants Module (line_solver.constants)

Constants and enumerations for LINE queueing network models.

This module defines the various constants, enumerations, and strategies used throughout LINE for specifying model behavior, including:

  • Scheduling strategies (FCFS, LCFS, PS, etc.)

  • Routing strategies (PROB, RAND, etc.)

  • Node types (SOURCE, QUEUE, SINK, etc.)

  • Job class types (OPEN, CLOSED)

  • Solver types and options

  • Activity precedence types for layered networks

  • Call types and drop strategies

These constants ensure type safety and consistency across the API.

class ActivityPrecedenceType(*values)[source]

Bases: Enum

Types of activity precedence relationships in layered networks.

These specify how activities are ordered and synchronized: - PRE_SEQ: Sequential prerequisite (must complete before) - PRE_AND: AND prerequisite (all must complete before) - PRE_OR: OR prerequisite (any must complete before) - POST_SEQ: Sequential post-condition - POST_AND: AND post-condition - POST_OR: OR post-condition - POST_LOOP: Loop post-condition - POST_CACHE: Cache post-condition

class CallType(*values)[source]

Bases: Enum

Types of calls between tasks in layered networks.

  • SYNC: Synchronous call (caller waits for response)

  • ASYNC: Asynchronous call (caller continues immediately)

  • FWD: Forward call (caller terminates, response goes to caller’s caller)

class DropStrategy(*values)[source]

Bases: Enum

Strategies for handling queue overflow and capacity limits.

  • WaitingQueue: Jobs wait in a waiting queue when capacity is exceeded

  • Queue: Alias for WaitingQueue

  • Drop: Jobs are dropped (lost) when capacity is exceeded

  • BlockingAfterService: Jobs are blocked after service completion

  • BlockingBeforeService: Jobs are blocked before service starts

  • ReServiceOnRejection: Rejected jobs are re-served at the upstream station

Values match the MATLAB DropStrategy constants and the JAR jline.lang.constant.DropStrategy ids, which are the interchange encoding of sn.droprule and sn.regionrule. Keep the three Python definitions of this enum (here, lang/base.py, api/sn/network_struct.py) numerically identical: they are written and read by different modules over the same sn fields.

BlockingBeforeService = 3
ReServiceOnRejection = 4
class DepartureDiscipline(*values)[source]

Bases: Enum

Departure disciplines for the depository of a queueing place (QPN semantics).

A queueing place serves tokens in its embedded queue and, on service completion, moves them to a depository from which they become available to the output transitions. The departure discipline governs the order in which depository tokens become available.

  • NORMAL: tokens available immediately upon service completion (standard QPN)

  • FIFO: tokens available in their order of arrival to the depository

NORMAL = 0
class SignalType(*values)[source]

Bases: Enum

Types of signals for signal classes in G-networks and related models.

This is the single canonical definition: lang/classes.py re-exports it rather than defining a second enum. Two coexisting definitions used to be disambiguated only by the import order in line_solver/__init__.py, and the losing definition carried auto() ordinals (1-based) that would have mis-decoded against the 0-based MATLAB/Java enums on the JSON wire.

The member values are the lowercase names used on the JSON wire.

NEGATIVE

Removes a job from the destination queue (G-network negative customer)

REPLY

Triggers a reply action

CATASTROPHE

Removes ALL jobs from the destination queue

NEGATIVE = 'negative'
REPLY = 'reply'
CATASTROPHE = 'catastrophe'
class RemovalPolicy(*values)[source]

Bases: Enum

Removal policies for negative signals in G-networks.

Single canonical definition; see the note on SignalType above. The member values are the lowercase names used on the JSON wire.

RANDOM

Select job uniformly at random from all jobs at the station

FCFS

Remove the oldest job (first arrived)

LCFS

Remove the newest job (last arrived)

RANDOM = 'random'
class EventType(*values)[source]

Bases: Enum

Types of events in discrete-event simulation.

  • INIT: Initialization event

  • LOCAL: Local processing event

  • ARV: Job arrival event

  • DEP: Job departure event

  • PHASE: Phase transition event in multi-phase processes

  • READ: Cache read event

  • STAGE: Staging area event

READ = 6
ENABLE = 8
FIRE = 9
PRE = 10
POST = 11
RENEGE = 12
RETRY = 13
SWITCH = 14
class JobClassType(*values)[source]

Bases: Enum

Types of job classes in queueing networks.

  • OPEN: Open class (jobs arrive from outside the system)

  • CLOSED: Closed class (fixed population circulating in the system)

  • DISABLED: Disabled class (not currently active)

class JoinStrategy(*values)[source]

Bases: Enum

Strategies for join node synchronization in fork-join networks.

  • STD: Standard join (wait for all parallel branches)

  • PARTIAL: Partial join (proceed when some branches complete)

  • Quorum: Quorum-based join (wait for minimum number of branches)

  • Guard: Guard condition join (custom completion criteria)

class MetricType(*values)[source]

Bases: Enum

Types of performance metrics that can be computed.

SysDropR = 11
SysPower = 13
Tard = 24
SysTard = 25
class Metric(metric_type, job_class, station=None)[source]

Bases: object

An output metric of a Solver, such as a performance index.

class TranResult(t, metric)[source]

Bases: object

Container for transient result time series with attribute access.

class NodeType(*values)[source]

Bases: Enum

Types of nodes in queueing network models.

static from_line(obj)[source]
class ProcessType(*values)[source]

Bases: Enum

Types of stochastic processes for arrivals and service times.

BMAP = 22
MMAP = 23
DUNIFORM = 24
BERNOULLI = 25
PRIOR = 26
GEOMETRIC = 27
ME = 28
RAP = 29
DISCRETESAMPLER = 30
ZIPF = 31
DMAP = 32
EMPIRICALCDF = 33
NHPP = 34
static fromString(obj)[source]
class RoutingStrategy(*values)[source]

Bases: Enum

Strategies for routing jobs between network nodes. Values must match MATLAB’s RoutingStrategy constants for JMT compatibility.

RL = 7
class SchedStrategy(*values)[source]

Bases: Enum

Scheduling strategies for service stations.

Values match lang/base.py SchedStrategy for consistency.

LCFSPI = 3
HOL = 9
LPS = 17
SETF = 18
FCFSPR = 22
EDF = 23
JOIN = 25
EDD = 27
SRPT = 28
SRPTPRIO = 29
LCFSPRIO = 30
LCFSPRPRIO = 31
LCFSPIPRIO = 32
FCFSPRPRIO = 33
FCFSPIPRIO = 34
PSJF = 36
FB = 37
LAS = 38
LRPT = 39
FSP = 40
PAS = 41
OI = 42
static fromString(obj)[source]
static fromLINEString(sched)[source]
static toID(sched)[source]
class SchedStrategyType(*values)[source]

Bases: Enum

Categories of scheduling strategies by preemption behavior.

class ServiceStrategy(*values)[source]

Bases: Enum

Service strategies defining service time dependence.

class SolverType(*values)[source]

Bases: Enum

Types of solvers available in LINE.

BA = 2
LDES = 4
class TimingStrategy(*values)[source]

Bases: Enum

Timing strategies for transitions in Petri nets.

class VerboseLevel(*values)[source]

Bases: Enum

Verbosity levels for LINE solver output.

class PollingType(*values)[source]

Bases: Enum

Polling strategies for polling systems.

DECREMENTING = 4
static fromString(obj)[source]
class HeteroSchedPolicy(*values)[source]

Bases: Enum

Scheduling policies for heterogeneous multiserver queues.

ORDER = 1
ALIS = 2
ALFS = 3
FAIRNESS = 4
FSF = 5
RAIS = 6
static fromString(obj)[source]
class GlobalConstants[source]

Bases: object

Global constants and configuration for the LINE solver.

Immediate = 100000000.0
classmethod getInstance()[source]

Get the singleton instance of GlobalConstants.

classmethod get_instance()

Get the singleton instance of GlobalConstants.

classmethod getVerbose()[source]

Get the current verbosity level.

classmethod get_verbose()

Get the current verbosity level.

classmethod setVerbose(verbosity)[source]

Set the verbosity level for solver output.

classmethod set_verbose(verbosity)

Set the verbosity level for solver output.

classmethod getConstants()[source]

Get a dictionary of all global constants.

classmethod get_constants()

Get a dictionary of all global constants.

default_verbose()[source]

Default solver verbosity, inherited from GlobalConstants.

True unless the global verbosity level is SILENT, so solver banners print by default as in MATLAB and Java.