UQ (Uncertainty Quantification)

Methods · Configuration · Shared options · All solvers

The UQ solver is a meta-solver for uncertainty quantification, exposed through the Posterior class. It attaches a Prior distribution to one or more uncertain model parameters, repeatedly evaluates the model with an inner back-end solver under alternative parameter values, and aggregates the outcomes into a posterior distribution of the chosen performance metrics. This enables propagation of parameter uncertainty through a queueing model without re-implementing the underlying analytical or simulation loop. See Tutorial 13: Posterior Analysis for a complete walkthrough.

Methods

The method names and defaults below describe the MATLAB interface. Aliases share a row; model-specific restrictions and backend differences are noted. Use solver.listValidMethods() to inspect the names available for your model.

UQ methods and aliases
MethodAlgorithm and applicability
defaultDiscrete Priors expanded as given, continuous Priors discretized by quadrature; resolves to quad.
ddDiscrete design over the support of the prior distribution.
quadGaussian quadrature discretization of the continuous priors into a weighted design.
mcMonte Carlo sampling of the priors.

Configuration options

This solver uses the shared options structure and coordinates inner solvers. Pass an options struct to configure its fields. See shared solver options for all top-level fields, shared configuration, defaults and usage. Options apply only to the methods and model features that consume them.

Relevant top-level options: samples, iter_max, seed.

UQ has no additional config fields in this reference. Its own defaults are samples=11 and iter_max=1. samples sets the number of nodes per continuous Prior or the Monte Carlo design size. Discrete Priors keep their declared support. Tensor-product designs are capped at 4096 points; mc has no such cap. The constructor's solverFactory chooses and configures the inner solver, for example @(m) SolverMVA(m,'iter_tol',1e-8).

Example

This example propagates uncertainty in the service rate of an M/M/1 queue. A Prior distribution over a set of exponential service alternatives is attached to the queue, and Posterior runs an inner MVA solver once per alternative, aggregating the results into prior-weighted mean performance metrics.

% Build an M/M/1 model with an uncertain service rate
model = Network('UncertainServiceModel');
source = Source(model, 'Source');
queue  = Queue(model, 'Queue', SchedStrategy.FCFS);
sink   = Sink(model, 'Sink');
jobClass = OpenClass(model, 'Jobs');
source.setArrival(jobClass, Exp(0.5));

% Prior over service-rate alternatives
serviceRates = linspace(0.7, 2.5, 30);
priorProbs = exp(-0.5 * ((serviceRates - 1.3) / 0.4).^2);
priorProbs = priorProbs / sum(priorProbs);
alternatives = arrayfun(@(r) Exp(r), serviceRates, 'UniformOutput', false);
queue.setService(jobClass, Prior(alternatives, priorProbs));

model.link(Network.serialRouting(source, queue, sink));

% Run the UQ meta-solver over an MVA back-end
post = Posterior(model, @SolverMVA);
post.getAvgTable()   % prior-weighted means

Output:

Posterior analysis [back-end: MVA, alternatives: 30] completed.

  Station     JobClass     QLen     Util     RespT     Tput
  Queue         Jobs       0.62     0.38     1.24      0.50
// Build an M/M/1 model with an uncertain service rate
Network model = new Network("UncertainServiceModel");
Source source = new Source(model, "Source");
Queue queue   = new Queue(model, "Queue", SchedStrategy.FCFS);
Sink sink     = new Sink(model, "Sink");
OpenClass jobClass = new OpenClass(model, "Jobs", 0);
source.setArrival(jobClass, new Exp(0.5));

// Prior over service-rate alternatives
int numAlternatives = 30;
List<Distribution> alternatives = new ArrayList<>();
double[] priorProbs = new double[numAlternatives];
double sum = 0.0;
for (int i = 0; i < numAlternatives; i++) {
    double rate = 0.7 + (2.5 - 0.7) * i / (double) (numAlternatives - 1);
    alternatives.add(new Exp(rate));
    double z = (rate - 1.3) / 0.4;
    priorProbs[i] = Math.exp(-0.5 * z * z);
    sum += priorProbs[i];
}
for (int i = 0; i < numAlternatives; i++) priorProbs[i] /= sum;
queue.setService(jobClass, new Prior(alternatives, priorProbs));

model.link(Network.serialRouting(source, queue, sink));

// Run the UQ meta-solver over an MVA back-end
Posterior post = new Posterior(model, m -> new MVA(m));
post.getAvgTable().print();   // prior-weighted means

Output:

Posterior analysis [back-end: MVA, alternatives: 30] completed.

  Station     JobClass     QLen     Util     RespT     Tput
  Queue         Jobs       0.62     0.38     1.24      0.50
from line_solver import *
import numpy as np

# Build an M/M/1 model with an uncertain service rate
model = Network('UncertainServiceModel')
source = Source(model, 'Source')
queue  = Queue(model, 'Queue', SchedStrategy.FCFS)
sink   = Sink(model, 'Sink')
jobClass = OpenClass(model, 'Jobs')
source.setArrival(jobClass, Exp(0.5))

# Prior over service-rate alternatives
service_rates = np.linspace(0.7, 2.5, 30)
prior_probs = np.exp(-0.5 * ((service_rates - 1.3) / 0.4) ** 2)
prior_probs = prior_probs / np.sum(prior_probs)
alternatives = [Exp(rate) for rate in service_rates]
queue.setService(jobClass, Prior(alternatives, prior_probs.tolist()))

model.link(Network.serial_routing([source, queue, sink]))

# Run the UQ meta-solver over an MVA back-end
post = Posterior(model, MVA)
print(post.get_avg_table())   # prior-weighted means

Output:

Posterior analysis [back-end: MVA, alternatives: 30] completed.

  Station     JobClass     QLen     Util     RespT     Tput
  Queue         Jobs       0.62     0.38     1.24      0.50