32#define stress_pca_dim 50
47 double sum,
dist, Dij;
49 for (count = 0, i = 0; i < n - 1; i++) {
51 for (j = 1; j < n - i; j++, count++) {
54 for (l = 0; l <
dim; l++) {
56 (coords[l][i] - coords[l][
neighbor]) * (coords[l][i] -
62 Dij = 1.0 / sqrt(lap[count]);
63 sum += (Dij -
dist) * (Dij -
dist) * lap[count];
65 Dij = 1.0 / lap[count];
66 sum += (Dij -
dist) * (Dij -
dist) * lap[count];
80 double sum,
dist, Dij;
83 for (i = 0; i < n; i++) {
84 for (
size_t j = 0; j < distances[i].
nedges; j++) {
90 for (l = 0; l <
dim; l++) {
92 (coords[l][i] - coords[l][
node]) * (coords[l][i] -
97 Dij = distances[i].
edist[j];
98 sum += (Dij -
dist) * (Dij -
dist) / (Dij * Dij);
102 for (i = 0; i < n; i++) {
103 for (
size_t j = 0; j < distances[i].
nedges; j++) {
109 for (l = 0; l <
dim; l++) {
111 (coords[l][i] - coords[l][
node]) * (coords[l][i] -
116 Dij = distances[i].
edist[j];
117 sum += (Dij -
dist) * (Dij -
dist) / Dij;
140 for (i = 0; i < n; i++) {
147 for (d = 2; d <
dim; d++)
148 coords[d][i] = *pt++;
156 for (d = 2; d <
dim; d++)
162 for (d = 0; d <
dim; d++)
171 float *Dij =
gv_calloc(nG * (nG + 1) / 2,
sizeof(
float));
180 for (i = 0; i < nG; i++) {
181 for (
size_t e = 1; e <
graph[i].nedges; e++) {
182 j =
graph[i].edges[e];
184 Gm[i][j] = Gm[j][i] = -1.0 /
graph[i].ewgts[e];
188 for (i = 0; i < nG; i++) {
189 for (
size_t e = 1; e <
graph[i].nedges; e++) {
190 j =
graph[i].edges[e];
192 Gm[i][j] = Gm[j][i] = -1.0;
202 for (i = 0; i < nG; i++) {
203 for (j = i; j < nG; j++) {
207 v = (float) (Gm_inv[i][i] + Gm_inv[j][j] -
257 double **subspace =
gv_calloc(subspace_dim,
sizeof(
double *));
258 double *d_storage =
gv_calloc(subspace_dim * n,
sizeof(
double));
259 int num_centers_local;
272 int *storage1 =
NULL;
274 int num_visited_nodes;
287 double *b_restricted;
289 double old_stress, new_stress;
292 for (i = 0; i < subspace_dim; i++) {
293 subspace[i] = d_storage + i * n;
297 num_centers_local =
MIN(n,
MAX(2 * subspace_dim, 50));
304 PCA_alloc(full_coords, num_centers_local, n, subspace, subspace_dim);
306 free(full_coords[0]);
313 int *CenterIndex =
gv_calloc(n,
sizeof(
int));
314 for (i = 0; i < n; i++) {
317 invCenterIndex =
NULL;
319 old_weights =
graph[0].ewgts;
321 if (reweight_graph) {
333 if (num_centers == 0) {
334 goto after_pivots_selection;
337 invCenterIndex =
gv_calloc(num_centers,
sizeof(
int));
341 for (i = 0; i < num_centers; i++)
342 Dij[i] = storage + i * n;
348 CenterIndex[
node] = 0;
349 invCenterIndex[0] =
node;
351 if (reweight_graph) {
359 for (i = 0; i < n; i++) {
361 if (
dist[i] > max_dist) {
367 for (i = 1; i < num_centers; i++) {
368 CenterIndex[
node] = i;
369 invCenterIndex[i] =
node;
370 if (reweight_graph) {
376 for (
int j = 0; j < n; j++) {
378 if (
dist[j] > max_dist
379 || (
dist[j] == max_dist && rand() % (j + 1) == 0)) {
386 after_pivots_selection:
391 for (i = 0; i < n; i++) {
395 visited_nodes =
gv_calloc(n,
sizeof(
int));
399 for (i = 0; i < n; i++) {
400 if (CenterIndex[i] >= 0) {
403 distances[i].
nedges = (size_t)n - 1;
406 index = CenterIndex[i];
407 for (
int j = 0; j < i; j++) {
408 distances[i].
edges[j] = j;
409 distances[i].
edist[j] = Dij[index][j];
411 for (
int j = i + 1; j < n; j++) {
412 distances[i].
edges[j - 1] = j;
413 distances[i].
edist[j - 1] = Dij[index][j];
420 num_visited_nodes = 0;
421 num_neighbors = num_visited_nodes + num_centers;
422 if (num_neighbors > available_space) {
424 storage1 =
gv_calloc(available_space,
sizeof(
int));
430 distances[i].
edges = storage1;
431 distances[i].
edist = storage2;
432 distances[i].
nedges = (size_t)num_neighbors;
433 nedges += (size_t)num_neighbors;
434 for (
int j = 0; j < num_visited_nodes; j++) {
435 storage1[j] = visited_nodes[j];
436 storage2[j] =
dist[visited_nodes[j]];
437 dist[visited_nodes[j]] = -1;
440 for (
int j = num_visited_nodes; j < num_neighbors; j++) {
441 index = j - num_visited_nodes;
442 storage1[j] = invCenterIndex[index];
443 storage2[j] = Dij[index][i];
446 storage1 += num_neighbors;
447 storage2 += num_neighbors;
448 available_space -= num_neighbors;
466 for (i = 0; i < n; i++) {
467 lap[i].
edges = edges;
468 lap[i].
ewgts = ewgts;
470 dist_list = distances[i].
edist - 1;
473 for (
size_t j = 1; j < lap[i].
nedges; j++) {
474 edges[j] = distances[i].
edges[j - 1];
475 ewgts[j] = (float) -1.0 / ((
float) dist_list[j] * (float) dist_list[j]);
479 for (
size_t j = 1; j < lap[i].
nedges; j++) {
480 edges[j] = distances[i].
edges[j - 1];
481 ewgts[j] = -1.0f / (float) dist_list[j];
486 ewgts[0] = (float) degree;
498 directions[0] =
gv_calloc(
dim * subspace_dim,
sizeof(
double));
499 for (i = 1; i <
dim; i++) {
500 directions[i] = directions[0] + i * subspace_dim;
505 for (k = 0; k <
dim; k++) {
506 for (i = 0; i < subspace_dim; i++) {
507 directions[k][i] = 0;
513 for (k = 0; k <
dim; k++) {
514 directions[k][k] = 1;
521 directions[0][0] = 1;
523 for (k = 0; k < subspace_dim; k++) {
524 directions[1][k] = 0;
526 directions[1][1] = 1;
532 for (k = 0; k <
dim; k++) {
533 for (i = 0; i < subspace_dim; i++) {
534 directions[k][i] = (double) rand() / RAND_MAX;
541 for (k = 0; k <
dim; k++) {
543 directions[k], coords[k]);
564 b_restricted =
gv_calloc(subspace_dim,
sizeof(
double));
566 for (converged =
false, iterations = 0;
567 iterations < n_iterations && !converged; iterations++) {
570 for (k = 0; k <
dim; k++) {
574 for (i = 0; i < n; i++) {
577 dist_list = distances[i].
edist - 1;
578 edges = lap[i].
edges;
579 ewgts = lap[i].
ewgts;
580 for (
size_t j = 1; j < lap[i].
nedges; j++) {
583 if (dist_ij > 1e-30) {
584 L_ij = -ewgts[j] * dist_list[j] / dist_ij;
586 b[i] += L_ij * coords[k][
node];
589 b[i] += degree * coords[k][i];
594 subspace_dim, conj_tol, subspace_dim,
600 directions[k], coords[k]);
603 if (iterations % 2 == 0) {
605 converged = fabs(new_stress - old_stress) / (new_stress + 1e-10) <
Epsilon;
606 old_stress = new_stress;
613 if (reweight_graph) {
617 for (i = 0; i < n; i++) {
618 if (distances[i].free_mem) {
619 free(distances[i].edges);
620 free(distances[i].edist);
629 free(invCenterIndex);
632 if (matrix !=
NULL) {
648 float *Dij =
gv_calloc(n * (n + 1) / 2,
sizeof(
float));
653 for (i = 0; i < n; i++) {
655 for (j = i; j < n; j++) {
656 Dij[count++] = Di[j];
681 for (i = 0; i < nG; i++) {
683 for (
size_t e = 1; e <
graph[i].nedges; e++) {
684 j =
graph[i].edges[e];
687 delta += fabsf(Dij[i * nG + j - shift] -
graph[i].ewgts[e]);
688 Dij[i * nG + j - shift] =
graph[i].ewgts[e];
692 fprintf(stderr,
"mdsModel: delta = %f\n",
delta);
703 float *Dij =
gv_calloc(n * (n + 1) / 2,
sizeof(
float));
708 for (i = 0; i < n; i++) {
710 for (j = i; j < n; j++) {
711 Dij[count++] = (float)Di[j];
724 float *old_weights =
graph[0].ewgts;
729 for (i = 0; i < n; i++) {
734 int *vtx_vec =
gv_calloc(n,
sizeof(
int));
737 for (i = 0; i < n; i++) {
739 deg_i =
graph[i].nedges - 1;
740 for (
size_t j = 1; j <= deg_i; j++) {
743 weights[j] = fmaxf((
float)(deg_i + deg_j -
747 graph[i].ewgts = weights;
748 weights +=
graph[i].nedges;
752 for (i = 0; i < n; i++) {
753 graph[i].ewgts = weights;
755 deg_i =
graph[i].nedges - 1;
756 for (
size_t j = 1; j <= deg_i; j++) {
763 weights +=
graph[i].nedges;
771 if (old_weights !=
NULL) {
772 for (i = 0; i < n; i++) {
773 graph[i].ewgts = old_weights;
774 old_weights +=
graph[i].nedges;
780#if defined(DEBUG) && DEBUG > 1
781static void dumpMatrix(
float *Dij,
int n)
784 for (i = 0; i < n; i++) {
785 for (j = i; j < n; j++) {
786 fprintf(stderr,
"%.02f ", Dij[count++]);
796#define DegType long double
816 float **coords =
NULL;
817 float *f_storage =
NULL;
826 double old_stress, new_stress;
829 float *tmp_coords =
NULL;
830 float *dist_accumulator =
NULL;
856 fprintf(stderr,
"Calculating subset model");
862 "graph is disconnected. Hence, the circuit model\n");
864 "is undefined. Reverting to the shortest path model.\n");
868 fprintf(stderr,
"Calculating MDS model");
873 fprintf(stderr,
"Calculating shortest paths");
882 fprintf(stderr,
"Setting initial positions");
890 if (smart_ini && n > 1) {
896 d_coords,
dim, smart_ini, exp,
903 for (i = 0; i <
dim; i++) {
906 for (j = 0; j < n; j++) {
907 if (fabs(d_coords[i][j]) > max) {
908 max = fabs(d_coords[i][j]);
911 for (j = 0; j < n; j++) {
912 d_coords[i][j] /= max;
915 for (j = 0; j < n; j++) {
916 d_coords[i][j] += 1e-6 * (
drand48() - 0.5);
925 if (n == 1 || maxi == 0) {
932 fprintf(stderr,
"Setting up stress function");
937 for (i = 0; i <
dim; i++) {
938 coords[i] = f_storage + i * n;
939 for (j = 0; j < n; j++) {
940 coords[i][j] = (float)d_coords[i][j];
946 assert(exp == 1 || exp == 2);
947 constant_term = (float)n * (n - 1) / 2;
953 lap_length = n * (n + 1) / 2;
964 for (i = 0; i < n - 1; i++) {
967 for (j = 1; j < n - i; j++, count++) {
970 degrees[i + j] -= val;
972 degrees[i] -= degree;
974 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
975 lap2[count] = degrees[i];
984 for (k = 1; k <
dim; k++) {
988 tmp_coords =
gv_calloc(n,
sizeof(
float));
989 dist_accumulator =
gv_calloc(n,
sizeof(
float));
990 lap1 =
gv_calloc(lap_length,
sizeof(
float));
993 old_stress = DBL_MAX;
996 fprintf(stderr,
"Solving model: ");
1000 for (converged =
false, iterations = 0;
1001 iterations < maxi && !converged; iterations++) {
1005 memset(degrees, 0, n *
sizeof(
DegType));
1009 for (count = 0, i = 0; i < n - 1; i++) {
1015 for (k = 0; k <
dim; k++) {
1017 for (x = 0; x < (size_t)
len; ++x) {
1018 float tmp = coords[k][i] + -1.0f * (coords[k] + i + 1)[x];
1019 dist_accumulator[x] += tmp * tmp;
1026 for (j = 0; j <
len; j++) {
1027 if (dist_accumulator[j] >= FLT_MAX || dist_accumulator[j] < 0) {
1028 dist_accumulator[j] = 0;
1035 for (j = 0; j <
len; j++, count++) {
1036 val = lap1[count] *= dist_accumulator[j];
1038 degrees[i + j + 1] -= val;
1041 for (j = 0; j <
len; j++, count++) {
1042 val = lap1[count] = dist_accumulator[j];
1044 degrees[i + j + 1] -= val;
1047 degrees[i] -= degree;
1049 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
1050 lap1[count] = degrees[i];
1054 for (k = 0; k <
dim; k++) {
1063 for (k = 0; k <
dim; k++) {
1067 new_stress += constant_term;
1068 for (k = 0; k <
dim; k++) {
1076 double diff = old_stress - new_stress;
1077 double change = fabs(diff);
1078 converged = change / old_stress <
Epsilon || new_stress <
Epsilon;
1080 old_stress = new_stress;
1082 for (k = 0; k <
dim; k++) {
1091 for (i = 0; i < n; i++) {
1094 coords[k][i] = tmp_coords[i];
1104 if (
Verbose && iterations % 5 == 0) {
1105 fprintf(stderr,
"%.3f ", new_stress);
1106 if ((iterations + 5) % 50 == 0)
1107 fprintf(stderr,
"\n");
1111 fprintf(stderr,
"\nfinal e = %f %d iterations %.2f sec\n",
1116 for (i = 0; i <
dim; i++) {
1117 for (j = 0; j < n; j++) {
1118 d_coords[i][j] = coords[i][j];
1131 free(dist_accumulator);
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
void bfs(int vertex, vtx_data *graph, int n, DistType *dist)
int solveCircuit(int nG, double **Gm, double **Gm_inv)
int conjugate_gradient_mkernel(float *A, float *x, float *b, int n, double tol, int max_iterations)
int conjugate_gradient_f(float **A, double *x, double *b, int n, double tol, int max_iterations, bool ortho1)
void embed_graph(vtx_data *graph, int n, int dim, DistType ***Coords, int reweight_graph)
void center_coordinate(DistType **coords, int n, int dim)
static double dist(int dim, double *x, double *y)
static double len(glCompPoint p)
void agwarningf(const char *fmt,...)
int agerr(agerrlevel_t level, const char *fmt,...)
Agraph_t * graph(char *name)
void compute_new_weights(vtx_data *graph, int n)
double distance_kD(double **coords, int dim, int i, int j)
void fill_neighbors_vec_unweighted(vtx_data *graph, int vtx, int *vtx_vec)
size_t common_neighbors(vtx_data *graph, int u, int *v_vector)
void restore_old_weights(vtx_data *graph, int n, float *old_weights)
void empty_neighbors_vec(vtx_data *graph, int vtx, int *vtx_vec)
void dijkstra_f(int vertex, vtx_data *graph, int n, float *dist)
#define neighbor(t, i, edim, elist)
void right_mult_with_vector_transpose(double **matrix, int dim1, int dim2, double *vector, double *result)
void invert_vec(int n, float *vec)
void right_mult_with_vector_d(double **matrix, int dim1, int dim2, double *vector, double *result)
void mult_sparse_dense_mat_transpose(vtx_data *A, double **B, int dim1, int dim2, float ***CC)
void invert_sqrt_vec(int n, float *vec)
void mult_dense_mat(double **A, float **B, int dim1, int dim2, int dim3, float ***CC)
void set_vector_valf(int n, float val, float *result)
void orthog1(int n, double *vec)
void copy_vectorf(int n, float *source, float *dest)
void sqrt_vecf(int n, float *source, float *target)
void right_mult_with_vector_ff(float *packed_matrix, int n, float *vector, float *result)
void square_vec(int n, float *vec)
double vectors_inner_productf(int n, float *vector1, float *vector2)
NEATOPROCS_API void free_array(double **rv)
NEATOPROCS_API double ** new_array(int i, int j, double val)
void PCA_alloc(DistType **coords, int dim, int n, double **new_coords, int new_dim)
bool iterativePCA_1D(double **coords, int dim, int n, double *new_direction)
static int nedges
total no. of edges used in routing
float * compute_apsp_artificial_weights_packed(vtx_data *graph, int n)
static double compute_stressf(float **coords, float *lap, int dim, int n, int exp)
int stress_majorization_kD_mkernel(vtx_data *graph, int n, double **d_coords, node_t **nodes, int dim, int opts, int model, int maxi)
static float * compute_weighted_apsp_packed(vtx_data *graph, int n)
static int sparse_stress_subspace_majorization_kD(vtx_data *graph, int n, double **coords, int dim, int smart_ini, int exp, int reweight_graph, int n_iterations, int num_centers)
float * circuitModel(vtx_data *graph, int nG)
int initLayout(int n, int dim, double **coords, node_t **nodes)
float * mdsModel(vtx_data *graph, int nG)
float * compute_apsp_packed(vtx_data *graph, int n)
static double compute_stress1(double **coords, dist_data *distances, int dim, int n, int exp)
#define num_pivots_stress