1classdef StationaryDistribution < handle
2 properties (Access =
private)
6 is_rho_computed = false
11 is_mean_clients_computed =
false
12 sum_from_c_to_inf = []
16 function obj = StationaryDistribution(proc)
22 function bind(obj, proc)
25 obj.is_rho_computed =
false;
26 obj.is_mean_clients_computed =
false;
31 obj.sum_from_c_to_inf = [];
34 function value = get_rho(obj)
39 function matrix = get_R(obj)
44 function matrix = get_G(obj)
49 function dist = get_dist(obj, max_level)
51 dist = obj.pi_0_c(1:min(max_level + 1, numel(obj.pi_0_c)));
53 for k = numel(dist):max_level
59 function dist = get_pi_0_c(obj)
64 function value = get_mean_clients(obj)
65 if obj.is_mean_clients_computed
78 for k = 2:(numel(obj.pi_0_c) - 1)
79 value = value + (k - 1) * sum(obj.pi_0_c{k});
84 tmp = (I - obj.R) \ I;
86 value = value + sum(pi * ((obj.R * tmp) + (numel(obj.pi_0_c) - 1) * I) * tmp);
88 obj.is_mean_clients_computed =
true;
91 function value = get_sum_from_c_to_inf(obj)
92 if isempty(obj.sum_from_c_to_inf)
95 obj.sum_from_c_to_inf = ((I - obj.R).') \ obj.pi_0_c{end}.
';
96 obj.sum_from_c_to_inf = obj.sum_from_c_to_inf.';
98 value = obj.sum_from_c_to_inf;
101 function value = get_mean_queue(obj, queue_size_vector)
102 obj.compute_pi_0_c();
103 if numel(queue_size_vector) ~= numel(obj.pi_0_c)
104 libqbd.raise_error('You need to specify c first levels.');
114 for k = 1:(numel(obj.pi_0_c) - 1)
115 value = value + sum(libqbd.as_row_vector(obj.pi_0_c{k}) .* libqbd.as_row_vector(queue_size_vector{k}));
118 I = eye(size(obj.R));
120 pi = obj.pi_0_c{end}.';
121 queue_tail = libqbd.as_row_vector(queue_size_vector{end});
122 value = value + sum(((tmp \ pi).
') .* queue_tail);
123 value = value + sum((tmp \ (tmp \ ((obj.pi_0_c{end} * obj.R).'))));
127 methods (Access =
private)
130 libqbd.raise_error('Not binded to the process.');
132 if isempty(obj.process.all_A_0())
133 libqbd.raise_error('Infinitesimal generator matrix
is empty.');
137 function compute_rho(obj)
138 if obj.is_rho_computed
143 am = obj.process.all_A_minus();
144 a0 = obj.process.all_A_0();
145 ap = obj.process.all_A_plus();
146 A = am{end} + a0{end} + ap{end};
148 r = zeros(size(A, 1), 1);
151 obj.rho = sum(alpha * ap{end}) / sum(alpha * am{end});
152 obj.is_rho_computed =
true;
155 function compute_G(obj)
163 libqbd.raise_error('rho
is equal or greater than 1.');
166 am = obj.process.all_A_minus();
167 a0 = obj.process.all_A_0();
168 ap = obj.process.all_A_plus();
172 T = -(A_0 \ eye(size(A_0)));
176 W = (I - V_m * V_p - V_p * V_m) \ I;
179 tol = realmin(
class(G));
184 W = (I - V_m * V_p - V_p * V_m) \ I;
188 if max(abs(delta(:))) <= tol
195 function compute_R(obj)
202 a0 = obj.process.all_A_0();
203 ap = obj.process.all_A_plus();
206 U = -(A_0 + A_p * obj.G);
210 function compute_pi_0_c(obj)
212 if ~isempty(obj.pi_0_c)
218 libqbd.raise_error('rho
is equal or greater than 1.');
221 c = numel(obj.process.all_A_0());
223 libqbd.raise_error('Generator matrix
is empty.');
231 matrix_len = matrix_len + size(obj.process.get_A_0(k), 1);
234 B = zeros(matrix_len, matrix_len);
235 A00 = obj.process.get_A_0(0);
236 Ap0 = obj.process.get_A_plus(0);
237 B(1:size(A00, 1), 1:size(A00, 2)) = A00;
238 B(1:size(Ap0, 1), (size(A00, 2) + 1):(size(A00, 2) + size(Ap0, 2))) = Ap0;
240 row_offset = size(A00, 1) + 1;
243 A_minus = obj.process.get_A_minus(k);
244 A_0 = obj.process.get_A_0(k);
245 A_plus = obj.process.get_A_plus(k);
246 B(row_offset:(row_offset + size(A_minus, 1) - 1), (col_offset + 1):(col_offset + size(A_minus, 2))) = A_minus;
247 col_offset = col_offset + size(A_minus, 2);
248 B(row_offset:(row_offset + size(A_0, 1) - 1), (col_offset + 1):(col_offset + size(A_0, 2))) = A_0;
249 B(row_offset:(row_offset + size(A_plus, 1) - 1), (col_offset + size(A_0, 2) + 1):(col_offset + size(A_0, 2) + size(A_plus, 2))) = A_plus;
250 row_offset = row_offset + size(A_0, 1);
253 A_minus = obj.process.get_A_minus(c);
254 B(row_offset:(row_offset + size(A_minus, 1) - 1), (col_offset + 1):(col_offset + size(A_minus, 2))) = A_minus;
255 col_offset = col_offset + size(A_minus, 2);
257 A_tail = obj.process.get_A_0(c) + obj.R * obj.process.get_A_minus(c + 1);
258 B(row_offset:(row_offset + size(A_tail, 1) - 1), (col_offset + 1):(col_offset + size(A_tail, 2))) = A_tail;
260 norm_eq = ones(size(B, 1), 1);
261 I = eye(size(obj.R));
262 ones_tail = ones(size(obj.R, 1), 1);
263 norm_eq(end - size(obj.R, 1) + 1:end) = (I - obj.R) \ ones_tail;
265 right = zeros(size(B, 1), 1);
267 dist = (B.' \ right).';
268 dist(dist < 0.0) = 0.0;
272 right_idx = left + size(obj.process.get_A_0(k), 1) - 1;
273 obj.pi_0_c{end + 1} = dist(left:right_idx);
274 left = right_idx + 1;