LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
example_qrf_comparison.m
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.
4%
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.
8
9clear;
10
11%% Build model
12model = Network('QRF Comparison');
13
14node{1} = Delay(model, 'Delay');
15node{2} = Queue(model, 'Queue1', SchedStrategy.FCFS);
16
17N = 5;
18jobclass{1} = ClosedClass(model, 'Class1', N, node{1}, 0);
19
20% Delay: exponential think time (mean = 1)
21node{1}.setService(jobclass{1}, Exp.fitMean(1));
22
23% Queue: 2-phase MAP service (mean ~ 0.5, moderate variability)
24D0 = [-4, 2; 1, -3];
25D1 = [1, 1; 0.5, 1.5];
26node{2}.setService(jobclass{1}, MAP(D0, D1));
27
28% Serial routing: Delay -> Queue -> Delay
29P = model.initRoutingMatrix();
30P{1} = Network.serialRouting(node);
31model.link(P);
32
33%% Exact CTMC reference
34fprintf('=== Exact CTMC ===\n');
35solver_exact = SolverCTMC(model);
36AvgTable_exact = solver_exact.getAvgTable();
37disp(AvgTable_exact);
38
39%% QRF methods (no-blocking variants)
40qrf_methods = {'qrf.mmi', 'qrf.mem', 'qrf.mmi.ld', 'qrf.mmi.linear'};
41
42results = struct();
43results.method = {};
44results.QN_delay = [];
45results.QN_queue = [];
46results.UN_delay = [];
47results.UN_queue = [];
48results.TN_queue = [];
49results.RN_queue = [];
50
51% Store exact results
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);
63
64for m = 1:length(qrf_methods)
65 method = qrf_methods{m};
66 fprintf('\n=== %s ===\n', method);
67 try
68 solver = SolverCTMC(model, 'method', method);
69 AvgTable = solver.getAvgTable();
70 disp(AvgTable);
71
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);
79 catch err
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;
88 end
89end
90
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);
97 try
98 solver = SolverCTMC(model, 'method', method);
99 AvgTable = solver.getAvgTable();
100 disp(AvgTable);
101
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);
109 catch err
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;
118 end
119end
120
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));
134end
135
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);
149end