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%
6% Parameters
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 while evalimag / real(evalues(i)) >= cot(pi/n)
99 n = n + 1;
100 size = size + 1;
101 if size > maxSize
102 error ('The represetation is too large (>maxSize). No result returned.');
103 end
104 end
105 sigma = -(2*real(evalues(i)) + evalimag*(cot(pi/n) - tan(pi/n))) / 2;
106 z = (-evalimag*(cot(pi/n) + tan(pi/n)) / (2*sigma))^n;
107 ev = []; em = [];
108 for k=1:n
109 ev = [ev; complex(-(1-z^(1/n)*cos(2*(k-1)*pi/n))*sigma,z^(1/n)*sin(2*(k-1)*pi/n)*sigma)];
110 em = [em; multip];
111 end
112 end
113
114 febs(ix).lambda = sigma;
115 febs(ix).z = z;
116 febs(ix).n = n;
117 febs(ix).multip = multip;
118 febs(ix).evals = ev;
119 febs(ix).emuls = em;
120
121 if -evalimag < precision
122 i = i + 1;
123 else
124 i = i + 2;
125 end
126 ix = ix + 1;
127 end
128
129 % ordering according to the dominant eigenvalue (simple bubble sort)
130 N = length(febs);
131 for i=1:N-1
132 for j=1:N-i
133 if max(febs(j).evals) < max(febs(j+1).evals)
134 F = febs(j+1);
135 febs(j+1) = febs(j);
136 febs(j) = F;
137 end
138 end
139 end
140 end
141
142 function A = febGenerator (lambda, z, n, multip)
143 A = zeros(multip*n);
144 for ii=1:multip
145 lv = ones(1,n)*lambda;
146 A((ii-1)*n+1:ii*n, (ii-1)*n+1:ii*n) = -diag(lv) + diag(lv(1:n-1),1);
147 A(ii*n,(ii-1)*n+1) = A(ii*n,(ii-1)*n+1) + z * lambda;
148 if ii<multip
149 A(ii*n,ii*n+1) = (1-z)*lambda;
150 end
151 end
152 end
153
154 % determine eigenvalues and their multiplicities
155 [evalues, repeats] = eigvalc(A);
156
157 % build monocyclic representation
158 febs = generateFEBs (A, evalues, repeats, maxSize, precision);
159
160 % assemble generator matrix of the hyper-feb
161 B = [];
162 pos = 1;
163 for i=1:length(febs)
164 Ni = febs(i).n*febs(i).multip;
165 B(pos:pos+Ni-1,pos:pos+Ni-1) = febGenerator (febs(i).lambda, febs(i).z, febs(i).n, febs(i).multip);
166 if i<length(febs)
167 B(pos+Ni-1, pos+Ni) = -sum(B(pos+Ni-1,:));
168 end
169 pos = pos + Ni;
170 end
171end