LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
fj_char_max.m
1%{ @file fj_char_max.m
2 % @brief Characteristic maximum M_K for order statistics
3 %
4 % @author LINE Development Team
5%}
6
7%{
8 % @brief Characteristic maximum M_K for order statistics
9 %
10 % @details
11 % Computes the characteristic maximum M_K, which provides a bound for
12 % the expected value of the maximum of K i.i.d. random variables.
13 %
14 % Let m_K be the greatest lower bound such that P(X > m_K) <= 1/K.
15 % For continuous distributions with a density: P(X > m_K) = 1/K.
16 %
17 % The characteristic maximum is:
18 % M_K = m_K + K * integral_{m_K}^{inf} P(X > x) dx
19 %
20 % For specific distributions:
21 % - Exponential: m_K = ln(K)/μ, M_K = H_K/μ
22 % - Erlang-k: m_K solves exp(-μ*m_K) * sum_{i=0}^{k-1} (μ*m_K)^i/i! = 1/K
23 % M_K = (k/μ) * [1 + K*exp(-μ*m_K)*(μ*m_K)^k/k!]
24 %
25 % @par Syntax:
26 % @code
27 % [MK, mK] = fj_char_max(K, mu) % Exponential
28 % [MK, mK] = fj_char_max(K, mu, 'exp') % Exponential (explicit)
29 % [MK, mK] = fj_char_max(K, [k, mu], 'erlang') % Erlang-k
30 % [MK, mK] = fj_char_max(K, S_X, 'general') % General (S_X is survival function)
31 % @endcode
32 %
33 % @par Parameters:
34 % <table>
35 % <tr><th>Name<th>Description
36 % <tr><td>K<td>Number of random variables (positive integer)
37 % <tr><td>param<td>Distribution parameters (rate mu, or [k, mu] for Erlang)
38 % <tr><td>dist_type<td>Optional: 'exp' (default), 'erlang', or 'general'
39 % </table>
40 %
41 % @par Returns:
42 % <table>
43 % <tr><th>Name<th>Description
44 % <tr><td>MK<td>Characteristic maximum M_K
45 % <tr><td>mK<td>Threshold m_K where P(X > m_K) = 1/K
46 % </table>
47 %
48 % @par Reference:
49 % A. Thomasian, "Analysis of Fork/Join and Related Queueing Systems",
50 % ACM Computing Surveys, Vol. 47, No. 2, Article 17, July 2014.
51 % Eq. (47) on page 17:24.
52 %
53 % A. Gravey, "A Simple Construction of an Upper Bound for the Mean of
54 % the Maximum of n Identically Distributed Random Variables", 1985.
55%}
56function [MK, mK] = fj_char_max(K, param, dist_type)
57
58if nargin < 3
59 dist_type = 'exp';
60end
61
62if K < 1
63 line_error(mfilename, 'K must be a positive integer. Got K=%d.', K);
64end
65
66switch lower(dist_type)
67 case 'exp'
68 % Exponential distribution with rate mu
69 mu = param;
70 if mu <= 0
71 line_error(mfilename, 'Rate mu must be positive.');
72 end
73 % m_K = ln(K) / mu
74 mK = log(K) / mu;
75 % M_K = H_K / mu (exact for exponential)
76 MK = fj_harmonic(K) / mu;
77
78 case 'erlang'
79 % Erlang-k distribution
80 if numel(param) ~= 2
81 line_error(mfilename, 'For Erlang, param must be [k, mu].');
82 end
83 k = param(1);
84 mu = param(2);
85
86 if k < 1
87 line_error(mfilename, 'Erlang stages k must be positive.');
88 end
89 if mu <= 0
90 line_error(mfilename, 'Rate mu must be positive.');
91 end
92
93 % Find m_K by solving: exp(-mu*m_K) * sum_{i=0}^{k-1} (mu*m_K)^i/i! = 1/K
94 mK = find_mK_erlang(K, k, mu);
95
96 % M_K = (k/mu) * [1 + K * exp(-mu*m_K) * (mu*m_K)^k / k!]
97 MK = (k / mu) * (1 + K * exp(-mu * mK) * (mu * mK)^k / factorial(k));
98
99 case 'general'
100 % General distribution: param is survival function S_X(x) = P(X > x)
101 S_X = param;
102 if ~isa(S_X, 'function_handle')
103 line_error(mfilename, 'For general distribution, param must be a survival function handle.');
104 end
105
106 % Find m_K such that S_X(m_K) = 1/K
107 mK = find_mK_general(K, S_X);
108
109 % M_K = m_K + K * integral_{m_K}^{inf} S_X(x) dx
110 integrand = @(x) S_X(x);
111 upper_limit = find_upper_limit(S_X, 1e-10);
112 tail_integral = integral(integrand, mK, upper_limit, 'RelTol', 1e-8, 'AbsTol', 1e-10);
113 MK = mK + K * tail_integral;
114
115 otherwise
116 line_error(mfilename, 'Unknown distribution type: %s. Valid: exp, erlang, general.', dist_type);
117end
118
119end
120
121function mK = find_mK_erlang(K, k, mu)
122% Find m_K for Erlang-k by solving:
123% exp(-mu*m_K) * sum_{i=0}^{k-1} (mu*m_K)^i/i! = 1/K
124
125% Erlang survival function
126S_erlang = @(x) erlang_survival(x, k, mu);
127
128% Use fzero to find the root
129objective = @(x) S_erlang(x) - 1/K;
130
131% Initial guess: for large K, m_K is approximately the mean plus adjustment
132initial_guess = k / mu + log(K) / mu;
133
134options = optimset('TolX', 1e-10, 'Display', 'off');
135mK = fzero(objective, initial_guess, options);
136end
137
138function S = erlang_survival(x, k, mu)
139% Erlang-k survival function: P(X > x) = exp(-mu*x) * sum_{i=0}^{k-1} (mu*x)^i/i!
140if x <= 0
141 S = 1;
142else
143 S = 0;
144 for i = 0:(k-1)
145 S = S + (mu * x)^i / factorial(i);
146 end
147 S = exp(-mu * x) * S;
148end
149end
150
151function mK = find_mK_general(K, S_X)
152% Find m_K such that S_X(m_K) = 1/K
153objective = @(x) S_X(x) - 1/K;
154
155% Find bounds
156lower = 0;
157upper = 1;
158while S_X(upper) > 1/K
159 upper = upper * 2;
160end
161
162options = optimset('TolX', 1e-10, 'Display', 'off');
163mK = fzero(objective, [lower, upper], options);
164end
165
166function u = find_upper_limit(S_X, target)
167% Find u such that S_X(u) <= target
168u = 1;
169max_iter = 100;
170for iter = 1:max_iter
171 if S_X(u) <= target
172 break;
173 end
174 u = u * 2;
175end
176end