00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "neato.h"
00019 #include "dijkstra.h"
00020 #include "bfs.h"
00021 #include "pca.h"
00022 #include "matrix_ops.h"
00023 #include "conjgrad.h"
00024 #include "embed_graph.h"
00025 #include "kkutils.h"
00026 #include "stress.h"
00027 #include <math.h>
00028 #include <stdlib.h>
00029 #include <time.h>
00030
00031 #ifdef UNUSED
00032
00033
00034 static int stress_majorization_kD(vtx_data * graph,
00035 int n,
00036 int nedges_graph,
00037 double **coords,
00038 int dim,
00039 int smart_ini,
00040 int reweight_graph,
00041 int maxi
00042 );
00043
00044
00045
00046 static int sparse_stress_majorization_kD(vtx_data * graph,
00047 int n,
00048 int nedges_graph,
00049 double **coords,
00050 int dim,
00051 int smart_ini,
00052 int reweight_graph,
00053 int maxi,
00054 int dist_bound,
00055 int num_centers
00056 );
00057 #endif
00058
00059
00060
00061 static int sparse_stress_subspace_majorization_kD(vtx_data * graph,
00062 int n,
00063 int nedges_graph,
00064 double **coords,
00065 int dim,
00066 int smart_ini,
00067 int reweight_graph,
00068 int maxi,
00069 int dist_bound,
00070 int num_centers
00071 );
00072
00073 #ifndef HAVE_DRAND48
00074 extern double drand48(void);
00075 #endif
00076
00077 #define Dij2
00078
00079
00080
00081 #ifdef NONCORE
00082
00083
00084
00085
00086 #define max_nodes_in_mem 18000
00087 #endif
00088
00089
00090 #define smooth_pivots true
00091
00092
00093
00094
00095 #define stress_pca_dim 50
00096
00097
00098 typedef struct {
00099 int nedges;
00100 int *edges;
00101 DistType *edist;
00102 boolean free_mem;
00103 } dist_data;
00104
00105 static double compute_stressf(float **coords, float *lap, int dim, int n)
00106 {
00107
00108
00109 int i, j, l, neighbor, count;
00110 double sum, dist, Dij;
00111 sum = 0;
00112 for (count = 0, i = 0; i < n - 1; i++) {
00113 count++;
00114 for (j = 1; j < n - i; j++, count++) {
00115 dist = 0;
00116 neighbor = i + j;
00117 for (l = 0; l < dim; l++) {
00118 dist +=
00119 (coords[l][i] - coords[l][neighbor]) * (coords[l][i] -
00120 coords[l]
00121 [neighbor]);
00122 }
00123 dist = sqrt(dist);
00124 #ifdef Dij2
00125 Dij = 1.0 / sqrt(lap[count]);
00126 sum += (Dij - dist) * (Dij - dist) * (lap[count]);
00127 #else
00128 Dij = 1.0 / lap[count];
00129 sum += (Dij - dist) * (Dij - dist) * (lap[count]);
00130 #endif
00131 }
00132 }
00133
00134 return sum;
00135 }
00136
00137 #ifdef UNUSED
00138 static double compute_stress(double **coords, int **Dij, int dim, int n)
00139 {
00140
00141
00142 int i, j, l;
00143 double sum, dist;
00144 sum = 0;
00145 for (i = 1; i < n; i++) {
00146 for (j = 0; j < i; j++) {
00147 dist = 0;
00148 for (l = 0; l < dim; l++) {
00149 dist +=
00150 (coords[l][i] - coords[l][j]) * (coords[l][i] -
00151 coords[l][j]);
00152 }
00153 dist = sqrt(dist);
00154 #ifdef Dij2
00155 sum +=
00156 (Dij[i][j] - dist) * (Dij[i][j] -
00157 dist) / (Dij[i][j] * Dij[i][j]);
00158 #else
00159 sum += (Dij[i][j] - dist) * (Dij[i][j] - dist) / Dij[i][j];
00160 #endif
00161 }
00162 }
00163
00164 return sum;
00165 }
00166 #endif
00167
00168 static double
00169 compute_stress1(double **coords, dist_data * distances, int dim, int n)
00170 {
00171
00172
00173 int i, j, l, node;
00174 double sum, dist, Dij;
00175 sum = 0;
00176 for (i = 0; i < n; i++) {
00177 for (j = 0; j < distances[i].nedges; j++) {
00178 node = distances[i].edges[j];
00179 if (node <= i) {
00180 continue;
00181 }
00182 dist = 0;
00183 for (l = 0; l < dim; l++) {
00184 dist +=
00185 (coords[l][i] - coords[l][node]) * (coords[l][i] -
00186 coords[l][node]);
00187 }
00188 dist = sqrt(dist);
00189 Dij = distances[i].edist[j];
00190 #ifdef Dij2
00191 sum += (Dij - dist) * (Dij - dist) / (Dij * Dij);
00192 #else
00193 sum += (Dij - dist) * (Dij - dist) / Dij;
00194 #endif
00195 }
00196 }
00197
00198 return sum;
00199 }
00200
00201
00202
00203
00204
00205
00206 int
00207 initLayout(vtx_data * graph, int n, int dim, double **coords)
00208 {
00209 node_t *np;
00210 double *xp;
00211 double *yp;
00212 double *pt;
00213 int i, d;
00214 int pinned = 0;
00215
00216 xp = coords[0];
00217 yp = coords[1];
00218 for (i = 0; i < n; i++) {
00219 np = graph[i].np;
00220 if (hasPos(np)) {
00221 pt = ND_pos(np);
00222 *xp++ = *pt++;
00223 *yp++ = *pt++;
00224 if (dim > 2) {
00225 for (d = 2; d < dim; d++)
00226 coords[d][i] = *pt++;
00227 }
00228 if (isFixed(np))
00229 pinned = 1;
00230 } else {
00231 *xp++ = drand48();
00232 *yp++ = drand48();
00233 if (dim > 2) {
00234 for (d = 2; d < dim; d++)
00235 coords[d][i] = drand48();
00236 }
00237 }
00238 }
00239
00240 for (d = 0; d < dim; d++)
00241 orthog1(n, coords[d]);
00242
00243 return pinned;
00244 }
00245
00246 float*
00247 circuitModel(vtx_data * graph, int nG)
00248 {
00249 int i, j, e, rv, count;
00250 float *Dij = N_NEW(nG * (nG + 1) / 2, float);
00251 double **Gm;
00252 double **Gm_inv;
00253
00254 Gm = new_array(nG, nG, 0.0);
00255 Gm_inv = new_array(nG, nG, 0.0);
00256
00257
00258 if (graph->ewgts) {
00259 for (i = 0; i < nG; i++) {
00260 for (e = 1; e < graph[i].nedges; e++) {
00261 j = graph[i].edges[e];
00262
00263 Gm[i][j] = Gm[j][i] = -1.0 / graph[i].ewgts[e];
00264 }
00265 }
00266 } else {
00267 for (i = 0; i < nG; i++) {
00268 for (e = 1; e < graph[i].nedges; e++) {
00269 j = graph[i].edges[e];
00270
00271 Gm[i][j] = Gm[j][i] = -1.0;
00272 }
00273 }
00274 }
00275
00276 rv = solveCircuit(nG, Gm, Gm_inv);
00277
00278 if (rv) {
00279 float v;
00280 count = 0;
00281 for (i = 0; i < nG; i++) {
00282 for (j = i; j < nG; j++) {
00283 if (i == j)
00284 v = 0.0;
00285 else
00286 v = (float) (Gm_inv[i][i] + Gm_inv[j][j] -
00287 2.0 * Gm_inv[i][j]);
00288 Dij[count++] = v;
00289 }
00290 }
00291 } else {
00292 free(Dij);
00293 Dij = NULL;
00294 }
00295 free_array(Gm);
00296 free_array(Gm_inv);
00297 return Dij;
00298 }
00299
00300 #ifdef UNUSED
00301 int stress_majorization_kD(vtx_data * graph,
00302 int n,
00303 int nedges_graph,
00304 double **coords,
00305 int dim,
00306 int smart_ini,
00307 int reweight_graph,
00308 int n_iterations
00309 )
00310 {
00311 int iterations;
00312 double conj_tol = tolerance_cg;
00313 DistType **Dij;
00314 float *f_storage;
00315 float **lap;
00316 double degree;
00317 double dist_ij;
00318 double *b;
00319 double L_ij;
00320 double old_stress, new_stress;
00321 boolean converged;
00322
00323
00324
00325
00326
00327
00328 int i, j, k;
00329
00330
00331
00332
00333
00334 if (!reweight_graph) {
00335
00336 Dij = compute_apsp(graph, n);
00337 } else {
00338
00339
00340 Dij = compute_apsp_artifical_weights(graph, n);
00341 }
00342
00343
00344
00345
00346
00347 if (smart_ini) {
00348
00349 sparse_stress_subspace_majorization_kD(graph, n, nedges_graph,
00350 coords, dim, smart_ini,
00351 reweight_graph, 50,
00352 neighborhood_radius_subspace,
00353 num_pivots_stress);
00354 } else {
00355 initLayout(graph, n, dim, coords);
00356 }
00357
00358
00359
00360
00361
00362 lap = N_GNEW(n, float *);
00363 f_storage = N_GNEW(n * n, float);
00364 for (i = 0; i < n; i++) {
00365 lap[i] = f_storage + i * n;
00366 degree = 0;
00367 for (j = 0; j < n; j++) {
00368 if (j == i)
00369 continue;
00370 #ifdef Dij2
00371 degree -= lap[i][j] = -1.0f / ((float) Dij[i][j] * (float) Dij[i][j]);
00372 #else
00373 degree -= lap[i][j] = -1.0f / Dij[i][j];
00374 #endif
00375 }
00376 lap[i][i] = (float) (degree);
00377 }
00378
00379
00380
00381
00382
00383 b = N_GNEW(n, double);
00384 old_stress = compute_stress(coords, Dij, dim, n);
00385 for (converged = FALSE, iterations = 0;
00386 iterations < n_iterations && !converged; iterations++) {
00387
00388
00389 for (k = 0; k < dim; k++) {
00390
00391
00392
00393 for (i = 0; i < n; i++) {
00394 degree = 0;
00395 b[i] = 0;
00396 for (j = 0; j < n; j++) {
00397 if (j == i)
00398 continue;
00399 dist_ij = distance_kD(coords, dim, i, j);
00400 if (dist_ij > 1e-30) {
00401
00402 #ifdef Dij2
00403 L_ij = (float) (-1 / (dist_ij * Dij[i][j]));
00404 #else
00405 L_ij = (float) (-1 / dist_ij);
00406 #endif
00407 degree -= L_ij;
00408 b[i] += L_ij * coords[k][j];
00409 }
00410 }
00411 b[i] += degree * coords[k][i];
00412 }
00413 conjugate_gradient_f(lap, coords[k], b, n, conj_tol, n, TRUE);
00414 }
00415
00416 if ((converged = (iterations % 2 == 0))) {
00417 new_stress = compute_stress(coords, Dij, dim, n);
00418 converged =
00419 fabs(new_stress - old_stress) / (new_stress + 1e-10) <
00420 Epsilon;
00421 old_stress = new_stress;
00422 if (Verbose && (iterations % 10 == 0)) {
00423 fprintf(stderr, "%.3f ", new_stress);
00424 if (iterations % 100 == 0)
00425 fprintf(stderr, "\n");
00426 }
00427 }
00428 }
00429 if (Verbose)
00430 fprintf(stderr, "\nfinal e = %f\n",
00431 compute_stress(coords, Dij, dim, n));
00432
00433
00434 free(Dij[0]);
00435 free(Dij);
00436 free(lap[0]);
00437 free(lap);
00438 free(b);
00439
00440 return (iterations);
00441 }
00442
00443 static void
00444 local_beautify_kD(int *nodes, int num_nodes, vtx_data * graph, int n,
00445 int dist_bound, int reweight_graph, double **coords,
00446 int dim)
00447 {
00448
00449
00450
00451
00452 int i, j, k;
00453 int *visited_nodes;
00454 DistType *dist;
00455 double *weights;
00456 Queue Q;
00457 int num_visited_nodes;
00458 double dist_ij;
00459 int v, neighbor;
00460 double dist_1d;
00461 double total_wgts;
00462 double *newpos;
00463 double max_diff;
00464
00465 if (dist_bound <= 0) {
00466 return;
00467 }
00468
00469 visited_nodes = N_GNEW(n, int);
00470 dist = N_GNEW(n, DistType);
00471 weights = N_GNEW(n, double);
00472 newpos = N_GNEW(dim, double);
00473 mkQueue(&Q, n);
00474
00475
00476 for (i = 0; i < n; i++) {
00477 dist[i] = -1;
00478 }
00479
00480 for (i = 0; i < num_nodes; i++) {
00481 v = nodes[i];
00482 if (reweight_graph) {
00483 num_visited_nodes =
00484 dijkstra_bounded(v, graph, n, dist, dist_bound,
00485 visited_nodes);
00486 } else {
00487 num_visited_nodes =
00488 bfs_bounded(v, graph, n, dist, &Q, dist_bound,
00489 visited_nodes);
00490 }
00491
00492 total_wgts = 0;
00493 for (j = 0; j < num_visited_nodes; j++) {
00494 neighbor = visited_nodes[j];
00495 if (neighbor != v) {
00496 #ifdef Dij2
00497 total_wgts += weights[j] =
00498 1.0 / ((double) dist[neighbor] *
00499 (double) dist[neighbor]);
00500 #else
00501 total_wgts += weights[j] = 1.0 / (double) dist[neighbor];
00502 #endif
00503 }
00504 }
00505
00506 if (total_wgts == 0) {
00507 continue;
00508 }
00509
00510 do {
00511 for (k = 0; k < dim; newpos[k++] = 0);
00512
00513 for (j = 0; j < num_visited_nodes; j++) {
00514 neighbor = visited_nodes[j];
00515 if (neighbor == v) {
00516 continue;
00517 }
00518 for (k = 0; k < dim; k++) {
00519 dist_1d = coords[k][v] - coords[k][neighbor];
00520 dist_ij = distance_kD(coords, dim, v, neighbor);
00521 newpos[k] +=
00522 weights[j] * (coords[k][neighbor] +
00523 dist[neighbor] * dist_1d / dist_ij);
00524 }
00525 }
00526 max_diff = 0;
00527 for (k = 0; k < dim; k++) {
00528 newpos[k] /= total_wgts;
00529 max_diff =
00530 MAX(max_diff,
00531 fabs(newpos[k] - coords[k][v]) / fabs(newpos[k] +
00532 1e-20));
00533 coords[k][v] = newpos[k];
00534 }
00535 } while (max_diff > Epsilon);
00536
00537
00538 for (j = 0; j < num_visited_nodes; j++) {
00539 dist[visited_nodes[j]] = -1;
00540 }
00541 }
00542
00543 free(visited_nodes);
00544 free(dist);
00545 free(weights);
00546 free(newpos);
00547 freeQueue(&Q);
00548 }
00549
00550 int sparse_stress_majorization_kD(vtx_data * graph,
00551 int n,
00552 int nedges_graph,
00553 double **coords,
00554 int dim,
00555 int smart_ini,
00556 int reweight_graph,
00557 int n_iterations,
00558 int dist_bound,
00559 int num_centers
00560 )
00561 {
00562 int iterations;
00563 double conj_tol = tolerance_cg;
00564
00565
00566
00567
00568
00569
00570 int i, j, k;
00571 int node;
00572
00573 int *CenterIndex;
00574 int *invCenterIndex;
00575 Queue Q;
00576 float *old_weights;
00577
00578 DistType **Dij;
00579
00580 DistType *dist;
00581 DistType *storage;
00582 DistType max_dist;
00583 int *visited_nodes;
00584 dist_data *distances;
00585 int available_space;
00586 int *storage1 = NULL;
00587 DistType *storage2 = NULL;
00588 int num_visited_nodes;
00589 int num_neighbors;
00590 int index;
00591 int nedges;
00592 DistType *dist_list;
00593 vtx_data *lap;
00594 int *edges;
00595 float *ewgts;
00596 double degree;
00597 double dist_ij;
00598 double *b;
00599 double L_ij;
00600 double old_stress, new_stress;
00601 boolean converged;
00602
00603
00604
00605
00606
00607 if (smart_ini) {
00608
00609 sparse_stress_subspace_majorization_kD(graph, n, nedges_graph,
00610 coords, dim, smart_ini,
00611 reweight_graph, 50,
00612 dist_bound, num_centers);
00613 } else {
00614 initLayout(graph, n, dim, coords);
00615 }
00616
00617
00618
00619
00620
00621 CenterIndex = N_GNEW(n, int);
00622 for (i = 0; i < n; i++) {
00623 CenterIndex[i] = -1;
00624 }
00625 invCenterIndex = NULL;
00626
00627 mkQueue(&Q, n);
00628 old_weights = graph[0].ewgts;
00629
00630 if (reweight_graph) {
00631
00632
00633 compute_new_weights(graph, n);
00634 }
00635
00636
00637
00638
00639
00640 Dij = NULL;
00641 dist = N_GNEW(n, DistType);
00642
00643 if (num_centers == 0) {
00644 goto after_pivots_selection;
00645 }
00646
00647 invCenterIndex = N_GNEW(num_centers, int);
00648
00649 storage = N_GNEW(n * num_centers, DistType);
00650 Dij = N_GNEW(num_centers, DistType *);
00651 for (i = 0; i < num_centers; i++)
00652 Dij[i] = storage + i * n;
00653
00654
00655
00656
00657 node = rand() % n;
00658 CenterIndex[node] = 0;
00659 invCenterIndex[0] = node;
00660
00661 if (reweight_graph) {
00662 dijkstra(node, graph, n, Dij[0]);
00663 } else {
00664 bfs(node, graph, n, Dij[0], &Q);
00665 }
00666
00667
00668 max_dist = 0;
00669 for (i = 0; i < n; i++) {
00670 dist[i] = Dij[0][i];
00671 if (dist[i] > max_dist) {
00672 node = i;
00673 max_dist = dist[i];
00674 }
00675 }
00676
00677 for (i = 1; i < num_centers; i++) {
00678 CenterIndex[node] = i;
00679 invCenterIndex[i] = node;
00680 if (reweight_graph) {
00681 dijkstra(node, graph, n, Dij[i]);
00682 } else {
00683 bfs(node, graph, n, Dij[i], &Q);
00684 }
00685 max_dist = 0;
00686 for (j = 0; j < n; j++) {
00687 dist[j] = MIN(dist[j], Dij[i][j]);
00688 if (dist[j] > max_dist
00689 || (dist[j] == max_dist && rand() % (j + 1) == 0)) {
00690 node = j;
00691 max_dist = dist[j];
00692 }
00693 }
00694 }
00695
00696 after_pivots_selection:
00697
00698
00699
00700
00701 for (i = 0; i < n; i++) {
00702 dist[i] = -1;
00703 }
00704
00705 visited_nodes = N_GNEW(n, int);
00706 distances = N_GNEW(n, dist_data);
00707 available_space = 0;
00708 nedges = 0;
00709 for (i = 0; i < n; i++) {
00710 if (CenterIndex[i] >= 0) {
00711 distances[i].edges = N_GNEW(n - 1, int);
00712 distances[i].edist = N_GNEW(n - 1, DistType);
00713 distances[i].nedges = n - 1;
00714 nedges += n - 1;
00715 distances[i].free_mem = TRUE;
00716 index = CenterIndex[i];
00717 for (j = 0; j < i; j++) {
00718 distances[i].edges[j] = j;
00719 distances[i].edist[j] = Dij[index][j];
00720 }
00721 for (j = i + 1; j < n; j++) {
00722 distances[i].edges[j - 1] = j;
00723 distances[i].edist[j - 1] = Dij[index][j];
00724 }
00725 continue;
00726 }
00727
00728
00729
00730 if (dist_bound > 0) {
00731 if (reweight_graph) {
00732 num_visited_nodes =
00733 dijkstra_bounded(i, graph, n, dist, dist_bound,
00734 visited_nodes);
00735 } else {
00736 num_visited_nodes =
00737 bfs_bounded(i, graph, n, dist, &Q, dist_bound,
00738 visited_nodes);
00739 }
00740
00741 for (j = 0; j < num_visited_nodes;) {
00742 if (CenterIndex[visited_nodes[j]] < 0
00743 && visited_nodes[j] != i) {
00744
00745 j++;
00746 } else {
00747 dist[visited_nodes[j]] = -1;
00748 visited_nodes[j] = visited_nodes[--num_visited_nodes];
00749 }
00750 }
00751 } else {
00752 num_visited_nodes = 0;
00753 }
00754 num_neighbors = num_visited_nodes + num_centers;
00755 if (num_neighbors > available_space) {
00756 available_space = (dist_bound + 1) * n;
00757 storage1 = N_GNEW(available_space, int);
00758 storage2 = N_GNEW(available_space, DistType);
00759 distances[i].free_mem = TRUE;
00760 } else {
00761 distances[i].free_mem = FALSE;
00762 }
00763 distances[i].edges = storage1;
00764 distances[i].edist = storage2;
00765 distances[i].nedges = num_neighbors;
00766 nedges += num_neighbors;
00767 for (j = 0; j < num_visited_nodes; j++) {
00768 storage1[j] = visited_nodes[j];
00769 storage2[j] = dist[visited_nodes[j]];
00770 dist[visited_nodes[j]] = -1;
00771 }
00772
00773 for (j = num_visited_nodes; j < num_neighbors; j++) {
00774 index = j - num_visited_nodes;
00775 storage1[j] = invCenterIndex[index];
00776 storage2[j] = Dij[index][i];
00777 }
00778
00779 storage1 += num_neighbors;
00780 storage2 += num_neighbors;
00781 available_space -= num_neighbors;
00782 }
00783
00784 free(dist);
00785 free(visited_nodes);
00786
00787
00788 if (Dij != NULL) {
00789 free(Dij[0]);
00790 free(Dij);
00791 }
00792
00793
00794
00795
00796
00797 lap = N_GNEW(n, vtx_data);
00798 edges = N_GNEW(nedges + n, int);
00799 ewgts = N_GNEW(nedges + n, float);
00800 for (i = 0; i < n; i++) {
00801 lap[i].edges = edges;
00802 lap[i].ewgts = ewgts;
00803 lap[i].nedges = distances[i].nedges + 1;
00804 dist_list = distances[i].edist - 1;
00805 degree = 0;
00806 for (j = 1; j < lap[i].nedges; j++) {
00807 edges[j] = distances[i].edges[j - 1];
00808 #ifdef Dij2
00809 ewgts[j] = (float) -1.0 / ((float) dist_list[j] * (float) dist_list[j]);
00810 #else
00811 ewgts[j] = -1.0 / (float) dist_list[j];
00812 #endif
00813 degree -= ewgts[j];
00814 }
00815 edges[0] = i;
00816 ewgts[0] = (float) degree;
00817 edges += lap[i].nedges;
00818 ewgts += lap[i].nedges;
00819 }
00820
00821
00822
00823
00824
00825 b = N_GNEW(n, double);
00826 old_stress = compute_stress1(coords, distances, dim, n), new_stress;
00827 for (converged = FALSE, iterations = 0;
00828 iterations < n_iterations && !converged; iterations++) {
00829
00830
00831 for (k = 0; k < dim; k++) {
00832
00833
00834
00835 for (i = 0; i < n; i++) {
00836 degree = 0;
00837 b[i] = 0;
00838 dist_list = distances[i].edist - 1;
00839 edges = lap[i].edges;
00840 ewgts = lap[i].ewgts;
00841 for (j = 1; j < lap[i].nedges; j++) {
00842 node = edges[j];
00843 dist_ij = distance_kD(coords, dim, i, node);
00844 if (dist_ij > 1e-30) {
00845 L_ij = -ewgts[j] * dist_list[j] / dist_ij;
00846 degree -= L_ij;
00847 b[i] += L_ij * coords[k][node];
00848 }
00849 }
00850 b[i] += degree * coords[k][i];
00851 }
00852 conjugate_gradient(lap, coords[k], b, n, conj_tol, n);
00853 }
00854
00855 if ((converged = (iterations % 2 == 0))) {
00856 new_stress = compute_stress1(coords, distances, dim, n);
00857 converged =
00858 fabs(new_stress - old_stress) / (new_stress + 1e-10) <
00859 Epsilon;
00860 old_stress = new_stress;
00861 }
00862 }
00863 free(b);
00864
00865 if (smooth_pivots) {
00866
00867 local_beautify_kD(invCenterIndex, num_centers, graph, n,
00868 dist_bound, reweight_graph, coords, dim);
00869 }
00870
00871 if (reweight_graph) {
00872 restore_old_weights(graph, n, old_weights);
00873 }
00874
00875 for (i = 0; i < n; i++) {
00876 if (distances[i].free_mem) {
00877 free(distances[i].edges);
00878 free(distances[i].edist);
00879 }
00880 }
00881
00882 free(distances);
00883 free(lap[0].edges);
00884 free(lap[0].ewgts);
00885 free(lap);
00886 free(CenterIndex);
00887 free(invCenterIndex);
00888 freeQueue(&Q);
00889 return iterations;
00890 }
00891 #endif
00892
00893
00894
00895
00896
00897
00898
00899 static int sparse_stress_subspace_majorization_kD(vtx_data * graph,
00900 int n,
00901 int nedges_graph,
00902 double **coords,
00903 int dim,
00904 int smart_ini,
00905 int reweight_graph,
00906 int n_iterations,
00907 int dist_bound,
00908 int num_centers
00909 )
00910 {
00911 int iterations;
00912
00913 double conj_tol = tolerance_cg;
00914
00915
00916
00917
00918
00919
00920 int i, j, k, node;
00921
00922
00923
00924
00925
00926
00927 int subspace_dim = MIN(stress_pca_dim, n);
00928 double **subspace = N_GNEW(subspace_dim, double *);
00929 double *d_storage = N_GNEW(subspace_dim * n, double);
00930 int num_centers_local;
00931 DistType **full_coords;
00932
00933 int *CenterIndex;
00934 int *invCenterIndex;
00935 Queue Q;
00936 float *old_weights;
00937
00938 DistType **Dij;
00939
00940 DistType *dist;
00941 DistType max_dist;
00942 DistType *storage;
00943 int *visited_nodes;
00944 dist_data *distances;
00945 int available_space;
00946 int *storage1 = NULL;
00947 DistType *storage2 = NULL;
00948 int num_visited_nodes;
00949 int num_neighbors;
00950 int index;
00951 int nedges;
00952 DistType *dist_list;
00953 vtx_data *lap;
00954 int *edges;
00955 float *ewgts;
00956 double degree;
00957 double **directions;
00958 float **tmp_mat;
00959 float **matrix;
00960 double dist_ij;
00961 double *b;
00962 double *b_restricted;
00963 double L_ij;
00964 double old_stress, new_stress;
00965 boolean converged;
00966
00967 for (i = 0; i < subspace_dim; i++) {
00968 subspace[i] = d_storage + i * n;
00969 }
00970
00971
00972 num_centers_local = MIN(n, MAX(2 * subspace_dim, 50));
00973 full_coords = NULL;
00974
00975 embed_graph(graph, n, num_centers_local, &full_coords, reweight_graph);
00976
00977 center_coordinate(full_coords, n, num_centers_local);
00978
00979 PCA_alloc(full_coords, num_centers_local, n, subspace, subspace_dim);
00980
00981 free(full_coords[0]);
00982 free(full_coords);
00983
00984
00985
00986
00987
00988 CenterIndex = N_GNEW(n, int);
00989 for (i = 0; i < n; i++) {
00990 CenterIndex[i] = -1;
00991 }
00992 invCenterIndex = NULL;
00993
00994 mkQueue(&Q, n);
00995 old_weights = graph[0].ewgts;
00996
00997 if (reweight_graph) {
00998
00999
01000 compute_new_weights(graph, n);
01001 }
01002
01003
01004
01005
01006
01007 Dij = NULL;
01008 dist = N_GNEW(n, DistType);
01009 if (num_centers == 0) {
01010 goto after_pivots_selection;
01011 }
01012
01013 invCenterIndex = N_GNEW(num_centers, int);
01014
01015 storage = N_GNEW(n * num_centers, DistType);
01016 Dij = N_GNEW(num_centers, DistType *);
01017 for (i = 0; i < num_centers; i++)
01018 Dij[i] = storage + i * n;
01019
01020
01021
01022
01023 node = rand() % n;
01024 CenterIndex[node] = 0;
01025 invCenterIndex[0] = node;
01026
01027 if (reweight_graph) {
01028 dijkstra(node, graph, n, Dij[0]);
01029 } else {
01030 bfs(node, graph, n, Dij[0], &Q);
01031 }
01032
01033
01034 max_dist = 0;
01035 for (i = 0; i < n; i++) {
01036 dist[i] = Dij[0][i];
01037 if (dist[i] > max_dist) {
01038 node = i;
01039 max_dist = dist[i];
01040 }
01041 }
01042
01043 for (i = 1; i < num_centers; i++) {
01044 CenterIndex[node] = i;
01045 invCenterIndex[i] = node;
01046 if (reweight_graph) {
01047 dijkstra(node, graph, n, Dij[i]);
01048 } else {
01049 bfs(node, graph, n, Dij[i], &Q);
01050 }
01051 max_dist = 0;
01052 for (j = 0; j < n; j++) {
01053 dist[j] = MIN(dist[j], Dij[i][j]);
01054 if (dist[j] > max_dist
01055 || (dist[j] == max_dist && rand() % (j + 1) == 0)) {
01056 node = j;
01057 max_dist = dist[j];
01058 }
01059 }
01060 }
01061
01062 after_pivots_selection:
01063
01064
01065
01066
01067 for (i = 0; i < n; i++) {
01068 dist[i] = -1;
01069 }
01070
01071 visited_nodes = N_GNEW(n, int);
01072 distances = N_GNEW(n, dist_data);
01073 available_space = 0;
01074 nedges = 0;
01075 for (i = 0; i < n; i++) {
01076 if (CenterIndex[i] >= 0) {
01077 distances[i].edges = N_GNEW(n - 1, int);
01078 distances[i].edist = N_GNEW(n - 1, DistType);
01079 distances[i].nedges = n - 1;
01080 nedges += n - 1;
01081 distances[i].free_mem = TRUE;
01082 index = CenterIndex[i];
01083 for (j = 0; j < i; j++) {
01084 distances[i].edges[j] = j;
01085 distances[i].edist[j] = Dij[index][j];
01086 }
01087 for (j = i + 1; j < n; j++) {
01088 distances[i].edges[j - 1] = j;
01089 distances[i].edist[j - 1] = Dij[index][j];
01090 }
01091 continue;
01092 }
01093
01094
01095
01096 if (dist_bound > 0) {
01097 if (reweight_graph) {
01098 num_visited_nodes =
01099 dijkstra_bounded(i, graph, n, dist, dist_bound,
01100 visited_nodes);
01101 } else {
01102 num_visited_nodes =
01103 bfs_bounded(i, graph, n, dist, &Q, dist_bound,
01104 visited_nodes);
01105 }
01106
01107 for (j = 0; j < num_visited_nodes;) {
01108 if (CenterIndex[visited_nodes[j]] < 0
01109 && visited_nodes[j] != i) {
01110
01111 j++;
01112 } else {
01113 dist[visited_nodes[j]] = -1;
01114 visited_nodes[j] = visited_nodes[--num_visited_nodes];
01115 }
01116 }
01117 } else {
01118 num_visited_nodes = 0;
01119 }
01120 num_neighbors = num_visited_nodes + num_centers;
01121 if (num_neighbors > available_space) {
01122 available_space = (dist_bound + 1) * n;
01123 storage1 = N_GNEW(available_space, int);
01124 storage2 = N_GNEW(available_space, DistType);
01125 distances[i].free_mem = TRUE;
01126 } else {
01127 distances[i].free_mem = FALSE;
01128 }
01129 distances[i].edges = storage1;
01130 distances[i].edist = storage2;
01131 distances[i].nedges = num_neighbors;
01132 nedges += num_neighbors;
01133 for (j = 0; j < num_visited_nodes; j++) {
01134 storage1[j] = visited_nodes[j];
01135 storage2[j] = dist[visited_nodes[j]];
01136 dist[visited_nodes[j]] = -1;
01137 }
01138
01139 for (j = num_visited_nodes; j < num_neighbors; j++) {
01140 index = j - num_visited_nodes;
01141 storage1[j] = invCenterIndex[index];
01142 storage2[j] = Dij[index][i];
01143 }
01144
01145 storage1 += num_neighbors;
01146 storage2 += num_neighbors;
01147 available_space -= num_neighbors;
01148 }
01149
01150 free(dist);
01151 free(visited_nodes);
01152
01153 if (Dij != NULL) {
01154 free(Dij[0]);
01155 free(Dij);
01156 }
01157
01158
01159
01160
01161
01162 lap = N_GNEW(n, vtx_data);
01163 edges = N_GNEW(nedges + n, int);
01164 ewgts = N_GNEW(nedges + n, float);
01165 for (i = 0; i < n; i++) {
01166 lap[i].edges = edges;
01167 lap[i].ewgts = ewgts;
01168 lap[i].nedges = distances[i].nedges + 1;
01169 dist_list = distances[i].edist - 1;
01170 degree = 0;
01171 for (j = 1; j < lap[i].nedges; j++) {
01172 edges[j] = distances[i].edges[j - 1];
01173 #ifdef Dij2
01174 ewgts[j] = (float) -1.0 / ((float) dist_list[j] * (float) dist_list[j]);
01175 #else
01176 ewgts[j] = -1.0 / (float) dist_list[j];
01177 #endif
01178 degree -= ewgts[j];
01179 }
01180 edges[0] = i;
01181 ewgts[0] = (float) degree;
01182 edges += lap[i].nedges;
01183 ewgts += lap[i].nedges;
01184 }
01185
01186
01187
01188
01189
01190
01191
01192 directions = N_GNEW(dim, double *);
01193 directions[0] = N_GNEW(dim * subspace_dim, double);
01194 for (i = 1; i < dim; i++) {
01195 directions[i] = directions[0] + i * subspace_dim;
01196 }
01197
01198 if (smart_ini) {
01199
01200 for (k = 0; k < dim; k++) {
01201 for (i = 0; i < subspace_dim; i++) {
01202 directions[k][i] = 0;
01203 }
01204 }
01205 if (dim != 2) {
01206
01207
01208 for (k = 0; k < dim; k++) {
01209 directions[k][k] = 1;
01210 }
01211 } else {
01212
01213
01214
01215
01216 directions[0][0] = 1;
01217 if (!iterativePCA_1D(subspace, subspace_dim, n, directions[1])) {
01218 for (k = 0; k < subspace_dim; k++) {
01219 directions[1][k] = 0;
01220 }
01221 directions[1][1] = 1;
01222 }
01223 }
01224
01225 } else {
01226
01227 for (k = 0; k < dim; k++) {
01228 for (i = 0; i < subspace_dim; i++) {
01229 directions[k][i] = (double) (rand()) / RAND_MAX;
01230 }
01231 }
01232 }
01233
01234
01235
01236 for (k = 0; k < dim; k++) {
01237 right_mult_with_vector_transpose(subspace, n, subspace_dim,
01238 directions[k], coords[k]);
01239 }
01240
01241
01242
01243
01244
01245 tmp_mat = NULL;
01246 matrix = NULL;
01247 mult_sparse_dense_mat_transpose(lap, subspace, n, subspace_dim,
01248 &tmp_mat);
01249 mult_dense_mat(subspace, tmp_mat, subspace_dim, n, subspace_dim,
01250 &matrix);
01251 free(tmp_mat[0]);
01252 free(tmp_mat);
01253
01254
01255
01256
01257
01258 b = N_GNEW(n, double);
01259 b_restricted = N_GNEW(subspace_dim, double);
01260 old_stress = compute_stress1(coords, distances, dim, n);
01261 for (converged = FALSE, iterations = 0;
01262 iterations < n_iterations && !converged; iterations++) {
01263
01264
01265 for (k = 0; k < dim; k++) {
01266
01267
01268
01269 for (i = 0; i < n; i++) {
01270 degree = 0;
01271 b[i] = 0;
01272 dist_list = distances[i].edist - 1;
01273 edges = lap[i].edges;
01274 ewgts = lap[i].ewgts;
01275 for (j = 1; j < lap[i].nedges; j++) {
01276 node = edges[j];
01277 dist_ij = distance_kD(coords, dim, i, node);
01278 if (dist_ij > 1e-30) {
01279 L_ij = -ewgts[j] * dist_list[j] / dist_ij;
01280 degree -= L_ij;
01281 b[i] += L_ij * coords[k][node];
01282 }
01283 }
01284 b[i] += degree * coords[k][i];
01285 }
01286 right_mult_with_vector_d(subspace, subspace_dim, n, b,
01287 b_restricted);
01288 conjugate_gradient_f(matrix, directions[k], b_restricted,
01289 subspace_dim, conj_tol, subspace_dim,
01290 FALSE);
01291 right_mult_with_vector_transpose(subspace, n, subspace_dim,
01292 directions[k], coords[k]);
01293 }
01294
01295 if ((converged = (iterations % 2 == 0))) {
01296 new_stress = compute_stress1(coords, distances, dim, n);
01297 converged =
01298 fabs(new_stress - old_stress) / (new_stress + 1e-10) <
01299 Epsilon;
01300 old_stress = new_stress;
01301 }
01302 }
01303 free(b_restricted);
01304 free(b);
01305
01306 if (reweight_graph) {
01307 restore_old_weights(graph, n, old_weights);
01308 }
01309
01310 for (i = 0; i < n; i++) {
01311 if (distances[i].free_mem) {
01312 free(distances[i].edges);
01313 free(distances[i].edist);
01314 }
01315 }
01316
01317 free(distances);
01318 free(lap[0].edges);
01319 free(lap[0].ewgts);
01320 free(lap);
01321 free(CenterIndex);
01322 free(invCenterIndex);
01323 free(directions[0]);
01324 free(directions);
01325 if (matrix != NULL) {
01326 free(matrix[0]);
01327 free(matrix);
01328 }
01329 free(subspace[0]);
01330 free(subspace);
01331 freeQueue(&Q);
01332
01333 return iterations;
01334 }
01335
01336
01337
01338
01339 static float *compute_weighted_apsp_packed(vtx_data * graph, int n)
01340 {
01341 int i, j, count;
01342 float *Dij = N_NEW(n * (n + 1) / 2, float);
01343
01344 float *Di = N_NEW(n, float);
01345 Queue Q;
01346
01347 mkQueue(&Q, n);
01348
01349 count = 0;
01350 for (i = 0; i < n; i++) {
01351 dijkstra_f(i, graph, n, Di);
01352 for (j = i; j < n; j++) {
01353 Dij[count++] = Di[j];
01354 }
01355 }
01356 free(Di);
01357 freeQueue(&Q);
01358 return Dij;
01359 }
01360
01361
01362
01363
01364 float *compute_apsp_packed(vtx_data * graph, int n)
01365 {
01366 int i, j, count;
01367 float *Dij = N_NEW(n * (n + 1) / 2, float);
01368
01369 DistType *Di = N_NEW(n, DistType);
01370 Queue Q;
01371
01372 mkQueue(&Q, n);
01373
01374 count = 0;
01375 for (i = 0; i < n; i++) {
01376 bfs(i, graph, n, Di, &Q);
01377 for (j = i; j < n; j++) {
01378 Dij[count++] = ((float) Di[j]);
01379 }
01380 }
01381 free(Di);
01382 freeQueue(&Q);
01383 return Dij;
01384 }
01385
01386 #define max(x,y) ((x)>(y)?(x):(y))
01387
01388 float *compute_apsp_artifical_weights_packed(vtx_data * graph, int n)
01389 {
01390
01391
01392
01393 float *Dij;
01394 int i, j;
01395 float *old_weights = graph[0].ewgts;
01396 int nedges = 0;
01397 float *weights;
01398 int *vtx_vec;
01399 int deg_i, deg_j, neighbor;
01400
01401 for (i = 0; i < n; i++) {
01402 nedges += graph[i].nedges;
01403 }
01404
01405 weights = N_NEW(nedges, float);
01406 vtx_vec = N_NEW(n, int);
01407 for (i = 0; i < n; i++) {
01408 vtx_vec[i] = 0;
01409 }
01410
01411 if (graph->ewgts) {
01412 for (i = 0; i < n; i++) {
01413 fill_neighbors_vec_unweighted(graph, i, vtx_vec);
01414 deg_i = graph[i].nedges - 1;
01415 for (j = 1; j <= deg_i; j++) {
01416 neighbor = graph[i].edges[j];
01417 deg_j = graph[neighbor].nedges - 1;
01418 weights[j] =
01419 (float)
01420 max((float)
01421 (deg_i + deg_j -
01422 2 * common_neighbors(graph, i, neighbor,
01423 vtx_vec)),
01424 graph[i].ewgts[j]);
01425 }
01426 empty_neighbors_vec(graph, i, vtx_vec);
01427 graph[i].ewgts = weights;
01428 weights += graph[i].nedges;
01429 }
01430 Dij = compute_weighted_apsp_packed(graph, n);
01431 } else {
01432 for (i = 0; i < n; i++) {
01433 graph[i].ewgts = weights;
01434 fill_neighbors_vec_unweighted(graph, i, vtx_vec);
01435 deg_i = graph[i].nedges - 1;
01436 for (j = 1; j <= deg_i; j++) {
01437 neighbor = graph[i].edges[j];
01438 deg_j = graph[neighbor].nedges - 1;
01439 weights[j] =
01440 ((float) deg_i + deg_j -
01441 2 * common_neighbors(graph, i, neighbor, vtx_vec));
01442 }
01443 empty_neighbors_vec(graph, i, vtx_vec);
01444 weights += graph[i].nedges;
01445 }
01446 Dij = compute_apsp_packed(graph, n);
01447 }
01448
01449 free(vtx_vec);
01450 free(graph[0].ewgts);
01451 graph[0].ewgts = NULL;
01452 if (old_weights != NULL) {
01453 for (i = 0; i < n; i++) {
01454 graph[i].ewgts = old_weights;
01455 old_weights += graph[i].nedges;
01456 }
01457 }
01458 return Dij;
01459 }
01460
01461
01462
01463
01464 #define DegType long double
01465
01466
01467
01468
01469 int stress_majorization_kD_mkernel(vtx_data * graph,
01470 int n,
01471 int nedges_graph,
01472 double **d_coords,
01473 int dim,
01474 int smart_ini,
01475 int model,
01476 int maxi
01477 )
01478 {
01479 int iterations;
01480
01481 double conj_tol = tolerance_cg;
01482 float *Dij = NULL;
01483 int i, j, k;
01484 float **coords;
01485 float *f_storage;
01486 float constant_term;
01487 int count;
01488 DegType degree;
01489 int lap_length;
01490 float *lap2;
01491 DegType *degrees;
01492 int step;
01493 float val;
01494 double old_stress, new_stress;
01495 boolean converged;
01496 float **b;
01497 float *tmp_coords;
01498 float *dist_accumulator;
01499 float *lap1;
01500 int len;
01501 int havePinned;
01502 #ifdef ALTERNATIVE_STRESS_CALC
01503 double mat_stress;
01504 #endif
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515 if (maxi == 0)
01516 return 0;
01517
01518 if (Verbose)
01519 start_timer();
01520
01521 if (model == MODEL_SUBSET) {
01522
01523
01524 if (Verbose)
01525 fprintf(stderr, "Calculating subset model");
01526 Dij = compute_apsp_artifical_weights_packed(graph, n);
01527 } else if (model == MODEL_CIRCUIT) {
01528 Dij = circuitModel(graph, n);
01529 if (!Dij) {
01530 agerr(AGWARN,
01531 "graph is disconnected. Hence, the circuit model\n");
01532 agerr(AGPREV,
01533 "is undefined. Reverting to the shortest path model.\n");
01534 }
01535 }
01536 if (!Dij) {
01537 if (Verbose)
01538 fprintf(stderr, "Calculating shortest paths");
01539 if (graph->ewgts)
01540 Dij = compute_weighted_apsp_packed(graph, n);
01541 else
01542 Dij = compute_apsp_packed(graph, n);
01543 }
01544
01545 if (Verbose) {
01546 fprintf(stderr, ": %.2f sec\n", elapsed_sec());
01547 fprintf(stderr, "Setting initial positions");
01548 start_timer();
01549 }
01550
01551
01552
01553
01554
01555 if (smart_ini && (n > 1)) {
01556 havePinned = 0;
01557
01558
01559
01560 sparse_stress_subspace_majorization_kD(graph, n, nedges_graph,
01561 d_coords, dim, smart_ini,
01562 (model == MODEL_SUBSET), 50,
01563 neighborhood_radius_subspace,
01564 num_pivots_stress);
01565
01566 for (i = 0; i < dim; i++) {
01567
01568 double max = 1;
01569 for (j = 0; j < n; j++) {
01570 if (fabs(d_coords[i][j]) > max) {
01571 max = fabs(d_coords[i][j]);
01572 }
01573 }
01574 for (j = 0; j < n; j++) {
01575 d_coords[i][j] /= max;
01576 }
01577
01578 for (j = 0; j < n; j++) {
01579 d_coords[i][j] += 1e-6 * (drand48() - 0.5);
01580 }
01581 orthog1(n, d_coords[i]);
01582 }
01583 } else {
01584 havePinned = initLayout(graph, n, dim, d_coords);
01585 }
01586 if (Verbose) fprintf(stderr, ": %.2f sec", elapsed_sec());
01587 if (n == 1) return 0;
01588
01589 if (Verbose) {
01590 fprintf(stderr, ": %.2f sec\n", elapsed_sec());
01591 fprintf(stderr, "Setting up stress function");
01592 start_timer();
01593 }
01594 coords = N_NEW(dim, float *);
01595 f_storage = N_NEW(dim * n, float);
01596 for (i = 0; i < dim; i++) {
01597 coords[i] = f_storage + i * n;
01598 for (j = 0; j < n; j++) {
01599 coords[i][j] = ((float) d_coords[i][j]);
01600 }
01601 }
01602
01603
01604
01605 #ifdef Dij2
01606 constant_term = ((float) n * (n - 1) / 2);
01607 #else
01608 constant_term = 0;
01609 for (count = 0, i = 0; i < n - 1; i++) {
01610 count++;
01611 for (j = 1; j < n - i; j++, count++) {
01612 constant_term += Dij[count];
01613 }
01614 }
01615 #endif
01616
01617
01618
01619
01620
01621 lap_length = n * (n + 1) / 2;
01622 lap2 = Dij;
01623 #ifdef Dij2
01624 square_vec(lap_length, lap2);
01625 #endif
01626
01627 invert_vec(lap_length, lap2);
01628
01629
01630 count = 0;
01631 degrees = N_NEW(n, DegType);
01632
01633 memset(degrees, 0, n * sizeof(DegType));
01634 for (i = 0; i < n - 1; i++) {
01635 degree = 0;
01636 count++;
01637 for (j = 1; j < n - i; j++, count++) {
01638 val = lap2[count];
01639 degree += val;
01640 degrees[i + j] -= val;
01641 }
01642 degrees[i] -= degree;
01643 }
01644 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
01645 lap2[count] = degrees[i];
01646 }
01647
01648 #ifdef NONCORE
01649 if (n > max_nodes_in_mem) {
01650 #define FILENAME "tmp_Dij$$$.bin"
01651 fp = fopen(FILENAME, "wb");
01652 fwrite(lap2, sizeof(float), lap_length, fp);
01653 fclose(fp);
01654 }
01655 #endif
01656
01657
01658
01659
01660
01661 b = N_NEW(dim, float *);
01662 b[0] = N_NEW(dim * n, float);
01663 for (k = 1; k < dim; k++) {
01664 b[k] = b[0] + k * n;
01665 }
01666
01667 tmp_coords = N_NEW(n, float);
01668 dist_accumulator = N_NEW(n, float);
01669 lap1 = NULL;
01670 #ifdef NONCORE
01671 if (n <= max_nodes_in_mem) {
01672 lap1 = N_NEW(lap_length, float);
01673 } else {
01674 lap1 = lap2;
01675 fp = fopen(FILENAME, "rb");
01676 fgetpos(fp, &pos);
01677 }
01678 #else
01679 lap1 = N_NEW(lap_length, float);
01680 #endif
01681
01682
01683 old_stress = MAXDOUBLE;
01684 if (Verbose) {
01685 fprintf(stderr, ": %.2f sec\n", elapsed_sec());
01686 fprintf(stderr, "Solving model: ");
01687 start_timer();
01688 }
01689
01690 for (converged = FALSE, iterations = 0;
01691 iterations < maxi && !converged; iterations++) {
01692
01693
01694
01695 memset(degrees, 0, n * sizeof(DegType));
01696 #ifdef Dij2
01697 #ifdef NONCORE
01698 if (n <= max_nodes_in_mem) {
01699 sqrt_vecf(lap_length, lap2, lap1);
01700 } else {
01701 sqrt_vec(lap_length, lap1);
01702 }
01703 #else
01704 sqrt_vecf(lap_length, lap2, lap1);
01705 #endif
01706 #endif
01707 for (count = 0, i = 0; i < n - 1; i++) {
01708 len = n - i - 1;
01709
01710 set_vector_valf(len, 0, dist_accumulator);
01711
01712
01713 for (k = 0; k < dim; k++) {
01714 set_vector_valf(len, coords[k][i], tmp_coords);
01715 vectors_mult_additionf(len, tmp_coords, -1,
01716 coords[k] + i + 1);
01717 square_vec(len, tmp_coords);
01718 vectors_additionf(len, tmp_coords, dist_accumulator,
01719 dist_accumulator);
01720 }
01721
01722
01723 invert_sqrt_vec(len, dist_accumulator);
01724
01725 for (j = 0; j < len; j++) {
01726 if (dist_accumulator[j] >= MAXFLOAT
01727 || dist_accumulator[j] < 0) {
01728 dist_accumulator[j] = 0;
01729 }
01730 }
01731
01732 count++;
01733 degree = 0;
01734 for (j = 0; j < len; j++, count++) {
01735 #ifdef Dij2
01736 val = lap1[count] *= dist_accumulator[j];
01737 #else
01738 val = lap1[count] = dist_accumulator[j];
01739 #endif
01740 degree += val;
01741 degrees[i + j + 1] -= val;
01742 }
01743 degrees[i] -= degree;
01744 }
01745 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
01746 lap1[count] = degrees[i];
01747 }
01748
01749
01750 for (k = 0; k < dim; k++) {
01751
01752 right_mult_with_vector_ff(lap1, n, coords[k], b[k]);
01753 }
01754
01755
01756
01757
01758 new_stress = 0;
01759 for (k = 0; k < dim; k++) {
01760 new_stress += vectors_inner_productf(n, coords[k], b[k]);
01761 }
01762 new_stress *= 2;
01763 new_stress += constant_term;
01764 #ifdef NONCORE
01765 if (n > max_nodes_in_mem) {
01766
01767 fsetpos(fp, &pos);
01768 fread(lap2, sizeof(float), lap_length, fp);
01769 }
01770 #endif
01771 for (k = 0; k < dim; k++) {
01772 right_mult_with_vector_ff(lap2, n, coords[k], tmp_coords);
01773 new_stress -= vectors_inner_productf(n, coords[k], tmp_coords);
01774 }
01775 #ifdef ALTERNATIVE_STRESS_CALC
01776 mat_stress = new_stress;
01777 new_stress = compute_stressf(coords, lap2, dim, n);
01778 if (fabs(mat_stress - new_stress) / min(mat_stress, new_stress) >
01779 0.001) {
01780 fprintf(stderr, "Diff stress vals: %lf %lf (iteration #%d)\n",
01781 mat_stress, new_stress, iterations);
01782 }
01783 #endif
01784
01785
01786
01787 converged =
01788 (((fabs(old_stress - new_stress) / old_stress) < Epsilon)
01789 || (new_stress < Epsilon));
01790 old_stress = new_stress;
01791
01792 for (k = 0; k < dim; k++) {
01793 node_t *np;
01794 if (havePinned) {
01795 copy_vectorf(n, coords[k], tmp_coords);
01796 conjugate_gradient_mkernel(lap2, tmp_coords, b[k], n,
01797 conj_tol, n);
01798 for (i = 0; i < n; i++) {
01799 np = graph[i].np;
01800 if (!isFixed(np))
01801 coords[k][i] = tmp_coords[i];
01802 }
01803 } else {
01804 conjugate_gradient_mkernel(lap2, coords[k], b[k], n,
01805 conj_tol, n);
01806 }
01807 }
01808 if (Verbose && (iterations % 5 == 0)) {
01809 fprintf(stderr, "%.3f ", new_stress);
01810 if ((iterations + 5) % 50 == 0)
01811 fprintf(stderr, "\n");
01812 }
01813 }
01814 if (Verbose) {
01815 fprintf(stderr, "\nfinal e = %f %d iterations %.2f sec\n",
01816 compute_stressf(coords, lap2, dim, n),
01817 iterations, elapsed_sec());
01818 }
01819
01820 for (i = 0; i < dim; i++) {
01821 for (j = 0; j < n; j++) {
01822 d_coords[i][j] = coords[i][j];
01823 }
01824 }
01825 free(coords[0]);
01826 free(coords);
01827
01828 free(lap2);
01829 free(b[0]);
01830 free(b);
01831 free(tmp_coords);
01832 free(dist_accumulator);
01833 free(degrees);
01834 free(lap1);
01835 return iterations;
01836 }