1%% QRF Method Comparison on a Simple Closed Queueing Network
2% Single-
class closed network: Delay + Queue(FCFS) with 2-phase MAP service.
3% Compares exact CTMC solution against all available QRF methods.
5% QRF approximation methods (qrf.mmi, qrf.mem, qrf.mmi.ld, qrf.mmi.linear)
6% approximate performance metrics via nonlinear programming.
7% QRF bounds methods (qrf.bas, qrf.rsrd) compute utilization bounds via LP.
12model = Network('QRF Comparison');
14node{1} = Delay(model,
'Delay');
15node{2} = Queue(model,
'Queue1', SchedStrategy.FCFS);
18jobclass{1} = ClosedClass(model,
'Class1', N, node{1}, 0);
20% Delay: exponential think time (mean = 1)
21node{1}.setService(
jobclass{1}, Exp.fitMean(1));
23% Queue: 2-phase MAP service (mean ~ 0.5, moderate variability)
26node{2}.setService(
jobclass{1}, MAP(D0, D1));
28% Serial routing: Delay -> Queue -> Delay
29P = model.initRoutingMatrix();
30P{1} = Network.serialRouting(node);
33%% Exact CTMC reference
34fprintf(
'=== Exact CTMC ===\n');
35solver_exact = SolverCTMC(model);
36AvgTable_exact = solver_exact.getAvgTable();
39%% QRF methods (no-blocking variants)
40qrf_methods = {
'qrf.mmi',
'qrf.mem',
'qrf.mmi.ld',
'qrf.mmi.linear'};
52results.method{end+1} =
'exact (CTMC)';
53exact_Q = AvgTable_exact.QLen;
54exact_U = AvgTable_exact.Util;
55exact_T = AvgTable_exact.Tput;
56exact_R = AvgTable_exact.RespT;
57results.QN_delay(end+1) = exact_Q(1);
58results.QN_queue(end+1) = exact_Q(2);
59results.UN_delay(end+1) = exact_U(1);
60results.UN_queue(end+1) = exact_U(2);
61results.TN_queue(end+1) = exact_T(2);
62results.RN_queue(end+1) = exact_R(2);
64for m = 1:length(qrf_methods)
65 method = qrf_methods{m};
66 fprintf(
'\n=== %s ===\n', method);
68 solver = SolverCTMC(model,
'method', method);
69 AvgTable = solver.getAvgTable();
72 results.method{end+1} = method;
73 results.QN_delay(end+1) = AvgTable.QLen(1);
74 results.QN_queue(end+1) = AvgTable.QLen(2);
75 results.UN_delay(end+1) = AvgTable.Util(1);
76 results.UN_queue(end+1) = AvgTable.Util(2);
77 results.TN_queue(end+1) = AvgTable.Tput(2);
78 results.RN_queue(end+1) = AvgTable.RespT(2);
80 fprintf(
' FAILED: %s\n', err.message);
81 results.method{end+1} = [method,
' (FAILED)'];
82 results.QN_delay(end+1) = NaN;
83 results.QN_queue(end+1) = NaN;
84 results.UN_delay(end+1) = NaN;
85 results.UN_queue(end+1) = NaN;
86 results.TN_queue(end+1) = NaN;
87 results.RN_queue(end+1) = NaN;
91%% QRF bounds methods (qrf.bas, qrf.rsrd)
92% These use no-blocking defaults
for an unbounded network
93bounds_methods = {
'qrf.bas',
'qrf.rsrd'};
94for m = 1:length(bounds_methods)
95 method = bounds_methods{m};
96 fprintf(
'\n=== %s ===\n', method);
98 solver = SolverCTMC(model,
'method', method);
99 AvgTable = solver.getAvgTable();
102 results.method{end+1} = method;
103 results.QN_delay(end+1) = AvgTable.QLen(1);
104 results.QN_queue(end+1) = AvgTable.QLen(2);
105 results.UN_delay(end+1) = AvgTable.Util(1);
106 results.UN_queue(end+1) = AvgTable.Util(2);
107 results.TN_queue(end+1) = AvgTable.Tput(2);
108 results.RN_queue(end+1) = AvgTable.RespT(2);
110 fprintf(
' FAILED: %s\n', err.message);
111 results.method{end+1} = [method,
' (FAILED)'];
112 results.QN_delay(end+1) = NaN;
113 results.QN_queue(end+1) = NaN;
114 results.UN_delay(end+1) = NaN;
115 results.UN_queue(end+1) = NaN;
116 results.TN_queue(end+1) = NaN;
117 results.RN_queue(end+1) = NaN;
121%% Summary comparison table
122fprintf(
'\n\n========================================\n');
123fprintf(
' QRF Method Comparison Summary\n');
124fprintf(
'========================================\n');
125fprintf(
'%-20s %8s %8s %8s %8s %8s\n', ...
126 'Method',
'QN(D)',
'QN(Q)',
'UN(Q)',
'TN(Q)',
'RN(Q)');
127fprintf(
'%-20s %8s %8s %8s %8s %8s\n', ...
128 '--------------------',
'--------',
'--------',
'--------',
'--------',
'--------');
129for i = 1:length(results.method)
130 fprintf('%-20s %8.4f %8.4f %8.4f %8.4f %8.4f\n', ...
131 results.method{i}, ...
132 results.QN_delay(i), results.QN_queue(i), ...
133 results.UN_queue(i), results.TN_queue(i), results.RN_queue(i));
136% Relative errors vs exact
137fprintf(
'\n%-20s %8s %8s %8s %8s %8s\n', ...
138 'Relative Error (%)',
'QN(D)',
'QN(Q)',
'UN(Q)',
'TN(Q)',
'RN(Q)');
139fprintf(
'%-20s %8s %8s %8s %8s %8s\n', ...
140 '--------------------',
'--------',
'--------',
'--------',
'--------',
'--------');
141for i = 2:length(results.method)
142 errQD = abs(results.QN_delay(i) - results.QN_delay(1)) / max(abs(results.QN_delay(1)), 1e-10) * 100;
143 errQQ = abs(results.QN_queue(i) - results.QN_queue(1)) / max(abs(results.QN_queue(1)), 1e-10) * 100;
144 errUQ = abs(results.UN_queue(i) - results.UN_queue(1)) / max(abs(results.UN_queue(1)), 1e-10) * 100;
145 errTQ = abs(results.TN_queue(i) - results.TN_queue(1)) / max(abs(results.TN_queue(1)), 1e-10) * 100;
146 errRQ = abs(results.RN_queue(i) - results.RN_queue(1)) / max(abs(results.RN_queue(1)), 1e-10) * 100;
147 fprintf('%-20s %7.2f%% %7.2f%% %7.2f%% %7.2f%% %7.2f%%\n', ...
148 results.method{i}, errQD, errQQ, errUQ, errTQ, errRQ);