Adapt to coding conventions.
[libfirm] / heuristical_co_ld.c
1 /*
2  * heuristical_co_ld.c
3  *
4  *  Created on: 06.05.2010
5  *      Author: berschth
6  */
7
8 #include "config.h"
9
10 #include "adt/array.h"
11 #include "assert.h"
12 #include "error.h"
13
14 #include "bucket.h"
15 #include "heuristical_co_ld.h"
16 #include "optimal.h"
17 #if     KAPS_DUMP
18 #include "html_dumper.h"
19 #endif
20 #include "kaps.h"
21 #include "matrix.h"
22 #include "pbqp_edge.h"
23 #include "pbqp_edge_t.h"
24 #include "pbqp_node.h"
25 #include "pbqp_node_t.h"
26 #include "vector.h"
27
28 #include "plist.h"
29 #include "timing.h"
30
31 static void back_propagate_RI(pbqp *pbqp, pbqp_node *node)
32 {
33         pbqp_edge   *edge;
34         pbqp_node   *other;
35         pbqp_matrix *mat;
36         vector      *vec;
37         int          is_src;
38
39         assert(pbqp);
40         assert(node);
41
42         (void) pbqp;
43
44         edge = node->edges[0];
45         mat = edge->costs;
46         is_src = edge->src == node;
47         vec = node->costs;
48
49         if (is_src) {
50                 other = edge->tgt;
51                 assert(other);
52
53                 node->solution = pbqp_matrix_get_col_min_index(mat, other->solution, vec);
54         } else {
55                 other = edge->src;
56                 assert(other);
57
58                 node->solution = pbqp_matrix_get_row_min_index(mat, other->solution, vec);
59         }
60
61 #if     KAPS_DUMP
62         if (pbqp->dump_file) {
63                 fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
64         }
65 #endif
66 }
67
68 static void back_propagate_RII(pbqp *pbqp, pbqp_node *node)
69 {
70         pbqp_edge   *src_edge   = node->edges[0];
71         pbqp_edge   *tgt_edge   = node->edges[1];
72         int          src_is_src = src_edge->src == node;
73         int          tgt_is_src = tgt_edge->src == node;
74         pbqp_matrix *src_mat;
75         pbqp_matrix *tgt_mat;
76         pbqp_node   *src_node;
77         pbqp_node   *tgt_node;
78         vector      *vec;
79         vector      *node_vec;
80         unsigned     col_index;
81         unsigned     row_index;
82
83         assert(pbqp);
84
85         if (src_is_src) {
86                 src_node = src_edge->tgt;
87         } else {
88                 src_node = src_edge->src;
89         }
90
91         if (tgt_is_src) {
92                 tgt_node = tgt_edge->tgt;
93         } else {
94                 tgt_node = tgt_edge->src;
95         }
96
97         /* Swap nodes if necessary. */
98         if (tgt_node->index < src_node->index) {
99                 pbqp_node *tmp_node;
100                 pbqp_edge *tmp_edge;
101
102                 tmp_node = src_node;
103                 src_node = tgt_node;
104                 tgt_node = tmp_node;
105
106                 tmp_edge = src_edge;
107                 src_edge = tgt_edge;
108                 tgt_edge = tmp_edge;
109
110                 src_is_src = src_edge->src == node;
111                 tgt_is_src = tgt_edge->src == node;
112         }
113
114         src_mat = src_edge->costs;
115         tgt_mat = tgt_edge->costs;
116
117         node_vec = node->costs;
118
119         row_index = src_node->solution;
120         col_index = tgt_node->solution;
121
122         vec = vector_copy(pbqp, node_vec);
123
124         if (src_is_src) {
125                 vector_add_matrix_col(vec, src_mat, row_index);
126         } else {
127                 vector_add_matrix_row(vec, src_mat, row_index);
128         }
129
130         if (tgt_is_src) {
131                 vector_add_matrix_col(vec, tgt_mat, col_index);
132         } else {
133                 vector_add_matrix_row(vec, tgt_mat, col_index);
134         }
135
136         node->solution = vector_get_min_index(vec);
137
138 #if     KAPS_DUMP
139         if (pbqp->dump_file) {
140                 fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
141         }
142 #endif
143
144         obstack_free(&pbqp->obstack, vec);
145 }
146
147 static void back_propagate_RN(pbqp *pbqp, pbqp_node *node)
148 {
149         vector    *vec      = NULL;
150         pbqp_node *neighbor = NULL;
151         pbqp_edge *edge     = NULL;
152         unsigned   idx      = 0;
153
154         assert(pbqp);
155
156         vec = vector_copy(pbqp, node->costs);
157
158         for(idx = 0; idx < pbqp_node_get_degree(node); idx++) {
159                 /* get neighbor node */
160                 edge = node->edges[idx];
161                 neighbor = edge->src == node ? edge->tgt : edge->src;
162
163                 /* node is edge src node */
164                 if(edge->src == node)
165                         vector_add_matrix_col(vec, edge->costs, neighbor->solution);
166                 /* node is edge tgt node */
167                 else
168                         vector_add_matrix_row(vec, edge->costs, neighbor->solution);
169         }
170
171         assert(vector_get_min(vec) != INF_COSTS);
172         node->solution = vector_get_min_index(vec);
173
174 #if     KAPS_DUMP
175         if (pbqp->dump_file) {
176                 fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
177         }
178 #endif
179
180         obstack_free(&pbqp->obstack, vec);
181 }
182
183 static void back_propagate_ld(pbqp *pbqp)
184 {
185         unsigned node_index;
186         unsigned node_len   = node_bucket_get_length(reduced_bucket);
187
188         assert(pbqp);
189
190 #if     KAPS_DUMP
191         if (pbqp->dump_file) {
192                 dump_section(pbqp->dump_file, 2, "Back Propagation");
193         }
194 #endif
195
196         for (node_index = node_len; node_index > 0; --node_index) {
197                 pbqp_node *node = reduced_bucket[node_index - 1];
198
199                 switch (pbqp_node_get_degree(node)) {
200                         case 1:
201                                 back_propagate_RI(pbqp, node);
202                                 break;
203                         case 2:
204                                 back_propagate_RII(pbqp, node);
205                                 break;
206                         default:
207                                 back_propagate_RN(pbqp, node);
208                                 break;
209                 }
210         }
211 }
212
213 static void apply_RN_co_without_selection(pbqp *pbqp, plist_t *rpeo)
214 {
215         pbqp_node *node     = NULL;
216         pbqp_node *neighbor = NULL;
217         pbqp_edge *edge     = NULL;
218         unsigned   idx      = 0;
219
220         (void)pbqp;
221
222         do {
223                 /* get last element from reverse perfect elimination order */
224                 node = plist_last(rpeo)->data;
225                 /* remove element from reverse perfect elimination order */
226                 plist_erase(rpeo, plist_last(rpeo));
227                 /* insert node at the beginning of rpeo so the rpeo already exits after pbqp solving */
228                 plist_insert_front(rpeo, node);
229         } while(node_is_reduced(node));
230
231         assert(node);
232         assert(pbqp_node_get_degree(node) > 2);
233
234 #if     KAPS_DUMP
235         if (pbqp->dump_file) {
236                 char     txt[100];
237                 sprintf(txt, "RN-Reduction of Node n%d", node->index);
238                 dump_section(pbqp->dump_file, 2, txt);
239                 pbqp_dump_graph(pbqp);
240         }
241 #endif
242
243         /* Disconnect neighbor nodes */
244         for(idx = 0; idx < pbqp_node_get_degree(node); idx++) {
245                 /* get neighbor node */
246                 edge = node->edges[idx];
247                 neighbor = edge->src == node ? edge->tgt : edge->src;
248
249                 assert(neighbor != node);
250
251                 if(!is_connected(neighbor, edge))
252                         continue;
253
254                 disconnect_edge(neighbor, edge);
255                 reorder_node(neighbor);
256         }
257
258         /* Remove node from old bucket */
259         node_bucket_remove(&node_buckets[3], node);
260
261         /* Add node to back propagation list. */
262         node_bucket_insert(&reduced_bucket, node);
263 }
264
265
266
267 static void apply_heuristic_reductions_co(pbqp *pbqp, plist_t *rpeo)
268 {
269         #if KAPS_TIMING
270                 /* create timers */
271                 ir_timer_t *t_edge = ir_timer_new();
272                 ir_timer_t *t_r1   = ir_timer_new();
273                 ir_timer_t *t_r2   = ir_timer_new();
274                 ir_timer_t *t_rn   = ir_timer_new();
275         #endif
276
277         for (;;) {
278                 if (edge_bucket_get_length(edge_bucket) > 0) {
279                         #if KAPS_TIMING
280                                 ir_timer_start(t_edge);
281                         #endif
282
283                         apply_edge(pbqp);
284
285                         #if KAPS_TIMING
286                                 ir_timer_stop(t_edge);
287                         #endif
288                 } else if (node_bucket_get_length(node_buckets[1]) > 0) {
289                         #if KAPS_TIMING
290                                 ir_timer_start(t_r1);
291                         #endif
292
293                         apply_RI(pbqp);
294
295                         #if KAPS_TIMING
296                                 ir_timer_stop(t_r1);
297                         #endif
298                 } else if (node_bucket_get_length(node_buckets[2]) > 0) {
299                         #if KAPS_TIMING
300                                 ir_timer_start(t_r2);
301                         #endif
302
303                         apply_RII(pbqp);
304
305                         #if KAPS_TIMING
306                                 ir_timer_stop(t_r2);
307                         #endif
308                 } else if (node_bucket_get_length(node_buckets[3]) > 0) {
309                         #if KAPS_TIMING
310                                 ir_timer_start(t_rn);
311                         #endif
312
313                         apply_RN_co_without_selection(pbqp, rpeo);
314
315                         #if KAPS_TIMING
316                                 ir_timer_stop(t_rn);
317                         #endif
318                 } else {
319                         #if KAPS_TIMING
320                                 printf("PBQP RE reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_edge) / 1000.0);
321                                 printf("PBQP R1 reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_r1) / 1000.0);
322                                 printf("PBQP R2 reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_r2) / 1000.0);
323                                 printf("PBQP RN reductions:           %10.3lf msec\n", (double)ir_timer_elapsed_usec(t_rn) / 1000.0);
324                         #endif
325
326                         return;
327                 }
328         }
329 }
330
331 void solve_pbqp_heuristical_co_ld(pbqp *pbqp, plist_t *rpeo)
332 {
333         /* Reduce nodes degree ... */
334         initial_simplify_edges(pbqp);
335
336         /* ... and put node into bucket representing their degree. */
337         fill_node_buckets(pbqp);
338
339         #if KAPS_STATISTIC
340                 FILE *fh = fopen("solutions.pb", "a");
341                 fprintf(fh, "Solution");
342                 fclose(fh);
343         #endif
344
345         apply_heuristic_reductions_co(pbqp, rpeo);
346
347         pbqp->solution = determine_solution(pbqp);
348
349         #if KAPS_STATISTIC
350                 fh = fopen("solutions.pb", "a");
351                 #if KAPS_USE_UNSIGNED
352                         fprintf(fh, ": %u RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
353                                         pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
354                                         pbqp->num_rm, pbqp->num_rn);
355                 #else
356                         fprintf(fh, ": %lld RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
357                                         pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
358                                         pbqp->num_rm, pbqp->num_rn);
359                 #endif
360                 fclose(fh);
361         #endif
362
363         /* Solve reduced nodes. */
364         back_propagate_ld(pbqp);
365
366         free_buckets();
367 }