Project

General

Profile

Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ 382d8398

History | View | Annotate | Download (30.7 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) 2006-2008 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

    
46
void SequenceChartFacade::synchronize(FileReader::FileChangedState change)
47
{
48
    if (change != FileReader::UNCHANGED) {
49
        EventLogFacade::synchronize(change);
50

    
51
        setNonLinearFocus(calculateNonLinearFocus());
52

    
53
        if (timelineCoordinateOriginEventNumber != -1) {
54
            IEvent *event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber);
55

    
56
            if (event)
57
                relocateTimelineCoordinateSystem(event);
58
            else
59
                undefineTimelineCoordinateSystem();
60
        }
61
    }
62
}
63

    
64
double SequenceChartFacade::calculateNonLinearFocus()
65
{
66
    if (!eventLog->isEmpty()) {
67
        double lastEventSimulationTime = eventLog->getLastEvent()->getSimulationTime().dbl();
68
        double firstEventSimulationTime = eventLog->getFirstEvent()->getSimulationTime().dbl();
69
        double totalSimulationTimeDelta = lastEventSimulationTime - firstEventSimulationTime;
70

    
71
        if (totalSimulationTimeDelta == 0)
72
            totalSimulationTimeDelta = firstEventSimulationTime;
73

    
74
        if (totalSimulationTimeDelta == 0)
75
            return 1;
76
        else
77
            return totalSimulationTimeDelta / eventLog->getApproximateNumberOfEvents() / 10;
78
    }
79
    else
80
        return 1;
81
}
82

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

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

    
95
void SequenceChartFacade::undefineTimelineCoordinateSystem()
96
{
97
    timelineCoordinateSystemVersion++;
98
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = -1;
99
    timelineCoordinateOriginSimulationTime = simtime_nil;
100
}
101

    
102
void SequenceChartFacade::relocateTimelineCoordinateSystem(IEvent *event)
103
{
104
    Assert(event);
105

    
106
    timelineCoordinateSystemVersion++;
107
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = event->getEventNumber();
108
    timelineCoordinateOriginSimulationTime = event->getSimulationTime();
109
    event->cachedTimelineCoordinate = 0;
110
    event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
111
}
112

    
113
void SequenceChartFacade::setTimelineMode(TimelineMode timelineMode)
114
{
115
    this->timelineMode = timelineMode;
116

    
117
    if (timelineCoordinateOriginEventNumber != -1)
118
        relocateTimelineCoordinateSystem(eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber));
119
}
120

    
121
double SequenceChartFacade::IEvent_getTimelineCoordinate(ptr_t ptr)
122
{
123
    IEVENT_PTR(ptr);
124
    return getTimelineCoordinate((IEvent*)ptr);
125
}
126

    
127
double SequenceChartFacade::IEvent_getTimelineEventEndCoordinate(ptr_t ptr)
128
{
129
    IEVENT_PTR(ptr);
130
    return getTimelineEventEndCoordinate((IEvent*)ptr);
131
}
132

    
133
double SequenceChartFacade::getTimelineCoordinateDelta(double simulationTimeDelta)
134
{
135
    Assert(nonLinearFocus > 0);
136

    
137
    if (timelineMode == STEP)
138
        return 1;
139
    else
140
        return nonLinearMinimumTimelineCoordinateDelta + (1 - nonLinearMinimumTimelineCoordinateDelta) * atan(fabs(simulationTimeDelta) / nonLinearFocus) / PI * 2;
141
}
142

    
143
double SequenceChartFacade::getTimelineCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
144
{
145
    IEVENT_PTR(ptr);
146
    return getTimelineCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
147
}
148

    
149
double SequenceChartFacade::getTimelineEventEndCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
150
{
151
    IEVENT_PTR(ptr);
152
    return getTimelineEventEndCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
153
}
154

    
155
double SequenceChartFacade::getTimelineCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
156
{
157
    Assert(event);
158
    Assert(event->getEventLog() == eventLog);
159
    Assert(timelineCoordinateSystemVersion != -1);
160
    Assert(timelineCoordinateOriginEventNumber != -1);
161

    
162
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion) {
163
        double timelineCoordinate;
164

    
165
        switch (timelineMode) {
166
            case SIMULATION_TIME:
167
                timelineCoordinate = (event->getSimulationTime() - timelineCoordinateOriginSimulationTime).dbl();
168
                break;
169
            case EVENT_NUMBER:
170
                timelineCoordinate = event->getEventNumber() - timelineCoordinateOriginEventNumber;
171
                break;
172
            case STEP:
173
            case NONLINEAR:
174
                {
175
                    IEvent *previousEvent = NULL;
176
                    // do we go forward from end or backward from start of known range
177
                    bool forward = event->getEventNumber() > timelineCoordinateRangeEndEventNumber;
178
                    IEvent *currentEvent = eventLog->getEventForEventNumber(forward ? timelineCoordinateRangeEndEventNumber : timelineCoordinateRangeStartEventNumber);
179

    
180
                    Assert(event->getEventNumber() < timelineCoordinateRangeStartEventNumber || timelineCoordinateRangeEndEventNumber < event->getEventNumber());
181

    
182
                    // TODO: LONG RUNNING OPERATION
183
                    // does a linear search towards the event to calculate the non linear timeline coordinate
184
                    do {
185
                        eventLog->progress();
186

    
187
                        Assert(currentEvent);
188
                        previousEvent = currentEvent;
189
                        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
190
                        Assert(currentEvent);
191

    
192
                        simtime_t previousSimulationTime = previousEvent->getSimulationTime();
193
                        double previousTimelineCoordinate = previousEvent->cachedTimelineCoordinate;
194
                        simtime_t simulationTime = currentEvent->getSimulationTime();
195
                        double timelineCoordinateDelta = getTimelineCoordinateDelta((simulationTime - previousSimulationTime).dbl());
196

    
197
                        if (forward) {
198
                            timelineCoordinate = previousTimelineCoordinate + timelineCoordinateDelta;
199

    
200
                            if (timelineCoordinate > upperTimelineCoordinateCalculationLimit)
201
                                return NaN;
202
                        }
203
                        else {
204
                            timelineCoordinate = previousTimelineCoordinate - timelineCoordinateDelta;
205

    
206
                            if (timelineCoordinate < lowerTimelineCoordinateCalculationLimit)
207
                                return NaN;
208
                        }
209

    
210
                        currentEvent->cachedTimelineCoordinate = timelineCoordinate;
211
                        currentEvent->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
212
                    }
213
                    while (currentEvent != event);
214

    
215
                    if (forward)
216
                        timelineCoordinateRangeEndEventNumber = event->getEventNumber();
217
                    else
218
                        timelineCoordinateRangeStartEventNumber = event->getEventNumber();
219
                }
220
                break;
221
            default:
222
                throw opp_runtime_error("Unknown timeline mode");
223
        }
224

    
225
        event->cachedTimelineCoordinate = timelineCoordinate;
226
        event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
227
    }
228

    
229
    return event->cachedTimelineCoordinate;
230
}
231

    
232
double SequenceChartFacade::getTimelineEventEndCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
233
{
234
    Assert(event);
235
    Assert(event->getEventLog() == eventLog);
236
    if(!eventLog->isLegacyTrace()) {
237
        return getTimelineCoordinate(event);
238
    }
239
        double timelineEventEndCoordinate;
240
        switch (timelineMode) {
241
            case SIMULATION_TIME:
242
                timelineEventEndCoordinate = (event->getSimulationTime()+event->getEventEntry()->duration - timelineCoordinateOriginSimulationTime).dbl();
243
                break;
244
            default:
245
                return getTimelineCoordinate(event);
246
        }
247
    return timelineEventEndCoordinate;
248
}
249

    
250
double SequenceChartFacade::getCachedTimelineCoordinate(IEvent *event)
251
{
252
    Assert(event);
253
    Assert(timelineCoordinateSystemVersion != -1);
254
    Assert(timelineCoordinateOriginEventNumber != -1);
255

    
256
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion)
257
        return -1;
258
    else
259
        return event->cachedTimelineCoordinate;
260
}
261

    
262
IEvent *SequenceChartFacade::getEventForNonLinearTimelineCoordinate(double timelineCoordinate, bool &forward)
263
{
264
    Assert(timelineCoordinateOriginEventNumber != -1);
265
    IEvent *timelineCoordinateRangeStartEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeStartEventNumber);
266
    IEvent *timelineCoordinateRangeEndEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeEndEventNumber);
267
    IEvent *currentEvent;
268

    
269
    Assert(timelineCoordinateRangeStartEvent && timelineCoordinateRangeEndEvent);
270

    
271
    if (timelineCoordinate <= getTimelineCoordinate(timelineCoordinateRangeStartEvent)) {
272
        forward = false;
273
        currentEvent = timelineCoordinateRangeStartEvent;
274
    }
275
    else if (getTimelineCoordinate(timelineCoordinateRangeEndEvent) <= timelineCoordinate) {
276
        forward = true;
277
        currentEvent = timelineCoordinateRangeEndEvent;
278
    }
279
    else {
280
        forward = true;
281
        currentEvent = timelineCoordinateRangeStartEvent;
282
    }
283

    
284
    // TODO: LONG RUNNING OPERATION
285
    // does a linear search towards requested non linear timeline coordinate
286
    while (currentEvent && (forward ? getTimelineCoordinate(currentEvent) < timelineCoordinate :
287
                                      timelineCoordinate <= getTimelineCoordinate(currentEvent)))
288
    {
289
        eventLog->progress();
290
        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
291
    }
292

    
293
    return currentEvent;
294
}
295

    
296
IEvent *SequenceChartFacade::getLastEventNotAfterTimelineCoordinate(double timelineCoordinate)
297
{
298
    if (eventLog->isEmpty())
299
        return NULL;
300

    
301
    switch (timelineMode) {
302
        case SIMULATION_TIME:
303
            return eventLog->getLastEventNotAfterSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
304
        case EVENT_NUMBER:
305
            {
306
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
307

    
308
                if (eventNumber < 0)
309
                    return NULL;
310
                else
311
                    return eventLog->getLastEventNotAfterEventNumber(eventNumber);
312
            }
313
        case STEP:
314
        case NONLINEAR:
315
            {
316
                bool forward;
317
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
318
                currentEvent = forward ? (currentEvent ? currentEvent->getPreviousEvent() : eventLog->getLastEvent()) : currentEvent;
319

    
320
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) <= timelineCoordinate);
321
                return currentEvent;
322
            }
323
        default:
324
            throw opp_runtime_error("Unknown timeline mode");
325
    }
326
}
327

    
328
IEvent *SequenceChartFacade::getFirstEventNotBeforeTimelineCoordinate(double timelineCoordinate)
329
{
330
    if (eventLog->isEmpty())
331
        return NULL;
332

    
333
    switch (timelineMode) {
334
        case SIMULATION_TIME:
335
            return eventLog->getFirstEventNotBeforeSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
336
        case EVENT_NUMBER:
337
            {
338
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
339

    
340
                if (eventNumber < 0)
341
                    return eventLog->getFirstEvent();
342
                else
343
                    return eventLog->getFirstEventNotBeforeEventNumber(eventNumber);
344
            }
345
        case STEP:
346
        case NONLINEAR:
347
            {
348
                bool forward;
349
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
350
                currentEvent = forward ? currentEvent : (currentEvent ? currentEvent->getNextEvent() : eventLog->getFirstEvent());
351

    
352
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) >= timelineCoordinate);
353
                return currentEvent;
354
            }
355
        default:
356
            throw opp_runtime_error("Unknown timeline mode");
357
    }
358
}
359

    
360
void SequenceChartFacade::extractSimulationTimesAndTimelineCoordinates(
361
    IEvent *event, IEvent *&nextEvent,
362
    simtime_t &eventSimulationTime, double &eventTimelineCoordinate,
363
    simtime_t &nextEventSimulationTime, double &nextEventTimelineCoordinate,
364
    simtime_t &simulationTimeDelta, double &timelineCoordinateDelta)
365
{
366
    // if before the first event
367
    if (event) {
368
        eventSimulationTime = event->getSimulationTime();
369
        eventTimelineCoordinate = getTimelineCoordinate(event);
370
    }
371
    else {
372
        eventSimulationTime = BigDecimal::Zero;
373
        IEvent *firstEvent = eventLog->getFirstEvent();
374
        eventTimelineCoordinate = getTimelineCoordinate(firstEvent);
375

    
376
        if (timelineMode == EVENT_NUMBER)
377
            eventTimelineCoordinate -= 1;
378
        else
379
            eventTimelineCoordinate -= getTimelineCoordinateDelta(firstEvent->getSimulationTime().dbl());
380
    }
381

    
382
    // linear approximation between two enclosing events
383
    nextEvent = event ? event->getNextEvent() : eventLog->getFirstEvent();
384

    
385
    if (nextEvent) {
386
        nextEventSimulationTime = nextEvent->getSimulationTime();
387
        nextEventTimelineCoordinate = getTimelineCoordinate(nextEvent);
388

    
389
        simulationTimeDelta = nextEventSimulationTime - eventSimulationTime;
390
        timelineCoordinateDelta = nextEventTimelineCoordinate - eventTimelineCoordinate;
391
    }
392
}
393

    
394
simtime_t SequenceChartFacade::getSimulationTimeForTimelineCoordinate(double timelineCoordinate, bool upperLimit)
395
{
396
    Assert(!isNaN(timelineCoordinate));
397

    
398
    if (eventLog->isEmpty())
399
        return BigDecimal::Zero;
400

    
401
    simtime_t simulationTime;
402

    
403
    switch (timelineMode)
404
    {
405
        case SIMULATION_TIME:
406
            {
407
                simtime_t lastEventSimulationTime = eventLog->getLastEvent()->getSimulationTime();
408
                simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, timelineCoordinate + timelineCoordinateOriginSimulationTime));
409
            }
410
            break;
411
        case EVENT_NUMBER:
412
        case STEP:
413
        case NONLINEAR:
414
            {
415
                IEvent *nextEvent;
416
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
417
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
418

    
419
                IEvent *event = getLastEventNotAfterTimelineCoordinate(timelineCoordinate);
420
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
421
                                                             eventSimulationTime, eventTimelineCoordinate,
422
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
423
                                                             simulationTimeDelta, timelineCoordinateDelta);
424

    
425
                if (nextEvent) {
426
                    if (timelineCoordinateDelta == 0) {
427
                        // IMPORTANT NOTE: this is just an approximation
428
                        if (upperLimit)
429
                            simulationTime = nextEventSimulationTime;
430
                        else
431
                            simulationTime = eventSimulationTime;
432
                    }
433
                    else {
434
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
435
                        simulationTime = eventSimulationTime + simulationTimeDelta * (timelineCoordinate - eventTimelineCoordinate) / timelineCoordinateDelta;
436
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
437
                    }
438
                }
439
                else
440
                    simulationTime = eventSimulationTime;
441
            }
442
            break;
443
        default:
444
            throw opp_runtime_error("Unknown timeline mode");
445
    }
446

    
447
    Assert(!simulationTime.isNaN());
448
    Assert(simulationTime >= BigDecimal::Zero);
449
    Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
450

    
451
    return simulationTime;
452
}
453

    
454
double SequenceChartFacade::getTimelineCoordinateForSimulationTime(simtime_t simulationTime, bool upperLimit)
455
{
456
    Assert(!simulationTime.isNaN());
457

    
458
    if (eventLog->isEmpty())
459
        return 0;
460

    
461
    Assert(simulationTime >= BigDecimal::Zero);
462
    Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
463

    
464
    double timelineCoordinate;
465

    
466
    switch (timelineMode)
467
    {
468
        case SIMULATION_TIME:
469
            timelineCoordinate = (simulationTime - timelineCoordinateOriginSimulationTime).dbl();
470
            break;
471
        case EVENT_NUMBER:
472
        case STEP:
473
        case NONLINEAR:
474
            {
475
                IEvent *nextEvent;
476
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
477
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
478

    
479
                IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
480
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
481
                                                             eventSimulationTime, eventTimelineCoordinate,
482
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
483
                                                             simulationTimeDelta, timelineCoordinateDelta);
484

    
485
                if (nextEvent) {
486
                    if (simulationTimeDelta == BigDecimal::Zero) {
487
                        // IMPORTANT NOTE: this is just an approximation
488
                        if (upperLimit)
489
                            timelineCoordinate = nextEventTimelineCoordinate;
490
                        else
491
                            timelineCoordinate = eventTimelineCoordinate;
492
                    }
493
                    else {
494
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
495
                        timelineCoordinate = eventTimelineCoordinate + timelineCoordinateDelta * (simulationTime - eventSimulationTime).dbl() / simulationTimeDelta.dbl();
496
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
497
                    }
498
                }
499
                else
500
                    timelineCoordinate = eventTimelineCoordinate;
501
            }
502
            break;
503
        default:
504
            throw opp_runtime_error("Unknown timeline mode");
505
    }
506

    
507
    Assert(!isNaN(timelineCoordinate));
508

    
509
    return timelineCoordinate;
510
}
511

    
512
double SequenceChartFacade::getTimelineCoordinateForSimulationTimeAndEventInModule(simtime_t simulationTime, int moduleId)
513
{
514
    IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
515

    
516
    while (event && event->getSimulationTime() == simulationTime) {
517
        if (event->getModuleId() == moduleId)
518
            return getTimelineCoordinate(event);
519

    
520
        event = event->getNextEvent();
521
    }
522

    
523
    return getTimelineCoordinateForSimulationTime(simulationTime);
524
}
525

    
526
std::vector<ptr_t> *SequenceChartFacade::getModuleMethodBeginEntries(ptr_t startEventPtr, ptr_t endEventPtr)
527
{
528
    IEvent *startEvent = (IEvent *)startEventPtr;
529
    IEvent *endEvent = (IEvent *)endEventPtr;
530
    Assert(startEvent);
531
    Assert(endEvent);
532
    std::vector<ptr_t> *moduleMethodBeginEntries = new std::vector<ptr_t>();
533

    
534
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
535
        eventLog->progress();
536

    
537
        for (int i = 0; i < event->getNumEventLogEntries(); i++) {
538
            EventLogEntry *eventLogEntry = event->getEventLogEntry(i);
539

    
540
            if (dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry))
541
                moduleMethodBeginEntries->push_back((ptr_t)eventLogEntry);
542
        }
543

    
544
        if (event == endEvent)
545
            break;
546
    }
547

    
548
    return moduleMethodBeginEntries;
549
}
550

    
551
std::vector<ptr_t> *SequenceChartFacade::getIntersectingMessageDependencies(ptr_t startEventPtr, ptr_t endEventPtr)
552
{
553
    IEvent *startEvent = (IEvent *)startEventPtr;
554
    IEvent *endEvent = (IEvent *)endEventPtr;
555
    Assert(startEvent);
556
    Assert(endEvent);
557
    std::set<ptr_t> messageDependencies;
558
    eventnumber_t startEventNumber = startEvent->getEventNumber();
559

    
560
    // TODO: LONG RUNNING OPERATION
561
    // this might take a while if start and end events are far away from each other
562
    // if not completed then some dependencies will not be included
563
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
564
        eventLog->progress();
565
        IMessageDependencyList *causes = event->getCauses();
566

    
567
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
568
            IMessageDependency *messageDependency = *it;
569

    
570
            if (messageDependency->getCauseEventNumber() < startEventNumber)
571
                messageDependencies.insert((ptr_t)messageDependency);
572
        }
573

    
574
        IMessageDependencyList *consequences = event->getConsequences();
575

    
576
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
577
            messageDependencies.insert((ptr_t)*it);
578

    
579
        if (event == endEvent)
580
            break;
581
    }
582

    
583
    std::vector<ptr_t> *result = new std::vector<ptr_t>;
584
    result->resize(messageDependencies.size());
585
    std::copy(messageDependencies.begin(), messageDependencies.end(), result->begin());
586

    
587
    return result;
588
}
589

    
590
std::vector<int> SequenceChartFacade::getApproximateMessageDependencyCountAdjacencyMatrix(std::map<int, int> *moduleIdToAxisIndexMap, int numberOfSamples, int messageSendWeight, int messageReuseWeight)
591
{
592
    LCGRandom lcgRandom;
593
    std::vector<int> adjacencyMatrix;
594
    std::set<int> axisIndexSet;
595
    std::map<eventnumber_t, IEvent *> eventNumberToEventMap;
596

    
597
    for (std::map<int, int>::iterator it = moduleIdToAxisIndexMap->begin(); it != moduleIdToAxisIndexMap->end(); it++)
598
        axisIndexSet.insert(it->second);
599

    
600
    int numberOfAxes = axisIndexSet.size();
601
    adjacencyMatrix.resize(numberOfAxes * numberOfAxes);
602

    
603
    for (int i = 0; i < numberOfSamples; i++)
604
    {
605
        // draw random
606
        double percentage = lcgRandom.next01();
607
        IEvent *event = eventLog->getApproximateEventAt(percentage);
608
        eventNumberToEventMap[event->getEventNumber()] = event;
609

    
610
        // look before origin
611
        if (timelineCoordinateOriginEventNumber != -1) {
612
            if (timelineCoordinateOriginEventNumber - i >= 0) {
613
                event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber - i);
614
                if (event)
615
                    eventNumberToEventMap[event->getEventNumber()] = event;
616
            }
617

    
618
            // look after origin
619
            event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber + i);
620
            if (event)
621
                eventNumberToEventMap[event->getEventNumber()] = event;
622
        }
623
    }
624

    
625
    for (std::map<eventnumber_t, IEvent *>::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++) {
626
        IEvent *event = it->second;
627
        IMessageDependencyList *causes = event->getCauses();
628

    
629
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
630
            IMessageDependency *messageDependency = *it;
631
            IEvent *causeEvent = messageDependency->getCauseEvent();
632
            IEvent *consequenceEvent = messageDependency->getConsequenceEvent();
633
            int weight = messageDependency->getIsReuse() ? messageReuseWeight : messageSendWeight;
634

    
635
            if (causeEvent && consequenceEvent && weight != 0) {
636
                int causeModuleId = causeEvent->getModuleId();
637
                int consequenceModuleId = consequenceEvent->getModuleId();
638

    
639
                std::map<int, int>::iterator causeModuleIdIt = moduleIdToAxisIndexMap->find(causeModuleId);
640
                std::map<int, int>::iterator consequenceModuleIdIt = moduleIdToAxisIndexMap->find(consequenceModuleId);
641

    
642
                if (causeModuleIdIt !=  moduleIdToAxisIndexMap->end() && consequenceModuleIdIt != moduleIdToAxisIndexMap->end())
643
                    adjacencyMatrix.at(causeModuleIdIt->second * numberOfAxes + consequenceModuleIdIt->second) += weight;
644
            }
645
        }
646
    }
647

    
648
    return adjacencyMatrix;
649
}
650

    
651

    
652
long SequenceChartFacade::getSmallestEventComplexity() {
653
    long complexity = 0;
654
    if (smallestComplexity < 0) {
655
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
656
             if (event->getEventEndEntry()) {
657
                 complexity = event->getEventEndEntry()->complexity;
658
             } else {
659
                 continue;
660
             }
661
             if (complexity < smallestComplexity || smallestComplexity < 0) {
662
                 smallestComplexity = complexity;
663
             }
664
             if (complexity > largestComplexity || largestComplexity < 0) {
665
                 largestComplexity = complexity;
666
             }
667
        }
668
    }
669
    if (smallestComplexity < 0) {
670
        smallestComplexity = 0;
671
    }
672
    return smallestComplexity;
673
}
674

    
675
long SequenceChartFacade::getLargestEventComplexity() {
676
    if (largestComplexity < 0) {
677
        getSmallestEventComplexity();
678
    }
679
    if (largestComplexity < 0) {
680
        largestComplexity = 0;
681
    }
682
    return largestComplexity;
683
}
684

    
685
simtime_t SequenceChartFacade::getSmallestEventDuration() {
686
    simtime_t duration = 0;
687
    if (smallestDuration < 0) {
688
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
689
             if (event->getEventEntry()) {
690
                 duration = event->getEventEntry()->duration;
691
             } else {
692
                 continue;
693
             }
694
             if (duration < smallestDuration || smallestDuration < 0) {
695
                 smallestDuration = duration;
696
             }
697
             if (duration > largestDuration || largestDuration < 0) {
698
                 largestDuration = duration;
699
             }
700
        }
701
    }
702
    if (smallestDuration < 0) {
703
        smallestDuration = 0;
704
    }
705
    return smallestDuration;
706
}
707

    
708
simtime_t SequenceChartFacade::getLargestEventDuration() {
709
    if (largestDuration < 0) {
710
        getSmallestEventComplexity();
711
    }
712
    if (largestDuration < 0) {
713
        largestDuration = 0;
714
    }
715
    return largestDuration;
716
}
717

    
718

    
719
IEvent* SequenceChartFacade::getPreviousBottleneck(IEvent* e, unsigned int threshold) {
720
    IEvent* next = e->getPreviousEvent();
721
    while (next) {
722
        if (isBottleneck(next,threshold)) {
723
            return next;
724
        }
725
        next = next->getPreviousEvent();
726
    }
727
    return e;
728
}
729

    
730
IEvent* SequenceChartFacade::getNextBottleneck(IEvent* e, unsigned int threshold) {
731
    IEvent* next = e->getNextEvent();
732
    while (next) {
733
        if (isBottleneck(next,threshold)) {
734
            return next;
735
        }
736
        next = next->getNextEvent();
737
    }
738
    return e;
739
}
740

    
741
/*
742
 * Returns whether an event not part of a set of parallel events with more than treshold elements.
743
 */
744
bool SequenceChartFacade::isBottleneck(IEvent* event, unsigned int threshold)
745
{
746
    return getLargestParallelSetSize(event) <= threshold;
747
}
748

    
749
unsigned int SequenceChartFacade::getLargestParallelSetSize(IEvent* event)
750
{
751
    IEvent* prev = event;
752
    std::set<ptr_t> parallelSet;
753
    parallelSet.clear();
754
    unsigned int previousSize = 0;
755
    while (prev)
756
    {
757
        previousSize = parallelSet.size();
758

    
759
        getParallelSet(prev, &parallelSet);
760

    
761
        if (parallelSet.find((ptr_t) event) == parallelSet.end())
762
        {
763
            break;
764
        }
765
        prev = prev->getPreviousEvent();
766
    }
767
    return previousSize;
768
}
769

    
770
void SequenceChartFacade::getParallelSet(IEvent* event,
771
        std::set<ptr_t>* parallelSet)
772
{
773
    IEvent* next = event->getNextEvent();
774
    simtime_t smallestParallelEndtime = getSmallestParallelEndtime(event);
775
    parallelSet->clear();
776
    parallelSet->insert((ptr_t) event);
777
    while (next)
778
    {
779
        if ((next->getSimulationTime() >= event->getSimulationTime())
780
                && (smallestParallelEndtime >= next->getSimulationTime()))
781
        {
782
            parallelSet->insert((ptr_t) next);
783
        }
784
        else
785
        {
786
            break;
787
        }
788
        next = next->getNextEvent();
789
    }
790
}
791

    
792
simtime_t SequenceChartFacade::getSmallestParallelEndtime(IEvent* event)
793
{
794
    simtime_t minimum = event->getSimulationTime()
795
            + event->getEventEntry()->duration;
796
    for (IEvent *current = eventLog->getFirstEvent(); current; current
797
            = current->getNextEvent())
798
    {
799
        if (current->getSimulationTime() >= event->getSimulationTime())
800
        {
801
            if ((current->getSimulationTime()
802
                    + current->getEventEntry()->duration)
803
                    > event->getSimulationTime())
804
            {
805
                if (minimum > (current->getSimulationTime()
806
                        + current->getEventEntry()->duration))
807
                {
808
                    minimum = current->getSimulationTime()
809
                            + current->getEventEntry()->duration;
810
                }
811
            }
812
            if (current->getSimulationTime() > minimum)
813
            { // After this, no overlapping can follow
814
                break;
815
            }
816
        }
817
    }
818
    return minimum;
819
}