00001
00002
00003
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "digcola.h"
00038 #ifdef IPSEPCOLA
00039 #include <math.h>
00040 #include <stdlib.h>
00041 #include <time.h>
00042 #include <stdio.h>
00043 #include <float.h>
00044 #include "stress.h"
00045 #include "dijkstra.h"
00046 #include "bfs.h"
00047 #include "matrix_ops.h"
00048 #include "kkutils.h"
00049 #include "conjgrad.h"
00050 #include <csolve_VPSC.h>
00051 #include "quad_prog_vpsc.h"
00052 #include "quad_prog_solver.h"
00053 #include "matrix_ops.h"
00054
00055 #define localConstrMajorIterations 1000
00056
00057 int stress_majorization_cola(
00058 vtx_data * graph,
00059 int n,
00060 int nedges_graph,
00061 double **d_coords,
00062 int dim,
00063 int model,
00064 int maxi,
00065 ipsep_options * opt)
00066 {
00067 int iterations = 0;
00068
00069
00070
00071
00072
00073
00074
00075 int i, j, k;
00076 float *lap1 = NULL;
00077 float *dist_accumulator = NULL;
00078 float *tmp_coords = NULL;
00079 float **b = NULL;
00080 double *degrees = NULL;
00081 float *lap2 = NULL;
00082 int lap_length;
00083 float *f_storage = NULL;
00084 float **coords = NULL;
00085 int orig_n = n;
00086
00087
00088 CMajEnvVPSC *cMajEnvHor = NULL;
00089 CMajEnvVPSC *cMajEnvVrt = NULL;
00090 double y_0;
00091 int length;
00092 DistType diameter;
00093 float *Dij = NULL;
00094 float constant_term;
00095 int count;
00096 double degree;
00097 int step;
00098 float val;
00099 double old_stress, new_stress = 0;
00100 boolean converged;
00101 int len;
00102 double nsizeScale = 0;
00103 float maxEdgeLen = 0;
00104 double max = 1;
00105
00106 initLayout(graph, n, dim, d_coords);
00107 if (n == 1)
00108 return 0;
00109
00110 for (i = 0; i < n; i++) {
00111 for (j = 1; j < graph[i].nedges; j++) {
00112 maxEdgeLen = MAX(graph[i].ewgts[j], maxEdgeLen);
00113 }
00114 }
00115
00116
00117
00118
00119
00120 if (maxi == 0)
00121 return iterations;
00122
00123 if (model == MODEL_SUBSET) {
00124
00125
00126 if (Verbose)
00127 fprintf(stderr, "Calculating subset model");
00128 Dij = compute_apsp_artifical_weights_packed(graph, n);
00129 } else if (model == MODEL_CIRCUIT) {
00130 Dij = circuitModel(graph, n);
00131 if (!Dij) {
00132 agerr(AGWARN,
00133 "graph is disconnected. Hence, the circuit model\n");
00134 agerr(AGPREV,
00135 "is undefined. Reverting to the shortest path model.\n");
00136 }
00137 }
00138 if (!Dij) {
00139 if (Verbose)
00140 fprintf(stderr, "Calculating shortest paths\n ");
00141 Dij = compute_apsp_packed(graph, n);
00142 }
00143
00144 diameter = -1;
00145 length = n + n * (n - 1) / 2;
00146 for (i = 0; i < length; i++) {
00147 if (Dij[i] > diameter) {
00148 diameter = (int) Dij[i];
00149 }
00150 }
00151
00152
00153
00154 for (i = 0; i < dim; i++) {
00155 for (j = 0; j < n; j++) {
00156 if (fabs(d_coords[i][j]) > max) {
00157 max = fabs(d_coords[i][j]);
00158 }
00159 }
00160 }
00161 for (i = 0; i < dim; i++) {
00162 for (j = 0; j < n; j++) {
00163 d_coords[i][j] *= 10 / max;
00164 }
00165 }
00166
00167
00168
00169
00170
00171 for (i = 0; i < dim; i++) {
00172 orthog1(n, d_coords[i]);
00173 }
00174
00175
00176 y_0 = d_coords[1][0];
00177 for (i = 0; i < n; i++) {
00178 d_coords[1][i] -= y_0;
00179 }
00180
00181
00182
00183
00184
00185 lap2 = Dij;
00186 lap_length = n + n * (n - 1) / 2;
00187 square_vec(lap_length, lap2);
00188
00189 invert_vec(lap_length, lap2);
00190
00191 if (opt->clusters->nclusters > 0) {
00192 int nn = n + opt->clusters->nclusters * 2;
00193 int clap_length = nn + nn * (nn - 1) / 2;
00194 float *clap = N_GNEW(clap_length, float);
00195 int c0, c1;
00196 float v;
00197 c0 = c1 = 0;
00198 for (i = 0; i < nn; i++) {
00199 for (j = 0; j < nn - i; j++) {
00200 if (i < n && j < n - i) {
00201 v = lap2[c0++];
00202 } else {
00203
00204 if (j == 1 && i % 2 == 1) {
00205 v = maxEdgeLen;
00206 v *= v;
00207 if (v > 0.01) {
00208 v = 1.0 / v;
00209 }
00210 } else
00211 v = 0;
00212 }
00213 clap[c1++] = v;
00214 }
00215 }
00216 free(lap2);
00217 lap2 = clap;
00218 n = nn;
00219 lap_length = clap_length;
00220 }
00221
00222 count = 0;
00223 degrees = N_GNEW(n, double);
00224 set_vector_val(n, 0, degrees);
00225 for (i = 0; i < n - 1; i++) {
00226 degree = 0;
00227 count++;
00228 for (j = 1; j < n - i; j++, count++) {
00229 val = lap2[count];
00230 degree += val;
00231 degrees[i + j] -= val;
00232 }
00233 degrees[i] -= degree;
00234 }
00235 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
00236 lap2[count] = (float) degrees[i];
00237 }
00238
00239 coords = N_GNEW(dim, float *);
00240 f_storage = N_GNEW(dim * n, float);
00241 for (i = 0; i < dim; i++) {
00242 coords[i] = f_storage + i * n;
00243 for (j = 0; j < n; j++) {
00244 coords[i][j] = j < orig_n ? (float) (d_coords[i][j]) : 0;
00245 }
00246 }
00247
00248
00249
00250
00251 constant_term = (float) (n * (n - 1) / 2);
00252
00253
00254
00255
00256
00257 b = N_GNEW(dim, float *);
00258 b[0] = N_GNEW(dim * n, float);
00259 for (k = 1; k < dim; k++) {
00260 b[k] = b[0] + k * n;
00261 }
00262
00263 tmp_coords = N_GNEW(n, float);
00264 dist_accumulator = N_GNEW(n, float);
00265
00266 old_stress = DBL_MAX;
00267
00268 cMajEnvHor = initCMajVPSC(n, lap2, graph, opt, 0);
00269 cMajEnvVrt = initCMajVPSC(n, lap2, graph, opt, opt->diredges);
00270
00271 lap1 = N_GNEW(lap_length, float);
00272
00273 for (converged = FALSE, iterations = 0;
00274 iterations < maxi && !converged; iterations++) {
00275
00276
00277 set_vector_val(n, 0, degrees);
00278 sqrt_vecf(lap_length, lap2, lap1);
00279 for (count = 0, i = 0; i < n - 1; i++) {
00280 len = n - i - 1;
00281
00282 set_vector_valf(n, 0, dist_accumulator);
00283
00284
00285
00286
00287 for (k = 0; k < dim; k++) {
00288 set_vector_valf(len, coords[k][i], tmp_coords);
00289 vectors_mult_additionf(len, tmp_coords, -1,
00290 coords[k] + i + 1);
00291 square_vec(len, tmp_coords);
00292 vectors_additionf(len, tmp_coords, dist_accumulator,
00293 dist_accumulator);
00294 }
00295
00296
00297 invert_sqrt_vec(len, dist_accumulator);
00298
00299 for (j = 0; j < len; j++) {
00300 if (dist_accumulator[j] >= FLT_MAX
00301 || dist_accumulator[j] < 0) {
00302 dist_accumulator[j] = 0;
00303 }
00304 }
00305
00306 count++;
00307 degree = 0;
00308 for (j = 0; j < len; j++, count++) {
00309 val = lap1[count] *= dist_accumulator[j];
00310 degree += val;
00311 degrees[i + j + 1] -= val;
00312 }
00313 degrees[i] -= degree;
00314 }
00315 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
00316 lap1[count] = (float) degrees[i];
00317 }
00318
00319
00320 for (k = 0; k < dim; k++) {
00321
00322 right_mult_with_vector_ff(lap1, n, coords[k], b[k]);
00323 }
00324
00325
00326
00327
00328
00329 new_stress = 0;
00330 for (k = 0; k < dim; k++) {
00331 new_stress += vectors_inner_productf(n, coords[k], b[k]);
00332 }
00333 new_stress *= 2;
00334 new_stress += constant_term;
00335 for (k = 0; k < dim; k++) {
00336 right_mult_with_vector_ff(lap2, n, coords[k], tmp_coords);
00337 new_stress -= vectors_inner_productf(n, coords[k], tmp_coords);
00338 }
00339
00340 #ifdef ALTERNATIVE_STRESS_CALC
00341 {
00342 double mat_stress = new_stress;
00343 double compute_stress(float **coords, float *lap, int dim,
00344 int n);
00345 new_stress = compute_stress(coords, lap2, dim, n);
00346 if (fabs(mat_stress - new_stress) /
00347 min(mat_stress, new_stress) > 0.001) {
00348 fprintf(stderr,
00349 "Diff stress vals: %lf %lf (iteration #%d)\n",
00350 mat_stress, new_stress, iterations);
00351 }
00352 }
00353 #endif
00354
00355 if (Verbose && (iterations % 1 == 0)) {
00356 fprintf(stderr, "%.3f ", new_stress);
00357 if (iterations % 10 == 0)
00358 fprintf(stderr, "\n");
00359 }
00360 converged = new_stress < old_stress
00361 && fabs(new_stress - old_stress) / fabs(old_stress + 1e-10) <
00362 Epsilon;
00363
00364
00365
00366
00367 old_stress = new_stress;
00368
00369
00370
00371
00372 if ((iterations >= maxi - 1 || converged) && opt->noverlap == 1
00373 && nsizeScale < 0.999) {
00374 nsizeScale += 0.1;
00375 if (Verbose)
00376 fprintf(stderr, "nsizescale=%f,iterations=%d\n",
00377 nsizeScale, iterations);
00378 iterations = 0;
00379 converged = FALSE;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 if (opt->noverlap == 1 && nsizeScale > 0.001) {
00396 generateNonoverlapConstraints(cMajEnvHor, nsizeScale, coords,
00397 0,
00398 nsizeScale < 0.5 ? FALSE : TRUE,
00399 opt);
00400 }
00401 if (cMajEnvHor->m > 0) {
00402 #ifdef MOSEK
00403 if (opt->mosek) {
00404 mosek_quad_solve_sep(cMajEnvHor->mosekEnv, n, b[0],
00405 coords[0]);
00406 } else
00407 #endif
00408 constrained_majorization_vpsc(cMajEnvHor, b[0], coords[0],
00409 localConstrMajorIterations);
00410 } else {
00411
00412
00413
00414 conjugate_gradient_mkernel(lap2, coords[0], b[0], n,
00415 tolerance_cg, n);
00416 }
00417 if (opt->noverlap == 1 && nsizeScale > 0.001) {
00418 generateNonoverlapConstraints(cMajEnvVrt, nsizeScale, coords,
00419 1, FALSE, opt);
00420 }
00421 if (cMajEnvVrt->m > 0) {
00422 #ifdef MOSEK
00423 if (opt->mosek) {
00424 mosek_quad_solve_sep(cMajEnvVrt->mosekEnv, n, b[1],
00425 coords[1]);
00426 } else
00427 #endif
00428 constrained_majorization_vpsc(cMajEnvVrt, b[1], coords[1],
00429 localConstrMajorIterations);
00430 } else {
00431 conjugate_gradient_mkernel(lap2, coords[1], b[1], n,
00432 tolerance_cg, n);
00433 }
00434 }
00435 if (Verbose) {
00436 fprintf(stderr, "\nfinal e = %f %d iterations %.2f sec\n",
00437 new_stress, iterations, elapsed_sec());
00438 }
00439 deleteCMajEnvVPSC(cMajEnvHor);
00440 deleteCMajEnvVPSC(cMajEnvVrt);
00441
00442 if (opt->noverlap == 2) {
00443
00444 removeoverlaps(orig_n, coords, opt);
00445 }
00446
00447 if (coords != NULL) {
00448 for (i = 0; i < dim; i++) {
00449 for (j = 0; j < orig_n; j++) {
00450 d_coords[i][j] = coords[i][j];
00451 }
00452 }
00453 free(coords[0]);
00454 free(coords);
00455 }
00456
00457 if (b) {
00458 free(b[0]);
00459 free(b);
00460 }
00461 free(tmp_coords);
00462 free(dist_accumulator);
00463 free(degrees);
00464 free(lap2);
00465 free(lap1);
00466
00467 return iterations;
00468 }
00469 #endif