1function sysStateAggr = sampleSysAggr(self, numEvents, markActivePassive)
2% SYSSTATEAGGR = SAMPLESYSAGGR(NUMEVENTS)
4if GlobalConstants.DummyMode
9if nargin<2 %~exist(
'numEvents',
'var')
10 numEvents = self.options.samples;
14 markActivePassive = false;
18numEvents = numEvents - 1; % we include the initialization as an event
19Q = getAvgQLenHandles(self);
20statStateAggr = cell(sn.nstations,1);
23modelCopy = self.model.copy;
24modelCopy.resetNetwork;
26% determine the
nodes to logs
27isNodeClassLogged = false(modelCopy.getNumberOfNodes, modelCopy.getNumberOfClasses);
28for i= 1:modelCopy.getNumberOfStations
29 ind = self.model.getNodeIndex(modelCopy.getStationNames{i});
30 if sn.nodetype(ind) ~= NodeType.Source
31 for r=1:modelCopy.getNumberOfClasses
32 if ~Q{i,r}.disabled || nargin == 1
33 isNodeClassLogged(ind,r) =
true;
35 isNodeClassLogged(node,r) =
true;
41% apply logging to the copied model
43isNodeLogged = max(isNodeClassLogged,[],2);
45modelCopy.linkAndLog(Plinked, isNodeLogged, logpath);
47% simulate the model copy and retrieve log data
48options = self.getOptions;
49options.method =
'jsim'; % Force jsim method to avoid recursion with
'replication'
50solverjmt = SolverJMT(modelCopy, options);
51solverjmt.maxEvents = numEvents*sn.nnodes*sn.nclasses;
52solverjmt.runAnalyzer(); % log data
53logData = SolverJMT.parseLogs(modelCopy, isNodeLogged, MetricType.toText(MetricType.QLen));
55% from here convert from
nodes in logData to stations
57sn = modelCopy.getStruct;
58for ist= 1:sn.nstations
59 isf = sn.stationToStateful(ist);
60 ind = sn.stationToNode(ist);
62 nir = cell(1,sn.nclasses);
64 if sn.nodetype(ind) == NodeType.Source
68 if ~isempty(logData{isf,r})
69 [~,uniqTSi] = unique(logData{isf,r}.t);
70 if isNodeClassLogged(isf,r)
71 if ~isempty(logData{isf,r})
72 t = logData{isf,r}.t(uniqTSi);
73 event{isf,r} = logData{isf,r}.event;
74 %t = [t(2:end);t(end)];
75 nir{r} = logData{isf,r}.QLen(uniqTSi);
84 if isfinite(self.options.timespan(2))
85 stopAt = find(t>self.options.timespan(2),1,'first');
86 if ~isempty(stopAt) && stopAt>1
89 nir{r} = nir{r}(1:(stopAt-1));
93 statStateAggr{ist} =
struct();
94 statStateAggr{ist}.handle = self.model.stations{ist};
95 statStateAggr{ist}.t = t;
96 statStateAggr{ist}.state = cell2mat(nir);
97 statStateAggr{ist}.event = {
event{isf,:}};
98 statStateAggr{ist}.isaggregate =
true;
99 %sysStateAggr.arv_job_id = logData{2}.arvID;
100 %sysStateAggr.dep_job_id = logData{2}.depID;
103tranSysStateAggr = cell(1,1+sn.nstations);
105tranSysStateAggr{1} = []; % timestamps
106for i=1:sn.nstations % stations
107 if isempty(tranSysStateAggr{1})
108 tranSysStateAggr{1} = statStateAggr{i}.t;
110 tumax = min(max(tranSysStateAggr{1}),max(statStateAggr{i}.t));
111 tranSysStateAggr{1} =
union(tranSysStateAggr{1}, statStateAggr{i}.t);
112 tranSysStateAggr{1} = tranSysStateAggr{1}(tranSysStateAggr{1}<=tumax);
113 tranSysStateAggr{1} =
union(tranSysStateAggr{1}, statStateAggr{i}.t);
117for i=1:sn.nstations % stations
118 ind = sn.stationToNode(i);
119 tranSysStateAggr{1+i} = [];
120 [~,uniqTSi] = unique(statStateAggr{i}.t);
121 if sn.nodetype(ind) ~= NodeType.Source
123 % we floor the interpolation as we hold the last state
125 Qijt = interp1(statStateAggr{i}.t(uniqTSi), statStateAggr{i}.state(uniqTSi,j), tranSysStateAggr{1},
'previous');
127 Qijt(end)=Qijt(end-1);
129 tranSysStateAggr{1+i} = [tranSysStateAggr{1+i}, Qijt];
131 Qijt = NaN*ones(length(tranSysStateAggr{1}),1);
132 tranSysStateAggr{1+i} = [tranSysStateAggr{1+i}, Qijt];
136 tranSysStateAggr{1+i} = [Inf];
140sysStateAggr =
struct();
141sysStateAggr.handle = self.model.stations
';
142sysStateAggr.t = tranSysStateAggr{1};
143sysStateAggr.state = {tranSysStateAggr{2:end}};
145% % % now put the events in the .event cell
146% eventSysStateAggr = cell(sn.nstations, sn.nclasses); % timestamps
147% for i=1:sn.nstations % stations
149% if isempty(statStateAggr{i}.event)
150% eventSysStateAggr{i,r} = struct();
152% eventSysStateAggr{i,r} = struct();
153% for e=1:size(statStateAggr{i}.event{r},1)
154% if ~isempty(statStateAggr{i}.event{r}{e})
155% %statStateAggr{i}.event{r}{e}.t
156% %etpos = find(sysStateAggr.t == statStateAggr{i}.event{r}{e}.t);
158% evtype = statStateAggr{i}.event{r}{e}.event;
159% evfield = EventType.toText(evtype);
160% if ~isfield(eventSysStateAggr{i,r},evfield)
161% eventSysStateAggr{i,r}.(EventType.toText(evtype)) = {};
163% eventSysStateAggr{i,r}.(EventType.toText(evtype)){end+1,1} = statStateAggr{i}.event{r}{e};
167% %eventSysStateAggr{i,r} = statStateAggr{i}.event{r};
171% %sysStateAggr.t = [0; sysStateAggr.t(1:end-1)];
172% sysStateAggr.event = eventSysStateAggr;
174% Flatten the 2D `event` cell into a column cell of Event objects, sorted by
175% time. Robust to the fact that some `event{i,j}` slots may be `[]` (numeric)
176% rather than `{}` (cell) when nclasses>1, due to implicit cell-array growth.
178for ii=1:size(event,1)
179 for jj=1:size(event,2)
180 cellij = event{ii,jj};
181 if iscell(cellij) && ~isempty(cellij)
182 for kk=1:numel(cellij)
183 if isa(cellij{kk}, 'Event
')
184 flatEvents{end+1,1} = cellij{kk};
190if isempty(flatEvents)
191 sysStateAggr.event = cell(0,1);
193 event_t = cellfun(@(c) c.t, flatEvents);
194 [~,I] = sort(event_t);
195 sysStateAggr.event = flatEvents(I);
197sysStateAggr.isaggregate = true;
198%sysStateAggr.arv_job_id = logData{2}.arvID;
199%sysStateAggr.dep_job_id = logData{2}.depID;
202 apevent = cell(1,length(sysStateAggr.t)-1);
203 for ti = 1:length(apevent)
204 apevent{ti} = struct('active
',[],'passive
',[]);
206 for e=1:length(sysStateAggr.event)
207 ti = find(sysStateAggr.event{e}.t == sysStateAggr.t);
209 switch sysStateAggr.event{e}.event
211 apevent{ti-1}.passive = sysStateAggr.event{e};
213 apevent{ti-1}.active = sysStateAggr.event{e};
217 sysStateAggr.event = apevent';