Fixed warning.
[libfirm] / ir / kaps / brute_force.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Brute force PBQP solver.
23  * @date    02.12.2008
24  * @author  Sebastian Buchwald
25  * @version $Id$
26  */
27 #include "config.h"
28
29 #include "assert.h"
30 #include "error.h"
31
32 #include "bucket.h"
33 #include "brute_force.h"
34 #include "optimal.h"
35 #if KAPS_DUMP
36 #include "html_dumper.h"
37 #endif
38 #include "kaps.h"
39 #include "matrix.h"
40 #include "pbqp_edge.h"
41 #include "pbqp_edge_t.h"
42 #include "pbqp_node.h"
43 #include "pbqp_node_t.h"
44 #include "vector.h"
45
46 #if KAPS_STATISTIC
47 static int dump = 0;
48 #endif
49
50 /* Forward declarations. */
51 static void apply_Brute_Force(pbqp_t *pbqp);
52
53 static void apply_brute_force_reductions(pbqp_t *pbqp)
54 {
55         for (;;) {
56                 if (edge_bucket_get_length(edge_bucket) > 0) {
57                         apply_edge(pbqp);
58                 } else if (node_bucket_get_length(node_buckets[1]) > 0) {
59                         apply_RI(pbqp);
60                 } else if (node_bucket_get_length(node_buckets[2]) > 0) {
61                         apply_RII(pbqp);
62                 } else if (node_bucket_get_length(node_buckets[3]) > 0) {
63                         apply_Brute_Force(pbqp);
64                 } else {
65                         return;
66                 }
67         }
68 }
69
70 static unsigned get_minimal_alternative(pbqp_t *pbqp, pbqp_node_t *node)
71 {
72         vector_t *node_vec;
73         unsigned  node_index;
74         unsigned  node_len;
75         unsigned  min_index    = 0;
76         num       min          = INF_COSTS;
77         unsigned  bucket_index;
78
79         assert(pbqp);
80         node_vec     = node->costs;
81         node_len     = node_vec->len;
82         bucket_index = node->bucket_index;
83
84         for (node_index = 0; node_index < node_len; ++node_index) {
85                 pbqp_node_bucket_t bucket_deg3;
86                 num                value;
87                 unsigned           bucket_0_length;
88                 unsigned           bucket_red_length;
89
90                 char *tmp = (char*)obstack_finish(&pbqp->obstack);
91
92                 node_bucket_init(&bucket_deg3);
93
94                 /* Some node buckets and the edge bucket should be empty. */
95                 assert(node_bucket_get_length(node_buckets[1]) == 0);
96                 assert(node_bucket_get_length(node_buckets[2]) == 0);
97                 assert(edge_bucket_get_length(edge_bucket)     == 0);
98
99                 /* char *tmp = obstack_finish(&pbqp->obstack); */
100
101                 /* Save current PBQP state. */
102                 node_bucket_copy(&bucket_deg3, node_buckets[3]);
103                 node_bucket_shrink(&node_buckets[3], 0);
104                 node_bucket_deep_copy(pbqp, &node_buckets[3], bucket_deg3);
105                 node_bucket_update(pbqp, node_buckets[3]);
106                 bucket_0_length   = node_bucket_get_length(node_buckets[0]);
107                 bucket_red_length = node_bucket_get_length(reduced_bucket);
108
109                 /* Select alternative and solve PBQP recursively. */
110                 select_alternative(node_buckets[3][bucket_index], node_index);
111                 apply_brute_force_reductions(pbqp);
112
113                 value = determine_solution(pbqp);
114
115                 if (value < min) {
116                         min = value;
117                         min_index = node_index;
118                 }
119
120                 /* Some node buckets and the edge bucket should still be empty. */
121                 assert(node_bucket_get_length(node_buckets[1]) == 0);
122                 assert(node_bucket_get_length(node_buckets[2]) == 0);
123                 assert(edge_bucket_get_length(edge_bucket)     == 0);
124
125                 /* Clear modified buckets... */
126                 node_bucket_shrink(&node_buckets[3], 0);
127
128                 /* ... and restore old PBQP state. */
129                 node_bucket_shrink(&node_buckets[0], bucket_0_length);
130                 node_bucket_shrink(&reduced_bucket, bucket_red_length);
131                 node_bucket_copy(&node_buckets[3], bucket_deg3);
132                 node_bucket_update(pbqp, node_buckets[3]);
133
134                 /* Free copies. */
135                 /* obstack_free(&pbqp->obstack, tmp); */
136                 node_bucket_free(&bucket_deg3);
137
138                 obstack_free(&pbqp->obstack, tmp);
139         }
140
141         return min_index;
142 }
143
144 static void apply_Brute_Force(pbqp_t *pbqp)
145 {
146         pbqp_node_t *node         = NULL;
147         unsigned     min_index    = 0;
148
149         assert(pbqp);
150
151         /* We want to reduce a node with maximum degree. */
152         node = get_node_with_max_degree();
153         assert(pbqp_node_get_degree(node) > 2);
154
155 #if KAPS_DUMP
156         if (pbqp->dump_file) {
157                 char     txt[100];
158                 sprintf(txt, "BF-Reduction of Node n%d", node->index);
159                 dump_section(pbqp->dump_file, 2, txt);
160                 pbqp_dump_graph(pbqp);
161         }
162 #endif
163
164 #if KAPS_STATISTIC
165         dump++;
166 #endif
167
168         min_index = get_minimal_alternative(pbqp, node);
169         node = pbqp->nodes[node->index];
170
171 #if KAPS_DUMP
172         if (pbqp->dump_file) {
173                 fprintf(pbqp->dump_file, "node n%d is set to %d<br><br>\n",
174                                         node->index, min_index);
175         }
176 #endif
177
178 #if KAPS_STATISTIC
179         dump--;
180         if (dump == 0) {
181                 FILE *fh = fopen("solutions.pb", "a");
182                 fprintf(fh, "[%u]", min_index);
183                 fclose(fh);
184                 pbqp->num_bf++;
185         }
186 #endif
187
188         /* Now that we found the minimum set all other costs to infinity. */
189         select_alternative(node, min_index);
190 }
191
192
193
194 static void back_propagate_RI(pbqp_t *pbqp, pbqp_node_t *node)
195 {
196         pbqp_edge_t   *edge;
197         pbqp_node_t   *other;
198         pbqp_matrix_t *mat;
199         vector_t      *vec;
200         int            is_src;
201
202         assert(pbqp);
203
204         edge = node->edges[0];
205         mat = edge->costs;
206         is_src = edge->src == node;
207         vec = node->costs;
208
209         if (is_src) {
210                 other = edge->tgt;
211
212                 /* Update pointer for brute force solver. */
213                 other = pbqp->nodes[other->index];
214
215                 node->solution = pbqp_matrix_get_col_min_index(mat, other->solution, vec);
216         } else {
217                 other = edge->src;
218
219                 /* Update pointer for brute force solver. */
220                 other = pbqp->nodes[other->index];
221
222                 node->solution = pbqp_matrix_get_row_min_index(mat, other->solution, vec);
223         }
224
225 #if KAPS_DUMP
226         if (pbqp->dump_file) {
227                 fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
228         }
229 #endif
230 }
231
232 static void back_propagate_RII(pbqp_t *pbqp, pbqp_node_t *node)
233 {
234         pbqp_edge_t   *src_edge   = node->edges[0];
235         pbqp_edge_t   *tgt_edge   = node->edges[1];
236         int            src_is_src = src_edge->src == node;
237         int            tgt_is_src = tgt_edge->src == node;
238         pbqp_matrix_t *src_mat;
239         pbqp_matrix_t *tgt_mat;
240         pbqp_node_t   *src_node;
241         pbqp_node_t   *tgt_node;
242         vector_t      *vec;
243         vector_t      *node_vec;
244         unsigned       col_index;
245         unsigned       row_index;
246
247         assert(pbqp);
248
249         if (src_is_src) {
250                 src_node = src_edge->tgt;
251         } else {
252                 src_node = src_edge->src;
253         }
254
255         if (tgt_is_src) {
256                 tgt_node = tgt_edge->tgt;
257         } else {
258                 tgt_node = tgt_edge->src;
259         }
260
261         /* Swap nodes if necessary. */
262         if (tgt_node->index < src_node->index) {
263                 pbqp_node_t *tmp_node;
264                 pbqp_edge_t *tmp_edge;
265
266                 tmp_node = src_node;
267                 src_node = tgt_node;
268                 tgt_node = tmp_node;
269
270                 tmp_edge = src_edge;
271                 src_edge = tgt_edge;
272                 tgt_edge = tmp_edge;
273
274                 src_is_src = src_edge->src == node;
275                 tgt_is_src = tgt_edge->src == node;
276         }
277
278         /* Update pointer for brute force solver. */
279         src_node = pbqp->nodes[src_node->index];
280         tgt_node = pbqp->nodes[tgt_node->index];
281
282         src_mat = src_edge->costs;
283         tgt_mat = tgt_edge->costs;
284
285         node_vec = node->costs;
286
287         row_index = src_node->solution;
288         col_index = tgt_node->solution;
289
290         vec = vector_copy(pbqp, node_vec);
291
292         if (src_is_src) {
293                 vector_add_matrix_col(vec, src_mat, row_index);
294         } else {
295                 vector_add_matrix_row(vec, src_mat, row_index);
296         }
297
298         if (tgt_is_src) {
299                 vector_add_matrix_col(vec, tgt_mat, col_index);
300         } else {
301                 vector_add_matrix_row(vec, tgt_mat, col_index);
302         }
303
304         node->solution = vector_get_min_index(vec);
305
306 #if KAPS_DUMP
307         if (pbqp->dump_file) {
308                 fprintf(pbqp->dump_file, "node n%d is set to %d<br>\n", node->index, node->solution);
309         }
310 #endif
311
312         obstack_free(&pbqp->obstack, vec);
313 }
314
315 static void back_propagate_brute_force(pbqp_t *pbqp)
316 {
317         unsigned node_index;
318         unsigned node_len = node_bucket_get_length(reduced_bucket);
319
320         assert(pbqp);
321
322 #if KAPS_DUMP
323         if (pbqp->dump_file) {
324                 dump_section(pbqp->dump_file, 2, "Back Propagation");
325         }
326 #endif
327
328         for (node_index = node_len; node_index > 0; --node_index) {
329                 pbqp_node_t *node = reduced_bucket[node_index - 1];
330
331                 switch (pbqp_node_get_degree(node)) {
332                         case 1:
333                                 back_propagate_RI(pbqp, node);
334                                 break;
335                         case 2:
336                                 back_propagate_RII(pbqp, node);
337                                 break;
338                         default:
339                                 panic("Only nodes with degree one or two should be in this bucket");
340                                 break;
341                 }
342         }
343 }
344
345 void solve_pbqp_brute_force(pbqp_t *pbqp)
346 {
347         /* Reduce nodes degree ... */
348         initial_simplify_edges(pbqp);
349
350         /* ... and put node into bucket representing their degree. */
351         fill_node_buckets(pbqp);
352
353 #if KAPS_STATISTIC
354         FILE *fh = fopen("solutions.pb", "a");
355         fprintf(fh, "Solution");
356         fclose(fh);
357 #endif
358
359         apply_brute_force_reductions(pbqp);
360
361         pbqp->solution = determine_solution(pbqp);
362
363 #if KAPS_STATISTIC
364         fh = fopen("solutions.pb", "a");
365         #if KAPS_USE_UNSIGNED
366                 fprintf(fh, ": %u RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
367                                 pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
368                                 pbqp->num_rm, pbqp->num_rn);
369         #else
370                 fprintf(fh, ": %lld RE:%u R0:%u R1:%u R2:%u RM:%u RN/BF:%u\n", pbqp->solution,
371                                 pbqp->num_edges, pbqp->num_r0, pbqp->num_r1, pbqp->num_r2,
372                                 pbqp->num_rm, pbqp->num_bf);
373         #endif
374         fclose(fh);
375 #endif
376
377         /* Solve reduced nodes. */
378         back_propagate_brute_force(pbqp);
379
380         free_buckets();
381 }