Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ ced95c57

History | View | Annotate | Download (29.5 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::getTimelineCoordinateDelta(double simulationTimeDelta)
128
{
129
    Assert(nonLinearFocus > 0);
130

    
131
    if (timelineMode == STEP)
132
        return 1;
133
    else
134
        return nonLinearMinimumTimelineCoordinateDelta + (1 - nonLinearMinimumTimelineCoordinateDelta) * atan(fabs(simulationTimeDelta) / nonLinearFocus) / PI * 2;
135
}
136

    
137
double SequenceChartFacade::getTimelineCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
138
{
139
    IEVENT_PTR(ptr);
140
    return getTimelineCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
141
}
142

    
143
double SequenceChartFacade::getTimelineCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
144
{
145
    Assert(event);
146
    Assert(event->getEventLog() == eventLog);
147
    Assert(timelineCoordinateSystemVersion != -1);
148
    Assert(timelineCoordinateOriginEventNumber != -1);
149

    
150
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion) {
151
        double timelineCoordinate;
152

    
153
        switch (timelineMode) {
154
            case SIMULATION_TIME:
155
                timelineCoordinate = (event->getSimulationTime() - timelineCoordinateOriginSimulationTime).dbl();
156
                break;
157
            case EVENT_NUMBER:
158
                timelineCoordinate = event->getEventNumber() - timelineCoordinateOriginEventNumber;
159
                break;
160
            case STEP:
161
            case NONLINEAR:
162
                {
163
                    IEvent *previousEvent = NULL;
164
                    // do we go forward from end or backward from start of known range
165
                    bool forward = event->getEventNumber() > timelineCoordinateRangeEndEventNumber;
166
                    IEvent *currentEvent = eventLog->getEventForEventNumber(forward ? timelineCoordinateRangeEndEventNumber : timelineCoordinateRangeStartEventNumber);
167

    
168
                    Assert(event->getEventNumber() < timelineCoordinateRangeStartEventNumber || timelineCoordinateRangeEndEventNumber < event->getEventNumber());
169

    
170
                    // TODO: LONG RUNNING OPERATION
171
                    // does a linear search towards the event to calculate the non linear timeline coordinate
172
                    do {
173
                        eventLog->progress();
174

    
175
                        Assert(currentEvent);
176
                        previousEvent = currentEvent;
177
                        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
178
                        Assert(currentEvent);
179

    
180
                        simtime_t previousSimulationTime = previousEvent->getSimulationTime();
181
                        double previousTimelineCoordinate = previousEvent->cachedTimelineCoordinate;
182
                        simtime_t simulationTime = currentEvent->getSimulationTime();
183
                        double timelineCoordinateDelta = getTimelineCoordinateDelta((simulationTime - previousSimulationTime).dbl());
184

    
185
                        if (forward) {
186
                            timelineCoordinate = previousTimelineCoordinate + timelineCoordinateDelta;
187

    
188
                            if (timelineCoordinate > upperTimelineCoordinateCalculationLimit)
189
                                return NaN;
190
                        }
191
                        else {
192
                            timelineCoordinate = previousTimelineCoordinate - timelineCoordinateDelta;
193

    
194
                            if (timelineCoordinate < lowerTimelineCoordinateCalculationLimit)
195
                                return NaN;
196
                        }
197

    
198
                        currentEvent->cachedTimelineCoordinate = timelineCoordinate;
199
                        currentEvent->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
200
                    }
201
                    while (currentEvent != event);
202

    
203
                    if (forward)
204
                        timelineCoordinateRangeEndEventNumber = event->getEventNumber();
205
                    else
206
                        timelineCoordinateRangeStartEventNumber = event->getEventNumber();
207
                }
208
                break;
209
            default:
210
                throw opp_runtime_error("Unknown timeline mode");
211
        }
212

    
213
        event->cachedTimelineCoordinate = timelineCoordinate;
214
        event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
215
    }
216

    
217
    return event->cachedTimelineCoordinate;
218
}
219

    
220
double SequenceChartFacade::getCachedTimelineCoordinate(IEvent *event)
221
{
222
    Assert(event);
223
    Assert(timelineCoordinateSystemVersion != -1);
224
    Assert(timelineCoordinateOriginEventNumber != -1);
225

    
226
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion)
227
        return -1;
228
    else
229
        return event->cachedTimelineCoordinate;
230
}
231

    
232
IEvent *SequenceChartFacade::getEventForNonLinearTimelineCoordinate(double timelineCoordinate, bool &forward)
233
{
234
    Assert(timelineCoordinateOriginEventNumber != -1);
235
    IEvent *timelineCoordinateRangeStartEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeStartEventNumber);
236
    IEvent *timelineCoordinateRangeEndEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeEndEventNumber);
237
    IEvent *currentEvent;
238

    
239
    Assert(timelineCoordinateRangeStartEvent && timelineCoordinateRangeEndEvent);
240

    
241
    if (timelineCoordinate <= getTimelineCoordinate(timelineCoordinateRangeStartEvent)) {
242
        forward = false;
243
        currentEvent = timelineCoordinateRangeStartEvent;
244
    }
245
    else if (getTimelineCoordinate(timelineCoordinateRangeEndEvent) <= timelineCoordinate) {
246
        forward = true;
247
        currentEvent = timelineCoordinateRangeEndEvent;
248
    }
249
    else {
250
        forward = true;
251
        currentEvent = timelineCoordinateRangeStartEvent;
252
    }
253

    
254
    // TODO: LONG RUNNING OPERATION
255
    // does a linear search towards requested non linear timeline coordinate
256
    while (currentEvent && (forward ? getTimelineCoordinate(currentEvent) < timelineCoordinate :
257
                                      timelineCoordinate <= getTimelineCoordinate(currentEvent)))
258
    {
259
        eventLog->progress();
260
        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
261
    }
262

    
263
    return currentEvent;
264
}
265

    
266
IEvent *SequenceChartFacade::getLastEventNotAfterTimelineCoordinate(double timelineCoordinate)
267
{
268
    if (eventLog->isEmpty())
269
        return NULL;
270

    
271
    switch (timelineMode) {
272
        case SIMULATION_TIME:
273
            return eventLog->getLastEventNotAfterSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
274
        case EVENT_NUMBER:
275
            {
276
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
277

    
278
                if (eventNumber < 0)
279
                    return NULL;
280
                else
281
                    return eventLog->getLastEventNotAfterEventNumber(eventNumber);
282
            }
283
        case STEP:
284
        case NONLINEAR:
285
            {
286
                bool forward;
287
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
288
                currentEvent = forward ? (currentEvent ? currentEvent->getPreviousEvent() : eventLog->getLastEvent()) : currentEvent;
289

    
290
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) <= timelineCoordinate);
291
                return currentEvent;
292
            }
293
        default:
294
            throw opp_runtime_error("Unknown timeline mode");
295
    }
296
}
297

    
298
IEvent *SequenceChartFacade::getFirstEventNotBeforeTimelineCoordinate(double timelineCoordinate)
299
{
300
    if (eventLog->isEmpty())
301
        return NULL;
302

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

    
310
                if (eventNumber < 0)
311
                    return eventLog->getFirstEvent();
312
                else
313
                    return eventLog->getFirstEventNotBeforeEventNumber(eventNumber);
314
            }
315
        case STEP:
316
        case NONLINEAR:
317
            {
318
                bool forward;
319
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
320
                currentEvent = forward ? currentEvent : (currentEvent ? currentEvent->getNextEvent() : eventLog->getFirstEvent());
321

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

    
330
void SequenceChartFacade::extractSimulationTimesAndTimelineCoordinates(
331
    IEvent *event, IEvent *&nextEvent,
332
    simtime_t &eventSimulationTime, double &eventTimelineCoordinate,
333
    simtime_t &nextEventSimulationTime, double &nextEventTimelineCoordinate,
334
    simtime_t &simulationTimeDelta, double &timelineCoordinateDelta)
335
{
336
    // if before the first event
337
    if (event) {
338
        eventSimulationTime = event->getSimulationTime();
339
        eventTimelineCoordinate = getTimelineCoordinate(event);
340
    }
341
    else {
342
        eventSimulationTime = BigDecimal::Zero;
343
        IEvent *firstEvent = eventLog->getFirstEvent();
344
        eventTimelineCoordinate = getTimelineCoordinate(firstEvent);
345

    
346
        if (timelineMode == EVENT_NUMBER)
347
            eventTimelineCoordinate -= 1;
348
        else
349
            eventTimelineCoordinate -= getTimelineCoordinateDelta(firstEvent->getSimulationTime().dbl());
350
    }
351

    
352
    // linear approximation between two enclosing events
353
    nextEvent = event ? event->getNextEvent() : eventLog->getFirstEvent();
354

    
355
    if (nextEvent) {
356
        nextEventSimulationTime = nextEvent->getSimulationTime();
357
        nextEventTimelineCoordinate = getTimelineCoordinate(nextEvent);
358

    
359
        simulationTimeDelta = nextEventSimulationTime - eventSimulationTime;
360
        timelineCoordinateDelta = nextEventTimelineCoordinate - eventTimelineCoordinate;
361
    }
362
}
363

    
364
simtime_t SequenceChartFacade::getSimulationTimeForTimelineCoordinate(double timelineCoordinate, bool upperLimit)
365
{
366
    Assert(!isNaN(timelineCoordinate));
367

    
368
    if (eventLog->isEmpty())
369
        return BigDecimal::Zero;
370

    
371
    simtime_t simulationTime;
372

    
373
    switch (timelineMode)
374
    {
375
        case SIMULATION_TIME:
376
            {
377
                simtime_t lastEventSimulationTime = eventLog->getLastEvent()->getSimulationTime();
378
                simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, timelineCoordinate + timelineCoordinateOriginSimulationTime));
379
            }
380
            break;
381
        case EVENT_NUMBER:
382
        case STEP:
383
        case NONLINEAR:
384
            {
385
                IEvent *nextEvent;
386
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
387
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
388

    
389
                IEvent *event = getLastEventNotAfterTimelineCoordinate(timelineCoordinate);
390
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
391
                                                             eventSimulationTime, eventTimelineCoordinate,
392
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
393
                                                             simulationTimeDelta, timelineCoordinateDelta);
394

    
395
                if (nextEvent) {
396
                    if (timelineCoordinateDelta == 0) {
397
                        // IMPORTANT NOTE: this is just an approximation
398
                        if (upperLimit)
399
                            simulationTime = nextEventSimulationTime;
400
                        else
401
                            simulationTime = eventSimulationTime;
402
                    }
403
                    else {
404
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
405
                        simulationTime = eventSimulationTime + simulationTimeDelta * (timelineCoordinate - eventTimelineCoordinate) / timelineCoordinateDelta;
406
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
407
                    }
408
                }
409
                else
410
                    simulationTime = eventSimulationTime;
411
            }
412
            break;
413
        default:
414
            throw opp_runtime_error("Unknown timeline mode");
415
    }
416

    
417
    Assert(!simulationTime.isNaN());
418
    Assert(simulationTime >= BigDecimal::Zero);
419
    Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
420

    
421
    return simulationTime;
422
}
423

    
424
double SequenceChartFacade::getTimelineCoordinateForSimulationTime(simtime_t simulationTime, bool upperLimit)
425
{
426
    Assert(!simulationTime.isNaN());
427

    
428
    if (eventLog->isEmpty())
429
        return 0;
430

    
431
    Assert(simulationTime >= BigDecimal::Zero);
432
    Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
433

    
434
    double timelineCoordinate;
435

    
436
    switch (timelineMode)
437
    {
438
        case SIMULATION_TIME:
439
            timelineCoordinate = (simulationTime - timelineCoordinateOriginSimulationTime).dbl();
440
            break;
441
        case EVENT_NUMBER:
442
        case STEP:
443
        case NONLINEAR:
444
            {
445
                IEvent *nextEvent;
446
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
447
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
448

    
449
                IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
450
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
451
                                                             eventSimulationTime, eventTimelineCoordinate,
452
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
453
                                                             simulationTimeDelta, timelineCoordinateDelta);
454

    
455
                if (nextEvent) {
456
                    if (simulationTimeDelta == BigDecimal::Zero) {
457
                        // IMPORTANT NOTE: this is just an approximation
458
                        if (upperLimit)
459
                            timelineCoordinate = nextEventTimelineCoordinate;
460
                        else
461
                            timelineCoordinate = eventTimelineCoordinate;
462
                    }
463
                    else {
464
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
465
                        timelineCoordinate = eventTimelineCoordinate + timelineCoordinateDelta * (simulationTime - eventSimulationTime).dbl() / simulationTimeDelta.dbl();
466
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
467
                    }
468
                }
469
                else
470
                    timelineCoordinate = eventTimelineCoordinate;
471
            }
472
            break;
473
        default:
474
            throw opp_runtime_error("Unknown timeline mode");
475
    }
476

    
477
    Assert(!isNaN(timelineCoordinate));
478

    
479
    return timelineCoordinate;
480
}
481

    
482
double SequenceChartFacade::getTimelineCoordinateForSimulationTimeAndEventInModule(simtime_t simulationTime, int moduleId)
483
{
484
    IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
485

    
486
    while (event && event->getSimulationTime() == simulationTime) {
487
        if (event->getModuleId() == moduleId)
488
            return getTimelineCoordinate(event);
489

    
490
        event = event->getNextEvent();
491
    }
492

    
493
    return getTimelineCoordinateForSimulationTime(simulationTime);
494
}
495

    
496
std::vector<ptr_t> *SequenceChartFacade::getModuleMethodBeginEntries(ptr_t startEventPtr, ptr_t endEventPtr)
497
{
498
    IEvent *startEvent = (IEvent *)startEventPtr;
499
    IEvent *endEvent = (IEvent *)endEventPtr;
500
    Assert(startEvent);
501
    Assert(endEvent);
502
    std::vector<ptr_t> *moduleMethodBeginEntries = new std::vector<ptr_t>();
503

    
504
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
505
        eventLog->progress();
506

    
507
        for (int i = 0; i < event->getNumEventLogEntries(); i++) {
508
            EventLogEntry *eventLogEntry = event->getEventLogEntry(i);
509

    
510
            if (dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry))
511
                moduleMethodBeginEntries->push_back((ptr_t)eventLogEntry);
512
        }
513

    
514
        if (event == endEvent)
515
            break;
516
    }
517

    
518
    return moduleMethodBeginEntries;
519
}
520

    
521
std::vector<ptr_t> *SequenceChartFacade::getIntersectingMessageDependencies(ptr_t startEventPtr, ptr_t endEventPtr)
522
{
523
    IEvent *startEvent = (IEvent *)startEventPtr;
524
    IEvent *endEvent = (IEvent *)endEventPtr;
525
    Assert(startEvent);
526
    Assert(endEvent);
527
    std::set<ptr_t> messageDependencies;
528
    eventnumber_t startEventNumber = startEvent->getEventNumber();
529

    
530
    // TODO: LONG RUNNING OPERATION
531
    // this might take a while if start and end events are far away from each other
532
    // if not completed then some dependencies will not be included
533
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
534
        eventLog->progress();
535
        IMessageDependencyList *causes = event->getCauses();
536

    
537
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
538
            IMessageDependency *messageDependency = *it;
539

    
540
            if (messageDependency->getCauseEventNumber() < startEventNumber)
541
                messageDependencies.insert((ptr_t)messageDependency);
542
        }
543

    
544
        IMessageDependencyList *consequences = event->getConsequences();
545

    
546
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
547
            messageDependencies.insert((ptr_t)*it);
548

    
549
        if (event == endEvent)
550
            break;
551
    }
552

    
553
    std::vector<ptr_t> *result = new std::vector<ptr_t>;
554
    result->resize(messageDependencies.size());
555
    std::copy(messageDependencies.begin(), messageDependencies.end(), result->begin());
556

    
557
    return result;
558
}
559

    
560
std::vector<int> SequenceChartFacade::getApproximateMessageDependencyCountAdjacencyMatrix(std::map<int, int> *moduleIdToAxisIndexMap, int numberOfSamples, int messageSendWeight, int messageReuseWeight)
561
{
562
    LCGRandom lcgRandom;
563
    std::vector<int> adjacencyMatrix;
564
    std::set<int> axisIndexSet;
565
    std::map<eventnumber_t, IEvent *> eventNumberToEventMap;
566

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

    
570
    int numberOfAxes = axisIndexSet.size();
571
    adjacencyMatrix.resize(numberOfAxes * numberOfAxes);
572

    
573
    for (int i = 0; i < numberOfSamples; i++)
574
    {
575
        // draw random
576
        double percentage = lcgRandom.next01();
577
        IEvent *event = eventLog->getApproximateEventAt(percentage);
578
        eventNumberToEventMap[event->getEventNumber()] = event;
579

    
580
        // look before origin
581
        if (timelineCoordinateOriginEventNumber != -1) {
582
            if (timelineCoordinateOriginEventNumber - i >= 0) {
583
                event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber - i);
584
                if (event)
585
                    eventNumberToEventMap[event->getEventNumber()] = event;
586
            }
587

    
588
            // look after origin
589
            event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber + i);
590
            if (event)
591
                eventNumberToEventMap[event->getEventNumber()] = event;
592
        }
593
    }
594

    
595
    for (std::map<eventnumber_t, IEvent *>::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++) {
596
        IEvent *event = it->second;
597
        IMessageDependencyList *causes = event->getCauses();
598

    
599
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
600
            IMessageDependency *messageDependency = *it;
601
            IEvent *causeEvent = messageDependency->getCauseEvent();
602
            IEvent *consequenceEvent = messageDependency->getConsequenceEvent();
603
            int weight = messageDependency->getIsReuse() ? messageReuseWeight : messageSendWeight;
604

    
605
            if (causeEvent && consequenceEvent && weight != 0) {
606
                int causeModuleId = causeEvent->getModuleId();
607
                int consequenceModuleId = consequenceEvent->getModuleId();
608

    
609
                std::map<int, int>::iterator causeModuleIdIt = moduleIdToAxisIndexMap->find(causeModuleId);
610
                std::map<int, int>::iterator consequenceModuleIdIt = moduleIdToAxisIndexMap->find(consequenceModuleId);
611

    
612
                if (causeModuleIdIt !=  moduleIdToAxisIndexMap->end() && consequenceModuleIdIt != moduleIdToAxisIndexMap->end())
613
                    adjacencyMatrix.at(causeModuleIdIt->second * numberOfAxes + consequenceModuleIdIt->second) += weight;
614
            }
615
        }
616
    }
617

    
618
    return adjacencyMatrix;
619
}
620

    
621

    
622
long SequenceChartFacade::getSmallestEventComplexity() {
623
    long complexity = 0;
624
    if (smallestComplexity < 0) {
625
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
626
             if (event->getEventEndEntry()) {
627
                 complexity = event->getEventEndEntry()->complexity;
628
             } else {
629
                 continue;
630
             }
631
             if (complexity < smallestComplexity || smallestComplexity < 0) {
632
                 smallestComplexity = complexity;
633
             }
634
             if (complexity > largestComplexity || largestComplexity < 0) {
635
                 largestComplexity = complexity;
636
             }
637
        }
638
    }
639
    if (smallestComplexity < 0) {
640
        smallestComplexity = 0;
641
    }
642
    return smallestComplexity;
643
}
644

    
645
long SequenceChartFacade::getLargestEventComplexity() {
646
    if (largestComplexity < 0) {
647
        getSmallestEventComplexity();
648
    }
649
    if (largestComplexity < 0) {
650
        largestComplexity = 0;
651
    }
652
    return largestComplexity;
653
}
654

    
655
simtime_t SequenceChartFacade::getSmallestEventDuration() {
656
    simtime_t duration = 0;
657
    if (smallestDuration < 0) {
658
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
659
             if (event->getEventEntry()) {
660
                 duration = event->getEventEntry()->duration;
661
             } else {
662
                 continue;
663
             }
664
             if (duration < smallestDuration || smallestDuration < 0) {
665
                 smallestDuration = duration;
666
             }
667
             if (duration > largestDuration || largestDuration < 0) {
668
                 largestDuration = duration;
669
             }
670
        }
671
    }
672
    if (smallestDuration < 0) {
673
        smallestDuration = 0;
674
    }
675
    return smallestDuration;
676
}
677

    
678
simtime_t SequenceChartFacade::getLargestEventDuration() {
679
    if (largestDuration < 0) {
680
        getSmallestEventComplexity();
681
    }
682
    if (largestDuration < 0) {
683
        largestDuration = 0;
684
    }
685
    return largestDuration;
686
}
687

    
688

    
689
IEvent* SequenceChartFacade::getPreviousBottleneck(IEvent* e, unsigned int threshold) {
690
    IEvent* next = e->getPreviousEvent();
691
    while (next) {
692
        if (isBottleneck(next,threshold)) {
693
            return next;
694
        }
695
        next = next->getPreviousEvent();
696
    }
697
    return e;
698
}
699

    
700
IEvent* SequenceChartFacade::getNextBottleneck(IEvent* e, unsigned int threshold) {
701
    IEvent* next = e->getNextEvent();
702
    while (next) {
703
        if (isBottleneck(next,threshold)) {
704
            return next;
705
        }
706
        next = next->getNextEvent();
707
    }
708
    return e;
709
}
710

    
711
/*
712
 * Returns whether an event not part of a set of parallel events with more than treshold elements.
713
 */
714
bool SequenceChartFacade::isBottleneck(IEvent* event, unsigned int threshold)
715
{
716
    return getLargestParallelSetSize(event) <= threshold;
717
}
718

    
719
unsigned int SequenceChartFacade::getLargestParallelSetSize(IEvent* event)
720
{
721
    IEvent* prev = event;
722
    std::set<ptr_t> parallelSet;
723
    parallelSet.clear();
724
    unsigned int previousSize = 0;
725
    while (prev)
726
    {
727
        previousSize = parallelSet.size();
728

    
729
        getParallelSet(prev, &parallelSet);
730

    
731
        if (parallelSet.find((ptr_t) event) == parallelSet.end())
732
        {
733
            break;
734
        }
735
        prev = prev->getPreviousEvent();
736
    }
737
    return previousSize;
738
}
739

    
740
void SequenceChartFacade::getParallelSet(IEvent* event,
741
        std::set<ptr_t>* parallelSet)
742
{
743
    IEvent* next = event->getNextEvent();
744
    simtime_t smallestParallelEndtime = getSmallestParallelEndtime(event);
745
    parallelSet->clear();
746
    parallelSet->insert((ptr_t) event);
747
    while (next)
748
    {
749
        if ((next->getSimulationTime() >= event->getSimulationTime())
750
                && (smallestParallelEndtime >= next->getSimulationTime()))
751
        {
752
            parallelSet->insert((ptr_t) next);
753
        }
754
        else
755
        {
756
            break;
757
        }
758
        next = next->getNextEvent();
759
    }
760
}
761

    
762
simtime_t SequenceChartFacade::getSmallestParallelEndtime(IEvent* event)
763
{
764
    simtime_t minimum = event->getSimulationTime()
765
            + event->getEventEntry()->duration;
766
    for (IEvent *current = eventLog->getFirstEvent(); current; current
767
            = current->getNextEvent())
768
    {
769
        if (current->getSimulationTime() >= event->getSimulationTime())
770
        {
771
            if ((current->getSimulationTime()
772
                    + current->getEventEntry()->duration)
773
                    > event->getSimulationTime())
774
            {
775
                if (minimum > (current->getSimulationTime()
776
                        + current->getEventEntry()->duration))
777
                {
778
                    minimum = current->getSimulationTime()
779
                            + current->getEventEntry()->duration;
780
                }
781
            }
782
            if (current->getSimulationTime() > minimum)
783
            { // After this, no overlapping can follow
784
                break;
785
            }
786
        }
787
    }
788
    return minimum;
789
}