File: ParseDAG.cpp

package info (click to toggle)
vite 1.4-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,112 kB
  • sloc: cpp: 30,167; makefile: 467; sh: 233; python: 140; ansic: 67
file content (244 lines) | stat: -rw-r--r-- 9,118 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/**
 *
 * @file plugins/CriticalPath/ParseDAG.cpp
 *
 * @copyright 2008-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
 *                      Univ. Bordeaux. All rights reserved.
 *
 * @author Camille Ordronneau
 * @author Johnny Jazeix
 * @author Mathieu Faverge
 *
 * @date 2024-07-17
 */
#include "ParseDAG.hpp"

typedef boost::graph_traits<graph_t>::vertex_iterator vertex_iterator_t;
typedef boost::graph_traits<graph_t>::in_edge_iterator in_edge_iterator_t;
typedef boost::graph_traits<graph_t>::edge_descriptor edge_descriptor_t;
typedef boost::graph_traits<graph_t>::vertex_descriptor vertex_descriptor_t;

int get_job_id(std::string task) {
    std::string strId = task.substr(5); // task_88 ---> 88
    int job_id = std::stoi(strId);
    return job_id;
}

std::pair<std::pair<double, size_t>, double> critical_path_length(graph_t &g, std::vector<double> &task_time) {
    /* Order the vertices topologically */
    std::deque<int> topo_order;
    topological_sort(g, std::front_inserter(topo_order),
                     vertex_index_map(identity_property_map()));

    std::pair<std::pair<double, size_t>, double> ret;
    std::pair<double, vertex_descriptor_t> length__last_task; // Returned value
    length__last_task.first = 0;
    length__last_task.second = 0;

    /* Computes the length of the longest path ending at the v
    where v is every vertex in the graph in topological order */
    int n = 1;
    for (std::deque<int>::iterator i = topo_order.begin(); i != topo_order.end(); ++i, ++n) {

        /* Task_time is a vector indexed with jobId,
        task_time.size() is the highest jobId parsed */
        g[*i].task_id = get_job_id(g[*i].task_name);
        g[*i].not_max_breadth = 0;
        if (g[*i].task_id >= (int)task_time.size()) {
            g[*i].execution_time = 0;
        }
        else {
            g[*i].execution_time = get_time(g[*i].task_id, task_time);
        }

        g[*i].time_elapsed = 0;

        if (in_degree(*i, g)) { // if g[*i] is not a root
            double max_time_elapsed = 0;
            std::pair<in_edge_iterator_t, in_edge_iterator_t> e = in_edges(*i, g);

            while (e.first != e.second) {
                edge_descriptor_t ed = *e.first;
                vertex_descriptor_t s = source(ed, g);
                max_time_elapsed = std::max(max_time_elapsed, g[s].time_elapsed);
                e.first++;
            }

            g[*i].time_elapsed = max_time_elapsed + g[*i].execution_time;
        }

        else {
            g[*i].time_elapsed = g[*i].execution_time;
            /* If the vertex is a root then its elapsed time is equal to its execution time */
        }

        /* Updating critical path length as it is the max of max_time_elapsed of all vertexes */
        if (length__last_task.first < g[*i].time_elapsed || (length__last_task.first == g[*i].time_elapsed && g[*i].execution_time == 0)) {
            length__last_task.second = *i;
            length__last_task.first = g[*i].time_elapsed;
        }
    }
    ret.first = std::move(length__last_task);
    ret.second = n - 1;
    return ret;
}

void dag_draw_critical_path(graph_t &g, int source_task) {

    while (in_degree(source_task, g)) {
        double max_value = 0;
        std::pair<in_edge_iterator_t, in_edge_iterator_t> e = in_edges(source_task, g);
        vertex_descriptor_t target_task = source_task;

        while (e.first != e.second) {
            edge_descriptor_t ed = *e.first;
            vertex_descriptor_t s = source(ed, g);
            double last_max = max_value;
            max_value = std::max(max_value, g[s].time_elapsed);

            if (max_value != last_max || max_value == 0) {
                source_task = s;
            }
            e.first++;
        }
        remove_edge(source_task, target_task, g);
        add_edge(source_task, target_task, Edge { "red" }, g);
    }
}

std::vector<int> critical_path(graph_t &g, int source_task) {
    std::vector<int> criticalPath; // Returned value
    while (in_degree(source_task, g)) {
        criticalPath.push_back(g[source_task].task_id);
        double max_recorded_value = 0;
        std::pair<in_edge_iterator_t, in_edge_iterator_t> e = in_edges(source_task, g);
        vertex_descriptor_t target_task = source_task;

        while (e.first != e.second) {
            edge_descriptor_t ed = *e.first;
            vertex_descriptor_t s = source(ed, g);
            double last_max = max_recorded_value;
            max_recorded_value = std::max(max_recorded_value, g[s].time_elapsed);

            if (max_recorded_value != last_max || max_recorded_value == 0) {
                source_task = s;
            }
            e.first++;
        }
        remove_edge(source_task, target_task, g);
        add_edge(source_task, target_task, Edge { "red" }, g);
    }
    criticalPath.push_back(g[source_task].task_id);
    return criticalPath;
}

std::vector<int> critical_last_tasks(graph_t &g, double max_value) {
    std::vector<int> critical_last_tasks;
    for (std::pair<vertex_iterator_t, vertex_iterator_t> vp = vertices(g);
         vp.first != vp.second; ++vp.first) {

        if (g[*vp.first].time_elapsed == max_value && out_degree(*vp.first, g) == 0) {
            critical_last_tasks.push_back(*vp.first);
        }
    }
    return critical_last_tasks;
}

std::pair<double, pair> get_number_processing(graph_t &g, double begin, double end) {
    std::pair<double, pair> ret; // Returned Value
    ret.first = 0; // ret.first is the max breadth
    ret.second.first = begin;
    ret.second.second = end;
    // ret.second is a pair representing the interval where this max breadth was achieved
    if (end <= begin) {
        return ret;
    }

    double count = 0;
    double count_right = 0;
    double count_left = 0;
    double new_begin = ret.second.first;
    double new_end = ret.second.second;

    for (std::pair<vertex_iterator_t, vertex_iterator_t> vp = vertices(g);
         vp.first != vp.second; ++vp.first) {

        double task_start = g[*vp.first].time_elapsed - g[*vp.first].execution_time;
        double task_end = g[*vp.first].time_elapsed;

        if (g[*vp.first].execution_time > 0) {

            /**** Smaller Full Overlapping ****/
            if ((begin <= task_start && task_end <= end) && (begin != task_start || task_end != end)) {
                /* If a task is strictly within (begin-end) just return because (begin - end)
                cannot possibly be the exact interval where the max breadth is obtained.
                But the max breadth can be achived in an interval within (begin - end)*/

                ret.first = -1;
                ret.second.first = 0;
                ret.second.second = 0;
                return ret;
            }

            /**** Right Overlapping ****/
            if ((begin <= task_start && task_start < end) && end < task_end) {
                /* We update the right interval which overlaps with most other tasks
                    (This interval is now (new_begin - end)) */

                if (task_start > new_begin) {
                    new_begin = task_start;
                }
                count_right++; // Incrementing right overlapping counter
            }

            /**** Left Overlapping ****/
            else if (task_start < begin && (begin < task_end && task_end <= end)) {
                /* We update the left interval which overlaps with most other tasks
                    (This interval is now (begin - new_end)*/

                if (task_end < new_end) {
                    new_end = task_end;
                }
                count_left++; // Incrementing left overlapping counter
            }

            /**** Bigger Full Overlapping ****/
            else if (task_start <= begin && end <= task_end) {
                /* If a task is overlapping and strictly bigger than (begin-end),
                    then we increase our normal count */
                g[*vp.first].not_max_breadth = 1;
                count++;
            }
        }
    }

    /* We then update ret.first with count + max(count_right, count_left),
        and we update the correspondant side of the interval */
    if (count_right > count_left) {
        ret.second.first = new_begin;
    }
    else if (count_right < count_left) {
        ret.second.second = new_end;
    }
    count += std::max(count_right, count_left);
    ret.first = count;
    return ret;
}

std::pair<double, pair> max_breadth(graph_t &g) {
    std::pair<double, pair> max_breadth; // Returned value
    std::pair<double, pair> num_process;
    max_breadth.first = 0;

    for (std::pair<vertex_iterator_t, vertex_iterator_t> vp = vertices(g);
         vp.first != vp.second; ++vp.first) {
        if (g[*vp.first].not_max_breadth == 0) {
            num_process = get_number_processing(g, g[*vp.first].time_elapsed - g[*vp.first].execution_time,
                                                g[*vp.first].time_elapsed);
            if (num_process.first > max_breadth.first) {
                max_breadth = num_process;
            }
        }
    }
    return max_breadth;
}