LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
ME.m
1classdef ME < Markovian
2 % Matrix Exponential (ME) distribution
3 %
4 % ME distributions are characterized by an initial vector alpha and
5 % a matrix parameter A. They generalize Phase-Type (PH) distributions
6 % by allowing alpha to have entries outside [0,1] and A to have
7 % arbitrary structure (not necessarily a valid sub-generator).
8 %
9 % Copyright (c) 2012-2026, Imperial College London
10 % All rights reserved.
11
12 properties
13 alpha; % Initial vector
14 A; % Matrix parameter
15 end
16
17 methods
18 function self = ME(alpha, A)
19 % ME Create a Matrix Exponential distribution instance
20 %
21 % @brief Creates an ME distribution with the given initial vector and matrix parameter
22 % @param alpha Initial vector (may have negative entries or sum != 1)
23 % @param A Matrix parameter (must have all eigenvalues with negative real parts)
24 % @return self ME distribution instance
25
26 % Call superclass constructor
27 self@Markovian('ME', 2);
28
29 % Validate using BuTools
30 if ~CheckMERepresentation(alpha, A)
31 error('Invalid ME representation: Check that A is square, alpha and A have compatible dimensions, all eigenvalues of A have negative real parts, and the dominant eigenvalue is real.');
32 end
33
34 % Store parameters
35 self.alpha = alpha;
36 self.A = A;
37 self.nPhases = length(alpha);
38
39 % Set parameters
40 setParam(self, 1, 'alpha', alpha);
41 setParam(self, 2, 'A', A);
42
43 % Create Java object
44 alphaMatrix = jline.util.matrix.Matrix(alpha);
45 AMatrix = jline.util.matrix.Matrix(A);
46 self.obj = jline.lang.processes.ME(alphaMatrix, AMatrix);
47
48 % Build process representation: {D0=A, D1=-A*e*alpha'}
49 % where e is column vector of ones
50 e = ones(self.nPhases, 1);
51 self.process = {A, -A * e * alpha};
52
53 self.immediate = false;
54 end
55
56 function X = sample(self, n)
57 % X = SAMPLE(N)
58 % Get n samples from the distribution using inverse CDF interpolation
59
60 if nargin < 2
61 n = 1;
62 end
63
64 % Use me_sample for accurate sampling
65 X = me_sample(self.process, n);
66 end
67
68 function phases = getNumberOfPhases(self)
69 % PHASES = GETNUMBEROFPHASES()
70 % Get number of phases in the ME representation
71 phases = self.nPhases;
72 end
73
74 function Ft = evalCDF(self, t)
75 % FT = EVALCDF(SELF, T)
76 % Evaluate the cumulative distribution function at t
77 %
78 % For ME distribution: CDF(t) = 1 - alpha * exp(A*t) * e
79
80 Ft = map_cdf(self.process, t);
81 end
82
83 function L = evalLST(self, s)
84 % L = EVALST(S)
85 % Evaluate the Laplace-Stieltjes transform at s
86
87 % LST(s) = alpha * (sI - A)^(-1) * (-A) * e
88 e = ones(self.nPhases, 1);
89 sI = s * eye(self.nPhases);
90 L = self.alpha * ((sI - self.A) \ (-self.A * e));
91 end
92
93 function mean_val = getMean(self)
94 % MEAN_VAL = GETMEAN()
95 % Get mean of the ME distribution
96
97 mean_val = map_mean(self.process);
98 end
99
100 function var_val = getVar(self)
101 % VAR_VAL = GETVAR()
102 % Get variance of the ME distribution
103
104 var_val = map_var(self.process);
105 end
106
107 function scv = getSCV(self)
108 % SCV = GETSCV()
109 % Get squared coefficient of variation
110
111 scv = map_scv(self.process);
112 end
113
114 function proc = getProcess(self)
115 % PROC = GETPROCESS()
116 % Get process representation {D0, D1}
117
118 proc = self.process;
119 end
120 end
121
122 methods(Static)
123 function me = fitMoments(moms)
124 % ME = FITMOMENTS(MOMS)
125 % Create ME distribution by fitting the given moments
126 % Uses BuTools MEFromMoments algorithm
127 %
128 % @param moms Array of moments (requires 2*M-1 moments for order M)
129 % @return me ME distribution matching the given moments
130
131 [alpha, A] = MEFromMoments(moms);
132 me = ME(alpha, A);
133 end
134
135 function me = fromExp(rate)
136 % ME = FROMEXP(RATE)
137 % Create ME distribution from exponential distribution
138 % Convenience method showing that Exp is a special case of ME
139 %
140 % @param rate Rate parameter (lambda)
141 % @return me ME distribution equivalent to Exp(rate)
142
143 alpha = 1.0;
144 A = -rate;
145 me = ME(alpha, A);
146 end
147
148 function me = fromErlang(k, rate)
149 % ME = FROMERLANG(K, RATE)
150 % Create ME distribution from Erlang distribution
151 % Convenience method showing that Erlang is a special case of ME
152 %
153 % @param k Number of phases
154 % @param rate Rate parameter for each phase
155 % @return me ME distribution equivalent to Erlang(k, rate)
156
157 alpha = zeros(1, k);
158 alpha(1) = 1.0; % alpha = [1, 0, 0, ..., 0]
159
160 A = zeros(k, k);
161 for i = 1:k
162 A(i, i) = -rate; % diagonal
163 if i < k
164 A(i, i+1) = rate; % super-diagonal
165 end
166 end
167
168 me = ME(alpha, A);
169 end
170
171 function me = fromHyperExp(p, rates)
172 % ME = FROMHYPEREXP(P, RATES)
173 % Create ME distribution from HyperExponential distribution
174 % Convenience method showing that HyperExp is a special case of ME
175 %
176 % @param p Array of probabilities for each branch
177 % @param rates Array of rates for each branch
178 % @return me ME distribution equivalent to HyperExp(p, rates)
179
180 if length(p) ~= length(rates)
181 error('p and rates must have the same length');
182 end
183
184 k = length(p);
185 alpha = p; % alpha = p
186
187 A = zeros(k, k);
188 for i = 1:k
189 A(i, i) = -rates(i); % diagonal matrix of rates
190 end
191
192 me = ME(alpha, A);
193 end
194 end
195end