LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
solver_nc_mem.m
1function [QN,UN,RN,TN,CN,XN,totiter] = solver_nc_mem(sn, options)
2% [QN,UN,RN,TN,CN,XN,TOTITER] = SOLVER_NC_MEM(SN, OPTIONS)
3%
4% Maximum Entropy Method (MEM) for Open Queueing Networks
5%
6% Implements the ME algorithm from Kouvatsos (1994) for analyzing open
7% queueing networks with general arrival and service processes.
8%
9% Parameters:
10% sn - Network structure from getStruct()
11% options - Solver options with MEM-specific fields:
12% - config.mem_tol: convergence tolerance (default 1e-6)
13% - config.mem_maxiter: maximum iterations (default 1000)
14% - config.mem_verbose: print iteration info (default false)
15%
16% Returns:
17% QN - Mean queue lengths [M x R matrix]
18% UN - Utilizations [M x R matrix]
19% RN - Mean response times [M x R matrix]
20% TN - Throughputs (arrival rates) [M x R matrix]
21% CN - Completion times (not computed by MEM, returns zeros)
22% XN - System throughputs (not computed by MEM, returns zeros)
23% totiter - Number of iterations until convergence
24%
25% Reference:
26% D.D. Kouvatsos, "Entropy Maximisation and Queueing Network Models",
27% Annals of Operations Research, 48:63-126, 1994.
28%
29% Copyright (c) 2012-2026, Imperial College London
30% All rights reserved.
31
32% Validate that model is open
33if ~sn_is_open_model(sn)
34 line_error(mfilename, 'MEM only supports open queueing networks (all classes must be open).');
35end
36
37if sn_is_closed_model(sn)
38 line_error(mfilename, 'MEM does not support models with closed classes.');
39end
40
41% Extract dimensions
42M = sn.nstations;
43R = sn.nclasses;
44
45% Get MEM options from config
46if isfield(options, 'config') && isfield(options.config, 'mem_tol')
47 tol = options.config.mem_tol;
48else
49 tol = 1e-6;
50end
51
52if isfield(options, 'config') && isfield(options.config, 'mem_maxiter')
53 maxiter = options.config.mem_maxiter;
54else
55 maxiter = 1000;
56end
57
58if isfield(options, 'config') && isfield(options.config, 'mem_verbose')
59 verbose = options.config.mem_verbose;
60else
61 verbose = false;
62end
63
64% Create MEM options structure
65mem_options = struct();
66mem_options.tol = tol;
67mem_options.maxiter = maxiter;
68mem_options.verbose = verbose;
69
70% Initialize parameter matrices for me_oqn
71lambda0 = zeros(M, R); % External arrival rates
72Ca0 = zeros(M, R); % External arrival SCV
73mu = zeros(M, R); % Service rates
74Cs = zeros(M, R); % Service SCV
75P = zeros(M, M, R); % Routing probabilities
76
77% Extract service rates and service SCVs
78for i = 1:M
79 for r = 1:R
80 if sn.rates(i, r) > 0
81 mu(i, r) = sn.rates(i, r);
82
83 % Extract service SCV from service process
84 if ~isempty(sn.proc) && i <= length(sn.proc) && ~isempty(sn.proc{i}) && ...
85 r <= length(sn.proc{i}) && ~isempty(sn.proc{i}{r})
86 MAP = sn.proc{i}{r};
87 if iscell(MAP) && length(MAP) >= 2
88 Cs(i, r) = map_scv(MAP);
89 else
90 Cs(i, r) = 1.0; % Default to exponential
91 end
92 else
93 Cs(i, r) = 1.0; % Default to exponential
94 end
95 end
96 end
97end
98
99% Find source node for external arrivals
100sourceIdx = [];
101for i = 1:sn.nnodes
102 if sn.nodetype(i) == NodeType.Source
103 sourceIdx = sn.nodeToStation(i);
104 break;
105 end
106end
107
108% Extract external arrival rates and SCVs
109if ~isempty(sourceIdx) && sourceIdx > 0
110 for r = 1:R
111 if sn.rates(sourceIdx, r) > 0
112 externalRate = sn.rates(sourceIdx, r);
113 Ca_external = 1.0;
114
115 % Extract arrival SCV from arrival process
116 if ~isempty(sn.proc) && sourceIdx <= length(sn.proc) && ~isempty(sn.proc{sourceIdx}) && ...
117 r <= length(sn.proc{sourceIdx}) && ~isempty(sn.proc{sourceIdx}{r})
118 MAP = sn.proc{sourceIdx}{r};
119 if iscell(MAP) && length(MAP) >= 2
120 Ca_external = map_scv(MAP);
121 end
122 end
123
124 % Distribute external arrivals based on routing from source
125 for i = 1:M
126 if i ~= sourceIdx
127 % Check if queue i receives external arrivals
128 if ~isempty(sn.rt)
129 sourceNode = sn.stationToNode(sourceIdx);
130 queueNode = sn.stationToNode(i);
131
132 if sourceNode > 0 && queueNode > 0
133 routeIdx = (sourceNode-1)*R + r;
134 destIdx = (queueNode-1)*R + r;
135
136 if routeIdx <= size(sn.rt, 1) && destIdx <= size(sn.rt, 2)
137 routeProb = sn.rt(routeIdx, destIdx);
138 if routeProb > 0
139 lambda0(i, r) = externalRate * routeProb;
140 Ca0(i, r) = Ca_external;
141 end
142 end
143 end
144 end
145 end
146 end
147 end
148 end
149end
150
151% Extract routing probabilities between queues
152if ~isempty(sn.rt)
153 for r = 1:R
154 for j = 1:M
155 for i = 1:M
156 jNode = sn.stationToNode(j);
157 iNode = sn.stationToNode(i);
158
159 if jNode > 0 && iNode > 0
160 % Skip Source and Sink nodes
161 if sn.nodetype(jNode) ~= NodeType.Source && ...
162 sn.nodetype(jNode) ~= NodeType.Sink && ...
163 sn.nodetype(iNode) ~= NodeType.Source && ...
164 sn.nodetype(iNode) ~= NodeType.Sink
165
166 routeIdx = (jNode-1)*R + r;
167 destIdx = (iNode-1)*R + r;
168
169 if routeIdx <= size(sn.rt, 1) && destIdx <= size(sn.rt, 2)
170 P(j, i, r) = sn.rt(routeIdx, destIdx);
171 end
172 end
173 end
174 end
175 end
176 end
177end
178
179% Call Maximum Entropy algorithm
180[L, W, Ca, Cd, lambda, rho] = me_oqn(M, R, lambda0, Ca0, mu, Cs, P, mem_options);
181
182% Map to LINE standard output format
183QN = L; % Queue lengths
184UN = rho; % Utilizations
185RN = W; % Response times (waiting times)
186TN = lambda; % Throughputs (arrival rates)
187CN = zeros(1, R); % Completion times (not computed by MEM)
188XN = zeros(1, R); % System throughputs (not computed by MEM)
189
190% Extract iteration count if available
191% (me_oqn doesn't currently return this, so we return maxiter as placeholder)
192totiter = mem_options.maxiter;
193
194end
Definition mmt.m:92