1% Example 12: Posterior analysis with uncertain parameters
3% This tutorial demonstrates how to analyze queueing models with parameter
4% uncertainty
using the Posterior solver. The Posterior solver works with
5% Prior distributions that represent uncertainty about model parameters,
6% computing posterior distributions of performance metrics.
8% Scenario: An M/M/1 queue where the service rate
is uncertain. We model
9%
this uncertainty
using a Prior distribution with 30 alternatives,
10% creating a Gaussian-like distribution of possible service rates.
12%% Block 1: Create model with uncertain service rate
13model = Network(
'UncertainServiceModel');
16source = Source(model,
'Source');
17queue = Queue(model,
'Queue', SchedStrategy.FCFS);
18sink = Sink(model,
'Sink');
21jobClass = OpenClass(model,
'Jobs');
23% Set arrival rate (lambda = 0.5)
25source.setArrival(jobClass, Exp(lambda));
27%% Block 2: Define Prior distribution for uncertain service rate
28% Use many alternatives to create a smooth, continuous-looking PDF
29% Service rates range from 0.7 to 2.5 with a Gaussian-like prior
31serviceRates = linspace(0.7, 2.5, numAlternatives);
33% Create Gaussian-like prior probabilities centered at mu=1.3
36priorProbs = exp(-0.5 * ((serviceRates - priorMean) / priorStd).^2);
37priorProbs = priorProbs / sum(priorProbs); % Normalize to sum to 1
39alternatives = cell(1, numAlternatives);
40for i = 1:numAlternatives
41 alternatives{i} = Exp(serviceRates(i));
44prior = Prior(alternatives, priorProbs);
45queue.setService(jobClass, prior);
47%% Block 3: Complete model topology
48model.link(model.serialRouting(source, queue, sink));
50fprintf(
'Model: M/M/1 with uncertain service rate\n');
51fprintf(
'Arrival rate: lambda = %.1f\n', lambda);
52fprintf(
'Number of service rate alternatives: %d\n', numAlternatives);
53fprintf(
'Service rate range: mu in [%.2f, %.2f]\n', min(serviceRates), max(serviceRates));
54fprintf(
'Prior: Gaussian-like centered at mu=%.1f with std=%.1f\n\n', priorMean, priorStd);
56%% Block 4: Solve with Posterior wrapper
using MVA
57post = Posterior(model, @SolverMVA);
60%% Block 5: Get prior-weighted average results
61avgTable = post.getAvgTable()
63%% Block 6: Get posterior table with per-alternative results
64postTable = post.getPosteriorTable()
66%% Block 7: Extract posterior distributions
for different metrics
67% Get posterior distribution of response time at the queue
68respDist = post.getPosteriorDist(
'R', queue, jobClass);
70% Get posterior distribution of queue length at the queue
71qlenDist = post.getPosteriorDist(
'Q', queue, jobClass);
73% Get posterior distribution of utilization at the queue
74utilDist = post.getPosteriorDist(
'U', queue, jobClass);
76%% Block 8: Extract values and probabilities from the EmpiricalCDF objects
78respCdfData = respDist.data; % [CDF, Value]
79respValues = respCdfData(:, 2);
80respCdf = respCdfData(:, 1);
81respProbs = [respCdf(1); diff(respCdf)]; % Convert CDF to PMF
84qlenCdfData = qlenDist.data;
85qlenValues = qlenCdfData(:, 2);
86qlenCdf = qlenCdfData(:, 1);
87qlenProbs = [qlenCdf(1); diff(qlenCdf)];
90utilCdfData = utilDist.data;
91utilValues = utilCdfData(:, 2);
92utilCdf = utilCdfData(:, 1);
93utilProbs = [utilCdf(1); diff(utilCdf)];
95%% Block 9: Print posterior distribution statistics
96% Response time statistics
97expectedR = sum(respValues .* respProbs);
98[~, modeIdxR] = max(respProbs);
99fprintf(
'Response Time (R) at Queue:\n');
100fprintf(
' Expected Value E[R]: %.4f\n', expectedR);
101fprintf(
' Mode (most likely): %.4f\n\n', respValues(modeIdxR));
103% Queue length statistics
104expectedQ = sum(qlenValues .* qlenProbs);
105[~, modeIdxQ] = max(qlenProbs);
106fprintf(
'Queue Length (Q) at Queue:\n');
107fprintf(
' Expected Value E[Q]: %.4f\n', expectedQ);
108fprintf(
' Mode (most likely): %.4f\n\n', qlenValues(modeIdxQ));
110% Utilization statistics
111expectedU = sum(utilValues .* utilProbs);
112[~, modeIdxU] = max(utilProbs);
113fprintf(
'Utilization (U) at Queue:\n');
114fprintf(
' Expected Value E[U]: %.4f\n', expectedU);
115fprintf(
' Mode (most likely): %.4f\n\n', utilValues(modeIdxU));
117% Optional: Find median from CDF
118medianIdx = find(respCdf >= 0.5, 1,
'first');
119if ~isempty(medianIdx)
120 medianR = respValues(medianIdx);
121 fprintf(
'Response Time Median: %.4f\n', medianR);
124%% Block 10: Create PDF plots
125figure(
'Name',
'Posterior Distribution PDFs',
'Position', [100, 100, 1200, 400]);
127% Plot 1: Response Time PDF
129bar(respValues, respProbs, 1.0,
'FaceColor', [0.2, 0.6, 0.8],
'EdgeColor', [0.1, 0.4, 0.6]);
131xline(expectedR,
'r-',
'LineWidth', 2.5);
133xlabel(
'Response Time (R)');
134ylabel(
'Probability');
135title(
'Posterior PDF: Response Time');
136legend({
'P(R)', sprintf(
'E[R] = %.3f', expectedR)},
'Location',
'best');
139% Plot 2: Queue Length PDF
141bar(qlenValues, qlenProbs, 1.0,
'FaceColor', [0.4, 0.8, 0.4],
'EdgeColor', [0.2, 0.6, 0.2]);
143xline(expectedQ,
'r-',
'LineWidth', 2.5);
145xlabel(
'Queue Length (Q)');
146ylabel(
'Probability');
147title(
'Posterior PDF: Queue Length');
148legend({
'P(Q)', sprintf(
'E[Q] = %.3f', expectedQ)},
'Location',
'best');
151% Plot 3: Utilization PDF
153bar(utilValues, utilProbs, 1.0,
'FaceColor', [0.8, 0.4, 0.4],
'EdgeColor', [0.6, 0.2, 0.2]);
155xline(expectedU,
'r-',
'LineWidth', 2.5);
157xlabel(
'Utilization (U)');
158ylabel(
'Probability');
159title(
'Posterior PDF: Utilization');
160legend({
'P(U)', sprintf(
'E[U] = %.3f', expectedU)},
'Location',
'best');
163sgtitle(
'Posterior Distribution PDFs for M/M/1 with Uncertain Service Rate');
165%% Block 11: Create PDF and CDF plot
for response time
166figure(
'Name',
'Response Time: PDF and CDF',
'Position', [150, 150, 1000, 400]);
168% Left: Area plot
for continuous-looking PDF
170area(respValues, respProbs,
'FaceColor', [0.2, 0.6, 0.8],
'FaceAlpha', 0.7,
'EdgeColor', [0.1, 0.4, 0.6],
'LineWidth', 1.5);
172xline(expectedR,
'r-',
'LineWidth', 2.5);
173[~, modeIdx] = max(respProbs);
174plot(respValues(modeIdx), respProbs(modeIdx),
'ko',
'MarkerSize', 8,
'MarkerFaceColor',
'k');
176xlabel(
'Response Time (R)');
177ylabel(
'Probability Density');
178title(
'Posterior PDF');
179legend({
'f(R)', sprintf(
'E[R] = %.3f', expectedR), sprintf(
'Mode = %.3f', respValues(modeIdx))},
'Location',
'best');
184plot(respValues, respCdf,
'LineWidth', 2.5,
'Color', [0.2, 0.6, 0.8]);
186medianIdx = find(respCdf >= 0.5, 1,
'first');
187if ~isempty(medianIdx)
188 medianR = respValues(medianIdx);
189 plot(medianR, 0.5,
'ro',
'MarkerSize', 10,
'MarkerFaceColor',
'r');
190 xline(medianR,
'r:',
'LineWidth', 1.5);
192xline(expectedR,
'g--',
'LineWidth', 2);
193yline(0.5,
'k:',
'LineWidth', 1);
195xlabel(
'Response Time (R)');
196ylabel(
'Cumulative Probability');
197title(
'Posterior CDF');
198if ~isempty(medianIdx)
199 legend({
'F(R)', sprintf(
'Median = %.3f', medianR),
'', sprintf(
'E[R] = %.3f', expectedR)},
'Location',
'best');
201 legend({
'F(R)', sprintf(
'E[R] = %.3f', expectedR)},
'Location',
'best');
204xlim([min(respValues)*0.9, max(respValues)*1.1]);
207sgtitle(
'Response Time Posterior Distribution');