abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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. */
50 int *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. */
55 int *gt;
56 
57  /* n is the number of variables in the modified problem. n should be twice
58  the number of independent cells. */
59 int n;
60 
61 qps_float_t *cp; /* current location during CG iteration */
62 qps_float_t f; /* value of cost function at p */
63 
64 #endif
65 
66 /**********************************************************************/
67 
68 static void
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 
128 static qps_float_t
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 
215 static void
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 
343 static void
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 
458 static void
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 
541 void
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 
650 static qps_float_t
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 
701 static void
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 
980 void
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 
1258 void
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 
static void qps_solve_inner(qps_problem_t *p)
char * malloc()
void qps_solve(qps_problem_t *p)
qps_float_t * priv_lt
VOID_HACK free()
void qps_clean(qps_problem_t *p)
qps_float_t * priv_mxh
static Llb_Mgr_t * p
Definition: llb3Image.c:950
qps_float_t max_y
static void qps_cgmin(qps_problem_t *p)
qps_float_t priv_fopt
#define QPS_TOL
qps_float_t * priv_h
#define QPS_MAX_ITER
qps_float_t * y
qps_float_t * priv_gm
ABC_NAMESPACE_HEADER_START typedef float qps_float_t
qps_float_t priv_fprev
qps_float_t * priv_cw
#define QPS_MINSTEP
qps_float_t * priv_xi
#define QPS_EPS
qps_float_t * area
#define QPS_MAX_TOL
qps_float_t priv_fmax
#define QPS_LOOP_TOL
#define QPS_STEPSIZE_RETRIES
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
qps_float_t * x
qps_float_t * cog_x
static void qps_settp(qps_problem_t *p)
qps_float_t * priv_ct
qps_float_t * priv_myl
qps_float_t * edge_weight
#define QPS_RELAX_ITER
qps_float_t * priv_mxl
#define QPS_DEC_CHANGE
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
static void qps_linmin(qps_problem_t *p, qps_float_t dgg, qps_float_t *h)
qps_float_t * priv_cp
qps_float_t * priv_gw
qps_float_t * loop_penalty
qps_float_t * cog_y
qps_float_t * priv_myh
static void qps_dfunc(qps_problem_t *p, qps_float_t *d)
void qps_init(qps_problem_t *p)
qps_float_t priv_f
#define QPS_PRECON_EPS
#define assert(ex)
Definition: util_old.h:213
static qps_float_t qps_estopt(qps_problem_t *p)
static qps_float_t qps_func(qps_problem_t *p)
qps_float_t * priv_tp
qps_float_t * priv_tp2
qps_float_t priv_eps
qps_float_t * priv_pcgt
qps_float_t * priv_pcg
ConcreteCell * cell
qps_float_t * loop_max
qps_float_t f
qps_float_t * priv_g
qps_float_t max_x