ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
place_qpsolver.c
Go to the documentation of this file.
1/*===================================================================*/
2//
3// place_qpsolver.c
4//
5// Philip Chong
6// pchong@cadence.com
7//
8/*===================================================================*/
9
10#include <assert.h>
11#include <math.h>
12#include <stdio.h>
13#include <stdlib.h>
14
15#include "place_qpsolver.h"
16
18
19
20#undef QPS_DEBUG
21
22#define QPS_TOL 1.0e-3
23#define QPS_EPS (QPS_TOL * QPS_TOL)
24
25#define QPS_MAX_TOL 0.1
26#define QPS_LOOP_TOL 1.0e-3
27
28#define QPS_RELAX_ITER 180
29#define QPS_MAX_ITER 200
30#define QPS_STEPSIZE_RETRIES 2
31#define QPS_MINSTEP 1.0e-6
32#define QPS_DEC_CHANGE 0.01
33
34#define QPS_PRECON
35#define QPS_PRECON_EPS 1.0e-9
36
37#undef QPS_HOIST
38
39#if defined(QPS_DEBUG)
40#define QPS_DEBUG_FILE "/tmp/qps_debug.log"
41#endif
42
43#if 0
44 /* ii is an array [0..p->num_cells-1] of indices from cells of original
45 problem to modified problem variables. If ii[k] >= 0, cell is an
46 independent cell; ii[k], ii[k]+1 are the indices of the corresponding
47 variables for the modified problem. If ii[k] == -1, cell is a fixed
48 cell. If ii[k] <= -2, cell is a dependent cell; -(ii[k]+2) is the index
49 of the corresponding COG constraint. */
50int *ii;
51
52 /* gt is an array [0..p->cog_num-1] of indices from COG constraints to
53 locations in the gl array (in qps_problem_t). gt[k] is the offset into
54 gl where the kth constraint begins. */
55int *gt;
56
57 /* n is the number of variables in the modified problem. n should be twice
58 the number of independent cells. */
59int n;
60
61qps_float_t *cp; /* current location during CG iteration */
62qps_float_t f; /* value of cost function at p */
63
64#endif
65
66/**********************************************************************/
67
68static void
69qps_settp(qps_problem_t * p)
70{
71 /* Fill in the p->priv_tp array with the current locations of all cells
72 (independent, dependent and fixed). */
73
74 int i;
75 int t, u;
76 int pr;
77 qps_float_t rx, ry;
78 qps_float_t ta;
79
80 int *ii = p->priv_ii;
81 qps_float_t *tp = p->priv_tp;
82 qps_float_t *cp = p->priv_cp;
83
84 /* do independent and fixed cells first */
85 for (i = p->num_cells; i--;) {
86 t = ii[i];
87 if (t >= 0) { /* indep cell */
88 tp[i * 2] = cp[t];
89 tp[i * 2 + 1] = cp[t + 1];
90 }
91 else if (t == -1) { /* fixed cell */
92 tp[i * 2] = p->x[i];
93 tp[i * 2 + 1] = p->y[i];
94 }
95 }
96 /* now do dependent cells */
97 for (i = p->num_cells; i--;) {
98 if (ii[i] < -1) {
99 t = -(ii[i] + 2); /* index of COG constraint */
100 ta = 0.0;
101 rx = 0.0;
102 ry = 0.0;
103 pr = p->priv_gt[t];
104 while ((u = p->cog_list[pr++]) >= 0) {
105 ta += p->area[u];
106 if (u != i) {
107 rx -= p->area[u] * tp[u * 2];
108 ry -= p->area[u] * tp[u * 2 + 1];
109 }
110 }
111 rx += p->cog_x[t] * ta;
112 ry += p->cog_y[t] * ta;
113 tp[i * 2] = rx / p->area[i];
114 tp[i * 2 + 1] = ry / p->area[i];
115 }
116 }
117
118#if (QPS_DEBUG > 5)
119 fprintf(p->priv_fp, "### qps_settp()\n");
120 for (i = 0; i < p->num_cells; i++) {
121 fprintf(p->priv_fp, "%f %f\n", tp[i * 2], tp[i * 2 + 1]);
122 }
123#endif
124}
125
126/**********************************************************************/
127
128static qps_float_t
129qps_func(qps_problem_t * p)
130{
131 /* Return f(p). qps_settp() should have already been called before
132 entering here */
133
134 int j, k;
135 int pr;
136 qps_float_t jx, jy, tx, ty;
137 qps_float_t f;
138 qps_float_t w;
139
140#if !defined(QPS_HOIST)
141 int i;
142 int st;
143 qps_float_t kx, ky, sx, sy;
144 qps_float_t t;
145#endif
146
147 qps_float_t *tp = p->priv_tp;
148
149 f = 0.0;
150 pr = 0;
151 for (j = 0; j < p->num_cells; j++) {
152 jx = tp[j * 2];
153 jy = tp[j * 2 + 1];
154 while ((k = p->priv_cc[pr]) >= 0) {
155 w = p->priv_cw[pr];
156 tx = tp[k * 2] - jx;
157 ty = tp[k * 2 + 1] - jy;
158 f += w * (tx * tx + ty * ty);
159 pr++;
160 }
161 pr++;
162 }
163 p->f = f;
164
165#if !defined(QPS_HOIST)
166 /* loop penalties */
167 pr = 0;
168 for (i = 0; i < p->loop_num; i++) {
169 t = 0.0;
170 j = st = p->loop_list[pr++];
171 jx = sx = tp[j * 2];
172 jy = sy = tp[j * 2 + 1];
173 while ((k = p->loop_list[pr]) >= 0) {
174 kx = tp[k * 2];
175 ky = tp[k * 2 + 1];
176 tx = jx - kx;
177 ty = jy - ky;
178 t += tx * tx + ty * ty;
179 j = k;
180 jx = kx;
181 jy = ky;
182 pr++;
183 }
184 tx = jx - sx;
185 ty = jy - sy;
186 t += tx * tx + ty * ty;
187 t -= p->loop_max[i];
188#if (QPS_DEBUG > 5)
189 fprintf(p->priv_fp, "### qps_penalty() %d %f %f\n",
190 i, p->loop_max[i], t);
191#endif
192 p->priv_lt[i] = t;
193 f += p->loop_penalty[i] * t;
194 pr++;
195 }
196#endif /* QPS_HOIST */
197
198 if (p->max_enable) {
199 for (j = p->num_cells; j--;) {
200 f += p->priv_mxl[j] * (-tp[j * 2]);
201 f += p->priv_mxh[j] * (tp[j * 2] - p->max_x);
202 f += p->priv_myl[j] * (-tp[j * 2 + 1]);
203 f += p->priv_myh[j] * (tp[j * 2 + 1] - p->max_y);
204 }
205 }
206
207#if (QPS_DEBUG > 5)
208 fprintf(p->priv_fp, "### qps_func() %f %f\n", f, p->f);
209#endif
210 return f;
211}
212
213/**********************************************************************/
214
215static void
216qps_dfunc(qps_problem_t * p, qps_float_t * d)
217{
218 /* Set d to grad f(p). First computes partial derivatives wrt all cells
219 then finds gradient wrt only the independent cells. qps_settp() should
220 have already been called before entering here */
221
222 int i, j, k;
223 int pr = 0;
224 qps_float_t jx, jy, kx, ky, tx, ty;
225 int ji, ki;
226 qps_float_t w;
227
228#if !defined(QPS_HOIST)
229 qps_float_t sx, sy;
230 int st;
231#endif
232
233 qps_float_t *tp = p->priv_tp;
234 qps_float_t *tp2 = p->priv_tp2;
235
236 /* compute partials and store in tp2 */
237 for (i = p->num_cells; i--;) {
238 tp2[i * 2] = 0.0;
239 tp2[i * 2 + 1] = 0.0;
240 }
241 for (j = 0; j < p->num_cells; j++) {
242 jx = tp[j * 2];
243 jy = tp[j * 2 + 1];
244 while ((k = p->priv_cc[pr]) >= 0) {
245 w = 2.0 * p->priv_cw[pr];
246 kx = tp[k * 2];
247 ky = tp[k * 2 + 1];
248 tx = w * (jx - kx);
249 ty = w * (jy - ky);
250 tp2[j * 2] += tx;
251 tp2[k * 2] -= tx;
252 tp2[j * 2 + 1] += ty;
253 tp2[k * 2 + 1] -= ty;
254 pr++;
255 }
256 pr++;
257 }
258
259#if !defined(QPS_HOIST)
260 /* loop penalties */
261 pr = 0;
262 for (i = 0; i < p->loop_num; i++) {
263 j = st = p->loop_list[pr++];
264 jx = sx = tp[j * 2];
265 jy = sy = tp[j * 2 + 1];
266 w = 2.0 * p->loop_penalty[i];
267 while ((k = p->loop_list[pr]) >= 0) {
268 kx = tp[k * 2];
269 ky = tp[k * 2 + 1];
270 tx = w * (jx - kx);
271 ty = w * (jy - ky);
272 tp2[j * 2] += tx;
273 tp2[k * 2] -= tx;
274 tp2[j * 2 + 1] += ty;
275 tp2[k * 2 + 1] -= ty;
276 j = k;
277 jx = kx;
278 jy = ky;
279 pr++;
280 }
281 tx = w * (jx - sx);
282 ty = w * (jy - sy);
283 tp2[j * 2] += tx;
284 tp2[st * 2] -= tx;
285 tp2[j * 2 + 1] += ty;
286 tp2[st * 2 + 1] -= ty;
287 pr++;
288 }
289#endif /* QPS_HOIST */
290
291 if (p->max_enable) {
292 for (j = p->num_cells; j--;) {
293 tp2[j * 2] += p->priv_mxh[j] - p->priv_mxl[j];
294 tp2[j * 2 + 1] += p->priv_myh[j] - p->priv_myl[j];
295 }
296 }
297
298#if (QPS_DEBUG > 5)
299 fprintf(p->priv_fp, "### qps_dfunc() partials\n");
300 for (j = 0; j < p->num_cells; j++) {
301 fprintf(p->priv_fp, "%f %f\n", tp2[j * 2], tp2[j * 2 + 1]);
302 }
303#endif
304
305 /* translate partials to independent variables */
306 for (j = p->priv_n; j--;) {
307 d[j] = 0.0;
308 }
309 for (j = p->num_cells; j--;) {
310 ji = p->priv_ii[j];
311 if (ji >= 0) { /* indep var */
312 d[ji] += tp2[j * 2];
313 d[ji + 1] += tp2[j * 2 + 1];
314 }
315 else if (ji < -1) { /* dependent variable */
316 ji = -(ji + 2); /* get COG index */
317 pr = p->priv_gt[ji];
318 while ((k = p->cog_list[pr]) >= 0) {
319 ki = p->priv_ii[k];
320 if (ki >= 0) {
321 w = p->priv_gw[pr];
322#if (QPS_DEBUG > 0)
323 assert(fabs(w - p->area[k] / p->area[j]) < 1.0e-6);
324#endif
325 d[ki] -= tp2[j * 2] * w;
326 d[ki + 1] -= tp2[j * 2 + 1] * w;
327 }
328 pr++;
329 }
330 }
331 }
332
333#if (QPS_DEBUG > 5)
334 fprintf(p->priv_fp, "### qps_dfunc() gradient\n");
335 for (j = 0; j < p->priv_n; j++) {
336 fprintf(p->priv_fp, "%f\n", d[j]);
337 }
338#endif
339}
340
341/**********************************************************************/
342
343static void
344qps_linmin(qps_problem_t * p, qps_float_t dgg, qps_float_t * h)
345{
346 /* Perform line minimization. p->priv_cp is the current location, h is
347 direction of the gradient. Updates p->priv_cp to line minimal position
348 based on formulas from "Handbook of Applied Optimization", Pardalos and
349 Resende, eds., Oxford Univ. Press, 2002. qps_settp() should have
350 already been called before entering here. Since p->priv_cp is changed,
351 p->priv_tp array becomes invalid following this routine. */
352
353 int i, j, k;
354 int pr;
355 int ji, ki;
356 qps_float_t jx, jy, kx, ky;
357 qps_float_t f = 0.0;
358 qps_float_t w;
359
360#if !defined(QPS_HOIST)
361 int st;
362 qps_float_t sx, sy, tx, ty;
363 qps_float_t t;
364#endif
365
366 qps_float_t *tp = p->priv_tp;
367
368 /* translate h vector to partials over all variables and store in tp */
369 for (i = p->num_cells; i--;) {
370 tp[i * 2] = 0.0;
371 tp[i * 2 + 1] = 0.0;
372 }
373 for (j = p->num_cells; j--;) {
374 ji = p->priv_ii[j];
375 if (ji >= 0) { /* indep cell */
376 tp[j * 2] = h[ji];
377 tp[j * 2 + 1] = h[ji + 1];
378 }
379 else if (ji < -1) { /* dep cell */
380 ji = -(ji + 2); /* get COG index */
381 pr = p->priv_gt[ji];
382 while ((k = p->cog_list[pr]) >= 0) {
383 ki = p->priv_ii[k];
384 if (ki >= 0) {
385 w = p->priv_gw[pr];
386#if (QPS_DEBUG > 0)
387 assert(fabs(w - p->area[k] / p->area[j]) < 1.0e-6);
388#endif
389 tp[j * 2] -= h[ki] * w;
390 tp[j * 2 + 1] -= h[ki + 1] * w;
391 }
392 pr++;
393 }
394 }
395 }
396
397 /* take product x^T Z^T C Z x */
398 pr = 0;
399 for (j = 0; j < p->num_cells; j++) {
400 jx = tp[j * 2];
401 jy = tp[j * 2 + 1];
402 while ((k = p->priv_cc[pr]) >= 0) {
403 w = p->priv_cw[pr];
404 kx = tp[k * 2] - jx;
405 ky = tp[k * 2 + 1] - jy;
406 f += w * (kx * kx + ky * ky);
407 pr++;
408 }
409 pr++;
410 }
411
412#if !defined(QPS_HOIST)
413 /* add loop penalties */
414 pr = 0;
415 for (i = 0; i < p->loop_num; i++) {
416 t = 0.0;
417 j = st = p->loop_list[pr++];
418 jx = sx = tp[j * 2];
419 jy = sy = tp[j * 2 + 1];
420 while ((k = p->loop_list[pr]) >= 0) {
421 kx = tp[k * 2];
422 ky = tp[k * 2 + 1];
423 tx = jx - kx;
424 ty = jy - ky;
425 t += tx * tx + ty * ty;
426 j = k;
427 jx = kx;
428 jy = ky;
429 pr++;
430 }
431 tx = jx - sx;
432 ty = jy - sy;
433 t += tx * tx + ty * ty;
434 f += p->loop_penalty[i] * t;
435 pr++;
436 }
437#endif /* QPS_HOIST */
438
439#if (QPS_DEBUG > 0)
440 assert(f);
441#endif
442
443 /* compute step size */
444 f = (dgg / f) / 2.0;
445 for (j = p->priv_n; j--;) {
446 p->priv_cp[j] += f * h[j];
447 }
448#if (QPS_DEBUG > 5)
449 fprintf(p->priv_fp, "### qps_linmin() step %f\n", f);
450 for (j = 0; j < p->priv_n; j++) {
451 fprintf(p->priv_fp, "%f\n", p->priv_cp[j]);
452 }
453#endif
454}
455
456/**********************************************************************/
457
458static void
459qps_cgmin(qps_problem_t * p)
460{
461 /* Perform CG minimization. Mostly from "Numerical Recipes", Press et al.,
462 Cambridge Univ. Press, 1992, with some changes to help performance in
463 our restricted problem domain. */
464
465 qps_float_t fp, gg, dgg, gam;
466 qps_float_t t;
467 int i, j;
468
469 int n = p->priv_n;
470 qps_float_t *g = p->priv_g;
471 qps_float_t *h = p->priv_h;
472 qps_float_t *xi = p->priv_xi;
473
474 qps_settp(p);
475 fp = qps_func(p);
476 qps_dfunc(p, g);
477
478 dgg = 0.0;
479 for (j = n; j--;) {
480 g[j] = -g[j];
481 h[j] = g[j];
482#if defined(QPS_PRECON)
483 h[j] *= p->priv_pcgt[j];
484#endif
485 dgg += g[j] * h[j];
486 }
487
488 for (i = 0; i < 2 * n; i++) {
489
490#if (QPS_DEBUG > 5)
491 fprintf(p->priv_fp, "### qps_cgmin() top\n");
492 for (j = 0; j < p->priv_n; j++) {
493 fprintf(p->priv_fp, "%f\n", p->priv_cp[j]);
494 }
495#endif
496
497 if (dgg == 0.0) {
498 break;
499 }
500 qps_linmin(p, dgg, h);
501 qps_settp(p);
502 p->priv_f = qps_func(p);
503 if (fabs((p->priv_f) - fp) <=
504 (fabs(p->priv_f) + fabs(fp) + QPS_EPS) * QPS_TOL / 2.0) {
505 break;
506 }
507 fp = p->priv_f;
508 qps_dfunc(p, xi);
509 gg = dgg;
510 dgg = 0.0;
511 for (j = n; j--;) {
512 t = xi[j] * xi[j];
513#if defined(QPS_PRECON)
514 t *= p->priv_pcgt[j];
515#endif
516 dgg += t;
517 }
518 gam = dgg / gg;
519 for (j = n; j--;) {
520 g[j] = -xi[j];
521 t = g[j];
522#if defined(QPS_PRECON)
523 t *= p->priv_pcgt[j];
524#endif
525 h[j] = t + gam * h[j];
526 }
527 }
528#if (QPS_DEBUG > 0)
529 fprintf(p->priv_fp, "### CG ITERS=%d %d %d\n", i, p->cog_num, p->loop_num);
530#endif
531 if (i == 2 * n) {
532 fprintf(stderr, "### Too many iterations in qps_cgmin()\n");
533#if defined(QPS_DEBUG)
534 fprintf(p->priv_fp, "### Too many iterations in qps_cgmin()\n");
535#endif
536 }
537}
538
539/**********************************************************************/
540
541void
543{
544 int i, j;
545 int pr, pw;
546
547#if defined(QPS_DEBUG)
548 p->priv_fp = fopen(QPS_DEBUG_FILE, "a");
549 assert(p->priv_fp);
550#endif
551
552#if (QPS_DEBUG > 5)
553 fprintf(p->priv_fp, "### n=%d gn=%d ln=%d\n", p->num_cells, p->cog_num,
554 p->loop_num);
555 pr = 0;
556 fprintf(p->priv_fp, "### (c w) values\n");
557 for (i = 0; i < p->num_cells; i++) {
558 fprintf(p->priv_fp, "net %d: ", i);
559 while (p->connect[pr] >= 0) {
560 fprintf(p->priv_fp, "(%d %f) ", p->connect[pr], p->edge_weight[pr]);
561 pr++;
562 }
563 fprintf(p->priv_fp, "(-1 -1.0)\n");
564 pr++;
565 }
566 fprintf(p->priv_fp, "### (x y f) values\n");
567 for (i = 0; i < p->num_cells; i++) {
568 fprintf(p->priv_fp, "cell %d: (%f %f %d)\n", i, p->x[i], p->y[i],
569 p->fixed[i]);
570 }
571#if 0
572 if (p->cog_num) {
573 fprintf(p->priv_fp, "### ga values\n");
574 for (i = 0; i < p->num_cells; i++) {
575 fprintf(p->priv_fp, "cell %d: (%f)\n", i, p->area[i]);
576 }
577 }
578 pr = 0;
579 fprintf(p->priv_fp, "### gl values\n");
580 for (i = 0; i < p->cog_num; i++) {
581 fprintf(p->priv_fp, "cog %d: ", i);
582 while (p->cog_list[pr] >= 0) {
583 fprintf(p->priv_fp, "%d ", p->cog_list[pr]);
584 pr++;
585 }
586 fprintf(p->priv_fp, "-1\n");
587 pr++;
588 }
589 fprintf(p->priv_fp, "### (gx gy) values\n");
590 for (i = 0; i < p->cog_num; i++) {
591 fprintf(p->priv_fp, "cog %d: (%f %f)\n", i, p->cog_x[i], p->cog_y[i]);
592 }
593#endif
594#endif /* QPS_DEBUG */
595
596 p->priv_ii = (int *)malloc(p->num_cells * sizeof(int));
597 assert(p->priv_ii);
598
599 p->max_enable = 0;
600
601 p->priv_fopt = 0.0;
602
603 /* canonify c and w */
604 pr = pw = 0;
605 for (i = 0; i < p->num_cells; i++) {
606 while ((j = p->connect[pr]) >= 0) {
607 if (j > i) {
608 pw++;
609 }
610 pr++;
611 }
612 pw++;
613 pr++;
614 }
615 p->priv_cc = (int *)malloc(pw * sizeof(int));
616 assert(p->priv_cc);
617 p->priv_cr = (int *)malloc(p->num_cells * sizeof(int));
618 assert(p->priv_cr);
619 p->priv_cw = (qps_float_t*)malloc(pw * sizeof(qps_float_t));
620 assert(p->priv_cw);
621 p->priv_ct = (qps_float_t*)malloc(pw * sizeof(qps_float_t));
622 assert(p->priv_ct);
623 p->priv_cm = pw;
624 pr = pw = 0;
625 for (i = 0; i < p->num_cells; i++) {
626 p->priv_cr[i] = pw;
627 while ((j = p->connect[pr]) >= 0) {
628 if (j > i) {
629 p->priv_cc[pw] = p->connect[pr];
630 p->priv_ct[pw] = p->edge_weight[pr];
631 pw++;
632 }
633 pr++;
634 }
635 p->priv_cc[pw] = -1;
636 p->priv_ct[pw] = -1.0;
637 pw++;
638 pr++;
639 }
640 assert(pw == p->priv_cm);
641
642 /* temp arrays for function eval */
643 p->priv_tp = (qps_float_t *) malloc(4 * p->num_cells * sizeof(qps_float_t));
644 assert(p->priv_tp);
645 p->priv_tp2 = p->priv_tp + 2 * p->num_cells;
646}
647
648/**********************************************************************/
649
650static qps_float_t
651qps_estopt(qps_problem_t * p)
652{
653 int i, j, cell;
654 qps_float_t r;
655 qps_float_t *t1, *t2;
656 qps_float_t t;
657
658 if (p->max_enable) {
659 r = 0.0;
660 t1 = (qps_float_t *) malloc(2 * p->num_cells * sizeof(qps_float_t));
661#if (QPS_DEBUG > 0)
662 assert(t1);
663#endif
664 for (i = 2 * p->num_cells; i--;) {
665 t1[i] = 0.0;
666 }
667 j = 0;
668 for (i = 0; i < p->cog_num; i++) {
669 while ((cell = p->cog_list[j]) >= 0) {
670 t1[cell * 2] = p->cog_x[i];
671 t1[cell * 2 + 1] = p->cog_y[i];
672 j++;
673 }
674 j++;
675 }
676 t2 = p->priv_tp;
677 p->priv_tp = t1;
678 r = qps_func(p);
679 p->priv_tp = t2;
680 free(t1);
681 t = (p->max_x * p->max_x + p->max_y * p->max_y);
682 t *= p->num_cells;
683 for (i = p->num_cells; i--;) {
684 if (p->fixed[i]) {
685 r += t;
686 }
687 }
688 }
689 else {
690 r = p->priv_f;
691 }
692 if (p->loop_num) {
693 /* FIXME hacky */
694 r *= 8.0;
695 }
696 return r;
697}
698
699/**********************************************************************/
700
701static void
702qps_solve_inner(qps_problem_t * p)
703{
704 int i;
705 qps_float_t t;
706 qps_float_t z;
707 qps_float_t pm1, pm2, tp;
708 qps_float_t *tw;
709#if defined(QPS_HOIST)
710 int j, k;
711 qps_float_t jx, jy, kx, ky, sx, sy, tx, ty;
712 int pr, st;
713#endif
714
715 tw = p->priv_cw;
716#if defined(QPS_HOIST)
717 if (!p->loop_num) {
718 p->priv_cw = p->priv_ct;
719 }
720 else {
721 for(i=p->priv_cm; i--;) {
722 p->priv_cw[i] = p->priv_ct[i];
723 }
724 /* augment with loop penalties */
725 pr = 0;
726 for (i = 0; i < p->loop_num; i++) {
727 while ((j = p->priv_la[pr++]) != -1) {
728 if (j >= 0) {
729 p->priv_cw[j] += p->loop_penalty[i];
730 }
731 }
732 pr++;
733 }
734 }
735#else /* !QPS_HOIST */
736 p->priv_cw = p->priv_ct;
737#endif /* QPS_HOIST */
738
739 qps_cgmin(p);
740
741 if (p->max_enable || p->loop_num) {
742 if (p->max_enable == 1 || (p->loop_num && p->loop_k == 0)) {
743 p->priv_eps = 2.0;
744 p->priv_fmax = p->priv_f;
745 p->priv_fprev = p->priv_f;
746 p->priv_fopt = qps_estopt(p);
747 p->priv_pn = 0;
748 p->loop_fail = 0;
749 }
750 else {
751 if (p->priv_f < p->priv_fprev &&
752 (p->priv_fprev - p->priv_f) >
753 QPS_DEC_CHANGE * fabs(p->priv_fprev)) {
754 if (p->priv_pn++ >= QPS_STEPSIZE_RETRIES) {
755 p->priv_eps /= 2.0;
756 p->priv_pn = 0;
757 }
758 }
759 p->priv_fprev = p->priv_f;
760 if (p->priv_fmax < p->priv_f) {
761 p->priv_fmax = p->priv_f;
762 }
763 if (p->priv_f >= p->priv_fopt) {
764 p->priv_fopt = p->priv_fmax * 2.0;
765 p->loop_fail |= 2;
766#if (QPS_DEBUG > 0)
767 fprintf(p->priv_fp, "### warning: changing fopt\n");
768#endif
769 }
770 }
771#if (QPS_DEBUG > 0)
772 fprintf(p->priv_fp, "### max_stat %.2e %.2e %.2e %.2e\n",
773 p->priv_f, p->priv_eps, p->priv_fmax, p->priv_fopt);
774 fflush(p->priv_fp);
775#endif
776 }
777
778 p->loop_done = 1;
779 if (p->loop_num) {
780#if (QPS_DEBUG > 0)
781 fprintf(p->priv_fp, "### begin_update %d\n", p->loop_k);
782#endif
783 p->loop_k++;
784
785#if defined(QPS_HOIST)
786 /* calc loop penalties */
787 pr = 0;
788 for (i = 0; i < p->loop_num; i++) {
789 t = 0.0;
790 j = st = p->loop_list[pr++];
791 jx = sx = p->priv_tp[j * 2];
792 jy = sy = p->priv_tp[j * 2 + 1];
793 while ((k = p->loop_list[pr]) >= 0) {
794 kx = p->priv_tp[k * 2];
795 ky = p->priv_tp[k * 2 + 1];
796 tx = jx - kx;
797 ty = jy - ky;
798 t += tx * tx + ty * ty;
799 j = k;
800 jx = kx;
801 jy = ky;
802 pr++;
803 }
804 tx = jx - sx;
805 ty = jy - sy;
806 t += tx * tx + ty * ty;
807 p->priv_lt[i] = t - p->loop_max[i];
808 pr++;
809 }
810#endif /* QPS_HOIST */
811
812 /* check KKT conditions */
813#if (QPS_DEBUG > 1)
814 for (i = p->loop_num; i--;) {
815 if (p->loop_penalty[i] != 0.0) {
816 fprintf(p->priv_fp, "### penalty %d %.2e\n", i, p->loop_penalty[i]);
817 }
818 }
819#endif
820 t = 0.0;
821 for (i = p->loop_num; i--;) {
822 if (p->priv_lt[i] > 0.0 || p->loop_penalty[i] > 0.0) {
823 t += p->priv_lt[i] * p->priv_lt[i];
824 }
825 if (fabs(p->priv_lt[i]) < QPS_LOOP_TOL) {
826#if (QPS_DEBUG > 4)
827 fprintf(p->priv_fp, "### skip %d %f\n", i, p->priv_lt[i]);
828#endif
829 continue;
830 }
831 z = QPS_LOOP_TOL * p->loop_max[i];
832 if (p->priv_lt[i] > z || (p->loop_k < QPS_RELAX_ITER &&
833 p->loop_penalty[i] * p->priv_lt[i] < -z)) {
834 p->loop_done = 0;
835#if (QPS_DEBUG > 1)
836 fprintf(p->priv_fp, "### not_done %d %f %f %f %f\n", i,
837 p->priv_lt[i], z, p->loop_max[i], p->loop_penalty[i]);
838#endif
839 }
840#if (QPS_DEBUG > 5)
841 else {
842 fprintf(p->priv_fp, "### done %d %f %f %f %f\n", i,
843 p->priv_lt[i], z, p->loop_max[i], p->loop_penalty[i]);
844 }
845#endif
846 }
847 /* update penalties */
848 if (!p->loop_done) {
849 t = p->priv_eps * (p->priv_fopt - p->priv_f) / t;
850 tp = 0.0;
851 for (i = p->loop_num; i--;) {
852 pm1 = p->loop_penalty[i];
853#if (QPS_DEBUG > 5)
854 fprintf(p->priv_fp, "### update %d %.2e %.2e %.2e %.2e %.2e\n", i,
855 t, p->priv_lt[i], t * p->priv_lt[i], pm1, p->loop_max[i]);
856#endif
857 p->loop_penalty[i] += t * p->priv_lt[i];
858 if (p->loop_penalty[i] < 0.0) {
859 p->loop_penalty[i] = 0.0;
860 }
861 pm2 = p->loop_penalty[i];
862 tp += fabs(pm1 - pm2);
863 }
864#if (QPS_DEBUG > 4)
865 fprintf(p->priv_fp, "### penalty mag %f\n", tp);
866#endif
867 }
868 }
869
870 p->max_done = 1;
871 if (p->max_enable) {
872#if (QPS_DEBUG > 4)
873 fprintf(p->priv_fp, "### begin_max_update %d\n", p->max_enable);
874#endif
875 t = 0.0;
876 for (i = p->num_cells; i--;) {
877 z = -(p->x[i]);
878 t += z * z;
879 if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER &&
880 p->priv_mxl[i] * z < -QPS_MAX_TOL)) {
881 p->max_done = 0;
882#if (QPS_DEBUG > 4)
883 fprintf(p->priv_fp, "### nxl %d %f %f\n", i, z, p->priv_mxl[i]);
884#endif
885 }
886 z = (p->x[i] - p->max_x);
887 t += z * z;
888 if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER &&
889 p->priv_mxh[i] * z < -QPS_MAX_TOL)) {
890 p->max_done = 0;
891#if (QPS_DEBUG > 4)
892 fprintf(p->priv_fp, "### nxh %d %f %f\n", i, z, p->priv_mxh[i]);
893#endif
894 }
895 z = -(p->y[i]);
896 t += z * z;
897 if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER &&
898 p->priv_myl[i] * z < -QPS_MAX_TOL)) {
899 p->max_done = 0;
900#if (QPS_DEBUG > 4)
901 fprintf(p->priv_fp, "### nyl %d %f %f\n", i, z, p->priv_myl[i]);
902#endif
903 }
904 z = (p->y[i] - p->max_y);
905 t += z * z;
906 if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER &&
907 p->priv_myh[i] * z < -QPS_MAX_TOL)) {
908 p->max_done = 0;
909#if (QPS_DEBUG > 4)
910 fprintf(p->priv_fp, "### nyh %d %f %f\n", i, z, p->priv_myh[i]);
911#endif
912 }
913 }
914#if (QPS_DEBUG > 4)
915 fprintf(p->priv_fp, "### max_done %d %f\n", p->max_done, t);
916#endif
917 if (!p->max_done) {
918 t = p->priv_eps * (p->priv_fopt - p->priv_f) / t;
919 tp = 0.0;
920 for (i = p->num_cells; i--;) {
921 z = -(p->x[i]);
922 pm1 = p->priv_mxl[i];
923 p->priv_mxl[i] += t * z;
924 if (p->priv_mxl[i] < 0.0) {
925 p->priv_mxl[i] = 0.0;
926 }
927 pm2 = p->priv_mxl[i];
928 tp += fabs(pm1 - pm2);
929
930 z = (p->x[i] - p->max_x);
931 pm1 = p->priv_mxh[i];
932 p->priv_mxh[i] += t * z;
933 if (p->priv_mxh[i] < 0.0) {
934 p->priv_mxh[i] = 0.0;
935 }
936 pm2 = p->priv_mxh[i];
937 tp += fabs(pm1 - pm2);
938
939 z = -(p->y[i]);
940 pm1 = p->priv_myl[i];
941 p->priv_myl[i] += t * z;
942 if (p->priv_myl[i] < 0.0) {
943 p->priv_myl[i] = 0.0;
944 }
945 pm2 = p->priv_myl[i];
946 tp += fabs(pm1 - pm2);
947
948 z = (p->y[i] - p->max_y);
949 pm1 = p->priv_myh[i];
950 p->priv_myh[i] += t * z;
951 if (p->priv_myh[i] < 0.0) {
952 p->priv_myh[i] = 0.0;
953 }
954 pm2 = p->priv_myh[i];
955 tp += fabs(pm1 - pm2);
956 }
957 }
958#if (QPS_DEBUG > 4)
959 for (i = p->num_cells; i--;) {
960 fprintf(p->priv_fp, "### max_penalty %d %f %f %f %f\n", i,
961 p->priv_mxl[i], p->priv_mxh[i], p->priv_myl[i], p->priv_myh[i]);
962 }
963#endif
964 p->max_enable++;
965 }
966
967 if (p->loop_k >= QPS_MAX_ITER || p->priv_eps < QPS_MINSTEP) {
968 p->loop_fail |= 1;
969 }
970
971 if (p->loop_fail) {
972 p->loop_done = 1;
973 }
974
975 p->priv_cw = tw;
976}
977
978/**********************************************************************/
979
980void
982{
983 int i, j;
984 int pr, pw;
985 qps_float_t bk;
986 int tk;
987
988#if defined(QPS_PRECON)
989 int c;
990 qps_float_t t;
991#endif
992
993#if defined(QPS_HOIST)
994 int k;
995 int st;
996 int m1, m2;
997#endif
998
999 if (p->max_enable) {
1000 p->priv_mxl = (qps_float_t *)
1001 malloc(4 * p->num_cells * sizeof(qps_float_t));
1002 assert(p->priv_mxl);
1003 p->priv_mxh = p->priv_mxl + p->num_cells;
1004 p->priv_myl = p->priv_mxl + 2 * p->num_cells;
1005 p->priv_myh = p->priv_mxl + 3 * p->num_cells;
1006 for (i = 4 * p->num_cells; i--;) {
1007 p->priv_mxl[i] = 0.0;
1008 }
1009 }
1010
1011 /* flag fixed cells with -1 */
1012 for (i = p->num_cells; i--;) {
1013 p->priv_ii[i] = (p->fixed[i]) ? (-1) : (0);
1014 }
1015
1016 /* read gl and set up dependent variables */
1017 if (p->cog_num) {
1018 p->priv_gt = (int *)malloc(p->cog_num * sizeof(int));
1019 assert(p->priv_gt);
1020 p->priv_gm = (qps_float_t*)malloc(p->cog_num * sizeof(qps_float_t));
1021 assert(p->priv_gm);
1022 pr = 0;
1023 for (i = 0; i < p->cog_num; i++) {
1024 tk = -1;
1025 bk = -1.0;
1026 pw = pr;
1027 while ((j = p->cog_list[pr++]) >= 0) {
1028 if (!p->fixed[j]) {
1029 /* use largest entry for numerical stability; see Gordian paper */
1030 if (p->area[j] > bk) {
1031 tk = j;
1032 bk = p->area[j];
1033 }
1034 }
1035 }
1036 assert(bk > 0.0);
1037 /* dependent variables have index=(-2-COG_constraint) */
1038 p->priv_ii[tk] = -2 - i;
1039 p->priv_gt[i] = pw;
1040 p->priv_gm[i] = bk;
1041 }
1042 p->priv_gw = (qps_float_t*)malloc(pr * sizeof(qps_float_t));
1043 assert(p->priv_gw);
1044 pr = 0;
1045 for (i = 0; i < p->cog_num; i++) {
1046 while ((j = p->cog_list[pr]) >= 0) {
1047 p->priv_gw[pr] = p->area[j] / p->priv_gm[i];
1048 pr++;
1049 }
1050 p->priv_gw[pr] = -1.0;
1051 pr++;
1052 }
1053 }
1054
1055 /* set up indexes from independent floating cells to variables */
1056 p->priv_n = 0;
1057 for (i = p->num_cells; i--;) {
1058 if (!p->priv_ii[i]) {
1059 p->priv_ii[i] = 2 * (p->priv_n++);
1060 }
1061 }
1062 p->priv_n *= 2;
1063
1064#if (QPS_DEBUG > 5)
1065 for (i = 0; i < p->num_cells; i++) {
1066 fprintf(p->priv_fp, "### ii %d %d\n", i, p->priv_ii[i]);
1067 }
1068#endif
1069
1070#if defined(QPS_PRECON)
1071 p->priv_pcg = (qps_float_t *) malloc(p->num_cells * sizeof(qps_float_t));
1072 assert(p->priv_pcg);
1073 p->priv_pcgt = (qps_float_t *) malloc(p->priv_n * sizeof(qps_float_t));
1074 assert(p->priv_pcgt);
1075 for (i = p->num_cells; i--;) {
1076 p->priv_pcg[i] = 0.0;
1077 }
1078 pr = 0;
1079 for (i = 0; i < p->num_cells; i++) {
1080 while ((c = p->priv_cc[pr]) >= 0) {
1081 t = p->priv_ct[pr];
1082 p->priv_pcg[i] += t;
1083 p->priv_pcg[c] += t;
1084 pr++;
1085 }
1086 pr++;
1087 }
1088 pr = 0;
1089 for (i = 0; i < p->loop_num; i++) {
1090 t = 2.0 * p->loop_penalty[i];
1091 while ((c = p->loop_list[pr++]) >= 0) {
1092 p->priv_pcg[c] += t;
1093 }
1094 pr++;
1095 }
1096#if (QPS_DEBUG > 6)
1097 for (i = p->num_cells; i--;) {
1098 fprintf(p->priv_fp, "### precon %d %.2e\n", i, p->priv_pcg[i]);
1099 }
1100#endif
1101 for (i = p->priv_n; i--;) {
1102 p->priv_pcgt[i] = 0.0;
1103 }
1104 for (i = 0; i < p->num_cells; i++) {
1105 c = p->priv_ii[i];
1106 if (c >= 0) {
1107 t = p->priv_pcg[i];
1108 p->priv_pcgt[c] += t;
1109 p->priv_pcgt[c + 1] += t;
1110 }
1111#if 0
1112 else if (c < -1) {
1113 pr = p->priv_gt[-(c+2)];
1114 while ((j = p->cog_list[pr++]) >= 0) {
1115 ji = p->priv_ii[j];
1116 if (ji >= 0) {
1117 w = p->area[j] / p->area[i];
1118 t = w * w * p->priv_pcg[i];
1119 p->priv_pcgt[ji] += t;
1120 p->priv_pcgt[ji + 1] += t;
1121 }
1122 }
1123 }
1124#endif
1125 }
1126 for (i = 0; i < p->priv_n; i++) {
1127 t = p->priv_pcgt[i];
1128 if (fabs(t) < QPS_PRECON_EPS || fabs(t) > 1.0/QPS_PRECON_EPS) {
1129 p->priv_pcgt[i] = 1.0;
1130 }
1131 else {
1132 p->priv_pcgt[i] = 1.0 / p->priv_pcgt[i];
1133 }
1134 }
1135#endif
1136
1137 /* allocate variable storage */
1138 p->priv_cp = (qps_float_t *) malloc(4 * p->priv_n * sizeof(qps_float_t));
1139 assert(p->priv_cp);
1140
1141 /* temp arrays for cg */
1142 p->priv_g = p->priv_cp + p->priv_n;
1143 p->priv_h = p->priv_cp + 2 * p->priv_n;
1144 p->priv_xi = p->priv_cp + 3 * p->priv_n;
1145
1146 /* set values */
1147 for (i = p->num_cells; i--;) {
1148 if (p->priv_ii[i] >= 0) {
1149 p->priv_cp[p->priv_ii[i]] = p->x[i];
1150 p->priv_cp[p->priv_ii[i] + 1] = p->y[i];
1151 }
1152 }
1153
1154 if (p->loop_num) {
1155 p->priv_lt = (qps_float_t *) malloc(p->loop_num * sizeof(qps_float_t));
1156 assert(p->priv_lt);
1157#if defined(QPS_HOIST)
1158 pr = 0;
1159 for (i=p->loop_num; i--;) {
1160 while (p->loop_list[pr++] >= 0) {
1161 }
1162 pr++;
1163 }
1164 p->priv_lm = pr;
1165 p->priv_la = (int *) malloc(pr * sizeof(int));
1166 assert(p->priv_la);
1167 pr = 0;
1168 for (i = 0; i < p->loop_num; i++) {
1169 j = st = p->loop_list[pr++];
1170 while ((k = p->loop_list[pr]) >= 0) {
1171 if (j > k) {
1172 m1 = k;
1173 m2 = j;
1174 }
1175 else {
1176 assert(k > j);
1177 m1 = j;
1178 m2 = k;
1179 }
1180 pw = p->priv_cr[m1];
1181 while (p->priv_cc[pw] != m2) {
1182/* assert(p->priv_cc[pw] >= 0); */
1183 if (p->priv_cc[pw] < 0) {
1184 pw = -2;
1185 break;
1186 }
1187 pw++;
1188 }
1189 p->priv_la[pr-1] = pw;
1190 j = k;
1191 pr++;
1192 }
1193 if (j > st) {
1194 m1 = st;
1195 m2 = j;
1196 }
1197 else {
1198 assert(st > j);
1199 m1 = j;
1200 m2 = st;
1201 }
1202 pw = p->priv_cr[m1];
1203 while (p->priv_cc[pw] != m2) {
1204/* assert(p->priv_cc[pw] >= 0); */
1205 if (p->priv_cc[pw] < 0) {
1206 pw = -2;
1207 break;
1208 }
1209 pw++;
1210 }
1211 p->priv_la[pr-1] = pw;
1212 p->priv_la[pr] = -1;
1213 pr++;
1214 }
1215#endif /* QPS_HOIST */
1216 }
1217
1218 do {
1219 qps_solve_inner(p);
1220 } while (!p->loop_done || !p->max_done);
1221
1222 /* retrieve values */
1223 /* qps_settp() should have already been called at this point */
1224 for (i = p->num_cells; i--;) {
1225 p->x[i] = p->priv_tp[i * 2];
1226 p->y[i] = p->priv_tp[i * 2 + 1];
1227 }
1228#if (QPS_DEBUG > 5)
1229 for (i = p->num_cells; i--;) {
1230 fprintf(p->priv_fp, "### cloc %d %f %f\n", i, p->x[i], p->y[i]);
1231 }
1232#endif
1233
1234 free(p->priv_cp);
1235 if (p->max_enable) {
1236 free(p->priv_mxl);
1237 }
1238 if (p->cog_num) {
1239 free(p->priv_gt);
1240 free(p->priv_gm);
1241 free(p->priv_gw);
1242 }
1243 if(p->loop_num) {
1244 free(p->priv_lt);
1245#if defined(QPS_HOIST)
1246 free(p->priv_la);
1247#endif
1248 }
1249
1250#if defined(QPS_PRECON)
1251 free(p->priv_pcg);
1252 free(p->priv_pcgt);
1253#endif
1254}
1255
1256/**********************************************************************/
1257
1258void
1260{
1261 free(p->priv_tp);
1262 free(p->priv_ii);
1263 free(p->priv_cc);
1264 free(p->priv_cr);
1265 free(p->priv_cw);
1266 free(p->priv_ct);
1267
1268#if defined(QPS_DEBUG)
1269 fclose(p->priv_fp);
1270#endif /* QPS_DEBUG */
1271}
1272
1273/**********************************************************************/
1275
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
Cube * p
Definition exorList.c:222
#define QPS_STEPSIZE_RETRIES
#define QPS_MAX_TOL
#define QPS_TOL
#define QPS_PRECON_EPS
#define QPS_DEC_CHANGE
#define QPS_MAX_ITER
#define QPS_EPS
void qps_init(qps_problem_t *p)
#define QPS_LOOP_TOL
void qps_solve(qps_problem_t *p)
void qps_clean(qps_problem_t *p)
#define QPS_MINSTEP
#define QPS_RELAX_ITER
struct qps_problem qps_problem_t
ABC_NAMESPACE_HEADER_START typedef float qps_float_t
#define assert(ex)
Definition util_old.h:213
VOID_HACK free()
char * malloc()