root / src / eventlog / sequencechartfacade.cc @ 0596ce67
History  View  Annotate  Download (37.4 KB)
1 
//=========================================================================


2 
// SEQUENCECHARTFACADE.CC  part of

3 
// OMNeT++/OMNEST

4 
// Discrete System Simulation in C++

5 
//

6 
// Author: Levente Meszaros

7 
//

8 
//=========================================================================

9  
10 
/**

11 
Copyright (C) 20062008 OpenSim Ltd.

12 

13 
This file is distributed WITHOUT ANY WARRANTY. See the file

14 
`license' for details on this and other legal matters.

15 
**/

16  
17 
#include <stdio.h> 
18 
#include <algorithm> 
19 
#include <set> 
20 
#include <math.h> 
21 
#include "lcgrandom.h" 
22 
#include "ievent.h" 
23 
#include "ieventlog.h" 
24 
#include "event.h" 
25 
#include "messagedependency.h" 
26 
#include "sequencechartfacade.h" 
27  
28 
USING_NAMESPACE 
29  
30 
SequenceChartFacade::SequenceChartFacade(IEventLog *eventLog) : EventLogFacade(eventLog) 
31 
{ 
32 
timelineMode = NONLINEAR; 
33 
timelineCoordinateSystemVersion = 1;

34 
undefineTimelineCoordinateSystem(); 
35  
36 
nonLinearMinimumTimelineCoordinateDelta = 0.1; 
37 
setNonLinearFocus(calculateNonLinearFocus()); 
38  
39 
smallestComplexity = 1;

40 
largestComplexity = 1;

41  
42 
smallestDuration = 1;

43 
largestDuration = 1;

44  
45 
cachedParallelSet.clear(); 
46 
cachedCriticalPath.clear(); 
47 
} 
48  
49 
void SequenceChartFacade::synchronize(FileReader::FileChangedState change)

50 
{ 
51 
if (change != FileReader::UNCHANGED) {

52 
EventLogFacade::synchronize(change); 
53  
54 
setNonLinearFocus(calculateNonLinearFocus()); 
55  
56 
if (timelineCoordinateOriginEventNumber != 1) { 
57 
IEvent *event = eventLog>getEventForEventNumber(timelineCoordinateOriginEventNumber); 
58  
59 
if (event)

60 
relocateTimelineCoordinateSystem(event); 
61 
else

62 
undefineTimelineCoordinateSystem(); 
63 
} 
64 
} 
65 
} 
66  
67 
double SequenceChartFacade::calculateNonLinearFocus()

68 
{ 
69 
if (!eventLog>isEmpty()) {

70 
double lastEventSimulationTime = eventLog>getLastEvent()>getSimulationTime().dbl();

71 
double firstEventSimulationTime = eventLog>getFirstEvent()>getSimulationTime().dbl();

72 
double totalSimulationTimeDelta = lastEventSimulationTime  firstEventSimulationTime;

73  
74 
if (totalSimulationTimeDelta == 0) 
75 
totalSimulationTimeDelta = firstEventSimulationTime; 
76  
77 
if (totalSimulationTimeDelta == 0) 
78 
return 1; 
79 
else

80 
return totalSimulationTimeDelta / eventLog>getApproximateNumberOfEvents() / 10; 
81 
} 
82 
else

83 
return 1; 
84 
} 
85  
86 
void SequenceChartFacade::setNonLinearMinimumTimelineCoordinateDelta(double value) 
87 
{ 
88 
Assert(value >= 0);

89 
nonLinearMinimumTimelineCoordinateDelta = value; 
90 
} 
91  
92 
void SequenceChartFacade::setNonLinearFocus(double nonLinearFocus) 
93 
{ 
94 
Assert(nonLinearFocus >= 0);

95 
this>nonLinearFocus = nonLinearFocus;

96 
} 
97  
98 
void SequenceChartFacade::undefineTimelineCoordinateSystem()

99 
{ 
100 
timelineCoordinateSystemVersion++; 
101 
timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = 1;

102 
timelineCoordinateOriginSimulationTime = simtime_nil; 
103 
timelineCoordinateOriginRealTime = 0;

104 
} 
105  
106 
void SequenceChartFacade::relocateTimelineCoordinateSystem(IEvent *event)

107 
{ 
108 
Assert(event); 
109  
110 
timelineCoordinateSystemVersion++; 
111 
timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = event>getEventNumber(); 
112 
timelineCoordinateOriginSimulationTime = event>getSimulationTime(); 
113 
timelineCoordinateOriginRealTime = event>getEarliestStartTime() / 1000000.0; 
114 
event>cachedTimelineCoordinate = 0;

115 
event>cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion; 
116 
} 
117  
118 
void SequenceChartFacade::setTimelineMode(TimelineMode timelineMode)

119 
{ 
120 
this>timelineMode = timelineMode;

121  
122 
if (timelineCoordinateOriginEventNumber != 1) 
123 
relocateTimelineCoordinateSystem(eventLog>getEventForEventNumber(timelineCoordinateOriginEventNumber)); 
124 
} 
125  
126 
double SequenceChartFacade::IEvent_getTimelineCoordinate(ptr_t ptr)

127 
{ 
128 
IEVENT_PTR(ptr); 
129 
return getTimelineCoordinate((IEvent*)ptr);

130 
} 
131  
132 
double SequenceChartFacade::IEvent_getTimelineEventEndCoordinate(ptr_t ptr)

133 
{ 
134 
IEVENT_PTR(ptr); 
135 
return getTimelineEventEndCoordinate((IEvent*)ptr);

136 
} 
137  
138 
double SequenceChartFacade::getTimelineCoordinateDelta(double simulationTimeDelta) 
139 
{ 
140 
Assert(nonLinearFocus > 0);

141  
142 
if (timelineMode == STEP)

143 
return 1; 
144 
else

145 
return nonLinearMinimumTimelineCoordinateDelta + (1  nonLinearMinimumTimelineCoordinateDelta) * atan(fabs(simulationTimeDelta) / nonLinearFocus) / PI * 2; 
146 
} 
147  
148 
double SequenceChartFacade::getTimelineCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit) 
149 
{ 
150 
IEVENT_PTR(ptr); 
151 
return getTimelineCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);

152 
} 
153  
154 
double SequenceChartFacade::getTimelineEventEndCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit) 
155 
{ 
156 
IEVENT_PTR(ptr); 
157 
return getTimelineEventEndCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);

158 
} 
159  
160 
double SequenceChartFacade::getTimelineCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit) 
161 
{ 
162 
Assert(event); 
163 
Assert(event>getEventLog() == eventLog); 
164 
Assert(timelineCoordinateSystemVersion != 1);

165 
Assert(timelineCoordinateOriginEventNumber != 1);

166  
167 
if (this>timelineCoordinateSystemVersion > event>cachedTimelineCoordinateSystemVersion) { 
168 
double timelineCoordinate;

169  
170 
switch (timelineMode) {

171 
case REAL_TIME:

172 
timelineCoordinate = ((event>getEarliestStartTime()/1000000.0  timelineCoordinateOriginRealTime)); 
173 
break;

174 
case SIMULATION_TIME:

175 
timelineCoordinate = (event>getSimulationTime()  timelineCoordinateOriginSimulationTime).dbl(); 
176 
break;

177 
case EVENT_NUMBER:

178 
timelineCoordinate = event>getEventNumber()  timelineCoordinateOriginEventNumber; 
179 
break;

180 
case STEP:

181 
case NONLINEAR:

182 
{ 
183 
IEvent *previousEvent = NULL;

184 
// do we go forward from end or backward from start of known range

185 
bool forward = event>getEventNumber() > timelineCoordinateRangeEndEventNumber;

186 
IEvent *currentEvent = eventLog>getEventForEventNumber(forward ? timelineCoordinateRangeEndEventNumber : timelineCoordinateRangeStartEventNumber); 
187  
188 
Assert(event>getEventNumber() < timelineCoordinateRangeStartEventNumber  timelineCoordinateRangeEndEventNumber < event>getEventNumber()); 
189  
190 
// TODO: LONG RUNNING OPERATION

191 
// does a linear search towards the event to calculate the non linear timeline coordinate

192 
do {

193 
eventLog>progress(); 
194  
195 
Assert(currentEvent); 
196 
previousEvent = currentEvent; 
197 
currentEvent = forward ? currentEvent>getNextEvent() : currentEvent>getPreviousEvent(); 
198 
Assert(currentEvent); 
199  
200 
simtime_t previousSimulationTime = previousEvent>getSimulationTime(); 
201 
double previousTimelineCoordinate = previousEvent>cachedTimelineCoordinate;

202 
simtime_t simulationTime = currentEvent>getSimulationTime(); 
203 
double timelineCoordinateDelta = getTimelineCoordinateDelta((simulationTime  previousSimulationTime).dbl());

204  
205 
if (forward) {

206 
timelineCoordinate = previousTimelineCoordinate + timelineCoordinateDelta; 
207  
208 
if (timelineCoordinate > upperTimelineCoordinateCalculationLimit)

209 
return NaN;

210 
} 
211 
else {

212 
timelineCoordinate = previousTimelineCoordinate  timelineCoordinateDelta; 
213  
214 
if (timelineCoordinate < lowerTimelineCoordinateCalculationLimit)

215 
return NaN;

216 
} 
217  
218 
currentEvent>cachedTimelineCoordinate = timelineCoordinate; 
219 
currentEvent>cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion; 
220 
} 
221 
while (currentEvent != event);

222  
223 
if (forward)

224 
timelineCoordinateRangeEndEventNumber = event>getEventNumber(); 
225 
else

226 
timelineCoordinateRangeStartEventNumber = event>getEventNumber(); 
227 
} 
228 
break;

229 
default:

230 
throw opp_runtime_error("Unknown timeline mode"); 
231 
} 
232  
233 
event>cachedTimelineCoordinate = timelineCoordinate; 
234 
event>cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion; 
235 
} 
236  
237 
return event>cachedTimelineCoordinate;

238 
} 
239  
240 
double SequenceChartFacade::getTimelineEventEndCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit) 
241 
{ 
242 
Assert(event); 
243 
Assert(event>getEventLog() == eventLog); 
244 
if(!eventLog>isLegacyTrace()) {

245 
return getTimelineCoordinate(event);

246 
} 
247 
double timelineEventEndCoordinate;

248 
switch (timelineMode) {

249 
case REAL_TIME:

250 
timelineEventEndCoordinate = (event>getEarliestProcessingTime()/ 1000000.0  timelineCoordinateOriginRealTime) ; 
251 
break;

252 
case SIMULATION_TIME:

253 
timelineEventEndCoordinate = (event>getSimulationTime()+event>getEventEntry()>duration  timelineCoordinateOriginSimulationTime).dbl(); 
254 
break;

255 
default:

256 
return getTimelineCoordinate(event);

257 
} 
258 
return timelineEventEndCoordinate;

259 
} 
260  
261 
double SequenceChartFacade::getCachedTimelineCoordinate(IEvent *event)

262 
{ 
263 
Assert(event); 
264 
Assert(timelineCoordinateSystemVersion != 1);

265 
Assert(timelineCoordinateOriginEventNumber != 1);

266  
267 
if (this>timelineCoordinateSystemVersion > event>cachedTimelineCoordinateSystemVersion) 
268 
return 1; 
269 
else

270 
return event>cachedTimelineCoordinate;

271 
} 
272  
273 
IEvent *SequenceChartFacade::getEventForNonLinearTimelineCoordinate(double timelineCoordinate, bool &forward) 
274 
{ 
275 
Assert(timelineCoordinateOriginEventNumber != 1);

276 
IEvent *timelineCoordinateRangeStartEvent = eventLog>getEventForEventNumber(timelineCoordinateRangeStartEventNumber); 
277 
IEvent *timelineCoordinateRangeEndEvent = eventLog>getEventForEventNumber(timelineCoordinateRangeEndEventNumber); 
278 
IEvent *currentEvent; 
279  
280 
Assert(timelineCoordinateRangeStartEvent && timelineCoordinateRangeEndEvent); 
281  
282 
if (timelineCoordinate <= getTimelineCoordinate(timelineCoordinateRangeStartEvent)) {

283 
forward = false;

284 
currentEvent = timelineCoordinateRangeStartEvent; 
285 
} 
286 
else if (getTimelineCoordinate(timelineCoordinateRangeEndEvent) <= timelineCoordinate) { 
287 
forward = true;

288 
currentEvent = timelineCoordinateRangeEndEvent; 
289 
} 
290 
else {

291 
forward = true;

292 
currentEvent = timelineCoordinateRangeStartEvent; 
293 
} 
294  
295 
// TODO: LONG RUNNING OPERATION

296 
// does a linear search towards requested non linear timeline coordinate

297 
while (currentEvent && (forward ? getTimelineCoordinate(currentEvent) < timelineCoordinate :

298 
timelineCoordinate <= getTimelineCoordinate(currentEvent))) 
299 
{ 
300 
eventLog>progress(); 
301 
currentEvent = forward ? currentEvent>getNextEvent() : currentEvent>getPreviousEvent(); 
302 
} 
303  
304 
return currentEvent;

305 
} 
306  
307 
IEvent *SequenceChartFacade::getLastEventNotAfterTimelineCoordinate(double timelineCoordinate)

308 
{ 
309 
if (eventLog>isEmpty())

310 
return NULL; 
311  
312 
switch (timelineMode) {

313 
case REAL_TIME:

314 
{ 
315 
//TODO MAKE THIS MORE EFFICIENT (i.e. sorted data structure)!

316 
IEvent* res = eventLog>getFirstEvent(); 
317 
for (IEvent *current = eventLog>getFirstEvent(); current; current = current>getNextEvent()) {

318 
if ((double) current>getEarliestStartTime() / 1000000.0 < timelineCoordinate) { 
319 
if (current>getEarliestStartTime() > res>getEarliestStartTime()) {

320 
res = current; 
321 
} 
322 
} 
323 
} 
324 
return res;

325 
} 
326 
case SIMULATION_TIME:

327 
return eventLog>getLastEventNotAfterSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));

328 
case EVENT_NUMBER:

329 
{ 
330 
eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber; 
331  
332 
if (eventNumber < 0) 
333 
return NULL; 
334 
else

335 
return eventLog>getLastEventNotAfterEventNumber(eventNumber);

336 
} 
337 
case STEP:

338 
case NONLINEAR:

339 
{ 
340 
bool forward;

341 
IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward); 
342 
currentEvent = forward ? (currentEvent ? currentEvent>getPreviousEvent() : eventLog>getLastEvent()) : currentEvent; 
343  
344 
Assert(!currentEvent  getTimelineCoordinate(currentEvent) <= timelineCoordinate); 
345 
return currentEvent;

346 
} 
347 
default:

348 
throw opp_runtime_error("Unknown timeline mode"); 
349 
} 
350 
} 
351  
352 
IEvent *SequenceChartFacade::getFirstEventNotBeforeTimelineCoordinate(double timelineCoordinate)

353 
{ 
354 
if (eventLog>isEmpty())

355 
return NULL; 
356  
357 
switch (timelineMode) {

358 
case REAL_TIME:

359 
{ 
360 
//TODO MAKE THIS MORE EFFICIENT (i.e. sorted data structure)!

361 
IEvent* res = eventLog>getLastEvent(); 
362 
for (IEvent *current = eventLog>getFirstEvent(); current; current = current>getNextEvent()) {

363 
if ((double) current>getEarliestStartTime() / 1000000.0 > timelineCoordinate) { 
364 
if (current>getEarliestStartTime() < res>getEarliestStartTime()) {

365 
res = current; 
366 
} 
367 
} 
368 
} 
369 
return res;

370 
} 
371 
case SIMULATION_TIME:

372 
return eventLog>getFirstEventNotBeforeSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));

373 
case EVENT_NUMBER:

374 
{ 
375 
eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber; 
376  
377 
if (eventNumber < 0) 
378 
return eventLog>getFirstEvent();

379 
else

380 
return eventLog>getFirstEventNotBeforeEventNumber(eventNumber);

381 
} 
382 
case STEP:

383 
case NONLINEAR:

384 
{ 
385 
bool forward;

386 
IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward); 
387 
currentEvent = forward ? currentEvent : (currentEvent ? currentEvent>getNextEvent() : eventLog>getFirstEvent()); 
388  
389 
Assert(!currentEvent  getTimelineCoordinate(currentEvent) >= timelineCoordinate); 
390 
return currentEvent;

391 
} 
392 
default:

393 
throw opp_runtime_error("Unknown timeline mode"); 
394 
} 
395 
} 
396  
397 
void SequenceChartFacade::extractSimulationTimesAndTimelineCoordinates(

398 
IEvent *event, IEvent *&nextEvent, 
399 
simtime_t &eventSimulationTime, double &eventTimelineCoordinate,

400 
simtime_t &nextEventSimulationTime, double &nextEventTimelineCoordinate,

401 
simtime_t &simulationTimeDelta, double &timelineCoordinateDelta)

402 
{ 
403 
// if before the first event

404 
if (event) {

405 
if (timelineMode==REAL_TIME) {

406 
eventSimulationTime = event>getEarliestStartTime() / 1000000.0; 
407 
} else {

408 
eventSimulationTime = event>getSimulationTime(); 
409 
} 
410 
eventTimelineCoordinate = getTimelineCoordinate(event); 
411 
} 
412 
else {

413 
eventSimulationTime = BigDecimal::Zero; 
414 
IEvent *firstEvent = eventLog>getFirstEvent(); 
415 
eventTimelineCoordinate = getTimelineCoordinate(firstEvent); 
416  
417 
if (timelineMode == EVENT_NUMBER)

418 
eventTimelineCoordinate = 1;

419 
else if (timelineMode == REAL_TIME) 
420 
eventTimelineCoordinate = getTimelineCoordinateDelta(0);

421 
else

422 
eventTimelineCoordinate = getTimelineCoordinateDelta(firstEvent>getSimulationTime().dbl()); 
423 
} 
424  
425 
// linear approximation between two enclosing events

426 
nextEvent = event ? event>getNextEvent() : eventLog>getFirstEvent(); 
427  
428 
if (nextEvent) {

429 
if(timelineMode==REAL_TIME) {

430 
nextEventSimulationTime = nextEvent>getEarliestStartTime() / 1000000.0; 
431 
} else {

432 
nextEventSimulationTime = nextEvent>getSimulationTime(); 
433 
} 
434  
435 
nextEventTimelineCoordinate = getTimelineCoordinate(nextEvent); 
436  
437 
simulationTimeDelta = nextEventSimulationTime  eventSimulationTime; 
438 
timelineCoordinateDelta = nextEventTimelineCoordinate  eventTimelineCoordinate; 
439 
} 
440 
} 
441  
442 
simtime_t SequenceChartFacade::getSimulationTimeForTimelineCoordinate(double timelineCoordinate, bool upperLimit) 
443 
{ 
444 
Assert(!isNaN(timelineCoordinate)); 
445  
446 
if (eventLog>isEmpty())

447 
return BigDecimal::Zero;

448  
449 
simtime_t simulationTime; 
450  
451 
switch (timelineMode)

452 
{ 
453 
case REAL_TIME:

454 
{ 
455 
simtime_t lastEventSimulationTime = (eventLog>getLastEvent()>getEarliestStartTime())/1000000.0; 
456 
//NOTE: This sometimes crashes the Sequencechart because the returned value might be too big

457 
simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, (timelineCoordinate + timelineCoordinateOriginRealTime))); 
458 
} 
459 
break;

460 
case SIMULATION_TIME:

461 
{ 
462 
simtime_t lastEventSimulationTime = eventLog>getLastEvent()>getSimulationTime(); 
463 
simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, timelineCoordinate + timelineCoordinateOriginSimulationTime)); 
464 
} 
465 
break;

466 
case EVENT_NUMBER:

467 
case STEP:

468 
case NONLINEAR:

469 
{ 
470 
IEvent *nextEvent; 
471 
simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta; 
472 
double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;

473  
474 
IEvent *event = getLastEventNotAfterTimelineCoordinate(timelineCoordinate); 
475 
extractSimulationTimesAndTimelineCoordinates(event, nextEvent, 
476 
eventSimulationTime, eventTimelineCoordinate, 
477 
nextEventSimulationTime, nextEventTimelineCoordinate, 
478 
simulationTimeDelta, timelineCoordinateDelta); 
479  
480 
if (nextEvent) {

481 
if (timelineCoordinateDelta == 0) { 
482 
// IMPORTANT NOTE: this is just an approximation

483 
if (upperLimit)

484 
simulationTime = nextEventSimulationTime; 
485 
else

486 
simulationTime = eventSimulationTime; 
487 
} 
488 
else {

489 
timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate)); 
490 
simulationTime = eventSimulationTime + simulationTimeDelta * (timelineCoordinate  eventTimelineCoordinate) / timelineCoordinateDelta; 
491 
simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime)); 
492 
} 
493 
} 
494 
else

495 
simulationTime = eventSimulationTime; 
496 
} 
497 
break;

498 
default:

499 
throw opp_runtime_error("Unknown timeline mode"); 
500 
} 
501  
502 
Assert(!simulationTime.isNaN()); 
503 
Assert(simulationTime >= BigDecimal::Zero); 
504 
if (timelineMode != REAL_TIME)

505 
Assert(simulationTime <= eventLog>getLastEvent()>getSimulationTime()); 
506  
507 
return simulationTime;

508 
} 
509  
510 
double SequenceChartFacade::getTimelineCoordinateForSimulationTime(simtime_t simulationTime, bool upperLimit) 
511 
{ 
512 
Assert(!simulationTime.isNaN()); 
513  
514 
if (eventLog>isEmpty())

515 
return 0; 
516  
517 
Assert(simulationTime >= BigDecimal::Zero); 
518 
if (timelineMode != REAL_TIME)

519 
Assert(simulationTime <= eventLog>getLastEvent()>getSimulationTime()); 
520  
521  
522 
double timelineCoordinate;

523  
524 
switch (timelineMode)

525 
{ 
526 
case REAL_TIME:

527 
//treat simulationTime as real time:

528 
timelineCoordinate = simulationTime.dbl()  timelineCoordinateOriginRealTime; 
529 
break;

530 
case SIMULATION_TIME:

531 
timelineCoordinate = (simulationTime  timelineCoordinateOriginSimulationTime).dbl(); 
532 
break;

533 
case EVENT_NUMBER:

534 
case STEP:

535 
case NONLINEAR:

536 
{ 
537 
IEvent *nextEvent; 
538 
simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta; 
539 
double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;

540  
541 
IEvent *event = eventLog>getLastEventNotAfterSimulationTime(simulationTime); 
542 
extractSimulationTimesAndTimelineCoordinates(event, nextEvent, 
543 
eventSimulationTime, eventTimelineCoordinate, 
544 
nextEventSimulationTime, nextEventTimelineCoordinate, 
545 
simulationTimeDelta, timelineCoordinateDelta); 
546  
547 
if (nextEvent) {

548 
if (simulationTimeDelta == BigDecimal::Zero) {

549 
// IMPORTANT NOTE: this is just an approximation

550 
if (upperLimit)

551 
timelineCoordinate = nextEventTimelineCoordinate; 
552 
else

553 
timelineCoordinate = eventTimelineCoordinate; 
554 
} 
555 
else {

556 
simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime)); 
557 
timelineCoordinate = eventTimelineCoordinate + timelineCoordinateDelta * (simulationTime  eventSimulationTime).dbl() / simulationTimeDelta.dbl(); 
558 
timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate)); 
559 
} 
560 
} 
561 
else

562 
timelineCoordinate = eventTimelineCoordinate; 
563 
} 
564 
break;

565 
default:

566 
throw opp_runtime_error("Unknown timeline mode"); 
567 
} 
568  
569 
Assert(!isNaN(timelineCoordinate)); 
570  
571 
return timelineCoordinate;

572 
} 
573  
574 
double SequenceChartFacade::getTimelineCoordinateForSimulationTimeAndEventInModule(simtime_t simulationTime, int moduleId) 
575 
{ 
576 
IEvent *event = eventLog>getLastEventNotAfterSimulationTime(simulationTime); 
577  
578 
while (event && event>getSimulationTime() == simulationTime) {

579 
if (event>getModuleId() == moduleId)

580 
return getTimelineCoordinate(event);

581  
582 
event = event>getNextEvent(); 
583 
} 
584  
585 
return getTimelineCoordinateForSimulationTime(simulationTime);

586 
} 
587  
588 
std::vector<ptr_t> *SequenceChartFacade::getModuleMethodBeginEntries(ptr_t startEventPtr, ptr_t endEventPtr) 
589 
{ 
590 
IEvent *startEvent = (IEvent *)startEventPtr; 
591 
IEvent *endEvent = (IEvent *)endEventPtr; 
592 
Assert(startEvent); 
593 
Assert(endEvent); 
594 
std::vector<ptr_t> *moduleMethodBeginEntries = new std::vector<ptr_t>();

595  
596 
for (IEvent *event = startEvent;; event = event>getNextEvent()) {

597 
eventLog>progress(); 
598  
599 
for (int i = 0; i < event>getNumEventLogEntries(); i++) { 
600 
EventLogEntry *eventLogEntry = event>getEventLogEntry(i); 
601  
602 
if (dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry)) 
603 
moduleMethodBeginEntries>push_back((ptr_t)eventLogEntry); 
604 
} 
605  
606 
if (event == endEvent)

607 
break;

608 
} 
609  
610 
return moduleMethodBeginEntries;

611 
} 
612  
613 
std::vector<ptr_t> *SequenceChartFacade::getIntersectingMessageDependencies(ptr_t startEventPtr, ptr_t endEventPtr) 
614 
{ 
615 
IEvent *startEvent = (IEvent *)startEventPtr; 
616 
IEvent *endEvent = (IEvent *)endEventPtr; 
617 
Assert(startEvent); 
618 
Assert(endEvent); 
619 
std::set<ptr_t> messageDependencies; 
620 
eventnumber_t startEventNumber = startEvent>getEventNumber(); 
621  
622 
// TODO: LONG RUNNING OPERATION

623 
// this might take a while if start and end events are far away from each other

624 
// if not completed then some dependencies will not be included

625 
for (IEvent *event = startEvent;; event = event>getNextEvent()) {

626 
eventLog>progress(); 
627 
IMessageDependencyList *causes = event>getCauses(); 
628  
629 
for (IMessageDependencyList::iterator it = causes>begin(); it != causes>end(); it++) {

630 
IMessageDependency *messageDependency = *it; 
631  
632 
if (messageDependency>getCauseEventNumber() < startEventNumber)

633 
messageDependencies.insert((ptr_t)messageDependency); 
634 
} 
635  
636 
IMessageDependencyList *consequences = event>getConsequences(); 
637  
638 
for (IMessageDependencyList::iterator it = consequences>begin(); it != consequences>end(); it++)

639 
messageDependencies.insert((ptr_t)*it); 
640  
641 
if (event == endEvent)

642 
break;

643 
} 
644  
645 
std::vector<ptr_t> *result = new std::vector<ptr_t>;

646 
result>resize(messageDependencies.size()); 
647 
std::copy(messageDependencies.begin(), messageDependencies.end(), result>begin()); 
648  
649 
return result;

650 
} 
651  
652 
std::vector<int> SequenceChartFacade::getApproximateMessageDependencyCountAdjacencyMatrix(std::map<int, int> *moduleIdToAxisIndexMap, int numberOfSamples, int messageSendWeight, int messageReuseWeight) 
653 
{ 
654 
LCGRandom lcgRandom; 
655 
std::vector<int> adjacencyMatrix;

656 
std::set<int> axisIndexSet;

657 
std::map<eventnumber_t, IEvent *> eventNumberToEventMap; 
658  
659 
for (std::map<int, int>::iterator it = moduleIdToAxisIndexMap>begin(); it != moduleIdToAxisIndexMap>end(); it++) 
660 
axisIndexSet.insert(it>second); 
661  
662 
int numberOfAxes = axisIndexSet.size();

663 
adjacencyMatrix.resize(numberOfAxes * numberOfAxes); 
664  
665 
for (int i = 0; i < numberOfSamples; i++) 
666 
{ 
667 
// draw random

668 
double percentage = lcgRandom.next01();

669 
IEvent *event = eventLog>getApproximateEventAt(percentage); 
670 
eventNumberToEventMap[event>getEventNumber()] = event; 
671  
672 
// look before origin

673 
if (timelineCoordinateOriginEventNumber != 1) { 
674 
if (timelineCoordinateOriginEventNumber  i >= 0) { 
675 
event = eventLog>getEventForEventNumber(timelineCoordinateOriginEventNumber  i); 
676 
if (event)

677 
eventNumberToEventMap[event>getEventNumber()] = event; 
678 
} 
679  
680 
// look after origin

681 
event = eventLog>getEventForEventNumber(timelineCoordinateOriginEventNumber + i); 
682 
if (event)

683 
eventNumberToEventMap[event>getEventNumber()] = event; 
684 
} 
685 
} 
686  
687 
for (std::map<eventnumber_t, IEvent *>::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++) {

688 
IEvent *event = it>second; 
689 
IMessageDependencyList *causes = event>getCauses(); 
690  
691 
for (IMessageDependencyList::iterator it = causes>begin(); it != causes>end(); it++) {

692 
IMessageDependency *messageDependency = *it; 
693 
IEvent *causeEvent = messageDependency>getCauseEvent(); 
694 
IEvent *consequenceEvent = messageDependency>getConsequenceEvent(); 
695 
int weight = messageDependency>getIsReuse() ? messageReuseWeight : messageSendWeight;

696  
697 
if (causeEvent && consequenceEvent && weight != 0) { 
698 
int causeModuleId = causeEvent>getModuleId();

699 
int consequenceModuleId = consequenceEvent>getModuleId();

700  
701 
std::map<int, int>::iterator causeModuleIdIt = moduleIdToAxisIndexMap>find(causeModuleId); 
702 
std::map<int, int>::iterator consequenceModuleIdIt = moduleIdToAxisIndexMap>find(consequenceModuleId); 
703  
704 
if (causeModuleIdIt != moduleIdToAxisIndexMap>end() && consequenceModuleIdIt != moduleIdToAxisIndexMap>end())

705 
adjacencyMatrix.at(causeModuleIdIt>second * numberOfAxes + consequenceModuleIdIt>second) += weight; 
706 
} 
707 
} 
708 
} 
709  
710 
return adjacencyMatrix;

711 
} 
712  
713  
714 
long SequenceChartFacade::getSmallestEventComplexity() {

715 
long complexity = 0; 
716 
if (smallestComplexity < 0) { 
717 
for (IEvent *event = eventLog>getFirstEvent();event != eventLog>getLastEvent(); event = event>getNextEvent()) {

718 
if (event>getEventEndEntry()) {

719 
complexity = event>getEventEndEntry()>complexity; 
720 
} else {

721 
continue;

722 
} 
723 
if (complexity < smallestComplexity  smallestComplexity < 0) { 
724 
smallestComplexity = complexity; 
725 
} 
726 
if (complexity > largestComplexity  largestComplexity < 0) { 
727 
largestComplexity = complexity; 
728 
} 
729 
} 
730 
} 
731 
if (smallestComplexity < 0) { 
732 
smallestComplexity = 0;

733 
} 
734 
return smallestComplexity;

735 
} 
736  
737 
long SequenceChartFacade::getLargestEventComplexity() {

738 
if (largestComplexity < 0) { 
739 
getSmallestEventComplexity(); 
740 
} 
741 
if (largestComplexity < 0) { 
742 
largestComplexity = 0;

743 
} 
744 
return largestComplexity;

745 
} 
746  
747 
simtime_t SequenceChartFacade::getSmallestEventDuration() { 
748 
simtime_t duration = 0;

749 
if (smallestDuration < 0) { 
750 
for (IEvent *event = eventLog>getFirstEvent();event != eventLog>getLastEvent(); event = event>getNextEvent()) {

751 
if (event>getEventEntry()) {

752 
duration = event>getEventEntry()>duration; 
753 
} else {

754 
continue;

755 
} 
756 
if (duration < smallestDuration  smallestDuration < 0) { 
757 
smallestDuration = duration; 
758 
} 
759 
if (duration > largestDuration  largestDuration < 0) { 
760 
largestDuration = duration; 
761 
} 
762 
} 
763 
} 
764 
if (smallestDuration < 0) { 
765 
smallestDuration = 0;

766 
} 
767 
return smallestDuration;

768 
} 
769  
770 
simtime_t SequenceChartFacade::getLargestEventDuration() { 
771 
if (largestDuration < 0) { 
772 
getSmallestEventComplexity(); 
773 
} 
774 
if (largestDuration < 0) { 
775 
largestDuration = 0;

776 
} 
777 
return largestDuration;

778 
} 
779  
780  
781 
IEvent* SequenceChartFacade::getPreviousBottleneck(IEvent* e, unsigned int threshold) { 
782 
IEvent* next = e>getPreviousEvent(); 
783 
while (next) {

784 
if (isBottleneck(next,threshold)) {

785 
return next;

786 
} 
787 
next = next>getPreviousEvent(); 
788 
} 
789 
return e;

790 
} 
791  
792 
IEvent* SequenceChartFacade::getNextBottleneck(IEvent* e, unsigned int threshold) { 
793 
IEvent* next = e>getNextEvent(); 
794 
while (next) {

795 
if (isBottleneck(next,threshold)) {

796 
return next;

797 
} 
798 
next = next>getNextEvent(); 
799 
} 
800 
return e;

801 
} 
802  
803 
/*

804 
* Returns whether an event not part of a set of parallel events with more than treshold elements.

805 
*/

806 
bool SequenceChartFacade::isBottleneck(IEvent* event, unsigned int threshold) 
807 
{ 
808 
return getLargestParallelSetSize(event) <= threshold;

809 
} 
810 
/*

811 
* Returns whether event is in the largest parallel set of selected.

812 
*/

813 
bool SequenceChartFacade::isParallelWithEvent(IEvent* event, IEvent* selected) {

814  
815 
if (lastSelected != selected) {

816 
getLargestParallelSet(selected, &cachedParallelSet); 
817 
} 
818 
return cachedParallelSet.find((ptr_t)event) != cachedParallelSet.end();

819 
} 
820 
/*

821 
* Returns the size of the largest set that is parallel with event.

822 
*

823 
* Works by calculating the first parallel set which does not contain event by

824 
* successively going backwards through all events starting from event.

825 
*/

826 
unsigned int SequenceChartFacade::getLargestParallelSetSize(IEvent* event) 
827 
{ 
828 
IEvent* prev = event; 
829 
std::set<ptr_t> parallelSet; 
830 
parallelSet.clear(); 
831 
unsigned int previousSize = 0; 
832 
while (prev)

833 
{ 
834 
previousSize = parallelSet.size(); 
835  
836 
getParallelSet(prev, ¶llelSet); 
837  
838 
if (parallelSet.find((ptr_t) event) == parallelSet.end())

839 
{ 
840 
//The current set does not contain event.

841 
//Therefore the previous set was the largest Parallel Set.

842 
break;

843 
} 
844 
prev = prev>getPreviousEvent(); 
845 
} 
846 
return previousSize;

847 
} 
848 
/*

849 
* Returns the largest set that is parallel with event.

850 
*

851 
* Works by calculating the first parallel set which does not contain event by

852 
* successively going backwards through all events starting from event.

853 
*/

854 
std::set<ptr_t>* SequenceChartFacade::getLargestParallelSet(IEvent* event, std::set<ptr_t>* parallelSet) { 
855 
IEvent* prev = event; 
856 
parallelSet>clear(); 
857 
while (prev)

858 
{ 
859 
getParallelSet(prev, parallelSet); 
860 
if (parallelSet>find((ptr_t) event) == parallelSet>end())

861 
{ 
862 
//The current set does not contain event.

863 
//Therefore the previous set was the largest Parallel Set.

864 
break;

865 
} 
866 
prev = prev>getPreviousEvent(); 
867 
} 
868 
if (prev != event) {

869 
getParallelSet(prev>getNextEvent(), parallelSet); 
870 
} 
871 
return parallelSet;

872 
} 
873  
874 
/*

875 
* Calculates a set of those events that start after event but are still in parallel to event.

876 
* This means that no other event must end before the latest start time in this set.

877 
*/

878 
void SequenceChartFacade::getParallelSet(IEvent* event,

879 
std::set<ptr_t>* parallelSet) 
880 
{ 
881 
IEvent* next = event>getNextEvent(); 
882 
simtime_t smallestParallelEndtime = getSmallestParallelEndtime(event); 
883 
parallelSet>clear(); 
884 
parallelSet>insert((ptr_t) event); 
885 
while (next)

886 
{ 
887 
if ((next>getSimulationTime() >= event>getSimulationTime())

888 
&& (smallestParallelEndtime >= next>getSimulationTime())) 
889 
{ 
890 
if(parallelSet>find((ptr_t)(next>getCauseEvent())) == parallelSet>end()) {

891 
parallelSet>insert((ptr_t) next); 
892 
} 
893 
} 
894 
else

895 
{ 
896 
break;

897 
} 
898 
next = next>getNextEvent(); 
899 
} 
900 
} 
901 
/*

902 
*

903 
*/

904 
simtime_t SequenceChartFacade::getSmallestParallelEndtime(IEvent* event) 
905 
{ 
906 
simtime_t minimum = event>getSimulationTime() 
907 
+ event>getEventEntry()>duration; 
908 
for (IEvent *current = eventLog>getFirstEvent(); current; current

909 
= current>getNextEvent()) 
910 
{ 
911 
if (current>getSimulationTime() >= event>getSimulationTime())

912 
{ 
913 
if ((current>getSimulationTime()

914 
+ current>getEventEntry()>duration) 
915 
> event>getSimulationTime()) 
916 
{ 
917 
if (minimum > (current>getSimulationTime()

918 
+ current>getEventEntry()>duration)) 
919 
{ 
920 
minimum = current>getSimulationTime() 
921 
+ current>getEventEntry()>duration; 
922 
} 
923 
} 
924 
if (current>getSimulationTime() > minimum)

925 
{ // After this, no overlapping can follow

926 
break;

927 
} 
928 
} 
929 
} 
930 
return minimum;

931 
} 
932  
933 
/*

934 
* Determines whether the event lies on the critical path

935 
*/

936 
bool SequenceChartFacade::isOnCriticalPath(IEvent* event) {

937 
if (cachedCriticalPath.empty()) {

938 
calculateCriticalPath(); 
939 
} 
940 
return (cachedCriticalPath.find((ptr_t)event) != cachedCriticalPath.end());

941 
} 
942  
943 
/*

944 
* Calculates the critical path of the run and stores it in the set cachedCriticalPath

945 
*/

946 
void SequenceChartFacade::calculateCriticalPath() {

947 
long maxEarliestProcessingTime = 0; 
948 
IEvent* maxEarliestProcessingTimeEvent; 
949  
950 
for (IEvent *current = eventLog>getFirstEvent(); current; current = current>getNextEvent()) {

951 
simtime_t startTime = current>getSimulationTime(); 
952 
int moduleId = current>getModuleId();

953 
if(current>getEventEndEntry()) {

954 
current>_earliestProcessingTime = current>getComplexity(); 
955 
} 
956  
957 
current>setCriticalPredecessor(eventLog>getFirstEvent()); 
958  
959 
for (IEvent *antecessor = eventLog>getFirstEvent(); antecessor; antecessor = antecessor>getNextEvent()) {

960 
if(antecessor==current) {

961 
break; //We have to consider earlier events only 
962 
} 
963 
if(antecessor>getModuleId() != moduleId && current>getCauseEvent() != antecessor) {

964 
continue; // Check if this is an antecesor 
965 
} 
966 
if(antecessor>_earliestProcessingTime+current>getComplexity() > current>_earliestProcessingTime) {

967 
current>_earliestProcessingTime = antecessor>_earliestProcessingTime+current>getComplexity(); 
968 
current>setCriticalPredecessor(antecessor); 
969 
} 
970 
} 
971 
// Memorize max event

972 
if (maxEarliestProcessingTime < current>_earliestProcessingTime) {

973 
maxEarliestProcessingTime = current>_earliestProcessingTime; 
974 
maxEarliestProcessingTimeEvent = current; 
975 
} 
976 
} 
977 
//Now produce the convex hull of critical antecessors/predecessors:

978 
cachedCriticalPath.clear(); 
979 
for (IEvent *predecessor = maxEarliestProcessingTimeEvent; predecessor ; predecessor = predecessor>getCriticalPredecessor()) {

980 
cachedCriticalPath.insert((ptr_t)predecessor); 
981 
if(predecessor>getEventNumber() == 0) { 
982 
break;

983 
} 
984 
} 
985 
} 
986 