42 #define max_nodes_in_mem 18000
46 #define smooth_pivots true
51 #define stress_pca_dim 50
61 static double compute_stressf(
float **coords,
float *lap,
int dim,
int n,
int exp)
65 int i, j, l, neighbor, count;
66 double sum,
dist, Dij;
68 for (count = 0, i = 0; i < n - 1; i++) {
70 for (j = 1; j < n - i; j++, count++) {
73 for (l = 0; l < dim; l++) {
75 (coords[l][i] - coords[l][neighbor]) * (coords[l][i] -
82 Dij = 1.0 / sqrt(lap[count]);
83 sum += (Dij -
dist) * (Dij - dist) * (lap[count]);
85 Dij = 1.0 / lap[count];
86 sum += (Dij -
dist) * (Dij - dist) * (lap[count]);
89 Dij = 1.0 / lap[count];
90 sum += (Dij -
dist) * (Dij - dist) * (lap[count]);
99 compute_stress1(
double **coords,
dist_data * distances,
int dim,
int n,
int exp)
104 double sum,
dist, Dij;
107 for (i = 0; i < n; i++) {
108 for (j = 0; j < distances[i].
nedges; j++) {
109 node = distances[i].
edges[j];
114 for (l = 0; l < dim; l++) {
116 (coords[l][i] - coords[l][
node]) * (coords[l][i] -
121 Dij = distances[i].
edist[j];
123 sum += (Dij -
dist) * (Dij - dist) / (Dij * Dij);
125 sum += (Dij -
dist) * (Dij - dist) / Dij;
130 for (i = 0; i < n; i++) {
131 for (j = 0; j < distances[i].
nedges; j++) {
132 node = distances[i].
edges[j];
137 for (l = 0; l < dim; l++) {
139 (coords[l][i] - coords[l][
node]) * (coords[l][i] -
144 Dij = distances[i].
edist[j];
145 sum += (Dij -
dist) * (Dij - dist) / Dij;
171 for (i = 0; i < n; i++) {
178 for (d = 2; d < dim; d++)
179 coords[d][i] = *pt++;
187 for (d = 2; d < dim; d++)
193 for (d = 0; d < dim; d++)
201 int i, j, e, rv, count;
202 float *Dij =
N_NEW(nG * (nG + 1) / 2,
float);
211 for (i = 0; i < nG; i++) {
212 for (e = 1; e < graph[i].
nedges; e++) {
213 j = graph[i].
edges[e];
215 Gm[i][j] = Gm[j][i] = -1.0 / graph[i].
ewgts[e];
219 for (i = 0; i < nG; i++) {
220 for (e = 1; e < graph[i].
nedges; e++) {
221 j = graph[i].
edges[e];
223 Gm[i][j] = Gm[j][i] = -1.0;
233 for (i = 0; i < nG; i++) {
234 for (j = i; j < nG; j++) {
238 v = (float) (Gm_inv[i][i] + Gm_inv[j][j] -
260 static int sparse_stress_subspace_majorization_kD(
vtx_data *
graph,
290 double **subspace =
N_GNEW(subspace_dim,
double *);
291 double *d_storage =
N_GNEW(subspace_dim * n,
double);
292 int num_centers_local;
308 int *storage1 =
NULL;
310 int num_visited_nodes;
324 double *b_restricted;
326 double old_stress, new_stress;
329 for (i = 0; i < subspace_dim; i++) {
330 subspace[i] = d_storage + i * n;
334 num_centers_local =
MIN(n,
MAX(2 * subspace_dim, 50));
337 embed_graph(graph, n, num_centers_local, &full_coords, reweight_graph);
341 PCA_alloc(full_coords, num_centers_local, n, subspace, subspace_dim);
343 free(full_coords[0]);
350 CenterIndex =
N_GNEW(n,
int);
351 for (i = 0; i < n; i++) {
354 invCenterIndex =
NULL;
357 old_weights = graph[0].
ewgts;
359 if (reweight_graph) {
371 if (num_centers == 0) {
372 goto after_pivots_selection;
375 invCenterIndex =
N_GNEW(num_centers,
int);
379 for (i = 0; i < num_centers; i++)
380 Dij[i] = storage + i * n;
386 CenterIndex[
node] = 0;
387 invCenterIndex[0] =
node;
389 if (reweight_graph) {
392 bfs(node, graph, n, Dij[0], &Q);
397 for (i = 0; i < n; i++) {
399 if (dist[i] > max_dist) {
405 for (i = 1; i < num_centers; i++) {
406 CenterIndex[
node] = i;
407 invCenterIndex[i] =
node;
408 if (reweight_graph) {
411 bfs(node, graph, n, Dij[i], &Q);
414 for (j = 0; j < n; j++) {
415 dist[j] =
MIN(dist[j], Dij[i][j]);
416 if (dist[j] > max_dist
417 || (dist[j] == max_dist && rand() % (j + 1) == 0)) {
424 after_pivots_selection:
429 for (i = 0; i < n; i++) {
433 visited_nodes =
N_GNEW(n,
int);
437 for (i = 0; i < n; i++) {
438 if (CenterIndex[i] >= 0) {
441 distances[i].
nedges = n - 1;
444 index = CenterIndex[i];
445 for (j = 0; j < i; j++) {
446 distances[i].
edges[j] = j;
447 distances[i].
edist[j] = Dij[index][j];
449 for (j = i + 1; j < n; j++) {
450 distances[i].
edges[j - 1] = j;
451 distances[i].
edist[j - 1] = Dij[index][j];
458 if (dist_bound > 0) {
459 if (reweight_graph) {
469 for (j = 0; j < num_visited_nodes;) {
470 if (CenterIndex[visited_nodes[j]] < 0
471 && visited_nodes[j] != i) {
475 dist[visited_nodes[j]] = -1;
476 visited_nodes[j] = visited_nodes[--num_visited_nodes];
480 num_visited_nodes = 0;
482 num_neighbors = num_visited_nodes + num_centers;
483 if (num_neighbors > available_space) {
484 available_space = (dist_bound + 1) * n;
485 storage1 =
N_GNEW(available_space,
int);
491 distances[i].
edges = storage1;
492 distances[i].
edist = storage2;
493 distances[i].
nedges = num_neighbors;
494 nedges += num_neighbors;
495 for (j = 0; j < num_visited_nodes; j++) {
496 storage1[j] = visited_nodes[j];
497 storage2[j] = dist[visited_nodes[j]];
498 dist[visited_nodes[j]] = -1;
501 for (j = num_visited_nodes; j < num_neighbors; j++) {
502 index = j - num_visited_nodes;
503 storage1[j] = invCenterIndex[index];
504 storage2[j] = Dij[index][i];
507 storage1 += num_neighbors;
508 storage2 += num_neighbors;
509 available_space -= num_neighbors;
525 edges =
N_GNEW(nedges + n,
int);
526 ewgts =
N_GNEW(nedges + n,
float);
527 for (i = 0; i < n; i++) {
528 lap[i].
edges = edges;
529 lap[i].
ewgts = ewgts;
531 dist_list = distances[i].
edist - 1;
534 for (j = 1; j < lap[i].
nedges; j++) {
535 edges[j] = distances[i].
edges[j - 1];
537 ewgts[j] = (float) -1.0 / ((
float) dist_list[j] * (float) dist_list[j]);
539 ewgts[j] = -1.0 / (float) dist_list[j];
544 for (j = 1; j < lap[i].
nedges; j++) {
545 edges[j] = distances[i].
edges[j - 1];
546 ewgts[j] = -1.0 / (float) dist_list[j];
551 ewgts[0] = (float) degree;
562 directions =
N_GNEW(dim,
double *);
563 directions[0] =
N_GNEW(dim * subspace_dim,
double);
564 for (i = 1; i < dim; i++) {
565 directions[i] = directions[0] + i * subspace_dim;
570 for (k = 0; k < dim; k++) {
571 for (i = 0; i < subspace_dim; i++) {
572 directions[k][i] = 0;
578 for (k = 0; k < dim; k++) {
579 directions[k][k] = 1;
586 directions[0][0] = 1;
588 for (k = 0; k < subspace_dim; k++) {
589 directions[1][k] = 0;
591 directions[1][1] = 1;
597 for (k = 0; k < dim; k++) {
598 for (i = 0; i < subspace_dim; i++) {
599 directions[k][i] = (double) (rand()) / RAND_MAX;
606 for (k = 0; k < dim; k++) {
608 directions[k], coords[k]);
629 b_restricted =
N_GNEW(subspace_dim,
double);
630 old_stress = compute_stress1(coords, distances, dim, n, exp);
631 for (converged =
FALSE, iterations = 0;
632 iterations < n_iterations && !converged; iterations++) {
635 for (k = 0; k < dim; k++) {
639 for (i = 0; i < n; i++) {
642 dist_list = distances[i].
edist - 1;
643 edges = lap[i].
edges;
644 ewgts = lap[i].
ewgts;
645 for (j = 1; j < lap[i].
nedges; j++) {
648 if (dist_ij > 1e-30) {
649 L_ij = -ewgts[j] * dist_list[j] / dist_ij;
651 b[i] += L_ij * coords[k][
node];
654 b[i] += degree * coords[k][i];
659 subspace_dim, conj_tol, subspace_dim,
665 directions[k], coords[k]);
668 if ((converged = (iterations % 2 == 0))) {
669 new_stress = compute_stress1(coords, distances, dim, n, exp);
671 fabs(new_stress - old_stress) / (new_stress + 1e-10) <
673 old_stress = new_stress;
680 if (reweight_graph) {
684 for (i = 0; i < n; i++) {
685 if (distances[i].free_mem) {
686 free(distances[i].edges);
687 free(distances[i].edist);
696 free(invCenterIndex);
699 if (matrix !=
NULL) {
713 static float *compute_weighted_apsp_packed(
vtx_data * graph,
int n)
716 float *Dij =
N_NEW(n * (n + 1) / 2,
float);
718 float *Di =
N_NEW(n,
float);
724 for (i = 0; i < n; i++) {
726 for (j = i; j < n; j++) {
727 Dij[count++] = Di[j];
750 Dij = compute_weighted_apsp_packed(graph, nG);
753 for (i = 0; i < nG; i++) {
755 for (e = 1; e < graph[i].
nedges; e++) {
756 j = graph[i].
edges[e];
759 delta += fabsf(Dij[i * nG + j - shift] - graph[i].ewgts[e]);
760 Dij[i * nG + j - shift] = graph[i].
ewgts[e];
764 fprintf(stderr,
"mdsModel: delta = %f\n", delta);
775 float *Dij =
N_NEW(n * (n + 1) / 2,
float);
783 for (i = 0; i < n; i++) {
784 bfs(i, graph, n, Di, &Q);
785 for (j = i; j < n; j++) {
786 Dij[count++] = ((float) Di[j]);
794 #define max(x,y) ((x)>(y)?(x):(y))
803 float *old_weights = graph[0].
ewgts;
807 int deg_i, deg_j, neighbor;
809 for (i = 0; i < n; i++) {
810 nedges += graph[i].
nedges;
813 weights =
N_NEW(nedges,
float);
814 vtx_vec =
N_NEW(n,
int);
815 for (i = 0; i < n; i++) {
820 for (i = 0; i < n; i++) {
822 deg_i = graph[i].
nedges - 1;
823 for (j = 1; j <= deg_i; j++) {
824 neighbor = graph[i].
edges[j];
825 deg_j = graph[neighbor].
nedges - 1;
834 graph[i].
ewgts = weights;
835 weights += graph[i].
nedges;
837 Dij = compute_weighted_apsp_packed(graph, n);
839 for (i = 0; i < n; i++) {
840 graph[i].
ewgts = weights;
842 deg_i = graph[i].
nedges - 1;
843 for (j = 1; j <= deg_i; j++) {
844 neighbor = graph[i].
edges[j];
845 deg_j = graph[neighbor].
nedges - 1;
847 ((float) deg_i + deg_j -
851 weights += graph[i].
nedges;
857 free(graph[0].ewgts);
859 if (old_weights !=
NULL) {
860 for (i = 0; i < n; i++) {
861 graph[i].
ewgts = old_weights;
862 old_weights += graph[i].
nedges;
869 static void dumpMatrix(
float *Dij,
int n)
872 for (i = 0; i < n; i++) {
873 for (j = i; j < n; j++) {
874 fprintf(stderr,
"%.02f ", Dij[count++]);
884 #define DegType long double
905 float **coords =
NULL;
906 float *f_storage =
NULL;
915 double old_stress, new_stress;
918 float *tmp_coords =
NULL;
919 float *dist_accumulator =
NULL;
925 #ifdef ALTERNATIVE_STRESS_CALC
952 fprintf(stderr,
"Calculating subset model");
958 "graph is disconnected. Hence, the circuit model\n");
960 "is undefined. Reverting to the shortest path model.\n");
964 fprintf(stderr,
"Calculating MDS model");
969 fprintf(stderr,
"Calculating shortest paths");
971 Dij = compute_weighted_apsp_packed(graph, n);
978 fprintf(stderr,
"Setting initial positions");
986 if (smart_ini && (n > 1)) {
991 if (sparse_stress_subspace_majorization_kD(graph, n, nedges_graph,
992 d_coords, dim, smart_ini, exp,
1000 for (i = 0; i < dim; i++) {
1003 for (j = 0; j < n; j++) {
1004 if (fabs(d_coords[i][j]) > max) {
1005 max = fabs(d_coords[i][j]);
1008 for (j = 0; j < n; j++) {
1009 d_coords[i][j] /=
max;
1012 for (j = 0; j < n; j++) {
1013 d_coords[i][j] += 1e-6 * (
drand48() - 0.5);
1018 havePinned =
initLayout(graph, n, dim, d_coords, nodes);
1022 if ((n == 1) || (maxi == 0))
1027 fprintf(stderr,
"Setting up stress function");
1030 coords =
N_NEW(dim,
float *);
1031 f_storage =
N_NEW(dim * n,
float);
1032 for (i = 0; i < dim; i++) {
1033 coords[i] = f_storage + i * n;
1034 for (j = 0; j < n; j++) {
1035 coords[i][j] = ((float) d_coords[i][j]);
1043 constant_term = ((float) n * (n - 1) / 2);
1046 for (count = 0, i = 0; i < n - 1; i++) {
1048 for (j = 1; j < n - i; j++, count++) {
1049 constant_term += Dij[count];
1055 for (count = 0, i = 0; i < n - 1; i++) {
1057 for (j = 1; j < n - i; j++, count++) {
1058 constant_term += Dij[count];
1067 lap_length = n * (n + 1) / 2;
1081 memset(degrees, 0, n *
sizeof(
DegType));
1082 for (i = 0; i < n - 1; i++) {
1085 for (j = 1; j < n - i; j++, count++) {
1088 degrees[i + j] -= val;
1090 degrees[i] -= degree;
1092 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
1093 lap2[count] = degrees[i];
1097 if (n > max_nodes_in_mem) {
1098 #define FILENAME "tmp_Dij$$$.bin"
1099 fp = fopen(FILENAME,
"wb");
1100 fwrite(lap2,
sizeof(
float), lap_length, fp);
1110 b =
N_NEW(dim,
float *);
1111 b[0] =
N_NEW(dim * n,
float);
1112 for (k = 1; k < dim; k++) {
1113 b[k] = b[0] + k * n;
1116 tmp_coords =
N_NEW(n,
float);
1117 dist_accumulator =
N_NEW(n,
float);
1120 if (n <= max_nodes_in_mem) {
1121 lap1 =
N_NEW(lap_length,
float);
1124 fp = fopen(FILENAME,
"rb");
1128 lap1 =
N_NEW(lap_length,
float);
1139 fprintf(stderr,
"Solving model: ");
1143 for (converged =
FALSE, iterations = 0;
1144 iterations < maxi && !converged; iterations++) {
1148 memset(degrees, 0, n *
sizeof(
DegType));
1152 if (n <= max_nodes_in_mem) {
1162 for (count = 0, i = 0; i < n - 1; i++) {
1168 for (k = 0; k < dim; k++) {
1180 for (j = 0; j < len; j++) {
1181 if (dist_accumulator[j] >=
MAXFLOAT
1182 || dist_accumulator[j] < 0) {
1183 dist_accumulator[j] = 0;
1190 for (j = 0; j < len; j++, count++) {
1192 val = lap1[count] *= dist_accumulator[j];
1194 val = lap1[count] = dist_accumulator[j];
1197 degrees[i + j + 1] -= val;
1200 for (j = 0; j < len; j++, count++) {
1201 val = lap1[count] = dist_accumulator[j];
1203 degrees[i + j + 1] -= val;
1206 degrees[i] -= degree;
1208 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
1209 lap1[count] = degrees[i];
1213 for (k = 0; k < dim; k++) {
1222 for (k = 0; k < dim; k++) {
1226 new_stress += constant_term;
1228 if (n > max_nodes_in_mem) {
1231 fread(lap2,
sizeof(
float), lap_length, fp);
1234 for (k = 0; k < dim; k++) {
1238 #ifdef ALTERNATIVE_STRESS_CALC
1239 mat_stress = new_stress;
1240 new_stress = compute_stressf(coords, lap2, dim, n);
1241 if (fabs(mat_stress - new_stress) / min(mat_stress, new_stress) >
1243 fprintf(stderr,
"Diff stress vals: %lf %lf (iteration #%d)\n",
1244 mat_stress, new_stress, iterations);
1251 double diff = old_stress - new_stress;
1252 double change =
ABS(diff);
1253 converged = (((change / old_stress) <
Epsilon)
1256 old_stress = new_stress;
1258 for (k = 0; k < dim; k++) {
1267 for (i = 0; i < n; i++) {
1270 coords[k][i] = tmp_coords[i];
1280 if (
Verbose && (iterations % 5 == 0)) {
1281 fprintf(stderr,
"%.3f ", new_stress);
1282 if ((iterations + 5) % 50 == 0)
1283 fprintf(stderr,
"\n");
1287 fprintf(stderr,
"\nfinal e = %f %d iterations %.2f sec\n",
1288 compute_stressf(coords, lap2, dim, n, exp),
1292 for (i = 0; i < dim; i++) {
1293 for (j = 0; j < n; j++) {
1294 d_coords[i][j] = coords[i][j];
1311 free(dist_accumulator);
void vectors_additionf(int n, float *vector1, float *vector2, float *result)
void invert_sqrt_vec(int n, float *vec)
boolean iterativePCA_1D(double **coords, int dim, int n, double *new_direction)
void sqrt_vec(int n, float *vec)
void orthog1(int n, double *vec)
#define neighborhood_radius_subspace
void restore_old_weights(vtx_data *graph, int n, float *old_weights)
void invert_vec(int n, float *vec)
int initLayout(vtx_data *graph, int n, int dim, double **coords, node_t **nodes)
void copy_vectorf(int n, float *source, float *dest)
void set_vector_valf(int n, float val, float *result)
int common_neighbors(vtx_data *graph, int v, int u, int *v_vector)
void center_coordinate(DistType **coords, int n, int dim)
#define num_pivots_stress
void dijkstra_f(int vertex, vtx_data *graph, int n, float *dist)
int agerr(agerrlevel_t level, const char *fmt,...)
void bfs(int vertex, vtx_data *graph, int n, DistType *dist, Queue *Q)
void freeQueue(Queue *qp)
void mult_dense_mat(double **A, float **B, int dim1, int dim2, int dim3, float ***CC)
void right_mult_with_vector_transpose(double **matrix, int dim1, int dim2, double *vector, double *result)
void fill_neighbors_vec_unweighted(vtx_data *graph, int vtx, int *vtx_vec)
void square_vec(int n, float *vec)
void vectors_mult_additionf(int n, float *vector1, float alpha, float *vector2)
double vectors_inner_productf(int n, float *vector1, float *vector2)
double distance_kD(double **coords, int dim, int i, int j)
int bfs_bounded(int vertex, vtx_data *graph, int n, DistType *dist, Queue *Q, int bound, int *visited_nodes)
void free_array(double **rv)
double ** new_array(int i, int j, double val)
void mult_sparse_dense_mat_transpose(vtx_data *A, double **B, int dim1, int dim2, float ***CC)
void dijkstra(int vertex, vtx_data *graph, int n, DistType *dist)
void sqrt_vecf(int n, float *source, float *target)
int stress_majorization_kD_mkernel(vtx_data *graph, int n, int nedges_graph, double **d_coords, node_t **nodes, int dim, int opts, int model, int maxi)
void empty_neighbors_vec(vtx_data *graph, int vtx, int *vtx_vec)
float * circuitModel(vtx_data *graph, int nG)
float * compute_apsp_packed(vtx_data *graph, int n)
void mkQueue(Queue *qp, int size)
Agraph_t * graph(char *name)
void compute_new_weights(vtx_data *graph, int n)
void embed_graph(vtx_data *graph, int n, int dim, DistType ***Coords, int reweight_graph)
EXTERN unsigned char Verbose
Agnode_t * node(Agraph_t *g, char *name)
void PCA_alloc(DistType **coords, int dim, int n, double **new_coords, int new_dim)
float * compute_apsp_artifical_weights_packed(vtx_data *graph, int n)
float * mdsModel(vtx_data *graph, int nG)
int conjugate_gradient_f(float **A, double *x, double *b, int n, double tol, int max_iterations, boolean ortho1)
double dist(Site *s, Site *t)
int solveCircuit(int nG, double **Gm, double **Gm_inv)
void right_mult_with_vector_ff(float *packed_matrix, int n, float *vector, float *result)
int conjugate_gradient_mkernel(float *A, float *x, float *b, int n, double tol, int max_iterations)
int dijkstra_bounded(int vertex, vtx_data *graph, int n, DistType *dist, int bound, int *visited_nodes)
void right_mult_with_vector_d(double **matrix, int dim1, int dim2, double *vector, double *result)