b4c0a25992be79232accf24f1754cf80ce5ac895
[libfirm] / ir / be / becopyilp.c
1 /**
2  * Minimizing copies with an exact algorithm using mixed integer programming (MIP).
3  * Problem statement as a 'quadratic 0-1 program with linear constraints' with
4  * n binary variables. Constraints are knapsack (enforce color for each node) and
5  * cliques of ifg (interference constraints).
6  * Transformation into a 'mixed integer program' with n binary variables and
7  * additional 2n real variables. Constraints are the above the transformed
8  * objective function and 'complementary conditions' for two var classes.
9  * @author Daniel Grund
10  *
11  * NOTE: Unfortunately no good solver is available locally (or even for linking)
12  *       We use CPLEX 9.0 which runs on a machine residing at the Rechenzentrum.
13  * @date 12.04.2005
14  */
15
16 #include "becopyopt.h"
17 #include "becopystat.h"
18
19 #undef DUMP_MATRICES            /**< dumps all matrices completely. only recommended for small problems */
20 #define DUMP_MILP                       /**< dumps the problem as Mixed Integer Linear Programming in "CPLEX"-MPS format. NOT fixed-column-MPS. */
21 #undef DO_SOLVE                         /**< solve the MPS output with CPLEX */
22 #undef DELETE_FILES             /**< deletes all dumped files after use */
23
24 /* CPLEX-account related stuff */
25 #define SSH_USER_HOST "kb61@sp-smp.rz.uni-karlsruhe.de"
26 #define SSH_PASSWD_FILE "/ben/daniel/.smppw"
27 #define EXPECT_FILENAME "runme" /** name of the expect-script */
28
29 #define DEBUG_LVL 0 //SET_LEVEL_1
30 static firm_dbg_module_t *dbg = NULL;
31
32 #define SLOTS_NUM2POS 256
33 #define SLOTS_LIVING 32
34
35 /* get_weight represents the _gain_ if node n and m have the same color. */
36 #define get_weight(n,m) 1
37
38 /**
39  * A type storing names of the x variables in the form x[NUMBER]_[COLOR]
40  */
41 typedef struct _x_name_t {
42         int n, c;
43 } x_name_t;
44
45 /**
46  * For each node taking part in the opt-problem its position in the
47  * x-variable-vector is stored in a set. This set maps the node-nr (given by
48  * benumb) to the position in the vector.
49  */
50 typedef struct _num2pos_t {
51         int num, pos;
52 } num2pos_t;
53
54 /**
55  * A type storing the unmodified '0-1 quadratic program' of the form
56  * min f = xQx
57  * udN:  Ax  = e
58  *       Bx <= e
59  *        x \in {0, 1}
60  *
61  * This problem is called the original problem
62  */
63 typedef struct _problem_instance_t {
64         const copy_opt_t *co;                   /** the original copy_opt problem */
65         int x_dim, A_dim, B_dim;                /**< number of: x variables (equals Q_dim), rows in A, rows in B */
66         x_name_t *x;                                    /**< stores the names of the x variables. all possible colors for a node are ordered and occupy consecutive entries. lives in obstack ob. */
67         set *num2pos;                                   /**< maps node numbers to positions in x. */
68         sp_matrix_t *Q, *A, *B;                 /**< the (sparse) matrices of this problem */
69
70         /* needed only for linearizations */
71         int bigM, maxQij, minQij;
72
73         /* overhead needed to build this */
74         struct obstack ob;
75         int curr_color;
76         int curr_row;
77 } problem_instance_t;
78
79 /* Nodes have consecutive numbers so this hash shoud be fine */
80 #define HASH_NUM(num) num
81
82 static int set_cmp_num2pos(const void *x, const void *y, size_t size) {
83         return ((num2pos_t *)x)->num != ((num2pos_t *)y)->num;
84 }
85
86 /**
87  * Sets the first position of node with number num to pos.
88  * See x_name_t *x in _problem_instance_t.
89  */
90 static INLINE void pi_set_first_pos(problem_instance_t *pi, int num, int pos) {
91         num2pos_t find;
92         find.num = num;
93         find.pos = pos;
94         set_insert(pi->num2pos, &find, sizeof(find), HASH_NUM(num));
95 }
96
97 /**
98  * Get position by number. (First possible color)
99  * returns -1 if not found.
100  */
101 static INLINE int pi_get_first_pos(problem_instance_t *pi, int num) {
102         num2pos_t find, *found;
103         find.num = num;
104         found = set_find(pi->num2pos, &find, sizeof(find), HASH_NUM(num));
105         if (found) {
106                 assert(pi->x[found->pos].n == num && (found->pos == 0 || pi->x[found->pos-1].n != num) && "pi->num2pos is broken!");
107                 return found->pos;
108         } else
109                 return -1;
110 }
111
112 /**
113  * Get position by number and color.
114  * returns -1 if not found.
115  */
116 static INLINE int pi_get_pos(problem_instance_t *pi, int num, int col) {
117         num2pos_t find, *found;
118         find.num = num;
119         int pos;
120         found = set_find(pi->num2pos, &find, sizeof(find), HASH_NUM(num));
121         if (!found)
122                 return -1;
123         pos = found->pos;
124         while (pos < pi->x_dim && pi->x[pos].n == num && pi->x[pos].c < col)
125                 pos++;
126
127         if (pi->x[pos].n == num && pi->x[pos].c == col)
128                 return pos;
129         else
130                 return -1;
131 }
132
133 #ifdef DUMP_MATRICES
134 /**
135  * Dump the raw matrices of the problem to a file for debugging.
136  */
137 static void pi_dump_matrices(problem_instance_t *pi) {
138         int i;
139         FILE *out = ffopen(pi->co->name, "matrix", "wt");
140
141         DBG((dbg, LEVEL_1, "Dumping raw...\n"));
142         fprintf(out, "\n\nx-names =\n");
143         for (i=0; i<pi->x_dim; ++i)
144                 fprintf(out, "%5d %2d\n", pi->x[i].n, pi->x[i].c);
145
146         fprintf(out, "\n\n-Q =\n");
147         matrix_dump(pi->Q, out, -1);
148
149         fprintf(out, "\n\nA =\n");
150         matrix_dump(pi->A, out, 1);
151
152         fprintf(out, "\n\nB =\n");
153         matrix_dump(pi->B, out, 1);
154
155         fclose(out);
156 }
157 #endif
158
159 #ifdef DUMP_MILP
160 /**
161  * Dumps an mps file representing the problem. This is NOT the old-style,
162  * fixed-column format. Some white spaces are important, in general spaces
163  * are separators, MARKER-lines are used in COLUMN section to define binaries.
164  */
165 //BETTER use last 2 fields in COLUMNS section. See MPS docu for details
166 static void pi_dump_milp(problem_instance_t *pi) {
167         int i, max_abs_Qij;
168         const matrix_elem_t *e;
169         FILE *out = ffopen(pi->co->name, "milp", "wt");
170
171         DBG((dbg, LEVEL_1, "Dumping milp...\n"));
172         max_abs_Qij = pi->maxQij;
173         if (-pi->minQij > max_abs_Qij)
174                 max_abs_Qij = -pi->minQij;
175         pi->bigM = pi->A_dim * max_abs_Qij;
176         DBG((dbg, LEVEL_2, "BigM = %d\n", pi->bigM));
177
178         matrix_optimize(pi->Q);
179         bitset_t *good_row = bitset_alloca(pi->x_dim);
180         for (i=0; i<pi->x_dim; ++i)
181                 if (matrix_row_first(pi->Q, i))
182                         bitset_set(good_row, i);
183
184         fprintf(out, "NAME %s\n", pi->co->name);
185
186         fprintf(out, "ROWS\n");
187         fprintf(out, " N obj\n");
188         for (i=0; i<pi->x_dim; ++i)
189                 if (bitset_is_set(good_row, i))
190                         fprintf(out, " E cQ%d\n", i);
191         for (i=0; i<pi->A_dim; ++i)
192                 fprintf(out, " E cA%d\n", i);
193         for (i=0; i<pi->B_dim; ++i)
194                 fprintf(out, " L cB%d\n", i);
195         for (i=0; i<pi->x_dim; ++i)
196                 if (bitset_is_set(good_row, i))
197                         fprintf(out, " L cy%d\n", i);
198
199         fprintf(out, "COLUMNS\n");
200         /* the x vars come first */
201         /* mark them as binaries */
202         fprintf(out, "    MARKI0\t'MARKER'\t'INTORG'\n");
203         for (i=0; i<pi->x_dim; ++i) {
204                 /* participation in objective */
205                 if (bitset_is_set(good_row, i))
206                         fprintf(out, "    x%d_%d\tobj\t%d\n", pi->x[i].n, pi->x[i].c, -pi->bigM);
207                 /* in Q */
208                 matrix_foreach_in_col(pi->Q, i, e)
209                         fprintf(out, "    x%d_%d\tcQ%d\t%d\n", pi->x[i].n, pi->x[i].c, e->row, e->val);
210                 /* in A */
211                 matrix_foreach_in_col(pi->A, i, e)
212                         fprintf(out, "    x%d_%d\tcA%d\t%d\n", pi->x[i].n, pi->x[i].c, e->row, e->val);
213                 /* in B */
214                 matrix_foreach_in_col(pi->B, i, e)
215                         fprintf(out, "    x%d_%d\tcB%d\t%d\n", pi->x[i].n, pi->x[i].c, e->row, e->val);
216                 /* in y */
217                 if (bitset_is_set(good_row, i))
218                         fprintf(out, "    x%d_%d\tcy%d\t%d\n", pi->x[i].n, pi->x[i].c, i, 2*pi->bigM);
219         }
220
221         fprintf(out, "    MARKI1\t'MARKER'\t'INTEND'\n"); /* end of marking */
222
223         /* next the s vars */
224         for (i=0; i<pi->x_dim; ++i)
225                 if (bitset_is_set(good_row, i)) {
226                         /* participation in objective */
227                         fprintf(out, "    s%d_%d\tobj\t%d\n", pi->x[i].n, pi->x[i].c, 1);
228                         /* in Q */
229                         fprintf(out, "    s%d_%d\tcQ%d\t%d\n", pi->x[i].n, pi->x[i].c, i, -1);
230                 }
231
232         /* next the y vars */
233         for (i=0; i<pi->x_dim; ++i)
234                 if (bitset_is_set(good_row, i)) {
235                         /* in Q */
236                         fprintf(out, "    y%d_%d\tcQ%d\t%d\n", pi->x[i].n, pi->x[i].c, i, -1);
237                         /* in y */
238                         fprintf(out, "    y%d_%d\tcy%d\t%d\n", pi->x[i].n, pi->x[i].c, i, 1);
239                 }
240
241         fprintf(out, "RHS\n");
242         for (i=0; i<pi->x_dim; ++i)
243                 if (bitset_is_set(good_row, i))
244                         fprintf(out, "    rhs\tcQ%d\t%d\n", i, -pi->bigM);
245         for (i=0; i<pi->A_dim; ++i)
246                 fprintf(out, "    rhs\tcA%d\t%d\n", i, 1);
247         for (i=0; i<pi->B_dim; ++i)
248                 fprintf(out, "    rhs\tcB%d\t%d\n", i, 1);
249         for (i=0; i<pi->x_dim; ++i)
250                 if (bitset_is_set(good_row, i))
251                         fprintf(out, "    rhs\tcy%d\t%d\n", i, 2*pi->bigM);
252
253         fprintf(out, "ENDATA\n");
254         fclose(out);
255 }
256 #endif
257
258 #ifdef DO_SOLVE
259 /**
260  * Dumps the known solution to a file to make use of it
261  * as a starting solution respectively as a bound
262  */
263 static void pi_dump_start_sol(problem_instance_t *pi) {
264         int i;
265         FILE *out = ffopen(pi->co->name, "mst", "wt");
266         fprintf(out, "NAME\n");
267         for (i=0; i<pi->x_dim; ++i) {
268                 int val, n, c;
269                 n = pi->x[i].n;
270                 c = pi->x[i].c;
271                 if (get_irn_color(get_irn_for_graph_nr(pi->co->irg, n)) == c)
272                         val = 1;
273                 else
274                         val = 0;
275                 fprintf(out, "    x%d_%d\t%d\n", n, c, val);
276         }
277         fprintf(out, "ENDATA\n");
278         fclose(out);
279 }
280
281 /**
282  * Invoke an external solver
283  */
284 static void pi_solve_ilp(problem_instance_t *pi) {
285         FILE *out, *pwfile;
286         char passwd[128];
287
288         DBG((dbg, LEVEL_1, "Solving with CPLEX@RZ...\n"));
289         /* write command file for CPLEX */
290         out = ffopen(pi->co->name, "cmd", "wt");
291         fprintf(out, "set logfile %s.sol\n", pi->co->name);
292 #ifdef DUMP_MILP
293         fprintf(out, "read %s.milp mps\n", pi->co->name);
294 #endif
295 #ifdef DUMP_MIQP
296         fprintf(out, "read %s.miqp mps\n", pi->co->name);
297 #endif
298         fprintf(out, "read %s.mst\n", pi->co->name);
299         fprintf(out, "set mip strategy mipstart 1\n");
300         fprintf(out, "set mip emphasis 3\n");
301         fprintf(out, "optimize\n");
302         fprintf(out, "display solution variables 1-%d\n", pi->x_dim);
303         fprintf(out, "set logfile cplex.log\n");
304         fprintf(out, "quit\n");
305         fclose(out);
306
307         /* write expect-file for copying problem to RZ */
308         pwfile = fopen(SSH_PASSWD_FILE, "rt");
309         fgets(passwd, sizeof(passwd), pwfile);
310         fclose(pwfile);
311
312         out = ffopen(EXPECT_FILENAME, "exp", "wt");
313         fprintf(out, "#! /usr/bin/expect\n");
314         fprintf(out, "spawn scp %s.miqp %s.milp %s.mst %s.cmd %s:\n", pi->co->name, pi->co->name, pi->co->name, pi->co->name, SSH_USER_HOST); /* copy problem files */
315         fprintf(out, "expect \"word:\"\nsend \"%s\\n\"\ninteract\n", passwd);
316
317         fprintf(out, "spawn ssh %s \"./cplex90 < %s.cmd\"\n", SSH_USER_HOST, pi->co->name); /* solve */
318         fprintf(out, "expect \"word:\"\nsend \"%s\\n\"\ninteract\n", passwd);
319
320         fprintf(out, "spawn scp %s:%s.sol .\n", SSH_USER_HOST, pi->co->name); /*copy back solution */
321         fprintf(out, "expect \"word:\"\nsend \"%s\\n\"\ninteract\n", passwd);
322
323         fprintf(out, "spawn ssh %s ./dell\n", SSH_USER_HOST); /* clean files on server */
324         fprintf(out, "expect \"word:\"\nsend \"%s\\n\"\ninteract\n", passwd);
325         fclose(out);
326
327         /* call the expect script */
328         chmod(EXPECT_FILENAME ".exp", 0700);
329         system(EXPECT_FILENAME ".exp");
330 }
331
332 /**
333  * Sets the colors of irns according to the values of variables found in the
334  * output file of the solver.
335  */
336 static void pi_apply_solution(problem_instance_t *pi) {
337         FILE *in = ffopen(pi->co->name, "sol", "rt");
338
339         if (!in)
340                 return;
341         DBG((dbg, LEVEL_1, "Applying solution...\n"));
342         while (!feof(in)) {
343                 char buf[1024];
344                 int num = -1, col = -1, val = -1;
345
346                 fgets(buf, sizeof(buf), in);
347                 DBG((dbg, LEVEL_3, "Line: %s", buf));
348
349                 if (strcmp(buf, "No integer feasible solution exists.") == 0)
350                         assert(0 && "CPLEX says: No integer feasible solution exists!");
351
352                 if (strcmp(buf, "TODO Out of memory") == 0) {}
353
354 #ifdef DO_STAT
355                 {
356                         /* solution time */
357                         float sol_time;
358                         int iter;
359                         if (sscanf(buf, "Solution time = %f sec. Iterations = %d", &sol_time, &iter) == 2) {
360                                 DBG((dbg, LEVEL_2, " Time: %f Iter: %d\n", sol_time, iter));
361                                 curr_vals[I_ILP_TIME] += 10 * sol_time;
362                                 curr_vals[I_ILP_ITER] += iter;
363                         }
364                 }
365 #endif
366
367                 /* variable value */
368                 if (sscanf(buf, "x%d_%d %d", &num, &col, &val) == 3 && val == 1) {
369                         DBG((dbg, LEVEL_2, " x%d_%d = %d\n", num, col, val));
370                         set_irn_color(get_irn_for_graph_nr(pi->co->irg, num), col);
371                 }
372         }
373         fclose(in);
374 }
375 #endif /* DO_SOLVE */
376
377 #ifdef DELETE_FILES
378 static void pi_delete_files(problem_instance_t *pi) {
379         char buf[1024];
380         int end = snprintf(buf, sizeof(buf), "%s", pi->co->name);
381         DBG((dbg, LEVEL_1, "Deleting files...\n"));
382 #ifdef DUMP_MATRICES
383         snprintf(buf+end, sizeof(buf)-end, ".matrix");
384         remove(buf);
385 #endif
386 #ifdef DUMP_MILP
387         snprintf(buf+end, sizeof(buf)-end, ".mps");
388         remove(buf);
389         snprintf(buf+end, sizeof(buf)-end, ".mst");
390         remove(buf);
391         snprintf(buf+end, sizeof(buf)-end, ".cmd");
392         remove(buf);
393         remove(EXPECT_FILENAME ".exp");
394 #endif
395 #ifdef DO_SOLVE
396         snprintf(buf+end, sizeof(buf)-end, ".sol");
397         remove(buf);
398 #endif
399 }
400 #endif
401
402 /**
403  * Collects all irns in currently processed register class
404  */
405 static void pi_collect_x_names(ir_node *block, void *env) {
406         problem_instance_t *pi = env;
407         struct list_head *head = &get_ra_block_info(block)->border_head;
408         border_t *curr;
409         bitset_t *pos_regs = bitset_alloca(pi->co->cls->n_regs);
410
411         list_for_each_entry_reverse(border_t, curr, head, list)
412                 if (curr->is_def && curr->is_real) {
413                         x_name_t xx;
414                         pi->A_dim++;                    /* one knapsack constraint for each node */
415
416                         xx.n = get_irn_graph_nr(curr->irn);
417                         pi_set_first_pos(pi, xx.n, pi->x_dim);
418
419                         // iterate over all possible colors in order
420                         bitset_clear_all(pos_regs);
421                         pi->co->isa->get_allocatable_regs(curr->irn, pi->co->cls, pos_regs);
422                         bitset_foreach(pos_regs, xx.c) {
423                                 DBG((dbg, LEVEL_2, "Adding %n %d\n", curr->irn, xx.c));
424                                 obstack_grow(&pi->ob, &xx, sizeof(xx));
425                                 pi->x_dim++;            /* one x variable for each node and color */
426                         }
427                 }
428 }
429
430 /**
431  * Checks if all nodes in living are live_out in block block.
432  */
433 static INLINE int all_live_in(ir_node *block, pset *living) {
434         ir_node *n;
435         for (n = pset_first(living); n; n = pset_next(living))
436                 if (!is_live_in(block, n)) {
437                         pset_break(living);
438                         return 0;
439                 }
440         return 1;
441 }
442
443 /**
444  * Finds cliques in the interference graph, considering only nodes
445  * for which the color pi->curr_color is possible. Finds only 'maximal-cliques',
446  * viz cliques which are not conatained in another one.
447  * This is used for the matrix B.
448  */
449 static void pi_clique_finder(ir_node *block, void *env) {
450         problem_instance_t *pi = env;
451         enum phase_t {growing, shrinking} phase = growing;
452         struct list_head *head = &get_ra_block_info(block)->border_head;
453         border_t *b;
454         pset *living = pset_new_ptr(SLOTS_LIVING);
455
456         list_for_each_entry_reverse(border_t, b, head, list) {
457                 const ir_node *irn = b->irn;
458
459                 if (b->is_def) {
460                         DBG((dbg, LEVEL_2, "Def %n\n", irn));
461                         pset_insert_ptr(living, irn);
462                         phase = growing;
463                 } else { /* is_use */
464                         DBG((dbg, LEVEL_2, "Use %n\n", irn));
465
466                         /* before shrinking the set, store the current 'maximum' clique;
467                          * do NOT if clique is a single node
468                          * do NOT if all values are live_in (in this case they were contained in a live-out clique elsewhere) */
469                         if (phase == growing && pset_count(living) >= 2 && !all_live_in(block, living)) {
470                                 ir_node *n;
471                                 for (n = pset_first(living); n; n = pset_next(living)) {
472                                         int pos = pi_get_pos(pi, get_irn_graph_nr(n), pi->curr_color);
473                                         matrix_set(pi->B, pi->curr_row, pos, 1);
474                                         DBG((dbg, LEVEL_2, "B[%d, %d] := %d\n", pi->curr_row, pos, 1));
475                                 }
476                                 pi->curr_row++;
477                         }
478                         pset_remove_ptr(living, irn);
479                         phase = shrinking;
480                 }
481         }
482
483         del_pset(living);
484 }
485
486 /**
487  * Generate the initial problem matrices and vectors.
488  */
489 static problem_instance_t *new_pi(const copy_opt_t *co) {
490         DBG((dbg, LEVEL_1, "Generating new instance...\n"));
491         problem_instance_t *pi = calloc(1, sizeof(*pi));
492         pi->co = co;
493         pi->num2pos = new_set(set_cmp_num2pos, SLOTS_NUM2POS);
494         pi->bigM = 1;
495
496         /* Vector x
497          * one entry per node and possible color */
498         obstack_init(&pi->ob);
499         dom_tree_walk_irg(co->irg, pi_collect_x_names, NULL, pi);
500         pi->x = obstack_finish(&pi->ob);
501
502         /* Matrix Q
503          * weights for the 'same-color-optimization' target */
504         {
505                 unit_t *curr;
506                 pi->Q = new_matrix(pi->x_dim, pi->x_dim);
507
508                 list_for_each_entry(unit_t, curr, &co->units, units) {
509                         const ir_node *root, *arg;
510                         int rootnr, argnr;
511                         unsigned rootpos, argpos;
512                         int i;
513
514                         root = curr->nodes[0];
515                         rootnr = get_irn_graph_nr(root);
516                         rootpos = pi_get_first_pos(pi, rootnr);
517                         for (i = 1; i < curr->node_count; ++i) {
518                                 int weight = -get_weight(root, arg);
519                                 arg = curr->nodes[i];
520                                 argnr = get_irn_graph_nr(arg);
521                                 argpos = pi_get_first_pos(pi, argnr);
522
523                                 DBG((dbg, LEVEL_2, "Q[%n, %n] := %d\n", root, arg, weight));
524                                 /* for all colors root and arg have in common, set the weight for
525                                  * this pair in the objective function matrix Q */
526                                 while (rootpos < pi->x_dim && argpos < pi->x_dim &&
527                                                 pi->x[rootpos].n == rootnr && pi->x[argpos].n == argnr) {
528                                         if (pi->x[rootpos].c < pi->x[argpos].c)
529                                                 ++rootpos;
530                                         else if (pi->x[rootpos].c > pi->x[argpos].c)
531                                                 ++argpos;
532                                         else {
533                                                 matrix_set(pi->Q, rootpos++, argpos++, weight);
534
535                                                 if (weight < pi->minQij) {
536                                                         DBG((dbg, LEVEL_2, "minQij = %d\n", weight));
537                                                         pi->minQij = weight;
538                                                 }
539                                                 if (weight > pi->maxQij) {
540                                                         DBG((dbg, LEVEL_2, "maxQij = %d\n", weight));
541                                                         pi->maxQij = weight;
542                                                 }
543                                         }
544                                 }
545                         }
546                 }
547         }
548
549         /* Matrix A
550          * knapsack constraint for each node */
551         {
552                 int row = 0, col = 0;
553                 pi->A = new_matrix(pi->A_dim, pi->x_dim);
554                 while (col < pi->x_dim) {
555                         int curr_n = pi->x[col].n;
556                         while (col < pi->x_dim && pi->x[col].n == curr_n) {
557                                 DBG((dbg, LEVEL_2, "A[%d, %d] := %d\n", row, col, 1));
558                                 matrix_set(pi->A, row, col++, 1);
559                         }
560                         ++row;
561                 }
562                 assert(row == pi->A_dim);
563         }
564
565         /* Matrix B
566          * interference constraints using exactly those cliques not contained in others. */
567         {
568                 int color, expected_clipques = pi->A_dim/4 * pi->co->cls->n_regs;
569                 pi->B = new_matrix(expected_clipques, pi->x_dim);
570                 for (color = 0; color < pi->co->cls->n_regs; ++color) {
571                         pi->curr_color = color;
572                         dom_tree_walk_irg(pi->co->irg, pi_clique_finder, NULL, pi);
573                 }
574                 pi->B_dim = matrix_get_rowcount(pi->B);
575         }
576
577         return pi;
578 }
579
580 /**
581  * clean the problem instance
582  */
583 static void free_pi(problem_instance_t *pi) {
584         DBG((dbg, LEVEL_1, "Generating new instance...\n"));
585         del_matrix(pi->Q);
586         del_matrix(pi->A);
587         del_matrix(pi->B);
588         del_set(pi->num2pos);
589         obstack_free(&pi->ob, NULL);
590         free(pi);
591 }
592
593 void co_ilp_opt(copy_opt_t *co) {
594         dbg = firm_dbg_register("ir.be.copyoptilp");
595         firm_dbg_set_mask(dbg, DEBUG_LVL);
596         if (!strcmp(co->name, DEBUG_IRG))
597                 firm_dbg_set_mask(dbg, -1);
598
599         problem_instance_t *pi = new_pi(co);
600         DBG((dbg, 0, "\t\t\t %5d %5d %5d\n", pi->x_dim, pi->A_dim, pi->B_dim));
601
602         if (pi->x_dim > 0) {
603 #ifdef DUMP_MATRICES
604         pi_dump_matrices(pi);
605 #endif
606
607 #ifdef DUMP_MILP
608         pi_dump_milp(pi);
609 #endif
610
611 #ifdef DO_SOLVE
612         pi_dump_start_sol(pi);
613         pi_solve_ilp(pi);
614         pi_apply_solution(pi);
615 #endif
616
617 #ifdef DELETE_FILES
618         pi_delete_files(pi);
619 #endif
620         }
621         free_pi(pi);
622 }