LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
TransformToMonocyclic.m
1% B = TransformToMonocyclic(A, maxSize, precision)
2%
3% Transforms an arbitrary matrix to a Markovian monocyclic
4% matrix (see [1]_).
5%
7% ----------
8% A : matrix, shape (N,N)
9% Matrix parameter of the initial representation
10% maxSize : int, optional
11% The maximal order of the resulting Markovian
12% representation. The default value is 100
13% precision : double, optional
14% Matrix entries smaller than the precision are
15% considered to be zeros. The default value is 1e-14
16%
17% Returns
18% -------
19% B : matrix, shape (M,M)
20% Transient generator matrix of the Markovian monocyclic
21% representation. Note that M>N if there are complex
22% eigenvalues.
23%
24% Notes
25% -----
26% Raises an exception if no Markovian monocyclic generator
27% has been found up to the given size.
28%
29% References
30% ----------
31% .. [1] Mocanu, S., Commault, C.: "Sparse representations
32% of phase-type distributions," Stoch. Models 15,
33% 759-778 (1999)
34
35function B = TransformToMonocyclic (A, maxSize, precision)
36
37 if ~exist('precision','var')
38 precision = 1e-14;
39 end
40
41 if ~exist('maxSize','var')
42 maxSize = 100;
43 end
44
45 function [evalues, repeats] = eigvalc(A)
46 % eigval Eigenvalues and their algebraic multiplicity.
47 %
48 % evalues = eigval(A) returns the distinct eigenvalues of A,
49 % with duplicates removed and sorted in increasing order.
50 %
51 % [evalues, repeats] = eigval(A) also returns the row vector
52 % repeats that gives the multiplicity of each eigenvalue.
53 % The sum of the multiplicities is n.
54 %
55 % Examples: Let A = eye(n) and B = diag([3 4]).
56 % For A, evalues is 1 and repeats is n.
57 % For B, evalues is [4; 3] and repeats is [1 1].
58
59 tol = sqrt(eps);
60 lambda = sort(eig(A));
61 lambda = round(lambda/tol) * tol;
62 %
63 % lambda gives all n eigenvalues (repetitions included).
64 %
65 evalues = unique(lambda);
66 n = length(lambda);
67 d = length(evalues);
68 A = ones(n, 1) * evalues';
69 B = lambda * ones(1, d);
70 MATCH = abs(A-B) <= tol;
71 %
72 % MATCH is an n by d zero matrix except
73 % MATCH(i,j) = 1 when lambda(i) = evalues(j).
74 % Summing the columns gives the row vector repeats.
75 %
76 repeats = sum(MATCH);
77 end
78
79 function febs = generateFEBs (A, evalues, repeats, maxSize, precision)
80 % calculate the parameters of the febs
81 febs = [];
82 ix = 1;
83 i = 1;
84 size = 0;
85 while i<=length(evalues)
86 multip = repeats(i);
87 evalimag = -abs(imag(evalues(i)));
88 if -evalimag < precision
89 n = 1;
90 sigma = -real(evalues(i));
91 z = 0;
92 ev = real(evalues(i));
93 em = multip;
94 size = size + 1;
95 else
96 n = 3;
97 size = size + 3;
98 % The feedback probability z is strictly less than 1 only if
99 % the ratio stays strictly below cot(pi/n). At the exact
100 % boundary (ratio == cot(pi/n)) rounding can let the loop
101 % exit with z == 1, which yields a block with zero exit rate,
102 % hence a degenerate generator with a zero eigenvalue. Keep a
103 % margin so that the boundary is always resolved upwards.
104 while evalimag / real(evalues(i)) >= cot(pi/n) - sqrt(eps)
105 n = n + 1;
106 size = size + 1;
107 if size > maxSize
108 error ('The represetation is too large (>maxSize). No result returned.');
109 end
110 end
111 sigma = -(2*real(evalues(i)) + evalimag*(cot(pi/n) - tan(pi/n))) / 2;
112 z = (-evalimag*(cot(pi/n) + tan(pi/n)) / (2*sigma))^n;
113 ev = []; em = [];
114 for k=1:n
115 ev = [ev; complex(-(1-z^(1/n)*cos(2*(k-1)*pi/n))*sigma,z^(1/n)*sin(2*(k-1)*pi/n)*sigma)];
116 em = [em; multip];
117 end
118 end
119
120 febs(ix).lambda = sigma;
121 febs(ix).z = z;
122 febs(ix).n = n;
123 febs(ix).multip = multip;
124 febs(ix).evals = ev;
125 febs(ix).emuls = em;
126
127 if -evalimag < precision
128 i = i + 1;
129 else
130 i = i + 2;
131 end
132 ix = ix + 1;
133 end
134
135 % ordering according to the dominant eigenvalue (simple bubble sort)
136 N = length(febs);
137 for i=1:N-1
138 for j=1:N-i
139 if max(febs(j).evals) < max(febs(j+1).evals)
140 F = febs(j+1);
141 febs(j+1) = febs(j);
142 febs(j) = F;
143 end
144 end
145 end
146 end
147
148 function A = febGenerator (lambda, z, n, multip)
149 A = zeros(multip*n);
150 for ii=1:multip
151 lv = ones(1,n)*lambda;
152 A((ii-1)*n+1:ii*n, (ii-1)*n+1:ii*n) = -diag(lv) + diag(lv(1:n-1),1);
153 A(ii*n,(ii-1)*n+1) = A(ii*n,(ii-1)*n+1) + z * lambda;
154 if ii<multip
155 A(ii*n,ii*n+1) = (1-z)*lambda;
156 end
157 end
158 end
159
160 % determine eigenvalues and their multiplicities
161 [evalues, repeats] = eigvalc(A);
162
163 % build monocyclic representation
164 febs = generateFEBs (A, evalues, repeats, maxSize, precision);
165
166 % assemble generator matrix of the hyper-feb
167 B = [];
168 pos = 1;
169 for i=1:length(febs)
170 Ni = febs(i).n*febs(i).multip;
171 B(pos:pos+Ni-1,pos:pos+Ni-1) = febGenerator (febs(i).lambda, febs(i).z, febs(i).n, febs(i).multip);
172 if i<length(febs)
173 B(pos+Ni-1, pos+Ni) = -sum(B(pos+Ni-1,:));
174 end
175 pos = pos + Ni;
176 end
177end
Definition Station.m:245