LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
MarkedMMPP.m
1classdef MarkedMMPP < MarkovModulated
2 % Marked Markov-Modulated Poisson Process
3 % Also referred to as a M3PP model
4 %
5 % Copyright (c) 2012-2026, Imperial College London
6 % All rights reserved.
7
8 methods
9 %Constructor
10 function self = MarkedMMPP(D,K)
11 % SELF = MarkedMMPP(D,K)
12 %
13 % LINE uses the M3A representation format
14 % D={D0, D1, D11, D12, D13, ..., D1K}
15 % K is the number of marking types
16
17 self@MarkovModulated('MarkedMMPP',K+2);
18
19 if K == length(D)-1
20 setParam(self, 1, 'D0', D{1});
21 D1 = cellsum({D{2:end}});
22 if any(D1-diag(diag(D1)))
23 line_error(mfilename,'Non-diagonal elements in the D1k matrices, not a Marked MMPP.');
24 end
25 setParam(self, 2, 'D1', D1);
26 for k=1:K
27 setParam(self, 2+k, sprintf('D1%d',k), D{1+k});
28 end
29 elseif K == length(D)-2
30 setParam(self, 1, 'D0', D{1});
31 D1 = D{2};
32 if any(D1-diag(diag(D1)))
33 line_error(mfilename,'Non-diagonal elements in the D1k matrices, not a Marked MMPP.');
34 end
35 setParam(self, 2, 'D1', D1);
36 for k=1:K
37 setParam(self, 2+k, sprintf('D1%d',k), D{2+k});
38 end
39 else
40 line_error(mfilename,'Inconsistency between the number of classes and the number of supplied D matrices.')
41 end
42 end
43
44 function Di = D(self, i, j, wantSparse)
45 % Di = D(i)
46 if nargin == 1
47 Di = self.getProcess;
48 return
49 end
50 if nargin<4
51 wantSparse = false;
52 end
53 if nargin<3
54 if i<=1
55 j = 0;
56 else
57 line_error(mfilename,'Invalid D matrix indexes');
58 end
59 end
60
61 % Return representation matrix, e.g., D0=MAP.D(0)
62 if wantSparse
63 if nargin<2
64 Di=self.getProcess;
65 else
66 Di=self.getProcess{1+i+j};
67 end
68 % else
69 if nargin<2
70 Di=self.getProcess;
71 for i=1:length(Di)
72 Di(i)=full(Di(i));
73 end
74 else
75 Di=full(self.getProcess{1+i+j});
76 end
77 end
78 end
79
80 function meant = evalMeanT(self, t)
81 % MEANT = EVALMEANT(SELF,T)
82
83 meant = self.toMAP.evalMeanT(t);
84 end
85
86 function vart = evalVarT(self, t)
87 % VART = EVALVART(SELF,T)
88
89 % Evaluate the variance-time curve at timescale t
90 vart = self.toMAP.evalVarT(t);
91 end
92
93 function acf = evalACFT(self, lags, timescale)
94 % ACF = EVALACFT(self, lags)
95 %
96 % Evaluate the autocorrelation in counts at timescale t
97
98 acf = self.toMAP.evalACFT(lags, timescale);
99 end
100
101 % inter-arrival time properties
102 function mean = getMean(self)
103 % MEAN = GETMEAN()
104
105 mean = self.toMAP.getMean;
106 end
107
108 function scv = getSCV(self)
109 % SCV = GETSCV()
110
111 scv = self.toMAP.scv;
112 end
113
114 % inter-arrival time properties for each marking type
115 function mean = getMarkedMeans(self)
116 % MEAN = GETMARKEDMEAN()
117
118 mean = 1 ./ mmap_lambda(self.D);
119 end
120
121 function acf = getACF(self, lags)
122 % ACF = GETACF(self, lags)
123
124 acf = self.toMAP.getACF(lags);
125 end
126
127 function map = toMAP(self)
128 map = MAP(self.D(0), self.D(1));
129 end
130
131 function maps = toMAPs(self, types)
132 if nargin<2
133 types = 1:self.getNumberOfTypes;
134 end
135 maps = {};
136 for k=types
137 Df = self.D(0);
138 Df = Df + (self.D(1) - self.D(1,k));
139 maps{end+1} = MAP(Df, self.D(1,k));
140 end
141 end
142
143 function [gamma2, gamma] = getACFDecay(self)
144 % [gamma2, gamma] = GETACFDECAY(self)
145 %
146 % gamma2: asymptotic decay rate of acf
147 % gamma: interpolated decay rate of acf
148
149 [gamma2, gamma] = self.toMAP.getACFDecay();
150 end
151
152 function id = getIDC(self, t) % index of dispersion for counts
153 % ID = GETIDC() % INDEX OF DISPERSION
154 if nargin < 2
155 id = self.toMAP.getIDC;
156 else
157 id = self.toMAP.getIDC(t);
158 end
159 end
160
161 function id = getMarkedIDC(self, t) % asymptotic index of dispersion for counts for each type
162 % ID = GETMARKEDIDC() % ASYMPTOTIC INDEX OF DISPERSION
163 if nargin < 2
164 id = mmpp_count_idc(self.getProcess, GlobalConstants.Immediate);
165 else
166 id = mmpp_count_idc(self.getProcess, t);
167 end
168 end
169
170 function lam = getRate(self)
171 % LAMBDA = GETRATE()
172
173 lam = self.toMAP.getRate;
174 end
175
176 function MarkedMMPP = getProcess(self)
177 % MarkedMMPP = GETPROCESS()
178 K = self.getNumParams;
179 MarkedMMPP = cell(1,K-1);
180 for k=1:K
181 MarkedMMPP{k} = self.getParam(k).paramValue;
182 end
183 end
184
185 function n = getNumberOfPhases(self)
186 % N = GETNUMBEROFMAPASES()
187 D0 = self.getParam(1).paramValue;
188 n = length(D0);
189 end
190
191 function mu = getMu(self)
192 % MU = GETMU()
193 % Aggregate departure rate from each state
194 mu = sum(self.D(1),2); % sum D1 rows / diag -D0
195 end
196
197 function phi = getPhi(self)
198 % MAPI = GETMAPI()
199 % Return the exit vector of the underlying MAP
200 phi = sum(self.D(1),2) ./ diag(-self.D(0)); % sum D1 rows / diag -D0
201 end
202
203 function K = getNumberOfTypes(self)
204 % K = GETNUMBEROFTYPES()
205 % Number of marking types
206
207 K = length(self.D)-2;
208 end
209
210 function MMAPr = toTimeReversed(self)
211 MMAPr = MarkedMMPP(mmap_timereverse(self.D), self.getNumberOfTypes);
212 end
213
214 function [X,C] = sample(self, n)
215 % [X,C] = SAMPLE(N)
216 if nargin<2 %~exist('n','var'),
217 n = 1;
218 end
219 MarkedMMPP = self.getProcess;
220 if mmpp_isfeasible(MarkedMMPP)
221 [X,C] = mmpp_sample(MarkedMMPP,n);
222 else
223 line_error(mfilename,'This process is infeasible (negative rates).');
224 end
225 end
226
227 end
228
229 methods (Static)
230
231 function m3pp = fit(trace, markings, order)
232 % M3PP = FIT(TRACE, ORDER)
233 T = m3afit_init(trace,markings);
234 m3pp = m3afit_auto(T,'NumStates',order,'Method',1);
235 end
236
237 function m3pp = rand(order, nclasses)
238 % M3PP = RAND(ORDER,NCLASSES)
239 %
240 % Generate random MarkedMMPP using uniform random numbers
241 if nargin < 1
242 order = 2;
243 end
244 m3pp = MarkedMMPP(m3pp_rand(order,nclasses),nclasses);
245 end
246 end
247end